Bug 846687 - Set the transport as non-seekable if the server sends Accept-Ranges...
[gecko.git] / netwerk / cookie / nsCookieService.h
blob3200c27fdb40df9a36ae1c2c5f6120d13caac03c
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 "nsTHashtable.h"
20 #include "mozIStorageStatement.h"
21 #include "mozIStorageAsyncStatement.h"
22 #include "mozIStoragePendingStatement.h"
23 #include "mozIStorageConnection.h"
24 #include "mozIStorageRow.h"
25 #include "mozIStorageCompletionCallback.h"
26 #include "mozIStorageStatementCallback.h"
28 class nsICookiePermission;
29 class nsIEffectiveTLDService;
30 class nsIIDNService;
31 class nsIPrefBranch;
32 class nsIObserverService;
33 class nsIURI;
34 class nsIChannel;
35 class nsIArray;
36 class mozIStorageService;
37 class mozIThirdPartyUtil;
38 class ReadCookieDBListener;
40 struct nsCookieAttributes;
41 struct nsListIter;
42 struct nsEnumerationData;
44 namespace mozilla {
45 namespace net {
46 class CookieServiceParent;
50 // hash key class
51 class nsCookieKey : public PLDHashEntryHdr
53 public:
54 typedef const nsCookieKey& KeyType;
55 typedef const nsCookieKey* KeyTypePointer;
57 nsCookieKey()
60 nsCookieKey(const nsCString &baseDomain, uint32_t appId, bool inBrowser)
61 : mBaseDomain(baseDomain)
62 , mAppId(appId)
63 , mInBrowserElement(inBrowser)
66 nsCookieKey(const KeyTypePointer other)
67 : mBaseDomain(other->mBaseDomain)
68 , mAppId(other->mAppId)
69 , mInBrowserElement(other->mInBrowserElement)
72 nsCookieKey(const KeyType other)
73 : mBaseDomain(other.mBaseDomain)
74 , mAppId(other.mAppId)
75 , mInBrowserElement(other.mInBrowserElement)
78 ~nsCookieKey()
81 bool KeyEquals(KeyTypePointer other) const
83 return mBaseDomain == other->mBaseDomain &&
84 mAppId == other->mAppId &&
85 mInBrowserElement == other->mInBrowserElement;
88 static KeyTypePointer KeyToPointer(KeyType aKey)
90 return &aKey;
93 static PLDHashNumber HashKey(KeyTypePointer aKey)
95 // TODO: more efficient way to generate hash?
96 nsAutoCString temp(aKey->mBaseDomain);
97 temp.Append("#");
98 temp.Append(aKey->mAppId);
99 temp.Append("#");
100 temp.Append(aKey->mInBrowserElement ? 1 : 0);
101 return mozilla::HashString(temp);
104 enum { ALLOW_MEMMOVE = true };
106 nsCString mBaseDomain;
107 uint32_t mAppId;
108 bool mInBrowserElement;
111 // Inherit from nsCookieKey so this can be stored in nsTHashTable
112 // TODO: why aren't we using nsClassHashTable<nsCookieKey, ArrayType>?
113 class nsCookieEntry : public nsCookieKey
115 public:
116 // Hash methods
117 typedef nsTArray< nsRefPtr<nsCookie> > ArrayType;
118 typedef ArrayType::index_type IndexType;
120 nsCookieEntry(KeyTypePointer aKey)
121 : nsCookieKey(aKey)
124 nsCookieEntry(const nsCookieEntry& toCopy)
126 // if we end up here, things will break. nsTHashtable shouldn't
127 // allow this, since we set ALLOW_MEMMOVE to true.
128 NS_NOTREACHED("nsCookieEntry copy constructor is forbidden!");
131 ~nsCookieEntry()
134 inline ArrayType& GetCookies() { return mCookies; }
136 private:
137 ArrayType mCookies;
140 // encapsulates a (key, nsCookie) tuple for temporary storage purposes.
141 struct CookieDomainTuple
143 nsCookieKey key;
144 nsRefPtr<nsCookie> cookie;
147 // encapsulates in-memory and on-disk DB states, so we can
148 // conveniently switch state when entering or exiting private browsing.
149 struct DBState
151 DBState() : cookieCount(0), cookieOldestTime(INT64_MAX), corruptFlag(OK)
153 hostTable.Init();
156 NS_INLINE_DECL_REFCOUNTING(DBState)
158 // State of the database connection.
159 enum CorruptFlag {
160 OK, // normal
161 CLOSING_FOR_REBUILD, // corruption detected, connection closing
162 REBUILDING // close complete, rebuilding database from memory
165 nsTHashtable<nsCookieEntry> hostTable;
166 uint32_t cookieCount;
167 int64_t cookieOldestTime;
168 nsCOMPtr<nsIFile> cookieFile;
169 nsCOMPtr<mozIStorageConnection> dbConn;
170 nsCOMPtr<mozIStorageAsyncStatement> stmtInsert;
171 nsCOMPtr<mozIStorageAsyncStatement> stmtDelete;
172 nsCOMPtr<mozIStorageAsyncStatement> stmtUpdate;
173 CorruptFlag corruptFlag;
175 // Various parts representing asynchronous read state. These are useful
176 // while the background read is taking place.
177 nsCOMPtr<mozIStorageConnection> syncConn;
178 nsCOMPtr<mozIStorageStatement> stmtReadDomain;
179 nsCOMPtr<mozIStoragePendingStatement> pendingRead;
180 // The asynchronous read listener. This is a weak ref (storage has ownership)
181 // since it may need to outlive the DBState's database connection.
182 ReadCookieDBListener* readListener;
183 // An array of (baseDomain, cookie) tuples representing data read in
184 // asynchronously. This is merged into hostTable once read is complete.
185 nsTArray<CookieDomainTuple> hostArray;
186 // A hashset of baseDomains read in synchronously, while the async read is
187 // in flight. This is used to keep track of which data in hostArray is stale
188 // when the time comes to merge.
189 nsTHashtable<nsCookieKey> readSet;
191 // DB completion handlers.
192 nsCOMPtr<mozIStorageStatementCallback> insertListener;
193 nsCOMPtr<mozIStorageStatementCallback> updateListener;
194 nsCOMPtr<mozIStorageStatementCallback> removeListener;
195 nsCOMPtr<mozIStorageCompletionCallback> closeListener;
198 // these constants represent a decision about a cookie based on user prefs.
199 enum CookieStatus
201 STATUS_ACCEPTED,
202 STATUS_ACCEPT_SESSION,
203 STATUS_REJECTED,
204 // STATUS_REJECTED_WITH_ERROR indicates the cookie should be rejected because
205 // of an error (rather than something the user can control). this is used for
206 // notification purposes, since we only want to notify of rejections where
207 // the user can do something about it (e.g. whitelist the site).
208 STATUS_REJECTED_WITH_ERROR
211 // Result codes for TryInitDB() and Read().
212 enum OpenDBResult
214 RESULT_OK,
215 RESULT_RETRY,
216 RESULT_FAILURE
219 /******************************************************************************
220 * nsCookieService:
221 * class declaration
222 ******************************************************************************/
224 class nsCookieService : public nsICookieService
225 , public nsICookieManager2
226 , public nsIObserver
227 , public nsSupportsWeakReference
229 public:
230 // nsISupports
231 NS_DECL_ISUPPORTS
232 NS_DECL_NSIOBSERVER
233 NS_DECL_NSICOOKIESERVICE
234 NS_DECL_NSICOOKIEMANAGER
235 NS_DECL_NSICOOKIEMANAGER2
237 nsCookieService();
238 virtual ~nsCookieService();
239 static nsICookieService* GetXPCOMSingleton();
240 nsresult Init();
243 * Start watching the observer service for messages indicating that an app has
244 * been uninstalled. When an app is uninstalled, we get the cookie service
245 * (thus instantiating it, if necessary) and clear all the cookies for that
246 * app.
248 static void AppClearDataObserverInit();
250 protected:
251 void PrefChanged(nsIPrefBranch *aPrefBranch);
252 void InitDBStates();
253 OpenDBResult TryInitDB(bool aDeleteExistingDB);
254 nsresult CreateTable();
255 void CloseDBStates();
256 void CloseDefaultDBConnection();
257 void HandleDBClosed(DBState* aDBState);
258 void HandleCorruptDB(DBState* aDBState);
259 void RebuildCorruptDB(DBState* aDBState);
260 OpenDBResult Read();
261 template<class T> nsCookie* GetCookieFromRow(T &aRow);
262 void AsyncReadComplete();
263 void CancelAsyncRead(bool aPurgeReadSet);
264 void EnsureReadDomain(const nsCookieKey &aKey);
265 void EnsureReadComplete();
266 nsresult NormalizeHost(nsCString &aHost);
267 nsresult GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
268 nsresult GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
269 nsresult GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
270 void GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, uint32_t aAppId, bool aInBrowserElement, bool aIsPrivate, nsCString &aCookie);
271 nsresult SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
272 void SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, uint32_t aAppId, bool aInBrowserElement, bool aIsPrivate, nsIChannel* aChannel);
273 bool SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel);
274 void AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
275 void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = NULL);
276 void AddCookieToList(const nsCookieKey& aKey, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true);
277 void UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
278 static bool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound);
279 static bool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
280 bool RequireThirdPartyCheck();
281 CookieStatus CheckPrefs(nsIURI *aHostURI, bool aIsForeign, bool aRequireHostMatch, const char *aCookieHeader);
282 bool CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, bool aRequireHostMatch);
283 static bool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
284 static bool GetExpiry(nsCookieAttributes &aCookie, int64_t aServerTime, int64_t aCurrentTime);
285 void RemoveAllFromMemory();
286 already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec);
287 bool FindCookie(const nsCookieKey& aKey, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
288 static void FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsListIter &aIter);
289 void NotifyRejected(nsIURI *aHostURI);
290 void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData);
291 void NotifyPurged(nsICookie2* aCookie);
292 already_AddRefed<nsIArray> CreatePurgeList(nsICookie2* aCookie);
295 * This method is used to iterate the cookie hash table and select the ones
296 * that are part of a specific app.
298 static PLDHashOperator GetCookiesForApp(nsCookieEntry* entry, void* arg);
301 * This method is a helper that allows calling nsICookieManager::Remove()
302 * with appId/inBrowserElement parameters.
303 * NOTE: this could be added to a public interface if we happen to need it.
305 nsresult Remove(const nsACString& aHost, uint32_t aAppId,
306 bool aInBrowserElement, const nsACString& aName,
307 const nsACString& aPath, bool aBlocked);
309 protected:
310 // cached members.
311 nsCOMPtr<nsIObserverService> mObserverService;
312 nsCOMPtr<nsICookiePermission> mPermissionService;
313 nsCOMPtr<mozIThirdPartyUtil> mThirdPartyUtil;
314 nsCOMPtr<nsIEffectiveTLDService> mTLDService;
315 nsCOMPtr<nsIIDNService> mIDNService;
316 nsCOMPtr<mozIStorageService> mStorageService;
318 // we have two separate DB states: one for normal browsing and one for
319 // private browsing, switching between them on a per-cookie-request basis.
320 // this state encapsulates both the in-memory table and the on-disk DB.
321 // note that the private states' dbConn should always be null - we never
322 // want to be dealing with the on-disk DB when in private browsing.
323 DBState *mDBState;
324 nsRefPtr<DBState> mDefaultDBState;
325 nsRefPtr<DBState> mPrivateDBState;
327 // cached prefs
328 uint8_t mCookieBehavior; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT, LIMITFOREIGN}
329 bool mThirdPartySession;
330 uint16_t mMaxNumberOfCookies;
331 uint16_t mMaxCookiesPerHost;
332 int64_t mCookiePurgeAge;
334 // friends!
335 friend PLDHashOperator purgeCookiesCallback(nsCookieEntry *aEntry, void *aArg);
336 friend class DBListenerErrorHandler;
337 friend class ReadCookieDBListener;
338 friend class CloseCookieDBListener;
340 static nsCookieService* GetSingleton();
341 friend class mozilla::net::CookieServiceParent;
344 #endif // nsCookieService_h__