tor-browser

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

UtilityProcessManager.h (7478B)


      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 #ifndef _include_ipc_glue_UtilityProcessManager_h_
      7 #define _include_ipc_glue_UtilityProcessManager_h_
      8 #include "mozilla/MozPromise.h"
      9 #include "mozilla/dom/ipc/IdType.h"
     10 #include "mozilla/ipc/UtilityProcessHost.h"
     11 #include "mozilla/EnumeratedArray.h"
     12 #include "mozilla/ProcInfo.h"
     13 #include "nsIObserver.h"
     14 #include "nsTArray.h"
     15 
     16 #include "mozilla/PRemoteMediaManagerChild.h"
     17 
     18 namespace mozilla {
     19 
     20 class MemoryReportingProcess;
     21 
     22 namespace dom {
     23 class JSOracleParent;
     24 class WindowsUtilsParent;
     25 }  // namespace dom
     26 
     27 namespace widget::filedialog {
     28 class ProcessProxy;
     29 }  // namespace widget::filedialog
     30 
     31 namespace ipc {
     32 
     33 class UtilityProcessParent;
     34 
     35 // The UtilityProcessManager is a singleton responsible for creating
     36 // Utility-bound objects that may live in another process. Currently, it
     37 // provides access to the Utility process via ContentParent.
     38 class UtilityProcessManager final : public UtilityProcessHost::Listener {
     39  friend class UtilityProcessParent;
     40 
     41 public:
     42  template <typename T>
     43  using LaunchPromise = MozPromise<T, LaunchError, true>;
     44  template <typename T>
     45  using SharedLaunchPromise = MozPromise<T, LaunchError, false>;
     46 
     47  using StartRemoteDecodingUtilityPromise =
     48      LaunchPromise<Endpoint<PRemoteMediaManagerChild>>;
     49  using JSOraclePromise = GenericNonExclusivePromise;
     50 
     51 #ifdef XP_WIN
     52  using WindowsUtilsPromise = LaunchPromise<RefPtr<dom::WindowsUtilsParent>>;
     53  using WinFileDialogPromise = LaunchPromise<widget::filedialog::ProcessProxy>;
     54 #endif
     55 
     56  static RefPtr<UtilityProcessManager> GetSingleton();
     57 
     58  static RefPtr<UtilityProcessManager> GetIfExists();
     59 
     60  // Launch a new Utility process asynchronously
     61  RefPtr<SharedLaunchPromise<Ok>> LaunchProcess(SandboxingKind aSandbox);
     62 
     63  template <typename Actor>
     64  RefPtr<LaunchPromise<Ok>> StartUtility(RefPtr<Actor> aActor,
     65                                         SandboxingKind aSandbox);
     66 
     67  RefPtr<StartRemoteDecodingUtilityPromise> StartProcessForRemoteMediaDecoding(
     68      EndpointProcInfo aOtherProcess, dom::ContentParentId aChildId,
     69      SandboxingKind aSandbox);
     70 
     71  RefPtr<JSOraclePromise> StartJSOracle(mozilla::dom::JSOracleParent* aParent);
     72 
     73 #ifdef XP_WIN
     74  // Get the (possibly already resolved) promise for the Windows utility
     75  // process actor.  Creates the process if it is not running.
     76  RefPtr<WindowsUtilsPromise> GetWindowsUtilsPromise();
     77  // Releases the WindowsUtils actor so that it can be destroyed.
     78  // Subsequent attempts to use WindowsUtils will create a new process.
     79  void ReleaseWindowsUtils();
     80 
     81  // Get a new Windows file-dialog utility-process actor. These are never
     82  // reused; this will always return a fresh actor.
     83  RefPtr<WinFileDialogPromise> CreateWinFileDialogActor();
     84 #endif
     85 
     86  void OnProcessUnexpectedShutdown(UtilityProcessHost* aHost);
     87 
     88  // Returns the platform pid for this utility sandbox process.
     89  Maybe<base::ProcessId> ProcessPid(SandboxingKind aSandbox);
     90 
     91  // Create a MemoryReportingProcess object for this utility process
     92  RefPtr<MemoryReportingProcess> GetProcessMemoryReporter(
     93      UtilityProcessParent* parent);
     94 
     95  // Returns access to the PUtility protocol if a Utility process for that
     96  // sandbox is present.
     97  RefPtr<UtilityProcessParent> GetProcessParent(SandboxingKind aSandbox) {
     98    RefPtr<ProcessFields> p = GetProcess(aSandbox);
     99    if (!p) {
    100      return nullptr;
    101    }
    102    return p->mProcessParent;
    103  }
    104 
    105  // Get a list of all valid utility process parent references
    106  nsTArray<RefPtr<UtilityProcessParent>> GetAllProcessesProcessParent() {
    107    nsTArray<RefPtr<UtilityProcessParent>> rv;
    108    for (auto& p : mProcesses) {
    109      if (p && p->mProcessParent) {
    110        rv.AppendElement(p->mProcessParent);
    111      }
    112    }
    113    return rv;
    114  }
    115 
    116  // Returns the Utility Process for that sandbox
    117  UtilityProcessHost* Process(SandboxingKind aSandbox) {
    118    RefPtr<ProcessFields> p = GetProcess(aSandbox);
    119    if (!p) {
    120      return nullptr;
    121    }
    122    return p->mProcess;
    123  }
    124 
    125  void RegisterActor(const RefPtr<UtilityProcessParent>& aParent,
    126                     UtilityActorName aActorName) {
    127    for (auto& p : mProcesses) {
    128      if (p && p->mProcessParent && p->mProcessParent == aParent) {
    129        p->mActors.AppendElement(aActorName);
    130        return;
    131      }
    132    }
    133  }
    134 
    135  Span<const UtilityActorName> GetActors(
    136      const RefPtr<UtilityProcessParent>& aParent) {
    137    for (auto& p : mProcesses) {
    138      if (p && p->mProcessParent && p->mProcessParent == aParent) {
    139        return p->mActors;
    140      }
    141    }
    142    return {};
    143  }
    144 
    145  Span<const UtilityActorName> GetActors(GeckoChildProcessHost* aHost) {
    146    for (auto& p : mProcesses) {
    147      if (p && p->mProcess == aHost) {
    148        return p->mActors;
    149      }
    150    }
    151    return {};
    152  }
    153 
    154  Span<const UtilityActorName> GetActors(SandboxingKind aSbKind) {
    155    auto proc = GetProcess(aSbKind);
    156    if (!proc) {
    157      return {};
    158    }
    159    return proc->mActors;
    160  }
    161 
    162  // Shutdown the Utility process for that sandbox.
    163  void CleanShutdown(SandboxingKind aSandbox);
    164 
    165  // Shutdown all utility processes
    166  void CleanShutdownAllProcesses();
    167 
    168  uint16_t AliveProcesses();
    169 
    170 private:
    171  ~UtilityProcessManager();
    172 
    173  bool IsProcessLaunching(SandboxingKind aSandbox);
    174  bool IsProcessDestroyed(SandboxingKind aSandbox);
    175 
    176  // Called from our xpcom-shutdown observer.
    177  void OnXPCOMShutdown();
    178  void OnPreferenceChange(const char16_t* aData);
    179 
    180  UtilityProcessManager();
    181 
    182  void Init();
    183 
    184  void DestroyProcess(SandboxingKind aSandbox);
    185 
    186  bool IsShutdown() const;
    187 
    188  class Observer final : public nsIObserver {
    189   public:
    190    NS_DECL_ISUPPORTS
    191    NS_DECL_NSIOBSERVER
    192    explicit Observer(UtilityProcessManager* aManager);
    193 
    194   protected:
    195    ~Observer() = default;
    196 
    197    RefPtr<UtilityProcessManager> mManager;
    198  };
    199  friend class Observer;
    200 
    201  RefPtr<Observer> mObserver;
    202 
    203  class ProcessFields final {
    204   public:
    205    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProcessFields);
    206 
    207    explicit ProcessFields(SandboxingKind aSandbox) : mSandbox(aSandbox) {};
    208 
    209    // Promise will be resolved when this Utility process has been fully started
    210    // and configured. Only accessed on the main thread.
    211    RefPtr<SharedLaunchPromise<Ok>> mLaunchPromise;
    212 
    213    uint32_t mNumProcessAttempts = 0;
    214    uint32_t mNumUnexpectedCrashes = 0;
    215 
    216    // Fields that are associated with the current Utility process.
    217    UtilityProcessHost* mProcess = nullptr;
    218    RefPtr<UtilityProcessParent> mProcessParent = nullptr;
    219 
    220    // Collects any pref changes that occur during process launch (after
    221    // the initial map is passed in command-line arguments) to be sent
    222    // when the process can receive IPC messages.
    223    nsTArray<dom::Pref> mQueuedPrefs;
    224 
    225    nsTArray<UtilityActorName> mActors;
    226 
    227    SandboxingKind mSandbox = SandboxingKind::COUNT;
    228 
    229   protected:
    230    ~ProcessFields() = default;
    231  };
    232 
    233  EnumeratedArray<SandboxingKind, RefPtr<ProcessFields>,
    234                  size_t(SandboxingKind::COUNT)>
    235      mProcesses;
    236 
    237  RefPtr<ProcessFields> GetProcess(SandboxingKind);
    238  bool NoMoreProcesses();
    239 
    240 #ifdef XP_WIN
    241  RefPtr<dom::WindowsUtilsParent> mWindowsUtils;
    242 #endif  // XP_WIN
    243 };
    244 
    245 }  // namespace ipc
    246 
    247 }  // namespace mozilla
    248 
    249 #endif  // _include_ipc_glue_UtilityProcessManager_h_