diff options
author | Pale Moon <git-repo@palemoon.org> | 2016-09-01 13:39:08 +0200 |
---|---|---|
committer | Pale Moon <git-repo@palemoon.org> | 2016-09-01 13:39:08 +0200 |
commit | 3d8ce1a11a7347cc94a937719c4bc8df46fb8d14 (patch) | |
tree | 8c26ca375a6312751c00a27e1653fb6f189f0463 /netwerk/cookie | |
parent | e449bdb1ec3a82f204bffdd9c3c54069d086eee3 (diff) | |
download | palemoon-gre-3d8ce1a11a7347cc94a937719c4bc8df46fb8d14.tar.gz |
Base import of Tycho code (warning: huge commit)
Diffstat (limited to 'netwerk/cookie')
-rw-r--r-- | netwerk/cookie/CookieServiceChild.cpp | 45 | ||||
-rw-r--r-- | netwerk/cookie/CookieServiceChild.h | 3 | ||||
-rw-r--r-- | netwerk/cookie/CookieServiceParent.cpp | 45 | ||||
-rw-r--r-- | netwerk/cookie/CookieServiceParent.h | 21 | ||||
-rw-r--r-- | netwerk/cookie/Makefile.in | 34 | ||||
-rw-r--r-- | netwerk/cookie/PCookieService.ipdl | 28 | ||||
-rw-r--r-- | netwerk/cookie/ipdl.mk | 8 | ||||
-rw-r--r-- | netwerk/cookie/moz.build | 37 | ||||
-rw-r--r-- | netwerk/cookie/nsCookie.cpp | 15 | ||||
-rw-r--r-- | netwerk/cookie/nsCookie.h | 8 | ||||
-rw-r--r-- | netwerk/cookie/nsCookieService.cpp | 393 | ||||
-rw-r--r-- | netwerk/cookie/nsCookieService.h | 55 | ||||
-rw-r--r-- | netwerk/cookie/nsICookieManager.idl | 2 | ||||
-rw-r--r-- | netwerk/cookie/test/unit/xpcshell.ini | 1 | ||||
-rw-r--r-- | netwerk/cookie/test/unit_ipc/xpcshell.ini | 1 |
15 files changed, 407 insertions, 289 deletions
diff --git a/netwerk/cookie/CookieServiceChild.cpp b/netwerk/cookie/CookieServiceChild.cpp index 3150c9627..3edff1aef 100644 --- a/netwerk/cookie/CookieServiceChild.cpp +++ b/netwerk/cookie/CookieServiceChild.cpp @@ -4,14 +4,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/net/CookieServiceChild.h" -#include "mozilla/dom/TabChild.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/net/NeckoChild.h" #include "nsIURI.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" -#include "nsITabChild.h" #include "nsNetUtil.h" +#include "SerializedLoadContext.h" using namespace mozilla::ipc; @@ -21,7 +20,7 @@ namespace net { // Behavior pref constants static const int32_t BEHAVIOR_ACCEPT = 0; static const int32_t BEHAVIOR_REJECTFOREIGN = 1; -static const int32_t BEHAVIOR_REJECT = 2; +// static const int32_t BEHAVIOR_REJECT = 2; static const int32_t BEHAVIOR_LIMITFOREIGN = 3; // Pref string constants @@ -41,10 +40,10 @@ CookieServiceChild::GetSingleton() return gCookieService; } -NS_IMPL_ISUPPORTS3(CookieServiceChild, - nsICookieService, - nsIObserver, - nsISupportsWeakReference) +NS_IMPL_ISUPPORTS(CookieServiceChild, + nsICookieService, + nsIObserver, + nsISupportsWeakReference) CookieServiceChild::CookieServiceChild() : mCookieBehavior(BEHAVIOR_ACCEPT) @@ -108,7 +107,7 @@ CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI, NS_ENSURE_ARG(aHostURI); NS_ENSURE_ARG_POINTER(aCookieString); - *aCookieString = NULL; + *aCookieString = nullptr; // Determine whether the request is foreign. Failure is acceptable. bool isForeign = true; @@ -118,22 +117,10 @@ CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI, URIParams uriParams; SerializeURI(aHostURI, uriParams); - nsCOMPtr<nsITabChild> iTabChild; - mozilla::dom::TabChild* tabChild = nullptr; - if (aChannel) { - NS_QueryNotificationCallbacks(aChannel, iTabChild); - if (iTabChild) { - tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get()); - } - if (MissingRequiredTabChild(tabChild, "cookie")) { - return NS_ERROR_ILLEGAL_VALUE; - } - } - // Synchronously call the parent. nsAutoCString result; SendGetCookieString(uriParams, !!isForeign, aFromHttp, - IPC::SerializedLoadContext(aChannel), tabChild, &result); + IPC::SerializedLoadContext(aChannel), &result); if (!result.IsEmpty()) *aCookieString = ToNewCString(result); @@ -163,28 +150,16 @@ CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI, URIParams uriParams; SerializeURI(aHostURI, uriParams); - nsCOMPtr<nsITabChild> iTabChild; - mozilla::dom::TabChild* tabChild = nullptr; - if (aChannel) { - NS_QueryNotificationCallbacks(aChannel, iTabChild); - if (iTabChild) { - tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get()); - } - if (MissingRequiredTabChild(tabChild, "cookie")) { - return NS_ERROR_ILLEGAL_VALUE; - } - } - // Synchronously call the parent. SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime, - aFromHttp, IPC::SerializedLoadContext(aChannel), tabChild); + aFromHttp, IPC::SerializedLoadContext(aChannel)); return NS_OK; } NS_IMETHODIMP CookieServiceChild::Observe(nsISupports *aSubject, const char *aTopic, - const PRUnichar *aData) + const char16_t *aData) { NS_ASSERTION(strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0, "not a pref change topic!"); diff --git a/netwerk/cookie/CookieServiceChild.h b/netwerk/cookie/CookieServiceChild.h index 8f2678866..9b556615e 100644 --- a/netwerk/cookie/CookieServiceChild.h +++ b/netwerk/cookie/CookieServiceChild.h @@ -27,11 +27,12 @@ public: NS_DECL_NSIOBSERVER CookieServiceChild(); - virtual ~CookieServiceChild(); static CookieServiceChild* GetSingleton(); protected: + virtual ~CookieServiceChild(); + void SerializeURIs(nsIURI *aHostURI, nsIChannel *aChannel, nsCString &aHostSpec, diff --git a/netwerk/cookie/CookieServiceParent.cpp b/netwerk/cookie/CookieServiceParent.cpp index 5d8fe641c..7546690fa 100644 --- a/netwerk/cookie/CookieServiceParent.cpp +++ b/netwerk/cookie/CookieServiceParent.cpp @@ -4,34 +4,35 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/net/CookieServiceParent.h" -#include "mozilla/dom/PBrowserParent.h" +#include "mozilla/dom/PContentParent.h" #include "mozilla/net/NeckoParent.h" #include "mozilla/ipc/URIUtils.h" #include "nsCookieService.h" #include "nsNetUtil.h" #include "nsPrintfCString.h" +#include "SerializedLoadContext.h" using namespace mozilla::ipc; -using mozilla::dom::PBrowserParent; +using mozilla::dom::PContentParent; using mozilla::net::NeckoParent; namespace mozilla { namespace net { MOZ_WARN_UNUSED_RESULT -static bool -GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext, - PBrowserParent* aBrowser, - uint32_t& aAppId, - bool& aIsInBrowserElement, - bool& aIsPrivate) +bool +CookieServiceParent::GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext, + uint32_t& aAppId, + bool& aIsInBrowserElement, + bool& aIsPrivate) { aAppId = NECKO_NO_APP_ID; aIsInBrowserElement = false; aIsPrivate = false; - const char* error = NeckoParent::GetValidatedAppInfo(aLoadContext, aBrowser, + const char* error = NeckoParent::GetValidatedAppInfo(aLoadContext, + Manager()->Manager(), &aAppId, &aIsInBrowserElement); if (error) { @@ -63,13 +64,18 @@ CookieServiceParent::~CookieServiceParent() { } +void +CookieServiceParent::ActorDestroy(ActorDestroyReason aWhy) +{ + // Implement me! Bug 1005181 +} + bool CookieServiceParent::RecvGetCookieString(const URIParams& aHost, const bool& aIsForeign, const bool& aFromHttp, const IPC::SerializedLoadContext& aLoadContext, - PBrowserParent* aBrowser, nsCString* aResult) { if (!mCookieService) @@ -83,7 +89,7 @@ CookieServiceParent::RecvGetCookieString(const URIParams& aHost, uint32_t appId; bool isInBrowserElement, isPrivate; - bool valid = GetAppInfoFromParams(aLoadContext, aBrowser, appId, + bool valid = GetAppInfoFromParams(aLoadContext, appId, isInBrowserElement, isPrivate); if (!valid) { return false; @@ -101,8 +107,7 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost, const nsCString& aServerTime, const bool& aFromHttp, const IPC::SerializedLoadContext& - aLoadContext, - PBrowserParent* aBrowser) + aLoadContext) { if (!mCookieService) return true; @@ -115,7 +120,7 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost, uint32_t appId; bool isInBrowserElement, isPrivate; - bool valid = GetAppInfoFromParams(aLoadContext, aBrowser, appId, + bool valid = GetAppInfoFromParams(aLoadContext, appId, isInBrowserElement, isPrivate); if (!valid) { return false; @@ -129,6 +134,18 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost, return true; } +mozilla::ipc::IProtocol* +CookieServiceParent::CloneProtocol(Channel* aChannel, + mozilla::ipc::ProtocolCloneContext* aCtx) +{ + NeckoParent* manager = aCtx->GetNeckoParent(); + nsAutoPtr<PCookieServiceParent> actor(manager->AllocPCookieServiceParent()); + if (!actor || !manager->RecvPCookieServiceConstructor(actor)) { + return nullptr; + } + return actor.forget(); +} + } } diff --git a/netwerk/cookie/CookieServiceParent.h b/netwerk/cookie/CookieServiceParent.h index ec228ae6a..bbc092b16 100644 --- a/netwerk/cookie/CookieServiceParent.h +++ b/netwerk/cookie/CookieServiceParent.h @@ -13,9 +13,6 @@ class nsCookieService; class nsIIOService; namespace mozilla { -namespace dom { - class PBrowserParent; -} namespace net { class CookieServiceParent : public PCookieServiceParent @@ -25,13 +22,20 @@ public: virtual ~CookieServiceParent(); protected: + MOZ_WARN_UNUSED_RESULT bool + GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext, + uint32_t& aAppId, + bool& aIsInBrowserElement, + bool& aIsPrivate); + + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + virtual bool RecvGetCookieString(const URIParams& aHost, const bool& aIsForeign, const bool& aFromHttp, const IPC::SerializedLoadContext& loadContext, - mozilla::dom::PBrowserParent* aBrowser, - nsCString* aResult); + nsCString* aResult) override; virtual bool RecvSetCookieString(const URIParams& aHost, const bool& aIsForeign, @@ -39,8 +43,11 @@ protected: const nsCString& aServerTime, const bool& aFromHttp, const IPC::SerializedLoadContext& - loadContext, - mozilla::dom::PBrowserParent* aBrowser); + loadContext) override; + + virtual mozilla::ipc::IProtocol* + CloneProtocol(Channel* aChannel, + mozilla::ipc::ProtocolCloneContext* aCtx) override; nsRefPtr<nsCookieService> mCookieService; }; diff --git a/netwerk/cookie/Makefile.in b/netwerk/cookie/Makefile.in deleted file mode 100644 index 024ad3314..000000000 --- a/netwerk/cookie/Makefile.in +++ /dev/null @@ -1,34 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -DEPTH = @DEPTH@ -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ -relativesrcdir = @relativesrcdir@ - -include $(DEPTH)/config/autoconf.mk - -# export required interfaces, even if --disable-cookies has been given -FAIL_ON_WARNINGS := 1 - -ifdef NECKO_COOKIES -LIBRARY_NAME = neckocookie_s -MSVC_ENABLE_PGO := 1 -LIBXUL_LIBRARY = 1 -FORCE_STATIC_LIB = 1 - -LOCAL_INCLUDES = \ - -I$(topsrcdir)/intl/uconv/src \ - $(NULL) - -endif - - -include $(topsrcdir)/config/config.mk -include $(topsrcdir)/ipc/chromium/chromium-config.mk -include $(topsrcdir)/config/rules.mk - -DEFINES += -DIMPL_NS_NET diff --git a/netwerk/cookie/PCookieService.ipdl b/netwerk/cookie/PCookieService.ipdl index 5a004a9b1..183a4ff3f 100644 --- a/netwerk/cookie/PCookieService.ipdl +++ b/netwerk/cookie/PCookieService.ipdl @@ -6,12 +6,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PNecko; -include protocol PBrowser; include URIParams; -include "SerializedLoadContext.h"; -using IPC::SerializedLoadContext; +using class IPC::SerializedLoadContext from "SerializedLoadContext.h"; namespace mozilla { namespace net { @@ -29,7 +27,7 @@ namespace net { * @see nsICookiePermission */ -sync protocol PCookieService +prio(normal upto urgent) sync protocol PCookieService { manager PNecko; @@ -62,11 +60,10 @@ parent: * * @return the resulting cookie string. */ - sync GetCookieString(URIParams host, - bool isForeign, - bool fromHttp, - SerializedLoadContext loadContext, - nullable PBrowser browser) + prio(urgent) sync GetCookieString(URIParams host, + bool isForeign, + bool fromHttp, + SerializedLoadContext loadContext) returns (nsCString result); /* @@ -98,13 +95,12 @@ parent: * @see nsICookieService.setCookieStringFromHttp * @see mozIThirdPartyUtil.isThirdPartyChannel */ - SetCookieString(URIParams host, - bool isForeign, - nsCString cookieString, - nsCString serverTime, - bool fromHttp, - SerializedLoadContext loadContext, - nullable PBrowser browser); + prio(urgent) async SetCookieString(URIParams host, + bool isForeign, + nsCString cookieString, + nsCString serverTime, + bool fromHttp, + SerializedLoadContext loadContext); __delete__(); }; diff --git a/netwerk/cookie/ipdl.mk b/netwerk/cookie/ipdl.mk deleted file mode 100644 index cf848207f..000000000 --- a/netwerk/cookie/ipdl.mk +++ /dev/null @@ -1,8 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -IPDLSRCS = \ - PCookieService.ipdl \ - $(NULL) - diff --git a/netwerk/cookie/moz.build b/netwerk/cookie/moz.build index e9a61b9b3..51582c94e 100644 --- a/netwerk/cookie/moz.build +++ b/netwerk/cookie/moz.build @@ -4,6 +4,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +# export required interfaces, even if --disable-cookies has been given XPIDL_SOURCES += [ 'nsICookie.idl', 'nsICookie2.idl', @@ -15,23 +16,37 @@ XPIDL_SOURCES += [ XPIDL_MODULE = 'necko_cookie' -MODULE = 'necko' - if CONFIG['NECKO_COOKIES']: + MSVC_ENABLE_PGO = True + EXPORTS.mozilla.net = [ - 'CookieServiceParent.h', 'CookieServiceChild.h', + 'CookieServiceParent.h', ] - CPP_SOURCES += [ + UNIFIED_SOURCES += [ + 'CookieServiceChild.cpp', + 'CookieServiceParent.cpp', 'nsCookie.cpp', + ] + # nsCookieService.cpp can't be unified because of symbol conflicts + SOURCES += [ 'nsCookieService.cpp', - 'CookieServiceParent.cpp', - 'CookieServiceChild.cpp', + ] + LOCAL_INCLUDES += [ + '/intl/uconv', ] -if CONFIG['NECKO_COOKIES']: - XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini'] + XPCSHELL_TESTS_MANIFESTS += [ + 'test/unit/xpcshell.ini', + 'test/unit_ipc/xpcshell.ini', + ] + +IPDL_SOURCES = [ + 'PCookieService.ipdl', +] + +FAIL_ON_WARNINGS = True + +include('/ipc/chromium/chromium-config.mozbuild') -# FIXME/bug 575918: out-of-process xpcshell is broken on OS X -if CONFIG['NECKO_COOKIES'] and CONFIG['OS_ARCH'] != 'Darwin': - XPCSHELL_TESTS_MANIFESTS += ['test/unit_ipc/xpcshell.ini'] +FINAL_LIBRARY = 'xul' diff --git a/netwerk/cookie/nsCookie.cpp b/netwerk/cookie/nsCookie.cpp index e5cc845a4..8b976f9dd 100644 --- a/netwerk/cookie/nsCookie.cpp +++ b/netwerk/cookie/nsCookie.cpp @@ -6,6 +6,7 @@ #include "nsCookie.h" #include "nsUTF8ConverterService.h" #include <stdlib.h> +#include "nsAutoPtr.h" /****************************************************************************** * nsCookie: @@ -80,9 +81,9 @@ nsCookie::Create(const nsACString &aName, { // Ensure mValue contains a valid UTF-8 sequence. Otherwise XPConnect will // truncate the string after the first invalid octet. - nsUTF8ConverterService converter; + nsRefPtr<nsUTF8ConverterService> converter = new nsUTF8ConverterService(); nsAutoCString aUTF8Value; - converter.ConvertStringToUTF8(aValue, "UTF-8", false, true, 1, aUTF8Value); + converter->ConvertStringToUTF8(aValue, "UTF-8", false, true, 1, aUTF8Value); // find the required string buffer size, adding 4 for the terminating nulls const uint32_t stringLength = aName.Length() + aUTF8Value.Length() + @@ -111,6 +112,14 @@ nsCookie::Create(const nsACString &aName, aIsSession, aIsSecure, aIsHttpOnly); } +size_t +nsCookie::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const +{ + // There is no need to measure the sizes of the individual string + // members, since the strings are stored in-line with the nsCookie. + return aMallocSizeOf(this); +} + /****************************************************************************** * nsCookie: * xpcom impl @@ -145,4 +154,4 @@ nsCookie::GetExpires(uint64_t *aExpires) return NS_OK; } -NS_IMPL_ISUPPORTS2(nsCookie, nsICookie2, nsICookie) +NS_IMPL_ISUPPORTS(nsCookie, nsICookie2, nsICookie) diff --git a/netwerk/cookie/nsCookie.h b/netwerk/cookie/nsCookie.h index 2effda333..882a1b11e 100644 --- a/netwerk/cookie/nsCookie.h +++ b/netwerk/cookie/nsCookie.h @@ -10,6 +10,8 @@ #include "nsICookie2.h" #include "nsString.h" +#include "mozilla/MemoryReporting.h" + /** * The nsCookie class is the main cookie storage medium for use within cookie * code. It implements nsICookie2, which extends nsICookie, a frozen interface @@ -74,7 +76,7 @@ class nsCookie : public nsICookie2 bool aIsSecure, bool aIsHttpOnly); - virtual ~nsCookie() {} + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; // fast (inline, non-xpcom) getters inline const nsDependentCString Name() const { return nsDependentCString(mName, mValue - 1); } @@ -99,11 +101,15 @@ class nsCookie : public nsICookie2 inline void SetCreationTime(int64_t aTime) { mCreationTime = aTime; } protected: + virtual ~nsCookie() {} + // member variables // we use char* ptrs to store the strings in a contiguous block, // so we save on the overhead of using nsCStrings. However, we // store a terminating null for each string, so we can hand them // out as nsAFlatCStrings. + // + // Please update SizeOfIncludingThis if this strategy changes. const char *mName; const char *mValue; const char *mHost; diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp index 636b52ef0..0556fa7c7 100644 --- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -8,11 +8,6 @@ #include "mozilla/DebugOnly.h" #include "mozilla/Likely.h" -#ifdef MOZ_LOGGING -// this next define has to appear before the include of prlog.h -#define FORCE_PR_LOG // Allow logging in the release build -#endif - #include "mozilla/net/CookieServiceChild.h" #include "mozilla/net/NeckoCommon.h" @@ -49,8 +44,10 @@ #include "mozilla/storage.h" #include "mozilla/AutoRestore.h" #include "mozilla/FileUtils.h" +#include "mozilla/Telemetry.h" #include "nsIAppsService.h" #include "mozIApplication.h" +#include "nsIConsoleService.h" using namespace mozilla; using namespace mozilla::net; @@ -355,12 +352,12 @@ LogSuccess(bool aSetCookie, nsIURI *aHostURI, const nsAFlatCString &aCookieStrin class DBListenerErrorHandler : public mozIStorageStatementCallback { protected: - DBListenerErrorHandler(DBState* dbState) : mDBState(dbState) { } + explicit DBListenerErrorHandler(DBState* dbState) : mDBState(dbState) { } nsRefPtr<DBState> mDBState; virtual const char *GetOpType() = 0; public: - NS_IMETHOD HandleError(mozIStorageError* aError) + NS_IMETHOD HandleError(mozIStorageError* aError) override { int32_t result = -1; aError->GetResult(&result); @@ -385,21 +382,23 @@ public: * InsertCookieDBListener impl: * mozIStorageStatementCallback used to track asynchronous insertion operations. ******************************************************************************/ -class InsertCookieDBListener MOZ_FINAL : public DBListenerErrorHandler +class InsertCookieDBListener final : public DBListenerErrorHandler { -protected: - virtual const char *GetOpType() { return "INSERT"; } +private: + virtual const char *GetOpType() override { return "INSERT"; } + + ~InsertCookieDBListener() {} public: NS_DECL_ISUPPORTS - InsertCookieDBListener(DBState* dbState) : DBListenerErrorHandler(dbState) { } - NS_IMETHOD HandleResult(mozIStorageResultSet*) + explicit InsertCookieDBListener(DBState* dbState) : DBListenerErrorHandler(dbState) { } + NS_IMETHOD HandleResult(mozIStorageResultSet*) override { NS_NOTREACHED("Unexpected call to InsertCookieDBListener::HandleResult"); return NS_OK; } - NS_IMETHOD HandleCompletion(uint16_t aReason) + NS_IMETHOD HandleCompletion(uint16_t aReason) override { // If we were rebuilding the db and we succeeded, make our corruptFlag say // so. @@ -413,74 +412,80 @@ public: } }; -NS_IMPL_ISUPPORTS1(InsertCookieDBListener, mozIStorageStatementCallback) +NS_IMPL_ISUPPORTS(InsertCookieDBListener, mozIStorageStatementCallback) /****************************************************************************** * UpdateCookieDBListener impl: * mozIStorageStatementCallback used to track asynchronous update operations. ******************************************************************************/ -class UpdateCookieDBListener MOZ_FINAL : public DBListenerErrorHandler +class UpdateCookieDBListener final : public DBListenerErrorHandler { -protected: - virtual const char *GetOpType() { return "UPDATE"; } +private: + virtual const char *GetOpType() override { return "UPDATE"; } + + ~UpdateCookieDBListener() {} public: NS_DECL_ISUPPORTS - UpdateCookieDBListener(DBState* dbState) : DBListenerErrorHandler(dbState) { } - NS_IMETHOD HandleResult(mozIStorageResultSet*) + explicit UpdateCookieDBListener(DBState* dbState) : DBListenerErrorHandler(dbState) { } + NS_IMETHOD HandleResult(mozIStorageResultSet*) override { NS_NOTREACHED("Unexpected call to UpdateCookieDBListener::HandleResult"); return NS_OK; } - NS_IMETHOD HandleCompletion(uint16_t aReason) + NS_IMETHOD HandleCompletion(uint16_t aReason) override { return NS_OK; } }; -NS_IMPL_ISUPPORTS1(UpdateCookieDBListener, mozIStorageStatementCallback) +NS_IMPL_ISUPPORTS(UpdateCookieDBListener, mozIStorageStatementCallback) /****************************************************************************** * RemoveCookieDBListener impl: * mozIStorageStatementCallback used to track asynchronous removal operations. ******************************************************************************/ -class RemoveCookieDBListener MOZ_FINAL : public DBListenerErrorHandler +class RemoveCookieDBListener final : public DBListenerErrorHandler { -protected: - virtual const char *GetOpType() { return "REMOVE"; } +private: + virtual const char *GetOpType() override { return "REMOVE"; } + + ~RemoveCookieDBListener() {} public: NS_DECL_ISUPPORTS - RemoveCookieDBListener(DBState* dbState) : DBListenerErrorHandler(dbState) { } - NS_IMETHOD HandleResult(mozIStorageResultSet*) + explicit RemoveCookieDBListener(DBState* dbState) : DBListenerErrorHandler(dbState) { } + NS_IMETHOD HandleResult(mozIStorageResultSet*) override { NS_NOTREACHED("Unexpected call to RemoveCookieDBListener::HandleResult"); return NS_OK; } - NS_IMETHOD HandleCompletion(uint16_t aReason) + NS_IMETHOD HandleCompletion(uint16_t aReason) override { return NS_OK; } }; -NS_IMPL_ISUPPORTS1(RemoveCookieDBListener, mozIStorageStatementCallback) +NS_IMPL_ISUPPORTS(RemoveCookieDBListener, mozIStorageStatementCallback) /****************************************************************************** * ReadCookieDBListener impl: * mozIStorageStatementCallback used to track asynchronous removal operations. ******************************************************************************/ -class ReadCookieDBListener MOZ_FINAL : public DBListenerErrorHandler +class ReadCookieDBListener final : public DBListenerErrorHandler { -protected: - virtual const char *GetOpType() { return "READ"; } +private: + virtual const char *GetOpType() override { return "READ"; } bool mCanceled; + ~ReadCookieDBListener() {} + public: NS_DECL_ISUPPORTS - ReadCookieDBListener(DBState* dbState) + explicit ReadCookieDBListener(DBState* dbState) : DBListenerErrorHandler(dbState) , mCanceled(false) { @@ -488,7 +493,7 @@ public: void Cancel() { mCanceled = true; } - NS_IMETHOD HandleResult(mozIStorageResultSet *aResult) + NS_IMETHOD HandleResult(mozIStorageResultSet *aResult) override { nsCOMPtr<mozIStorageRow> row; @@ -508,7 +513,7 @@ public: return NS_OK; } - NS_IMETHOD HandleCompletion(uint16_t aReason) + NS_IMETHOD HandleCompletion(uint16_t aReason) override { // Process the completion of the read operation. If we have been canceled, // we cannot assume that the cookieservice still has an open connection @@ -544,38 +549,43 @@ public: } }; -NS_IMPL_ISUPPORTS1(ReadCookieDBListener, mozIStorageStatementCallback) +NS_IMPL_ISUPPORTS(ReadCookieDBListener, mozIStorageStatementCallback) /****************************************************************************** * CloseCookieDBListener imp: * Static mozIStorageCompletionCallback used to notify when the database is * successfully closed. ******************************************************************************/ -class CloseCookieDBListener MOZ_FINAL : public mozIStorageCompletionCallback +class CloseCookieDBListener final : public mozIStorageCompletionCallback { + ~CloseCookieDBListener() {} + public: - CloseCookieDBListener(DBState* dbState) : mDBState(dbState) { } + explicit CloseCookieDBListener(DBState* dbState) : mDBState(dbState) { } nsRefPtr<DBState> mDBState; NS_DECL_ISUPPORTS - NS_IMETHOD Complete() + NS_IMETHOD Complete(nsresult, nsISupports*) override { gCookieService->HandleDBClosed(mDBState); return NS_OK; } }; -NS_IMPL_ISUPPORTS1(CloseCookieDBListener, mozIStorageCompletionCallback) +NS_IMPL_ISUPPORTS(CloseCookieDBListener, mozIStorageCompletionCallback) namespace { -class AppClearDataObserver MOZ_FINAL : public nsIObserver { +class AppClearDataObserver final : public nsIObserver { + + ~AppClearDataObserver() {} + public: NS_DECL_ISUPPORTS // nsIObserver implementation. NS_IMETHODIMP - Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *data) + Observe(nsISupports *aSubject, const char *aTopic, const char16_t *data) override { MOZ_ASSERT(!nsCRT::strcmp(aTopic, TOPIC_WEB_APP_CLEAR_DATA)); @@ -592,10 +602,56 @@ public: } }; -NS_IMPL_ISUPPORTS1(AppClearDataObserver, nsIObserver) +NS_IMPL_ISUPPORTS(AppClearDataObserver, nsIObserver) } // anonymous namespace +size_t +nsCookieKey::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +{ + return mBaseDomain.SizeOfExcludingThisIfUnshared(aMallocSizeOf); +} + +size_t +nsCookieEntry::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +{ + size_t amount = nsCookieKey::SizeOfExcludingThis(aMallocSizeOf); + + amount += mCookies.SizeOfExcludingThis(aMallocSizeOf); + for (uint32_t i = 0; i < mCookies.Length(); ++i) { + amount += mCookies[i]->SizeOfIncludingThis(aMallocSizeOf); + } + + return amount; +} + +size_t +CookieDomainTuple::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +{ + size_t amount = 0; + + amount += key.SizeOfExcludingThis(aMallocSizeOf); + amount += cookie->SizeOfIncludingThis(aMallocSizeOf); + + return amount; +} + +size_t +DBState::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const +{ + size_t amount = 0; + + amount += aMallocSizeOf(this); + amount += hostTable.SizeOfExcludingThis(aMallocSizeOf); + amount += hostArray.SizeOfExcludingThis(aMallocSizeOf); + for (uint32_t i = 0; i < hostArray.Length(); ++i) { + amount += hostArray[i].SizeOfExcludingThis(aMallocSizeOf); + } + amount += readSet.SizeOfExcludingThis(aMallocSizeOf); + + return amount; +} + /****************************************************************************** * nsCookieService impl: * singleton instance ctor/dtor methods @@ -641,7 +697,7 @@ nsCookieService::GetSingleton() nsCookieService::AppClearDataObserverInit() { nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1"); - nsCOMPtr<AppClearDataObserver> obs = new AppClearDataObserver(); + nsCOMPtr<nsIObserver> obs = new AppClearDataObserver(); observerService->AddObserver(obs, TOPIC_WEB_APP_CLEAR_DATA, /* holdsWeak= */ false); } @@ -651,15 +707,16 @@ nsCookieService::AppClearDataObserverInit() * public methods ******************************************************************************/ -NS_IMPL_ISUPPORTS5(nsCookieService, - nsICookieService, - nsICookieManager, - nsICookieManager2, - nsIObserver, - nsISupportsWeakReference) +NS_IMPL_ISUPPORTS(nsCookieService, + nsICookieService, + nsICookieManager, + nsICookieManager2, + nsIObserver, + nsISupportsWeakReference, + nsIMemoryReporter) nsCookieService::nsCookieService() - : mDBState(NULL) + : mDBState(nullptr) , mCookieBehavior(BEHAVIOR_ACCEPT) , mThirdPartySession(false) , mMaxNumberOfCookies(kMaxNumberOfCookies) @@ -698,6 +755,8 @@ nsCookieService::Init() // Init our default, and possibly private DBStates. InitDBStates(); + RegisterWeakMemoryReporter(this); + mObserverService = mozilla::services::GetObserverService(); NS_ENSURE_STATE(mObserverService); mObserverService->AddObserver(this, "profile-before-change", true); @@ -744,8 +803,8 @@ nsCookieService::InitDBStates() // Database may be corrupt. Synchronously close the connection, clean up the // default DBState, and try again. COOKIE_LOGSTRING(PR_LOG_WARNING, ("InitDBStates(): retrying TryInitDB()")); - - CloseDefaultDBConnection(); + CleanupCachedStatements(); + CleanupDefaultDBConnection(); result = TryInitDB(true); if (result == RESULT_RETRY) { // We're done. Change the code to failure so we clean up below. @@ -759,7 +818,8 @@ nsCookieService::InitDBStates() // Connection failure is unrecoverable. Clean up our connection. We can run // fine without persistent storage -- e.g. if there's no profile. - CloseDefaultDBConnection(); + CleanupCachedStatements(); + CleanupDefaultDBConnection(); } } @@ -790,13 +850,15 @@ nsCookieService::TryInitDB(bool aRecreateDB) if (aRecreateDB) { nsCOMPtr<nsIFile> backupFile; mDefaultDBState->cookieFile->Clone(getter_AddRefs(backupFile)); - rv = backupFile->MoveToNative(NULL, + rv = backupFile->MoveToNative(nullptr, NS_LITERAL_CSTRING(COOKIES_FILE ".bak")); NS_ENSURE_SUCCESS(rv, RESULT_FAILURE); } // This block provides scope for the Telemetry AutoTimer { + Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_COOKIES_OPEN_READAHEAD_MS> + telemetry; ReadAheadFile(mDefaultDBState->cookieFile); // open a connection to the cookie database, and only cache our connection @@ -1233,13 +1295,16 @@ void nsCookieService::CloseDBStates() { // Null out our private and pointer DBStates regardless. - mPrivateDBState = NULL; - mDBState = NULL; + mPrivateDBState = nullptr; + mDBState = nullptr; // If we don't have a default DBState, we're done. if (!mDefaultDBState) return; + // Cleanup cached statements before we can close anything. + CleanupCachedStatements(); + if (mDefaultDBState->dbConn) { // Cancel any pending read. No further results will be received by our // read listener. @@ -1251,36 +1316,46 @@ nsCookieService::CloseDBStates() mDefaultDBState->dbConn->AsyncClose(mDefaultDBState->closeListener); } - CloseDefaultDBConnection(); + CleanupDefaultDBConnection(); - mDefaultDBState = NULL; + mDefaultDBState = nullptr; } -// Close the default connection by nulling out statements, listeners, and the -// connection itself. This will not cancel a pending read or asynchronously -// close the connection -- these must be done beforehand if necessary. +// Null out the statements. +// This must be done before closing the connection. void -nsCookieService::CloseDefaultDBConnection() +nsCookieService::CleanupCachedStatements() { - // Destroy our statements before we close the db. - mDefaultDBState->stmtInsert = NULL; - mDefaultDBState->stmtDelete = NULL; - mDefaultDBState->stmtUpdate = NULL; + mDefaultDBState->stmtInsert = nullptr; + mDefaultDBState->stmtDelete = nullptr; + mDefaultDBState->stmtUpdate = nullptr; +} + +// Null out the listeners, and the database connection itself. This +// will not null out the statements, cancel a pending read or +// asynchronously close the connection -- these must be done +// beforehand if necessary. +void +nsCookieService::CleanupDefaultDBConnection() +{ + MOZ_ASSERT(!mDefaultDBState->stmtInsert, "stmtInsert has been cleaned up"); + MOZ_ASSERT(!mDefaultDBState->stmtDelete, "stmtDelete has been cleaned up"); + MOZ_ASSERT(!mDefaultDBState->stmtUpdate, "stmtUpdate has been cleaned up"); // Null out the database connections. If 'dbConn' has not been used for any // asynchronous operations yet, this will synchronously close it; otherwise, // it's expected that the caller has performed an AsyncClose prior. - mDefaultDBState->dbConn = NULL; - mDefaultDBState->syncConn = NULL; + mDefaultDBState->dbConn = nullptr; + mDefaultDBState->syncConn = nullptr; // Manually null out our listeners. This is necessary because they hold a // strong ref to the DBState itself. They'll stay alive until whatever // statements are still executing complete. - mDefaultDBState->readListener = NULL; - mDefaultDBState->insertListener = NULL; - mDefaultDBState->updateListener = NULL; - mDefaultDBState->removeListener = NULL; - mDefaultDBState->closeListener = NULL; + mDefaultDBState->readListener = nullptr; + mDefaultDBState->insertListener = nullptr; + mDefaultDBState->updateListener = nullptr; + mDefaultDBState->removeListener = nullptr; + mDefaultDBState->closeListener = nullptr; } void @@ -1307,7 +1382,7 @@ nsCookieService::HandleDBClosed(DBState* aDBState) // 'cookies.sqlite.bak-rebuild'. nsCOMPtr<nsIFile> backupFile; aDBState->cookieFile->Clone(getter_AddRefs(backupFile)); - nsresult rv = backupFile->MoveToNative(NULL, + nsresult rv = backupFile->MoveToNative(nullptr, NS_LITERAL_CSTRING(COOKIES_FILE ".bak-rebuild")); COOKIE_LOGSTRING(PR_LOG_WARNING, @@ -1351,8 +1426,9 @@ nsCookieService::HandleCorruptDB(DBState* aDBState) mDefaultDBState->syncConn = nullptr; } + CleanupCachedStatements(); mDefaultDBState->dbConn->AsyncClose(mDefaultDBState->closeListener); - CloseDefaultDBConnection(); + CleanupDefaultDBConnection(); break; } case DBState::CLOSING_FOR_REBUILD: { @@ -1363,10 +1439,11 @@ nsCookieService::HandleCorruptDB(DBState* aDBState) case DBState::REBUILDING: { // We had an error while rebuilding the DB. Game over. Close the database // and let the close handler do nothing; then we'll move it out of the way. + CleanupCachedStatements(); if (mDefaultDBState->dbConn) { mDefaultDBState->dbConn->AsyncClose(mDefaultDBState->closeListener); } - CloseDefaultDBConnection(); + CleanupDefaultDBConnection(); break; } } @@ -1384,7 +1461,7 @@ RebuildDBCallback(nsCookieEntry *aEntry, nsCookie* cookie = cookies[i]; if (!cookie->IsSession()) { - bindCookieParameters(paramsArray, aEntry, cookie); + bindCookieParameters(paramsArray, nsCookieKey(aEntry), cookie); } } @@ -1422,7 +1499,8 @@ nsCookieService::RebuildCorruptDB(DBState* aDBState) // closure. COOKIE_LOGSTRING(PR_LOG_WARNING, ("RebuildCorruptDB(): TryInitDB() failed with result %u", result)); - CloseDefaultDBConnection(); + CleanupCachedStatements(); + CleanupDefaultDBConnection(); mDefaultDBState->corruptFlag = DBState::OK; mObserverService->NotifyObservers(nullptr, "cookie-db-closed", nullptr); return; @@ -1452,30 +1530,27 @@ nsCookieService::RebuildCorruptDB(DBState* aDBState) NS_ASSERT_SUCCESS(rv); nsCOMPtr<mozIStoragePendingStatement> handle; rv = stmt->ExecuteAsync(aDBState->insertListener, getter_AddRefs(handle)); - NS_ASSERT_SUCCESS(rv); + NS_ASSERT_SUCCESS(rv); } nsCookieService::~nsCookieService() { CloseDBStates(); + UnregisterWeakMemoryReporter(this); + gCookieService = nullptr; } NS_IMETHODIMP nsCookieService::Observe(nsISupports *aSubject, const char *aTopic, - const PRUnichar *aData) + const char16_t *aData) { // check the topic if (!strcmp(aTopic, "profile-before-change")) { // The profile is about to change, // or is going away because the application is shutting down. - if (mDBState && mDBState->dbConn && - !nsCRT::strcmp(aData, NS_LITERAL_STRING("shutdown-cleanse").get())) { - // Clear the cookie db if we're in the default DBState. - RemoveAll(); - } // Close the default DB connection and null out our DBStates before // changing. @@ -1557,7 +1632,19 @@ nsCookieService::SetCookieString(nsIURI *aHostURI, const char *aCookieHeader, nsIChannel *aChannel) { - return SetCookieStringCommon(aHostURI, aCookieHeader, NULL, aChannel, false); + // The aPrompt argument is deprecated and unused. Avoid introducing new + // code that uses this argument by warning if the value is non-null. + MOZ_ASSERT(!aPrompt); + if (aPrompt) { + nsCOMPtr<nsIConsoleService> aConsoleService = + do_GetService("@mozilla.org/consoleservice;1"); + if (aConsoleService) { + aConsoleService->LogStringMessage( + MOZ_UTF16("Non-null prompt ignored by nsCookieService.")); + } + } + return SetCookieStringCommon(aHostURI, aCookieHeader, nullptr, aChannel, + false); } NS_IMETHODIMP @@ -1568,6 +1655,17 @@ nsCookieService::SetCookieStringFromHttp(nsIURI *aHostURI, const char *aServerTime, nsIChannel *aChannel) { + // The aPrompt argument is deprecated and unused. Avoid introducing new + // code that uses this argument by warning if the value is non-null. + MOZ_ASSERT(!aPrompt); + if (aPrompt) { + nsCOMPtr<nsIConsoleService> aConsoleService = + do_GetService("@mozilla.org/consoleservice;1"); + if (aConsoleService) { + aConsoleService->LogStringMessage( + MOZ_UTF16("Non-null prompt ignored by nsCookieService.")); + } + } return SetCookieStringCommon(aHostURI, aCookieHeader, aServerTime, aChannel, true); } @@ -1705,8 +1803,24 @@ nsCookieService::NotifyThirdParty(nsIURI *aHostURI, bool aIsAccepted, nsIChannel if (!mObserverService) { return; } - const char* topic = aIsAccepted ? "third-party-cookie-accepted" - : "third-party-cookie-rejected"; + + const char* topic; + + if (mDBState != mPrivateDBState) { + // Regular (non-private) browsing + if (aIsAccepted) { + topic = "third-party-cookie-accepted"; + } else { + topic = "third-party-cookie-rejected"; + } + } else { + // Private browsing + if (aIsAccepted) { + topic = "private-third-party-cookie-accepted"; + } else { + topic = "private-third-party-cookie-rejected"; + } + } do { // Attempt to find the host of aChannel. @@ -1735,7 +1849,7 @@ nsCookieService::NotifyThirdParty(nsIURI *aHostURI, bool aIsAccepted, nsIChannel // This can fail for a number of reasons, in which kind we fallback to "?" mObserverService->NotifyObservers(aHostURI, topic, - NS_LITERAL_STRING("?").get()); + MOZ_UTF16("?")); } // notify observers that the cookie list changed. there are five possible @@ -1748,7 +1862,7 @@ nsCookieService::NotifyThirdParty(nsIURI *aHostURI, bool aIsAccepted, nsIChannel // cookies. void nsCookieService::NotifyChanged(nsISupports *aSubject, - const PRUnichar *aData) + const char16_t *aData) { const char* topic = mDBState == mPrivateDBState ? "private-cookie-changed" : "cookie-changed"; @@ -1834,7 +1948,7 @@ nsCookieService::RemoveAll() } } - NotifyChanged(nullptr, NS_LITERAL_STRING("cleared").get()); + NotifyChanged(nullptr, MOZ_UTF16("cleared")); return NS_OK; } @@ -1960,7 +2074,7 @@ nsCookieService::Remove(const nsACString& aHost, uint32_t aAppId, if (cookie) { // Everything's done. Notify observers. - NotifyChanged(cookie, NS_LITERAL_STRING("deleted").get()); + NotifyChanged(cookie, MOZ_UTF16("deleted")); } return NS_OK; @@ -1985,7 +2099,7 @@ OpenDBResult nsCookieService::Read() { // Set up a statement for the read. Note that our query specifies that - // 'baseDomain' not be NULL -- see below for why. + // 'baseDomain' not be nullptr -- see below for why. nsCOMPtr<mozIStorageAsyncStatement> stmtRead; nsresult rv = mDefaultDBState->dbConn->CreateAsyncStatement(NS_LITERAL_CSTRING( "SELECT " @@ -2005,7 +2119,7 @@ nsCookieService::Read() "WHERE baseDomain NOTNULL"), getter_AddRefs(stmtRead)); NS_ENSURE_SUCCESS(rv, RESULT_RETRY); - // Set up a statement to delete any rows with a NULL 'baseDomain' + // Set up a statement to delete any rows with a nullptr 'baseDomain' // column. This takes care of any cookies set by browsers that don't // understand the 'baseDomain' column, where the database schema version // is from one that does. (This would occur when downgrading.) @@ -2025,7 +2139,6 @@ nsCookieService::Read() // Init our readSet hash and execute the statements. Note that, after this // point, we cannot fail without altering the cleanup code in InitDBStates() // to handle closing of the now-asynchronous connection. - mDefaultDBState->readSet.Init(); mDefaultDBState->hostArray.SetCapacity(kMaxNumberOfCookies); mDefaultDBState->readListener = new ReadCookieDBListener(mDefaultDBState); @@ -2095,7 +2208,7 @@ nsCookieService::AsyncReadComplete() if (mDefaultDBState->readSet.GetEntry(tuple.key)) continue; - AddCookieToList(tuple.key, tuple.cookie, mDefaultDBState, NULL, false); + AddCookieToList(tuple.key, tuple.cookie, mDefaultDBState, nullptr, false); } mDefaultDBState->stmtReadDomain = nullptr; @@ -2222,7 +2335,7 @@ nsCookieService::EnsureReadDomain(const nsCookieKey &aKey) // Add the cookies to the table in a single operation. This makes sure that // either all the cookies get added, or in the case of corruption, none. for (uint32_t i = 0; i < array.Length(); ++i) { - AddCookieToList(aKey, array[i], mDefaultDBState, NULL, false); + AddCookieToList(aKey, array[i], mDefaultDBState, nullptr, false); } // Add it to the hashset of read entries, so we don't read it again. @@ -2311,7 +2424,7 @@ nsCookieService::EnsureReadComplete() // either all the cookies get added, or in the case of corruption, none. for (uint32_t i = 0; i < array.Length(); ++i) { CookieDomainTuple& tuple = array[i]; - AddCookieToList(tuple.key, tuple.cookie, mDefaultDBState, NULL, + AddCookieToList(tuple.key, tuple.cookie, mDefaultDBState, nullptr, false); } @@ -2471,7 +2584,7 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile) } else { AddInternal(key, newCookie, currentTimeInUsec, - NULL, NULL, true); + nullptr, nullptr, true); } } @@ -2766,16 +2879,8 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI, return newCookie; } - // XXX: For now we allow 0x20 (Space) in cookie names. - // Some websites apparently use cookie names with spaces in them, and the RFC - // doesn't exactly specify what to do in that case, so it's better to keep - // wider compatibility. - const char illegalNameCharacters[] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* 0x20, */ 0x00 }; - if (cookieAttributes.name.FindCharInSet(illegalNameCharacters, 0) != -1) { - COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "invalid cookie name character"); + if (cookieAttributes.name.FindChar('\t') != kNotFound) { + COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "invalid name character"); return newCookie; } @@ -2789,31 +2894,6 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI, return newCookie; } - // Reject cookie if value contains an RFC 6265 disallowed character. - // See RFC 6265 section 4.1.1 - // XXX: For now we allow for web compatibility (see issue #357): - // 0x20 (Space) - // 0x22 (DQUOTE) - // 0x2C (Comma) - // 0x5C (Backslash) - // - // FIXME: Before removing DQUOTE from the exceptions list: - // DQUOTE *cookie-octet DQUOTE is permitted and would fail if just removed. - // This needs better checking for first and last character allowing - // DQUOTE but not in the actual value. - // - // This only applies to cookies set via the Set-Cookie header, since - // document.cookie is defined to be UTF-8. - const char illegalCharacters[] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* 0x20, 0x22, */ - /* 0x2C, */ 0x3B, /* 0x5C, */ 0x7F, 0x00 }; - if (aFromHttp && (cookieAttributes.value.FindCharInSet(illegalCharacters, 0) != -1)) { - COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "illegal character in cookie"); - return newCookie; - } - // create a new nsCookie and copy attributes nsRefPtr<nsCookie> cookie = nsCookie::Create(cookieAttributes.name, @@ -2928,7 +3008,7 @@ nsCookieService::AddInternal(const nsCookieKey &aKey, if (aCookie->Expiry() <= currentTime) { COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "previously stored cookie was deleted"); - NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get()); + NotifyChanged(oldCookie, MOZ_UTF16("deleted")); return; } @@ -2973,17 +3053,17 @@ nsCookieService::AddInternal(const nsCookieKey &aKey, // Add the cookie to the db. We do not supply a params array for batching // because this might result in removals and additions being out of order. - AddCookieToList(aKey, aCookie, mDBState, NULL); + AddCookieToList(aKey, aCookie, mDBState, nullptr); COOKIE_LOGSUCCESS(SET_COOKIE, aHostURI, aCookieHeader, aCookie, foundCookie); // Now that list mutations are complete, notify observers. We do it here // because observers may themselves attempt to mutate the list. if (purgedList) { - NotifyChanged(purgedList, NS_LITERAL_STRING("batch-deleted").get()); + NotifyChanged(purgedList, MOZ_UTF16("batch-deleted")); } - NotifyChanged(aCookie, foundCookie ? NS_LITERAL_STRING("changed").get() - : NS_LITERAL_STRING("added").get()); + NotifyChanged(aCookie, foundCookie ? MOZ_UTF16("changed") + : MOZ_UTF16("added")); } /****************************************************************************** @@ -3814,7 +3894,7 @@ nsCookieService::FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsListIter &aIter) { - aIter.entry = NULL; + aIter.entry = nullptr; int64_t oldestTime = 0; const nsCookieEntry::ArrayType &cookies = aEntry->GetCookies(); @@ -3915,7 +3995,7 @@ struct GetCookiesForAppStruct { bool onlyBrowserElement; nsCOMArray<nsICookie> cookies; - GetCookiesForAppStruct() MOZ_DELETE; + GetCookiesForAppStruct() = delete; GetCookiesForAppStruct(uint32_t aAppId, bool aOnlyBrowserElement) : appId(aAppId) , onlyBrowserElement(aOnlyBrowserElement) @@ -3971,10 +4051,13 @@ nsCookieService::RemoveCookiesForApp(uint32_t aAppId, bool aOnlyBrowserElement) bool hasMore; while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr<nsISupports> supports; nsCOMPtr<nsICookie> cookie; - rv = enumerator->GetNext(getter_AddRefs(cookie)); + rv = enumerator->GetNext(getter_AddRefs(supports)); NS_ENSURE_SUCCESS(rv, rv); + cookie = do_QueryInterface(supports); + nsAutoCString host; cookie->GetHost(host); @@ -4243,3 +4326,29 @@ nsCookieService::UpdateCookieInList(nsCookie *aCookie, } } +size_t +nsCookieService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const +{ + size_t n = aMallocSizeOf(this); + + if (mDefaultDBState) { + n += mDefaultDBState->SizeOfIncludingThis(aMallocSizeOf); + } + if (mPrivateDBState) { + n += mPrivateDBState->SizeOfIncludingThis(aMallocSizeOf); + } + + return n; +} + +MOZ_DEFINE_MALLOC_SIZE_OF(CookieServiceMallocSizeOf) + +NS_IMETHODIMP +nsCookieService::CollectReports(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, bool aAnonymize) +{ + return MOZ_COLLECT_REPORT( + "explicit/cookie-service", KIND_HEAP, UNITS_BYTES, + SizeOfIncludingThis(CookieServiceMallocSizeOf), + "Memory used by the cookie service."); +} diff --git a/netwerk/cookie/nsCookieService.h b/netwerk/cookie/nsCookieService.h index c486c1a38..ee65ae4f7 100644 --- a/netwerk/cookie/nsCookieService.h +++ b/netwerk/cookie/nsCookieService.h @@ -16,6 +16,7 @@ #include "nsString.h" #include "nsAutoPtr.h" #include "nsHashKeys.h" +#include "nsIMemoryReporter.h" #include "nsTHashtable.h" #include "mozIStorageStatement.h" #include "mozIStorageAsyncStatement.h" @@ -25,6 +26,8 @@ #include "mozIStorageCompletionCallback.h" #include "mozIStorageStatementCallback.h" +#include "mozilla/MemoryReporting.h" + class nsICookiePermission; class nsIEffectiveTLDService; class nsIIDNService; @@ -63,13 +66,13 @@ public: , mInBrowserElement(inBrowser) {} - nsCookieKey(const KeyTypePointer other) + explicit nsCookieKey(KeyTypePointer other) : mBaseDomain(other->mBaseDomain) , mAppId(other->mAppId) , mInBrowserElement(other->mInBrowserElement) {} - nsCookieKey(const KeyType other) + nsCookieKey(KeyType other) : mBaseDomain(other.mBaseDomain) , mAppId(other.mAppId) , mInBrowserElement(other.mInBrowserElement) @@ -94,13 +97,15 @@ public: { // TODO: more efficient way to generate hash? nsAutoCString temp(aKey->mBaseDomain); - temp.Append("#"); + temp.Append('#'); temp.Append(aKey->mAppId); - temp.Append("#"); + temp.Append('#'); temp.Append(aKey->mInBrowserElement ? 1 : 0); return mozilla::HashString(temp); } + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + enum { ALLOW_MEMMOVE = true }; nsCString mBaseDomain; @@ -117,7 +122,7 @@ class nsCookieEntry : public nsCookieKey typedef nsTArray< nsRefPtr<nsCookie> > ArrayType; typedef ArrayType::index_type IndexType; - nsCookieEntry(KeyTypePointer aKey) + explicit nsCookieEntry(KeyTypePointer aKey) : nsCookieKey(aKey) {} @@ -133,6 +138,8 @@ class nsCookieEntry : public nsCookieKey inline ArrayType& GetCookies() { return mCookies; } + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + private: ArrayType mCookies; }; @@ -142,19 +149,29 @@ struct CookieDomainTuple { nsCookieKey key; nsRefPtr<nsCookie> cookie; + + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; }; // encapsulates in-memory and on-disk DB states, so we can // conveniently switch state when entering or exiting private browsing. -struct DBState +struct DBState final { DBState() : cookieCount(0), cookieOldestTime(INT64_MAX), corruptFlag(OK) { - hostTable.Init(); } +private: + // Private destructor, to discourage deletion outside of Release(): + ~DBState() + { + } + +public: NS_INLINE_DECL_REFCOUNTING(DBState) + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + // State of the database connection. enum CorruptFlag { OK, // normal @@ -221,21 +238,24 @@ enum OpenDBResult * class declaration ******************************************************************************/ -class nsCookieService : public nsICookieService - , public nsICookieManager2 - , public nsIObserver - , public nsSupportsWeakReference +class nsCookieService final : public nsICookieService + , public nsICookieManager2 + , public nsIObserver + , public nsSupportsWeakReference + , public nsIMemoryReporter { + private: + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + public: - // nsISupports NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER NS_DECL_NSICOOKIESERVICE NS_DECL_NSICOOKIEMANAGER NS_DECL_NSICOOKIEMANAGER2 + NS_DECL_NSIMEMORYREPORTER nsCookieService(); - virtual ~nsCookieService(); static nsICookieService* GetXPCOMSingleton(); nsresult Init(); @@ -248,12 +268,15 @@ class nsCookieService : public nsICookieService static void AppClearDataObserverInit(); protected: + virtual ~nsCookieService(); + void PrefChanged(nsIPrefBranch *aPrefBranch); void InitDBStates(); OpenDBResult TryInitDB(bool aDeleteExistingDB); nsresult CreateTable(); void CloseDBStates(); - void CloseDefaultDBConnection(); + void CleanupCachedStatements(); + void CleanupDefaultDBConnection(); void HandleDBClosed(DBState* aDBState); void HandleCorruptDB(DBState* aDBState); void RebuildCorruptDB(DBState* aDBState); @@ -272,7 +295,7 @@ class nsCookieService : public nsICookieService void SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, uint32_t aAppId, bool aInBrowserElement, bool aIsPrivate, nsIChannel* aChannel); bool SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel); void AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp); - void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = NULL); + void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = nullptr); void AddCookieToList(const nsCookieKey& aKey, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true); void UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray); static bool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound); @@ -288,7 +311,7 @@ class nsCookieService : public nsICookieService static void FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsListIter &aIter); void NotifyRejected(nsIURI *aHostURI); void NotifyThirdParty(nsIURI *aHostURI, bool aAccepted, nsIChannel *aChannel); - void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData); + void NotifyChanged(nsISupports *aSubject, const char16_t *aData); void NotifyPurged(nsICookie2* aCookie); already_AddRefed<nsIArray> CreatePurgeList(nsICookie2* aCookie); diff --git a/netwerk/cookie/nsICookieManager.idl b/netwerk/cookie/nsICookieManager.idl index 9abbf488f..bccef1e46 100644 --- a/netwerk/cookie/nsICookieManager.idl +++ b/netwerk/cookie/nsICookieManager.idl @@ -4,8 +4,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" -#include "nsISimpleEnumerator.idl" +interface nsISimpleEnumerator; /** * An optional interface for accessing or removing the cookies diff --git a/netwerk/cookie/test/unit/xpcshell.ini b/netwerk/cookie/test/unit/xpcshell.ini index f51f362de..40a543f61 100644 --- a/netwerk/cookie/test/unit/xpcshell.ini +++ b/netwerk/cookie/test/unit/xpcshell.ini @@ -1,6 +1,7 @@ [DEFAULT] head = tail = +skip-if = toolkit == 'gonk' [test_bug643051.js] [test_parser_0001.js] diff --git a/netwerk/cookie/test/unit_ipc/xpcshell.ini b/netwerk/cookie/test/unit_ipc/xpcshell.ini index 5fa215859..6ca62e653 100644 --- a/netwerk/cookie/test/unit_ipc/xpcshell.ini +++ b/netwerk/cookie/test/unit_ipc/xpcshell.ini @@ -1,6 +1,7 @@ [DEFAULT] head = tail = +skip-if = toolkit == 'android' || toolkit == 'gonk' [test_ipc_parser_0001.js] [test_ipc_parser_0019.js] |