diff --git a/dom/src/storage/DOMStorageCache.cpp b/dom/src/storage/DOMStorageCache.cpp index 813e2a6fac5b..cf24b61abdb8 100644 --- a/dom/src/storage/DOMStorageCache.cpp +++ b/dom/src/storage/DOMStorageCache.cpp @@ -75,12 +75,12 @@ NS_IMETHODIMP_(void) DOMStorageCacheBridge::Release(void) // DOMStorageCache DOMStorageCache::DOMStorageCache(const nsACString* aScope) -: mManager(nullptr) -, mScope(*aScope) +: mScope(*aScope) , mMonitor("DOMStorageCache") , mLoaded(false) , mLoadResult(NS_OK) , mInitialized(false) +, mPersistent(false) , mSessionOnlyDataSetActive(false) , mPreloadTelemetryRecorded(false) { @@ -128,15 +128,17 @@ DOMStorageCache::Init(DOMStorageManager* aManager, return; } - mManager = aManager; mInitialized = true; mPrincipal = aPrincipal; mPersistent = aPersistent; mQuotaScope = aQuotaScope.IsEmpty() ? mScope : aQuotaScope; if (mPersistent) { + mManager = aManager; Preload(); } + + mUsage = aManager->GetScopeUsage(mQuotaScope); } inline bool @@ -208,12 +210,8 @@ DOMStorageCache::ProcessUsageDelta(uint32_t aGetDataSetIndex, const int64_t aDel } // Now check eTLD+1 limit - GetDatabase(); - if (sDatabase) { - DOMStorageUsage* usage = sDatabase->GetScopeUsage(mQuotaScope); - if (!usage->CheckAndSetETLD1UsageDelta(aGetDataSetIndex, aDelta)) { - return false; - } + if (mUsage && !mUsage->CheckAndSetETLD1UsageDelta(aGetDataSetIndex, aDelta)) { + return false; } // Update size in our data set @@ -235,7 +233,6 @@ DOMStorageCache::Preload() } sDatabase->AsyncPreload(this); - sDatabase->GetScopeUsage(mQuotaScope); } namespace { // anon @@ -686,6 +683,11 @@ DOMStorageCache::LoadWait() } } +// DOMStorageUsageBridge + +NS_IMPL_ADDREF(DOMStorageUsageBridge) +NS_IMPL_RELEASE(DOMStorageUsageBridge) + // DOMStorageUsage DOMStorageUsage::DOMStorageUsage(const nsACString& aScope) diff --git a/dom/src/storage/DOMStorageCache.h b/dom/src/storage/DOMStorageCache.h index 5492ae3ec5ea..00714df2c0c0 100644 --- a/dom/src/storage/DOMStorageCache.h +++ b/dom/src/storage/DOMStorageCache.h @@ -20,6 +20,7 @@ namespace mozilla { namespace dom { class DOMStorage; +class DOMStorageUsage; class DOMStorageManager; class DOMStorageDBBridge; @@ -170,6 +171,10 @@ private: // Cache could potentially overlive the manager, hence the hard ref. nsRefPtr mManager; + // Reference to the usage counter object we check on for eTLD+1 quota limit. + // Obtained from the manager during initialization (Init method). + nsRefPtr mUsage; + // Timer that holds this cache alive for a while after it has been preloaded. nsCOMPtr mKeepAliveTimer; @@ -227,10 +232,17 @@ private: class DOMStorageUsageBridge { public: + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + virtual ~DOMStorageUsageBridge() {} virtual const nsCString& Scope() = 0; virtual void LoadUsage(const int64_t aUsage) = 0; + +protected: + ThreadSafeAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD }; class DOMStorageUsage : public DOMStorageUsageBridge diff --git a/dom/src/storage/DOMStorageDBThread.cpp b/dom/src/storage/DOMStorageDBThread.cpp index 3cdffa31bbbe..fec2f661f5a3 100644 --- a/dom/src/storage/DOMStorageDBThread.cpp +++ b/dom/src/storage/DOMStorageDBThread.cpp @@ -37,21 +37,6 @@ DOMStorageDBBridge::DOMStorageDBBridge() { } -DOMStorageUsage* -DOMStorageDBBridge::GetScopeUsage(const nsACString& aScope) -{ - DOMStorageUsage* usage; - if (mUsages.Get(aScope, &usage)) { - return usage; - } - - usage = new DOMStorageUsage(aScope); - AsyncGetUsage(usage); - mUsages.Put(aScope, usage); - - return usage; -} - DOMStorageDBThread::DOMStorageDBThread() : mThread(nullptr) diff --git a/dom/src/storage/DOMStorageDBThread.h b/dom/src/storage/DOMStorageDBThread.h index 7e930c1e7ed0..ed517b57fc5b 100644 --- a/dom/src/storage/DOMStorageDBThread.h +++ b/dom/src/storage/DOMStorageDBThread.h @@ -81,13 +81,6 @@ public: // Get the complete list of scopes having data virtual void GetScopesHavingData(InfallibleTArray* aScopes) = 0; - - // Returns object keeping usage cache for the scope. - DOMStorageUsage* GetScopeUsage(const nsACString& aScope); - -protected: - // Keeps usage cache objects for eTLD+1 scopes we have touched. - nsClassHashtable mUsages; }; // The implementation of the the database engine, this directly works @@ -157,7 +150,7 @@ public: friend class PendingOperations; OperationType mType; nsRefPtr mCache; - DOMStorageUsageBridge* mUsage; + nsRefPtr mUsage; nsString mKey; nsString mValue; nsCString mScope; diff --git a/dom/src/storage/DOMStorageIPC.cpp b/dom/src/storage/DOMStorageIPC.cpp index 569a45d4773f..b64ec456dd41 100644 --- a/dom/src/storage/DOMStorageIPC.cpp +++ b/dom/src/storage/DOMStorageIPC.cpp @@ -253,12 +253,7 @@ DOMStorageDBChild::RecvLoadDone(const nsCString& aScope, const nsresult& aRv) bool DOMStorageDBChild::RecvLoadUsage(const nsCString& aScope, const int64_t& aUsage) { - DOMStorageDBBridge* db = DOMStorageCache::GetDatabase(); - if (!db) { - return false; - } - - DOMStorageUsageBridge* scopeUsage = db->GetScopeUsage(aScope); + nsRefPtr scopeUsage = mManager->GetScopeUsage(aScope); scopeUsage->LoadUsage(aUsage); return true; } @@ -404,7 +399,7 @@ DOMStorageDBParent::RecvAsyncGetUsage(const nsCString& aScope) } // The object releases it self in LoadUsage method - UsageParentBridge* usage = new UsageParentBridge(this, aScope); + nsRefPtr usage = new UsageParentBridge(this, aScope); db->AsyncGetUsage(usage); return true; } @@ -733,7 +728,6 @@ DOMStorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage) { nsRefPtr r = new UsageRunnable(mParent, mScope, aUsage); NS_DispatchToMainThread(r); - delete this; } } // ::dom diff --git a/dom/src/storage/DOMStorageManager.cpp b/dom/src/storage/DOMStorageManager.cpp index d8da757b9438..0ba950ba5d6e 100644 --- a/dom/src/storage/DOMStorageManager.cpp +++ b/dom/src/storage/DOMStorageManager.cpp @@ -269,6 +269,28 @@ DOMStorageManager::GetCache(const nsACString& aScope) const return entry->cache(); } +already_AddRefed +DOMStorageManager::GetScopeUsage(const nsACString& aScope) +{ + nsRefPtr usage; + if (mUsages.Get(aScope, &usage)) { + return usage.forget(); + } + + usage = new DOMStorageUsage(aScope); + + if (mType == LocalStorage) { + DOMStorageDBBridge* db = DOMStorageCache::StartDatabase(); + if (db) { + db->AsyncGetUsage(usage); + } + } + + mUsages.Put(aScope, usage); + + return usage.forget(); +} + already_AddRefed DOMStorageManager::PutCache(const nsACString& aScope, nsIPrincipal* aPrincipal) @@ -283,7 +305,7 @@ DOMStorageManager::PutCache(const nsACString& aScope, case SessionStorage: // Lifetime handled by the manager, don't persist entry->HardRef(); - cache->Init(nullptr, false, aPrincipal, quotaScope); + cache->Init(this, false, aPrincipal, quotaScope); break; case LocalStorage: diff --git a/dom/src/storage/DOMStorageManager.h b/dom/src/storage/DOMStorageManager.h index f6c3ee9819f4..36477d45e35b 100644 --- a/dom/src/storage/DOMStorageManager.h +++ b/dom/src/storage/DOMStorageManager.h @@ -13,6 +13,8 @@ #include "DOMStorageCache.h" #include "nsTHashtable.h" +#include "nsDataHashtable.h" +#include "nsHashKeys.h" namespace mozilla { namespace dom { @@ -35,6 +37,8 @@ public: static uint32_t GetQuota(); // Gets (but not ensures) cache for the given scope DOMStorageCache* GetCache(const nsACString& aScope) const; + // Returns object keeping usage cache for the scope. + already_AddRefed GetScopeUsage(const nsACString& aScope); protected: DOMStorageManager(nsPIDOMStorage::StorageType aType); @@ -97,6 +101,9 @@ private: void* aClosure); protected: + // Keeps usage cache objects for eTLD+1 scopes we have touched. + nsDataHashtable > mUsages; + friend class DOMStorageCache; // Releases cache since it is no longer referrered by any DOMStorage object. virtual void DropCache(DOMStorageCache* aCache);