LCOV - code coverage report
Current view: top level - netwerk/cookie - nsCookieService.h (source / functions) Hit Total Coverage
Test: output.info Lines: 22 38 57.9 %
Date: 2017-07-14 16:53:18 Functions: 8 17 47.1 %
Legend: Lines: hit not hit

          Line data    Source code
       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 nsCookieService_h__
       7             : #define nsCookieService_h__
       8             : 
       9             : #include "nsICookieService.h"
      10             : #include "nsICookieManager.h"
      11             : #include "nsICookieManager2.h"
      12             : #include "nsIObserver.h"
      13             : #include "nsWeakReference.h"
      14             : 
      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"
      28             : #include "mozIStorageFunction.h"
      29             : #include "nsIVariant.h"
      30             : #include "nsIFile.h"
      31             : #include "mozilla/BasePrincipal.h"
      32             : #include "mozilla/MemoryReporting.h"
      33             : #include "mozilla/Maybe.h"
      34             : 
      35             : using mozilla::OriginAttributes;
      36             : 
      37             : class nsICookiePermission;
      38             : class nsIEffectiveTLDService;
      39             : class nsIIDNService;
      40             : class nsIPrefBranch;
      41             : class nsIObserverService;
      42             : class nsIURI;
      43             : class nsIChannel;
      44             : class nsIArray;
      45             : class mozIStorageService;
      46             : class mozIThirdPartyUtil;
      47             : class ReadCookieDBListener;
      48             : 
      49             : struct nsCookieAttributes;
      50             : struct nsListIter;
      51             : 
      52             : namespace mozilla {
      53             : namespace net {
      54             : class CookieServiceParent;
      55             : } // namespace net
      56             : } // namespace mozilla
      57             : 
      58             : // hash key class
      59           0 : class nsCookieKey : public PLDHashEntryHdr
      60             : {
      61             : public:
      62             :   typedef const nsCookieKey& KeyType;
      63             :   typedef const nsCookieKey* KeyTypePointer;
      64             : 
      65           0 :   nsCookieKey()
      66           0 :   {}
      67             : 
      68           6 :   nsCookieKey(const nsCString &baseDomain, const OriginAttributes &attrs)
      69           6 :     : mBaseDomain(baseDomain)
      70           6 :     , mOriginAttributes(attrs)
      71           6 :   {}
      72             : 
      73           1 :   explicit nsCookieKey(KeyTypePointer other)
      74           1 :     : mBaseDomain(other->mBaseDomain)
      75           1 :     , mOriginAttributes(other->mOriginAttributes)
      76           1 :   {}
      77             : 
      78             :   nsCookieKey(KeyType other)
      79             :     : mBaseDomain(other.mBaseDomain)
      80             :     , mOriginAttributes(other.mOriginAttributes)
      81             :   {}
      82             : 
      83           7 :   ~nsCookieKey()
      84           7 :   {}
      85             : 
      86           0 :   bool KeyEquals(KeyTypePointer other) const
      87             :   {
      88           0 :     return mBaseDomain == other->mBaseDomain &&
      89           0 :            mOriginAttributes == other->mOriginAttributes;
      90             :   }
      91             : 
      92           8 :   static KeyTypePointer KeyToPointer(KeyType aKey)
      93             :   {
      94           8 :     return &aKey;
      95             :   }
      96             : 
      97           1 :   static PLDHashNumber HashKey(KeyTypePointer aKey)
      98             :   {
      99             :     // TODO: more efficient way to generate hash?
     100           2 :     nsAutoCString temp(aKey->mBaseDomain);
     101           1 :     temp.Append('#');
     102           2 :     nsAutoCString suffix;
     103           1 :     aKey->mOriginAttributes.CreateSuffix(suffix);
     104           1 :     temp.Append(suffix);
     105           2 :     return mozilla::HashString(temp);
     106             :   }
     107             : 
     108             :   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     109             : 
     110             :   enum { ALLOW_MEMMOVE = true };
     111             : 
     112             :   nsCString        mBaseDomain;
     113             :   OriginAttributes mOriginAttributes;
     114             : };
     115             : 
     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< RefPtr<nsCookie> > ArrayType;
     123             :     typedef ArrayType::index_type IndexType;
     124             : 
     125           0 :     explicit nsCookieEntry(KeyTypePointer aKey)
     126           0 :      : nsCookieKey(aKey)
     127           0 :     {}
     128             : 
     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             :     }
     135             : 
     136           0 :     ~nsCookieEntry()
     137           0 :     {}
     138             : 
     139           0 :     inline ArrayType& GetCookies() { return mCookies; }
     140             : 
     141             :     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     142             : 
     143             :   private:
     144             :     ArrayType mCookies;
     145             : };
     146             : 
     147             : // encapsulates a (key, nsCookie) tuple for temporary storage purposes.
     148           0 : struct CookieDomainTuple
     149             : {
     150             :   nsCookieKey key;
     151             :   RefPtr<nsCookie> cookie;
     152             : 
     153             :   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     154             : };
     155             : 
     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 final
     159             : {
     160           2 :   DBState() : cookieCount(0), cookieOldestTime(INT64_MAX), corruptFlag(OK)
     161             :   {
     162           2 :   }
     163             : 
     164             : private:
     165             :   // Private destructor, to discourage deletion outside of Release():
     166           0 :   ~DBState()
     167           0 :   {
     168           0 :   }
     169             : 
     170             : public:
     171           8 :   NS_INLINE_DECL_REFCOUNTING(DBState)
     172             : 
     173             :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     174             : 
     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             :   };
     181             : 
     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;
     191             : 
     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;
     207             : 
     208             :   // DB completion handlers.
     209             :   nsCOMPtr<mozIStorageStatementCallback>  insertListener;
     210             :   nsCOMPtr<mozIStorageStatementCallback>  updateListener;
     211             :   nsCOMPtr<mozIStorageStatementCallback>  removeListener;
     212             :   nsCOMPtr<mozIStorageCompletionCallback> closeListener;
     213             : };
     214             : 
     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             : };
     227             : 
     228             : // Result codes for TryInitDB() and Read().
     229             : enum OpenDBResult
     230             : {
     231             :   RESULT_OK,
     232             :   RESULT_RETRY,
     233             :   RESULT_FAILURE
     234             : };
     235             : 
     236             : /******************************************************************************
     237             :  * nsCookieService:
     238             :  * class declaration
     239             :  ******************************************************************************/
     240             : 
     241             : class nsCookieService final : 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;
     249             : 
     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
     257             : 
     258             :     nsCookieService();
     259             :     static nsICookieService*      GetXPCOMSingleton();
     260             :     nsresult                      Init();
     261             : 
     262             :   /**
     263             :    * Start watching the observer service for messages indicating that an app has
     264             :    * been uninstalled.  When an app is uninstalled, we get the cookie service
     265             :    * (thus instantiating it, if necessary) and clear all the cookies for that
     266             :    * app.
     267             :    */
     268             :   static void AppClearDataObserverInit();
     269             : 
     270             :   protected:
     271             :     virtual ~nsCookieService();
     272             : 
     273             :     void                          PrefChanged(nsIPrefBranch *aPrefBranch);
     274             :     void                          InitDBStates();
     275             :     OpenDBResult                  TryInitDB(bool aDeleteExistingDB);
     276             :     nsresult                      CreateTableWorker(const char* aName);
     277             :     nsresult                      CreateIndex();
     278             :     nsresult                      CreateTable();
     279             :     nsresult                      CreateTableForSchemaVersion6();
     280             :     nsresult                      CreateTableForSchemaVersion5();
     281             :     void                          CloseDBStates();
     282             :     void                          CleanupCachedStatements();
     283             :     void                          CleanupDefaultDBConnection();
     284             :     void                          HandleDBClosed(DBState* aDBState);
     285             :     void                          HandleCorruptDB(DBState* aDBState);
     286             :     void                          RebuildCorruptDB(DBState* aDBState);
     287             :     OpenDBResult                  Read();
     288             :     template<class T> nsCookie*   GetCookieFromRow(T &aRow, const OriginAttributes& aOriginAttributes);
     289             :     void                          AsyncReadComplete();
     290             :     void                          CancelAsyncRead(bool aPurgeReadSet);
     291             :     void                          EnsureReadDomain(const nsCookieKey &aKey);
     292             :     void                          EnsureReadComplete();
     293             :     nsresult                      NormalizeHost(nsCString &aHost);
     294             :     nsresult                      GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
     295             :     nsresult                      GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
     296             :     nsresult                      GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
     297             :     void                          GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, nsCString &aCookie);
     298             :     nsresult                      SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
     299             :     void                          SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, const OriginAttributes &aOriginAttrs, nsIChannel* aChannel);
     300             :     bool                          SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel);
     301             :     void                          AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
     302             :     void                          RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = nullptr);
     303             :     void                          AddCookieToList(const nsCookieKey& aKey, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true);
     304             :     void                          UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
     305             :     static bool                   GetTokenValue(nsACString::const_char_iterator &aIter, nsACString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound);
     306             :     static bool                   ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
     307             :     bool                          RequireThirdPartyCheck();
     308             :     CookieStatus                  CheckPrefs(nsIURI *aHostURI, bool aIsForeign, const char *aCookieHeader);
     309             :     bool                          CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, bool aRequireHostMatch);
     310             :     static bool                   CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
     311             :     static bool                   CheckPrefixes(nsCookieAttributes &aCookie, bool aSecureRequest);
     312             :     static bool                   GetExpiry(nsCookieAttributes &aCookie, int64_t aServerTime, int64_t aCurrentTime);
     313             :     void                          RemoveAllFromMemory();
     314             :     already_AddRefed<nsIArray>    PurgeCookies(int64_t aCurrentTimeInUsec);
     315             :     bool                          FindCookie(const nsCookieKey& aKey, const nsCString& aHost, const nsCString& aName, const nsCString& aPath, nsListIter &aIter);
     316             :     bool                          FindSecureCookie(const nsCookieKey& aKey, nsCookie* aCookie);
     317             :     int64_t                       FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsIURI* aSource, const mozilla::Maybe<bool> &aIsSecure, nsListIter &aIter);
     318             :     void                          TelemetryForEvictingStaleCookie(nsCookie* aEvicted, int64_t oldestCookieTime);
     319             :     void                          NotifyRejected(nsIURI *aHostURI);
     320             :     void                          NotifyThirdParty(nsIURI *aHostURI, bool aAccepted, nsIChannel *aChannel);
     321             :     void                          NotifyChanged(nsISupports *aSubject, const char16_t *aData, bool aOldCookieIsSession = false);
     322             :     void                          NotifyPurged(nsICookie2* aCookie);
     323             :     already_AddRefed<nsIArray>    CreatePurgeList(nsICookie2* aCookie);
     324             :     void                          UpdateCookieOldestTime(DBState* aDBState, nsCookie* aCookie);
     325             : 
     326             :     nsresult                      GetCookiesWithOriginAttributes(const mozilla::OriginAttributesPattern& aPattern, const nsCString& aBaseDomain, nsISimpleEnumerator **aEnumerator);
     327             :     nsresult                      RemoveCookiesWithOriginAttributes(const mozilla::OriginAttributesPattern& aPattern, const nsCString& aBaseDomain);
     328             : 
     329             :     /**
     330             :      * This method is a helper that allows calling nsICookieManager::Remove()
     331             :      * with OriginAttributes parameter.
     332             :      * NOTE: this could be added to a public interface if we happen to need it.
     333             :      */
     334             :     nsresult Remove(const nsACString& aHost, const OriginAttributes& aAttrs,
     335             :                     const nsACString& aName, const nsACString& aPath,
     336             :                     bool aBlocked);
     337             : 
     338             :   protected:
     339             :     // cached members.
     340             :     nsCOMPtr<nsICookiePermission>    mPermissionService;
     341             :     nsCOMPtr<mozIThirdPartyUtil>     mThirdPartyUtil;
     342             :     nsCOMPtr<nsIEffectiveTLDService> mTLDService;
     343             :     nsCOMPtr<nsIIDNService>          mIDNService;
     344             :     nsCOMPtr<mozIStorageService>     mStorageService;
     345             : 
     346             :     // we have two separate DB states: one for normal browsing and one for
     347             :     // private browsing, switching between them on a per-cookie-request basis.
     348             :     // this state encapsulates both the in-memory table and the on-disk DB.
     349             :     // note that the private states' dbConn should always be null - we never
     350             :     // want to be dealing with the on-disk DB when in private browsing.
     351             :     DBState                      *mDBState;
     352             :     RefPtr<DBState>             mDefaultDBState;
     353             :     RefPtr<DBState>             mPrivateDBState;
     354             : 
     355             :     // cached prefs
     356             :     uint8_t                       mCookieBehavior; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT, LIMITFOREIGN}
     357             :     bool                          mThirdPartySession;
     358             :     bool                          mLeaveSecureAlone;
     359             :     uint16_t                      mMaxNumberOfCookies;
     360             :     uint16_t                      mMaxCookiesPerHost;
     361             :     int64_t                       mCookiePurgeAge;
     362             : 
     363             :     // friends!
     364             :     friend class DBListenerErrorHandler;
     365             :     friend class ReadCookieDBListener;
     366             :     friend class CloseCookieDBListener;
     367             : 
     368             :     static nsCookieService*       GetSingleton();
     369             :     friend class mozilla::net::CookieServiceParent;
     370             : };
     371             : 
     372             : #endif // nsCookieService_h__

Generated by: LCOV version 1.13