tor-browser

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

ClientHandle.cpp (6115B)


      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 "ClientHandle.h"
      8 
      9 #include "ClientHandleChild.h"
     10 #include "ClientHandleOpChild.h"
     11 #include "ClientManager.h"
     12 #include "ClientPrincipalUtils.h"
     13 #include "ClientState.h"
     14 #include "mozilla/dom/PClientManagerChild.h"
     15 #include "mozilla/dom/ServiceWorkerDescriptor.h"
     16 #include "mozilla/dom/ipc/StructuredCloneData.h"
     17 
     18 namespace mozilla::dom {
     19 
     20 using mozilla::dom::ipc::StructuredCloneData;
     21 
     22 ClientHandle::~ClientHandle() { Shutdown(); }
     23 
     24 void ClientHandle::Shutdown() {
     25  NS_ASSERT_OWNINGTHREAD(ClientSource);
     26  if (IsShutdown()) {
     27    return;
     28  }
     29 
     30  ShutdownThing();
     31 
     32  mManager = nullptr;
     33 }
     34 
     35 void ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs,
     36                           const ClientOpCallback&& aResolveCallback,
     37                           const ClientOpCallback&& aRejectCallback) {
     38  // Hold a ref to the client until the remote operation completes.  Otherwise
     39  // the ClientHandle might get de-refed and teardown the actor before we
     40  // get an answer.
     41  RefPtr<ClientHandle> kungFuGrip = this;
     42 
     43  MaybeExecute(
     44      [&aArgs, kungFuGrip, aRejectCallback,
     45       resolve = std::move(aResolveCallback)](ClientHandleChild* aActor) {
     46        MOZ_DIAGNOSTIC_ASSERT(aActor);
     47        ClientHandleOpChild* actor = new ClientHandleOpChild(
     48            kungFuGrip, aArgs, std::move(resolve), std::move(aRejectCallback));
     49        if (!aActor->SendPClientHandleOpConstructor(actor, aArgs)) {
     50          // Constructor failure will call reject callback via ActorDestroy()
     51          return;
     52        }
     53      },
     54      [aRejectCallback] {
     55        MOZ_DIAGNOSTIC_ASSERT(aRejectCallback);
     56        CopyableErrorResult rv;
     57        rv.ThrowInvalidStateError("Client has been destroyed");
     58        aRejectCallback(rv);
     59      });
     60 }
     61 
     62 void ClientHandle::OnShutdownThing() {
     63  NS_ASSERT_OWNINGTHREAD(ClientHandle);
     64  if (!mDetachPromise) {
     65    return;
     66  }
     67  mDetachPromise->Resolve(true, __func__);
     68 }
     69 
     70 ClientHandle::ClientHandle(ClientManager* aManager,
     71                           nsISerialEventTarget* aSerialEventTarget,
     72                           const ClientInfo& aClientInfo)
     73    : mManager(aManager),
     74      mSerialEventTarget(aSerialEventTarget),
     75      mClientInfo(aClientInfo) {
     76  MOZ_DIAGNOSTIC_ASSERT(mManager);
     77  MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
     78  MOZ_ASSERT(mSerialEventTarget->IsOnCurrentThread());
     79 }
     80 
     81 void ClientHandle::Activate(PClientManagerChild* aActor) {
     82  NS_ASSERT_OWNINGTHREAD(ClientHandle);
     83 
     84  if (IsShutdown()) {
     85    return;
     86  }
     87 
     88  RefPtr<ClientHandleChild> actor = new ClientHandleChild();
     89  if (!aActor->SendPClientHandleConstructor(actor, mClientInfo.ToIPC())) {
     90    Shutdown();
     91    return;
     92  }
     93 
     94  ActivateThing(actor);
     95 }
     96 
     97 void ClientHandle::ExecutionReady(const ClientInfo& aClientInfo) {
     98  mClientInfo = aClientInfo;
     99 }
    100 
    101 const ClientInfo& ClientHandle::Info() const { return mClientInfo; }
    102 
    103 RefPtr<GenericErrorResultPromise> ClientHandle::Control(
    104    const ServiceWorkerDescriptor& aServiceWorker) {
    105  RefPtr<GenericErrorResultPromise::Private> outerPromise =
    106      new GenericErrorResultPromise::Private(__func__);
    107 
    108  // We should never have a cross-origin controller.  Since this would be
    109  // same-origin policy violation we do a full release assertion here.
    110  MOZ_RELEASE_ASSERT(ClientMatchPrincipalInfo(mClientInfo.PrincipalInfo(),
    111                                              aServiceWorker.PrincipalInfo()));
    112 
    113  StartOp(
    114      ClientControlledArgs(aServiceWorker.ToIPC()),
    115      [outerPromise](const ClientOpResult& aResult) {
    116        outerPromise->Resolve(true, __func__);
    117      },
    118      [outerPromise](const ClientOpResult& aResult) {
    119        outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
    120      });
    121 
    122  return outerPromise;
    123 }
    124 
    125 RefPtr<ClientStatePromise> ClientHandle::Focus(CallerType aCallerType) {
    126  RefPtr<ClientStatePromise::Private> outerPromise =
    127      new ClientStatePromise::Private(__func__);
    128 
    129  StartOp(
    130      ClientFocusArgs(aCallerType),
    131      [outerPromise](const ClientOpResult& aResult) {
    132        outerPromise->Resolve(
    133            ClientState::FromIPC(aResult.get_IPCClientState()), __func__);
    134      },
    135      [outerPromise](const ClientOpResult& aResult) {
    136        outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
    137      });
    138 
    139  return outerPromise;
    140 }
    141 
    142 RefPtr<GenericErrorResultPromise> ClientHandle::PostMessage(
    143    StructuredCloneData& aData, const ServiceWorkerDescriptor& aSource) {
    144  if (IsShutdown()) {
    145    CopyableErrorResult rv;
    146    rv.ThrowInvalidStateError("Client has been destroyed");
    147    return GenericErrorResultPromise::CreateAndReject(rv, __func__);
    148  }
    149 
    150  ClientPostMessageArgs args;
    151  args.serviceWorker() = aSource.ToIPC();
    152 
    153  if (!aData.BuildClonedMessageData(args.clonedData())) {
    154    CopyableErrorResult rv;
    155    rv.ThrowInvalidStateError("Failed to clone data");
    156    return GenericErrorResultPromise::CreateAndReject(rv, __func__);
    157  }
    158 
    159  RefPtr<GenericErrorResultPromise::Private> outerPromise =
    160      new GenericErrorResultPromise::Private(__func__);
    161 
    162  StartOp(
    163      std::move(args),
    164      [outerPromise](const ClientOpResult& aResult) {
    165        outerPromise->Resolve(true, __func__);
    166      },
    167      [outerPromise](const ClientOpResult& aResult) {
    168        outerPromise->Reject(aResult.get_CopyableErrorResult(), __func__);
    169      });
    170 
    171  return outerPromise;
    172 }
    173 
    174 RefPtr<GenericPromise> ClientHandle::OnDetach() {
    175  NS_ASSERT_OWNINGTHREAD(ClientSource);
    176 
    177  if (!mDetachPromise) {
    178    mDetachPromise = new GenericPromise::Private(__func__);
    179    if (IsShutdown()) {
    180      mDetachPromise->Resolve(true, __func__);
    181    }
    182  }
    183 
    184  return mDetachPromise;
    185 }
    186 
    187 void ClientHandle::EvictFromBFCache() {
    188  ClientEvictBFCacheArgs args;
    189  StartOp(
    190      std::move(args), [](const ClientOpResult& aResult) {},
    191      [](const ClientOpResult& aResult) {});
    192 }
    193 
    194 }  // namespace mozilla::dom