123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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/. */
- #ifndef nsCookieService_h__
- #define nsCookieService_h__
- #include "nsICookieService.h"
- #include "nsICookieManager.h"
- #include "nsICookieManager2.h"
- #include "nsIObserver.h"
- #include "nsWeakReference.h"
- #include "nsCookie.h"
- #include "nsString.h"
- #include "nsAutoPtr.h"
- #include "nsHashKeys.h"
- #include "nsIMemoryReporter.h"
- #include "nsTHashtable.h"
- #include "mozIStorageStatement.h"
- #include "mozIStorageAsyncStatement.h"
- #include "mozIStoragePendingStatement.h"
- #include "mozIStorageConnection.h"
- #include "mozIStorageRow.h"
- #include "mozIStorageCompletionCallback.h"
- #include "mozIStorageStatementCallback.h"
- #include "mozIStorageFunction.h"
- #include "nsIVariant.h"
- #include "nsIFile.h"
- #include "mozilla/BasePrincipal.h"
- #include "mozilla/MemoryReporting.h"
- #include "mozilla/Maybe.h"
- using mozilla::NeckoOriginAttributes;
- using mozilla::OriginAttributes;
- class nsICookiePermission;
- class nsIEffectiveTLDService;
- class nsIIDNService;
- class nsIPrefBranch;
- class nsIObserverService;
- class nsIURI;
- class nsIChannel;
- class nsIArray;
- class mozIStorageService;
- class mozIThirdPartyUtil;
- class ReadCookieDBListener;
- struct nsCookieAttributes;
- struct nsListIter;
- namespace mozilla {
- namespace net {
- class CookieServiceParent;
- } // namespace net
- } // namespace mozilla
- // hash key class
- class nsCookieKey : public PLDHashEntryHdr
- {
- public:
- typedef const nsCookieKey& KeyType;
- typedef const nsCookieKey* KeyTypePointer;
- nsCookieKey()
- {}
- nsCookieKey(const nsCString &baseDomain, const NeckoOriginAttributes &attrs)
- : mBaseDomain(baseDomain)
- , mOriginAttributes(attrs)
- {}
- explicit nsCookieKey(KeyTypePointer other)
- : mBaseDomain(other->mBaseDomain)
- , mOriginAttributes(other->mOriginAttributes)
- {}
- nsCookieKey(KeyType other)
- : mBaseDomain(other.mBaseDomain)
- , mOriginAttributes(other.mOriginAttributes)
- {}
- ~nsCookieKey()
- {}
- bool KeyEquals(KeyTypePointer other) const
- {
- return mBaseDomain == other->mBaseDomain &&
- mOriginAttributes == other->mOriginAttributes;
- }
- static KeyTypePointer KeyToPointer(KeyType aKey)
- {
- return &aKey;
- }
- static PLDHashNumber HashKey(KeyTypePointer aKey)
- {
- // TODO: more efficient way to generate hash?
- nsAutoCString temp(aKey->mBaseDomain);
- temp.Append('#');
- nsAutoCString suffix;
- aKey->mOriginAttributes.CreateSuffix(suffix);
- temp.Append(suffix);
- return mozilla::HashString(temp);
- }
- size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
- enum { ALLOW_MEMMOVE = true };
- nsCString mBaseDomain;
- NeckoOriginAttributes mOriginAttributes;
- };
- // Inherit from nsCookieKey so this can be stored in nsTHashTable
- // TODO: why aren't we using nsClassHashTable<nsCookieKey, ArrayType>?
- class nsCookieEntry : public nsCookieKey
- {
- public:
- // Hash methods
- typedef nsTArray< RefPtr<nsCookie> > ArrayType;
- typedef ArrayType::index_type IndexType;
- explicit nsCookieEntry(KeyTypePointer aKey)
- : nsCookieKey(aKey)
- {}
- nsCookieEntry(const nsCookieEntry& toCopy)
- {
- // if we end up here, things will break. nsTHashtable shouldn't
- // allow this, since we set ALLOW_MEMMOVE to true.
- NS_NOTREACHED("nsCookieEntry copy constructor is forbidden!");
- }
- ~nsCookieEntry()
- {}
- inline ArrayType& GetCookies() { return mCookies; }
- size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
- private:
- ArrayType mCookies;
- };
- // encapsulates a (key, nsCookie) tuple for temporary storage purposes.
- struct CookieDomainTuple
- {
- nsCookieKey key;
- RefPtr<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 final
- {
- DBState() : cookieCount(0), cookieOldestTime(INT64_MAX), corruptFlag(OK)
- {
- }
- 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
- CLOSING_FOR_REBUILD, // corruption detected, connection closing
- REBUILDING // close complete, rebuilding database from memory
- };
- nsTHashtable<nsCookieEntry> hostTable;
- uint32_t cookieCount;
- int64_t cookieOldestTime;
- nsCOMPtr<nsIFile> cookieFile;
- nsCOMPtr<mozIStorageConnection> dbConn;
- nsCOMPtr<mozIStorageAsyncStatement> stmtInsert;
- nsCOMPtr<mozIStorageAsyncStatement> stmtDelete;
- nsCOMPtr<mozIStorageAsyncStatement> stmtUpdate;
- CorruptFlag corruptFlag;
- // Various parts representing asynchronous read state. These are useful
- // while the background read is taking place.
- nsCOMPtr<mozIStorageConnection> syncConn;
- nsCOMPtr<mozIStorageStatement> stmtReadDomain;
- nsCOMPtr<mozIStoragePendingStatement> pendingRead;
- // The asynchronous read listener. This is a weak ref (storage has ownership)
- // since it may need to outlive the DBState's database connection.
- ReadCookieDBListener* readListener;
- // An array of (baseDomain, cookie) tuples representing data read in
- // asynchronously. This is merged into hostTable once read is complete.
- nsTArray<CookieDomainTuple> hostArray;
- // A hashset of baseDomains read in synchronously, while the async read is
- // in flight. This is used to keep track of which data in hostArray is stale
- // when the time comes to merge.
- nsTHashtable<nsCookieKey> readSet;
- // DB completion handlers.
- nsCOMPtr<mozIStorageStatementCallback> insertListener;
- nsCOMPtr<mozIStorageStatementCallback> updateListener;
- nsCOMPtr<mozIStorageStatementCallback> removeListener;
- nsCOMPtr<mozIStorageCompletionCallback> closeListener;
- };
- // these constants represent a decision about a cookie based on user prefs.
- enum CookieStatus
- {
- STATUS_ACCEPTED,
- STATUS_ACCEPT_SESSION,
- STATUS_REJECTED,
- // STATUS_REJECTED_WITH_ERROR indicates the cookie should be rejected because
- // of an error (rather than something the user can control). this is used for
- // notification purposes, since we only want to notify of rejections where
- // the user can do something about it (e.g. whitelist the site).
- STATUS_REJECTED_WITH_ERROR
- };
- // Result codes for TryInitDB() and Read().
- enum OpenDBResult
- {
- RESULT_OK,
- RESULT_RETRY,
- RESULT_FAILURE
- };
- /******************************************************************************
- * nsCookieService:
- * class declaration
- ******************************************************************************/
- class nsCookieService final : public nsICookieService
- , public nsICookieManager2
- , public nsIObserver
- , public nsSupportsWeakReference
- , public nsIMemoryReporter
- {
- private:
- size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- NS_DECL_NSICOOKIESERVICE
- NS_DECL_NSICOOKIEMANAGER
- NS_DECL_NSICOOKIEMANAGER2
- NS_DECL_NSIMEMORYREPORTER
- nsCookieService();
- static nsICookieService* GetXPCOMSingleton();
- nsresult Init();
- /**
- * Start watching the observer service for messages indicating that an app has
- * been uninstalled. When an app is uninstalled, we get the cookie service
- * (thus instantiating it, if necessary) and clear all the cookies for that
- * app.
- */
- static void AppClearDataObserverInit();
- protected:
- virtual ~nsCookieService();
- void PrefChanged(nsIPrefBranch *aPrefBranch);
- void InitDBStates();
- OpenDBResult TryInitDB(bool aDeleteExistingDB);
- nsresult CreateTable();
- nsresult CreateTableForSchemaVersion6();
- nsresult CreateTableForSchemaVersion5();
- void CloseDBStates();
- void CleanupCachedStatements();
- void CleanupDefaultDBConnection();
- void HandleDBClosed(DBState* aDBState);
- void HandleCorruptDB(DBState* aDBState);
- void RebuildCorruptDB(DBState* aDBState);
- OpenDBResult Read();
- template<class T> nsCookie* GetCookieFromRow(T &aRow, const OriginAttributes& aOriginAttributes);
- void AsyncReadComplete();
- void CancelAsyncRead(bool aPurgeReadSet);
- void EnsureReadDomain(const nsCookieKey &aKey);
- void EnsureReadComplete();
- nsresult NormalizeHost(nsCString &aHost);
- nsresult GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
- nsresult GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
- nsresult GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
- void GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, const NeckoOriginAttributes aOriginAttrs, bool aIsPrivate, nsCString &aCookie);
- nsresult SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
- void SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, const NeckoOriginAttributes &aOriginAttrs, 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 = 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);
- static bool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
- bool RequireThirdPartyCheck();
- CookieStatus CheckPrefs(nsIURI *aHostURI, bool aIsForeign, const char *aCookieHeader);
- bool CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, bool aRequireHostMatch);
- static bool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
- static bool CheckPrefixes(nsCookieAttributes &aCookie, bool aSecureRequest);
- static bool GetExpiry(nsCookieAttributes &aCookie, int64_t aServerTime, int64_t aCurrentTime);
- void RemoveAllFromMemory();
- already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec);
- bool FindCookie(const nsCookieKey& aKey, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
- bool FindSecureCookie(const nsCookieKey& aKey, nsCookie* aCookie);
- int64_t FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsIURI* aSource, mozilla::Maybe<bool> aIsSecure, nsListIter &aIter);
- void NotifyRejected(nsIURI *aHostURI);
- void NotifyThirdParty(nsIURI *aHostURI, bool aAccepted, nsIChannel *aChannel);
- void NotifyChanged(nsISupports *aSubject, const char16_t *aData);
- void NotifyPurged(nsICookie2* aCookie);
- already_AddRefed<nsIArray> CreatePurgeList(nsICookie2* aCookie);
- void UpdateCookieOldestTime(DBState* aDBState, nsCookie* aCookie);
- nsresult GetCookiesWithOriginAttributes(const mozilla::OriginAttributesPattern& aPattern, const nsCString& aBaseDomain, nsISimpleEnumerator **aEnumerator);
- nsresult RemoveCookiesWithOriginAttributes(const mozilla::OriginAttributesPattern& aPattern, const nsCString& aBaseDomain);
- /**
- * This method is a helper that allows calling nsICookieManager::Remove()
- * with NeckoOriginAttributes parameter.
- * NOTE: this could be added to a public interface if we happen to need it.
- */
- nsresult Remove(const nsACString& aHost, const NeckoOriginAttributes& aAttrs,
- const nsACString& aName, const nsACString& aPath,
- bool aBlocked);
- protected:
- // cached members.
- nsCOMPtr<nsICookiePermission> mPermissionService;
- nsCOMPtr<mozIThirdPartyUtil> mThirdPartyUtil;
- nsCOMPtr<nsIEffectiveTLDService> mTLDService;
- nsCOMPtr<nsIIDNService> mIDNService;
- nsCOMPtr<mozIStorageService> mStorageService;
- // we have two separate DB states: one for normal browsing and one for
- // private browsing, switching between them on a per-cookie-request basis.
- // this state encapsulates both the in-memory table and the on-disk DB.
- // note that the private states' dbConn should always be null - we never
- // want to be dealing with the on-disk DB when in private browsing.
- DBState *mDBState;
- RefPtr<DBState> mDefaultDBState;
- RefPtr<DBState> mPrivateDBState;
- // cached prefs
- uint8_t mCookieBehavior; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT, LIMITFOREIGN}
- bool mThirdPartySession;
- bool mLeaveSecureAlone;
- uint16_t mMaxNumberOfCookies;
- uint16_t mMaxCookiesPerHost;
- int64_t mCookiePurgeAge;
- // friends!
- friend class DBListenerErrorHandler;
- friend class ReadCookieDBListener;
- friend class CloseCookieDBListener;
- static nsCookieService* GetSingleton();
- friend class mozilla::net::CookieServiceParent;
- };
- #endif // nsCookieService_h__
|