LCOV - code coverage report
Current view: top level - dom/quota - StorageManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 6 367 1.6 %
Date: 2017-07-14 16:53:18 Functions: 3 70 4.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "StorageManager.h"
       8             : 
       9             : #include "mozilla/dom/PromiseWorkerProxy.h"
      10             : #include "mozilla/dom/quota/QuotaManagerService.h"
      11             : #include "mozilla/dom/StorageManagerBinding.h"
      12             : #include "mozilla/dom/WorkerPrivate.h"
      13             : #include "mozilla/ErrorResult.h"
      14             : #include "mozilla/Telemetry.h"
      15             : #include "nsContentPermissionHelper.h"
      16             : #include "nsIQuotaCallbacks.h"
      17             : #include "nsIQuotaRequests.h"
      18             : #include "nsPIDOMWindow.h"
      19             : 
      20             : using namespace mozilla::dom::workers;
      21             : 
      22             : namespace mozilla {
      23             : namespace dom {
      24             : 
      25             : namespace {
      26             : 
      27             : // This class is used to get quota usage, request persist and check persisted
      28             : // status callbacks.
      29             : class RequestResolver final
      30             :   : public nsIQuotaCallback
      31             :   , public nsIQuotaUsageCallback
      32             : {
      33             : public:
      34             :   enum Type
      35             :   {
      36             :     Estimate,
      37             :     Persist,
      38             :     Persisted
      39             :   };
      40             : 
      41             : private:
      42             :   class FinishWorkerRunnable;
      43             : 
      44             :   // If this resolver was created for a window then mPromise must be non-null.
      45             :   // Otherwise mProxy must be non-null.
      46             :   RefPtr<Promise> mPromise;
      47             :   RefPtr<PromiseWorkerProxy> mProxy;
      48             : 
      49             :   nsresult mResultCode;
      50             :   StorageEstimate mStorageEstimate;
      51             :   const Type mType;
      52             :   bool mPersisted;
      53             : 
      54             : public:
      55           0 :   RequestResolver(Type aType, Promise* aPromise)
      56           0 :     : mPromise(aPromise)
      57             :     , mResultCode(NS_OK)
      58             :     , mType(aType)
      59           0 :     , mPersisted(false)
      60             :   {
      61           0 :     MOZ_ASSERT(NS_IsMainThread());
      62           0 :     MOZ_ASSERT(aPromise);
      63           0 :   }
      64             : 
      65           0 :   RequestResolver(Type aType, PromiseWorkerProxy* aProxy)
      66           0 :     : mProxy(aProxy)
      67             :     , mResultCode(NS_OK)
      68             :     , mType(aType)
      69           0 :     , mPersisted(false)
      70             :   {
      71           0 :     MOZ_ASSERT(NS_IsMainThread());
      72           0 :     MOZ_ASSERT(aProxy);
      73           0 :   }
      74             : 
      75             :   void
      76             :   ResolveOrReject();
      77             : 
      78             :   NS_DECL_THREADSAFE_ISUPPORTS
      79             :   NS_DECL_NSIQUOTACALLBACK
      80             :   NS_DECL_NSIQUOTAUSAGECALLBACK
      81             : 
      82             : private:
      83           0 :   ~RequestResolver()
      84           0 :   { }
      85             : 
      86             :   nsresult
      87             :   GetStorageEstimate(nsIVariant* aResult);
      88             : 
      89             :   nsresult
      90             :   GetPersisted(nsIVariant* aResult);
      91             : 
      92             :   template <typename T>
      93             :   nsresult
      94             :   OnCompleteOrUsageResult(T* aRequest);
      95             : 
      96             :   nsresult
      97             :   Finish();
      98             : };
      99             : 
     100             : // This class is used to return promise on worker thread.
     101           0 : class RequestResolver::FinishWorkerRunnable final
     102             :   : public WorkerRunnable
     103             : {
     104             :   RefPtr<RequestResolver> mResolver;
     105             : 
     106             : public:
     107           0 :   explicit FinishWorkerRunnable(RequestResolver* aResolver)
     108           0 :     : WorkerRunnable(aResolver->mProxy->GetWorkerPrivate())
     109           0 :     , mResolver(aResolver)
     110             :   {
     111           0 :     MOZ_ASSERT(NS_IsMainThread());
     112           0 :     MOZ_ASSERT(aResolver);
     113           0 :   }
     114             : 
     115             :   bool
     116             :   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
     117             : };
     118             : 
     119           0 : class EstimateWorkerMainThreadRunnable final
     120             :   : public WorkerMainThreadRunnable
     121             : {
     122             :   RefPtr<PromiseWorkerProxy> mProxy;
     123             : 
     124             : public:
     125           0 :   EstimateWorkerMainThreadRunnable(WorkerPrivate* aWorkerPrivate,
     126             :                                    PromiseWorkerProxy* aProxy)
     127           0 :     : WorkerMainThreadRunnable(aWorkerPrivate,
     128           0 :                                NS_LITERAL_CSTRING("StorageManager :: Estimate"))
     129           0 :     , mProxy(aProxy)
     130             :   {
     131           0 :     MOZ_ASSERT(aWorkerPrivate);
     132           0 :     aWorkerPrivate->AssertIsOnWorkerThread();
     133           0 :     MOZ_ASSERT(aProxy);
     134           0 :   }
     135             : 
     136             :   bool
     137             :   MainThreadRun() override;
     138             : };
     139             : 
     140           0 : class PersistedWorkerMainThreadRunnable final
     141             :   : public WorkerMainThreadRunnable
     142             : {
     143             :   RefPtr<PromiseWorkerProxy> mProxy;
     144             : 
     145             : public:
     146           0 :   PersistedWorkerMainThreadRunnable(WorkerPrivate* aWorkerPrivate,
     147             :                                     PromiseWorkerProxy* aProxy)
     148           0 :     : WorkerMainThreadRunnable(aWorkerPrivate,
     149           0 :                                NS_LITERAL_CSTRING("StorageManager :: Persisted"))
     150           0 :     , mProxy(aProxy)
     151             :   {
     152           0 :     MOZ_ASSERT(aWorkerPrivate);
     153           0 :     aWorkerPrivate->AssertIsOnWorkerThread();
     154           0 :     MOZ_ASSERT(aProxy);
     155           0 :   }
     156             : 
     157             :   bool
     158             :   MainThreadRun() override;
     159             : };
     160             : 
     161             : /*******************************************************************************
     162             :  * PersistentStoragePermissionRequest
     163             :  ******************************************************************************/
     164             : 
     165             : class PersistentStoragePermissionRequest final
     166             :   : public nsIContentPermissionRequest
     167             : {
     168             :   nsCOMPtr<nsIPrincipal> mPrincipal;
     169             :   nsCOMPtr<nsPIDOMWindowInner> mWindow;
     170             :   RefPtr<Promise> mPromise;
     171             :   nsCOMPtr<nsIContentPermissionRequester> mRequester;
     172             : 
     173             : public:
     174           0 :   PersistentStoragePermissionRequest(nsIPrincipal* aPrincipal,
     175             :                                      nsPIDOMWindowInner* aWindow,
     176             :                                      Promise* aPromise)
     177           0 :     : mPrincipal(aPrincipal)
     178             :     , mWindow(aWindow)
     179           0 :     , mPromise(aPromise)
     180             :   {
     181           0 :     MOZ_ASSERT(aPrincipal);
     182           0 :     MOZ_ASSERT(aWindow);
     183           0 :     MOZ_ASSERT(aPromise);
     184             : 
     185           0 :     mRequester = new nsContentPermissionRequester(mWindow);
     186           0 :   }
     187             : 
     188             :   nsresult
     189             :   Start();
     190             : 
     191             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     192             :   NS_DECL_NSICONTENTPERMISSIONREQUEST
     193           0 :   NS_DECL_CYCLE_COLLECTION_CLASS(PersistentStoragePermissionRequest)
     194             : 
     195             : private:
     196           0 :   ~PersistentStoragePermissionRequest()
     197           0 :   { }
     198             : };
     199             : 
     200             : nsresult
     201           0 : GetUsageForPrincipal(nsIPrincipal* aPrincipal,
     202             :                      nsIQuotaUsageCallback* aCallback,
     203             :                      nsIQuotaUsageRequest** aRequest)
     204             : {
     205           0 :   MOZ_ASSERT(aPrincipal);
     206           0 :   MOZ_ASSERT(aCallback);
     207           0 :   MOZ_ASSERT(aRequest);
     208             : 
     209           0 :   nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
     210           0 :   if (NS_WARN_IF(!qms)) {
     211           0 :     return NS_ERROR_FAILURE;
     212             :   }
     213             : 
     214           0 :   nsresult rv = qms->GetUsageForPrincipal(aPrincipal,
     215             :                                           aCallback,
     216             :                                           true,
     217           0 :                                           aRequest);
     218           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     219           0 :     return rv;
     220             :   }
     221             : 
     222           0 :   return NS_OK;
     223             : };
     224             : 
     225             : nsresult
     226           0 : Persisted(nsIPrincipal* aPrincipal,
     227             :           nsIQuotaCallback* aCallback,
     228             :           nsIQuotaRequest** aRequest)
     229             : {
     230           0 :   MOZ_ASSERT(aPrincipal);
     231           0 :   MOZ_ASSERT(aCallback);
     232           0 :   MOZ_ASSERT(aRequest);
     233             : 
     234           0 :   nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
     235           0 :   if (NS_WARN_IF(!qms)) {
     236           0 :     return NS_ERROR_FAILURE;
     237             :   }
     238             : 
     239           0 :   nsCOMPtr<nsIQuotaRequest> request;
     240           0 :   nsresult rv = qms->Persisted(aPrincipal, getter_AddRefs(request));
     241           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     242           0 :     return rv;
     243             :   }
     244             : 
     245             :   // All the methods in nsIQuotaManagerService shouldn't synchronously fire
     246             :   // any callbacks when they are being executed. Even when a result is ready,
     247             :   // a new runnable should be dispatched to current thread to fire the callback
     248             :   // asynchronously. It's safe to set the callback after we call Persisted().
     249           0 :   MOZ_ALWAYS_SUCCEEDS(request->SetCallback(aCallback));
     250             : 
     251           0 :   request.forget(aRequest);
     252             : 
     253           0 :   return NS_OK;
     254             : };
     255             : 
     256             : already_AddRefed<Promise>
     257           0 : ExecuteOpOnMainOrWorkerThread(nsIGlobalObject* aGlobal,
     258             :                               RequestResolver::Type aType,
     259             :                               ErrorResult& aRv)
     260             : {
     261           0 :   MOZ_ASSERT(aGlobal);
     262           0 :   MOZ_ASSERT_IF(aType == RequestResolver::Type::Persist,
     263             :                 NS_IsMainThread());
     264             : 
     265           0 :   RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
     266           0 :   if (NS_WARN_IF(!promise)) {
     267           0 :     return nullptr;
     268             :   }
     269             : 
     270           0 :   if (NS_IsMainThread()) {
     271           0 :     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
     272           0 :     if (NS_WARN_IF(!window)) {
     273           0 :       aRv.Throw(NS_ERROR_FAILURE);
     274           0 :       return nullptr;
     275             :     }
     276             : 
     277           0 :     nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
     278           0 :     if (NS_WARN_IF(!doc)) {
     279           0 :       aRv.Throw(NS_ERROR_FAILURE);
     280           0 :       return nullptr;
     281             :     }
     282             : 
     283           0 :     nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
     284           0 :     MOZ_ASSERT(principal);
     285             : 
     286             :     // Storage Standard 7. API
     287             :     // If origin is an opaque origin, then reject promise with a TypeError.
     288           0 :     if (principal->GetIsNullPrincipal()) {
     289           0 :       promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
     290           0 :       return promise.forget();
     291             :     }
     292             : 
     293           0 :     switch (aType) {
     294             :       case RequestResolver::Type::Persisted: {
     295             :         RefPtr<RequestResolver> resolver =
     296           0 :           new RequestResolver(RequestResolver::Type::Persisted, promise);
     297             : 
     298           0 :         RefPtr<nsIQuotaRequest> request;
     299           0 :         aRv = Persisted(principal, resolver, getter_AddRefs(request));
     300             : 
     301           0 :         break;
     302             :       }
     303             : 
     304             :       case RequestResolver::Type::Persist: {
     305             :         RefPtr<PersistentStoragePermissionRequest> request =
     306           0 :           new PersistentStoragePermissionRequest(principal, window, promise);
     307             : 
     308             :         // In private browsing mode, no permission prompt.
     309           0 :         if (nsContentUtils::IsInPrivateBrowsing(doc)) {
     310           0 :           aRv = request->Cancel();
     311             :         } else {
     312           0 :           aRv = request->Start();
     313             :         }
     314             : 
     315           0 :         break;
     316             :       }
     317             : 
     318             :       case RequestResolver::Type::Estimate: {
     319             :         RefPtr<RequestResolver> resolver =
     320           0 :           new RequestResolver(RequestResolver::Type::Estimate, promise);
     321             : 
     322           0 :         RefPtr<nsIQuotaUsageRequest> request;
     323           0 :         aRv = GetUsageForPrincipal(principal,
     324             :                                    resolver,
     325           0 :                                    getter_AddRefs(request));
     326             : 
     327           0 :         break;
     328             :       }
     329             : 
     330             :       default:
     331           0 :         MOZ_CRASH("Invalid aRequest type!");
     332             :     }
     333             : 
     334           0 :     if (NS_WARN_IF(aRv.Failed())) {
     335           0 :       return nullptr;
     336             :     }
     337             : 
     338           0 :     return promise.forget();
     339             :   }
     340             : 
     341           0 :   WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     342           0 :   MOZ_ASSERT(workerPrivate);
     343             : 
     344             :   RefPtr<PromiseWorkerProxy> promiseProxy =
     345           0 :     PromiseWorkerProxy::Create(workerPrivate, promise);
     346           0 :   if (NS_WARN_IF(!promiseProxy)) {
     347           0 :     return nullptr;
     348             :   }
     349             : 
     350           0 :   switch (aType) {
     351             :     case RequestResolver::Type::Estimate: {
     352             :       RefPtr<EstimateWorkerMainThreadRunnable> runnnable =
     353           0 :         new EstimateWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(),
     354           0 :                                              promiseProxy);
     355           0 :       runnnable->Dispatch(Terminating, aRv);
     356             : 
     357           0 :       break;
     358             :     }
     359             : 
     360             :     case RequestResolver::Type::Persisted: {
     361             :       RefPtr<PersistedWorkerMainThreadRunnable> runnnable =
     362           0 :         new PersistedWorkerMainThreadRunnable(promiseProxy->GetWorkerPrivate(),
     363           0 :                                               promiseProxy);
     364           0 :       runnnable->Dispatch(Terminating, aRv);
     365             : 
     366           0 :       break;
     367             :     }
     368             : 
     369             :     default:
     370           0 :       MOZ_CRASH("Invalid aRequest type");
     371             :   }
     372             : 
     373           0 :   if (NS_WARN_IF(aRv.Failed())) {
     374           0 :     return nullptr;
     375             :   }
     376             : 
     377           0 :   return promise.forget();
     378             : };
     379             : 
     380             : } // namespace
     381             : 
     382             : /*******************************************************************************
     383             :  * Local class implementations
     384             :  ******************************************************************************/
     385             : 
     386             : void
     387           0 : RequestResolver::ResolveOrReject()
     388             : {
     389             :   class MOZ_STACK_CLASS AutoCleanup final
     390             :   {
     391             :     RefPtr<PromiseWorkerProxy> mProxy;
     392             : 
     393             :   public:
     394           0 :     explicit AutoCleanup(PromiseWorkerProxy* aProxy)
     395           0 :       : mProxy(aProxy)
     396             :     {
     397           0 :       MOZ_ASSERT(aProxy);
     398           0 :     }
     399             : 
     400           0 :     ~AutoCleanup()
     401           0 :     {
     402           0 :       MOZ_ASSERT(mProxy);
     403             : 
     404           0 :       mProxy->CleanUp();
     405           0 :     }
     406             :   };
     407             : 
     408           0 :   RefPtr<Promise> promise;
     409           0 :   Maybe<AutoCleanup> autoCleanup;
     410             : 
     411           0 :   if (mPromise) {
     412           0 :     promise = mPromise;
     413             :   } else {
     414           0 :     MOZ_ASSERT(mProxy);
     415             : 
     416           0 :     promise = mProxy->WorkerPromise();
     417             : 
     418             :     // Only clean up for worker case.
     419           0 :     autoCleanup.emplace(mProxy);
     420             :   }
     421             : 
     422           0 :   MOZ_ASSERT(promise);
     423             : 
     424           0 :   if (mType == Type::Estimate) {
     425           0 :     if (NS_SUCCEEDED(mResultCode)) {
     426           0 :       promise->MaybeResolve(mStorageEstimate);
     427             :     } else {
     428           0 :       promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
     429             :     }
     430             : 
     431           0 :     return;
     432             :   }
     433             : 
     434           0 :   MOZ_ASSERT(mType == Type::Persist || mType == Type::Persisted);
     435             : 
     436           0 :   if (NS_SUCCEEDED(mResultCode)) {
     437           0 :     promise->MaybeResolve(mPersisted);
     438             :   } else {
     439           0 :     promise->MaybeResolve(false);
     440             :   }
     441             : }
     442             : 
     443           0 : NS_IMPL_ISUPPORTS(RequestResolver, nsIQuotaUsageCallback, nsIQuotaCallback)
     444             : 
     445             : nsresult
     446           0 : RequestResolver::GetStorageEstimate(nsIVariant* aResult)
     447             : {
     448           0 :   MOZ_ASSERT(aResult);
     449           0 :   MOZ_ASSERT(mType == Type::Estimate);
     450             : 
     451             : #ifdef DEBUG
     452             :   uint16_t dataType;
     453           0 :   MOZ_ALWAYS_SUCCEEDS(aResult->GetDataType(&dataType));
     454           0 :   MOZ_ASSERT(dataType == nsIDataType::VTYPE_INTERFACE_IS);
     455             : #endif
     456             : 
     457             :   nsID* iid;
     458           0 :   nsCOMPtr<nsISupports> supports;
     459           0 :   nsresult rv = aResult->GetAsInterface(&iid, getter_AddRefs(supports));
     460           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     461           0 :     return rv;
     462             :   }
     463             : 
     464           0 :   free(iid);
     465             : 
     466             :   nsCOMPtr<nsIQuotaOriginUsageResult> originUsageResult =
     467           0 :     do_QueryInterface(supports);
     468           0 :   MOZ_ASSERT(originUsageResult);
     469             : 
     470           0 :   MOZ_ALWAYS_SUCCEEDS(
     471             :     originUsageResult->GetUsage(&mStorageEstimate.mUsage.Construct()));
     472             : 
     473           0 :   MOZ_ALWAYS_SUCCEEDS(
     474             :     originUsageResult->GetLimit(&mStorageEstimate.mQuota.Construct()));
     475             : 
     476           0 :   return NS_OK;
     477             : }
     478             : 
     479             : nsresult
     480           0 : RequestResolver::GetPersisted(nsIVariant* aResult)
     481             : {
     482           0 :   MOZ_ASSERT(aResult);
     483           0 :   MOZ_ASSERT(mType == Type::Persist || mType == Type::Persisted);
     484             : 
     485             : #ifdef DEBUG
     486             :   uint16_t dataType;
     487           0 :   MOZ_ALWAYS_SUCCEEDS(aResult->GetDataType(&dataType));
     488             : #endif
     489             : 
     490           0 :   if (mType == Type::Persist) {
     491           0 :     MOZ_ASSERT(dataType == nsIDataType::VTYPE_VOID);
     492             : 
     493           0 :     mPersisted = true;
     494           0 :     return NS_OK;
     495             :   }
     496             : 
     497           0 :   MOZ_ASSERT(dataType == nsIDataType::VTYPE_BOOL);
     498             : 
     499             :   bool persisted;
     500           0 :   nsresult rv = aResult->GetAsBool(&persisted);
     501           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     502           0 :     return rv;
     503             :   }
     504             : 
     505           0 :   mPersisted = persisted;
     506           0 :   return NS_OK;
     507             : }
     508             : 
     509             : template <typename T>
     510             : nsresult
     511           0 : RequestResolver::OnCompleteOrUsageResult(T* aRequest)
     512             : {
     513           0 :   MOZ_ASSERT(NS_IsMainThread());
     514           0 :   MOZ_ASSERT(aRequest);
     515             : 
     516             :   nsresult resultCode;
     517           0 :   nsresult rv = aRequest->GetResultCode(&resultCode);
     518           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     519           0 :     return rv;
     520             :   }
     521             : 
     522           0 :   if (NS_FAILED(resultCode)) {
     523           0 :     return resultCode;
     524             :   }
     525             : 
     526           0 :   nsCOMPtr<nsIVariant> result;
     527           0 :   rv = aRequest->GetResult(getter_AddRefs(result));
     528           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     529           0 :     return rv;
     530             :   }
     531             : 
     532           0 :   if (mType == Type::Estimate) {
     533           0 :     rv = GetStorageEstimate(result);
     534             :   } else {
     535           0 :     MOZ_ASSERT(mType == Type::Persist || mType == Type::Persisted);
     536             : 
     537           0 :     rv = GetPersisted(result);
     538             :   }
     539           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     540           0 :     return rv;
     541             :   }
     542             : 
     543           0 :   return NS_OK;
     544             : }
     545             : 
     546             : nsresult
     547           0 : RequestResolver::Finish()
     548             : {
     549             :   // In a main thread request.
     550           0 :   if (!mProxy) {
     551           0 :     MOZ_ASSERT(mPromise);
     552             : 
     553           0 :     ResolveOrReject();
     554           0 :     return NS_OK;
     555             :   }
     556             : 
     557             :   {
     558             :     // In a worker thread request.
     559           0 :     MutexAutoLock lock(mProxy->Lock());
     560             : 
     561           0 :     if (NS_WARN_IF(mProxy->CleanedUp())) {
     562           0 :       return NS_ERROR_FAILURE;
     563             :     }
     564             : 
     565           0 :     RefPtr<FinishWorkerRunnable> runnable = new FinishWorkerRunnable(this);
     566           0 :     if (NS_WARN_IF(!runnable->Dispatch())) {
     567           0 :       return NS_ERROR_FAILURE;
     568             :     }
     569             :   }
     570             : 
     571           0 :   return NS_OK;
     572             : }
     573             : 
     574             : NS_IMETHODIMP
     575           0 : RequestResolver::OnComplete(nsIQuotaRequest *aRequest)
     576             : {
     577           0 :   MOZ_ASSERT(NS_IsMainThread());
     578           0 :   MOZ_ASSERT(aRequest);
     579             : 
     580           0 :   mResultCode = OnCompleteOrUsageResult(aRequest);
     581             : 
     582           0 :   nsresult rv = Finish();
     583           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     584           0 :     return rv;
     585             :   }
     586             : 
     587           0 :   return NS_OK;
     588             : }
     589             : 
     590             : NS_IMETHODIMP
     591           0 : RequestResolver::OnUsageResult(nsIQuotaUsageRequest *aRequest)
     592             : {
     593           0 :   MOZ_ASSERT(NS_IsMainThread());
     594           0 :   MOZ_ASSERT(aRequest);
     595             : 
     596           0 :   mResultCode = OnCompleteOrUsageResult(aRequest);
     597             : 
     598           0 :   nsresult rv = Finish();
     599           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     600           0 :     return rv;
     601             :   }
     602             : 
     603           0 :   return NS_OK;
     604             : }
     605             : 
     606             : bool
     607           0 : RequestResolver::
     608             : FinishWorkerRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
     609             : {
     610           0 :   MOZ_ASSERT(aCx);
     611           0 :   MOZ_ASSERT(aWorkerPrivate);
     612           0 :   aWorkerPrivate->AssertIsOnWorkerThread();
     613             : 
     614           0 :   MOZ_ASSERT(mResolver);
     615           0 :   mResolver->ResolveOrReject();
     616             : 
     617           0 :   return true;
     618             : }
     619             : 
     620             : bool
     621           0 : EstimateWorkerMainThreadRunnable::MainThreadRun()
     622             : {
     623           0 :   MOZ_ASSERT(NS_IsMainThread());
     624             : 
     625           0 :   nsCOMPtr<nsIPrincipal> principal;
     626             : 
     627             :   {
     628           0 :     MutexAutoLock lock(mProxy->Lock());
     629           0 :     if (mProxy->CleanedUp()) {
     630           0 :       return true;
     631             :     }
     632           0 :     principal = mProxy->GetWorkerPrivate()->GetPrincipal();
     633             :   }
     634             : 
     635           0 :   MOZ_ASSERT(principal);
     636             : 
     637             :   RefPtr<RequestResolver> resolver =
     638           0 :     new RequestResolver(RequestResolver::Type::Estimate, mProxy);
     639             : 
     640           0 :   RefPtr<nsIQuotaUsageRequest> request;
     641             :   nsresult rv =
     642           0 :     GetUsageForPrincipal(principal, resolver, getter_AddRefs(request));
     643           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     644           0 :     return false;
     645             :   }
     646             : 
     647           0 :   return true;
     648             : }
     649             : 
     650             : bool
     651           0 : PersistedWorkerMainThreadRunnable::MainThreadRun()
     652             : {
     653           0 :   MOZ_ASSERT(NS_IsMainThread());
     654             : 
     655           0 :   nsCOMPtr<nsIPrincipal> principal;
     656             : 
     657             :   {
     658           0 :     MutexAutoLock lock(mProxy->Lock());
     659           0 :     if (mProxy->CleanedUp()) {
     660           0 :       return true;
     661             :     }
     662           0 :     principal = mProxy->GetWorkerPrivate()->GetPrincipal();
     663             :   }
     664             : 
     665           0 :   MOZ_ASSERT(principal);
     666             : 
     667             :   RefPtr<RequestResolver> resolver =
     668           0 :     new RequestResolver(RequestResolver::Type::Persisted, mProxy);
     669             : 
     670           0 :   RefPtr<nsIQuotaRequest> request;
     671           0 :   nsresult rv = Persisted(principal, resolver, getter_AddRefs(request));
     672           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     673           0 :     return false;
     674             :   }
     675             : 
     676           0 :   return true;
     677             : }
     678             : 
     679             : nsresult
     680           0 : PersistentStoragePermissionRequest::Start()
     681             : {
     682           0 :   MOZ_ASSERT(NS_IsMainThread());
     683             : 
     684             :   // Grant permission if pref'ed on.
     685           0 :   if (Preferences::GetBool("dom.storageManager.prompt.testing", false)) {
     686           0 :     if (Preferences::GetBool("dom.storageManager.prompt.testing.allow",
     687             :                              false)) {
     688           0 :       return Allow(JS::UndefinedHandleValue);
     689             :     }
     690             : 
     691           0 :     return Cancel();
     692             :   }
     693             : 
     694           0 :   return nsContentPermissionUtils::AskPermission(this, mWindow);
     695             : }
     696             : 
     697           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(PersistentStoragePermissionRequest)
     698           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(PersistentStoragePermissionRequest)
     699             : 
     700           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PersistentStoragePermissionRequest)
     701           0 :   NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
     702           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     703           0 : NS_INTERFACE_MAP_END
     704             : 
     705           0 : NS_IMPL_CYCLE_COLLECTION(PersistentStoragePermissionRequest, mWindow, mPromise)
     706             : 
     707             : NS_IMETHODIMP
     708           0 : PersistentStoragePermissionRequest::GetPrincipal(nsIPrincipal** aPrincipal)
     709             : {
     710           0 :   MOZ_ASSERT(NS_IsMainThread());
     711           0 :   MOZ_ASSERT(aPrincipal);
     712           0 :   MOZ_ASSERT(mPrincipal);
     713             : 
     714           0 :   NS_ADDREF(*aPrincipal = mPrincipal);
     715             : 
     716           0 :   return NS_OK;
     717             : }
     718             : 
     719             : NS_IMETHODIMP
     720           0 : PersistentStoragePermissionRequest::GetWindow(mozIDOMWindow** aRequestingWindow)
     721             : {
     722           0 :   MOZ_ASSERT(NS_IsMainThread());
     723           0 :   MOZ_ASSERT(aRequestingWindow);
     724           0 :   MOZ_ASSERT(mWindow);
     725             : 
     726           0 :   NS_ADDREF(*aRequestingWindow = mWindow);
     727             : 
     728           0 :   return NS_OK;
     729             : }
     730             : 
     731             : NS_IMETHODIMP
     732           0 : PersistentStoragePermissionRequest::GetElement(nsIDOMElement** aElement)
     733             : {
     734           0 :   MOZ_ASSERT(NS_IsMainThread());
     735           0 :   MOZ_ASSERT(aElement);
     736             : 
     737           0 :   *aElement = nullptr;
     738           0 :   return NS_OK;
     739             : }
     740             : 
     741             : NS_IMETHODIMP
     742           0 : PersistentStoragePermissionRequest::Cancel()
     743             : {
     744           0 :   MOZ_ASSERT(NS_IsMainThread());
     745           0 :   MOZ_ASSERT(mPromise);
     746             : 
     747             :   RefPtr<RequestResolver> resolver =
     748           0 :     new RequestResolver(RequestResolver::Type::Persisted, mPromise);
     749             : 
     750           0 :   RefPtr<nsIQuotaRequest> request;
     751             : 
     752           0 :   return Persisted(mPrincipal, resolver, getter_AddRefs(request));
     753             : }
     754             : 
     755             : NS_IMETHODIMP
     756           0 : PersistentStoragePermissionRequest::Allow(JS::HandleValue aChoices)
     757             : {
     758           0 :   MOZ_ASSERT(NS_IsMainThread());
     759             : 
     760             :   RefPtr<RequestResolver> resolver =
     761           0 :     new RequestResolver(RequestResolver::Type::Persist, mPromise);
     762             : 
     763           0 :   nsCOMPtr<nsIQuotaManagerService> qms = QuotaManagerService::GetOrCreate();
     764           0 :   if (NS_WARN_IF(!qms)) {
     765           0 :     return NS_ERROR_FAILURE;
     766             :   }
     767             : 
     768           0 :   RefPtr<nsIQuotaRequest> request;
     769             : 
     770           0 :   nsresult rv = qms->Persist(mPrincipal, getter_AddRefs(request));
     771           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     772           0 :     return rv;
     773             :   }
     774             : 
     775           0 :   MOZ_ALWAYS_SUCCEEDS(request->SetCallback(resolver));
     776             : 
     777           0 :   return NS_OK;
     778             : }
     779             : 
     780             : NS_IMETHODIMP
     781           0 : PersistentStoragePermissionRequest::GetRequester(
     782             :                                      nsIContentPermissionRequester** aRequester)
     783             : {
     784           0 :   MOZ_ASSERT(NS_IsMainThread());
     785           0 :   MOZ_ASSERT(aRequester);
     786             : 
     787           0 :   nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
     788           0 :   requester.forget(aRequester);
     789             : 
     790           0 :   return NS_OK;
     791             : }
     792             : 
     793             : NS_IMETHODIMP
     794           0 : PersistentStoragePermissionRequest::GetTypes(nsIArray** aTypes)
     795             : {
     796           0 :   MOZ_ASSERT(aTypes);
     797             : 
     798           0 :   nsTArray<nsString> emptyOptions;
     799             : 
     800           0 :   return nsContentPermissionUtils::CreatePermissionArray(
     801           0 :                                        NS_LITERAL_CSTRING("persistent-storage"),
     802           0 :                                        NS_LITERAL_CSTRING("unused"),
     803             :                                        emptyOptions,
     804           0 :                                        aTypes);
     805             : }
     806             : 
     807             : /*******************************************************************************
     808             :  * StorageManager
     809             :  ******************************************************************************/
     810             : 
     811           0 : StorageManager::StorageManager(nsIGlobalObject* aGlobal)
     812           0 :   : mOwner(aGlobal)
     813             : {
     814           0 :   MOZ_ASSERT(aGlobal);
     815           0 : }
     816             : 
     817           0 : StorageManager::~StorageManager()
     818             : {
     819           0 : }
     820             : 
     821             : already_AddRefed<Promise>
     822           0 : StorageManager::Persisted(ErrorResult& aRv)
     823             : {
     824           0 :   MOZ_ASSERT(mOwner);
     825             : 
     826             :   return ExecuteOpOnMainOrWorkerThread(mOwner,
     827             :                                        RequestResolver::Type::Persisted,
     828           0 :                                        aRv);
     829             : }
     830             : 
     831             : already_AddRefed<Promise>
     832           0 : StorageManager::Persist(ErrorResult& aRv)
     833             : {
     834           0 :   MOZ_ASSERT(mOwner);
     835             : 
     836           0 :   Telemetry::ScalarAdd(Telemetry::ScalarID::NAVIGATOR_STORAGE_PERSIST_COUNT, 1);
     837             :   return ExecuteOpOnMainOrWorkerThread(mOwner,
     838             :                                        RequestResolver::Type::Persist,
     839           0 :                                        aRv);
     840             : }
     841             : 
     842             : already_AddRefed<Promise>
     843           0 : StorageManager::Estimate(ErrorResult& aRv)
     844             : {
     845           0 :   MOZ_ASSERT(mOwner);
     846             : 
     847             :   Telemetry::ScalarAdd(Telemetry::ScalarID::NAVIGATOR_STORAGE_ESTIMATE_COUNT,
     848           0 :                        1);
     849             :   return ExecuteOpOnMainOrWorkerThread(mOwner,
     850             :                                        RequestResolver::Type::Estimate,
     851           0 :                                        aRv);
     852             : }
     853             : 
     854             : // static
     855             : bool
     856           2 : StorageManager::PrefEnabled(JSContext* aCx, JSObject* aObj)
     857             : {
     858           2 :   if (NS_IsMainThread()) {
     859           0 :     return Preferences::GetBool("dom.storageManager.enabled");
     860             :   }
     861             : 
     862           2 :   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
     863           2 :   MOZ_ASSERT(workerPrivate);
     864             : 
     865           2 :   return workerPrivate->StorageManagerEnabled();
     866             : }
     867             : 
     868           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(StorageManager, mOwner)
     869             : 
     870           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(StorageManager)
     871           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(StorageManager)
     872             : 
     873           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StorageManager)
     874           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     875           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     876           0 : NS_INTERFACE_MAP_END
     877             : 
     878             : JSObject*
     879           0 : StorageManager::WrapObject(JSContext* aCx,
     880             :                            JS::Handle<JSObject*> aGivenProto)
     881             : {
     882           0 :   return StorageManagerBinding::Wrap(aCx, this, aGivenProto);
     883             : }
     884             : 
     885             : } // namespace dom
     886           9 : } // namespace mozilla

Generated by: LCOV version 1.13