Bug 961049 - Part 6: Quota Manager on PBackground cache changes; r=bkelly

This commit is contained in:
Jan Varga 2015-11-22 10:44:16 +01:00
parent e3138fe488
commit 34263265f8
11 changed files with 209 additions and 231 deletions

121
dom/cache/Context.cpp vendored
View File

@ -132,7 +132,7 @@ public:
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_INIT);
mState = STATE_OPEN_DIRECTORY;
mState = STATE_GET_INFO;
nsresult rv = NS_DispatchToMainThread(this, nsIThread::DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
mState = STATE_COMPLETE;
@ -149,6 +149,8 @@ public:
mInitAction->CancelOnInitiatingThread();
}
void OpenDirectory();
// OpenDirectoryListener methods
virtual void
DirectoryLockAcquired(DirectoryLock* aLock) override;
@ -195,6 +197,8 @@ private:
enum State
{
STATE_INIT,
STATE_GET_INFO,
STATE_CREATE_QUOTA_MANAGER,
STATE_OPEN_DIRECTORY,
STATE_WAIT_FOR_DIRECTORY_LOCK,
STATE_ENSURE_ORIGIN_INITIALIZED,
@ -234,7 +238,7 @@ private:
nsCOMPtr<nsIThread> mInitiatingThread;
nsresult mResult;
QuotaInfo mQuotaInfo;
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock;
RefPtr<DirectoryLock> mDirectoryLock;
State mState;
Atomic<bool> mCanceled;
@ -243,14 +247,35 @@ public:
NS_DECL_NSIRUNNABLE
};
void
Context::QuotaInitRunnable::OpenDirectory()
{
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_CREATE_QUOTA_MANAGER ||
mState == STATE_OPEN_DIRECTORY);
MOZ_ASSERT(QuotaManager::Get());
// QuotaManager::OpenDirectory() will hold a reference to us as
// a listener. We will then get DirectoryLockAcquired() on the owning
// thread when it is safe to access our storage directory.
mState = STATE_WAIT_FOR_DIRECTORY_LOCK;
QuotaManager::Get()->OpenDirectory(PERSISTENCE_TYPE_DEFAULT,
mQuotaInfo.mGroup,
mQuotaInfo.mOrigin,
mQuotaInfo.mIsApp,
quota::Client::DOMCACHE,
/* aExclusive */ false,
this);
}
void
Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_ASSERT(!mDirectoryLock);
mDirectoryLock = new nsMainThreadPtrHolder<DirectoryLock>(aLock);
mDirectoryLock = aLock;
if (mCanceled) {
Complete(NS_ERROR_ABORT);
@ -271,7 +296,7 @@ Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
void
Context::QuotaInitRunnable::DirectoryLockFailed()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_ASSERT(!mDirectoryLock);
@ -290,13 +315,23 @@ NS_IMPL_ISUPPORTS(mozilla::dom::cache::Context::QuotaInitRunnable, nsIRunnable);
// +-------+-------+ |
// | |
// +----------v-----------+ |
// | OpenDirectory | Resolve(error) |
// | GetInfo | Resolve(error) |
// | (Main Thread) +-----------------+
// +----------+-----------+ |
// | |
// +----------v-----------+ |
// | CreateQuotaManager | Resolve(error) |
// | (Orig Thread) +-----------------+
// +----------+-----------+ |
// | |
// +----------v-----------+ |
// | OpenDirectory | Resolve(error) |
// | (Orig Thread) +-----------------+
// +----------+-----------+ |
// | |
// +----------v-----------+ |
// | WaitForDirectoryLock | Resolve(error) |
// | (Main Thread) +-----------------+
// | (Orig Thread) +-----------------+
// +----------+-----------+ |
// | |
// +----------v------------+ |
@ -330,43 +365,61 @@ Context::QuotaInitRunnable::Run()
switch(mState) {
// -----------------------------------
case STATE_OPEN_DIRECTORY:
case STATE_GET_INFO:
{
MOZ_ASSERT(NS_IsMainThread());
if (mCanceled) {
resolver->Resolve(NS_ERROR_ABORT);
break;
}
RefPtr<ManagerId> managerId = mManager->GetManagerId();
nsCOMPtr<nsIPrincipal> principal = managerId->Principal();
nsresult rv = QuotaManager::GetInfoFromPrincipal(principal,
&mQuotaInfo.mGroup,
&mQuotaInfo.mOrigin,
&mQuotaInfo.mIsApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
resolver->Resolve(rv);
break;
}
mState = STATE_CREATE_QUOTA_MANAGER;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
mInitiatingThread->Dispatch(this, nsIThread::DISPATCH_NORMAL)));
break;
}
// ----------------------------------
case STATE_CREATE_QUOTA_MANAGER:
{
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
if (mCanceled || QuotaManager::IsShuttingDown()) {
resolver->Resolve(NS_ERROR_ABORT);
break;
}
QuotaManager* qm = QuotaManager::GetOrCreate();
if (!qm) {
if (QuotaManager::Get()) {
OpenDirectory();
return NS_OK;
}
mState = STATE_OPEN_DIRECTORY;
QuotaManager::GetOrCreate(this);
break;
}
// ----------------------------------
case STATE_OPEN_DIRECTORY:
{
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
if (NS_WARN_IF(!QuotaManager::Get())) {
resolver->Resolve(NS_ERROR_FAILURE);
break;
}
RefPtr<ManagerId> managerId = mManager->GetManagerId();
nsCOMPtr<nsIPrincipal> principal = managerId->Principal();
nsresult rv = qm->GetInfoFromPrincipal(principal,
&mQuotaInfo.mGroup,
&mQuotaInfo.mOrigin,
&mQuotaInfo.mIsApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
resolver->Resolve(rv);
break;
}
// QuotaManager::OpenDirectory() will hold a reference to us as
// a listener. We will then get DirectoryLockAcquired() on the main
// thread when it is safe to access our storage directory.
mState = STATE_WAIT_FOR_DIRECTORY_LOCK;
qm->OpenDirectory(PERSISTENCE_TYPE_DEFAULT,
mQuotaInfo.mGroup,
mQuotaInfo.mOrigin,
mQuotaInfo.mIsApp,
quota::Client::DOMCACHE,
/* aExclusive */ false,
this);
OpenDirectory();
break;
}
// ----------------------------------
@ -425,7 +478,7 @@ Context::QuotaInitRunnable::Run()
{
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
mInitAction->CompleteOnInitiatingThread(mResult);
mContext->OnQuotaInit(mResult, mQuotaInfo, mDirectoryLock);
mContext->OnQuotaInit(mResult, mQuotaInfo, mDirectoryLock.forget());
mState = STATE_COMPLETE;
// Explicitly cleanup here as the destructor could fire on any of
@ -987,7 +1040,7 @@ Context::DispatchAction(Action* aAction, bool aDoomData)
void
Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock)
already_AddRefed<DirectoryLock> aDirectoryLock)
{
NS_ASSERT_OWNINGTHREAD(Context);

5
dom/cache/Context.h vendored
View File

@ -190,7 +190,8 @@ private:
void Start();
void DispatchAction(Action* aAction, bool aDoomData = false);
void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock);
already_AddRefed<DirectoryLock> aDirectoryLock);
already_AddRefed<ThreadsafeHandle>
CreateThreadsafeHandle();
@ -221,7 +222,7 @@ private:
// when ThreadsafeHandle::AllowToClose() is called.
RefPtr<ThreadsafeHandle> mThreadsafeHandle;
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock;
RefPtr<DirectoryLock> mDirectoryLock;
RefPtr<Context> mNextContext;
public:

