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.

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

mercurial