/* -*- 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 mozilla_net_CookieStorage_h #define mozilla_net_CookieStorage_h #include "CookieKey.h" #include "nsIObserver.h" #include "nsTHashtable.h" #include "nsWeakReference.h" #include #include "CookieCommons.h" class nsIArray; class nsICookie; class nsICookieTransactionCallback; class nsIPrefBranch; namespace mozilla { namespace net { class Cookie; // Inherit from CookieKey so this can be stored in nsTHashTable // TODO: why aren't we using nsClassHashTable? class CookieEntry : public CookieKey { public: // Hash methods using ArrayType = nsTArray>; using IndexType = ArrayType::index_type; explicit CookieEntry(KeyTypePointer aKey) : CookieKey(aKey) {} CookieEntry(const CookieEntry& toCopy) { // if we end up here, things will break. nsTHashtable shouldn't // allow this, since we set ALLOW_MEMMOVE to true. MOZ_ASSERT_UNREACHABLE("CookieEntry copy constructor is forbidden!"); } ~CookieEntry() = default; inline ArrayType& GetCookies() { return mCookies; } inline const ArrayType& GetCookies() const { return mCookies; } size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; private: ArrayType mCookies; }; // stores the CookieEntry entryclass and an index into the cookie array within // that entryclass, for purposes of storing an iteration state that points to a // certain cookie. struct CookieListIter { // default (non-initializing) constructor. CookieListIter() = default; // explicit constructor to a given iterator state with entryclass 'aEntry' // and index 'aIndex'. explicit CookieListIter(CookieEntry* aEntry, CookieEntry::IndexType aIndex) : entry(aEntry), index(aIndex) {} // get the Cookie * the iterator currently points to. mozilla::net::Cookie* Cookie() const { return entry->GetCookies()[index]; } CookieEntry* entry; CookieEntry::IndexType index; }; class CookieStorage : public nsIObserver, public nsSupportsWeakReference { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIOBSERVER size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; void GetCookies(nsTArray>& aCookies) const; void GetSessionCookies(nsTArray>& aCookies) const; bool FindCookie(const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes, const nsACString& aHost, const nsACString& aName, const nsACString& aPath, CookieListIter& aIter); uint32_t CountCookiesFromHost(const nsACString& aBaseDomain, uint32_t aPrivateBrowsingId); void GetAll(nsTArray>& aResult) const; const nsTArray>* GetCookiesFromHost( const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes); void GetCookiesWithOriginAttributes(const OriginAttributesPattern& aPattern, const nsACString& aBaseDomain, nsTArray>& aResult); void RemoveCookie(const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes, const nsACString& aHost, const nsACString& aName, const nsACString& aPath); virtual void RemoveCookiesWithOriginAttributes( const OriginAttributesPattern& aPattern, const nsACString& aBaseDomain); virtual void RemoveCookiesFromExactHost( const nsACString& aHost, const nsACString& aBaseDomain, const OriginAttributesPattern& aPattern); void RemoveAll(); void NotifyChanged(nsISupports* aSubject, const char16_t* aData, bool aOldCookieIsSession = false); void AddCookie(nsIConsoleReportCollector* aCRC, const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes, Cookie* aCookie, int64_t aCurrentTimeInUsec, nsIURI* aHostURI, const nsACString& aCookieHeader, bool aFromHttp); static void CreateOrUpdatePurgeList(nsIArray** aPurgedList, nsICookie* aCookie); virtual void StaleCookies(const nsTArray& aCookieList, int64_t aCurrentTimeInUsec) = 0; virtual void Close() = 0; virtual void EnsureInitialized() = 0; virtual nsresult RunInTransaction( nsICookieTransactionCallback* aCallback) = 0; protected: CookieStorage() = default; virtual ~CookieStorage() = default; void Init(); void AddCookieToList(const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes, Cookie* aCookie); virtual void StoreCookie(const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes, Cookie* aCookie) = 0; virtual const char* NotificationTopic() const = 0; virtual void NotifyChangedInternal(nsISupports* aSubject, const char16_t* aData, bool aOldCookieIsSession) = 0; virtual void RemoveAllInternal() = 0; // This method calls RemoveCookieFromDB + RemoveCookieFromListInternal. void RemoveCookieFromList(const CookieListIter& aIter); void RemoveCookieFromListInternal(const CookieListIter& aIter); virtual void RemoveCookieFromDB(const CookieListIter& aIter) = 0; already_AddRefed PurgeCookiesWithCallbacks( int64_t aCurrentTimeInUsec, uint16_t aMaxNumberOfCookies, int64_t aCookiePurgeAge, std::function&& aRemoveCookieCallback, std::function&& aFinalizeCallback); nsTHashtable mHostTable; uint32_t mCookieCount{0}; private: void PrefChanged(nsIPrefBranch* aPrefBranch); bool FindSecureCookie(const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes, Cookie* aCookie); static void FindStaleCookies(CookieEntry* aEntry, int64_t aCurrentTime, bool aIsSecure, nsTArray& aOutput, uint32_t aLimit); void UpdateCookieOldestTime(Cookie* aCookie); void MergeCookieSchemeMap(Cookie* aOldCookie, Cookie* aNewCookie); static already_AddRefed CreatePurgeList(nsICookie* aCookie); virtual already_AddRefed PurgeCookies(int64_t aCurrentTimeInUsec, uint16_t aMaxNumberOfCookies, int64_t aCookiePurgeAge) = 0; int64_t mCookieOldestTime{INT64_MAX}; uint16_t mMaxNumberOfCookies{kMaxNumberOfCookies}; uint16_t mMaxCookiesPerHost{kMaxCookiesPerHost}; uint16_t mCookieQuotaPerHost{kCookieQuotaPerHost}; int64_t mCookiePurgeAge{kCookiePurgeAge}; }; } // namespace net } // namespace mozilla #endif // mozilla_net_CookieStorage_h