LCOV - code coverage report
Current view: top level - dom/base - DOMRequest.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 171 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 45 0.0 %
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 "DOMRequest.h"
       8             : 
       9             : #include "DOMError.h"
      10             : #include "nsThreadUtils.h"
      11             : #include "DOMCursor.h"
      12             : #include "mozilla/ErrorResult.h"
      13             : #include "mozilla/dom/Event.h"
      14             : #include "mozilla/dom/Promise.h"
      15             : #include "mozilla/dom/ScriptSettings.h"
      16             : #include "jsfriendapi.h"
      17             : #include "nsContentUtils.h"
      18             : 
      19             : using mozilla::dom::AnyCallback;
      20             : using mozilla::dom::DOMError;
      21             : using mozilla::dom::DOMRequest;
      22             : using mozilla::dom::DOMRequestService;
      23             : using mozilla::dom::DOMCursor;
      24             : using mozilla::dom::Promise;
      25             : using mozilla::dom::AutoJSAPI;
      26             : using mozilla::dom::RootingCx;
      27             : 
      28           0 : DOMRequest::DOMRequest(nsPIDOMWindowInner* aWindow)
      29             :   : DOMEventTargetHelper(aWindow)
      30           0 :   , mResult(JS::UndefinedValue())
      31           0 :   , mDone(false)
      32             : {
      33           0 : }
      34             : 
      35           0 : DOMRequest::DOMRequest(nsIGlobalObject* aGlobal)
      36             :   : DOMEventTargetHelper(aGlobal)
      37           0 :   , mResult(JS::UndefinedValue())
      38           0 :   , mDone(false)
      39             : {
      40           0 : }
      41             : 
      42           0 : DOMRequest::~DOMRequest()
      43             : {
      44           0 :   mResult.setUndefined();
      45           0 :   mozilla::DropJSObjects(this);
      46           0 : }
      47             : 
      48             : NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest)
      49             : 
      50           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest,
      51             :                                                   DOMEventTargetHelper)
      52           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
      53           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
      54           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      55             : 
      56           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest,
      57             :                                                 DOMEventTargetHelper)
      58           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
      59           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
      60           0 :   tmp->mResult.setUndefined();
      61           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      62             : 
      63           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DOMRequest,
      64             :                                                DOMEventTargetHelper)
      65             :   // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
      66             :   // DOMEventTargetHelper does it for us.
      67           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mResult)
      68           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
      69             : 
      70           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMRequest)
      71           0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMDOMRequest)
      72           0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
      73             : 
      74           0 : NS_IMPL_ADDREF_INHERITED(DOMRequest, DOMEventTargetHelper)
      75           0 : NS_IMPL_RELEASE_INHERITED(DOMRequest, DOMEventTargetHelper)
      76             : 
      77             : /* virtual */ JSObject*
      78           0 : DOMRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
      79             : {
      80           0 :   return DOMRequestBinding::Wrap(aCx, this, aGivenProto);
      81             : }
      82             : 
      83           0 : NS_IMPL_EVENT_HANDLER(DOMRequest, success)
      84           0 : NS_IMPL_EVENT_HANDLER(DOMRequest, error)
      85             : 
      86             : NS_IMETHODIMP
      87           0 : DOMRequest::GetReadyState(nsAString& aReadyState)
      88             : {
      89           0 :   DOMRequestReadyState readyState = ReadyState();
      90           0 :   switch (readyState) {
      91             :     case DOMRequestReadyState::Pending:
      92           0 :       aReadyState.AssignLiteral("pending");
      93           0 :       break;
      94             :     case DOMRequestReadyState::Done:
      95           0 :       aReadyState.AssignLiteral("done");
      96           0 :       break;
      97             :     default:
      98           0 :       MOZ_CRASH("Unrecognized readyState.");
      99             :   }
     100             : 
     101           0 :   return NS_OK;
     102             : }
     103             : 
     104             : NS_IMETHODIMP
     105           0 : DOMRequest::GetResult(JS::MutableHandle<JS::Value> aResult)
     106             : {
     107           0 :   GetResult(nullptr, aResult);
     108           0 :   return NS_OK;
     109             : }
     110             : 
     111             : NS_IMETHODIMP
     112           0 : DOMRequest::GetError(nsISupports** aError)
     113             : {
     114           0 :   NS_IF_ADDREF(*aError = GetError());
     115           0 :   return NS_OK;
     116             : }
     117             : 
     118             : void
     119           0 : DOMRequest::FireSuccess(JS::Handle<JS::Value> aResult)
     120             : {
     121           0 :   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
     122           0 :   NS_ASSERTION(!mError, "mError shouldn't have been set!");
     123           0 :   NS_ASSERTION(mResult.isUndefined(), "mResult shouldn't have been set!");
     124             : 
     125           0 :   mDone = true;
     126           0 :   if (aResult.isGCThing()) {
     127           0 :     RootResultVal();
     128             :   }
     129           0 :   mResult = aResult;
     130             : 
     131           0 :   FireEvent(NS_LITERAL_STRING("success"), false, false);
     132             : 
     133           0 :   if (mPromise) {
     134           0 :     mPromise->MaybeResolve(mResult);
     135             :   }
     136           0 : }
     137             : 
     138             : void
     139           0 : DOMRequest::FireError(const nsAString& aError)
     140             : {
     141           0 :   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
     142           0 :   NS_ASSERTION(!mError, "mError shouldn't have been set!");
     143           0 :   NS_ASSERTION(mResult.isUndefined(), "mResult shouldn't have been set!");
     144             : 
     145           0 :   mDone = true;
     146           0 :   mError = new DOMError(GetOwner(), aError);
     147             : 
     148           0 :   FireEvent(NS_LITERAL_STRING("error"), true, true);
     149             : 
     150           0 :   if (mPromise) {
     151           0 :     mPromise->MaybeRejectBrokenly(mError);
     152             :   }
     153           0 : }
     154             : 
     155             : void
     156           0 : DOMRequest::FireError(nsresult aError)
     157             : {
     158           0 :   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
     159           0 :   NS_ASSERTION(!mError, "mError shouldn't have been set!");
     160           0 :   NS_ASSERTION(mResult.isUndefined(), "mResult shouldn't have been set!");
     161             : 
     162           0 :   mDone = true;
     163           0 :   mError = new DOMError(GetOwner(), aError);
     164             : 
     165           0 :   FireEvent(NS_LITERAL_STRING("error"), true, true);
     166             : 
     167           0 :   if (mPromise) {
     168           0 :     mPromise->MaybeRejectBrokenly(mError);
     169             :   }
     170           0 : }
     171             : 
     172             : void
     173           0 : DOMRequest::FireDetailedError(DOMError* aError)
     174             : {
     175           0 :   NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!");
     176           0 :   NS_ASSERTION(!mError, "mError shouldn't have been set!");
     177           0 :   NS_ASSERTION(mResult.isUndefined(), "mResult shouldn't have been set!");
     178           0 :   NS_ASSERTION(aError, "No detailed error provided");
     179             : 
     180           0 :   mDone = true;
     181           0 :   mError = aError;
     182             : 
     183           0 :   FireEvent(NS_LITERAL_STRING("error"), true, true);
     184             : 
     185           0 :   if (mPromise) {
     186           0 :     mPromise->MaybeRejectBrokenly(mError);
     187             :   }
     188           0 : }
     189             : 
     190             : void
     191           0 : DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable)
     192             : {
     193           0 :   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     194           0 :     return;
     195             :   }
     196             : 
     197           0 :   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
     198           0 :   event->InitEvent(aType, aBubble, aCancelable);
     199           0 :   event->SetTrusted(true);
     200             : 
     201             :   bool dummy;
     202           0 :   DispatchEvent(event, &dummy);
     203             : }
     204             : 
     205             : void
     206           0 : DOMRequest::RootResultVal()
     207             : {
     208           0 :   mozilla::HoldJSObjects(this);
     209           0 : }
     210             : 
     211             : void
     212           0 : DOMRequest::Then(JSContext* aCx, AnyCallback* aResolveCallback,
     213             :                  AnyCallback* aRejectCallback,
     214             :                  JS::MutableHandle<JS::Value> aRetval,
     215             :                  mozilla::ErrorResult& aRv)
     216             : {
     217           0 :   if (!mPromise) {
     218           0 :     mPromise = Promise::Create(DOMEventTargetHelper::GetParentObject(), aRv);
     219           0 :     if (aRv.Failed()) {
     220           0 :       return;
     221             :     }
     222           0 :     if (mDone) {
     223             :       // Since we create mPromise lazily, it's possible that the DOMRequest object
     224             :       // has already fired its success/error event.  In that case we should
     225             :       // manually resolve/reject mPromise here.  mPromise will take care of
     226             :       // calling the callbacks on |promise| as needed.
     227           0 :       if (mError) {
     228           0 :         mPromise->MaybeRejectBrokenly(mError);
     229             :       } else {
     230           0 :         mPromise->MaybeResolve(mResult);
     231             :       }
     232             :     }
     233             :   }
     234             : 
     235             :   // Just use the global of the Promise itself as the callee global.
     236           0 :   JS::Rooted<JSObject*> global(aCx, mPromise->PromiseObj());
     237           0 :   global = js::GetGlobalForObjectCrossCompartment(global);
     238           0 :   mPromise->Then(aCx, global, aResolveCallback, aRejectCallback, aRetval, aRv);
     239             : }
     240             : 
     241           0 : NS_IMPL_ISUPPORTS(DOMRequestService, nsIDOMRequestService)
     242             : 
     243             : NS_IMETHODIMP
     244           0 : DOMRequestService::CreateRequest(mozIDOMWindow* aWindow,
     245             :                                  nsIDOMDOMRequest** aRequest)
     246             : {
     247           0 :   MOZ_ASSERT(NS_IsMainThread());
     248           0 :   NS_ENSURE_STATE(aWindow);
     249           0 :   auto* win = nsPIDOMWindowInner::From(aWindow);
     250           0 :   NS_ADDREF(*aRequest = new DOMRequest(win));
     251             : 
     252           0 :   return NS_OK;
     253             : }
     254             : 
     255             : NS_IMETHODIMP
     256           0 : DOMRequestService::CreateCursor(mozIDOMWindow* aWindow,
     257             :                                 nsICursorContinueCallback* aCallback,
     258             :                                 nsIDOMDOMCursor** aCursor)
     259             : {
     260           0 :   NS_ENSURE_STATE(aWindow);
     261           0 :   auto* win = nsPIDOMWindowInner::From(aWindow);
     262           0 :   NS_ADDREF(*aCursor = new DOMCursor(win, aCallback));
     263             : 
     264           0 :   return NS_OK;
     265             : }
     266             : 
     267             : NS_IMETHODIMP
     268           0 : DOMRequestService::FireSuccess(nsIDOMDOMRequest* aRequest,
     269             :                                JS::Handle<JS::Value> aResult)
     270             : {
     271           0 :   NS_ENSURE_STATE(aRequest);
     272           0 :   static_cast<DOMRequest*>(aRequest)->FireSuccess(aResult);
     273             : 
     274           0 :   return NS_OK;
     275             : }
     276             : 
     277             : NS_IMETHODIMP
     278           0 : DOMRequestService::FireError(nsIDOMDOMRequest* aRequest,
     279             :                              const nsAString& aError)
     280             : {
     281           0 :   NS_ENSURE_STATE(aRequest);
     282           0 :   static_cast<DOMRequest*>(aRequest)->FireError(aError);
     283             : 
     284           0 :   return NS_OK;
     285             : }
     286             : 
     287             : NS_IMETHODIMP
     288           0 : DOMRequestService::FireDetailedError(nsIDOMDOMRequest* aRequest,
     289             :                                      nsISupports* aError)
     290             : {
     291           0 :   NS_ENSURE_STATE(aRequest);
     292           0 :   nsCOMPtr<DOMError> err = do_QueryInterface(aError);
     293           0 :   NS_ENSURE_STATE(err);
     294           0 :   static_cast<DOMRequest*>(aRequest)->FireDetailedError(err);
     295             : 
     296           0 :   return NS_OK;
     297             : }
     298             : 
     299           0 : class FireSuccessAsyncTask : public mozilla::Runnable
     300             : {
     301             : 
     302           0 :   FireSuccessAsyncTask(DOMRequest* aRequest, const JS::Value& aResult)
     303           0 :     : mozilla::Runnable("FireSuccessAsyncTask")
     304             :     , mReq(aRequest)
     305           0 :     , mResult(RootingCx(), aResult)
     306             :   {
     307           0 :   }
     308             : 
     309             : public:
     310             : 
     311             :   // Due to the fact that initialization can fail during shutdown (since we
     312             :   // can't fetch a js context), set up an initiatization function to make sure
     313             :   // we can return the failure appropriately
     314             :   static nsresult
     315           0 :   Dispatch(DOMRequest* aRequest,
     316             :            const JS::Value& aResult)
     317             :   {
     318             :     RefPtr<FireSuccessAsyncTask> asyncTask =
     319           0 :       new FireSuccessAsyncTask(aRequest, aResult);
     320           0 :     MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(asyncTask));
     321           0 :     return NS_OK;
     322             :   }
     323             : 
     324             :   NS_IMETHOD
     325           0 :   Run() override
     326             :   {
     327           0 :     mReq->FireSuccess(JS::Handle<JS::Value>::fromMarkedLocation(mResult.address()));
     328           0 :     return NS_OK;
     329             :   }
     330             : 
     331             : private:
     332             :   RefPtr<DOMRequest> mReq;
     333             :   JS::PersistentRooted<JS::Value> mResult;
     334             : };
     335             : 
     336           0 : class FireErrorAsyncTask : public mozilla::Runnable
     337             : {
     338             : public:
     339           0 :   FireErrorAsyncTask(DOMRequest* aRequest, const nsAString& aError)
     340           0 :     : mozilla::Runnable("FireErrorAsyncTask")
     341             :     , mReq(aRequest)
     342           0 :     , mError(aError)
     343             :   {
     344           0 :   }
     345             : 
     346             :   NS_IMETHOD
     347           0 :   Run() override
     348             :   {
     349           0 :     mReq->FireError(mError);
     350           0 :     return NS_OK;
     351             :   }
     352             : private:
     353             :   RefPtr<DOMRequest> mReq;
     354             :   nsString mError;
     355             : };
     356             : 
     357             : NS_IMETHODIMP
     358           0 : DOMRequestService::FireSuccessAsync(nsIDOMDOMRequest* aRequest,
     359             :                                     JS::Handle<JS::Value> aResult)
     360             : {
     361           0 :   NS_ENSURE_STATE(aRequest);
     362           0 :   return FireSuccessAsyncTask::Dispatch(static_cast<DOMRequest*>(aRequest), aResult);
     363             : }
     364             : 
     365             : NS_IMETHODIMP
     366           0 : DOMRequestService::FireErrorAsync(nsIDOMDOMRequest* aRequest,
     367             :                                   const nsAString& aError)
     368             : {
     369           0 :   NS_ENSURE_STATE(aRequest);
     370             :   nsCOMPtr<nsIRunnable> asyncTask =
     371           0 :     new FireErrorAsyncTask(static_cast<DOMRequest*>(aRequest), aError);
     372           0 :   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(asyncTask));
     373           0 :   return NS_OK;
     374             : }
     375             : 
     376             : NS_IMETHODIMP
     377           0 : DOMRequestService::FireDone(nsIDOMDOMCursor* aCursor) {
     378           0 :   NS_ENSURE_STATE(aCursor);
     379           0 :   static_cast<DOMCursor*>(aCursor)->FireDone();
     380             : 
     381           0 :   return NS_OK;
     382             : }

Generated by: LCOV version 1.13