1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
23 * Daniel Witte (dwitte@stanford.edu)
24 * Michiel van Leeuwen (mvl@exedo.nl)
25 * Michael Ventnor <m.ventnor@gmail.com>
26 * Ehsan Akhgari <ehsan.akhgari@gmail.com>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #ifndef nsCookieService_h__
43 #define nsCookieService_h__
45 #include "nsICookieService.h"
46 #include "nsICookieManager.h"
47 #include "nsICookieManager2.h"
48 #include "nsIObserver.h"
49 #include "nsWeakReference.h"
53 #include "nsAutoPtr.h"
54 #include "nsHashKeys.h"
55 #include "nsTHashtable.h"
56 #include "mozIStorageStatement.h"
57 #include "mozIStorageAsyncStatement.h"
58 #include "mozIStoragePendingStatement.h"
59 #include "mozIStorageConnection.h"
60 #include "mozIStorageRow.h"
61 #include "mozIStorageCompletionCallback.h"
62 #include "mozIStorageStatementCallback.h"
64 class nsICookiePermission
;
65 class nsIEffectiveTLDService
;
68 class nsIObserverService
;
72 class mozIStorageService
;
73 class mozIThirdPartyUtil
;
74 class ReadCookieDBListener
;
76 struct nsCookieAttributes
;
78 struct nsEnumerationData
;
83 class CookieServiceParent
;
89 class nsCookieEntry
: public PLDHashEntryHdr
93 typedef const nsCString
& KeyType
;
94 typedef const nsCString
* KeyTypePointer
;
95 typedef nsTArray
< nsRefPtr
<nsCookie
> > ArrayType
;
96 typedef ArrayType::index_type IndexType
;
99 nsCookieEntry(KeyTypePointer aBaseDomain
)
100 : mBaseDomain(*aBaseDomain
)
104 nsCookieEntry(const nsCookieEntry
& toCopy
)
106 // if we end up here, things will break. nsTHashtable shouldn't
107 // allow this, since we set ALLOW_MEMMOVE to true.
108 NS_NOTREACHED("nsCookieEntry copy constructor is forbidden!");
115 KeyType
GetKey() const
120 PRBool
KeyEquals(KeyTypePointer aKey
) const
122 return mBaseDomain
== *aKey
;
125 static KeyTypePointer
KeyToPointer(KeyType aKey
)
130 static PLDHashNumber
HashKey(KeyTypePointer aKey
)
132 return HashString(*aKey
);
135 enum { ALLOW_MEMMOVE
= PR_TRUE
};
137 inline ArrayType
& GetCookies() { return mCookies
; }
140 nsCString mBaseDomain
;
144 // encapsulates a (baseDomain, nsCookie) tuple for temporary storage purposes.
145 struct CookieDomainTuple
147 nsCString baseDomain
;
148 nsRefPtr
<nsCookie
> cookie
;
151 // encapsulates in-memory and on-disk DB states, so we can
152 // conveniently switch state when entering or exiting private browsing.
155 DBState() : cookieCount(0), cookieOldestTime(LL_MAXINT
), corruptFlag(OK
)
160 NS_INLINE_DECL_REFCOUNTING(DBState
)
162 // State of the database connection.
165 CLOSING_FOR_REBUILD
, // corruption detected, connection closing
166 REBUILDING
// close complete, rebuilding database from memory
169 nsTHashtable
<nsCookieEntry
> hostTable
;
170 PRUint32 cookieCount
;
171 PRInt64 cookieOldestTime
;
172 nsCOMPtr
<nsIFile
> cookieFile
;
173 nsCOMPtr
<mozIStorageConnection
> dbConn
;
174 nsCOMPtr
<mozIStorageAsyncStatement
> stmtInsert
;
175 nsCOMPtr
<mozIStorageAsyncStatement
> stmtDelete
;
176 nsCOMPtr
<mozIStorageAsyncStatement
> stmtUpdate
;
177 CorruptFlag corruptFlag
;
179 // Various parts representing asynchronous read state. These are useful
180 // while the background read is taking place.
181 nsCOMPtr
<mozIStorageConnection
> syncConn
;
182 nsCOMPtr
<mozIStorageStatement
> stmtReadDomain
;
183 nsCOMPtr
<mozIStoragePendingStatement
> pendingRead
;
184 // The asynchronous read listener. This is a weak ref (storage has ownership)
185 // since it may need to outlive the DBState's database connection.
186 ReadCookieDBListener
* readListener
;
187 // An array of (baseDomain, cookie) tuples representing data read in
188 // asynchronously. This is merged into hostTable once read is complete.
189 nsTArray
<CookieDomainTuple
> hostArray
;
190 // A hashset of baseDomains read in synchronously, while the async read is
191 // in flight. This is used to keep track of which data in hostArray is stale
192 // when the time comes to merge.
193 nsTHashtable
<nsCStringHashKey
> readSet
;
195 // DB completion handlers.
196 nsCOMPtr
<mozIStorageStatementCallback
> insertListener
;
197 nsCOMPtr
<mozIStorageStatementCallback
> updateListener
;
198 nsCOMPtr
<mozIStorageStatementCallback
> removeListener
;
199 nsCOMPtr
<mozIStorageCompletionCallback
> closeListener
;
202 // these constants represent a decision about a cookie based on user prefs.
206 STATUS_ACCEPT_SESSION
,
208 // STATUS_REJECTED_WITH_ERROR indicates the cookie should be rejected because
209 // of an error (rather than something the user can control). this is used for
210 // notification purposes, since we only want to notify of rejections where
211 // the user can do something about it (e.g. whitelist the site).
212 STATUS_REJECTED_WITH_ERROR
215 // Result codes for TryInitDB() and Read().
223 /******************************************************************************
226 ******************************************************************************/
228 class nsCookieService
: public nsICookieService
229 , public nsICookieManager2
231 , public nsSupportsWeakReference
237 NS_DECL_NSICOOKIESERVICE
238 NS_DECL_NSICOOKIEMANAGER
239 NS_DECL_NSICOOKIEMANAGER2
242 virtual ~nsCookieService();
243 static nsICookieService
* GetXPCOMSingleton();
247 void PrefChanged(nsIPrefBranch
*aPrefBranch
);
249 OpenDBResult
TryInitDB(bool aDeleteExistingDB
);
250 nsresult
CreateTable();
251 void CloseDBStates();
252 void CloseDefaultDBConnection();
253 void HandleDBClosed(DBState
* aDBState
);
254 void HandleCorruptDB(DBState
* aDBState
);
255 void RebuildCorruptDB(DBState
* aDBState
);
257 template<class T
> nsCookie
* GetCookieFromRow(T
&aRow
);
258 void AsyncReadComplete();
259 void CancelAsyncRead(PRBool aPurgeReadSet
);
260 void EnsureReadDomain(const nsCString
&aBaseDomain
);
261 void EnsureReadComplete();
262 nsresult
NormalizeHost(nsCString
&aHost
);
263 nsresult
GetBaseDomain(nsIURI
*aHostURI
, nsCString
&aBaseDomain
, PRBool
&aRequireHostMatch
);
264 nsresult
GetBaseDomainFromHost(const nsACString
&aHost
, nsCString
&aBaseDomain
);
265 nsresult
GetCookieStringCommon(nsIURI
*aHostURI
, nsIChannel
*aChannel
, bool aHttpBound
, char** aCookie
);
266 void GetCookieStringInternal(nsIURI
*aHostURI
, bool aIsForeign
, PRBool aHttpBound
, nsCString
&aCookie
);
267 nsresult
SetCookieStringCommon(nsIURI
*aHostURI
, const char *aCookieHeader
, const char *aServerTime
, nsIChannel
*aChannel
, bool aFromHttp
);
268 void SetCookieStringInternal(nsIURI
*aHostURI
, bool aIsForeign
, const nsCString
&aCookieHeader
, const nsCString
&aServerTime
, PRBool aFromHttp
);
269 PRBool
SetCookieInternal(nsIURI
*aHostURI
, const nsCString
& aBaseDomain
, PRBool aRequireHostMatch
, CookieStatus aStatus
, nsDependentCString
&aCookieHeader
, PRInt64 aServerTime
, PRBool aFromHttp
);
270 void AddInternal(const nsCString
& aBaseDomain
, nsCookie
*aCookie
, PRInt64 aCurrentTimeInUsec
, nsIURI
*aHostURI
, const char *aCookieHeader
, PRBool aFromHttp
);
271 void RemoveCookieFromList(const nsListIter
&aIter
, mozIStorageBindingParamsArray
*aParamsArray
= NULL
);
272 void AddCookieToList(const nsCString
& aBaseDomain
, nsCookie
*aCookie
, DBState
*aDBState
, mozIStorageBindingParamsArray
*aParamsArray
, PRBool aWriteToDB
= PR_TRUE
);
273 void UpdateCookieInList(nsCookie
*aCookie
, PRInt64 aLastAccessed
, mozIStorageBindingParamsArray
*aParamsArray
);
274 static PRBool
GetTokenValue(nsASingleFragmentCString::const_char_iterator
&aIter
, nsASingleFragmentCString::const_char_iterator
&aEndIter
, nsDependentCSubstring
&aTokenString
, nsDependentCSubstring
&aTokenValue
, PRBool
&aEqualsFound
);
275 static PRBool
ParseAttributes(nsDependentCString
&aCookieHeader
, nsCookieAttributes
&aCookie
);
276 bool RequireThirdPartyCheck();
277 CookieStatus
CheckPrefs(nsIURI
*aHostURI
, bool aIsForeign
, const nsCString
&aBaseDomain
, PRBool aRequireHostMatch
, const char *aCookieHeader
);
278 PRBool
CheckDomain(nsCookieAttributes
&aCookie
, nsIURI
*aHostURI
, const nsCString
&aBaseDomain
, PRBool aRequireHostMatch
);
279 static PRBool
CheckPath(nsCookieAttributes
&aCookie
, nsIURI
*aHostURI
);
280 static PRBool
GetExpiry(nsCookieAttributes
&aCookie
, PRInt64 aServerTime
, PRInt64 aCurrentTime
);
281 void RemoveAllFromMemory();
282 already_AddRefed
<nsIArray
> PurgeCookies(PRInt64 aCurrentTimeInUsec
);
283 PRBool
FindCookie(const nsCString
& aBaseDomain
, const nsAFlatCString
&aHost
, const nsAFlatCString
&aName
, const nsAFlatCString
&aPath
, nsListIter
&aIter
);
284 static void FindStaleCookie(nsCookieEntry
*aEntry
, PRInt64 aCurrentTime
, nsListIter
&aIter
);
285 void NotifyRejected(nsIURI
*aHostURI
);
286 void NotifyChanged(nsISupports
*aSubject
, const PRUnichar
*aData
);
287 void NotifyPurged(nsICookie2
* aCookie
);
288 already_AddRefed
<nsIArray
> CreatePurgeList(nsICookie2
* aCookie
);
292 nsCOMPtr
<nsIObserverService
> mObserverService
;
293 nsCOMPtr
<nsICookiePermission
> mPermissionService
;
294 nsCOMPtr
<mozIThirdPartyUtil
> mThirdPartyUtil
;
295 nsCOMPtr
<nsIEffectiveTLDService
> mTLDService
;
296 nsCOMPtr
<nsIIDNService
> mIDNService
;
297 nsCOMPtr
<mozIStorageService
> mStorageService
;
299 // we have two separate DB states: one for normal browsing and one for
300 // private browsing, switching between them as appropriate. this state
301 // encapsulates both the in-memory table and the on-disk DB.
302 // note that the private states' dbConn should always be null - we never
303 // want to be dealing with the on-disk DB when in private browsing.
305 nsRefPtr
<DBState
> mDefaultDBState
;
306 nsRefPtr
<DBState
> mPrivateDBState
;
309 PRUint8 mCookieBehavior
; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT}
310 PRBool mThirdPartySession
;
311 PRUint16 mMaxNumberOfCookies
;
312 PRUint16 mMaxCookiesPerHost
;
313 PRInt64 mCookiePurgeAge
;
316 friend PLDHashOperator
purgeCookiesCallback(nsCookieEntry
*aEntry
, void *aArg
);
317 friend class DBListenerErrorHandler
;
318 friend class ReadCookieDBListener
;
319 friend class CloseCookieDBListener
;
321 static nsCookieService
* GetSingleton();
323 friend class mozilla::net::CookieServiceParent
;
327 #endif // nsCookieService_h__