tor-browser

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

RDDProcessHost.h (5859B)


      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 #ifndef _include_dom_media_ipc_RDDProcessHost_h_
      8 #define _include_dom_media_ipc_RDDProcessHost_h_
      9 #include "mozilla/UniquePtr.h"
     10 #include "mozilla/ipc/GeckoChildProcessHost.h"
     11 #include "mozilla/ipc/ProtocolUtils.h"
     12 #include "mozilla/media/MediaUtils.h"
     13 
     14 namespace mozilla::ipc {
     15 class SharedPreferenceSerializer;
     16 }  // namespace mozilla::ipc
     17 class nsITimer;
     18 
     19 namespace mozilla {
     20 
     21 class RDDChild;
     22 
     23 // RDDProcessHost is the "parent process" container for a subprocess handle and
     24 // IPC connection. It owns the parent process IPDL actor, which in this case,
     25 // is a RDDChild.
     26 //
     27 // RDDProcessHosts are allocated and managed by RDDProcessManager. For all
     28 // intents and purposes it is a singleton, though more than one may be allocated
     29 // at a time due to its shutdown being asynchronous.
     30 class RDDProcessHost final : public mozilla::ipc::GeckoChildProcessHost {
     31  friend class RDDChild;
     32 
     33 public:
     34  class Listener {
     35   public:
     36    // The RDDProcessHost has unexpectedly shutdown or had its connection
     37    // severed. This is not called if an error occurs after calling
     38    // Shutdown().
     39    virtual void OnProcessUnexpectedShutdown(RDDProcessHost* aHost) {}
     40  };
     41 
     42  explicit RDDProcessHost(Listener* listener);
     43 
     44  // Launch the subprocess asynchronously. On failure, false is returned.
     45  // Otherwise, true is returned. If succeeded, a follow-up call should be made
     46  // to LaunchPromise() which will return a promise that will be resolved once
     47  // the RDD process has launched and a channel has been established.
     48  //
     49  // @param aExtraOpts (geckoargs::ChildProcessArgs)
     50  //        Extra options to pass to the subprocess.
     51  bool Launch(geckoargs::ChildProcessArgs aExtraOpts);
     52 
     53  // Return a promise that will be resolved once the process has completed its
     54  // launch. The promise will be immediately resolved if the launch has already
     55  // succeeded.
     56  RefPtr<GenericNonExclusivePromise> LaunchPromise();
     57 
     58  // Inform the process that it should clean up its resources and shut
     59  // down. This initiates an asynchronous shutdown sequence. After this
     60  // method returns, it is safe for the caller to forget its pointer to
     61  // the RDDProcessHost.
     62  //
     63  // After this returns, the attached Listener is no longer used.
     64  void Shutdown();
     65 
     66  // Return the actor for the top-level actor of the process. If the process
     67  // has not connected yet, this returns null.
     68  RDDChild* GetActor() const {
     69    MOZ_ASSERT(NS_IsMainThread());
     70    return mRDDChild.get();
     71  }
     72 
     73  // Return a unique id for this process, guaranteed not to be shared with any
     74  // past or future instance of RDDProcessHost.
     75  uint64_t GetProcessToken() const;
     76 
     77  bool IsConnected() const {
     78    MOZ_ASSERT(NS_IsMainThread());
     79    return !!mRDDChild;
     80  }
     81 
     82  // Return the time stamp for when we tried to launch the RDD process.
     83  // This is currently used for Telemetry so that we can determine how
     84  // long RDD processes take to spin up. Note this doesn't denote a
     85  // successful launch, just when we attempted launch.
     86  TimeStamp GetLaunchTime() const { return mLaunchTime; }
     87 
     88  // Called on the IO thread.
     89  void OnChannelConnected(base::ProcessId peer_pid) override;
     90 
     91  void SetListener(Listener* aListener);
     92 
     93 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
     94  // Return the sandbox type to be used with this process type.
     95  static MacSandboxType GetMacSandboxType();
     96 #endif
     97 
     98 private:
     99  ~RDDProcessHost();
    100 
    101  // Called on the main thread with true after a connection has been established
    102  // or false if it failed (including if it failed before the timeout kicked in)
    103  void InitAfterConnect(bool aSucceeded);
    104 
    105  // Called on the main thread when the mRDDChild actor is shutting down.
    106  void OnChannelClosed();
    107 
    108  // Kill the remote process, triggering IPC shutdown.
    109  void KillHard(const char* aReason);
    110 
    111  void DestroyProcess();
    112 
    113 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
    114  static bool sLaunchWithMacSandbox;
    115 
    116  // Sandbox the RDD process at launch for all instances
    117  bool IsMacSandboxLaunchEnabled() override { return sLaunchWithMacSandbox; }
    118 
    119  // Override so we can turn on RDD process-specific sandbox logging
    120  bool FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
    121 #endif
    122 
    123  DISALLOW_COPY_AND_ASSIGN(RDDProcessHost);
    124 
    125  Listener* const mListener;
    126 
    127  // All members below are only ever accessed on the main thread.
    128  enum class LaunchPhase { Unlaunched, Waiting, Complete };
    129  LaunchPhase mLaunchPhase = LaunchPhase::Unlaunched;
    130 
    131  RefPtr<RDDChild> mRDDChild;
    132  uint64_t mProcessToken = 0;
    133 
    134  UniquePtr<ipc::SharedPreferenceSerializer> mPrefSerializer;
    135 
    136  bool mShutdownRequested = false;
    137  bool mChannelClosed = false;
    138 
    139  TimeStamp mLaunchTime;
    140  void RejectPromise();
    141  void ResolvePromise();
    142 
    143  // Set to true on construction and to false just prior deletion.
    144  // The RDDProcessHost isn't refcounted; so we can capture this by value in
    145  // lambdas along with a strong reference to mLiveToken and check if that value
    146  // is true before accessing "this".
    147  // While a reference to mLiveToken can be taken on any thread; its value can
    148  // only be read on the main thread.
    149  const RefPtr<media::Refcountable<bool>> mLiveToken;
    150  RefPtr<GenericNonExclusivePromise::Private> mLaunchPromise;
    151  bool mLaunchPromiseSettled = false;
    152  // Will be set to true if we've exceeded the allowed startup time or if the
    153  // RDD process as successfully started. This is used to determine if the
    154  // timeout runnable needs to execute code or not.
    155  bool mTimerChecked = false;
    156 };
    157 
    158 }  // namespace mozilla
    159 
    160 #endif  // _include_dom_media_ipc_RDDProcessHost_h_