208
dom/cache/Manager.cpp vendored
View File

@ -242,55 +242,61 @@ public:
}
static void
StartAbortOnMainThread(const nsACString& aOrigin)
Abort(const nsACString& aOrigin)
{
MOZ_ASSERT(NS_IsMainThread());
mozilla::ipc::AssertIsOnBackgroundThread();
// Lock for sBackgroundThread.
StaticMutexAutoLock lock(sMutex);
if (!sBackgroundThread) {
if (!sFactory) {
return;
}
// Guaranteed to succeed because we should get abort only before the
// background thread is destroyed.
nsCOMPtr<nsIRunnable> runnable = new AbortRunnable(aOrigin);
nsresult rv = sBackgroundThread->Dispatch(runnable,
nsIThread::DISPATCH_NORMAL);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
{
ManagerList::ForwardIterator iter(sFactory->mManagerList);
while (iter.HasMore()) {
RefPtr<Manager> manager = iter.GetNext();
if (aOrigin.IsVoid() ||
manager->mManagerId->QuotaOrigin() == aOrigin) {
manager->Abort();
}
}
}
}
static void
StartShutdownAllOnMainThread()
ShutdownAll()
{
MOZ_ASSERT(NS_IsMainThread());
mozilla::ipc::AssertIsOnBackgroundThread();
// Lock for sFactoryShutdown and sBackgroundThread.
StaticMutexAutoLock lock(sMutex);
sFactoryShutdown = true;
if (!sBackgroundThread) {
if (!sFactory) {
return;
}
// Guaranteed to succeed because we should be shutdown before the
// background thread is destroyed.
nsCOMPtr<nsIRunnable> runnable = new ShutdownAllRunnable();
nsresult rv = sBackgroundThread->Dispatch(runnable,
nsIThread::DISPATCH_NORMAL);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
{
// Note that we are synchronously calling shutdown code here. If any
// of the shutdown code synchronously decides to delete the Factory
// we need to delay that delete until the end of this method.
AutoRestore<bool> restore(sFactory->mInSyncShutdown);
sFactory->mInSyncShutdown = true;
ManagerList::ForwardIterator iter(sFactory->mManagerList);
while (iter.HasMore()) {
RefPtr<Manager> manager = iter.GetNext();
manager->Shutdown();
}
}
MaybeDestroyInstance();
}
static bool
IsShutdownAllCompleteOnMainThread()
IsShutdownAllComplete()
{
MOZ_ASSERT(NS_IsMainThread());
StaticMutexAutoLock lock(sMutex);
// Infer whether we have shutdown using the sBackgroundThread value. We
// guarantee this is nullptr when sFactory is destroyed.
return sFactoryShutdown && !sBackgroundThread;
mozilla::ipc::AssertIsOnBackgroundThread();
return !sFactory;
}
private:
@ -322,12 +328,6 @@ private:
if (sFactoryShutdown) {
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
}
// Cannot use ClearOnShutdown() because we're on the background thread.
// This is automatically cleared when Factory::Remove() calls
// MaybeDestroyInstance().
MOZ_ASSERT(!sBackgroundThread);
sBackgroundThread = NS_GetCurrentThread();
}
// We cannot use ClearOnShutdown() here because we're not on the main
@ -359,134 +359,21 @@ private:
return;
}
// Be clear about what we are locking. sFactory is bg thread only, so
// we don't need to lock it here. Just protect sBackgroundThread.
{
StaticMutexAutoLock lock(sMutex);
MOZ_ASSERT(sBackgroundThread);
sBackgroundThread = nullptr;
}
sFactory = nullptr;
}
static void
AbortOnBackgroundThread(const nsACString& aOrigin)
{
mozilla::ipc::AssertIsOnBackgroundThread();
// The factory was destroyed between when abort started on main thread and
// when we could start abort on the worker thread. Just declare abort
// complete.
if (!sFactory) {
#ifdef DEBUG
StaticMutexAutoLock lock(sMutex);
MOZ_ASSERT(!sBackgroundThread);
#endif
return;
}
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
{
ManagerList::ForwardIterator iter(sFactory->mManagerList);
while (iter.HasMore()) {
RefPtr<Manager> manager = iter.GetNext();
if (aOrigin.IsVoid() ||
manager->mManagerId->QuotaOrigin() == aOrigin) {
manager->Abort();
}
}
}
}
static void
ShutdownAllOnBackgroundThread()
{
mozilla::ipc::AssertIsOnBackgroundThread();
// The factory shutdown between when shutdown started on main thread and
// when we could start shutdown on the worker thread. Just declare
// shutdown complete. The sFactoryShutdown flag prevents the factory
// from racing to restart here.
if (!sFactory) {
#ifdef DEBUG
StaticMutexAutoLock lock(sMutex);
MOZ_ASSERT(!sBackgroundThread);
#endif
return;
}
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
{
// Note that we are synchronously calling shutdown code here. If any
// of the shutdown code synchronously decides to delete the Factory
// we need to delay that delete until the end of this method.
AutoRestore<bool> restore(sFactory->mInSyncShutdown);
sFactory->mInSyncShutdown = true;
ManagerList::ForwardIterator iter(sFactory->mManagerList);
while (iter.HasMore()) {
RefPtr<Manager> manager = iter.GetNext();
manager->Shutdown();
}
}
MaybeDestroyInstance();
}
class AbortRunnable final : public nsRunnable
{
public:
explicit AbortRunnable(const nsACString& aOrigin)
: mOrigin(aOrigin)
{ }
NS_IMETHOD
Run() override
{
mozilla::ipc::AssertIsOnBackgroundThread();
AbortOnBackgroundThread(mOrigin);
return NS_OK;
}
private:
~AbortRunnable() { }
const nsCString mOrigin;
};
class ShutdownAllRunnable final : public nsRunnable
{
public:
NS_IMETHOD
Run() override
{
mozilla::ipc::AssertIsOnBackgroundThread();
ShutdownAllOnBackgroundThread();
return NS_OK;
}
private:
~ShutdownAllRunnable() { }
};
// Singleton created on demand and deleted when last Manager is cleared
// in Remove().
// PBackground thread only.
static StaticAutoPtr<Factory> sFactory;
// protects following static attributes
// protects following static attribute
static StaticMutex sMutex;
// Indicate if shutdown has occurred to block re-creation of sFactory.
// Must hold sMutex to access.
static bool sFactoryShutdown;
// Background thread owning all Manager objects. Only set while sFactory is
// set.
// Must hold sMutex to access.
static StaticRefPtr<nsIThread> sBackgroundThread;
// Weak references as we don't want to keep Manager objects alive forever.
// When a Manager is destroyed it calls Factory::Remove() to clear itself.
// PBackground thread only.
@ -508,9 +395,6 @@ StaticMutex Manager::Factory::sMutex;
// static
bool Manager::Factory::sFactoryShutdown = false;
// static
StaticRefPtr<nsIThread> Manager::Factory::sBackgroundThread;
// ----------------------------------------------------------------------------
// Abstract class to help implement the various Actions. The vast majority
@ -1531,13 +1415,13 @@ Manager::Get(ManagerId* aManagerId)
// static
void
Manager::ShutdownAllOnMainThread()
Manager::ShutdownAll()
{
MOZ_ASSERT(NS_IsMainThread());
mozilla::ipc::AssertIsOnBackgroundThread();
Factory::StartShutdownAllOnMainThread();
Factory::ShutdownAll();
while (!Factory::IsShutdownAllCompleteOnMainThread()) {
while (!Factory::IsShutdownAllComplete()) {
if (!NS_ProcessNextEvent()) {
NS_WARNING("Something bad happened!");
break;
@ -1547,11 +1431,11 @@ Manager::ShutdownAllOnMainThread()
// static
void
Manager::AbortOnMainThread(const nsACString& aOrigin)
Manager::Abort(const nsACString& aOrigin)
{
MOZ_ASSERT(NS_IsMainThread());
mozilla::ipc::AssertIsOnBackgroundThread();
Factory::StartAbortOnMainThread(aOrigin);
Factory::Abort(aOrigin);
}
void

6
dom/cache/Manager.h vendored
View File

@ -131,11 +131,11 @@ public:
static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut);
static already_AddRefed<Manager> Get(ManagerId* aManagerId);
// Synchronously shutdown from main thread. This spins the event loop.
static void ShutdownAllOnMainThread();
// Synchronously shutdown. This spins the event loop.
static void ShutdownAll();
// Cancel actions for given origin or all actions if passed string is null.
static void AbortOnMainThread(const nsACString& aOrigin);
static void Abort(const nsACString& aOrigin);
// Must be called by Listener objects before they are destroyed.
void RemoveListener(Listener* aListener);

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/UsageInfo.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "nsThreadUtils.h"
@ -23,6 +24,7 @@ using mozilla::dom::quota::Client;
using mozilla::dom::quota::PersistenceType;
using mozilla::dom::quota::QuotaManager;
using mozilla::dom::quota::UsageInfo;
using mozilla::ipc::AssertIsOnBackgroundThread;
static nsresult
GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo)
@ -175,9 +177,9 @@ public:
virtual void
AbortOperations(const nsACString& aOrigin) override
{
MOZ_ASSERT(NS_IsMainThread());
AssertIsOnBackgroundThread();
Manager::AbortOnMainThread(aOrigin);
Manager::Abort(aOrigin);
}
virtual void
@ -195,22 +197,26 @@ public:
}
virtual void
PerformIdleMaintenance() override
StartIdleMaintenance() override
{ }
virtual void
StopIdleMaintenance() override
{ }
virtual void
ShutdownWorkThreads() override
{
MOZ_ASSERT(NS_IsMainThread());
AssertIsOnBackgroundThread();
// spins the event loop and synchronously shuts down all Managers
Manager::ShutdownAllOnMainThread();
Manager::ShutdownAll();
}
private:
~CacheQuotaClient()
{
MOZ_ASSERT(NS_IsMainThread());
AssertIsOnBackgroundThread();
}
NS_INLINE_DECL_REFCOUNTING(CacheQuotaClient, override)
@ -224,6 +230,8 @@ namespace cache {
already_AddRefed<quota::Client> CreateQuotaClient()
{
AssertIsOnBackgroundThread();
RefPtr<CacheQuotaClient> ref = new CacheQuotaClient();
return ref.forget();
}

View File

@ -35,7 +35,11 @@ function runTests(testFile, order) {
// adapted from dom/indexedDB/test/helpers.js
function clearStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var principal = SpecialPowers.wrap(document).nodePrincipal;
var request = qms.clearStoragesForPrincipal(principal);
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}

View File

@ -24,19 +24,31 @@ function setupTestIframe() {
function clearStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var principal = SpecialPowers.wrap(document).nodePrincipal;
var request = qms.clearStoragesForPrincipal(principal);
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}
function storageUsage() {
return new Promise(function(resolve, reject) {
SpecialPowers.getStorageUsageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var principal = SpecialPowers.wrap(document).nodePrincipal;
var cb = SpecialPowers.wrapCallback(function(request) {
resolve(request.usage, request.fileUsage);
});
qms.getUsageForPrincipal(principal, cb);
});
}
function resetStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var request = qms.reset();
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}

View File

@ -24,19 +24,31 @@ function setupTestIframe() {
function clearStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var principal = SpecialPowers.wrap(document).nodePrincipal;
var request = qms.clearStoragesForPrincipal(principal);
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}
function storageUsage() {
return new Promise(function(resolve, reject) {
SpecialPowers.getStorageUsageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var principal = SpecialPowers.wrap(document).nodePrincipal;
var cb = SpecialPowers.wrapCallback(function(request) {
resolve(request.usage, request.fileUsage);
});
qms.getUsageForPrincipal(principal, cb);
});
}
function resetStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var request = qms.reset();
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}

