netwerk/cookie/nsCookieService.h

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
parent 0
6474c204b198
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef nsCookieService_h__
michael@0 7 #define nsCookieService_h__
michael@0 8
michael@0 9 #include "nsICookieService.h"
michael@0 10 #include "nsICookieManager.h"
michael@0 11 #include "nsICookieManager2.h"
michael@0 12 #include "nsIObserver.h"
michael@0 13 #include "nsWeakReference.h"
michael@0 14
michael@0 15 #include "nsCookie.h"
michael@0 16 #include "nsString.h"
michael@0 17 #include "nsAutoPtr.h"
michael@0 18 #include "nsHashKeys.h"
michael@0 19 #include "nsIMemoryReporter.h"
michael@0 20 #include "nsTHashtable.h"
michael@0 21 #include "mozIStorageStatement.h"
michael@0 22 #include "mozIStorageAsyncStatement.h"
michael@0 23 #include "mozIStoragePendingStatement.h"
michael@0 24 #include "mozIStorageConnection.h"
michael@0 25 #include "mozIStorageRow.h"
michael@0 26 #include "mozIStorageCompletionCallback.h"
michael@0 27 #include "mozIStorageStatementCallback.h"
michael@0 28
michael@0 29 #include "mozilla/MemoryReporting.h"
michael@0 30
michael@0 31 class nsICookiePermission;
michael@0 32 class nsIEffectiveTLDService;
michael@0 33 class nsIIDNService;
michael@0 34 class nsIPrefBranch;
michael@0 35 class nsIObserverService;
michael@0 36 class nsIURI;
michael@0 37 class nsIChannel;
michael@0 38 class nsIArray;
michael@0 39 class mozIStorageService;
michael@0 40 class mozIThirdPartyUtil;
michael@0 41 class ReadCookieDBListener;
michael@0 42
michael@0 43 struct nsCookieAttributes;
michael@0 44 struct nsListIter;
michael@0 45 struct nsEnumerationData;
michael@0 46
michael@0 47 namespace mozilla {
michael@0 48 namespace net {
michael@0 49 class CookieServiceParent;
michael@0 50 }
michael@0 51 }
michael@0 52
michael@0 53 // hash key class
michael@0 54 class nsCookieKey : public PLDHashEntryHdr
michael@0 55 {
michael@0 56 public:
michael@0 57 typedef const nsCookieKey& KeyType;
michael@0 58 typedef const nsCookieKey* KeyTypePointer;
michael@0 59
michael@0 60 nsCookieKey()
michael@0 61 {}
michael@0 62
michael@0 63 nsCookieKey(const nsCString &baseDomain, uint32_t appId, bool inBrowser)
michael@0 64 : mBaseDomain(baseDomain)
michael@0 65 , mAppId(appId)
michael@0 66 , mInBrowserElement(inBrowser)
michael@0 67 {}
michael@0 68
michael@0 69 nsCookieKey(KeyTypePointer other)
michael@0 70 : mBaseDomain(other->mBaseDomain)
michael@0 71 , mAppId(other->mAppId)
michael@0 72 , mInBrowserElement(other->mInBrowserElement)
michael@0 73 {}
michael@0 74
michael@0 75 nsCookieKey(KeyType other)
michael@0 76 : mBaseDomain(other.mBaseDomain)
michael@0 77 , mAppId(other.mAppId)
michael@0 78 , mInBrowserElement(other.mInBrowserElement)
michael@0 79 {}
michael@0 80
michael@0 81 ~nsCookieKey()
michael@0 82 {}
michael@0 83
michael@0 84 bool KeyEquals(KeyTypePointer other) const
michael@0 85 {
michael@0 86 return mBaseDomain == other->mBaseDomain &&
michael@0 87 mAppId == other->mAppId &&
michael@0 88 mInBrowserElement == other->mInBrowserElement;
michael@0 89 }
michael@0 90
michael@0 91 static KeyTypePointer KeyToPointer(KeyType aKey)
michael@0 92 {
michael@0 93 return &aKey;
michael@0 94 }
michael@0 95
michael@0 96 static PLDHashNumber HashKey(KeyTypePointer aKey)
michael@0 97 {
michael@0 98 // TODO: more efficient way to generate hash?
michael@0 99 nsAutoCString temp(aKey->mBaseDomain);
michael@0 100 temp.Append("#");
michael@0 101 temp.Append(aKey->mAppId);
michael@0 102 temp.Append("#");
michael@0 103 temp.Append(aKey->mInBrowserElement ? 1 : 0);
michael@0 104 return mozilla::HashString(temp);
michael@0 105 }
michael@0 106
michael@0 107 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
michael@0 108
michael@0 109 enum { ALLOW_MEMMOVE = true };
michael@0 110
michael@0 111 nsCString mBaseDomain;
michael@0 112 uint32_t mAppId;
michael@0 113 bool mInBrowserElement;
michael@0 114 };
michael@0 115
michael@0 116 // Inherit from nsCookieKey so this can be stored in nsTHashTable
michael@0 117 // TODO: why aren't we using nsClassHashTable<nsCookieKey, ArrayType>?
michael@0 118 class nsCookieEntry : public nsCookieKey
michael@0 119 {
michael@0 120 public:
michael@0 121 // Hash methods
michael@0 122 typedef nsTArray< nsRefPtr<nsCookie> > ArrayType;
michael@0 123 typedef ArrayType::index_type IndexType;
michael@0 124
michael@0 125 nsCookieEntry(KeyTypePointer aKey)
michael@0 126 : nsCookieKey(aKey)
michael@0 127 {}
michael@0 128
michael@0 129 nsCookieEntry(const nsCookieEntry& toCopy)
michael@0 130 {
michael@0 131 // if we end up here, things will break. nsTHashtable shouldn't
michael@0 132 // allow this, since we set ALLOW_MEMMOVE to true.
michael@0 133 NS_NOTREACHED("nsCookieEntry copy constructor is forbidden!");
michael@0 134 }
michael@0 135
michael@0 136 ~nsCookieEntry()
michael@0 137 {}
michael@0 138
michael@0 139 inline ArrayType& GetCookies() { return mCookies; }
michael@0 140
michael@0 141 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
michael@0 142
michael@0 143 private:
michael@0 144 ArrayType mCookies;
michael@0 145 };
michael@0 146
michael@0 147 // encapsulates a (key, nsCookie) tuple for temporary storage purposes.
michael@0 148 struct CookieDomainTuple
michael@0 149 {
michael@0 150 nsCookieKey key;
michael@0 151 nsRefPtr<nsCookie> cookie;
michael@0 152
michael@0 153 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
michael@0 154 };
michael@0 155
michael@0 156 // encapsulates in-memory and on-disk DB states, so we can
michael@0 157 // conveniently switch state when entering or exiting private browsing.
michael@0 158 struct DBState MOZ_FINAL
michael@0 159 {
michael@0 160 DBState() : cookieCount(0), cookieOldestTime(INT64_MAX), corruptFlag(OK)
michael@0 161 {
michael@0 162 }
michael@0 163
michael@0 164 private:
michael@0 165 // Private destructor, to discourage deletion outside of Release():
michael@0 166 ~DBState()
michael@0 167 {
michael@0 168 }
michael@0 169
michael@0 170 public:
michael@0 171 NS_INLINE_DECL_REFCOUNTING(DBState)
michael@0 172
michael@0 173 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
michael@0 174
michael@0 175 // State of the database connection.
michael@0 176 enum CorruptFlag {
michael@0 177 OK, // normal
michael@0 178 CLOSING_FOR_REBUILD, // corruption detected, connection closing
michael@0 179 REBUILDING // close complete, rebuilding database from memory
michael@0 180 };
michael@0 181
michael@0 182 nsTHashtable<nsCookieEntry> hostTable;
michael@0 183 uint32_t cookieCount;
michael@0 184 int64_t cookieOldestTime;
michael@0 185 nsCOMPtr<nsIFile> cookieFile;
michael@0 186 nsCOMPtr<mozIStorageConnection> dbConn;
michael@0 187 nsCOMPtr<mozIStorageAsyncStatement> stmtInsert;
michael@0 188 nsCOMPtr<mozIStorageAsyncStatement> stmtDelete;
michael@0 189 nsCOMPtr<mozIStorageAsyncStatement> stmtUpdate;
michael@0 190 CorruptFlag corruptFlag;
michael@0 191
michael@0 192 // Various parts representing asynchronous read state. These are useful
michael@0 193 // while the background read is taking place.
michael@0 194 nsCOMPtr<mozIStorageConnection> syncConn;
michael@0 195 nsCOMPtr<mozIStorageStatement> stmtReadDomain;
michael@0 196 nsCOMPtr<mozIStoragePendingStatement> pendingRead;
michael@0 197 // The asynchronous read listener. This is a weak ref (storage has ownership)
michael@0 198 // since it may need to outlive the DBState's database connection.
michael@0 199 ReadCookieDBListener* readListener;
michael@0 200 // An array of (baseDomain, cookie) tuples representing data read in
michael@0 201 // asynchronously. This is merged into hostTable once read is complete.
michael@0 202 nsTArray<CookieDomainTuple> hostArray;
michael@0 203 // A hashset of baseDomains read in synchronously, while the async read is
michael@0 204 // in flight. This is used to keep track of which data in hostArray is stale
michael@0 205 // when the time comes to merge.
michael@0 206 nsTHashtable<nsCookieKey> readSet;
michael@0 207
michael@0 208 // DB completion handlers.
michael@0 209 nsCOMPtr<mozIStorageStatementCallback> insertListener;
michael@0 210 nsCOMPtr<mozIStorageStatementCallback> updateListener;
michael@0 211 nsCOMPtr<mozIStorageStatementCallback> removeListener;
michael@0 212 nsCOMPtr<mozIStorageCompletionCallback> closeListener;
michael@0 213 };
michael@0 214
michael@0 215 // these constants represent a decision about a cookie based on user prefs.
michael@0 216 enum CookieStatus
michael@0 217 {
michael@0 218 STATUS_ACCEPTED,
michael@0 219 STATUS_ACCEPT_SESSION,
michael@0 220 STATUS_REJECTED,
michael@0 221 // STATUS_REJECTED_WITH_ERROR indicates the cookie should be rejected because
michael@0 222 // of an error (rather than something the user can control). this is used for
michael@0 223 // notification purposes, since we only want to notify of rejections where
michael@0 224 // the user can do something about it (e.g. whitelist the site).
michael@0 225 STATUS_REJECTED_WITH_ERROR
michael@0 226 };
michael@0 227
michael@0 228 // Result codes for TryInitDB() and Read().
michael@0 229 enum OpenDBResult
michael@0 230 {
michael@0 231 RESULT_OK,
michael@0 232 RESULT_RETRY,
michael@0 233 RESULT_FAILURE
michael@0 234 };
michael@0 235
michael@0 236 /******************************************************************************
michael@0 237 * nsCookieService:
michael@0 238 * class declaration
michael@0 239 ******************************************************************************/
michael@0 240
michael@0 241 class nsCookieService : public nsICookieService
michael@0 242 , public nsICookieManager2
michael@0 243 , public nsIObserver
michael@0 244 , public nsSupportsWeakReference
michael@0 245 , public nsIMemoryReporter
michael@0 246 {
michael@0 247 private:
michael@0 248 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
michael@0 249
michael@0 250 public:
michael@0 251 NS_DECL_ISUPPORTS
michael@0 252 NS_DECL_NSIOBSERVER
michael@0 253 NS_DECL_NSICOOKIESERVICE
michael@0 254 NS_DECL_NSICOOKIEMANAGER
michael@0 255 NS_DECL_NSICOOKIEMANAGER2
michael@0 256 NS_DECL_NSIMEMORYREPORTER
michael@0 257
michael@0 258 nsCookieService();
michael@0 259 virtual ~nsCookieService();
michael@0 260 static nsICookieService* GetXPCOMSingleton();
michael@0 261 nsresult Init();
michael@0 262
michael@0 263 /**
michael@0 264 * Start watching the observer service for messages indicating that an app has
michael@0 265 * been uninstalled. When an app is uninstalled, we get the cookie service
michael@0 266 * (thus instantiating it, if necessary) and clear all the cookies for that
michael@0 267 * app.
michael@0 268 */
michael@0 269 static void AppClearDataObserverInit();
michael@0 270
michael@0 271 protected:
michael@0 272 void PrefChanged(nsIPrefBranch *aPrefBranch);
michael@0 273 void InitDBStates();
michael@0 274 OpenDBResult TryInitDB(bool aDeleteExistingDB);
michael@0 275 nsresult CreateTable();
michael@0 276 void CloseDBStates();
michael@0 277 void CleanupCachedStatements();
michael@0 278 void CleanupDefaultDBConnection();
michael@0 279 void HandleDBClosed(DBState* aDBState);
michael@0 280 void HandleCorruptDB(DBState* aDBState);
michael@0 281 void RebuildCorruptDB(DBState* aDBState);
michael@0 282 OpenDBResult Read();
michael@0 283 template<class T> nsCookie* GetCookieFromRow(T &aRow);
michael@0 284 void AsyncReadComplete();
michael@0 285 void CancelAsyncRead(bool aPurgeReadSet);
michael@0 286 void EnsureReadDomain(const nsCookieKey &aKey);
michael@0 287 void EnsureReadComplete();
michael@0 288 nsresult NormalizeHost(nsCString &aHost);
michael@0 289 nsresult GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
michael@0 290 nsresult GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
michael@0 291 nsresult GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
michael@4 292 void GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, uint32_t aAppId, bool aInBrowserElement, bool aIsPrivate, nsCString &aOrigin, nsCString &aCookie);
michael@0 293 nsresult SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
michael@0 294 void SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, uint32_t aAppId, bool aInBrowserElement, bool aIsPrivate, nsIChannel* aChannel);
michael@4 295 bool SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, const nsCString &aOrigin, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel);
michael@0 296 void AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
michael@0 297 void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = nullptr);
michael@0 298 void AddCookieToList(const nsCookieKey& aKey, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true);
michael@0 299 void UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
michael@0 300 static bool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound);
michael@0 301 static bool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
michael@0 302 bool RequireThirdPartyCheck();
michael@0 303 CookieStatus CheckPrefs(nsIURI *aHostURI, bool aIsForeign, bool aRequireHostMatch, const char *aCookieHeader);
michael@0 304 bool CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, bool aRequireHostMatch);
michael@0 305 static bool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
michael@0 306 static bool GetExpiry(nsCookieAttributes &aCookie, int64_t aServerTime, int64_t aCurrentTime);
michael@0 307 void RemoveAllFromMemory();
michael@0 308 already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec);
michael@4 309 bool FindCookie(const nsCookieKey& aKey, const nsAFlatCString &aOrigin, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
michael@0 310 static void FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsListIter &aIter);
michael@0 311 void NotifyRejected(nsIURI *aHostURI);
michael@0 312 void NotifyThirdParty(nsIURI *aHostURI, bool aAccepted, nsIChannel *aChannel);
michael@0 313 void NotifyChanged(nsISupports *aSubject, const char16_t *aData);
michael@0 314 void NotifyPurged(nsICookie2* aCookie);
michael@0 315 already_AddRefed<nsIArray> CreatePurgeList(nsICookie2* aCookie);
michael@0 316
michael@0 317 /**
michael@0 318 * This method is used to iterate the cookie hash table and select the ones
michael@0 319 * that are part of a specific app.
michael@0 320 */
michael@0 321 static PLDHashOperator GetCookiesForApp(nsCookieEntry* entry, void* arg);
michael@0 322
michael@0 323 /**
michael@0 324 * This method is a helper that allows calling nsICookieManager::Remove()
michael@0 325 * with appId/inBrowserElement parameters.
michael@0 326 * NOTE: this could be added to a public interface if we happen to need it.
michael@0 327 */
michael@0 328 nsresult Remove(const nsACString& aHost, uint32_t aAppId,
michael@0 329 bool aInBrowserElement, const nsACString& aName,
michael@0 330 const nsACString& aPath, bool aBlocked);
michael@0 331
michael@0 332 protected:
michael@0 333 // cached members.
michael@0 334 nsCOMPtr<nsIObserverService> mObserverService;
michael@0 335 nsCOMPtr<nsICookiePermission> mPermissionService;
michael@0 336 nsCOMPtr<mozIThirdPartyUtil> mThirdPartyUtil;
michael@0 337 nsCOMPtr<nsIEffectiveTLDService> mTLDService;
michael@0 338 nsCOMPtr<nsIIDNService> mIDNService;
michael@0 339 nsCOMPtr<mozIStorageService> mStorageService;
michael@0 340
michael@0 341 // we have two separate DB states: one for normal browsing and one for
michael@0 342 // private browsing, switching between them on a per-cookie-request basis.
michael@0 343 // this state encapsulates both the in-memory table and the on-disk DB.
michael@0 344 // note that the private states' dbConn should always be null - we never
michael@0 345 // want to be dealing with the on-disk DB when in private browsing.
michael@0 346 DBState *mDBState;
michael@0 347 nsRefPtr<DBState> mDefaultDBState;
michael@0 348 nsRefPtr<DBState> mPrivateDBState;
michael@0 349
michael@0 350 // cached prefs
michael@0 351 uint8_t mCookieBehavior; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT, LIMITFOREIGN}
michael@0 352 bool mThirdPartySession;
michael@0 353 uint16_t mMaxNumberOfCookies;
michael@0 354 uint16_t mMaxCookiesPerHost;
michael@0 355 int64_t mCookiePurgeAge;
michael@0 356
michael@0 357 // friends!
michael@0 358 friend PLDHashOperator purgeCookiesCallback(nsCookieEntry *aEntry, void *aArg);
michael@0 359 friend class DBListenerErrorHandler;
michael@0 360 friend class ReadCookieDBListener;
michael@0 361 friend class CloseCookieDBListener;
michael@0 362
michael@0 363 static nsCookieService* GetSingleton();
michael@0 364 friend class mozilla::net::CookieServiceParent;
michael@0 365 };
michael@0 366
michael@0 367 #endif // nsCookieService_h__

mercurial