Bug 461946 Replace nsIUrlListenerManager by an nsTObserverArray. r/sr=bienvenu

This commit is contained in:
Mark Banner 2008-10-28 14:27:21 +00:00
Родитель 00f5c088f2
Коммит 6cbbd16a70
10 изменённых файлов: 33 добавлений и 338 удалений

Просмотреть файл

@ -58,8 +58,6 @@
/* Include all of the interfaces our factory can generate components for */
#include "nsIUrlListenerManager.h"
#include "nsUrlListenerManager.h"
#include "nsMsgMailSession.h"
#include "nsMsgAccount.h"
#include "nsMsgAccountManager.h"
@ -128,7 +126,6 @@
// private factory declarations for each component we know how to produce
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMessengerBootstrap)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlListenerManager)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgMailSession, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMessenger)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgAccountManager, Init)
@ -296,10 +293,6 @@ static const nsModuleComponentInfo gComponents[] = {
RegisterCommandLineHandler,
UnregisterCommandLineHandler,
},
{ "UrlListenerManager", NS_URLLISTENERMANAGER_CID,
NS_URLLISTENERMANAGER_CONTRACTID,
nsUrlListenerManagerConstructor,
},
{ "Mail Session", NS_MSGMAILSESSION_CID,
NS_MSGMAILSESSION_CONTRACTID,
nsMsgMailSessionConstructor,

Просмотреть файл

@ -73,7 +73,6 @@ XPIDLSRCS = \
nsIMsgTagService.idl \
nsIMsgThread.idl \
nsIUrlListener.idl \
nsIUrlListenerManager.idl \
nsIMsgBiffManager.idl \
nsIStatusBarBiffManager.idl \
nsIMsgPurgeService.idl \

Просмотреть файл

@ -1,68 +0,0 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIUrlListener.idl"
interface nsIMsgMailNewsUrl;
%{C++
#include "nsIMsgMailNewsUrl.h"
%}
/*
* The url listener manager is a helper class used by all of our
* subclassed urls to implement registration and broadcasting of changes
* to all of their registered url listeners. I envision every url
* implementation to have a has a relationship with a nsIUrlListenerManager.
* All url listener register/unregister calls are forwarded to the
* listener manager. In addition, the url listener manager handles
* broadcasting of event changes on the url.
*/
[scriptable, uuid(5BCDB610-D00D-11d2-8069-006008128C4E)]
interface nsIUrlListenerManager : nsISupports {
void RegisterListener(in nsIUrlListener aUrlListener);
void UnRegisterListener(in nsIUrlListener aUrlListener);
// These functions turn around and broadcast the notifications to
// all url listeners...
void OnStartRunningUrl(in nsIMsgMailNewsUrl aUrl);
void OnStopRunningUrl(in nsIMsgMailNewsUrl aUrl, in nsresult aExitCode);
};

Просмотреть файл

@ -253,17 +253,6 @@
{ 0xbcdca970, 0x3b22, 0x11d3, \
{ 0x8d, 0x76, 0x00, 0x80, 0xf5, 0x8a, 0x66, 0x17 } }
//
// nsUrlListenerManager
//
#define NS_URLLISTENERMANAGER_CONTRACTID \
"@mozilla.org/messenger/urlListenerManager;1"
/* B1AA0820-D04B-11d2-8069-006008128C4E */
#define NS_URLLISTENERMANAGER_CID \
{ 0xb1aa0820, 0xd04b, 0x11d2, \
{0x80, 0x69, 0x0, 0x60, 0x8, 0x12, 0x8c, 0x4e} }
//
// nsMessengerBootstrap
//

Просмотреть файл

@ -94,7 +94,6 @@ REQUIRES = xpcom \
CPPSRCS = \
nsMessenger.cpp \
nsMessengerBootstrap.cpp \
nsUrlListenerManager.cpp \
nsMsgMailSession.cpp \
nsMsgAccountManager.cpp \
nsMsgAccount.cpp \

Просмотреть файл

@ -1,129 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "msgCore.h" // for pre-compiled headers...
#include "nsUrlListenerManager.h"
nsUrlListenerManager::nsUrlListenerManager() :
m_listeners(nsnull)
{
// create a new isupports array to store our listeners in...
NS_NewISupportsArray(getter_AddRefs(m_listeners));
}
nsUrlListenerManager::~nsUrlListenerManager()
{
ReleaseListeners();
}
void nsUrlListenerManager::ReleaseListeners()
{
if(m_listeners)
{
PRUint32 count;
nsresult rv = m_listeners->Count(&count);
NS_ASSERTION(NS_SUCCEEDED(rv), "m_listeners->Count() failed");
if (NS_FAILED(rv)) return;
for (int i = count - 1; i >= 0; i--)
m_listeners->RemoveElementAt(i);
}
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlListenerManager, nsIUrlListenerManager)
nsresult nsUrlListenerManager::RegisterListener(nsIUrlListener * aUrlListener)
{
if (m_listeners && aUrlListener)
m_listeners->AppendElement(aUrlListener);
return NS_OK;
}
nsresult nsUrlListenerManager::UnRegisterListener(nsIUrlListener * aUrlListener)
{
if (m_listeners && aUrlListener)
m_listeners->RemoveElement(aUrlListener);
return NS_OK;
}
nsresult nsUrlListenerManager::BroadcastChange(nsIURI * aUrl, nsUrlNotifyType notification, nsresult aErrorCode)
{
NS_PRECONDITION(aUrl, "we shouldn't get OnStartRunningUrl for the url listener manager without a url...");
nsresult rv = NS_OK;
if (m_listeners && aUrl)
{
// enumerate over all url listeners...(Start at the end and work our way down)
nsCOMPtr<nsIUrlListener> listener;
nsCOMPtr<nsISupports> aSupports;
PRUint32 index;
m_listeners->Count(&index);
for (; index > 0; index--)
{
m_listeners->GetElementAt(index-1, getter_AddRefs(aSupports));
listener = do_QueryInterface(aSupports);
if (listener)
{
if (notification == nsUrlNotifyStartRunning)
listener->OnStartRunningUrl(aUrl);
else if (notification == nsUrlNotifyStopRunning)
listener->OnStopRunningUrl(aUrl, aErrorCode);
}
} // for each listener
} // if m_listeners && aUrl
return rv;
}
nsresult nsUrlListenerManager::OnStartRunningUrl(nsIMsgMailNewsUrl * aUrl)
{
return BroadcastChange(aUrl, nsUrlNotifyStartRunning, 0);
}
nsresult nsUrlListenerManager::OnStopRunningUrl(nsIMsgMailNewsUrl * aUrl, nsresult aErrorCode)
{
nsresult rv = BroadcastChange(aUrl, nsUrlNotifyStopRunning, aErrorCode);
// in order to prevent circular references, after we issue on stop running url,
// go through and release all of our listeners...
ReleaseListeners();
return rv;
}

Просмотреть файл

@ -1,92 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsUrlListenerManager_h___
#define nsUrlListenerManager_h___
#include "nsIUrlListenerManager.h"
#include "nsISupportsArray.h"
#include "nsCOMPtr.h"
/********************************************************************************************
The url listener manager is a helper class used by all of our subclassed urls to implement
registration and broadcasting of changes to all of their registered url listeners. I envision
every url implementation to have a has a relationship with a nsIUrlListenerManager. All
url listener register/unregister calls are forwarded to the listener manager. In addition,
the url listener manager handles broadcasting of event changes on the url.
mscott --> hmm now that I think about it this class is probably going to have to be made
thread safe. It might have to proxy notification calls into another thread....
********************************************************************************************/
typedef enum {
nsUrlNotifyStartRunning = 0,
nsUrlNotifyStopRunning
} nsUrlNotifyType;
class nsUrlListenerManager : public nsIUrlListenerManager {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIURLLISTENERMANAGER
nsUrlListenerManager();
virtual ~nsUrlListenerManager();
protected:
// mscott --> for the longest time, I had m_listeners as a nsVoidArray to prevent
// circular references when the url listener owned the url which owned the manager
// which owned the url listener. By using a void array, were the manager didn't own
// the listeners, we got out of this problem. But this made the model very difficult
// to use for folks when it came to maintenance. Why? Because they would have a url
// listener which didn't own the url. And they had no way of knowing how to keep
// their object alive until the listener manager said the url was done. As a result,
// folks were using strange ref counting techniques on their objects such that they
// would addref themselves before adding their listener to the url. Then, when they
// received a on stop running url, they would throw a random release in there.
// Needless to say, this is far from ideal so I've decided to change this to
// an nsISupportsArray and cleanup the caller's ref counting hacks to get this to work.
// The danger is of course still the circular reference problem. In order to get around
// this, when we issue a on stop running url through the manager, I'm going to release
// all our url listeners. This should break the circle.
// nsVoidArray * m_listeners;
nsCOMPtr<nsISupportsArray> m_listeners;
// helper function used to enumerate ISupportsArray and broadcast the change
nsresult BroadcastChange(nsIURI * aUrl, nsUrlNotifyType notification, nsresult aErrorCode);
void ReleaseListeners();
};
#endif /* nsUrlListenerManager_h___ */

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -67,10 +67,18 @@ nsMsgMailNewsUrl::nsMsgMailNewsUrl()
m_msgIsInLocalCache = PR_FALSE;
m_suppressErrorMsgs = PR_FALSE;
m_urlListeners = do_CreateInstance(NS_URLLISTENERMANAGER_CONTRACTID);
m_baseURL = do_CreateInstance(NS_STANDARDURL_CONTRACTID);
}
#define NOTIFY_URL_LISTENERS(propertyfunc_, params_) \
PR_BEGIN_MACRO \
nsTObserverArray<nsCOMPtr<nsIUrlListener> >::ForwardIterator iter(mUrlListeners); \
while (iter.HasMore()) { \
nsCOMPtr<nsIUrlListener> listener = iter.GetNext(); \
listener->propertyfunc_ params_; \
} \
PR_END_MACRO
nsMsgMailNewsUrl::~nsMsgMailNewsUrl()
{
PR_FREEIF(m_errorMessage);
@ -117,35 +125,39 @@ nsresult nsMsgMailNewsUrl::SetUrlState(PRBool aRunningUrl, nsresult aExitCode)
statusFeedback->StopMeteors();
}
}
if (m_urlListeners)
if (m_runningUrl)
{
if (m_runningUrl)
{
m_urlListeners->OnStartRunningUrl(this);
}
else
{
m_urlListeners->OnStopRunningUrl(this, aExitCode);
m_urlListeners = nsnull;
}
NOTIFY_URL_LISTENERS(OnStartRunningUrl, (this));
}
else
printf("no listeners in set url state\n");
{
NOTIFY_URL_LISTENERS(OnStopRunningUrl, (this, aExitCode));
mUrlListeners.Clear();
}
return NS_OK;
}
nsresult nsMsgMailNewsUrl::RegisterListener (nsIUrlListener * aUrlListener)
NS_IMETHODIMP nsMsgMailNewsUrl::RegisterListener(nsIUrlListener *aUrlListener)
{
if (m_urlListeners)
m_urlListeners->RegisterListener(aUrlListener);
NS_ENSURE_ARG_POINTER(aUrlListener);
mUrlListeners.AppendElement(aUrlListener);
return NS_OK;
}
nsresult nsMsgMailNewsUrl::UnRegisterListener (nsIUrlListener * aUrlListener)
nsresult nsMsgMailNewsUrl::UnRegisterListener(nsIUrlListener *aUrlListener)
{
if (m_urlListeners)
m_urlListeners->UnRegisterListener(aUrlListener);
NS_ENSURE_ARG_POINTER(aUrlListener);
PRInt32 index = mUrlListeners.IndexOf(aUrlListener);
// Due to the way mailnews is structured, some listeners attempt to remove
// themselves twice. This may in fact be an error in the coding, however
// if they didn't do it as they do currently, then they could fail to remove
// their listeners.
if (index != -1)
mUrlListeners.RemoveElementAt(index);
return NS_OK;
}

