LCOV - code coverage report
Current view: top level - dom/cache - Cache.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 8 323 2.5 %
Date: 2017-07-14 16:53:18 Functions: 1 39 2.6 %
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
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/dom/cache/Cache.h"
       8             : 
       9             : #include "mozilla/dom/Headers.h"
      10             : #include "mozilla/dom/InternalResponse.h"
      11             : #include "mozilla/dom/Promise.h"
      12             : #include "mozilla/dom/PromiseNativeHandler.h"
      13             : #include "mozilla/dom/Response.h"
      14             : #include "mozilla/dom/WorkerPrivate.h"
      15             : #include "mozilla/dom/CacheBinding.h"
      16             : #include "mozilla/dom/cache/AutoUtils.h"
      17             : #include "mozilla/dom/cache/CacheChild.h"
      18             : #include "mozilla/dom/cache/CacheWorkerHolder.h"
      19             : #include "mozilla/dom/cache/ReadStream.h"
      20             : #include "mozilla/ErrorResult.h"
      21             : #include "mozilla/Preferences.h"
      22             : #include "mozilla/Unused.h"
      23             : #include "nsIGlobalObject.h"
      24             : 
      25             : namespace mozilla {
      26             : namespace dom {
      27             : namespace cache {
      28             : 
      29             : using mozilla::dom::workers::GetCurrentThreadWorkerPrivate;
      30             : using mozilla::dom::workers::WorkerPrivate;
      31             : using mozilla::ipc::PBackgroundChild;
      32             : 
      33             : namespace {
      34             : 
      35             : enum class PutStatusPolicy {
      36             :   Default,
      37             :   RequireOK
      38             : };
      39             : 
      40             : bool
      41           0 : IsValidPutRequestURL(const nsAString& aUrl, ErrorResult& aRv)
      42             : {
      43           0 :   bool validScheme = false;
      44             : 
      45             :   // make a copy because ProcessURL strips the fragmet
      46           0 :   NS_ConvertUTF16toUTF8 url(aUrl);
      47             : 
      48           0 :   TypeUtils::ProcessURL(url, &validScheme, nullptr, nullptr, aRv);
      49           0 :   if (aRv.Failed()) {
      50           0 :     return false;
      51             :   }
      52             : 
      53           0 :   if (!validScheme) {
      54           0 :     aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(NS_LITERAL_STRING("Request"),
      55           0 :                                                aUrl);
      56           0 :     return false;
      57             :   }
      58             : 
      59           0 :   return true;
      60             : }
      61             : 
      62             : static bool
      63           0 : IsValidPutRequestMethod(const Request& aRequest, ErrorResult& aRv)
      64             : {
      65           0 :   nsAutoCString method;
      66           0 :   aRequest.GetMethod(method);
      67           0 :   if (!method.LowerCaseEqualsLiteral("get")) {
      68           0 :     NS_ConvertASCIItoUTF16 label(method);
      69           0 :     aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
      70           0 :     return false;
      71             :   }
      72             : 
      73           0 :   return true;
      74             : }
      75             : 
      76             : static bool
      77           0 : IsValidPutRequestMethod(const RequestOrUSVString& aRequest, ErrorResult& aRv)
      78             : {
      79             :   // If the provided request is a string URL, then it will default to
      80             :   // a valid http method automatically.
      81           0 :   if (!aRequest.IsRequest()) {
      82           0 :     return true;
      83             :   }
      84           0 :   return IsValidPutRequestMethod(aRequest.GetAsRequest(), aRv);
      85             : }
      86             : 
      87             : static bool
      88           0 : IsValidPutResponseStatus(Response& aResponse, PutStatusPolicy aPolicy,
      89             :                          ErrorResult& aRv)
      90             : {
      91           0 :   if ((aPolicy == PutStatusPolicy::RequireOK && !aResponse.Ok()) ||
      92           0 :       aResponse.Status() == 206) {
      93           0 :     uint32_t t = static_cast<uint32_t>(aResponse.Type());
      94           0 :     NS_ConvertASCIItoUTF16 type(ResponseTypeValues::strings[t].value,
      95           0 :                                 ResponseTypeValues::strings[t].length);
      96           0 :     nsAutoString status;
      97           0 :     status.AppendInt(aResponse.Status());
      98           0 :     nsAutoString url;
      99           0 :     aResponse.GetUrl(url);
     100           0 :     aRv.ThrowTypeError<MSG_CACHE_ADD_FAILED_RESPONSE>(type, status, url);
     101           0 :     return false;
     102             :   }
     103             : 
     104           0 :   return true;
     105             : }
     106             : 
     107             : } // namespace
     108             : 
     109             : // Helper class to wait for Add()/AddAll() fetch requests to complete and
     110             : // then perform a PutAll() with the responses.  This class holds a WorkerHolder
     111             : // to keep the Worker thread alive.  This is mainly to ensure that Add/AddAll
     112             : // act the same as other Cache operations that directly create a CacheOpChild
     113             : // actor.
     114             : class Cache::FetchHandler final : public PromiseNativeHandler
     115             : {
     116             : public:
     117           0 :   FetchHandler(CacheWorkerHolder* aWorkerHolder, Cache* aCache,
     118             :                nsTArray<RefPtr<Request>>&& aRequestList, Promise* aPromise)
     119           0 :     : mWorkerHolder(aWorkerHolder)
     120             :     , mCache(aCache)
     121           0 :     , mRequestList(Move(aRequestList))
     122           0 :     , mPromise(aPromise)
     123             :   {
     124           0 :     MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerHolder);
     125           0 :     MOZ_DIAGNOSTIC_ASSERT(mCache);
     126           0 :     MOZ_DIAGNOSTIC_ASSERT(mPromise);
     127           0 :   }
     128             : 
     129             :   virtual void
     130           0 :   ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
     131             :   {
     132           0 :     NS_ASSERT_OWNINGTHREAD(FetchHandler);
     133             : 
     134             :     // Stop holding the worker alive when we leave this method.
     135           0 :     RefPtr<CacheWorkerHolder> workerHolder;
     136           0 :     workerHolder.swap(mWorkerHolder);
     137             : 
     138             :     // Promise::All() passed an array of fetch() Promises should give us
     139             :     // an Array of Response objects.  The following code unwraps these
     140             :     // JS values back to an nsTArray<RefPtr<Response>>.
     141             : 
     142           0 :     AutoTArray<RefPtr<Response>, 256> responseList;
     143           0 :     responseList.SetCapacity(mRequestList.Length());
     144             : 
     145             :     bool isArray;
     146           0 :     if (NS_WARN_IF(!JS_IsArrayObject(aCx, aValue, &isArray) || !isArray)) {
     147           0 :       Fail();
     148           0 :       return;
     149             :     }
     150             : 
     151           0 :     JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
     152             : 
     153             :     uint32_t length;
     154           0 :     if (NS_WARN_IF(!JS_GetArrayLength(aCx, obj, &length))) {
     155           0 :       Fail();
     156           0 :       return;
     157             :     }
     158             : 
     159           0 :     for (uint32_t i = 0; i < length; ++i) {
     160           0 :       JS::Rooted<JS::Value> value(aCx);
     161             : 
     162           0 :       if (NS_WARN_IF(!JS_GetElement(aCx, obj, i, &value))) {
     163           0 :         Fail();
     164           0 :         return;
     165             :       }
     166             : 
     167           0 :       if (NS_WARN_IF(!value.isObject())) {
     168           0 :         Fail();
     169           0 :         return;
     170             :       }
     171             : 
     172           0 :       JS::Rooted<JSObject*> responseObj(aCx, &value.toObject());
     173             : 
     174           0 :       RefPtr<Response> response;
     175           0 :       nsresult rv = UNWRAP_OBJECT(Response, responseObj, response);
     176           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     177           0 :         Fail();
     178           0 :         return;
     179             :       }
     180             : 
     181           0 :       if (NS_WARN_IF(response->Type() == ResponseType::Error)) {
     182           0 :         Fail();
     183           0 :         return;
     184             :       }
     185             : 
     186             :       // Do not allow the convenience methods .add()/.addAll() to store failed
     187             :       // or invalid responses.  A consequence of this is that these methods
     188             :       // cannot be used to store opaque or opaqueredirect responses since they
     189             :       // always expose a 0 status value.
     190           0 :       ErrorResult errorResult;
     191           0 :       if (!IsValidPutResponseStatus(*response, PutStatusPolicy::RequireOK,
     192             :                                     errorResult)) {
     193             :         // TODO: abort the fetch requests we have running (bug 1157434)
     194           0 :         mPromise->MaybeReject(errorResult);
     195           0 :         return;
     196             :       }
     197             : 
     198           0 :       responseList.AppendElement(Move(response));
     199             :     }
     200             : 
     201           0 :     MOZ_DIAGNOSTIC_ASSERT(mRequestList.Length() == responseList.Length());
     202             : 
     203             :     // Now store the unwrapped Response list in the Cache.
     204           0 :     ErrorResult result;
     205           0 :     RefPtr<Promise> put = mCache->PutAll(mRequestList, responseList, result);
     206           0 :     if (NS_WARN_IF(result.Failed())) {
     207             :       // TODO: abort the fetch requests we have running (bug 1157434)
     208           0 :       mPromise->MaybeReject(result);
     209           0 :       return;
     210             :     }
     211             : 
     212             :     // Chain the Cache::Put() promise to the original promise returned to
     213             :     // the content script.
     214           0 :     mPromise->MaybeResolve(put);
     215             :   }
     216             : 
     217             :   virtual void
     218           0 :   RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
     219             :   {
     220           0 :     NS_ASSERT_OWNINGTHREAD(FetchHandler);
     221           0 :     Fail();
     222           0 :   }
     223             : 
     224             : private:
     225           0 :   ~FetchHandler()
     226           0 :   {
     227           0 :   }
     228             : 
     229             :   void
     230           0 :   Fail()
     231             :   {
     232           0 :     ErrorResult rv;
     233           0 :     rv.ThrowTypeError<MSG_FETCH_FAILED>();
     234           0 :     mPromise->MaybeReject(rv);
     235           0 :   }
     236             : 
     237             :   RefPtr<CacheWorkerHolder> mWorkerHolder;
     238             :   RefPtr<Cache> mCache;
     239             :   nsTArray<RefPtr<Request>> mRequestList;
     240             :   RefPtr<Promise> mPromise;
     241             : 
     242             :   NS_DECL_ISUPPORTS
     243             : };
     244             : 
     245           0 : NS_IMPL_ISUPPORTS0(Cache::FetchHandler)
     246             : 
     247           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::Cache);
     248           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::Cache);
     249           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::Cache, mGlobal);
     250             : 
     251           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Cache)
     252           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     253           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     254           0 : NS_INTERFACE_MAP_END
     255             : 
     256           0 : Cache::Cache(nsIGlobalObject* aGlobal, CacheChild* aActor)
     257             :   : mGlobal(aGlobal)
     258           0 :   , mActor(aActor)
     259             : {
     260           0 :   MOZ_DIAGNOSTIC_ASSERT(mGlobal);
     261           0 :   MOZ_DIAGNOSTIC_ASSERT(mActor);
     262           0 :   mActor->SetListener(this);
     263           0 : }
     264             : 
     265             : already_AddRefed<Promise>
     266           0 : Cache::Match(const RequestOrUSVString& aRequest,
     267             :              const CacheQueryOptions& aOptions, ErrorResult& aRv)
     268             : {
     269           0 :   if (NS_WARN_IF(!mActor)) {
     270           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     271           0 :     return nullptr;
     272             :   }
     273             : 
     274           0 :   CacheChild::AutoLock actorLock(mActor);
     275             : 
     276           0 :   RefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
     277           0 :   if (NS_WARN_IF(aRv.Failed())) {
     278           0 :     return nullptr;
     279             :   }
     280             : 
     281           0 :   CacheQueryParams params;
     282           0 :   ToCacheQueryParams(params, aOptions);
     283             : 
     284           0 :   AutoChildOpArgs args(this, CacheMatchArgs(CacheRequest(), params), 1);
     285             : 
     286           0 :   args.Add(ir, IgnoreBody, IgnoreInvalidScheme, aRv);
     287           0 :   if (NS_WARN_IF(aRv.Failed())) {
     288           0 :     return nullptr;
     289             :   }
     290             : 
     291           0 :   return ExecuteOp(args, aRv);
     292             : }
     293             : 
     294             : already_AddRefed<Promise>
     295           0 : Cache::MatchAll(const Optional<RequestOrUSVString>& aRequest,
     296             :                 const CacheQueryOptions& aOptions, ErrorResult& aRv)
     297             : {
     298           0 :   if (NS_WARN_IF(!mActor)) {
     299           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     300           0 :     return nullptr;
     301             :   }
     302             : 
     303           0 :   CacheChild::AutoLock actorLock(mActor);
     304             : 
     305           0 :   CacheQueryParams params;
     306           0 :   ToCacheQueryParams(params, aOptions);
     307             : 
     308           0 :   AutoChildOpArgs args(this, CacheMatchAllArgs(void_t(), params), 1);
     309             : 
     310           0 :   if (aRequest.WasPassed()) {
     311           0 :     RefPtr<InternalRequest> ir = ToInternalRequest(aRequest.Value(),
     312           0 :                                                      IgnoreBody, aRv);
     313           0 :     if (aRv.Failed()) {
     314           0 :       return nullptr;
     315             :     }
     316             : 
     317           0 :     args.Add(ir, IgnoreBody, IgnoreInvalidScheme, aRv);
     318           0 :     if (aRv.Failed()) {
     319           0 :       return nullptr;
     320             :     }
     321             :   }
     322             : 
     323           0 :   return ExecuteOp(args, aRv);
     324             : }
     325             : 
     326             : already_AddRefed<Promise>
     327           0 : Cache::Add(JSContext* aContext, const RequestOrUSVString& aRequest,
     328             :            CallerType aCallerType, ErrorResult& aRv)
     329             : {
     330           0 :   if (NS_WARN_IF(!mActor)) {
     331           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     332           0 :     return nullptr;
     333             :   }
     334             : 
     335           0 :   CacheChild::AutoLock actorLock(mActor);
     336             : 
     337           0 :   if (!IsValidPutRequestMethod(aRequest, aRv)) {
     338           0 :     return nullptr;
     339             :   }
     340             : 
     341           0 :   GlobalObject global(aContext, mGlobal->GetGlobalJSObject());
     342           0 :   MOZ_DIAGNOSTIC_ASSERT(!global.Failed());
     343             : 
     344           0 :   nsTArray<RefPtr<Request>> requestList(1);
     345           0 :   RefPtr<Request> request = Request::Constructor(global, aRequest,
     346           0 :                                                    RequestInit(), aRv);
     347           0 :   if (NS_WARN_IF(aRv.Failed())) {
     348           0 :     return nullptr;
     349             :   }
     350             : 
     351           0 :   nsAutoString url;
     352           0 :   request->GetUrl(url);
     353           0 :   if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) {
     354           0 :     return nullptr;
     355             :   }
     356             : 
     357           0 :   requestList.AppendElement(Move(request));
     358           0 :   return AddAll(global, Move(requestList), aCallerType, aRv);
     359             : }
     360             : 
     361             : already_AddRefed<Promise>
     362           0 : Cache::AddAll(JSContext* aContext,
     363             :               const Sequence<OwningRequestOrUSVString>& aRequestList,
     364             :               CallerType aCallerType,
     365             :               ErrorResult& aRv)
     366             : {
     367           0 :   if (NS_WARN_IF(!mActor)) {
     368           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     369           0 :     return nullptr;
     370             :   }
     371             : 
     372           0 :   CacheChild::AutoLock actorLock(mActor);
     373             : 
     374           0 :   GlobalObject global(aContext, mGlobal->GetGlobalJSObject());
     375           0 :   MOZ_DIAGNOSTIC_ASSERT(!global.Failed());
     376             : 
     377           0 :   nsTArray<RefPtr<Request>> requestList(aRequestList.Length());
     378           0 :   for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
     379           0 :     RequestOrUSVString requestOrString;
     380             : 
     381           0 :     if (aRequestList[i].IsRequest()) {
     382           0 :       requestOrString.SetAsRequest() = aRequestList[i].GetAsRequest();
     383           0 :       if (NS_WARN_IF(!IsValidPutRequestMethod(requestOrString.GetAsRequest(),
     384             :                      aRv))) {
     385           0 :         return nullptr;
     386             :       }
     387             :     } else {
     388           0 :       requestOrString.SetAsUSVString().Rebind(
     389           0 :         aRequestList[i].GetAsUSVString().Data(),
     390           0 :         aRequestList[i].GetAsUSVString().Length());
     391             :     }
     392             : 
     393           0 :     RefPtr<Request> request = Request::Constructor(global, requestOrString,
     394           0 :                                                      RequestInit(), aRv);
     395           0 :     if (NS_WARN_IF(aRv.Failed())) {
     396           0 :       return nullptr;
     397             :     }
     398             : 
     399           0 :     nsAutoString url;
     400           0 :     request->GetUrl(url);
     401           0 :     if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) {
     402           0 :       return nullptr;
     403             :     }
     404             : 
     405           0 :     requestList.AppendElement(Move(request));
     406             :   }
     407             : 
     408           0 :   return AddAll(global, Move(requestList), aCallerType, aRv);
     409             : }
     410             : 
     411             : already_AddRefed<Promise>
     412           0 : Cache::Put(const RequestOrUSVString& aRequest, Response& aResponse,
     413             :            ErrorResult& aRv)
     414             : {
     415           0 :   if (NS_WARN_IF(!mActor)) {
     416           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     417           0 :     return nullptr;
     418             :   }
     419             : 
     420           0 :   CacheChild::AutoLock actorLock(mActor);
     421             : 
     422           0 :   if (NS_WARN_IF(!IsValidPutRequestMethod(aRequest, aRv))) {
     423           0 :     return nullptr;
     424             :   }
     425             : 
     426           0 :   if (!IsValidPutResponseStatus(aResponse, PutStatusPolicy::Default, aRv)) {
     427           0 :     return nullptr;
     428             :   }
     429             : 
     430           0 :   RefPtr<InternalRequest> ir = ToInternalRequest(aRequest, ReadBody, aRv);
     431           0 :   if (NS_WARN_IF(aRv.Failed())) {
     432           0 :     return nullptr;
     433             :   }
     434             : 
     435           0 :   AutoChildOpArgs args(this, CachePutAllArgs(), 1);
     436             : 
     437           0 :   args.Add(ir, ReadBody, TypeErrorOnInvalidScheme,
     438           0 :            aResponse, aRv);
     439           0 :   if (NS_WARN_IF(aRv.Failed())) {
     440           0 :     return nullptr;
     441             :   }
     442             : 
     443           0 :   return ExecuteOp(args, aRv);
     444             : }
     445             : 
     446             : already_AddRefed<Promise>
     447           0 : Cache::Delete(const RequestOrUSVString& aRequest,
     448             :               const CacheQueryOptions& aOptions, ErrorResult& aRv)
     449             : {
     450           0 :   if (NS_WARN_IF(!mActor)) {
     451           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     452           0 :     return nullptr;
     453             :   }
     454             : 
     455           0 :   CacheChild::AutoLock actorLock(mActor);
     456             : 
     457           0 :   RefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
     458           0 :   if (NS_WARN_IF(aRv.Failed())) {
     459           0 :     return nullptr;
     460             :   }
     461             : 
     462           0 :   CacheQueryParams params;
     463           0 :   ToCacheQueryParams(params, aOptions);
     464             : 
     465           0 :   AutoChildOpArgs args(this, CacheDeleteArgs(CacheRequest(), params), 1);
     466             : 
     467           0 :   args.Add(ir, IgnoreBody, IgnoreInvalidScheme, aRv);
     468           0 :   if (NS_WARN_IF(aRv.Failed())) {
     469           0 :     return nullptr;
     470             :   }
     471             : 
     472           0 :   return ExecuteOp(args, aRv);
     473             : }
     474             : 
     475             : already_AddRefed<Promise>
     476           0 : Cache::Keys(const Optional<RequestOrUSVString>& aRequest,
     477             :             const CacheQueryOptions& aOptions, ErrorResult& aRv)
     478             : {
     479           0 :   if (NS_WARN_IF(!mActor)) {
     480           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     481           0 :     return nullptr;
     482             :   }
     483             : 
     484           0 :   CacheChild::AutoLock actorLock(mActor);
     485             : 
     486           0 :   CacheQueryParams params;
     487           0 :   ToCacheQueryParams(params, aOptions);
     488             : 
     489           0 :   AutoChildOpArgs args(this, CacheKeysArgs(void_t(), params), 1);
     490             : 
     491           0 :   if (aRequest.WasPassed()) {
     492           0 :     RefPtr<InternalRequest> ir = ToInternalRequest(aRequest.Value(),
     493           0 :                                                      IgnoreBody, aRv);
     494           0 :     if (NS_WARN_IF(aRv.Failed())) {
     495           0 :       return nullptr;
     496             :     }
     497             : 
     498           0 :     args.Add(ir, IgnoreBody, IgnoreInvalidScheme, aRv);
     499           0 :     if (NS_WARN_IF(aRv.Failed())) {
     500           0 :       return nullptr;
     501             :     }
     502             :   }
     503             : 
     504           0 :   return ExecuteOp(args, aRv);
     505             : }
     506             : 
     507             : // static
     508             : bool
     509          10 : Cache::PrefEnabled(JSContext* aCx, JSObject* aObj)
     510             : {
     511             :   using mozilla::dom::workers::WorkerPrivate;
     512             :   using mozilla::dom::workers::GetWorkerPrivateFromContext;
     513             : 
     514             :   // If we're on the main thread, then check the pref directly.
     515          10 :   if (NS_IsMainThread()) {
     516           7 :     bool enabled = false;
     517           7 :     Preferences::GetBool("dom.caches.enabled", &enabled);
     518           7 :     return enabled;
     519             :   }
     520             : 
     521             :   // Otherwise check the pref via the work private helper
     522           3 :   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
     523           3 :   if (!workerPrivate) {
     524           0 :     return false;
     525             :   }
     526             : 
     527           3 :   return workerPrivate->DOMCachesEnabled();
     528             : }
     529             : 
     530             : nsISupports*
     531           0 : Cache::GetParentObject() const
     532             : {
     533           0 :   return mGlobal;
     534             : }
     535             : 
     536             : JSObject*
     537           0 : Cache::WrapObject(JSContext* aContext, JS::Handle<JSObject*> aGivenProto)
     538             : {
     539           0 :   return CacheBinding::Wrap(aContext, this, aGivenProto);
     540             : }
     541             : 
     542             : void
     543           0 : Cache::DestroyInternal(CacheChild* aActor)
     544             : {
     545           0 :   MOZ_DIAGNOSTIC_ASSERT(mActor);
     546           0 :   MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
     547           0 :   mActor->ClearListener();
     548           0 :   mActor = nullptr;
     549           0 : }
     550             : 
     551             : nsIGlobalObject*
     552           0 : Cache::GetGlobalObject() const
     553             : {
     554           0 :   return mGlobal;
     555             : }
     556             : 
     557             : #ifdef DEBUG
     558             : void
     559           0 : Cache::AssertOwningThread() const
     560             : {
     561           0 :   NS_ASSERT_OWNINGTHREAD(Cache);
     562           0 : }
     563             : #endif
     564             : 
     565             : PBackgroundChild*
     566           0 : Cache::GetIPCManager()
     567             : {
     568           0 :   NS_ASSERT_OWNINGTHREAD(Cache);
     569           0 :   MOZ_DIAGNOSTIC_ASSERT(mActor);
     570           0 :   return mActor->Manager();
     571             : }
     572             : 
     573           0 : Cache::~Cache()
     574             : {
     575           0 :   NS_ASSERT_OWNINGTHREAD(Cache);
     576           0 :   if (mActor) {
     577           0 :     mActor->StartDestroyFromListener();
     578             :     // DestroyInternal() is called synchronously by StartDestroyFromListener().
     579             :     // So we should have already cleared the mActor.
     580           0 :     MOZ_DIAGNOSTIC_ASSERT(!mActor);
     581             :   }
     582           0 : }
     583             : 
     584             : already_AddRefed<Promise>
     585           0 : Cache::ExecuteOp(AutoChildOpArgs& aOpArgs, ErrorResult& aRv)
     586             : {
     587           0 :   MOZ_DIAGNOSTIC_ASSERT(mActor);
     588             : 
     589           0 :   RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
     590           0 :   if (NS_WARN_IF(!promise)) {
     591           0 :     return nullptr;
     592             :   }
     593             : 
     594           0 :   mActor->ExecuteOp(mGlobal, promise, this, aOpArgs.SendAsOpArgs());
     595           0 :   return promise.forget();
     596             : }
     597             : 
     598             : already_AddRefed<Promise>
     599           0 : Cache::AddAll(const GlobalObject& aGlobal,
     600             :               nsTArray<RefPtr<Request>>&& aRequestList,
     601             :               CallerType aCallerType, ErrorResult& aRv)
     602             : {
     603           0 :   MOZ_DIAGNOSTIC_ASSERT(mActor);
     604             : 
     605             :   // If there is no work to do, then resolve immediately
     606           0 :   if (aRequestList.IsEmpty()) {
     607           0 :     RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
     608           0 :     if (NS_WARN_IF(!promise)) {
     609           0 :       return nullptr;
     610             :     }
     611             : 
     612           0 :     promise->MaybeResolveWithUndefined();
     613           0 :     return promise.forget();
     614             :   }
     615             : 
     616           0 :   AutoTArray<RefPtr<Promise>, 256> fetchList;
     617           0 :   fetchList.SetCapacity(aRequestList.Length());
     618             : 
     619             :   // Begin fetching each request in parallel.  For now, if an error occurs just
     620             :   // abandon our previous fetch calls.  In theory we could cancel them in the
     621             :   // future once fetch supports it.
     622             : 
     623           0 :   for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
     624           0 :     RequestOrUSVString requestOrString;
     625           0 :     requestOrString.SetAsRequest() = aRequestList[i];
     626           0 :     RefPtr<Promise> fetch = FetchRequest(mGlobal, requestOrString,
     627           0 :                                          RequestInit(), aCallerType, aRv);
     628           0 :     if (NS_WARN_IF(aRv.Failed())) {
     629           0 :       return nullptr;
     630             :     }
     631             : 
     632           0 :     fetchList.AppendElement(Move(fetch));
     633             :   }
     634             : 
     635           0 :   RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
     636           0 :   if (NS_WARN_IF(aRv.Failed())) {
     637           0 :     return nullptr;
     638             :   }
     639             : 
     640             :   RefPtr<FetchHandler> handler =
     641           0 :     new FetchHandler(mActor->GetWorkerHolder(), this,
     642           0 :                      Move(aRequestList), promise);
     643             : 
     644           0 :   RefPtr<Promise> fetchPromise = Promise::All(aGlobal, fetchList, aRv);
     645           0 :   if (NS_WARN_IF(aRv.Failed())) {
     646           0 :     return nullptr;
     647             :   }
     648           0 :   fetchPromise->AppendNativeHandler(handler);
     649             : 
     650           0 :   return promise.forget();
     651             : }
     652             : 
     653             : already_AddRefed<Promise>
     654           0 : Cache::PutAll(const nsTArray<RefPtr<Request>>& aRequestList,
     655             :               const nsTArray<RefPtr<Response>>& aResponseList,
     656             :               ErrorResult& aRv)
     657             : {
     658           0 :   MOZ_DIAGNOSTIC_ASSERT(aRequestList.Length() == aResponseList.Length());
     659             : 
     660           0 :   if (NS_WARN_IF(!mActor)) {
     661           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
     662           0 :     return nullptr;
     663             :   }
     664             : 
     665           0 :   CacheChild::AutoLock actorLock(mActor);
     666             : 
     667           0 :   AutoChildOpArgs args(this, CachePutAllArgs(), aRequestList.Length());
     668             : 
     669           0 :   for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
     670           0 :     RefPtr<InternalRequest> ir = aRequestList[i]->GetInternalRequest();
     671           0 :     args.Add(ir, ReadBody, TypeErrorOnInvalidScheme, *aResponseList[i], aRv);
     672           0 :     if (NS_WARN_IF(aRv.Failed())) {
     673           0 :       return nullptr;
     674             :     }
     675             :   }
     676             : 
     677           0 :   return ExecuteOp(args, aRv);
     678             : }
     679             : 
     680             : } // namespace cache
     681             : } // namespace dom
     682             : } // namespace mozilla

Generated by: LCOV version 1.13