Bug 916781 - DOM storage instances across managers must not share single eTLD+1 limit check, r=smaug

This commit is contained in:
Honza Bambas 2013-10-07 16:12:20 +02:00
parent 7c5b6ad83d
commit 3cc47ba520
7 changed files with 57 additions and 42 deletions

View File

@ -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)

View File

@ -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<DOMStorageManager> mManager;
// Reference to the usage counter object we check on for eTLD+1 quota limit.
// Obtained from the manager during initialization (Init method).
nsRefPtr<DOMStorageUsage> mUsage;
// Timer that holds this cache alive for a while after it has been preloaded.
nsCOMPtr<nsITimer> 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

View File

@ -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)

View File

@ -81,13 +81,6 @@ public:
// Get the complete list of scopes having data
virtual void GetScopesHavingData(InfallibleTArray<nsCString>* 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<nsCStringHashKey, DOMStorageUsage> mUsages;
};
// The implementation of the the database engine, this directly works
@ -157,7 +150,7 @@ public:
friend class PendingOperations;
OperationType mType;
nsRefPtr<DOMStorageCacheBridge> mCache;
DOMStorageUsageBridge* mUsage;
nsRefPtr<DOMStorageUsageBridge> mUsage;
nsString mKey;
nsString mValue;
nsCString mScope;

View File

@ -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<DOMStorageUsageBridge> 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<UsageParentBridge> usage = new UsageParentBridge(this, aScope);
db->AsyncGetUsage(usage);
return true;
}
@ -733,7 +728,6 @@ DOMStorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage)
{
nsRefPtr<UsageRunnable> r = new UsageRunnable(mParent, mScope, aUsage);
NS_DispatchToMainThread(r);
delete this;
}
} // ::dom

View File

@ -269,6 +269,28 @@ DOMStorageManager::GetCache(const nsACString& aScope) const
return entry->cache();
}
already_AddRefed<DOMStorageUsage>
DOMStorageManager::GetScopeUsage(const nsACString& aScope)
{
nsRefPtr<DOMStorageUsage> 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<DOMStorageCache>
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:

View File

@ -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<DOMStorageUsage> 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<nsCStringHashKey, nsRefPtr<DOMStorageUsage> > mUsages;
friend class DOMStorageCache;
// Releases cache since it is no longer referrered by any DOMStorage object.
virtual void DropCache(DOMStorageCache* aCache);