зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1286717 - Part 1: Expose persist/persisted to StorageManager, r=janv, r=baku
This commit is contained in:
Родитель
b24e38d3fc
Коммит
c9c55c765e
|
@ -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 <typename T>
|
||||
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<EstimateResolver> mResolver;
|
||||
RefPtr<RequestResolver> 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<PromiseWorkerProxy> mProxy;
|
||||
|
@ -101,10 +138,69 @@ public:
|
|||
MOZ_ASSERT(aProxy);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
bool
|
||||
MainThreadRun() override;
|
||||
};
|
||||
|
||||
class PersistedWorkerMainThreadRunnable final
|
||||
: public WorkerMainThreadRunnable
|
||||
{
|
||||
RefPtr<PromiseWorkerProxy> 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<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
RefPtr<Promise> mPromise;
|
||||
nsCOMPtr<nsIContentPermissionRequester> 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<nsIVariant> result;
|
||||
nsresult rv = aRequest->GetResult(getter_AddRefs(result));
|
||||
nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
|
||||
if (NS_WARN_IF(!qms)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIQuotaRequest> 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<Promise>
|
||||
ExecuteOpOnMainOrWorkerThread(nsIGlobalObject* aGlobal,
|
||||
RequestResolver::Type aType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT_IF(aType == RequestResolver::Type::Persist,
|
||||
NS_IsMainThread());
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
|
||||
if (NS_WARN_IF(!promise)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||
if (NS_WARN_IF(!window)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
MOZ_ASSERT(principal);
|
||||
|
||||
switch (aType) {
|
||||
case RequestResolver::Type::Persisted: {
|
||||
RefPtr<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Persisted, promise);
|
||||
|
||||
RefPtr<nsIQuotaRequest> request;
|
||||
aRv = Persisted(principal, resolver, getter_AddRefs(request));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RequestResolver::Type::Persist: {
|
||||
RefPtr<PersistentStoragePermissionRequest> request =
|
||||
new PersistentStoragePermissionRequest(principal, window, promise);
|
||||
|
||||
aRv = request->Start();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RequestResolver::Type::Estimate: {
|
||||
RefPtr<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Estimate, promise);
|
||||
|
||||
RefPtr<nsIQuotaUsageRequest> 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<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
if (NS_WARN_IF(!promiseProxy)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (aType) {
|
||||
case RequestResolver::Type::Estimate: {
|
||||
RefPtr<EstimateWorkerMainThreadRunnable> runnnable =
|
||||
new EstimateWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(),
|
||||
promiseProxy);
|
||||
runnnable->Dispatch(Terminating, aRv);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RequestResolver::Type::Persisted: {
|
||||
RefPtr<PersistedWorkerMainThreadRunnable> 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<PromiseWorkerProxy> mProxy;
|
||||
|
||||
public:
|
||||
explicit AutoCleanup(PromiseWorkerProxy* aProxy)
|
||||
: mProxy(aProxy)
|
||||
{
|
||||
MOZ_ASSERT(aProxy);
|
||||
}
|
||||
|
||||
~AutoCleanup()
|
||||
{
|
||||
MOZ_ASSERT(mProxy);
|
||||
|
||||
mProxy->CleanUp();
|
||||
}
|
||||
};
|
||||
|
||||
RefPtr<Promise> promise;
|
||||
Maybe<AutoCleanup> 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<nsISupports> 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 <typename T>
|
||||
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<nsIVariant> 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<FinishWorkerRunnable> runnable = new FinishWorkerRunnable(this);
|
||||
if (NS_WARN_IF(!runnable->Dispatch())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<FinishWorkerRunnable> 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<PromiseWorkerProxy> proxy = mResolver->mProxy;
|
||||
MOZ_ASSERT(proxy);
|
||||
|
||||
RefPtr<Promise> 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<EstimateResolver> resolver = new EstimateResolver(mProxy);
|
||||
RefPtr<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Estimate, mProxy);
|
||||
|
||||
RefPtr<nsIQuotaUsageRequest> request;
|
||||
nsresult rv =
|
||||
|
@ -269,6 +639,156 @@ EstimateWorkerMainThreadRunnable::MainThreadRun()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PersistedWorkerMainThreadRunnable::MainThreadRun()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mProxy->Lock());
|
||||
if (mProxy->CleanedUp()) {
|
||||
return true;
|
||||
}
|
||||
principal = mProxy->GetWorkerPrivate()->GetPrincipal();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(principal);
|
||||
|
||||
RefPtr<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Persisted, mProxy);
|
||||
|
||||
RefPtr<nsIQuotaRequest> 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<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Persisted, mPromise);
|
||||
|
||||
RefPtr<nsIQuotaRequest> request;
|
||||
|
||||
return Persisted(mPrincipal, resolver, getter_AddRefs(request));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PersistentStoragePermissionRequest::Allow(JS::HandleValue aChoices)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<RequestResolver> resolver =
|
||||
new RequestResolver(RequestResolver::Type::Persist, mPromise);
|
||||
|
||||
nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
|
||||
if (NS_WARN_IF(!qms)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<nsIQuotaRequest> 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<nsIContentPermissionRequester> requester = mRequester;
|
||||
requester.forget(aRequester);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PersistentStoragePermissionRequest::GetTypes(nsIArray** aTypes)
|
||||
{
|
||||
MOZ_ASSERT(aTypes);
|
||||
|
||||
nsTArray<nsString> emptyOptions;
|
||||
|
||||
return nsContentPermissionUtils::CreatePermissionArray(
|
||||
NS_LITERAL_CSTRING("persistent-storage"),
|
||||
NS_LITERAL_CSTRING("unused"),
|
||||
emptyOptions,
|
||||
aTypes);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* StorageManager
|
||||
******************************************************************************/
|
||||
|
@ -283,64 +803,34 @@ StorageManager::~StorageManager()
|
|||
{
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
StorageManager::Persisted(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mOwner);
|
||||
|
||||
return ExecuteOpOnMainOrWorkerThread(mOwner,
|
||||
RequestResolver::Type::Persisted,
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
StorageManager::Persist(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mOwner);
|
||||
|
||||
return ExecuteOpOnMainOrWorkerThread(mOwner,
|
||||
RequestResolver::Type::Persist,
|
||||
aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
StorageManager::Estimate(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mOwner);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(mOwner, aRv);
|
||||
if (NS_WARN_IF(!promise)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mOwner);
|
||||
if (NS_WARN_IF(!window)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
MOZ_ASSERT(principal);
|
||||
|
||||
RefPtr<EstimateResolver> resolver = new EstimateResolver(promise);
|
||||
|
||||
RefPtr<nsIQuotaUsageRequest> 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<PromiseWorkerProxy> promiseProxy =
|
||||
PromiseWorkerProxy::Create(workerPrivate, promise);
|
||||
if (NS_WARN_IF(!promiseProxy)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<EstimateWorkerMainThreadRunnable> 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
|
||||
|
|
|
@ -39,6 +39,12 @@ public:
|
|||
}
|
||||
|
||||
// WebIDL
|
||||
already_AddRefed<Promise>
|
||||
Persisted(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Persist(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Estimate(ErrorResult& aRv);
|
||||
|
||||
|
|
|
@ -12,10 +12,12 @@
|
|||
Exposed=(Window,Worker),
|
||||
Func="mozilla::dom::StorageManager::PrefEnabled"]
|
||||
interface StorageManager {
|
||||
// [Throws]
|
||||
// Promise<boolean> persisted();
|
||||
// [Throws]
|
||||
// [Exposed=Window] Promise<boolean> persist();
|
||||
[Throws]
|
||||
Promise<boolean> persisted();
|
||||
|
||||
[Exposed=Window, Throws]
|
||||
Promise<boolean> persist();
|
||||
|
||||
[Throws]
|
||||
Promise<StorageEstimate> estimate();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче