CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / dom / src / storage / nsDOMStorage.h
blob171ff852d7770aea28fe7cbbf08bedfd2edbc9b5
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
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2006
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Neil Deakin <enndeakin@sympatico.ca>
24 * Johnny Stenback <jst@mozilla.com>
25 * Ehsan Akhgari <ehsan.akhgari@gmail.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #ifndef nsDOMStorage_h___
42 #define nsDOMStorage_h___
44 #include "nscore.h"
45 #include "nsAutoPtr.h"
46 #include "nsIDOMStorageObsolete.h"
47 #include "nsIDOMStorage.h"
48 #include "nsIDOMStorageList.h"
49 #include "nsIDOMStorageItem.h"
50 #include "nsIPermissionManager.h"
51 #include "nsInterfaceHashtable.h"
52 #include "nsVoidArray.h"
53 #include "nsTArray.h"
54 #include "nsPIDOMStorage.h"
55 #include "nsIDOMToString.h"
56 #include "nsDOMEvent.h"
57 #include "nsIDOMStorageEvent.h"
58 #include "nsIDOMStorageEventObsolete.h"
59 #include "nsIDOMStorageManager.h"
60 #include "nsCycleCollectionParticipant.h"
61 #include "nsIObserver.h"
62 #include "nsITimer.h"
63 #include "nsWeakReference.h"
65 #define NS_DOMSTORAGE_FLUSH_TIMER_OBSERVER "domstorage-flush-timer"
67 #ifdef MOZ_STORAGE
68 #include "nsDOMStorageDBWrapper.h"
69 #endif
71 #define IS_PERMISSION_ALLOWED(perm) \
72 ((perm) != nsIPermissionManager::UNKNOWN_ACTION && \
73 (perm) != nsIPermissionManager::DENY_ACTION)
75 class nsDOMStorage;
76 class nsIDOMStorage;
77 class nsDOMStorageItem;
78 class nsDOMStoragePersistentDB;
80 namespace mozilla {
81 namespace dom {
82 class StorageParent;
85 using mozilla::dom::StorageParent;
87 class DOMStorageImpl;
89 class nsDOMStorageEntry : public nsVoidPtrHashKey
91 public:
92 nsDOMStorageEntry(KeyTypePointer aStr);
93 nsDOMStorageEntry(const nsDOMStorageEntry& aToCopy);
94 ~nsDOMStorageEntry();
96 // weak reference so that it can be deleted when no longer used
97 DOMStorageImpl* mStorage;
100 class nsSessionStorageEntry : public nsStringHashKey
102 public:
103 nsSessionStorageEntry(KeyTypePointer aStr);
104 nsSessionStorageEntry(const nsSessionStorageEntry& aToCopy);
105 ~nsSessionStorageEntry();
107 nsRefPtr<nsDOMStorageItem> mItem;
110 class nsDOMStorageManager : public nsIDOMStorageManager
111 , public nsIObserver
113 public:
114 // nsISupports
115 NS_DECL_ISUPPORTS
117 // nsIDOMStorageManager
118 NS_DECL_NSIDOMSTORAGEMANAGER
120 // nsIObserver
121 NS_DECL_NSIOBSERVER
123 nsDOMStorageManager();
125 void AddToStoragesHash(DOMStorageImpl* aStorage);
126 void RemoveFromStoragesHash(DOMStorageImpl* aStorage);
128 nsresult ClearAllStorages();
130 PRBool InPrivateBrowsingMode() { return mInPrivateBrowsing; }
132 static nsresult Initialize();
133 static nsDOMStorageManager* GetInstance();
134 static void Shutdown();
137 * Checks whether there is any data waiting to be flushed from a temp table.
139 PRBool UnflushedDataExists();
141 static nsDOMStorageManager* gStorageManager;
143 protected:
145 nsTHashtable<nsDOMStorageEntry> mStorages;
146 PRBool mInPrivateBrowsing;
149 class DOMStorageBase : public nsISupports
151 public:
152 DOMStorageBase();
153 DOMStorageBase(DOMStorageBase&);
155 virtual void InitAsSessionStorage(nsIURI* aDomainURI);
156 virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist);
157 virtual void InitAsGlobalStorage(const nsACString& aDomainDemanded);
159 virtual nsTArray<nsString>* GetKeys(bool aCallerSecure) = 0;
160 virtual nsresult GetLength(bool aCallerSecure, PRUint32* aLength) = 0;
161 virtual nsresult GetKey(bool aCallerSecure, PRUint32 aIndex, nsAString& aKey) = 0;
162 virtual nsIDOMStorageItem* GetValue(bool aCallerSecure, const nsAString& aKey,
163 nsresult* rv) = 0;
164 virtual nsresult SetValue(bool aCallerSecure, const nsAString& aKey,
165 const nsAString& aData, nsAString& aOldValue) = 0;
166 virtual nsresult RemoveValue(bool aCallerSecure, const nsAString& aKey,
167 nsAString& aOldValue) = 0;
168 virtual nsresult Clear(bool aCallerSecure, PRInt32* aOldCount) = 0;
170 // If true, the contents of the storage should be stored in the
171 // database, otherwise this storage should act like a session
172 // storage.
173 // This call relies on mSessionOnly, and should only be used
174 // after a CacheStoragePermissions() call. See the comments
175 // for mSessionOnly below.
176 PRBool UseDB() {
177 return mUseDB;
180 // retrieve the value and secure state corresponding to a key out of storage.
181 virtual nsresult
182 GetDBValue(const nsAString& aKey,
183 nsAString& aValue,
184 PRBool* aSecure) = 0;
186 // set the value corresponding to a key in the storage. If
187 // aSecure is false, then attempts to modify a secure value
188 // throw NS_ERROR_DOM_INVALID_ACCESS_ERR
189 virtual nsresult
190 SetDBValue(const nsAString& aKey,
191 const nsAString& aValue,
192 PRBool aSecure) = 0;
194 // set the value corresponding to a key as secure.
195 virtual nsresult
196 SetSecure(const nsAString& aKey, PRBool aSecure) = 0;
198 virtual nsresult
199 CloneFrom(bool aCallerSecure, DOMStorageBase* aThat) = 0;
201 // e.g. "moc.rab.oof.:" or "moc.rab.oof.:http:80" depending
202 // on association with a domain (globalStorage) or
203 // an origin (localStorage).
204 nsCString& GetScopeDBKey() {return mScopeDBKey;}
206 // e.g. "moc.rab.%" - reversed eTLD+1 subpart of the domain or
207 // reversed offline application allowed domain.
208 nsCString& GetQuotaDomainDBKey(PRBool aOfflineAllowed)
210 return aOfflineAllowed ? mQuotaDomainDBKey : mQuotaETLDplus1DomainDBKey;
213 virtual bool CacheStoragePermissions() = 0;
215 protected:
216 friend class nsDOMStorageManager;
217 friend class nsDOMStorage;
219 nsPIDOMStorage::nsDOMStorageType mStorageType;
221 // true if the storage database should be used for values
222 PRPackedBool mUseDB;
224 // true if the preferences indicates that this storage should be
225 // session only. This member is updated by
226 // CacheStoragePermissions(), using the current principal.
227 // CacheStoragePermissions() must be called at each entry point to
228 // make sure this stays up to date.
229 PRPackedBool mSessionOnly;
231 // domain this store is associated with
232 nsCString mDomain;
234 // keys are used for database queries.
235 // see comments of the getters bellow.
236 nsCString mScopeDBKey;
237 nsCString mQuotaETLDplus1DomainDBKey;
238 nsCString mQuotaDomainDBKey;
240 bool mCanUseChromePersist;
243 class DOMStorageImpl : public DOMStorageBase
246 public:
247 NS_DECL_CYCLE_COLLECTION_CLASS(DOMStorageImpl)
248 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
250 DOMStorageImpl(nsDOMStorage*);
251 DOMStorageImpl(nsDOMStorage*, DOMStorageImpl&);
252 ~DOMStorageImpl();
254 virtual void InitAsSessionStorage(nsIURI* aDomainURI);
255 virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist);
256 virtual void InitAsGlobalStorage(const nsACString& aDomainDemanded);
258 PRBool SessionOnly() {
259 return mSessionOnly;
262 virtual nsTArray<nsString>* GetKeys(bool aCallerSecure);
263 virtual nsresult GetLength(bool aCallerSecure, PRUint32* aLength);
264 virtual nsresult GetKey(bool aCallerSecure, PRUint32 aIndex, nsAString& aKey);
265 virtual nsIDOMStorageItem* GetValue(bool aCallerSecure, const nsAString& aKey,
266 nsresult* rv);
267 virtual nsresult SetValue(bool aCallerSecure, const nsAString& aKey,
268 const nsAString& aData, nsAString& aOldValue);
269 virtual nsresult RemoveValue(bool aCallerSecure, const nsAString& aKey,
270 nsAString& aOldValue);
271 virtual nsresult Clear(bool aCallerSecure, PRInt32* aOldCount);
273 // cache the keys from the database for faster lookup
274 nsresult CacheKeysFromDB();
276 // Some privileged internal pages can use a persistent storage even in
277 // session-only or private-browsing modes.
278 bool CanUseChromePersist();
280 // retrieve the value and secure state corresponding to a key out of storage
281 // that has been cached in mItems hash table.
282 nsresult
283 GetCachedValue(const nsAString& aKey,
284 nsAString& aValue,
285 PRBool* aSecure);
287 // retrieve the value and secure state corresponding to a key out of storage.
288 virtual nsresult
289 GetDBValue(const nsAString& aKey,
290 nsAString& aValue,
291 PRBool* aSecure);
293 // set the value corresponding to a key in the storage. If
294 // aSecure is false, then attempts to modify a secure value
295 // throw NS_ERROR_DOM_INVALID_ACCESS_ERR
296 virtual nsresult
297 SetDBValue(const nsAString& aKey,
298 const nsAString& aValue,
299 PRBool aSecure);
301 // set the value corresponding to a key as secure.
302 virtual nsresult
303 SetSecure(const nsAString& aKey, PRBool aSecure);
305 // clear all values from the store
306 void ClearAll();
308 virtual nsresult
309 CloneFrom(bool aCallerSecure, DOMStorageBase* aThat);
311 virtual bool CacheStoragePermissions();
313 private:
314 #ifdef MOZ_STORAGE
315 static nsDOMStorageDBWrapper* gStorageDB;
316 #endif
317 friend class nsDOMStorageManager;
318 friend class nsDOMStoragePersistentDB;
319 friend class StorageParent;
321 void Init(nsDOMStorage*);
323 // Cross-process storage implementations never have InitAs(Session|Local|Global)Storage
324 // called, so the appropriate initialization needs to happen from the child.
325 void InitFromChild(bool aUseDB, bool aCanUseChromePersist, bool aSessionOnly,
326 const nsACString& aDomain,
327 const nsACString& aScopeDBKey,
328 const nsACString& aQuotaDomainDBKey,
329 const nsACString& aQuotaETLDplus1DomainDBKey,
330 PRUint32 aStorageType);
331 void SetSessionOnly(bool aSessionOnly);
333 static nsresult InitDB();
335 // true if items from the database are cached
336 PRPackedBool mItemsCached;
338 // the key->value item pairs
339 nsTHashtable<nsSessionStorageEntry> mItems;
341 // Weak reference to the owning storage instance
342 nsDOMStorage* mOwner;
345 class nsDOMStorage : public nsIDOMStorageObsolete,
346 public nsPIDOMStorage
348 public:
349 nsDOMStorage();
350 nsDOMStorage(nsDOMStorage& aThat);
351 virtual ~nsDOMStorage();
353 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
354 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMStorage, nsIDOMStorageObsolete)
356 NS_DECL_NSIDOMSTORAGEOBSOLETE
358 // Helpers for implementing nsIDOMStorage
359 nsresult GetItem(const nsAString& key, nsAString& aData);
360 nsresult Clear();
362 // nsPIDOMStorage
363 virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
364 virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
365 virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded);
366 virtual already_AddRefed<nsIDOMStorage> Clone();
367 virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
368 virtual PRBool IsForkOf(nsIDOMStorage* aThat);
369 virtual nsTArray<nsString> *GetKeys();
370 virtual nsIPrincipal* Principal();
371 virtual PRBool CanAccess(nsIPrincipal *aPrincipal);
372 virtual nsDOMStorageType StorageType();
373 virtual void BroadcastChangeNotification(const nsSubstring &aKey,
374 const nsSubstring &aOldValue,
375 const nsSubstring &aNewValue);
377 // Check whether storage may be used by the caller, and whether it
378 // is session only. Returns true if storage may be used.
379 static PRBool
380 CanUseStorage(PRPackedBool* aSessionOnly);
382 // Check whether this URI can use chrome persist storage. This kind of
383 // storage can bypass cookies limits, private browsing and uses the offline
384 // apps quota.
385 static PRBool
386 URICanUseChromePersist(nsIURI* aURI);
388 // Check whether storage may be used. Updates mSessionOnly based on
389 // the result of CanUseStorage.
390 PRBool
391 CacheStoragePermissions();
393 nsIDOMStorageItem* GetNamedItem(const nsAString& aKey, nsresult* aResult);
395 static nsDOMStorage* FromSupports(nsISupports* aSupports)
397 return static_cast<nsDOMStorage*>(static_cast<nsIDOMStorageObsolete*>(aSupports));
400 nsresult SetSecure(const nsAString& aKey, PRBool aSecure)
402 return mStorageImpl->SetSecure(aKey, aSecure);
405 nsresult CloneFrom(nsDOMStorage* aThat);
407 protected:
408 friend class nsDOMStorage2;
409 friend class nsDOMStoragePersistentDB;
411 nsRefPtr<DOMStorageBase> mStorageImpl;
413 PRBool CanAccessSystem(nsIPrincipal *aPrincipal);
415 // document URI of the document this storage is bound to
416 nsString mDocumentURI;
418 // true if this storage was initialized as a localStorage object. localStorage
419 // objects are scoped to scheme/host/port in the database, while globalStorage
420 // objects are scoped just to host. this flag also tells the manager to map
421 // this storage also in mLocalStorages hash table.
422 nsDOMStorageType mStorageType;
424 friend class nsIDOMStorage2;
425 nsPIDOMStorage* mSecurityChecker;
426 nsPIDOMStorage* mEventBroadcaster;
429 class nsDOMStorage2 : public nsIDOMStorage,
430 public nsPIDOMStorage
432 public:
433 // nsISupports
434 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
435 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMStorage2, nsIDOMStorage)
437 nsDOMStorage2(nsDOMStorage2& aThat);
438 nsDOMStorage2();
440 NS_DECL_NSIDOMSTORAGE
442 // nsPIDOMStorage
443 virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
444 virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
445 virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded);
446 virtual already_AddRefed<nsIDOMStorage> Clone();
447 virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
448 virtual PRBool IsForkOf(nsIDOMStorage* aThat);
449 virtual nsTArray<nsString> *GetKeys();
450 virtual nsIPrincipal* Principal();
451 virtual PRBool CanAccess(nsIPrincipal *aPrincipal);
452 virtual nsDOMStorageType StorageType();
453 virtual void BroadcastChangeNotification(const nsSubstring &aKey,
454 const nsSubstring &aOldValue,
455 const nsSubstring &aNewValue);
457 nsresult InitAsSessionStorageFork(nsIPrincipal *aPrincipal,
458 const nsSubstring &aDocumentURI,
459 nsIDOMStorageObsolete* aStorage);
461 private:
462 // storages bound to an origin hold the principal to
463 // make security checks against it
464 nsCOMPtr<nsIPrincipal> mPrincipal;
466 // Needed for the storage event, this is address of the document this storage
467 // is bound to
468 nsString mDocumentURI;
469 nsRefPtr<nsDOMStorage> mStorage;
472 class nsDOMStorageList : public nsIDOMStorageList
474 public:
475 nsDOMStorageList()
477 mStorages.Init();
480 virtual ~nsDOMStorageList() {}
482 // nsISupports
483 NS_DECL_ISUPPORTS
485 // nsIDOMStorageList
486 NS_DECL_NSIDOMSTORAGELIST
488 nsIDOMStorageObsolete* GetNamedItem(const nsAString& aDomain, nsresult* aResult);
491 * Check whether aCurrentDomain has access to aRequestedDomain
493 static PRBool
494 CanAccessDomain(const nsACString& aRequestedDomain,
495 const nsACString& aCurrentDomain);
497 protected:
500 * Return the global nsIDOMStorageObsolete for a particular domain.
501 * aNoCurrentDomainCheck may be true to skip the domain comparison;
502 * this is used for chrome code so that it may retrieve data from
503 * any domain.
505 * @param aRequestedDomain domain to return
506 * @param aCurrentDomain domain of current caller
507 * @param aNoCurrentDomainCheck true to skip domain comparison
509 nsIDOMStorageObsolete*
510 GetStorageForDomain(const nsACString& aRequestedDomain,
511 const nsACString& aCurrentDomain,
512 PRBool aNoCurrentDomainCheck,
513 nsresult* aResult);
516 * Convert the domain into an array of its component parts.
518 static PRBool
519 ConvertDomainToArray(const nsACString& aDomain,
520 nsTArray<nsCString>* aArray);
522 nsInterfaceHashtable<nsCStringHashKey, nsIDOMStorageObsolete> mStorages;
525 class nsDOMStorageItem : public nsIDOMStorageItem,
526 public nsIDOMToString
528 public:
529 nsDOMStorageItem(DOMStorageBase* aStorage,
530 const nsAString& aKey,
531 const nsAString& aValue,
532 PRBool aSecure);
533 virtual ~nsDOMStorageItem();
535 // nsISupports
536 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
537 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMStorageItem, nsIDOMStorageItem)
539 // nsIDOMStorageObsolete
540 NS_DECL_NSIDOMSTORAGEITEM
542 // nsIDOMToString
543 NS_DECL_NSIDOMTOSTRING
545 PRBool IsSecure()
547 return mSecure;
550 void SetSecureInternal(PRBool aSecure)
552 mSecure = aSecure;
555 const nsAString& GetValueInternal()
557 return mValue;
560 const void SetValueInternal(const nsAString& aValue)
562 mValue = aValue;
565 void ClearValue()
567 mValue.Truncate();
570 protected:
572 // true if this value is for secure sites only
573 PRBool mSecure;
575 // key for the item
576 nsString mKey;
578 // value of the item
579 nsString mValue;
581 // If this item came from the db, mStorage points to the storage
582 // object where this item came from.
583 nsRefPtr<DOMStorageBase> mStorage;
586 class nsDOMStorageEvent : public nsDOMEvent,
587 public nsIDOMStorageEvent
589 public:
590 nsDOMStorageEvent()
591 : nsDOMEvent(nsnull, nsnull)
595 virtual ~nsDOMStorageEvent()
599 nsresult Init();
601 NS_DECL_ISUPPORTS_INHERITED
602 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMStorageEvent, nsDOMEvent)
604 NS_DECL_NSIDOMSTORAGEEVENT
605 NS_FORWARD_NSIDOMEVENT(nsDOMEvent::)
607 protected:
608 nsString mKey;
609 nsString mOldValue;
610 nsString mNewValue;
611 nsString mUrl;
612 nsCOMPtr<nsIDOMStorage> mStorageArea;
615 class nsDOMStorageEventObsolete : public nsDOMEvent,
616 public nsIDOMStorageEventObsolete
618 public:
619 nsDOMStorageEventObsolete()
620 : nsDOMEvent(nsnull, nsnull)
624 virtual ~nsDOMStorageEventObsolete()
628 NS_DECL_ISUPPORTS
629 NS_DECL_NSIDOMSTORAGEEVENTOBSOLETE
630 NS_FORWARD_NSIDOMEVENT(nsDOMEvent::)
632 protected:
633 nsString mDomain;
636 nsresult
637 NS_NewDOMStorage(nsISupports* aOuter, REFNSIID aIID, void** aResult);
639 nsresult
640 NS_NewDOMStorage2(nsISupports* aOuter, REFNSIID aIID, void** aResult);
642 nsresult
643 NS_NewDOMStorageList(nsIDOMStorageList** aResult);
645 PRUint32
646 GetOfflinePermission(const nsACString &aDomain);
648 PRBool
649 IsOfflineAllowed(const nsACString &aDomain);
651 #endif /* nsDOMStorage_h___ */