diff --git a/dom/quota/StorageManager.cpp b/dom/quota/StorageManager.cpp index 4e9f0cf8c6b2..ba3b3fbd11ed 100644 --- a/dom/quota/StorageManager.cpp +++ b/dom/quota/StorageManager.cpp @@ -11,6 +11,7 @@ #include "mozilla/dom/StorageManagerBinding.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/ErrorResult.h" +#include "nsContentPermissionHelper.h" #include "nsIQuotaCallbacks.h" #include "nsIQuotaRequests.h" #include "nsPIDOMWindow.h" @@ -22,10 +23,21 @@ namespace dom { namespace { -// This class is used to get quota usage callback. -class EstimateResolver final - : public nsIQuotaUsageCallback +// This class is used to get quota usage, request persist and check persisted +// status callbacks. +class RequestResolver final + : public nsIQuotaCallback + , public nsIQuotaUsageCallback { +public: + enum Type + { + Estimate, + Persist, + Persisted + }; + +private: class FinishWorkerRunnable; // If this resolver was created for a window then mPromise must be non-null. @@ -35,44 +47,69 @@ class EstimateResolver final nsresult mResultCode; StorageEstimate mStorageEstimate; + const Type mType; + bool mPersisted; public: - explicit EstimateResolver(Promise* aPromise) + RequestResolver(Type aType, Promise* aPromise) : mPromise(aPromise) , mResultCode(NS_OK) + , mType(aType) + , mPersisted(false) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPromise); } - explicit EstimateResolver(PromiseWorkerProxy* aProxy) + RequestResolver(Type aType, PromiseWorkerProxy* aProxy) : mProxy(aProxy) , mResultCode(NS_OK) + , mType(aType) + , mPersisted(false) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aProxy); } + Type + GetType() const + { + return mType; + } + void - ResolveOrReject(Promise* aPromise); + ResolveOrReject(); NS_DECL_THREADSAFE_ISUPPORTS - + NS_DECL_NSIQUOTACALLBACK NS_DECL_NSIQUOTAUSAGECALLBACK private: - ~EstimateResolver() + ~RequestResolver() { } + + nsresult + GetStorageEstimate(nsIVariant* aResult); + + nsresult + GetPersisted(nsIVariant* aResult); + + template + nsresult + OnCompleteOrUsageResult(T* aRequest); + + nsresult + Finish(); }; // This class is used to return promise on worker thread. -class EstimateResolver::FinishWorkerRunnable final +class RequestResolver::FinishWorkerRunnable final : public WorkerRunnable { - RefPtr mResolver; + RefPtr mResolver; public: - explicit FinishWorkerRunnable(EstimateResolver* aResolver) + explicit FinishWorkerRunnable(RequestResolver* aResolver) : WorkerRunnable(aResolver->mProxy->GetWorkerPrivate()) , mResolver(aResolver) { @@ -80,11 +117,11 @@ public: MOZ_ASSERT(aResolver); } - virtual bool + bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override; }; -class EstimateWorkerMainThreadRunnable +class EstimateWorkerMainThreadRunnable final : public WorkerMainThreadRunnable { RefPtr mProxy; @@ -101,10 +138,69 @@ public: MOZ_ASSERT(aProxy); } - virtual bool + bool MainThreadRun() override; }; +class PersistedWorkerMainThreadRunnable final + : public WorkerMainThreadRunnable +{ + RefPtr mProxy; + +public: + PersistedWorkerMainThreadRunnable(WorkerPrivate* aWorkerPrivate, + PromiseWorkerProxy* aProxy) + : WorkerMainThreadRunnable(aWorkerPrivate, + NS_LITERAL_CSTRING("StorageManager :: Persisted")) + , mProxy(aProxy) + { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + MOZ_ASSERT(aProxy); + } + + bool + MainThreadRun() override; +}; + +/******************************************************************************* + * PersistentStoragePermissionRequest + ******************************************************************************/ + +class PersistentStoragePermissionRequest final + : public nsIContentPermissionRequest +{ + nsCOMPtr mPrincipal; + nsCOMPtr mWindow; + RefPtr mPromise; + nsCOMPtr mRequester; + +public: + PersistentStoragePermissionRequest(nsIPrincipal* aPrincipal, + nsPIDOMWindowInner* aWindow, + Promise* aPromise) + : mPrincipal(aPrincipal) + , mWindow(aWindow) + , mPromise(aPromise) + { + MOZ_ASSERT(aPrincipal); + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aPromise); + + mRequester = new nsContentPermissionRequester(mWindow); + } + + nsresult + Start(); + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSICONTENTPERMISSIONREQUEST + +private: + ~PersistentStoragePermissionRequest() + { } +}; + nsresult GetUsageForPrincipal(nsIPrincipal* aPrincipal, nsIQuotaUsageCallback* aCallback, @@ -119,7 +215,10 @@ GetUsageForPrincipal(nsIPrincipal* aPrincipal, return NS_ERROR_FAILURE; } - nsresult rv = qms->GetUsageForPrincipal(aPrincipal, aCallback, true, aRequest); + nsresult rv = qms->GetUsageForPrincipal(aPrincipal, + aCallback, + true, + aRequest); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -128,20 +227,228 @@ GetUsageForPrincipal(nsIPrincipal* aPrincipal, }; nsresult -GetStorageEstimate(nsIQuotaUsageRequest* aRequest, - StorageEstimate& aStorageEstimate) +Persisted(nsIPrincipal* aPrincipal, + nsIQuotaCallback* aCallback, + nsIQuotaRequest** aRequest) { + MOZ_ASSERT(aPrincipal); + MOZ_ASSERT(aCallback); MOZ_ASSERT(aRequest); - nsCOMPtr result; - nsresult rv = aRequest->GetResult(getter_AddRefs(result)); + nsCOMPtr qms = QuotaManagerService::GetOrCreate(); + if (NS_WARN_IF(!qms)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr request; + nsresult rv = qms->Persisted(aPrincipal, getter_AddRefs(request)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + // All the methods in nsIQuotaManagerService shouldn't synchronously fire + // any callbacks when they are being executed. Even when a result is ready, + // a new runnable should be dispatched to current thread to fire the callback + // asynchronously. It's safe to set the callback after we call Persisted(). + MOZ_ALWAYS_SUCCEEDS(request->SetCallback(aCallback)); + + request.forget(aRequest); + + return NS_OK; +}; + +already_AddRefed +ExecuteOpOnMainOrWorkerThread(nsIGlobalObject* aGlobal, + RequestResolver::Type aType, + ErrorResult& aRv) +{ + MOZ_ASSERT(aGlobal); + MOZ_ASSERT_IF(aType == RequestResolver::Type::Persist, + NS_IsMainThread()); + + RefPtr promise = Promise::Create(aGlobal, aRv); + if (NS_WARN_IF(!promise)) { + return nullptr; + } + + if (NS_IsMainThread()) { + nsCOMPtr window = do_QueryInterface(aGlobal); + if (NS_WARN_IF(!window)) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsCOMPtr doc = window->GetExtantDoc(); + if (NS_WARN_IF(!doc)) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsCOMPtr principal = doc->NodePrincipal(); + MOZ_ASSERT(principal); + + switch (aType) { + case RequestResolver::Type::Persisted: { + RefPtr resolver = + new RequestResolver(RequestResolver::Type::Persisted, promise); + + RefPtr request; + aRv = Persisted(principal, resolver, getter_AddRefs(request)); + + break; + } + + case RequestResolver::Type::Persist: { + RefPtr request = + new PersistentStoragePermissionRequest(principal, window, promise); + + aRv = request->Start(); + + break; + } + + case RequestResolver::Type::Estimate: { + RefPtr resolver = + new RequestResolver(RequestResolver::Type::Estimate, promise); + + RefPtr request; + aRv = GetUsageForPrincipal(principal, + resolver, + getter_AddRefs(request)); + + break; + } + + default: + MOZ_CRASH("Invalid aRequest type!"); + } + + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return promise.forget(); + } + + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + + RefPtr promiseProxy = + PromiseWorkerProxy::Create(workerPrivate, promise); + if (NS_WARN_IF(!promiseProxy)) { + return nullptr; + } + + switch (aType) { + case RequestResolver::Type::Estimate: { + RefPtr runnnable = + new EstimateWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(), + promiseProxy); + runnnable->Dispatch(Terminating, aRv); + + break; + } + + case RequestResolver::Type::Persisted: { + RefPtr runnnable = + new PersistedWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(), + promiseProxy); + runnnable->Dispatch(Terminating, aRv); + + break; + } + + default: + MOZ_CRASH("Invalid aRequest type"); + } + + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return promise.forget(); +}; + +} // namespace + +/******************************************************************************* + * Local class implementations + ******************************************************************************/ + +void +RequestResolver::ResolveOrReject() +{ + class MOZ_STACK_CLASS AutoCleanup final + { + RefPtr mProxy; + + public: + explicit AutoCleanup(PromiseWorkerProxy* aProxy) + : mProxy(aProxy) + { + MOZ_ASSERT(aProxy); + } + + ~AutoCleanup() + { + MOZ_ASSERT(mProxy); + + mProxy->CleanUp(); + } + }; + + RefPtr promise; + Maybe autoCleanup; + + if (mPromise) { + promise = mPromise; + } else { + MOZ_ASSERT(mProxy); + + promise = mProxy->WorkerPromise(); + + // Only clean up for worker case. + autoCleanup.emplace(mProxy); + } + + MOZ_ASSERT(promise); + + if (mType == Type::Estimate) { + if (NS_SUCCEEDED(mResultCode)) { + promise->MaybeResolve(mStorageEstimate); + } else { + promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR); + } + + return; + } + + MOZ_ASSERT(mType == Type::Persist || mType == Type::Persisted); + + if (NS_SUCCEEDED(mResultCode)) { + promise->MaybeResolve(mPersisted); + } else { + promise->MaybeResolve(false); + } +} + +NS_IMPL_ISUPPORTS(RequestResolver, nsIQuotaUsageCallback, nsIQuotaCallback) + +nsresult +RequestResolver::GetStorageEstimate(nsIVariant* aResult) +{ + MOZ_ASSERT(aResult); + MOZ_ASSERT(mType == Type::Estimate); + +#ifdef DEBUG + uint16_t dataType; + MOZ_ALWAYS_SUCCEEDS(aResult->GetDataType(&dataType)); + MOZ_ASSERT(dataType == nsIDataType::VTYPE_INTERFACE_IS); +#endif + nsID* iid; nsCOMPtr supports; - rv = result->GetAsInterface(&iid, getter_AddRefs(supports)); + nsresult rv = aResult->GetAsInterface(&iid, getter_AddRefs(supports)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -153,89 +460,151 @@ GetStorageEstimate(nsIQuotaUsageRequest* aRequest, MOZ_ASSERT(originUsageResult); MOZ_ALWAYS_SUCCEEDS( - originUsageResult->GetUsage(&aStorageEstimate.mUsage.Construct())); + originUsageResult->GetUsage(&mStorageEstimate.mUsage.Construct())); MOZ_ALWAYS_SUCCEEDS( - originUsageResult->GetLimit(&aStorageEstimate.mQuota.Construct())); + originUsageResult->GetLimit(&mStorageEstimate.mQuota.Construct())); return NS_OK; } -} // namespace - -/******************************************************************************* - * Local class implementations - ******************************************************************************/ - -void -EstimateResolver::ResolveOrReject(Promise* aPromise) +nsresult +RequestResolver::GetPersisted(nsIVariant* aResult) { - MOZ_ASSERT(aPromise); + MOZ_ASSERT(aResult); + MOZ_ASSERT(mType == Type::Persist || mType == Type::Persisted); - if (NS_SUCCEEDED(mResultCode)) { - aPromise->MaybeResolve(mStorageEstimate); - } else { - aPromise->MaybeReject(mResultCode); +#ifdef DEBUG + uint16_t dataType; + MOZ_ALWAYS_SUCCEEDS(aResult->GetDataType(&dataType)); +#endif + + if (mType == Type::Persist) { + MOZ_ASSERT(dataType == nsIDataType::VTYPE_VOID); + + mPersisted = true; + return NS_OK; } + + MOZ_ASSERT(dataType == nsIDataType::VTYPE_BOOL); + + bool persisted; + nsresult rv = aResult->GetAsBool(&persisted); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + mPersisted = persisted; + return NS_OK; } -NS_IMPL_ISUPPORTS(EstimateResolver, nsIQuotaUsageCallback) - -NS_IMETHODIMP -EstimateResolver::OnUsageResult(nsIQuotaUsageRequest *aRequest) +template +nsresult +RequestResolver::OnCompleteOrUsageResult(T* aRequest) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aRequest); - nsresult rv = aRequest->GetResultCode(&mResultCode); + nsresult resultCode; + nsresult rv = aRequest->GetResultCode(&resultCode); if (NS_WARN_IF(NS_FAILED(rv))) { - mResultCode = rv; - } else if (NS_SUCCEEDED(mResultCode)) { - rv = GetStorageEstimate(aRequest, mStorageEstimate); - if (NS_WARN_IF(NS_FAILED(rv))) { - mResultCode = rv; - } + return rv; } + if (NS_FAILED(resultCode)) { + return resultCode; + } + + nsCOMPtr result; + rv = aRequest->GetResult(getter_AddRefs(result)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (mType == Type::Estimate) { + rv = GetStorageEstimate(result); + } else { + MOZ_ASSERT(mType == Type::Persist || mType == Type::Persisted); + + rv = GetPersisted(result); + } + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +nsresult +RequestResolver::Finish() +{ // In a main thread request. if (!mProxy) { MOZ_ASSERT(mPromise); - ResolveOrReject(mPromise); + ResolveOrReject(); return NS_OK; } - // In a worker thread request. - MutexAutoLock lock(mProxy->Lock()); + { + // In a worker thread request. + MutexAutoLock lock(mProxy->Lock()); - if (NS_WARN_IF(mProxy->CleanedUp())) { - return NS_ERROR_FAILURE; + if (NS_WARN_IF(mProxy->CleanedUp())) { + return NS_ERROR_FAILURE; + } + + RefPtr runnable = new FinishWorkerRunnable(this); + if (NS_WARN_IF(!runnable->Dispatch())) { + return NS_ERROR_FAILURE; + } } - RefPtr runnable = new FinishWorkerRunnable(this); - if (NS_WARN_IF(!runnable->Dispatch())) { - return NS_ERROR_FAILURE; + return NS_OK; +} + +NS_IMETHODIMP +RequestResolver::OnComplete(nsIQuotaRequest *aRequest) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aRequest); + + mResultCode = OnCompleteOrUsageResult(aRequest); + + nsresult rv = Finish(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +NS_IMETHODIMP +RequestResolver::OnUsageResult(nsIQuotaUsageRequest *aRequest) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aRequest); + + mResultCode = OnCompleteOrUsageResult(aRequest); + + nsresult rv = Finish(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; } return NS_OK; } bool -EstimateResolver:: +RequestResolver:: FinishWorkerRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) { + MOZ_ASSERT(aCx); MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); - RefPtr proxy = mResolver->mProxy; - MOZ_ASSERT(proxy); - - RefPtr promise = proxy->WorkerPromise(); - MOZ_ASSERT(promise); - - mResolver->ResolveOrReject(promise); - - proxy->CleanUp(); + MOZ_ASSERT(mResolver); + mResolver->ResolveOrReject(); return true; } @@ -257,7 +626,8 @@ EstimateWorkerMainThreadRunnable::MainThreadRun() MOZ_ASSERT(principal); - RefPtr resolver = new EstimateResolver(mProxy); + RefPtr resolver = + new RequestResolver(RequestResolver::Type::Estimate, mProxy); RefPtr request; nsresult rv = @@ -269,6 +639,156 @@ EstimateWorkerMainThreadRunnable::MainThreadRun() return true; } +bool +PersistedWorkerMainThreadRunnable::MainThreadRun() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr principal; + + { + MutexAutoLock lock(mProxy->Lock()); + if (mProxy->CleanedUp()) { + return true; + } + principal = mProxy->GetWorkerPrivate()->GetPrincipal(); + } + + MOZ_ASSERT(principal); + + RefPtr resolver = + new RequestResolver(RequestResolver::Type::Persisted, mProxy); + + RefPtr request; + nsresult rv = Persisted(principal, resolver, getter_AddRefs(request)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + + return true; +} + +nsresult +PersistentStoragePermissionRequest::Start() +{ + MOZ_ASSERT(NS_IsMainThread()); + + // Grant permission if pref'ed on. + if (Preferences::GetBool("dom.storageManager.prompt.testing", false)) { + if (Preferences::GetBool("dom.storageManager.prompt.testing.allow", + false)) { + return Allow(JS::UndefinedHandleValue); + } + + return Cancel(); + } + + return nsContentPermissionUtils::AskPermission(this, mWindow); +} + +NS_IMPL_ISUPPORTS(PersistentStoragePermissionRequest, + nsIContentPermissionRequest) + +NS_IMETHODIMP +PersistentStoragePermissionRequest::GetPrincipal(nsIPrincipal** aPrincipal) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aPrincipal); + MOZ_ASSERT(mPrincipal); + + NS_ADDREF(*aPrincipal = mPrincipal); + + return NS_OK; +} + +NS_IMETHODIMP +PersistentStoragePermissionRequest::GetWindow(mozIDOMWindow** aRequestingWindow) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aRequestingWindow); + MOZ_ASSERT(mWindow); + + NS_ADDREF(*aRequestingWindow = mWindow); + + return NS_OK; +} + +NS_IMETHODIMP +PersistentStoragePermissionRequest::GetElement(nsIDOMElement** aElement) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aElement); + + *aElement = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +PersistentStoragePermissionRequest::Cancel() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mPromise); + + RefPtr resolver = + new RequestResolver(RequestResolver::Type::Persisted, mPromise); + + RefPtr request; + + return Persisted(mPrincipal, resolver, getter_AddRefs(request)); +} + +NS_IMETHODIMP +PersistentStoragePermissionRequest::Allow(JS::HandleValue aChoices) +{ + MOZ_ASSERT(NS_IsMainThread()); + + RefPtr resolver = + new RequestResolver(RequestResolver::Type::Persist, mPromise); + + nsCOMPtr qms = QuotaManagerService::GetOrCreate(); + if (NS_WARN_IF(!qms)) { + return NS_ERROR_FAILURE; + } + + RefPtr request; + + nsresult rv = qms->Persist(mPrincipal, getter_AddRefs(request)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + MOZ_ALWAYS_SUCCEEDS(request->SetCallback(resolver)); + + return NS_OK; +} + +NS_IMETHODIMP +PersistentStoragePermissionRequest::GetRequester( + nsIContentPermissionRequester** aRequester) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aRequester); + + nsCOMPtr requester = mRequester; + requester.forget(aRequester); + + return NS_OK; +} + +NS_IMETHODIMP +PersistentStoragePermissionRequest::GetTypes(nsIArray** aTypes) +{ + MOZ_ASSERT(aTypes); + + nsTArray emptyOptions; + + return nsContentPermissionUtils::CreatePermissionArray( + NS_LITERAL_CSTRING("persistent-storage"), + NS_LITERAL_CSTRING("unused"), + emptyOptions, + aTypes); +} + /******************************************************************************* * StorageManager ******************************************************************************/ @@ -283,64 +803,34 @@ StorageManager::~StorageManager() { } +already_AddRefed +StorageManager::Persisted(ErrorResult& aRv) +{ + MOZ_ASSERT(mOwner); + + return ExecuteOpOnMainOrWorkerThread(mOwner, + RequestResolver::Type::Persisted, + aRv); +} + +already_AddRefed +StorageManager::Persist(ErrorResult& aRv) +{ + MOZ_ASSERT(mOwner); + + return ExecuteOpOnMainOrWorkerThread(mOwner, + RequestResolver::Type::Persist, + aRv); +} + already_AddRefed StorageManager::Estimate(ErrorResult& aRv) { MOZ_ASSERT(mOwner); - RefPtr promise = Promise::Create(mOwner, aRv); - if (NS_WARN_IF(!promise)) { - return nullptr; - } - - if (NS_IsMainThread()) { - nsCOMPtr window = do_QueryInterface(mOwner); - if (NS_WARN_IF(!window)) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr doc = window->GetExtantDoc(); - if (NS_WARN_IF(!doc)) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr principal = doc->NodePrincipal(); - MOZ_ASSERT(principal); - - RefPtr resolver = new EstimateResolver(promise); - - RefPtr request; - nsresult rv = - GetUsageForPrincipal(principal, resolver, getter_AddRefs(request)); - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(rv); - return nullptr; - } - - return promise.forget(); - } - - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - - RefPtr promiseProxy = - PromiseWorkerProxy::Create(workerPrivate, promise); - if (NS_WARN_IF(!promiseProxy)) { - return nullptr; - } - - RefPtr runnnable = - new EstimateWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(), - promiseProxy); - - runnnable->Dispatch(Terminating, aRv); - if (NS_WARN_IF(aRv.Failed())) { - return nullptr; - } - - return promise.forget(); + return ExecuteOpOnMainOrWorkerThread(mOwner, + RequestResolver::Type::Estimate, + aRv); } // static diff --git a/dom/quota/StorageManager.h b/dom/quota/StorageManager.h index 162390f48861..781daad3b3e5 100644 --- a/dom/quota/StorageManager.h +++ b/dom/quota/StorageManager.h @@ -39,6 +39,12 @@ public: } // WebIDL + already_AddRefed + Persisted(ErrorResult& aRv); + + already_AddRefed + Persist(ErrorResult& aRv); + already_AddRefed Estimate(ErrorResult& aRv); diff --git a/dom/webidl/StorageManager.webidl b/dom/webidl/StorageManager.webidl index 5649f307a34e..8078ce96a40e 100644 --- a/dom/webidl/StorageManager.webidl +++ b/dom/webidl/StorageManager.webidl @@ -12,10 +12,12 @@ Exposed=(Window,Worker), Func="mozilla::dom::StorageManager::PrefEnabled"] interface StorageManager { - // [Throws] - // Promise persisted(); - // [Throws] - // [Exposed=Window] Promise persist(); + [Throws] + Promise persisted(); + + [Exposed=Window, Throws] + Promise persist(); + [Throws] Promise estimate(); };