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_