зеркало из https://github.com/mozilla/pjs.git
merge backout, a=khuey
This commit is contained in:
Коммит
be85bc5cd2
|
@ -69,10 +69,21 @@ struct EnumerateData {
|
|||
nsTArray<nsCString> *pref_list;
|
||||
};
|
||||
|
||||
struct PrefCallbackData {
|
||||
nsPrefBranch *pBranch;
|
||||
nsISupports *pCanonical;
|
||||
nsIObserver *pObserver;
|
||||
nsIWeakReference *pWeakRef;
|
||||
char pDomain[1];
|
||||
};
|
||||
|
||||
|
||||
// Prototypes
|
||||
static PLDHashOperator
|
||||
pref_enumChild(PLDHashTable *table, PLDHashEntryHdr *heh,
|
||||
PRUint32 i, void *arg);
|
||||
static nsresult
|
||||
NotifyObserver(const char *newpref, void *data);
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
using mozilla::dom::ContentChild;
|
||||
|
@ -96,12 +107,11 @@ GetContentChild()
|
|||
*/
|
||||
|
||||
nsPrefBranch::nsPrefBranch(const char *aPrefRoot, PRBool aDefaultBranch)
|
||||
: mObservers(nsnull)
|
||||
{
|
||||
mPrefRoot = aPrefRoot;
|
||||
mPrefRootLength = mPrefRoot.Length();
|
||||
mIsDefault = aDefaultBranch;
|
||||
mFreeingObserverList = PR_FALSE;
|
||||
mObservers.Init();
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
|
@ -692,7 +702,7 @@ NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, PRUint32 *aCou
|
|||
|
||||
NS_IMETHODIMP nsPrefBranch::AddObserver(const char *aDomain, nsIObserver *aObserver, PRBool aHoldWeak)
|
||||
{
|
||||
PrefCallback *pCallback;
|
||||
PrefCallbackData *pCallback;
|
||||
const char *pref;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aDomain);
|
||||
|
@ -704,39 +714,51 @@ NS_IMETHODIMP nsPrefBranch::AddObserver(const char *aDomain, nsIObserver *aObser
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!mObservers) {
|
||||
mObservers = new nsAutoVoidArray();
|
||||
if (nsnull == mObservers)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pCallback = (PrefCallbackData *)NS_Alloc(sizeof(PrefCallbackData) + strlen(aDomain));
|
||||
if (nsnull == pCallback)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
pCallback->pBranch = this;
|
||||
pCallback->pObserver = aObserver;
|
||||
|
||||
// hold a weak reference to the observer if so requested
|
||||
if (aHoldWeak) {
|
||||
nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(aObserver);
|
||||
if (!weakRefFactory) {
|
||||
// the caller didn't give us a object that supports weak reference... tell them
|
||||
nsMemory::Free(pCallback);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Construct a PrefCallback with a weak reference to the observer.
|
||||
pCallback = new PrefCallback(aDomain, weakRefFactory, this);
|
||||
|
||||
nsCOMPtr<nsIWeakReference> tmp = do_GetWeakReference(weakRefFactory);
|
||||
NS_ADDREF(pCallback->pWeakRef = tmp);
|
||||
} else {
|
||||
// Construct a PrefCallback with a strong reference to the observer.
|
||||
pCallback = new PrefCallback(aDomain, aObserver, this);
|
||||
pCallback->pWeakRef = nsnull;
|
||||
NS_ADDREF(pCallback->pObserver);
|
||||
}
|
||||
|
||||
if (mObservers.Get(pCallback)) {
|
||||
NS_WARNING("Ignoring duplicate observer.");
|
||||
delete pCallback;
|
||||
return NS_OK;
|
||||
}
|
||||
// In RemoveObserver, we need a canonical pointer to compare the removed
|
||||
// observer to. In order to avoid having to call QI every time through the
|
||||
// loop, we call QI here. There are two cases:
|
||||
// 1. We hold a strong reference to the nsIObserver. This must hold
|
||||
// pCanonical alive.
|
||||
// 2. We hold a weak reference: either the object stays alive and eventually
|
||||
// we QI the nsIObserver to nsISupports and compare successfully. Or the
|
||||
// object dies and we have a dangling (but unused) pointer to the
|
||||
// canonical supports pointer until we remove this entry.
|
||||
CallQueryInterface(aObserver, &pCallback->pCanonical);
|
||||
pCallback->pCanonical->Release();
|
||||
|
||||
PRBool putSucceeded = mObservers.Put(pCallback, pCallback);
|
||||
|
||||
if (!putSucceeded) {
|
||||
delete pCallback;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
strcpy(pCallback->pDomain, aDomain);
|
||||
mObservers->AppendElement(pCallback);
|
||||
|
||||
// We must pass a fully qualified preference name to the callback
|
||||
// aDomain == nsnull is the only possible failure, and we trapped it with
|
||||
// NS_ENSURE_ARG_POINTER above.
|
||||
pref = getPrefName(aDomain);
|
||||
pref = getPrefName(aDomain); // aDomain == nsnull only possible failure, trapped above
|
||||
PREF_RegisterCallback(pref, NotifyObserver, pCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -746,10 +768,9 @@ NS_IMETHODIMP nsPrefBranch::RemoveObserver(const char *aDomain, nsIObserver *aOb
|
|||
NS_ENSURE_ARG_POINTER(aDomain);
|
||||
NS_ENSURE_ARG_POINTER(aObserver);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
nsresult rv = NS_OK;
|
||||
ContentChild *cpc = ContentChild::GetSingleton();
|
||||
// In case cpc doesn't exist here, we're silently returning (instead of
|
||||
// asserting), because the child process is likely to be null
|
||||
|
@ -762,29 +783,11 @@ NS_IMETHODIMP nsPrefBranch::RemoveObserver(const char *aDomain, nsIObserver *aOb
|
|||
}
|
||||
#endif
|
||||
|
||||
// If we're in the middle of a call to freeObserverList, don't process this
|
||||
// RemoveObserver call -- the observer in question will be removed soon, if
|
||||
// it hasn't been already.
|
||||
//
|
||||
// It's important that we don't touch mObservers in any way -- even a Get()
|
||||
// which retuns null might cause the hashtable to resize itself, which will
|
||||
// break the Enumerator in freeObserverList.
|
||||
if (mFreeingObserverList)
|
||||
if (!mObservers)
|
||||
return NS_OK;
|
||||
|
||||
// Remove the relevant PrefCallback from mObservers and get an owning
|
||||
// pointer to it. Unregister the callback first, and then let the owning
|
||||
// pointer go out of scope and destroy the callback.
|
||||
PrefCallback key(aDomain, aObserver, this);
|
||||
nsAutoPtr<PrefCallback> pCallback;
|
||||
mObservers.RemoveAndForget(&key, pCallback);
|
||||
if (pCallback) {
|
||||
// aDomain == nsnull is the only possible failure, trapped above
|
||||
const char *pref = getPrefName(aDomain);
|
||||
rv = PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
|
||||
}
|
||||
|
||||
return rv;
|
||||
nsCOMPtr<nsISupports> canonical(do_QueryInterface(aObserver));
|
||||
return RemoveObserverFromList(aDomain, canonical);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPrefBranch::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
|
||||
|
@ -796,12 +799,11 @@ NS_IMETHODIMP nsPrefBranch::Observe(nsISupports *aSubject, const char *aTopic, c
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult nsPrefBranch::NotifyObserver(const char *newpref, void *data)
|
||||
static nsresult NotifyObserver(const char *newpref, void *data)
|
||||
{
|
||||
#ifdef MOZ_IPC
|
||||
if (GetContentChild()) {
|
||||
// We shouldn't ever get here, since we never register NotifyObserver in the
|
||||
// We shouldn't ever get here, since we never register NotifyObserver in the
|
||||
// content process
|
||||
NS_NOTREACHED("Remote prefs observation should be done from the \
|
||||
chrome process!");
|
||||
|
@ -809,64 +811,114 @@ nsresult nsPrefBranch::NotifyObserver(const char *newpref, void *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
PrefCallback *pCallback = (PrefCallback *)data;
|
||||
|
||||
if (pCallback->IsExpired())
|
||||
{
|
||||
// Remove the expired weak reference from the pref branch's observers list.
|
||||
pCallback->GetPrefBranch()->RemoveExpiredCallback(pCallback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserver> observer(pCallback->GetObserver());
|
||||
PrefCallbackData *pData = (PrefCallbackData *)data;
|
||||
|
||||
// remove any root this string may contain so as to not confuse the observer
|
||||
// by passing them something other than what they passed us as a topic
|
||||
PRUint32 len = pCallback->GetPrefBranch()->GetRootLength();
|
||||
nsCAutoString suffix(newpref + len);
|
||||
PRUint32 len = pData->pBranch->GetRootLength();
|
||||
nsCAutoString suffix(newpref + len);
|
||||
|
||||
observer->Observe(static_cast<nsIPrefBranch *>(pCallback->GetPrefBranch()),
|
||||
nsCOMPtr<nsIObserver> observer;
|
||||
if (pData->pWeakRef) {
|
||||
observer = do_QueryReferent(pData->pWeakRef);
|
||||
if (!observer) {
|
||||
// this weak referenced observer went away, remove them from the list
|
||||
pData->pBranch->RemoveObserverFromList(pData->pDomain, pData->pCanonical);
|
||||
return NS_OK;
|
||||
}
|
||||
} else {
|
||||
observer = pData->pObserver;
|
||||
}
|
||||
|
||||
observer->Observe(static_cast<nsIPrefBranch *>(pData->pBranch),
|
||||
NS_PREFBRANCH_PREFCHANGE_TOPIC_ID,
|
||||
NS_ConvertASCIItoUTF16(suffix).get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
FreeObserverFunc(PrefCallback *aKey,
|
||||
nsAutoPtr<PrefCallback> &aCallback,
|
||||
void *aArgs)
|
||||
{
|
||||
// Calling NS_RELEASE below might trigger a call to
|
||||
// nsPrefBranch::RemoveObserver, since some classes remove themselves from
|
||||
// the pref branch on destruction. We don't need to worry about this causing
|
||||
// double-frees, however, because freeObserverList sets mFreeingObserverList
|
||||
// to true, which prevents RemoveObserver calls from doing anything.
|
||||
|
||||
nsPrefBranch *prefBranch = aCallback->GetPrefBranch();
|
||||
const char *pref = prefBranch->getPrefName(aCallback->GetDomain().get());
|
||||
PREF_UnregisterCallback(pref, nsPrefBranch::NotifyObserver, aCallback);
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void nsPrefBranch::freeObserverList(void)
|
||||
{
|
||||
// We need to prevent anyone from modifying mObservers while we're
|
||||
// enumerating over it. In particular, some clients will call
|
||||
// RemoveObserver() when they're destructed; we need to keep those calls from
|
||||
// touching mObservers.
|
||||
mFreeingObserverList = PR_TRUE;
|
||||
mObservers.Enumerate(&FreeObserverFunc, nsnull);
|
||||
mFreeingObserverList = PR_FALSE;
|
||||
const char *pref;
|
||||
PrefCallbackData *pCallback;
|
||||
|
||||
if (mObservers) {
|
||||
// unregister the observers
|
||||
|
||||
PRInt32 i;
|
||||
nsCAutoString domain;
|
||||
for (i = 0; i < mObservers->Count(); ++i) {
|
||||
pCallback = (PrefCallbackData *)mObservers->ElementAt(i);
|
||||
if (pCallback) {
|
||||
// We must pass a fully qualified preference name to remove the callback
|
||||
pref = getPrefName(pCallback->pDomain);
|
||||
// Remove this observer from our array so that nobody else can remove
|
||||
// what we're trying to remove right now.
|
||||
mObservers->ReplaceElementAt(nsnull, i);
|
||||
PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
|
||||
if (pCallback->pWeakRef) {
|
||||
NS_RELEASE(pCallback->pWeakRef);
|
||||
} else {
|
||||
NS_RELEASE(pCallback->pObserver);
|
||||
}
|
||||
nsMemory::Free(pCallback);
|
||||
}
|
||||
}
|
||||
|
||||
delete mObservers;
|
||||
mObservers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPrefBranch::RemoveExpiredCallback(PrefCallback *aCallback)
|
||||
nsresult
|
||||
nsPrefBranch::RemoveObserverFromList(const char *aDomain, nsISupports *aObserver)
|
||||
{
|
||||
NS_PRECONDITION(aCallback->IsExpired(), "Callback should be expired.");
|
||||
mObservers.Remove(aCallback);
|
||||
}
|
||||
PRInt32 count = mObservers->Count();
|
||||
if (!count) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool alreadyRemoved = PR_FALSE;
|
||||
#endif
|
||||
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
PrefCallbackData *pCallback = (PrefCallbackData *)mObservers->ElementAt(i);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!pCallback) {
|
||||
// Have to assume that the callback we're looking for was already
|
||||
// removed in freeObserverList below.
|
||||
alreadyRemoved = PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pCallback &&
|
||||
pCallback->pCanonical == aObserver &&
|
||||
!strcmp(pCallback->pDomain, aDomain)) {
|
||||
// We must pass a fully qualified preference name to remove the callback
|
||||
const char *pref = getPrefName(aDomain); // aDomain == nsnull only possible failure, trapped above
|
||||
nsresult rv = PREF_UnregisterCallback(pref, NotifyObserver, pCallback);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Remove this observer from our array so that nobody else can remove
|
||||
// what we're trying to remove ourselves right now.
|
||||
mObservers->RemoveElementAt(i);
|
||||
if (pCallback->pWeakRef) {
|
||||
NS_RELEASE(pCallback->pWeakRef);
|
||||
} else {
|
||||
NS_RELEASE(pCallback->pObserver);
|
||||
}
|
||||
NS_Free(pCallback);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
NS_WARN_IF_FALSE(alreadyRemoved,
|
||||
"Failed attempt to remove a pref observer, probably leaking");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPrefBranch::GetDefaultFromPropertiesFile(const char *aPrefName, PRUnichar **return_buf)
|
||||
{
|
||||
nsresult rv;
|
||||
|
|
|
@ -51,153 +51,6 @@
|
|||
#include "nsVoidArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prbit.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
class nsPrefBranch;
|
||||
|
||||
class PrefCallback : public PLDHashEntryHdr {
|
||||
|
||||
public:
|
||||
typedef PrefCallback* KeyType;
|
||||
typedef const PrefCallback* KeyTypePointer;
|
||||
|
||||
static const PrefCallback* KeyToPointer(PrefCallback *aKey)
|
||||
{
|
||||
return aKey;
|
||||
}
|
||||
|
||||
static PLDHashNumber HashKey(const PrefCallback *aKey)
|
||||
{
|
||||
PRUint32 strHash = nsCRT::HashCode(aKey->mDomain.BeginReading(),
|
||||
aKey->mDomain.Length());
|
||||
|
||||
return PR_ROTATE_LEFT32(strHash, 4) ^
|
||||
NS_PTR_TO_UINT32(aKey->mCanonical);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
// Create a PrefCallback with a strong reference to its observer.
|
||||
PrefCallback(const char *aDomain, nsIObserver *aObserver,
|
||||
nsPrefBranch *aBranch)
|
||||
: mDomain(aDomain),
|
||||
mBranch(aBranch),
|
||||
mWeakRef(nsnull),
|
||||
mStrongRef(aObserver)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PrefCallback);
|
||||
nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
|
||||
mCanonical = canonical;
|
||||
}
|
||||
|
||||
// Create a PrefCallback with a weak reference to its observer.
|
||||
PrefCallback(const char *aDomain,
|
||||
nsISupportsWeakReference *aObserver,
|
||||
nsPrefBranch *aBranch)
|
||||
: mDomain(aDomain),
|
||||
mBranch(aBranch),
|
||||
mWeakRef(do_GetWeakReference(aObserver)),
|
||||
mStrongRef(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PrefCallback);
|
||||
nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
|
||||
mCanonical = canonical;
|
||||
}
|
||||
|
||||
// Copy constructor needs to be explicit or the linker complains.
|
||||
PrefCallback(const PrefCallback *&aCopy)
|
||||
: mDomain(aCopy->mDomain),
|
||||
mBranch(aCopy->mBranch),
|
||||
mWeakRef(aCopy->mWeakRef),
|
||||
mStrongRef(aCopy->mStrongRef),
|
||||
mCanonical(aCopy->mCanonical)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PrefCallback);
|
||||
}
|
||||
|
||||
~PrefCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PrefCallback);
|
||||
}
|
||||
|
||||
PRBool KeyEquals(const PrefCallback *aKey) const
|
||||
{
|
||||
// We want to be able to look up a weakly-referencing PrefCallback after
|
||||
// its observer has died so we can remove it from the table. Once the
|
||||
// callback's observer dies, its canonical pointer is stale -- in
|
||||
// particular, we may have allocated a new observer in the same spot in
|
||||
// memory! So we can't just compare canonical pointers to determine
|
||||
// whether aKey refers to the same observer as this.
|
||||
//
|
||||
// Our workaround is based on the way we use this hashtable: When we ask
|
||||
// the hashtable to remove a PrefCallback whose weak reference has
|
||||
// expired, we use as the key for removal the same object as was inserted
|
||||
// into the hashtable. Thus we can say that if one of the keys' weak
|
||||
// references has expired, the two keys are equal iff they're the same
|
||||
// object.
|
||||
|
||||
if (IsExpired() || aKey->IsExpired())
|
||||
return this == aKey;
|
||||
|
||||
if (mCanonical != aKey->mCanonical)
|
||||
return PR_FALSE;
|
||||
|
||||
return mDomain.Equals(aKey->mDomain);
|
||||
}
|
||||
|
||||
PrefCallback *GetKey() const
|
||||
{
|
||||
return const_cast<PrefCallback*>(this);
|
||||
}
|
||||
|
||||
// Get a pointer to the callback's observer, or null if the observer was
|
||||
// weakly referenced and has been destroyed.
|
||||
nsIObserver *GetObserver() const
|
||||
{
|
||||
if (!IsWeak())
|
||||
return mStrongRef;
|
||||
|
||||
nsCOMPtr<nsIObserver> observer = do_QueryReferent(mWeakRef);
|
||||
return observer;
|
||||
}
|
||||
|
||||
const nsCString& GetDomain() const
|
||||
{
|
||||
return mDomain;
|
||||
}
|
||||
|
||||
nsPrefBranch* GetPrefBranch() const
|
||||
{
|
||||
return mBranch;
|
||||
}
|
||||
|
||||
// Has this callback's weak reference died?
|
||||
PRBool IsExpired() const
|
||||
{
|
||||
return IsWeak() && !GetObserver();
|
||||
}
|
||||
|
||||
enum { ALLOW_MEMMOVE = PR_TRUE };
|
||||
|
||||
private:
|
||||
nsCString mDomain;
|
||||
nsPrefBranch *mBranch;
|
||||
|
||||
// Exactly one of mWeakRef and mStrongRef should be non-null.
|
||||
nsWeakPtr mWeakRef;
|
||||
nsCOMPtr<nsIObserver> mStrongRef;
|
||||
|
||||
// We need a canonical nsISupports pointer, per bug 578392.
|
||||
nsISupports *mCanonical;
|
||||
|
||||
PRBool IsWeak() const
|
||||
{
|
||||
return !!mWeakRef;
|
||||
}
|
||||
};
|
||||
|
||||
class nsPrefBranch : public nsIPrefBranchInternal,
|
||||
public nsIObserver,
|
||||
|
@ -214,31 +67,22 @@ public:
|
|||
|
||||
PRInt32 GetRootLength() { return mPrefRootLength; }
|
||||
|
||||
nsresult RemoveObserverFromMap(const char *aDomain, nsISupports *aObserver);
|
||||
|
||||
static nsresult NotifyObserver(const char *newpref, void *data);
|
||||
nsresult RemoveObserverFromList(const char *aDomain, nsISupports *aObserver);
|
||||
|
||||
protected:
|
||||
nsPrefBranch() /* disallow use of this constructer */
|
||||
{ }
|
||||
|
||||
nsresult GetDefaultFromPropertiesFile(const char *aPrefName, PRUnichar **return_buf);
|
||||
void RemoveExpiredCallback(PrefCallback *aCallback);
|
||||
const char *getPrefName(const char *aPrefName);
|
||||
void freeObserverList(void);
|
||||
|
||||
friend PLDHashOperator
|
||||
FreeObserverFunc(PrefCallback *aKey,
|
||||
nsAutoPtr<PrefCallback> &aCallback,
|
||||
void *aArgs);
|
||||
|
||||
private:
|
||||
PRInt32 mPrefRootLength;
|
||||
nsAutoVoidArray *mObservers;
|
||||
nsCString mPrefRoot;
|
||||
PRBool mIsDefault;
|
||||
|
||||
PRBool mFreeingObserverList;
|
||||
nsClassHashtable<PrefCallback, PrefCallback> mObservers;
|
||||
};
|
||||
|
||||
|
||||
|
@ -259,7 +103,7 @@ private:
|
|||
NS_IMETHOD GetData(PRUnichar**);
|
||||
NS_IMETHOD SetData(const PRUnichar* aData);
|
||||
NS_IMETHOD SetDataWithLength(PRUint32 aLength, const PRUnichar *aData);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupportsString> mUnicodeString;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/* ***** 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 code
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Justin Lebar <justin.lebar@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either 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 ***** */
|
||||
|
||||
function run_test() {
|
||||
var ps = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService);
|
||||
|
||||
var pb2= Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch2);
|
||||
|
||||
var pb = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
||||
var observer = {
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
if (aIID.equals(Ci.nsIObserver) ||
|
||||
aIID.equals(Ci.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aState) {
|
||||
// Don't do anything.
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the same pref twice. This shouldn't leak. */
|
||||
pb.addObserver("UserPref.nonexistent.setIntPref", observer, false);
|
||||
pb.addObserver("UserPref.nonexistent.setIntPref", observer, false);
|
||||
}
|
|
@ -70,18 +70,6 @@ public:
|
|||
* @returns NULL if the key is not present.
|
||||
*/
|
||||
UserDataType Get(KeyType aKey) const;
|
||||
|
||||
/**
|
||||
* Remove the entry for the given key from the hashtable and return it in
|
||||
* aOut. If the key is not in the hashtable, aOut's pointer is set to NULL.
|
||||
*
|
||||
* Normally, an entry is deleted when it's removed from an nsClassHashtable,
|
||||
* but this function transfers ownership of the entry back to the caller
|
||||
* through aOut -- the entry will be deleted when aOut goes out of scope.
|
||||
*
|
||||
* @param aKey the key to get and remove from the hashtable
|
||||
*/
|
||||
void RemoveAndForget(KeyType aKey, nsAutoPtr<T> &aOut);
|
||||
};
|
||||
|
||||
|
||||
|
@ -145,23 +133,6 @@ nsClassHashtable<KeyClass,T>::Get(KeyType aKey) const
|
|||
return ent->mData;
|
||||
}
|
||||
|
||||
template<class KeyClass,class T>
|
||||
void
|
||||
nsClassHashtable<KeyClass,T>::RemoveAndForget(KeyType aKey, nsAutoPtr<T> &aOut)
|
||||
{
|
||||
aOut = nsnull;
|
||||
nsAutoPtr<T> ptr;
|
||||
|
||||
typename base_type::EntryType *ent = this->GetEntry(aKey);
|
||||
if (!ent)
|
||||
return;
|
||||
|
||||
// Transfer ownership from ent->mData into aOut.
|
||||
aOut = ent->mData;
|
||||
|
||||
this->Remove(aKey);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsClassHashtableMT definitions
|
||||
|
|
Загрузка…
Ссылка в новой задаче