View File

@ -23,7 +23,10 @@ function setupTestIframe() {
function resetStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var request = qms.reset();
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}

View File

@ -24,19 +24,31 @@ function setupTestIframe() {
function clearStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var principal = SpecialPowers.wrap(document).nodePrincipal;
var request = qms.clearStoragesForPrincipal(principal);
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}
function storageUsage() {
return new Promise(function(resolve, reject) {
SpecialPowers.getStorageUsageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var principal = SpecialPowers.wrap(document).nodePrincipal;
var cb = SpecialPowers.wrapCallback(function(request) {
resolve(request.usage, request.fileUsage);
});
qms.getUsageForPrincipal(principal, cb);
});
}
function resetStorage() {
return new Promise(function(resolve, reject) {
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
var qms = SpecialPowers.Services.qms;
var request = qms.reset();
var cb = SpecialPowers.wrapCallback(resolve);
request.callback = cb;
});
}

View File

@ -92,22 +92,11 @@ function resetQuotaManager() {
var pref = 'dom.quotaManager.testing';
prefService.getBranch(null).setBoolPref(pref, true);
qm.reset();
var request = qm.reset();
request.callback = resolve;
// disable quota manager testing mode
//prefService.getBranch(null).setBoolPref(pref, false);
var uri = Cc['@mozilla.org/network/io-service;1']
.getService(Ci.nsIIOService)
.newURI('http://example.com', null, null);
var principal = Cc['@mozilla.org/scriptsecuritymanager;1']
.getService(Ci.nsIScriptSecurityManager)
.getSystemPrincipal();
// use getUsageForPrincipal() to get a callback when the reset() is done
qm.getUsageForPrincipal(principal, function(principal, usage, fileUsage) {
resolve(usage);
});
});
}