From b8424948c9eaf1ca8a5be06a6ab173a2384a8f07 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 25 May 2012 12:20:31 +0100 Subject: [PATCH] Bug 722857 - Determine private browsing status for DOMStorage from owning docshell if available, and receive updates if its privacy status changes. r=mayhemer --- docshell/base/nsDocShell.cpp | 2 +- dom/base/nsGlobalWindow.cpp | 31 +++- dom/indexedDB/CheckPermissionsHelper.cpp | 6 +- .../storage/nsIDOMStorageManager.idl | 5 +- dom/interfaces/storage/nsPIDOMStorage.h | 6 +- dom/src/storage/PStorage.ipdl | 6 +- dom/src/storage/StorageChild.cpp | 26 +++- dom/src/storage/StorageChild.h | 8 +- dom/src/storage/StorageParent.cpp | 10 +- dom/src/storage/StorageParent.h | 3 + dom/src/storage/nsDOMStorage.cpp | 138 ++++++++++++------ dom/src/storage/nsDOMStorage.h | 54 ++++--- dom/src/storage/nsDOMStorageDBWrapper.cpp | 32 +--- dom/src/storage/nsDOMStorageDBWrapper.h | 8 +- 14 files changed, 211 insertions(+), 124 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index fe5b21c538a7..390cb1959fa8 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -2400,7 +2400,7 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal, if (!pistorage) return NS_ERROR_FAILURE; - rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI); + rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI, mInPrivateBrowsing); if (NS_FAILED(rv)) return rv; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 2b613b06dfa4..25f4cd500cd1 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -104,6 +104,7 @@ #include "nsIHttpProtocolHandler.h" #include "nsIJSContextStack.h" #include "nsIJSRuntimeService.h" +#include "nsILoadContext.h" #include "nsIMarkupDocumentViewer.h" #include "nsIPresShell.h" #include "nsIPrivateDOMEvent.h" @@ -2243,6 +2244,19 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) bool docShellActive; mDocShell->GetIsActive(&docShellActive); mIsBackground = !docShellActive; + + if (mLocalStorage) { + nsCOMPtr obs = do_GetInterface(mLocalStorage); + if (obs) { + mDocShell->AddWeakPrivacyTransitionObserver(obs); + } + } + if (mSessionStorage) { + nsCOMPtr obs = do_GetInterface(mSessionStorage); + if (obs) { + mDocShell->AddWeakPrivacyTransitionObserver(obs); + } + } } } @@ -8084,6 +8098,11 @@ nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage) if (!mSessionStorage) { return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } + + nsCOMPtr obs = do_GetInterface(mSessionStorage); + if (obs) { + docShell->AddWeakPrivacyTransitionObserver(obs); + } } #ifdef PR_LOGGING @@ -8113,8 +8132,7 @@ nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage) nsresult rv; - bool unused; - if (!nsDOMStorage::CanUseStorage(&unused)) + if (!nsDOMStorage::CanUseStorage()) return NS_ERROR_DOM_SECURITY_ERR; nsIPrincipal *principal = GetPrincipal(); @@ -8130,10 +8148,19 @@ nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage) mDocument->GetDocumentURI(documentURI); } + nsIDocShell* docShell = GetDocShell(); + nsCOMPtr loadContext = do_QueryInterface(docShell); + rv = storageManager->GetLocalStorageForPrincipal(principal, documentURI, + loadContext && loadContext->UsePrivateBrowsing(), getter_AddRefs(mLocalStorage)); NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr obs = do_GetInterface(mLocalStorage); + if (obs) { + docShell->AddWeakPrivacyTransitionObserver(obs); + } } NS_ADDREF(*aLocalStorage = mLocalStorage); diff --git a/dom/indexedDB/CheckPermissionsHelper.cpp b/dom/indexedDB/CheckPermissionsHelper.cpp index d760db7467c4..1d0009c40097 100644 --- a/dom/indexedDB/CheckPermissionsHelper.cpp +++ b/dom/indexedDB/CheckPermissionsHelper.cpp @@ -7,6 +7,8 @@ #include "CheckPermissionsHelper.h" #include "nsIDOMWindow.h" +#include "nsILoadContext.h" +#include "nsIWebNavigation.h" #include "nsIObserverService.h" #include "nsIPermissionManager.h" #include "nsIPrincipal.h" @@ -56,7 +58,9 @@ GetIndexedDBPermissions(const nsACString& aASCIIOrigin, return nsIPermissionManager::ALLOW_ACTION; } - if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) { + nsCOMPtr webNav = do_GetInterface(aWindow); + nsCOMPtr loadContext = do_QueryInterface(webNav); + if (loadContext && loadContext->UsePrivateBrowsing()) { // TODO Support private browsing indexedDB? return nsIPermissionManager::DENY_ACTION; } diff --git a/dom/interfaces/storage/nsIDOMStorageManager.idl b/dom/interfaces/storage/nsIDOMStorageManager.idl index 5f8c205ef1f1..94b8789f5f06 100644 --- a/dom/interfaces/storage/nsIDOMStorageManager.idl +++ b/dom/interfaces/storage/nsIDOMStorageManager.idl @@ -8,7 +8,7 @@ interface nsIDOMStorage; interface nsIPrincipal; -[scriptable, uuid(fd91ec36-7da8-43bb-b8f2-4b57a862a467)] +[scriptable, uuid(1541da6c-a9fb-4a8f-af9d-4493c981491d)] interface nsIDOMStorageManager : nsISupports { /** @@ -33,5 +33,6 @@ interface nsIDOMStorageManager : nsISupports * for a single origin. */ nsIDOMStorage getLocalStorageForPrincipal(in nsIPrincipal aPrincipal, - in DOMString aDocumentURI); + in DOMString aDocumentURI, + [optional] in bool aPrivate); }; diff --git a/dom/interfaces/storage/nsPIDOMStorage.h b/dom/interfaces/storage/nsPIDOMStorage.h index 9880efc33496..fabb5ccdd739 100644 --- a/dom/interfaces/storage/nsPIDOMStorage.h +++ b/dom/interfaces/storage/nsPIDOMStorage.h @@ -29,8 +29,10 @@ public: SessionStorage = 2 } nsDOMStorageType; - virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) = 0; - virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) = 0; + virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate) = 0; + virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate) = 0; virtual already_AddRefed Clone() = 0; virtual already_AddRefed Fork(const nsSubstring &aDocumentURI) = 0; diff --git a/dom/src/storage/PStorage.ipdl b/dom/src/storage/PStorage.ipdl index 1145f62d5fb5..9fa6b507ce12 100644 --- a/dom/src/storage/PStorage.ipdl +++ b/dom/src/storage/PStorage.ipdl @@ -35,8 +35,8 @@ sync protocol PStorage parent: __delete__(); - Init(bool useDB, bool canUseChromePersist, bool sessionOnly, nsCString domain, - nsCString scopeDBKey, nsCString quotaDomainDBKey, + Init(bool useDB, bool canUseChromePersist, bool sessionOnly, bool isPrivate, + nsCString domain, nsCString scopeDBKey, nsCString quotaDomainDBKey, nsCString quotaETLDplus1DomainDBKey, PRUint32 storageType); sync GetKeys(bool callerSecure) @@ -60,6 +60,8 @@ parent: returns (nsresult rv); sync SetSecure(nsString key, bool secure) returns (nsresult rv); + + UpdatePrivateState(bool enabled); }; } diff --git a/dom/src/storage/StorageChild.cpp b/dom/src/storage/StorageChild.cpp index 207c97be6c4b..41cc7bdf9cfa 100644 --- a/dom/src/storage/StorageChild.cpp +++ b/dom/src/storage/StorageChild.cpp @@ -15,7 +15,9 @@ NS_IMPL_CYCLE_COLLECTION_1(StorageChild, mStorage) NS_IMPL_CYCLE_COLLECTING_ADDREF(StorageChild) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StorageChild) - NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY(nsIPrivacyTransitionObserver) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrivacyTransitionObserver) NS_INTERFACE_MAP_END NS_IMETHODIMP_(nsrefcnt) StorageChild::Release(void) @@ -79,21 +81,21 @@ StorageChild::InitRemote() ContentChild* child = ContentChild::GetSingleton(); AddIPDLReference(); child->SendPStorageConstructor(this, null_t()); - SendInit(mUseDB, mCanUseChromePersist, mSessionOnly, mDomain, mScopeDBKey, + SendInit(mUseDB, mCanUseChromePersist, mSessionOnly, mInPrivateBrowsing, mDomain, mScopeDBKey, mQuotaDomainDBKey, mQuotaETLDplus1DomainDBKey, mStorageType); } void -StorageChild::InitAsSessionStorage(nsIURI* aDomainURI) +StorageChild::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate) { - DOMStorageBase::InitAsSessionStorage(aDomainURI); + DOMStorageBase::InitAsSessionStorage(aDomainURI, aPrivate); InitRemote(); } void -StorageChild::InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist) +StorageChild::InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate) { - DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist); + DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist, aPrivate); InitRemote(); } @@ -234,8 +236,16 @@ StorageChild::CloneFrom(bool aCallerSecure, DOMStorageBase* aThat) StorageClone clone(nsnull, other, aCallerSecure); AddIPDLReference(); child->SendPStorageConstructor(this, clone); - SendInit(mUseDB, mCanUseChromePersist, mSessionOnly, mDomain, mScopeDBKey, - mQuotaDomainDBKey, mQuotaETLDplus1DomainDBKey, mStorageType); + SendInit(mUseDB, mCanUseChromePersist, mSessionOnly, mInPrivateBrowsing, mDomain, + mScopeDBKey, mQuotaDomainDBKey, mQuotaETLDplus1DomainDBKey, mStorageType); + return NS_OK; +} + +NS_IMETHODIMP +StorageChild::PrivateModeChanged(bool enabled) +{ + mInPrivateBrowsing = enabled; + SendUpdatePrivateState(enabled); return NS_OK; } diff --git a/dom/src/storage/StorageChild.h b/dom/src/storage/StorageChild.h index 2547e9aa117c..db941b705c91 100644 --- a/dom/src/storage/StorageChild.h +++ b/dom/src/storage/StorageChild.h @@ -16,16 +16,18 @@ namespace dom { class StorageChild : public PStorageChild , public DOMStorageBase + , public nsSupportsWeakReference { public: - NS_DECL_CYCLE_COLLECTION_CLASS(StorageChild) + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(StorageChild, nsIPrivacyTransitionObserver) NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_NSIPRIVACYTRANSITIONOBSERVER StorageChild(nsDOMStorage* aOwner); StorageChild(nsDOMStorage* aOwner, StorageChild& aOther); - virtual void InitAsSessionStorage(nsIURI* aDomainURI); - virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist); + virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate); + virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate); virtual bool CacheStoragePermissions(); diff --git a/dom/src/storage/StorageParent.cpp b/dom/src/storage/StorageParent.cpp index f5e68ab51319..624a79602ed7 100644 --- a/dom/src/storage/StorageParent.cpp +++ b/dom/src/storage/StorageParent.cpp @@ -30,18 +30,26 @@ bool StorageParent::RecvInit(const bool& aUseDB, const bool& aCanUseChromePersist, const bool& aSessionOnly, + const bool& aPrivate, const nsCString& aDomain, const nsCString& aScopeDBKey, const nsCString& aQuotaDomainDBKey, const nsCString& aQuotaETLDplus1DomainDBKey, const PRUint32& aStorageType) { - mStorage->InitFromChild(aUseDB, aCanUseChromePersist, aSessionOnly, aDomain, + mStorage->InitFromChild(aUseDB, aCanUseChromePersist, aSessionOnly, aPrivate, aDomain, aScopeDBKey, aQuotaDomainDBKey, aQuotaETLDplus1DomainDBKey, aStorageType); return true; } +bool +StorageParent::RecvUpdatePrivateState(const bool& aEnabled) +{ + mStorage->PrivateModeChanged(aEnabled); + return true; +} + bool StorageParent::RecvGetKeys(const bool& aCallerSecure, InfallibleTArray* aKeys) { diff --git a/dom/src/storage/StorageParent.h b/dom/src/storage/StorageParent.h index 6ec8a1c7d5b8..1962e85b4e60 100644 --- a/dom/src/storage/StorageParent.h +++ b/dom/src/storage/StorageParent.h @@ -45,12 +45,15 @@ private: bool RecvInit(const bool& aUseDB, const bool& aCanUseChromePersist, const bool& aSessionOnly, + const bool& aPrivate, const nsCString& aDomain, const nsCString& aScopeDBKey, const nsCString& aQuotaDomainDBKey, const nsCString& aQuotaETLDplus1DomainDBKey, const PRUint32& aStorageType); + bool RecvUpdatePrivateState(const bool& aEnabled); + nsRefPtr mStorage; }; diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index 24f338babd74..4652ddc6e5c4 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -5,8 +5,10 @@ #include "StorageChild.h" #include "StorageParent.h" +#include "mozilla/dom/ContentChild.h" #include "nsXULAppAPI.h" using mozilla::dom::StorageChild; +using mozilla::dom::ContentChild; #include "prnetdb.h" #include "nsCOMPtr.h" @@ -219,7 +221,6 @@ nsSessionStorageEntry::~nsSessionStorageEntry() nsDOMStorageManager* nsDOMStorageManager::gStorageManager; nsDOMStorageManager::nsDOMStorageManager() - : mInPrivateBrowsing(false) { } @@ -252,8 +253,6 @@ nsDOMStorageManager::Initialize() NS_ENSURE_SUCCESS(rv, rv); rv = os->AddObserver(gStorageManager, "offline-app-removed", true); NS_ENSURE_SUCCESS(rv, rv); - rv = os->AddObserver(gStorageManager, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true); - NS_ENSURE_SUCCESS(rv, rv); rv = os->AddObserver(gStorageManager, "profile-after-change", true); NS_ENSURE_SUCCESS(rv, rv); rv = os->AddObserver(gStorageManager, "perm-changed", true); @@ -265,6 +264,8 @@ nsDOMStorageManager::Initialize() NS_ENSURE_SUCCESS(rv, rv); rv = os->AddObserver(gStorageManager, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC, true); NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, "last-pb-context-exited", true); + NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } @@ -361,10 +362,6 @@ nsDOMStorageManager::Observe(nsISupports *aSubject, const PRUnichar *aData) { if (!strcmp(aTopic, "profile-after-change")) { - nsCOMPtr pbs = - do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID); - if (pbs) - pbs->GetPrivateBrowsingEnabled(&gStorageManager->mInPrivateBrowsing); } else if (!strcmp(aTopic, "offline-app-removed")) { nsresult rv = DOMStorageImpl::InitDB(); @@ -383,16 +380,6 @@ nsDOMStorageManager::Observe(nsISupports *aSubject, rv = GetOfflineDomains(domains); NS_ENSURE_SUCCESS(rv, rv); return DOMStorageImpl::gStorageDB->RemoveOwners(domains, true, false); - } else if (!strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC)) { - mStorages.EnumerateEntries(ClearStorage, nsnull); - if (!nsCRT::strcmp(aData, NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).get())) - mInPrivateBrowsing = true; - else if (!nsCRT::strcmp(aData, NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).get())) - mInPrivateBrowsing = false; - nsresult rv = DOMStorageImpl::InitDB(); - NS_ENSURE_SUCCESS(rv, rv); - - return DOMStorageImpl::gStorageDB->DropPrivateBrowsingStorages(); } else if (!strcmp(aTopic, "perm-changed")) { // Check for cookie permission change nsCOMPtr perm(do_QueryInterface(aSubject)); @@ -471,6 +458,10 @@ nsDOMStorageManager::Observe(nsISupports *aSubject, NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "DOMStorage: temporary table commit failed"); } + } else if (!strcmp(aTopic, "last-pb-context-exited")) { + if (DOMStorageImpl::gStorageDB) { + return DOMStorageImpl::gStorageDB->DropPrivateBrowsingStorages(); + } } return NS_OK; @@ -484,7 +475,7 @@ nsDOMStorageManager::GetUsage(const nsAString& aDomain, NS_ENSURE_SUCCESS(rv, rv); return DOMStorageImpl::gStorageDB->GetUsage(NS_ConvertUTF16toUTF8(aDomain), - false, aUsage); + false, aUsage, false); } NS_IMETHODIMP @@ -502,6 +493,7 @@ nsDOMStorageManager::ClearOfflineApps() NS_IMETHODIMP nsDOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate, nsIDOMStorage **aResult) { NS_ENSURE_ARG_POINTER(aPrincipal); @@ -513,7 +505,7 @@ nsDOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal *aPrincipal, if (!storage) return NS_ERROR_OUT_OF_MEMORY; - rv = storage->InitAsLocalStorage(aPrincipal, aDocumentURI); + rv = storage->InitAsLocalStorage(aPrincipal, aDocumentURI, aPrivate); if (NS_FAILED(rv)) return rv; @@ -570,9 +562,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStorage) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorageObsolete) NS_INTERFACE_MAP_ENTRY(nsIDOMStorageObsolete) NS_INTERFACE_MAP_ENTRY(nsPIDOMStorage) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageObsolete) NS_INTERFACE_MAP_END +NS_IMETHODIMP +nsDOMStorage::GetInterface(const nsIID & aIID, void **result) +{ + nsresult rv = mStorageImpl->QueryInterface(aIID, result); + if (NS_SUCCEEDED(rv)) + return rv; + return QueryInterface(aIID, result); +} + nsresult NS_NewDOMStorage2(nsISupports* aOuter, REFNSIID aIID, void** aResult) { @@ -585,6 +587,7 @@ DOMStorageBase::DOMStorageBase() , mUseDB(false) , mSessionOnly(true) , mCanUseChromePersist(false) + , mInPrivateBrowsing(false) { } @@ -597,11 +600,12 @@ DOMStorageBase::DOMStorageBase(DOMStorageBase& aThat) , mQuotaETLDplus1DomainDBKey(aThat.mQuotaETLDplus1DomainDBKey) , mQuotaDomainDBKey(aThat.mQuotaDomainDBKey) , mCanUseChromePersist(aThat.mCanUseChromePersist) + , mInPrivateBrowsing(aThat.mInPrivateBrowsing) { } void -DOMStorageBase::InitAsSessionStorage(nsIURI* aDomainURI) +DOMStorageBase::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate) { // No need to check for a return value. If this would fail we would not get // here as we call GetPrincipalURIAndHost (nsDOMStorage.cpp:88) from @@ -614,11 +618,13 @@ DOMStorageBase::InitAsSessionStorage(nsIURI* aDomainURI) mScopeDBKey.Truncate(); mQuotaDomainDBKey.Truncate(); mStorageType = nsPIDOMStorage::SessionStorage; + mInPrivateBrowsing = aPrivate; } void DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI, - bool aCanUseChromePersist) + bool aCanUseChromePersist, + bool aPrivate) { // No need to check for a return value. If this would fail we would not get // here as we call GetPrincipalURIAndHost (nsDOMStorage.cpp:88) from @@ -642,6 +648,7 @@ DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI, true, true, mQuotaETLDplus1DomainDBKey); mCanUseChromePersist = aCanUseChromePersist; mStorageType = nsPIDOMStorage::LocalStorage; + mInPrivateBrowsing = aPrivate; } PLDHashOperator @@ -667,7 +674,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMStorageImpl) NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMStorageImpl) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMStorageImpl) - NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY(nsIPrivacyTransitionObserver) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrivacyTransitionObserver) NS_INTERFACE_MAP_END DOMStorageImpl::DOMStorageImpl(nsDOMStorage* aStorage) @@ -723,7 +732,8 @@ DOMStorageImpl::InitDB() void DOMStorageImpl::InitFromChild(bool aUseDB, bool aCanUseChromePersist, - bool aSessionOnly, const nsACString& aDomain, + bool aSessionOnly, bool aPrivate, + const nsACString& aDomain, const nsACString& aScopeDBKey, const nsACString& aQuotaDomainDBKey, const nsACString& aQuotaETLDplus1DomainDBKey, @@ -732,6 +742,7 @@ DOMStorageImpl::InitFromChild(bool aUseDB, bool aCanUseChromePersist, mUseDB = aUseDB; mCanUseChromePersist = aCanUseChromePersist; mSessionOnly = aSessionOnly; + mInPrivateBrowsing = aPrivate; mDomain = aDomain; mScopeDBKey = aScopeDBKey; mQuotaDomainDBKey = aQuotaDomainDBKey; @@ -746,16 +757,17 @@ DOMStorageImpl::SetSessionOnly(bool aSessionOnly) } void -DOMStorageImpl::InitAsSessionStorage(nsIURI* aDomainURI) +DOMStorageImpl::InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate) { - DOMStorageBase::InitAsSessionStorage(aDomainURI); + DOMStorageBase::InitAsSessionStorage(aDomainURI, aPrivate); } void DOMStorageImpl::InitAsLocalStorage(nsIURI* aDomainURI, - bool aCanUseChromePersist) + bool aCanUseChromePersist, + bool aPrivate) { - DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist); + DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist, aPrivate); } bool @@ -765,7 +777,7 @@ DOMStorageImpl::CacheStoragePermissions() // All the correct checks have been done on the child, so we just need to // make sure that our session-only status is correctly updated. if (!mOwner) - return nsDOMStorage::CanUseStorage(&mSessionOnly); + return CanUseStorage(); return mOwner->CacheStoragePermissions(); } @@ -1255,6 +1267,16 @@ DOMStorageImpl::Clear(bool aCallerSecure, PRInt32* aOldCount) return NS_OK; } +NS_IMETHODIMP +DOMStorageImpl::PrivateModeChanged(bool enabled) +{ + mInPrivateBrowsing = enabled; + CanUseStorage(); // cause mSessionOnly to update as well + mItems.Clear(); + mItemsCachedVersion = 0; + return NS_OK; +} + nsDOMStorage::nsDOMStorage() : mStorageType(nsPIDOMStorage::Unknown) , mEventBroadcaster(nsnull) @@ -1313,7 +1335,8 @@ GetDomainURI(nsIPrincipal *aPrincipal, bool aIncludeDomain, nsIURI **_domain) } nsresult -nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) +nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate) { nsCOMPtr domainURI; nsresult rv = GetDomainURI(aPrincipal, true, getter_AddRefs(domainURI)); @@ -1324,12 +1347,13 @@ nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring & mStorageType = SessionStorage; - mStorageImpl->InitAsSessionStorage(domainURI); + mStorageImpl->InitAsSessionStorage(domainURI, aPrivate); return NS_OK; } nsresult -nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) +nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate) { nsCOMPtr domainURI; nsresult rv = GetDomainURI(aPrincipal, false, getter_AddRefs(domainURI)); @@ -1346,18 +1370,25 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aD canUseChromePersist = URICanUseChromePersist(URI); } - mStorageImpl->InitAsLocalStorage(domainURI, canUseChromePersist); + mStorageImpl->InitAsLocalStorage(domainURI, canUseChromePersist, aPrivate); return NS_OK; } +bool +DOMStorageBase::CanUseStorage() +{ + return nsDOMStorage::CanUseStorage(this); +} + //static bool -nsDOMStorage::CanUseStorage(bool* aSessionOnly) +nsDOMStorage::CanUseStorage(DOMStorageBase* aStorage /* = NULL */) { - // check if the calling domain can use storage. Downgrade to session - // only if only session storage may be used. - NS_ASSERTION(aSessionOnly, "null session flag"); - *aSessionOnly = false; + if (aStorage) { + // check if the calling domain can use storage. Downgrade to session + // only if only session storage may be used. + aStorage->mSessionOnly = false; + } if (!Preferences::GetBool(kStorageEnabled)) { return false; @@ -1398,8 +1429,9 @@ nsDOMStorage::CanUseStorage(bool* aSessionOnly) // mode to prevent detection of being in private browsing mode and ensuring // that there will be no traces left. if (perm == nsICookiePermission::ACCESS_SESSION || - nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) { - *aSessionOnly = true; + (aStorage && aStorage->IsPrivate())) { + if (aStorage) + aStorage->mSessionOnly = true; } else if (perm != nsIPermissionManager::ALLOW_ACTION) { PRUint32 cookieBehavior = Preferences::GetUint(kCookiesBehavior); @@ -1411,8 +1443,8 @@ nsDOMStorage::CanUseStorage(bool* aSessionOnly) !URICanUseChromePersist(subjectURI)) return false; - if (lifetimePolicy == ACCEPT_SESSION) - *aSessionOnly = true; + if (lifetimePolicy == ACCEPT_SESSION && aStorage) + aStorage->mSessionOnly = true; } return true; @@ -1424,7 +1456,7 @@ nsDOMStorage::CacheStoragePermissions() // Bug 488446, disallowing storage use when in session only mode. // This is temporary fix before we find complete solution for storage // behavior in private browsing mode or session-only cookies mode. - if (!CanUseStorage(&mStorageImpl->mSessionOnly)) + if (!mStorageImpl->CanUseStorage()) return false; nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); @@ -1701,9 +1733,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStorage2) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorage) NS_INTERFACE_MAP_ENTRY(nsIDOMStorage) NS_INTERFACE_MAP_ENTRY(nsPIDOMStorage) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Storage) NS_INTERFACE_MAP_END +NS_IMETHODIMP +nsDOMStorage2::GetInterface(const nsIID & aIID, void **result) +{ + nsresult rv = mStorage->GetInterface(aIID, result); + if (NS_SUCCEEDED(rv)) + return rv; + return QueryInterface(aIID, result);; +} + nsDOMStorage2::nsDOMStorage2() { } @@ -1715,7 +1757,8 @@ nsDOMStorage2::nsDOMStorage2(nsDOMStorage2& aThat) } nsresult -nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) +nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate) { mStorage = new nsDOMStorage(); if (!mStorage) @@ -1724,11 +1767,12 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring mPrincipal = aPrincipal; mDocumentURI = aDocumentURI; - return mStorage->InitAsSessionStorage(aPrincipal, aDocumentURI); + return mStorage->InitAsSessionStorage(aPrincipal, aDocumentURI, aPrivate); } nsresult -nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) +nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate) { mStorage = new nsDOMStorage(); if (!mStorage) @@ -1737,7 +1781,7 @@ nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &a mPrincipal = aPrincipal; mDocumentURI = aDocumentURI; - return mStorage->InitAsLocalStorage(aPrincipal, aDocumentURI); + return mStorage->InitAsLocalStorage(aPrincipal, aDocumentURI, aPrivate); } already_AddRefed @@ -1907,7 +1951,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStorageItem) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStorageItem) { - cb.NoteXPCOMChild((nsISupports*) tmp->mStorage); + cb.NoteXPCOMChild(tmp->mStorage); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END diff --git a/dom/src/storage/nsDOMStorage.h b/dom/src/storage/nsDOMStorage.h index 0b3bcb79e6b3..bdc3529b8f5d 100644 --- a/dom/src/storage/nsDOMStorage.h +++ b/dom/src/storage/nsDOMStorage.h @@ -12,6 +12,7 @@ #include "nsIDOMStorage.h" #include "nsIDOMStorageItem.h" #include "nsIPermissionManager.h" +#include "nsIPrivacyTransitionObserver.h" #include "nsInterfaceHashtable.h" #include "nsVoidArray.h" #include "nsTArray.h" @@ -24,6 +25,7 @@ #include "nsIObserver.h" #include "nsITimer.h" #include "nsWeakReference.h" +#include "nsIInterfaceRequestor.h" #include "nsDOMStorageDBWrapper.h" @@ -87,8 +89,6 @@ public: nsresult ClearAllStorages(); - bool InPrivateBrowsingMode() { return mInPrivateBrowsing; } - static nsresult Initialize(); static nsDOMStorageManager* GetInstance(); static void Shutdown(); @@ -104,17 +104,16 @@ public: protected: nsTHashtable mStorages; - bool mInPrivateBrowsing; }; -class DOMStorageBase : public nsISupports +class DOMStorageBase : public nsIPrivacyTransitionObserver { public: DOMStorageBase(); DOMStorageBase(DOMStorageBase&); - virtual void InitAsSessionStorage(nsIURI* aDomainURI); - virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist); + virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate); + virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate); virtual nsTArray* GetKeys(bool aCallerSecure) = 0; virtual nsresult GetLength(bool aCallerSecure, PRUint32* aLength) = 0; @@ -126,7 +125,10 @@ public: virtual nsresult RemoveValue(bool aCallerSecure, const nsAString& aKey, nsAString& aOldValue) = 0; virtual nsresult Clear(bool aCallerSecure, PRInt32* aOldCount) = 0; - + + // Call nsDOMStorage::CanUseStorage with |this| + bool CanUseStorage(); + // If true, the contents of the storage should be stored in the // database, otherwise this storage should act like a session // storage. @@ -137,6 +139,10 @@ public: return mUseDB; } + bool IsPrivate() { + return mInPrivateBrowsing; + } + // retrieve the value and secure state corresponding to a key out of storage. virtual nsresult GetDBValue(const nsAString& aKey, @@ -198,21 +204,23 @@ protected: nsCString mQuotaDomainDBKey; bool mCanUseChromePersist; + bool mInPrivateBrowsing; }; class DOMStorageImpl : public DOMStorageBase - + , public nsSupportsWeakReference { public: - NS_DECL_CYCLE_COLLECTION_CLASS(DOMStorageImpl) + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DOMStorageImpl, nsIPrivacyTransitionObserver) NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_NSIPRIVACYTRANSITIONOBSERVER DOMStorageImpl(nsDOMStorage*); DOMStorageImpl(nsDOMStorage*, DOMStorageImpl&); ~DOMStorageImpl(); - virtual void InitAsSessionStorage(nsIURI* aDomainURI); - virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist); + virtual void InitAsSessionStorage(nsIURI* aDomainURI, bool aPrivate); + virtual void InitAsLocalStorage(nsIURI* aDomainURI, bool aCanUseChromePersist, bool aPrivate); bool SessionOnly() { return mSessionOnly; @@ -283,7 +291,7 @@ private: // Cross-process storage implementations never have InitAs(Session|Local|Global)Storage // called, so the appropriate initialization needs to happen from the child. void InitFromChild(bool aUseDB, bool aCanUseChromePersist, bool aSessionOnly, - const nsACString& aDomain, + bool aPrivate, const nsACString& aDomain, const nsACString& aScopeDBKey, const nsACString& aQuotaDomainDBKey, const nsACString& aQuotaETLDplus1DomainDBKey, @@ -306,7 +314,8 @@ private: class nsDOMStorage2; class nsDOMStorage : public nsIDOMStorageObsolete, - public nsPIDOMStorage + public nsPIDOMStorage, + public nsIInterfaceRequestor { public: nsDOMStorage(); @@ -317,14 +326,17 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMStorage, nsIDOMStorageObsolete) NS_DECL_NSIDOMSTORAGEOBSOLETE + NS_DECL_NSIINTERFACEREQUESTOR // Helpers for implementing nsIDOMStorage nsresult GetItem(const nsAString& key, nsAString& aData); nsresult Clear(); // nsPIDOMStorage - virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI); - virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI); + virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate); + virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate); virtual already_AddRefed Clone(); virtual already_AddRefed Fork(const nsSubstring &aDocumentURI); virtual bool IsForkOf(nsIDOMStorage* aThat); @@ -336,7 +348,7 @@ public: // Check whether storage may be used by the caller, and whether it // is session only. Returns true if storage may be used. static bool - CanUseStorage(bool* aSessionOnly); + CanUseStorage(DOMStorageBase* aStorage = nsnull); // Check whether this URI can use chrome persist storage. This kind of // storage can bypass cookies limits, private browsing and uses the offline @@ -381,7 +393,8 @@ public: }; class nsDOMStorage2 : public nsIDOMStorage, - public nsPIDOMStorage + public nsPIDOMStorage, + public nsIInterfaceRequestor { public: // nsISupports @@ -392,10 +405,13 @@ public: nsDOMStorage2(); NS_DECL_NSIDOMSTORAGE + NS_DECL_NSIINTERFACEREQUESTOR // nsPIDOMStorage - virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI); - virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI); + virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate); + virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, + bool aPrivate); virtual already_AddRefed Clone(); virtual already_AddRefed Fork(const nsSubstring &aDocumentURI); virtual bool IsForkOf(nsIDOMStorage* aThat); diff --git a/dom/src/storage/nsDOMStorageDBWrapper.cpp b/dom/src/storage/nsDOMStorageDBWrapper.cpp index 1fdc5ff9c729..25af0ddd44e5 100644 --- a/dom/src/storage/nsDOMStorageDBWrapper.cpp +++ b/dom/src/storage/nsDOMStorageDBWrapper.cpp @@ -90,7 +90,7 @@ nsDOMStorageDBWrapper::FlushAndDeleteTemporaryTables(bool force) PR_BEGIN_MACRO \ if (aStorage->CanUseChromePersist()) \ _return mChromePersistentDB._code; \ - if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) \ + if (aStorage->IsPrivate()) \ _return mPrivateBrowsingDB._code; \ if (aStorage->SessionOnly()) \ _return mSessionOnlyDB._code; \ @@ -188,9 +188,6 @@ nsDOMStorageDBWrapper::RemoveOwner(const nsACString& aOwner, rv = mPrivateBrowsingDB.RemoveOwner(aOwner, aIncludeSubDomains); NS_ENSURE_SUCCESS(rv, rv); - if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) - return NS_OK; - rv = mSessionOnlyDB.RemoveOwner(aOwner, aIncludeSubDomains); NS_ENSURE_SUCCESS(rv, rv); @@ -210,9 +207,6 @@ nsDOMStorageDBWrapper::RemoveOwners(const nsTArray &aOwners, rv = mPrivateBrowsingDB.RemoveOwners(aOwners, aIncludeSubDomains, aMatch); NS_ENSURE_SUCCESS(rv, rv); - if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) - return NS_OK; - rv = mSessionOnlyDB.RemoveOwners(aOwners, aIncludeSubDomains, aMatch); NS_ENSURE_SUCCESS(rv, rv); @@ -222,26 +216,6 @@ nsDOMStorageDBWrapper::RemoveOwners(const nsTArray &aOwners, return rv; } -nsresult -nsDOMStorageDBWrapper::RemoveAll() -{ - nsresult rv; - - rv = mPrivateBrowsingDB.RemoveAll(); - NS_ENSURE_SUCCESS(rv, rv); - - if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) - return NS_OK; - - rv = mSessionOnlyDB.RemoveAll(); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mPersistentDB.RemoveAll(); - NS_ENSURE_SUCCESS(rv, rv); - - return rv; -} - nsresult nsDOMStorageDBWrapper::GetUsage(DOMStorageImpl* aStorage, bool aExcludeOfflineFromUsage, PRInt32 *aUsage) @@ -251,9 +225,9 @@ nsDOMStorageDBWrapper::GetUsage(DOMStorageImpl* aStorage, nsresult nsDOMStorageDBWrapper::GetUsage(const nsACString& aDomain, - bool aIncludeSubDomains, PRInt32 *aUsage) + bool aIncludeSubDomains, PRInt32 *aUsage, bool aPrivate) { - if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) + if (aPrivate) return mPrivateBrowsingDB.GetUsage(aDomain, aIncludeSubDomains, aUsage); #if 0 diff --git a/dom/src/storage/nsDOMStorageDBWrapper.h b/dom/src/storage/nsDOMStorageDBWrapper.h index 34377fdd50fa..fdfcb6412edb 100644 --- a/dom/src/storage/nsDOMStorageDBWrapper.h +++ b/dom/src/storage/nsDOMStorageDBWrapper.h @@ -144,12 +144,6 @@ public: RemoveOwners(const nsTArray& aOwners, bool aIncludeSubDomains, bool aMatch); - /** - * Removes all keys from storage. Used when clearing storage. - */ - nsresult - RemoveAll(); - /** * Returns usage for a storage using its GetQuotaDomainDBKey() as a key. */ @@ -160,7 +154,7 @@ public: * Returns usage of the domain and optionaly by any subdomain. */ nsresult - GetUsage(const nsACString& aDomain, bool aIncludeSubDomains, PRInt32 *aUsage); + GetUsage(const nsACString& aDomain, bool aIncludeSubDomains, PRInt32 *aUsage, bool aPrivate); /** * Marks the storage as "cached" after the DOMStorageImpl object has loaded