Просмотреть файл

@ -42,7 +42,7 @@
#include "nscore.h"
#include "nsISupports.h"
#include "nsIUrlListener.h"
#include "nsIUrlListenerManager.h"
#include "nsTObserverArray.h"
#include "nsIMsgWindow.h"
#include "nsIMsgStatusFeedback.h"
#include "nsCOMPtr.h"
@ -106,8 +106,7 @@ protected:
// asks us for it, we'll return the right value.
nsCString mAttachmentFileName;
// manager of all of current url listeners....
nsCOMPtr<nsIUrlListenerManager> m_urlListeners;
nsTObserverArray<nsCOMPtr<nsIUrlListener> > mUrlListeners;
};
#undef IMETHOD_VISIBILITY

Просмотреть файл

@ -62,8 +62,6 @@
#include "nsMessengerBootstrap.h"
#include "nsMessenger.h"
#include "nsIContentViewer.h"
#include "nsIUrlListenerManager.h"
#include "nsUrlListenerManager.h"
#include "nsMsgMailSession.h"
#include "nsMsgAccount.h"
#include "nsMsgAccountManager.h"
@ -295,7 +293,6 @@
// mailnews base factories
////////////////////////////////////////////////////////////////////////////////
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMessengerBootstrap)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlListenerManager)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgMailSession, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMessenger)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgAccountManager, Init)
@ -692,10 +689,6 @@ static const nsModuleComponentInfo gComponents[] = {
NS_MESSENGERWINDOWSERVICE_CONTRACTID,
nsMessengerBootstrapConstructor,
},
{ "UrlListenerManager", NS_URLLISTENERMANAGER_CID,
NS_URLLISTENERMANAGER_CONTRACTID,
nsUrlListenerManagerConstructor,
},
{ "Mail Session", NS_MSGMAILSESSION_CID,
NS_MSGMAILSESSION_CONTRACTID,
nsMsgMailSessionConstructor,