tor-browser

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

ContentProcess.cpp (6467B)


      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 "ContentProcess.h"
      8 
      9 #include "mozilla/Preferences.h"
     10 
     11 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
     12 #  include <stdlib.h>
     13 
     14 #  include "mozilla/Sandbox.h"
     15 #  include "mozilla/SandboxSettings.h"
     16 #endif
     17 
     18 #include "mozilla/GeckoArgs.h"
     19 #include "mozilla/Omnijar.h"
     20 #include "mozilla/ipc/BackgroundChild.h"
     21 #include "mozilla/ipc/ProcessUtils.h"
     22 #include "nsAppRunner.h"
     23 #include "nsCategoryManagerUtils.h"
     24 
     25 namespace mozilla::dom {
     26 
     27 static nsresult GetGREDir(nsIFile** aResult) {
     28  nsCOMPtr<nsIFile> current;
     29  nsresult rv = XRE_GetBinaryPath(getter_AddRefs(current));
     30  NS_ENSURE_SUCCESS(rv, rv);
     31 
     32 #if defined(XP_MACOSX)
     33  // Walk out of [subprocess].app/Contents/MacOS to the real GRE dir
     34  const int depth = 4;
     35 #elif defined(XP_IOS)
     36  // Walk out of Extensions/[subprocess].appex to the real GRE dir
     37  const int depth = 3;
     38 #else
     39  const int depth = 1;
     40 #endif
     41 
     42  for (int i = 0; i < depth; ++i) {
     43    nsCOMPtr<nsIFile> parent;
     44    rv = current->GetParent(getter_AddRefs(parent));
     45    NS_ENSURE_SUCCESS(rv, rv);
     46 
     47    current = parent;
     48    NS_ENSURE_TRUE(current, NS_ERROR_UNEXPECTED);
     49  }
     50 
     51 #if defined(XP_MACOSX)
     52  rv = current->SetNativeLeafName("Resources"_ns);
     53  NS_ENSURE_SUCCESS(rv, rv);
     54 #elif defined(XP_IOS)
     55  // FIXME: Consider looking up the GeckoView.framework bundle directly, rather
     56  // than deriving it from XRE_GetBinaryPath on iOS. This may be more resilient
     57  // especially once we properly bundle XUL into a separate framework or support
     58  // multiple embedders.
     59  rv = current->AppendNative("Frameworks"_ns);
     60  NS_ENSURE_SUCCESS(rv, rv);
     61  rv = current->AppendNative("GeckoView.framework"_ns);
     62  NS_ENSURE_SUCCESS(rv, rv);
     63  rv = current->AppendNative("Frameworks"_ns);
     64  NS_ENSURE_SUCCESS(rv, rv);
     65 #endif
     66 
     67  current.forget(aResult);
     68 
     69  return NS_OK;
     70 }
     71 
     72 ContentProcess::ContentProcess(IPC::Channel::ChannelHandle aClientChannel,
     73                               ProcessId aParentPid,
     74                               const nsID& aMessageChannelId)
     75    : ProcessChild(std::move(aClientChannel), aParentPid, aMessageChannelId) {
     76  NS_LogInit();
     77 }
     78 
     79 ContentProcess::~ContentProcess() { NS_LogTerm(); }
     80 
     81 bool ContentProcess::Init(int aArgc, char* aArgv[]) {
     82  InfallibleInit(aArgc, aArgv);
     83  return true;
     84 }
     85 
     86 void ContentProcess::InfallibleInit(int aArgc, char* aArgv[]) {
     87  Maybe<bool> isForBrowser = Nothing();
     88  Maybe<const char*> parentBuildID =
     89      geckoargs::sParentBuildID.Get(aArgc, aArgv);
     90 
     91  // command line: -jsInitHandle handle
     92  Maybe<mozilla::ipc::ReadOnlySharedMemoryHandle> jsInitHandle =
     93      geckoargs::sJsInitHandle.Get(aArgc, aArgv);
     94 
     95  nsCOMPtr<nsIFile> appDirArg;
     96  Maybe<const char*> appDir = geckoargs::sAppDir.Get(aArgc, aArgv);
     97  if (appDir.isSome()) {
     98    bool flag;
     99    nsresult rv = XRE_GetFileFromPath(*appDir, getter_AddRefs(appDirArg));
    100    if (NS_FAILED(rv) || NS_FAILED(appDirArg->Exists(&flag)) || !flag) {
    101      NS_WARNING("Invalid application directory passed to content process.");
    102      appDirArg = nullptr;
    103    }
    104  }
    105 
    106  Maybe<bool> safeMode = geckoargs::sSafeMode.Get(aArgc, aArgv);
    107  if (safeMode.isSome()) {
    108    gSafeMode = *safeMode;
    109  }
    110 
    111  Maybe<bool> isForBrowerParam = geckoargs::sIsForBrowser.Get(aArgc, aArgv);
    112  Maybe<bool> notForBrowserParam = geckoargs::sNotForBrowser.Get(aArgc, aArgv);
    113  if (isForBrowerParam.isSome()) {
    114    isForBrowser = Some(true);
    115  }
    116  if (notForBrowserParam.isSome()) {
    117    isForBrowser = Some(false);
    118  }
    119 
    120 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
    121  nsCOMPtr<nsIFile> profileDir;
    122  bool flag;
    123  Maybe<const char*> profile = geckoargs::sProfile.Get(aArgc, aArgv);
    124  // xpcshell self-test on macOS will hit this, so check isSome() otherwise
    125  // Maybe<> assertions will MOZ_CRASH() us.
    126  if (profile.isSome()) {
    127    nsresult rv = XRE_GetFileFromPath(*profile, getter_AddRefs(profileDir));
    128    if (NS_FAILED(rv) || NS_FAILED(profileDir->Exists(&flag)) || !flag) {
    129      NS_WARNING("Invalid profile directory passed to content process.");
    130      profileDir = nullptr;
    131    }
    132  } else {
    133    NS_WARNING("No profile directory passed to content process.");
    134  }
    135 #endif /* XP_MACOSX && MOZ_SANDBOX */
    136 
    137  // Did we find all the mandatory flags?
    138  if (isForBrowser.isNothing()) {
    139    MOZ_CRASH("isForBrowser flag missing");
    140  }
    141  if (parentBuildID.isNothing()) {
    142    MOZ_CRASH("parentBuildID flag missing");
    143  }
    144 
    145  if (!ProcessChild::InitPrefs(aArgc, aArgv)) {
    146    MOZ_CRASH("InitPrefs failed");
    147  }
    148 
    149  if (jsInitHandle &&
    150      !::mozilla::ipc::ImportSharedJSInit(jsInitHandle.extract())) {
    151    MOZ_CRASH("ImportSharedJSInit failed");
    152  }
    153 
    154  mContent.Init(TakeInitialEndpoint(), *parentBuildID, *isForBrowser);
    155 
    156  nsCOMPtr<nsIFile> greDir;
    157  nsresult rv = GetGREDir(getter_AddRefs(greDir));
    158  if (NS_FAILED(rv)) {
    159    MOZ_CRASH("GetGREDir failed");
    160  }
    161 
    162  nsCOMPtr<nsIFile> xpcomAppDir = appDirArg ? appDirArg : greDir;
    163 
    164  rv = mDirProvider.Initialize(xpcomAppDir, greDir);
    165  if (NS_FAILED(rv)) {
    166    MOZ_CRASH("mDirProvider.Initialize failed");
    167  }
    168 
    169  // Handle the -greomni/-appomni flags (unless the forkserver already
    170  // preloaded the jar(s)).
    171  if (!Omnijar::IsInitialized()) {
    172    Omnijar::ChildProcessInit(aArgc, aArgv);
    173  }
    174 
    175  rv = NS_InitXPCOM(nullptr, xpcomAppDir, &mDirProvider);
    176  if (NS_FAILED(rv)) {
    177    MOZ_CRASH("NS_InitXPCOM failed");
    178  }
    179 
    180  // "app-startup" is the name of both the category and the event
    181  NS_CreateServicesFromCategory("app-startup", nullptr, "app-startup", nullptr);
    182 
    183 #if (defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
    184  mContent.SetProfileDir(profileDir);
    185 #  if defined(DEBUG)
    186  if (IsContentSandboxEnabled()) {
    187    AssertMacSandboxEnabled();
    188  }
    189 #  endif /* DEBUG */
    190 #endif   /* XP_MACOSX && MOZ_SANDBOX */
    191 
    192  // Do this as early as possible to get the parent process to initialize the
    193  // background thread since we'll likely need database information very soon.
    194  mozilla::ipc::BackgroundChild::Startup();
    195  mozilla::ipc::BackgroundChild::InitContentStarter(&mContent);
    196 }
    197 
    198 // Note: CleanUp() never gets called in non-debug builds because we exit early
    199 // in ContentChild::ActorDestroy().
    200 void ContentProcess::CleanUp() {
    201  mDirProvider.DoShutdown();
    202  NS_ShutdownXPCOM(nullptr);
    203 }
    204 
    205 }  // namespace mozilla::dom