tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RemoteWorkerController.cpp (18113B)


      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 "RemoteWorkerController.h"
      8 
      9 #include <utility>
     10 
     11 #include "RemoteWorkerControllerParent.h"
     12 #include "RemoteWorkerManager.h"
     13 #include "RemoteWorkerNonLifeCycleOpControllerParent.h"
     14 #include "RemoteWorkerParent.h"
     15 #include "mozilla/Assertions.h"
     16 #include "mozilla/DebugOnly.h"
     17 #include "mozilla/Maybe.h"
     18 #include "mozilla/RemoteLazyInputStreamStorage.h"
     19 #include "mozilla/dom/FetchEventOpParent.h"
     20 #include "mozilla/dom/FetchEventOpProxyParent.h"
     21 #include "mozilla/dom/MessagePortParent.h"
     22 #include "mozilla/dom/RemoteWorkerTypes.h"
     23 #include "mozilla/dom/ServiceWorkerCloneData.h"
     24 #include "mozilla/dom/ServiceWorkerShutdownState.h"
     25 #include "mozilla/ipc/BackgroundParent.h"
     26 #include "nsDebug.h"
     27 
     28 namespace mozilla {
     29 
     30 using namespace ipc;
     31 
     32 namespace dom {
     33 
     34 /* static */
     35 already_AddRefed<RemoteWorkerController> RemoteWorkerController::Create(
     36    const RemoteWorkerData& aData, RemoteWorkerObserver* aObserver,
     37    base::ProcessId aProcessId) {
     38  AssertIsInMainProcess();
     39  AssertIsOnBackgroundThread();
     40  MOZ_ASSERT(aObserver);
     41 
     42  RefPtr<RemoteWorkerController> controller =
     43      new RemoteWorkerController(aData, aObserver);
     44 
     45  RefPtr<RemoteWorkerManager> manager = RemoteWorkerManager::GetOrCreate();
     46  MOZ_ASSERT(manager);
     47 
     48  // XXX: We do not check for failure here, should we?
     49  manager->Launch(controller, aData, aProcessId);
     50 
     51  return controller.forget();
     52 }
     53 
     54 RemoteWorkerController::RemoteWorkerController(const RemoteWorkerData& aData,
     55                                               RemoteWorkerObserver* aObserver)
     56    : mObserver(aObserver),
     57      mState(ePending),
     58      mIsServiceWorker(aData.serviceWorkerData().type() ==
     59                       OptionalServiceWorkerData::TServiceWorkerData) {
     60  AssertIsInMainProcess();
     61  AssertIsOnBackgroundThread();
     62 }
     63 
     64 RemoteWorkerController::~RemoteWorkerController() {
     65  AssertIsOnBackgroundThread();
     66  MOZ_DIAGNOSTIC_ASSERT(mPendingOps.IsEmpty());
     67 }
     68 
     69 void RemoteWorkerController::SetWorkerActor(RemoteWorkerParent* aActor) {
     70  AssertIsOnBackgroundThread();
     71  MOZ_ASSERT(!mActor);
     72  MOZ_ASSERT(aActor);
     73 
     74  mActor = aActor;
     75 }
     76 
     77 void RemoteWorkerController::NoteDeadWorkerActor() {
     78  AssertIsOnBackgroundThread();
     79  MOZ_ASSERT(mActor);
     80 
     81  // The actor has been destroyed without a proper close() notification. Let's
     82  // inform the observer.
     83  if (mState == eReady) {
     84    mObserver->Terminated();
     85  }
     86 
     87  mActor = nullptr;
     88 
     89  Shutdown();
     90 }
     91 
     92 void RemoteWorkerController::CreationFailed() {
     93  AssertIsOnBackgroundThread();
     94  MOZ_ASSERT(XRE_IsParentProcess());
     95  MOZ_ASSERT(mState == ePending || mState == eTerminated);
     96 
     97  if (mState == eTerminated) {
     98    MOZ_ASSERT(!mActor);
     99    MOZ_ASSERT(!mNonLifeCycleOpController);
    100    MOZ_ASSERT(mPendingOps.IsEmpty());
    101    // Nothing to do.
    102    return;
    103  }
    104 
    105  NoteDeadWorker();
    106 
    107  mObserver->CreationFailed();
    108 }
    109 
    110 void RemoteWorkerController::CreationSucceeded() {
    111  AssertIsOnBackgroundThread();
    112  MOZ_ASSERT(mState == ePending || mState == eTerminated);
    113 
    114  if (mState == eTerminated) {
    115    MOZ_ASSERT(!mActor);
    116    MOZ_ASSERT(!mNonLifeCycleOpController);
    117    MOZ_ASSERT(mPendingOps.IsEmpty());
    118    // Nothing to do.
    119    return;
    120  }
    121 
    122  MOZ_ASSERT(mActor);
    123 
    124  // mNonLifeCycleOpController could be already shutdown at the this moment.
    125  // So no need to assert its existence.
    126  // op->MaybeStart() will return true to ensure the op will not be in the
    127  // mPendingOps
    128 
    129  mState = eReady;
    130 
    131  mObserver->CreationSucceeded();
    132 
    133  auto pendingOps = std::move(mPendingOps);
    134 
    135  for (auto& op : pendingOps) {
    136    DebugOnly<bool> started = op->MaybeStart(this);
    137    MOZ_ASSERT(started);
    138  }
    139 }
    140 
    141 void RemoteWorkerController::ErrorPropagation(const ErrorValue& aValue) {
    142  AssertIsOnBackgroundThread();
    143 
    144  mObserver->ErrorReceived(aValue);
    145 }
    146 
    147 void RemoteWorkerController::NotifyLock(bool aCreated) {
    148  AssertIsOnBackgroundThread();
    149 
    150  mObserver->LockNotified(aCreated);
    151 }
    152 
    153 void RemoteWorkerController::NotifyWebTransport(bool aCreated) {
    154  AssertIsOnBackgroundThread();
    155 
    156  mObserver->WebTransportNotified(aCreated);
    157 }
    158 
    159 void RemoteWorkerController::WorkerTerminated() {
    160  AssertIsOnBackgroundThread();
    161 
    162  NoteDeadWorker();
    163 
    164  mObserver->Terminated();
    165 }
    166 
    167 void RemoteWorkerController::CancelAllPendingOps() {
    168  AssertIsOnBackgroundThread();
    169 
    170  auto pendingOps = std::move(mPendingOps);
    171 
    172  for (auto& op : pendingOps) {
    173    op->Cancel();
    174  }
    175 }
    176 
    177 void RemoteWorkerController::Shutdown() {
    178  AssertIsOnBackgroundThread();
    179  (void)NS_WARN_IF(mIsServiceWorker && !mPendingOps.IsEmpty());
    180 
    181  if (mState == eTerminated) {
    182    MOZ_ASSERT(mPendingOps.IsEmpty());
    183    return;
    184  }
    185 
    186  mState = eTerminated;
    187 
    188  CancelAllPendingOps();
    189 
    190  if (mNonLifeCycleOpController) {
    191    mNonLifeCycleOpController->Shutdown();
    192    mNonLifeCycleOpController = nullptr;
    193  }
    194 
    195  if (!mActor) {
    196    return;
    197  }
    198 
    199  mActor->SetController(nullptr);
    200 
    201  /**
    202   * The "non-remote-side" of the Service Worker will have ensured that the
    203   * remote worker is terminated before calling `Shutdown().`
    204   */
    205  if (mIsServiceWorker) {
    206    mActor->MaybeSendDelete();
    207  } else {
    208    (void)mActor->SendExecOp(SharedWorkerTerminateOpArgs());
    209  }
    210 
    211  mActor = nullptr;
    212 }
    213 
    214 void RemoteWorkerController::NoteDeadWorker() {
    215  AssertIsOnBackgroundThread();
    216 
    217  CancelAllPendingOps();
    218 
    219  /**
    220   * The "non-remote-side" of the Service Worker will initiate `Shutdown()`
    221   * once it's notified that all dispatched operations have either completed
    222   * or canceled. That is, it'll explicitly call `Shutdown()` later.
    223   */
    224  if (!mIsServiceWorker) {
    225    Shutdown();
    226  }
    227 }
    228 
    229 template <typename... Args>
    230 void RemoteWorkerController::MaybeStartSharedWorkerOp(Args&&... aArgs) {
    231  AssertIsOnBackgroundThread();
    232  MOZ_ASSERT(!mIsServiceWorker);
    233 
    234  UniquePtr<PendingSharedWorkerOp> op =
    235      MakeUnique<PendingSharedWorkerOp>(std::forward<Args>(aArgs)...);
    236 
    237  if (!op->MaybeStart(this)) {
    238    mPendingOps.AppendElement(std::move(op));
    239  }
    240 }
    241 
    242 void RemoteWorkerController::AddWindowID(uint64_t aWindowID) {
    243  AssertIsOnBackgroundThread();
    244  MOZ_ASSERT(aWindowID);
    245 
    246  MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eAddWindowID, aWindowID);
    247 }
    248 
    249 void RemoteWorkerController::RemoveWindowID(uint64_t aWindowID) {
    250  AssertIsOnBackgroundThread();
    251  MOZ_ASSERT(aWindowID);
    252 
    253  MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eRemoveWindowID, aWindowID);
    254 }
    255 
    256 void RemoteWorkerController::AddPortIdentifier(
    257    const MessagePortIdentifier& aPortIdentifier) {
    258  AssertIsOnBackgroundThread();
    259 
    260  MaybeStartSharedWorkerOp(aPortIdentifier);
    261 }
    262 
    263 void RemoteWorkerController::Terminate() {
    264  AssertIsOnBackgroundThread();
    265 
    266  MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eTerminate);
    267 }
    268 
    269 void RemoteWorkerController::Suspend() {
    270  AssertIsOnBackgroundThread();
    271 
    272  MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eSuspend);
    273 }
    274 
    275 void RemoteWorkerController::Resume() {
    276  AssertIsOnBackgroundThread();
    277 
    278  MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eResume);
    279 }
    280 
    281 void RemoteWorkerController::Freeze() {
    282  AssertIsOnBackgroundThread();
    283 
    284  MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eFreeze);
    285 }
    286 
    287 void RemoteWorkerController::Thaw() {
    288  AssertIsOnBackgroundThread();
    289 
    290  MaybeStartSharedWorkerOp(PendingSharedWorkerOp::eThaw);
    291 }
    292 
    293 RefPtr<ServiceWorkerOpPromise> RemoteWorkerController::ExecServiceWorkerOp(
    294    ServiceWorkerOpArgs&& aArgs) {
    295  AssertIsOnBackgroundThread();
    296  MOZ_ASSERT(mIsServiceWorker);
    297 
    298  RefPtr<ServiceWorkerOpPromise::Private> promise =
    299      new ServiceWorkerOpPromise::Private(__func__);
    300 
    301  UniquePtr<PendingServiceWorkerOp> op =
    302      MakeUnique<PendingServiceWorkerOp>(std::move(aArgs), promise);
    303 
    304  if (!op->MaybeStart(this)) {
    305    mPendingOps.AppendElement(std::move(op));
    306  }
    307 
    308  return promise;
    309 }
    310 
    311 RefPtr<ServiceWorkerFetchEventOpPromise>
    312 RemoteWorkerController::ExecServiceWorkerFetchEventOp(
    313    const ParentToParentServiceWorkerFetchEventOpArgs& aArgs,
    314    RefPtr<FetchEventOpParent> aReal) {
    315  AssertIsOnBackgroundThread();
    316  MOZ_ASSERT(mIsServiceWorker);
    317 
    318  RefPtr<ServiceWorkerFetchEventOpPromise::Private> promise =
    319      new ServiceWorkerFetchEventOpPromise::Private(__func__);
    320 
    321  UniquePtr<PendingSWFetchEventOp> op =
    322      MakeUnique<PendingSWFetchEventOp>(aArgs, promise, std::move(aReal));
    323 
    324  if (!op->MaybeStart(this)) {
    325    mPendingOps.AppendElement(std::move(op));
    326  }
    327 
    328  return promise;
    329 }
    330 
    331 RefPtr<GenericPromise> RemoteWorkerController::SetServiceWorkerSkipWaitingFlag()
    332    const {
    333  AssertIsOnBackgroundThread();
    334  MOZ_ASSERT(mObserver);
    335 
    336  RefPtr<GenericPromise::Private> promise =
    337      new GenericPromise::Private(__func__);
    338 
    339  static_cast<RemoteWorkerControllerParent*>(mObserver.get())
    340      ->MaybeSendSetServiceWorkerSkipWaitingFlag(
    341          [promise](bool aOk) { promise->Resolve(aOk, __func__); });
    342 
    343  return promise;
    344 }
    345 
    346 bool RemoteWorkerController::IsTerminated() const {
    347  return mState == eTerminated;
    348 }
    349 
    350 RemoteWorkerController::PendingSharedWorkerOp::PendingSharedWorkerOp(
    351    Type aType, uint64_t aWindowID)
    352    : mType(aType), mWindowID(aWindowID) {
    353  AssertIsOnBackgroundThread();
    354 }
    355 
    356 RemoteWorkerController::PendingSharedWorkerOp::PendingSharedWorkerOp(
    357    const MessagePortIdentifier& aPortIdentifier)
    358    : mType(ePortIdentifier), mPortIdentifier(aPortIdentifier) {
    359  AssertIsOnBackgroundThread();
    360 }
    361 
    362 RemoteWorkerController::PendingSharedWorkerOp::~PendingSharedWorkerOp() {
    363  AssertIsOnBackgroundThread();
    364  MOZ_DIAGNOSTIC_ASSERT(mCompleted);
    365 }
    366 
    367 bool RemoteWorkerController::PendingSharedWorkerOp::MaybeStart(
    368    RemoteWorkerController* const aOwner) {
    369  AssertIsOnBackgroundThread();
    370  MOZ_ASSERT(!mCompleted);
    371  MOZ_ASSERT(aOwner);
    372 
    373  if (aOwner->mState == RemoteWorkerController::eTerminated) {
    374    Cancel();
    375    return true;
    376  }
    377 
    378  if (aOwner->mState == RemoteWorkerController::ePending &&
    379      mType != eTerminate) {
    380    return false;
    381  }
    382 
    383  switch (mType) {
    384    case eTerminate:
    385      aOwner->Shutdown();
    386      break;
    387    case eSuspend:
    388      (void)aOwner->mActor->SendExecOp(SharedWorkerSuspendOpArgs());
    389      break;
    390    case eResume:
    391      (void)aOwner->mActor->SendExecOp(SharedWorkerResumeOpArgs());
    392      break;
    393    case eFreeze:
    394      (void)aOwner->mActor->SendExecOp(SharedWorkerFreezeOpArgs());
    395      break;
    396    case eThaw:
    397      (void)aOwner->mActor->SendExecOp(SharedWorkerThawOpArgs());
    398      break;
    399    case ePortIdentifier:
    400      // mNonLifeCycleOpController can be nullptr if the Worker is in "Killing."
    401      // RemoteWorkerNonLifeCycleOpControllerChild switches to the Killed status
    402      // earlier than RemoteWorkerChild since it switches the status on the
    403      // worker thread, not the main thread.
    404      if (!aOwner->mNonLifeCycleOpController) {
    405        Cancel();
    406        return true;
    407      }
    408      if (!aOwner->mNonLifeCycleOpController->CanSend()) {
    409        return false;
    410      }
    411      (void)aOwner->mNonLifeCycleOpController->SendExecOp(
    412          SharedWorkerPortIdentifierOpArgs(mPortIdentifier));
    413      break;
    414    case eAddWindowID:
    415      (void)aOwner->mActor->SendExecOp(
    416          SharedWorkerAddWindowIDOpArgs(mWindowID));
    417      break;
    418    case eRemoveWindowID:
    419      (void)aOwner->mActor->SendExecOp(
    420          SharedWorkerRemoveWindowIDOpArgs(mWindowID));
    421      break;
    422    default:
    423      MOZ_CRASH("Unknown op.");
    424  }
    425 
    426  mCompleted = true;
    427 
    428  return true;
    429 }
    430 
    431 void RemoteWorkerController::PendingSharedWorkerOp::Cancel() {
    432  AssertIsOnBackgroundThread();
    433  MOZ_ASSERT(!mCompleted);
    434 
    435  // We don't want to leak the port if the operation has not been processed.
    436  if (mType == ePortIdentifier) {
    437    MessagePortParent::ForceClose(mPortIdentifier.uuid(),
    438                                  mPortIdentifier.destinationUuid(),
    439                                  mPortIdentifier.sequenceId());
    440  }
    441 
    442  mCompleted = true;
    443 }
    444 
    445 RemoteWorkerController::PendingServiceWorkerOp::PendingServiceWorkerOp(
    446    ServiceWorkerOpArgs&& aArgs,
    447    RefPtr<ServiceWorkerOpPromise::Private> aPromise)
    448    : mArgs(std::move(aArgs)), mPromise(std::move(aPromise)) {
    449  AssertIsOnBackgroundThread();
    450  MOZ_ASSERT(mPromise);
    451 }
    452 
    453 RemoteWorkerController::PendingServiceWorkerOp::~PendingServiceWorkerOp() {
    454  AssertIsOnBackgroundThread();
    455  MOZ_DIAGNOSTIC_ASSERT(!mPromise);
    456 }
    457 
    458 bool RemoteWorkerController::PendingServiceWorkerOp::MaybeStart(
    459    RemoteWorkerController* const aOwner) {
    460  AssertIsOnBackgroundThread();
    461  MOZ_ASSERT(mPromise);
    462  MOZ_ASSERT(aOwner);
    463 
    464  if (NS_WARN_IF(aOwner->mState == RemoteWorkerController::eTerminated)) {
    465    mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
    466    mPromise = nullptr;
    467    return true;
    468  }
    469 
    470  // The target content process must still be starting up.
    471  if (!aOwner->mActor) {
    472    // We can avoid starting the worker at all if we know it should be
    473    // terminated.
    474    MOZ_ASSERT(aOwner->mState == RemoteWorkerController::ePending);
    475    if (mArgs.type() ==
    476        ServiceWorkerOpArgs::TServiceWorkerTerminateWorkerOpArgs) {
    477      aOwner->CancelAllPendingOps();
    478      MaybeReportServiceWorkerShutdownProgress(mArgs, true);
    479      Cancel();
    480 
    481      aOwner->mState = RemoteWorkerController::eTerminated;
    482 
    483      return true;
    484    }
    485 
    486    return false;
    487  }
    488 
    489  /**
    490   * Allow termination operations to pass through while pending because the
    491   * remote Service Worker can be terminated while still starting up.
    492   */
    493  if (aOwner->mState == RemoteWorkerController::ePending &&
    494      mArgs.type() !=
    495          ServiceWorkerOpArgs::TServiceWorkerTerminateWorkerOpArgs) {
    496    return false;
    497  }
    498 
    499  switch (mArgs.type()) {
    500    case ServiceWorkerOpArgs::TServiceWorkerTerminateWorkerOpArgs:
    501    case ServiceWorkerOpArgs::TParentToChildServiceWorkerFetchEventOpArgs: {
    502      MaybeReportServiceWorkerShutdownProgress(mArgs);
    503 
    504      aOwner->mActor->SendExecServiceWorkerOp(mArgs)->Then(
    505          GetCurrentSerialEventTarget(), __func__,
    506          [promise = std::move(mPromise)](
    507              PRemoteWorkerParent::ExecServiceWorkerOpPromise::
    508                  ResolveOrRejectValue&& aResult) {
    509            if (NS_WARN_IF(aResult.IsReject())) {
    510              promise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
    511              return;
    512            }
    513 
    514            promise->Resolve(std::move(aResult.ResolveValue()), __func__);
    515          });
    516      break;
    517    }
    518    default: {
    519      // mNonLifeCycleOpController can be nullptr if the Worker is in "Killing."
    520      // RemoteWorkerNonLifeCycleOpControllerChild switches to the Killed status
    521      // earlier than RemoteWorkerChild since it switches the status on the
    522      // worker thread, not the main thread.
    523      if (!aOwner->mNonLifeCycleOpController) {
    524        Cancel();
    525        return true;
    526      }
    527      if (!aOwner->mNonLifeCycleOpController->CanSend()) {
    528        return false;
    529      }
    530      aOwner->mNonLifeCycleOpController->SendExecServiceWorkerOp(mArgs)->Then(
    531          GetCurrentSerialEventTarget(), __func__,
    532          [promise = std::move(mPromise)](
    533              PRemoteWorkerParent::ExecServiceWorkerOpPromise::
    534                  ResolveOrRejectValue&& aResult) {
    535            if (NS_WARN_IF(aResult.IsReject())) {
    536              promise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
    537              return;
    538            }
    539 
    540            promise->Resolve(std::move(aResult.ResolveValue()), __func__);
    541          });
    542    }
    543  }
    544  return true;
    545 }
    546 
    547 void RemoteWorkerController::PendingServiceWorkerOp::Cancel() {
    548  AssertIsOnBackgroundThread();
    549  MOZ_ASSERT(mPromise);
    550 
    551  mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
    552  mPromise = nullptr;
    553 }
    554 
    555 RemoteWorkerController::PendingSWFetchEventOp::PendingSWFetchEventOp(
    556    const ParentToParentServiceWorkerFetchEventOpArgs& aArgs,
    557    RefPtr<ServiceWorkerFetchEventOpPromise::Private> aPromise,
    558    RefPtr<FetchEventOpParent>&& aReal)
    559    : mArgs(aArgs), mPromise(std::move(aPromise)), mReal(aReal) {
    560  AssertIsOnBackgroundThread();
    561  MOZ_ASSERT(mPromise);
    562 
    563  // If there is a TParentToParentStream in the request body, we need to
    564  // save it to our stream.
    565  IPCInternalRequest& req = mArgs.common().internalRequest();
    566  if (req.body().isSome() &&
    567      req.body().ref().type() == BodyStreamVariant::TParentToParentStream) {
    568    nsCOMPtr<nsIInputStream> stream;
    569    auto streamLength = req.bodySize();
    570    const auto& uuid = req.body().ref().get_ParentToParentStream().uuid();
    571 
    572    auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
    573    MOZ_DIAGNOSTIC_ASSERT(storage);
    574    storage->GetStream(uuid, 0, streamLength, getter_AddRefs(mBodyStream));
    575    storage->ForgetStream(uuid);
    576 
    577    MOZ_DIAGNOSTIC_ASSERT(mBodyStream);
    578 
    579    req.body() = Nothing();
    580  }
    581 }
    582 
    583 RemoteWorkerController::PendingSWFetchEventOp::~PendingSWFetchEventOp() {
    584  AssertIsOnBackgroundThread();
    585  MOZ_DIAGNOSTIC_ASSERT(!mPromise);
    586 }
    587 
    588 bool RemoteWorkerController::PendingSWFetchEventOp::MaybeStart(
    589    RemoteWorkerController* const aOwner) {
    590  AssertIsOnBackgroundThread();
    591  MOZ_ASSERT(mPromise);
    592  MOZ_ASSERT(aOwner);
    593 
    594  if (NS_WARN_IF(aOwner->mState == RemoteWorkerController::eTerminated)) {
    595    mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
    596    mPromise = nullptr;
    597    // Because the worker has transitioned to terminated, this operation is moot
    598    // and so we should return true because there's no need to queue it.
    599    return true;
    600  }
    601 
    602  // The target content process must still be starting up.
    603  if (!aOwner->mActor) {
    604    MOZ_ASSERT(aOwner->mState == RemoteWorkerController::ePending);
    605    return false;
    606  }
    607 
    608  // At this point we are handing off responsibility for the promise to the
    609  // actor.
    610  FetchEventOpProxyParent::Create(aOwner->mActor.get(), std::move(mPromise),
    611                                  mArgs, std::move(mReal),
    612                                  std::move(mBodyStream));
    613 
    614  return true;
    615 }
    616 
    617 void RemoteWorkerController::PendingSWFetchEventOp::Cancel() {
    618  AssertIsOnBackgroundThread();
    619  MOZ_ASSERT(mPromise);
    620 
    621  if (mPromise) {
    622    mPromise->Reject(NS_ERROR_DOM_ABORT_ERR, __func__);
    623    mPromise = nullptr;
    624  }
    625 }
    626 
    627 }  // namespace dom
    628 }  // namespace mozilla