tor-browser

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

SocketProcessBridgeChild.cpp (6385B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "SocketProcessBridgeChild.h"
      7 #include "SocketProcessLogging.h"
      8 
      9 #include "mozilla/AppShutdown.h"
     10 #include "mozilla/Components.h"
     11 #include "mozilla/dom/ContentChild.h"
     12 #include "mozilla/ipc/BackgroundChild.h"
     13 #include "mozilla/ipc/Endpoint.h"
     14 #include "mozilla/net/NeckoChild.h"
     15 #include "nsIObserverService.h"
     16 #include "nsThreadUtils.h"
     17 #include "mozilla/Preferences.h"
     18 #include "mozilla/StaticPrefs_network.h"
     19 
     20 namespace mozilla {
     21 
     22 using dom::ContentChild;
     23 
     24 namespace net {
     25 
     26 StaticRefPtr<SocketProcessBridgeChild>
     27    SocketProcessBridgeChild::sSocketProcessBridgeChild;
     28 
     29 NS_IMPL_ISUPPORTS(SocketProcessBridgeChild, nsIObserver)
     30 
     31 // static
     32 bool SocketProcessBridgeChild::Create(
     33    Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
     34  MOZ_ASSERT(NS_IsMainThread());
     35 
     36  sSocketProcessBridgeChild = new SocketProcessBridgeChild();
     37 
     38  if (!aEndpoint.Bind(sSocketProcessBridgeChild)) {
     39    MOZ_ASSERT(false, "Bind failed!");
     40    sSocketProcessBridgeChild = nullptr;
     41    return false;
     42  }
     43 
     44  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     45  if (os) {
     46    os->AddObserver(sSocketProcessBridgeChild, "content-child-shutdown", false);
     47  }
     48 
     49  sSocketProcessBridgeChild->mSocketProcessPid = aEndpoint.OtherPid();
     50  return true;
     51 }
     52 
     53 // static
     54 already_AddRefed<SocketProcessBridgeChild>
     55 SocketProcessBridgeChild::GetSingleton() {
     56  RefPtr<SocketProcessBridgeChild> child = sSocketProcessBridgeChild;
     57  return child.forget();
     58 }
     59 
     60 // static
     61 RefPtr<SocketProcessBridgeChild::GetPromise>
     62 SocketProcessBridgeChild::GetSocketProcessBridge() {
     63  MOZ_ASSERT(NS_IsMainThread());
     64 
     65  if (!StaticPrefs::network_process_enabled()) {
     66    return GetPromise::CreateAndReject(nsCString("Socket process disabled!"),
     67                                       __func__);
     68  }
     69 
     70  if (!gNeckoChild) {
     71    return GetPromise::CreateAndReject(nsCString("No NeckoChild!"), __func__);
     72  }
     73 
     74  // ContentChild is shutting down, we should not try to create
     75  // SocketProcessBridgeChild.
     76  ContentChild* content = ContentChild::GetSingleton();
     77  if (!content || content->IsShuttingDown()) {
     78    return GetPromise::CreateAndReject(
     79        nsCString("ContentChild is shutting down."), __func__);
     80  }
     81 
     82  if (sSocketProcessBridgeChild) {
     83    return GetPromise::CreateAndResolve(sSocketProcessBridgeChild, __func__);
     84  }
     85 
     86  return gNeckoChild->SendInitSocketProcessBridge()->Then(
     87      GetMainThreadSerialEventTarget(), __func__,
     88      [](NeckoChild::InitSocketProcessBridgePromise::ResolveOrRejectValue&&
     89             aResult) {
     90        ContentChild* content = ContentChild::GetSingleton();
     91        if (!content || content->IsShuttingDown()) {
     92          return GetPromise::CreateAndReject(
     93              nsCString("ContentChild is shutting down."), __func__);
     94        }
     95        if (!sSocketProcessBridgeChild) {
     96          if (aResult.IsReject()) {
     97            return GetPromise::CreateAndReject(
     98                nsCString("SendInitSocketProcessBridge failed"), __func__);
     99          }
    100 
    101          if (!aResult.ResolveValue().IsValid()) {
    102            return GetPromise::CreateAndReject(
    103                nsCString(
    104                    "SendInitSocketProcessBridge resolved with an invalid "
    105                    "endpoint!"),
    106                __func__);
    107          }
    108 
    109          if (!SocketProcessBridgeChild::Create(
    110                  std::move(aResult.ResolveValue()))) {
    111            return GetPromise::CreateAndReject(
    112                nsCString("SendInitSocketProcessBridge resolved with a valid "
    113                          "endpoint, "
    114                          "but SocketProcessBridgeChild::Create failed!"),
    115                __func__);
    116          }
    117        }
    118 
    119        return GetPromise::CreateAndResolve(sSocketProcessBridgeChild,
    120                                            __func__);
    121      });
    122 }
    123 
    124 SocketProcessBridgeChild::SocketProcessBridgeChild() : mShuttingDown(false) {
    125  LOG(("CONSTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
    126 }
    127 
    128 SocketProcessBridgeChild::~SocketProcessBridgeChild() {
    129  LOG(("DESTRUCT SocketProcessBridgeChild::SocketProcessBridgeChild\n"));
    130 }
    131 
    132 mozilla::ipc::IPCResult SocketProcessBridgeChild::RecvTest() {
    133  LOG(("SocketProcessBridgeChild::RecvTest\n"));
    134  return IPC_OK();
    135 }
    136 
    137 void SocketProcessBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
    138  LOG(("SocketProcessBridgeChild::ActorDestroy\n"));
    139  if (AbnormalShutdown == aWhy) {
    140    if (gNeckoChild &&
    141        !AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
    142      // Let NeckoParent know that the socket process connections must be
    143      // rebuilt.
    144      gNeckoChild->SendResetSocketProcessBridge();
    145    }
    146 
    147    nsresult res;
    148    nsCOMPtr<nsISerialEventTarget> mSTSThread;
    149    mSTSThread = mozilla::components::SocketTransport::Service(&res);
    150    if (NS_SUCCEEDED(res) && mSTSThread) {
    151      // This must be called off the main thread.  If we don't make this call
    152      // ipc::BackgroundChild::GetOrCreateSocketActorForCurrentThread() will
    153      // return the previous actor that is no longer able to send. This causes
    154      // rebuilding the socket process connections to fail.
    155      MOZ_ALWAYS_SUCCEEDS(mSTSThread->Dispatch(NS_NewRunnableFunction(
    156          "net::SocketProcessBridgeChild::ActorDestroy",
    157          []() { ipc::BackgroundChild::CloseForCurrentThread(); })));
    158    }
    159  }
    160 
    161  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    162  if (os) {
    163    os->RemoveObserver(this, "content-child-shutdown");
    164  }
    165  GetCurrentSerialEventTarget()->Dispatch(
    166      NewRunnableMethod("net::SocketProcessBridgeChild::DeferredDestroy", this,
    167                        &SocketProcessBridgeChild::DeferredDestroy));
    168  mShuttingDown = true;
    169 }
    170 
    171 NS_IMETHODIMP
    172 SocketProcessBridgeChild::Observe(nsISupports* aSubject, const char* aTopic,
    173                                  const char16_t* aData) {
    174  if (!strcmp(aTopic, "content-child-shutdown")) {
    175    PSocketProcessBridgeChild::Close();
    176  }
    177  return NS_OK;
    178 }
    179 
    180 void SocketProcessBridgeChild::DeferredDestroy() {
    181  MOZ_ASSERT(NS_IsMainThread());
    182 
    183  sSocketProcessBridgeChild = nullptr;
    184 }
    185 
    186 }  // namespace net
    187 }  // namespace mozilla