nsCookieService.h 15 KB

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