CookieStorage.h (10133B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef mozilla_net_CookieStorage_h 7 #define mozilla_net_CookieStorage_h 8 9 #include "CookieKey.h" 10 11 #include "nsICookieNotification.h" 12 #include "nsIObserver.h" 13 #include "nsTHashtable.h" 14 #include "nsWeakReference.h" 15 #include <functional> 16 #include "CookieCommons.h" 17 18 class nsIArray; 19 class nsICookie; 20 class nsICookieTransactionCallback; 21 class nsIPrefBranch; 22 23 namespace mozilla { 24 namespace net { 25 26 class Cookie; 27 class CookieParser; 28 29 // Inherit from CookieKey so this can be stored in nsTHashTable 30 // TODO: why aren't we using nsClassHashTable<CookieKey, ArrayType>? 31 class CookieEntry : public CookieKey { 32 public: 33 // Hash methods 34 using ArrayType = nsTArray<RefPtr<Cookie>>; 35 using IndexType = ArrayType::index_type; 36 37 explicit CookieEntry(KeyTypePointer aKey) : CookieKey(aKey) {} 38 39 CookieEntry(const CookieEntry& toCopy) { 40 // if we end up here, things will break. nsTHashtable shouldn't 41 // allow this, since we set ALLOW_MEMMOVE to true. 42 MOZ_ASSERT_UNREACHABLE("CookieEntry copy constructor is forbidden!"); 43 } 44 45 ~CookieEntry() = default; 46 47 inline ArrayType& GetCookies() { return mCookies; } 48 inline const ArrayType& GetCookies() const { return mCookies; } 49 50 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; 51 52 bool IsPartitioned() const; 53 54 private: 55 ArrayType mCookies; 56 }; 57 58 class CookieStorage : public nsIObserver, public nsSupportsWeakReference { 59 public: 60 NS_DECL_THREADSAFE_ISUPPORTS 61 NS_DECL_NSIOBSERVER 62 63 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; 64 65 void GetCookies(nsTArray<RefPtr<nsICookie>>& aCookies) const; 66 67 void GetSessionCookies(nsTArray<RefPtr<nsICookie>>& aCookies) const; 68 69 already_AddRefed<Cookie> FindCookie(const nsACString& aBaseDomain, 70 const OriginAttributes& aOriginAttributes, 71 const nsACString& aHost, 72 const nsACString& aName, 73 const nsACString& aPath); 74 75 uint32_t CountCookiesFromHost(const nsACString& aBaseDomain, 76 uint32_t aPrivateBrowsingId); 77 78 uint32_t CountCookieBytesNotMatchingCookie(const Cookie& cookie, 79 const nsACString& baseDomain); 80 81 void GetAll(nsTArray<RefPtr<nsICookie>>& aResult) const; 82 83 void GetCookiesFromHost(const nsACString& aBaseDomain, 84 const OriginAttributes& aOriginAttributes, 85 nsTArray<RefPtr<Cookie>>& aCookies); 86 87 void GetCookiesWithOriginAttributes(const OriginAttributesPattern& aPattern, 88 const nsACString& aBaseDomain, 89 bool aSorted, 90 nsTArray<RefPtr<nsICookie>>& aResult); 91 92 void RemoveCookie(const nsACString& aBaseDomain, 93 const OriginAttributes& aOriginAttributes, 94 const nsACString& aHost, const nsACString& aName, 95 const nsACString& aPath, bool aFromHttp, 96 const nsID* aOperationID); 97 98 virtual void RemoveCookiesWithOriginAttributes( 99 const OriginAttributesPattern& aPattern, const nsACString& aBaseDomain); 100 101 virtual void RemoveCookiesFromExactHost( 102 const nsACString& aHost, const nsACString& aBaseDomain, 103 const OriginAttributesPattern& aPattern); 104 105 void RemoveAll(); 106 107 void NotifyChanged(nsISupports* aSubject, 108 nsICookieNotification::Action aAction, 109 const nsACString& aBaseDomain, bool aIsThirdParty = false, 110 dom::BrowsingContext* aBrowsingContext = nullptr, 111 bool aOldCookieIsSession = false, 112 const nsID* aOperationID = nullptr); 113 114 void AddCookie(CookieParser* aCookieParser, const nsACString& aBaseDomain, 115 const OriginAttributes& aOriginAttributes, Cookie* aCookie, 116 int64_t aCurrentTimeInUsec, nsIURI* aHostURI, 117 const nsACString& aCookieHeader, bool aFromHttp, 118 bool aIsThirdParty, dom::BrowsingContext* aBrowsingContext, 119 const nsID* aOperationID = nullptr); 120 121 uint32_t RemoveOldestCookies(CookieEntry* aEntry, bool aSecure, 122 uint32_t aBytesToRemove, 123 nsCOMPtr<nsIArray>& aPurgedList); 124 125 void RemoveOlderCookiesByBytes(CookieEntry* aEntry, uint32_t removeBytes, 126 nsCOMPtr<nsIArray>& aPurgedList); 127 128 // tracks how far over the hard and soft CHIPS limits 129 // we use the hard and soft limit to prevent excessive purging. 130 // the soft limit (aka quota) is derived directly from partitionLimitCapacity 131 // pref while the hard limit is the softLimit * a factor 132 // (kChipsHardLimitFactor). the hard limit is used to trigger purging and when 133 // we do purge, we purge down to the soft limit (quota) 134 struct ChipsLimitExcess { 135 uint32_t hard; 136 uint32_t soft; // aka quota 137 }; 138 139 ChipsLimitExcess PartitionLimitExceededBytes(Cookie* aCookie, 140 const nsACString& aBaseDomain); 141 142 static void CreateOrUpdatePurgeList(nsCOMPtr<nsIArray>& aPurgedList, 143 nsICookie* aCookie); 144 145 virtual void StaleCookies(const nsTArray<RefPtr<Cookie>>& aCookieList, 146 int64_t aCurrentTimeInUsec) = 0; 147 148 virtual void Close() = 0; 149 150 virtual void EnsureInitialized() = 0; 151 152 virtual nsresult RunInTransaction( 153 nsICookieTransactionCallback* aCallback) = 0; 154 155 protected: 156 // stores the CookieEntry entryclass and an index into the cookie array within 157 // that entryclass, for purposes of storing an iteration state that points to 158 // a certain cookie. 159 struct MOZ_STACK_CLASS CookieListIter { 160 // default (non-initializing) constructor. 161 CookieListIter() = default; 162 163 // explicit constructor to a given iterator state with entryclass 'aEntry' 164 // and index 'aIndex'. 165 explicit CookieListIter(CookieEntry* aEntry, CookieEntry::IndexType aIndex) 166 : entry(aEntry), index(aIndex) {} 167 168 // get the Cookie * the iterator currently points to. 169 mozilla::net::Cookie* Cookie() const { return entry->GetCookies()[index]; } 170 171 CookieEntry* entry; 172 CookieEntry::IndexType index; 173 }; 174 175 // comparator class for lastaccessed times of cookies. 176 class CompareCookiesByAge; 177 178 // Cookie comparator for the priority queue used in FindStaleCookies. 179 // Note that the expired cookie has the highest priority. 180 // Other non-expired cookies are sorted by their age. 181 class CookieIterComparator; 182 183 // comparator class for sorting cookies by entry and index. 184 class CompareCookiesByIndex; 185 186 CookieStorage() = default; 187 virtual ~CookieStorage() = default; 188 189 void Init(); 190 191 bool FindCookie(const nsACString& aBaseDomain, 192 const OriginAttributes& aOriginAttributes, 193 const nsACString& aHost, const nsACString& aName, 194 const nsACString& aPath, CookieListIter& aIter); 195 196 void AddCookieToList(const nsACString& aBaseDomain, 197 const OriginAttributes& aOriginAttributes, 198 Cookie* aCookie); 199 200 virtual void StoreCookie(const nsACString& aBaseDomain, 201 const OriginAttributes& aOriginAttributes, 202 Cookie* aCookie) = 0; 203 204 virtual const char* NotificationTopic() const = 0; 205 206 virtual void NotifyChangedInternal(nsICookieNotification* aSubject, 207 bool aOldCookieIsSession) = 0; 208 209 virtual void RemoveAllInternal() = 0; 210 211 // This method calls RemoveCookieFromDB + RemoveCookieFromListInternal. 212 void RemoveCookieFromList(const CookieListIter& aIter); 213 214 void RemoveCookieFromListInternal(const CookieListIter& aIter); 215 216 virtual void RemoveCookieFromDB(const Cookie& aCookie) = 0; 217 218 already_AddRefed<nsIArray> PurgeCookiesWithCallbacks( 219 int64_t aCurrentTimeInUsec, uint16_t aMaxNumberOfCookies, 220 int64_t aCookiePurgeAge, 221 std::function<void(const CookieListIter&)>&& aRemoveCookieCallback, 222 std::function<void()>&& aFinalizeCallback); 223 224 nsTHashtable<CookieEntry> mHostTable; 225 226 uint32_t mCookieCount{0}; 227 228 private: 229 void PrefChanged(nsIPrefBranch* aPrefBranch); 230 231 bool FindSecureCookie(const nsACString& aBaseDomain, 232 const OriginAttributes& aOriginAttributes, 233 Cookie* aCookie); 234 235 static void FindStaleCookies(CookieEntry* aEntry, int64_t aCurrentTimeInMSec, 236 bool aIsSecure, 237 nsTArray<CookieListIter>& aOutput, 238 uint32_t aLimit); 239 240 void UpdateCookieOldestTime(Cookie* aCookie); 241 242 void MergeCookieSchemeMap(Cookie* aOldCookie, Cookie* aNewCookie); 243 244 static already_AddRefed<nsIArray> CreatePurgeList(nsICookie* aCookie); 245 246 virtual already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec, 247 uint16_t aMaxNumberOfCookies, 248 int64_t aCookiePurgeAge) = 0; 249 250 void RemoveCookiesFromBack(nsTArray<CookieListIter>& aCookieIters, 251 nsCOMPtr<nsIArray>& aPurgedList); 252 253 // Serialize aBaseDomain e.g. apply "zero abbreveation" (::), use single 254 // zeros and remove brackets to match principal base domain representation. 255 static bool SerializeIPv6BaseDomain(nsACString& aBaseDomain); 256 257 virtual void CollectCookieJarSizeData() = 0; 258 259 int64_t mCookieOldestTime{INT64_MAX}; 260 261 uint16_t mMaxNumberOfCookies{kMaxNumberOfCookies}; 262 uint16_t mMaxCookiesPerHost{kMaxCookiesPerHost}; 263 uint16_t mCookieQuotaPerHost{kCookieQuotaPerHost}; 264 int64_t mCookiePurgeAge{kCookiePurgeAge}; 265 }; 266 267 } // namespace net 268 } // namespace mozilla 269 270 #endif // mozilla_net_CookieStorage_h