tor-browser

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

RDDParent.cpp (11132B)


      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 #include "RDDParent.h"
      7 
      8 #if defined(XP_WIN)
      9 #  include <dwrite.h>
     10 #  include <process.h>
     11 
     12 #  include "WMF.h"
     13 #  include "WMFDecoderModule.h"
     14 #  include "mozilla/WinDllServices.h"
     15 #  include "mozilla/gfx/DeviceManagerDx.h"
     16 #else
     17 #  include <unistd.h>
     18 #endif
     19 
     20 #include "MediaCodecsSupport.h"
     21 #include "gfxConfig.h"
     22 #include "mozilla/Assertions.h"
     23 #include "mozilla/FOGIPC.h"
     24 #include "mozilla/Preferences.h"
     25 #include "mozilla/RemoteMediaManagerParent.h"
     26 #include "mozilla/TimeStamp.h"
     27 #include "mozilla/dom/MemoryReportRequest.h"
     28 #include "mozilla/gfx/gfxVars.h"
     29 #include "mozilla/glean/GleanTestsTestMetrics.h"
     30 #include "mozilla/glean/IpcMetrics.h"
     31 #include "mozilla/ipc/CrashReporterClient.h"
     32 #include "mozilla/ipc/ProcessChild.h"
     33 
     34 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
     35 #  include "mozilla/Sandbox.h"
     36 #  include "mozilla/SandboxProfilerObserver.h"
     37 #endif
     38 
     39 #include "ChildProfilerController.h"
     40 
     41 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
     42 #  include "RDDProcessHost.h"
     43 #  include "mozilla/Sandbox.h"
     44 #  include "nsMacUtilsImpl.h"
     45 #endif
     46 
     47 #include "mozilla/ipc/ProcessUtils.h"
     48 #include "nsDebugImpl.h"
     49 #include "nsIObserverService.h"
     50 #include "nsIXULRuntime.h"
     51 #include "nsThreadManager.h"
     52 
     53 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
     54 #  include "mozilla/SandboxTestingChild.h"
     55 #endif
     56 
     57 #if defined(XP_MACOSX) || defined(XP_LINUX)
     58 #  include "VideoUtils.h"
     59 #endif
     60 
     61 #if defined(MOZ_WIDGET_GTK)
     62 #  include "mozilla/widget/DMABufSurface.h"
     63 #endif
     64 
     65 namespace TelemetryScalar {
     66 void Set(mozilla::Telemetry::ScalarID aId, uint32_t aValue);
     67 }
     68 
     69 namespace mozilla {
     70 
     71 using namespace ipc;
     72 using namespace gfx;
     73 
     74 static RDDParent* sRDDParent;
     75 
     76 RDDParent::RDDParent() : mLaunchTime(TimeStamp::Now()) { sRDDParent = this; }
     77 
     78 RDDParent::~RDDParent() { sRDDParent = nullptr; }
     79 
     80 /* static */
     81 RDDParent* RDDParent::GetSingleton() {
     82  MOZ_DIAGNOSTIC_ASSERT(sRDDParent);
     83  return sRDDParent;
     84 }
     85 
     86 bool RDDParent::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
     87                     const char* aParentBuildID) {
     88  // Initialize the thread manager before starting IPC. Otherwise, messages
     89  // may be posted to the main thread and we won't be able to process them.
     90  if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
     91    return false;
     92  }
     93 
     94  // Now it's safe to start IPC.
     95  if (NS_WARN_IF(!aEndpoint.Bind(this))) {
     96    return false;
     97  }
     98 
     99  nsDebugImpl::SetMultiprocessMode("RDD");
    100 
    101  // This must be checked before any IPDL message, which may hit sentinel
    102  // errors due to parent and content processes having different
    103  // versions.
    104  MessageChannel* channel = GetIPCChannel();
    105  if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
    106    // We need to quit this process if the buildID doesn't match the parent's.
    107    // This can occur when an update occurred in the background.
    108    ProcessChild::QuickExit();
    109  }
    110 
    111  // Init crash reporter support.
    112  CrashReporterClient::InitSingleton(this);
    113 
    114  if (NS_FAILED(NS_InitMinimalXPCOM())) {
    115    return false;
    116  }
    117 
    118  gfxConfig::Init();
    119  gfxVars::Initialize();
    120 #ifdef XP_WIN
    121  DeviceManagerDx::Init();
    122  auto rv = wmf::MediaFoundationInitializer::HasInitialized();
    123  if (!rv) {
    124    NS_WARNING("Failed to init Media Foundation in the RDD process");
    125  }
    126 #endif
    127 
    128  mozilla::ipc::SetThisProcessName("RDD Process");
    129 
    130  return true;
    131 }
    132 
    133 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
    134 extern "C" {
    135 void CGSShutdownServerConnections();
    136 };
    137 #endif
    138 
    139 mozilla::ipc::IPCResult RDDParent::RecvInit(
    140    nsTArray<GfxVarUpdate>&& vars, const Maybe<FileDescriptor>& aBrokerFd,
    141    const bool& aCanRecordReleaseTelemetry,
    142    const bool& aIsReadyForBackgroundProcessing) {
    143  gfxVars::ApplyUpdate(vars);
    144 
    145  auto supported = media::MCSInfo::GetSupportFromFactory();
    146  (void)SendUpdateMediaCodecsSupported(supported);
    147 
    148 #if defined(MOZ_SANDBOX)
    149 #  if defined(XP_MACOSX)
    150  // Close all current connections to the WindowServer. This ensures that the
    151  // Activity Monitor will not label the content process as "Not responding"
    152  // because it's not running a native event loop. See bug 1384336.
    153  CGSShutdownServerConnections();
    154 
    155 #  elif defined(XP_LINUX)
    156  int fd = -1;
    157  if (aBrokerFd.isSome()) {
    158    fd = aBrokerFd.value().ClonePlatformHandle().release();
    159  }
    160  RegisterProfilerObserversForSandboxProfiler();
    161  SetRemoteDataDecoderSandbox(fd);
    162 #  endif  // XP_MACOSX/XP_LINUX
    163 #endif    // MOZ_SANDBOX
    164 
    165 #if defined(XP_WIN)
    166  if (aCanRecordReleaseTelemetry) {
    167    RefPtr<DllServices> dllSvc(DllServices::Get());
    168    dllSvc->StartUntrustedModulesProcessor(aIsReadyForBackgroundProcessing);
    169  }
    170 #endif  // defined(XP_WIN)
    171  return IPC_OK();
    172 }
    173 
    174 IPCResult RDDParent::RecvUpdateVar(const nsTArray<GfxVarUpdate>& aUpdate) {
    175  gfxVars::ApplyUpdate(aUpdate);
    176 
    177  MOZ_ALWAYS_SUCCEEDS(NS_DispatchBackgroundTask(
    178      NS_NewRunnableFunction(
    179          "RDDParent::RecvUpdateVar",
    180          []() {
    181            NS_DispatchToMainThread(NS_NewRunnableFunction(
    182                "RDDParent::UpdateMediaCodecsSupported",
    183                [supported = media::MCSInfo::GetSupportFromFactory(
    184                     true /* force refresh */)]() {
    185                  if (auto* rdd = RDDParent::GetSingleton()) {
    186                    (void)rdd->SendUpdateMediaCodecsSupported(supported);
    187                  }
    188                }));
    189          }),
    190      nsIEventTarget::DISPATCH_NORMAL));
    191  return IPC_OK();
    192 }
    193 
    194 mozilla::ipc::IPCResult RDDParent::RecvInitProfiler(
    195    Endpoint<PProfilerChild>&& aEndpoint) {
    196  mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
    197  return IPC_OK();
    198 }
    199 
    200 mozilla::ipc::IPCResult RDDParent::RecvNewContentRemoteMediaManager(
    201    Endpoint<PRemoteMediaManagerParent>&& aEndpoint,
    202    const ContentParentId& aParentId) {
    203  if (!RemoteMediaManagerParent::CreateForContent(std::move(aEndpoint),
    204                                                  aParentId)) {
    205    return IPC_FAIL_NO_REASON(this);
    206  }
    207  return IPC_OK();
    208 }
    209 
    210 mozilla::ipc::IPCResult RDDParent::RecvInitVideoBridge(
    211    Endpoint<PVideoBridgeChild>&& aEndpoint, const bool& aCreateHardwareDevice,
    212    const ContentDeviceData& aContentDeviceData) {
    213  if (!RemoteMediaManagerParent::CreateVideoBridgeToOtherProcess(
    214          std::move(aEndpoint))) {
    215    return IPC_FAIL_NO_REASON(this);
    216  }
    217 
    218  gfxConfig::Inherit(
    219      {
    220          Feature::HW_COMPOSITING,
    221          Feature::D3D11_COMPOSITING,
    222          Feature::OPENGL_COMPOSITING,
    223      },
    224      aContentDeviceData.prefs());
    225 #ifdef XP_WIN
    226  if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
    227    auto* devmgr = DeviceManagerDx::Get();
    228    if (devmgr) {
    229      devmgr->ImportDeviceInfo(aContentDeviceData.d3d11());
    230      if (aCreateHardwareDevice) {
    231        devmgr->CreateContentDevices();
    232      }
    233    }
    234  }
    235 #endif
    236 
    237  return IPC_OK();
    238 }
    239 
    240 mozilla::ipc::IPCResult RDDParent::RecvRequestMemoryReport(
    241    const uint32_t& aGeneration, const bool& aAnonymize,
    242    const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile,
    243    const RequestMemoryReportResolver& aResolver) {
    244  nsPrintfCString processName("RDD (pid %u)", (unsigned)getpid());
    245 
    246  mozilla::dom::MemoryReportRequestClient::Start(
    247      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
    248      [&](const MemoryReport& aReport) {
    249        (void)GetSingleton()->SendAddMemoryReport(aReport);
    250      },
    251      aResolver);
    252  return IPC_OK();
    253 }
    254 
    255 #if defined(XP_WIN)
    256 mozilla::ipc::IPCResult RDDParent::RecvGetUntrustedModulesData(
    257    GetUntrustedModulesDataResolver&& aResolver) {
    258  RefPtr<DllServices> dllSvc(DllServices::Get());
    259  dllSvc->GetUntrustedModulesData()->Then(
    260      GetMainThreadSerialEventTarget(), __func__,
    261      [aResolver](Maybe<UntrustedModulesData>&& aData) {
    262        aResolver(std::move(aData));
    263      },
    264      [aResolver](nsresult aReason) { aResolver(Nothing()); });
    265  return IPC_OK();
    266 }
    267 
    268 mozilla::ipc::IPCResult RDDParent::RecvUnblockUntrustedModulesThread() {
    269  if (nsCOMPtr<nsIObserverService> obs =
    270          mozilla::services::GetObserverService()) {
    271    obs->NotifyObservers(nullptr, "unblock-untrusted-modules-thread", nullptr);
    272  }
    273  return IPC_OK();
    274 }
    275 #endif  // defined(XP_WIN)
    276 
    277 mozilla::ipc::IPCResult RDDParent::RecvPreferenceUpdate(const Pref& aPref) {
    278  Preferences::SetPreference(aPref);
    279  return IPC_OK();
    280 }
    281 
    282 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
    283 mozilla::ipc::IPCResult RDDParent::RecvInitSandboxTesting(
    284    Endpoint<PSandboxTestingChild>&& aEndpoint) {
    285  if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
    286    return IPC_FAIL(
    287        this, "InitSandboxTesting failed to initialise the child process.");
    288  }
    289  return IPC_OK();
    290 }
    291 #endif
    292 
    293 mozilla::ipc::IPCResult RDDParent::RecvFlushFOGData(
    294    FlushFOGDataResolver&& aResolver) {
    295  glean::FlushFOGData(std::move(aResolver));
    296  return IPC_OK();
    297 }
    298 
    299 mozilla::ipc::IPCResult RDDParent::RecvTestTriggerMetrics(
    300    TestTriggerMetricsResolver&& aResolve) {
    301  mozilla::glean::test_only_ipc::a_counter.Add(nsIXULRuntime::PROCESS_TYPE_RDD);
    302  aResolve(true);
    303  return IPC_OK();
    304 }
    305 
    306 mozilla::ipc::IPCResult RDDParent::RecvTestTelemetryProbes() {
    307  const uint32_t kExpectedUintValue = 42;
    308  TelemetryScalar::Set(Telemetry::ScalarID::TELEMETRY_TEST_RDD_ONLY_UINT,
    309                       kExpectedUintValue);
    310  return IPC_OK();
    311 }
    312 
    313 void RDDParent::ActorDestroy(ActorDestroyReason aWhy) {
    314 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
    315  DestroySandboxProfiler();
    316 #endif
    317 
    318  if (AbnormalShutdown == aWhy) {
    319    NS_WARNING("Shutting down RDD process early due to a crash!");
    320    glean::subprocess::abnormal_abort.Get("rdd"_ns).Add(1);
    321    ProcessChild::QuickExit();
    322  }
    323 
    324  // Send the last bits of Glean data over to the main process.
    325  glean::FlushFOGData(
    326      [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); });
    327 
    328 #ifndef NS_FREE_PERMANENT_DATA
    329  // No point in going through XPCOM shutdown because we don't keep persistent
    330  // state.
    331  ProcessChild::QuickExit();
    332 #endif
    333 
    334  // Wait until all RemoteMediaManagerParent have closed.
    335  mShutdownBlockers.WaitUntilClear(10 * 1000 /* 10s timeout*/)
    336      ->Then(GetCurrentSerialEventTarget(), __func__, [&]() {
    337 
    338 #if defined(XP_WIN)
    339        RefPtr<DllServices> dllSvc(DllServices::Get());
    340        dllSvc->DisableFull();
    341 #endif  // defined(XP_WIN)
    342 
    343        if (mProfilerController) {
    344          mProfilerController->Shutdown();
    345          mProfilerController = nullptr;
    346        }
    347 
    348        RemoteMediaManagerParent::ShutdownVideoBridge();
    349 
    350 #if defined(MOZ_WIDGET_GTK)
    351        // Linux runs VA-API decode on RDD process so we need to
    352        // shutdown GL here.
    353        DMABufSurface::ReleaseSnapshotGLContext();
    354 #endif
    355 
    356 #ifdef XP_WIN
    357        DeviceManagerDx::Shutdown();
    358 #endif
    359        gfxVars::Shutdown();
    360        gfxConfig::Shutdown();
    361        CrashReporterClient::DestroySingleton();
    362        XRE_ShutdownChildProcess();
    363      });
    364 }
    365 
    366 }  // namespace mozilla