tor-browser

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

ClientSourceOpChild.cpp (4376B)


      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 "ClientSourceOpChild.h"
      8 
      9 #include "ClientSource.h"
     10 #include "ClientSourceChild.h"
     11 #include "mozilla/Assertions.h"
     12 
     13 namespace mozilla::dom {
     14 
     15 ClientSource* ClientSourceOpChild::GetSource() const {
     16  auto actor = static_cast<ClientSourceChild*>(Manager());
     17  return actor->GetSource();
     18 }
     19 
     20 template <typename Method, typename... Args>
     21 void ClientSourceOpChild::DoSourceOp(Method aMethod, Args&&... aArgs) {
     22  RefPtr<ClientOpPromise> promise;
     23  nsCOMPtr<nsISerialEventTarget> target;
     24 
     25  // Some ClientSource operations can cause the ClientSource to be destroyed.
     26  // This means we should reference the ClientSource pointer for the minimum
     27  // possible to start the operation.  Use an extra block scope here to help
     28  // enforce this and prevent accidental usage later in the method.
     29  {
     30    ClientSource* source = GetSource();
     31    if (!source) {
     32      CopyableErrorResult rv;
     33      rv.ThrowAbortError("Unknown Client");
     34      (void)PClientSourceOpChild::Send__delete__(this, rv);
     35      return;
     36    }
     37 
     38    target = source->EventTarget();
     39 
     40    // This may cause the ClientSource object to be destroyed.  Do not
     41    // use the source variable after this call.
     42    promise = (source->*aMethod)(std::forward<Args>(aArgs)...);
     43  }
     44 
     45  // The ClientSource methods are required to always return a promise.  If
     46  // they encounter an error they should just immediately resolve or reject
     47  // the promise as appropriate.
     48  MOZ_DIAGNOSTIC_ASSERT(promise);
     49 
     50  // Capture 'this' is safe here because we disconnect the promise
     51  // ActorDestroy() which ensures neither lambda is called if the
     52  // actor is destroyed before the source operation completes.
     53  //
     54  // Also capture the promise to ensure it lives until we get a reaction
     55  // or the actor starts shutting down and we disconnect our Thenable.
     56  // If the ClientSource is doing something async it may throw away the
     57  // promise on its side if the global is closed.
     58  promise
     59      ->Then(
     60          target, __func__,
     61          [this, promise](const mozilla::dom::ClientOpResult& aResult) {
     62            mPromiseRequestHolder.Complete();
     63            (void)PClientSourceOpChild::Send__delete__(this, aResult);
     64          },
     65          [this, promise](const CopyableErrorResult& aRv) {
     66            mPromiseRequestHolder.Complete();
     67            (void)PClientSourceOpChild::Send__delete__(this, aRv);
     68          })
     69      ->Track(mPromiseRequestHolder);
     70 }
     71 
     72 void ClientSourceOpChild::ActorDestroy(ActorDestroyReason aReason) {
     73  Cleanup();
     74 }
     75 
     76 void ClientSourceOpChild::Init(const ClientOpConstructorArgs& aArgs) {
     77  switch (aArgs.type()) {
     78    case ClientOpConstructorArgs::TClientControlledArgs: {
     79      DoSourceOp(&ClientSource::Control, aArgs.get_ClientControlledArgs());
     80      break;
     81    }
     82    case ClientOpConstructorArgs::TClientFocusArgs: {
     83      DoSourceOp(&ClientSource::Focus, aArgs.get_ClientFocusArgs());
     84      break;
     85    }
     86    case ClientOpConstructorArgs::TClientPostMessageArgs: {
     87      DoSourceOp(&ClientSource::PostMessage, aArgs.get_ClientPostMessageArgs());
     88      break;
     89    }
     90    case ClientOpConstructorArgs::TClientClaimArgs: {
     91      MOZ_ASSERT_UNREACHABLE("shouldn't happen with parent intercept");
     92      break;
     93    }
     94    case ClientOpConstructorArgs::TClientGetInfoAndStateArgs: {
     95      DoSourceOp(&ClientSource::GetInfoAndState,
     96                 aArgs.get_ClientGetInfoAndStateArgs());
     97      break;
     98    }
     99    case ClientOpConstructorArgs::TClientEvictBFCacheArgs: {
    100      DoSourceOp(&ClientSource::EvictFromBFCacheOp);
    101      break;
    102    }
    103    default: {
    104      MOZ_ASSERT_UNREACHABLE("unknown client operation!");
    105      break;
    106    }
    107  }
    108 
    109  mInitialized.Flip();
    110 
    111  if (mDeletionRequested) {
    112    Cleanup();
    113    delete this;
    114  }
    115 }
    116 
    117 void ClientSourceOpChild::ScheduleDeletion() {
    118  if (mInitialized) {
    119    Cleanup();
    120    delete this;
    121    return;
    122  }
    123 
    124  mDeletionRequested.Flip();
    125 }
    126 
    127 ClientSourceOpChild::~ClientSourceOpChild() {
    128  MOZ_DIAGNOSTIC_ASSERT(mInitialized);
    129 }
    130 
    131 void ClientSourceOpChild::Cleanup() {
    132  mPromiseRequestHolder.DisconnectIfExists();
    133 }
    134 
    135 }  // namespace mozilla::dom