1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/glue/GeckoChildProcessHost.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,235 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ 1.9 +#define __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ 1.10 + 1.11 +#include "base/file_path.h" 1.12 +#include "base/process_util.h" 1.13 +#include "base/scoped_ptr.h" 1.14 +#include "base/waitable_event.h" 1.15 +#include "chrome/common/child_process_host.h" 1.16 + 1.17 +#include "mozilla/DebugOnly.h" 1.18 +#include "mozilla/ipc/FileDescriptor.h" 1.19 +#include "mozilla/Monitor.h" 1.20 +#include "mozilla/StaticPtr.h" 1.21 + 1.22 +#include "nsCOMPtr.h" 1.23 +#include "nsXULAppAPI.h" // for GeckoProcessType 1.24 +#include "nsString.h" 1.25 + 1.26 +class nsIFile; 1.27 + 1.28 +namespace mozilla { 1.29 +namespace ipc { 1.30 + 1.31 +class GeckoChildProcessHost : public ChildProcessHost 1.32 +{ 1.33 +protected: 1.34 + typedef mozilla::Monitor Monitor; 1.35 + typedef std::vector<std::string> StringVector; 1.36 + 1.37 +public: 1.38 + typedef base::ChildPrivileges ChildPrivileges; 1.39 + typedef base::ProcessHandle ProcessHandle; 1.40 + 1.41 + static ChildPrivileges DefaultChildPrivileges(); 1.42 + 1.43 + GeckoChildProcessHost(GeckoProcessType aProcessType, 1.44 + ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT); 1.45 + 1.46 + ~GeckoChildProcessHost(); 1.47 + 1.48 + static nsresult GetArchitecturesForBinary(const char *path, uint32_t *result); 1.49 + 1.50 + static uint32_t GetSupportedArchitecturesForProcessType(GeckoProcessType type); 1.51 + 1.52 + // Block until the IPC channel for our subprocess is initialized, 1.53 + // but no longer. The child process may or may not have been 1.54 + // created when this method returns. 1.55 + bool AsyncLaunch(StringVector aExtraOpts=StringVector()); 1.56 + 1.57 + // Block until the IPC channel for our subprocess is initialized and 1.58 + // the OS process is created. The subprocess may or may not have 1.59 + // connected back to us when this method returns. 1.60 + // 1.61 + // NB: on POSIX, this method is relatively cheap, and doesn't 1.62 + // require disk IO. On win32 however, it requires at least the 1.63 + // analogue of stat(). This difference induces a semantic 1.64 + // difference in this method: on POSIX, when we return, we know the 1.65 + // subprocess has been created, but we don't know whether its 1.66 + // executable image can be loaded. On win32, we do know that when 1.67 + // we return. But we don't know if dynamic linking succeeded on 1.68 + // either platform. 1.69 + bool LaunchAndWaitForProcessHandle(StringVector aExtraOpts=StringVector()); 1.70 + 1.71 + // Block until the child process has been created and it connects to 1.72 + // the IPC channel, meaning it's fully initialized. (Or until an 1.73 + // error occurs.) 1.74 + bool SyncLaunch(StringVector aExtraOpts=StringVector(), 1.75 + int32_t timeoutMs=0, 1.76 + base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture()); 1.77 + 1.78 + virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(), 1.79 + base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()); 1.80 + 1.81 + virtual void OnChannelConnected(int32_t peer_pid); 1.82 + virtual void OnMessageReceived(const IPC::Message& aMsg); 1.83 + virtual void OnChannelError(); 1.84 + virtual void GetQueuedMessages(std::queue<IPC::Message>& queue); 1.85 + 1.86 + virtual void InitializeChannel(); 1.87 + 1.88 + virtual bool CanShutdown() { return true; } 1.89 + 1.90 + virtual void OnWaitableEventSignaled(base::WaitableEvent *event); 1.91 + 1.92 + IPC::Channel* GetChannel() { 1.93 + return channelp(); 1.94 + } 1.95 + 1.96 + base::WaitableEvent* GetShutDownEvent() { 1.97 + return GetProcessEvent(); 1.98 + } 1.99 + 1.100 + // Returns a "borrowed" handle to the child process - the handle returned 1.101 + // by this function must not be closed by the caller. 1.102 + ProcessHandle GetChildProcessHandle() { 1.103 + return mChildProcessHandle; 1.104 + } 1.105 + 1.106 + // Returns an "owned" handle to the child process - the handle returned 1.107 + // by this function must be closed by the caller. 1.108 + ProcessHandle GetOwnedChildProcessHandle() { 1.109 + ProcessHandle handle; 1.110 + // We use OpenPrivilegedProcessHandle as that is where our 1.111 + // mChildProcessHandle initially came from. 1.112 + bool ok = base::OpenPrivilegedProcessHandle(base::GetProcId(mChildProcessHandle), 1.113 + &handle); 1.114 + NS_ASSERTION(ok, "Failed to get owned process handle"); 1.115 + return ok ? handle : 0; 1.116 + } 1.117 + 1.118 + GeckoProcessType GetProcessType() { 1.119 + return mProcessType; 1.120 + } 1.121 + 1.122 +#ifdef XP_MACOSX 1.123 + task_t GetChildTask() { 1.124 + return mChildTask; 1.125 + } 1.126 +#endif 1.127 + 1.128 + /** 1.129 + * Must run on the IO thread. Cause the OS process to exit and 1.130 + * ensure its OS resources are cleaned up. 1.131 + */ 1.132 + void Join(); 1.133 + 1.134 + // For bug 943174: Skip the EnsureProcessTerminated call in the destructor. 1.135 + void SetAlreadyDead(); 1.136 + 1.137 + void SetSandboxEnabled(bool aSandboxEnabled) { 1.138 + mSandboxEnabled = aSandboxEnabled; 1.139 + } 1.140 + 1.141 +protected: 1.142 + GeckoProcessType mProcessType; 1.143 + bool mSandboxEnabled; 1.144 + ChildPrivileges mPrivileges; 1.145 + Monitor mMonitor; 1.146 + FilePath mProcessPath; 1.147 + 1.148 + // This value must be accessed while holding mMonitor. 1.149 + enum { 1.150 + // This object has been constructed, but the OS process has not 1.151 + // yet. 1.152 + CREATING_CHANNEL = 0, 1.153 + // The IPC channel for our subprocess has been created, but the OS 1.154 + // process has still not been created. 1.155 + CHANNEL_INITIALIZED, 1.156 + // The OS process has been created, but it hasn't yet connected to 1.157 + // our IPC channel. 1.158 + PROCESS_CREATED, 1.159 + // The process is launched and connected to our IPC channel. All 1.160 + // is well. 1.161 + PROCESS_CONNECTED, 1.162 + PROCESS_ERROR 1.163 + } mProcessState; 1.164 + 1.165 + static int32_t mChildCounter; 1.166 + 1.167 + void PrepareLaunch(); 1.168 + 1.169 +#ifdef XP_WIN 1.170 + void InitWindowsGroupID(); 1.171 + nsString mGroupId; 1.172 +#endif 1.173 + 1.174 +#if defined(OS_POSIX) 1.175 + base::file_handle_mapping_vector mFileMap; 1.176 +#endif 1.177 + 1.178 + base::WaitableEventWatcher::Delegate* mDelegate; 1.179 + 1.180 + ProcessHandle mChildProcessHandle; 1.181 +#if defined(OS_MACOSX) 1.182 + task_t mChildTask; 1.183 +#endif 1.184 + 1.185 + void OpenPrivilegedHandle(base::ProcessId aPid); 1.186 + 1.187 +private: 1.188 + DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost); 1.189 + 1.190 + // Does the actual work for AsyncLaunch, on the IO thread. 1.191 + bool PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts, 1.192 + base::ProcessArchitecture arch); 1.193 + 1.194 + bool RunPerformAsyncLaunch(StringVector aExtraOpts=StringVector(), 1.195 + base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()); 1.196 + 1.197 + static void GetPathToBinary(FilePath& exePath); 1.198 + static void CacheGreDir(); 1.199 + 1.200 + // In between launching the subprocess and handing off its IPC 1.201 + // channel, there's a small window of time in which *we* might still 1.202 + // be the channel listener, and receive messages. That's bad 1.203 + // because we have no idea what to do with those messages. So queue 1.204 + // them here until we hand off the eventual listener. 1.205 + // 1.206 + // FIXME/cjones: this strongly indicates bad design. Shame on us. 1.207 + std::queue<IPC::Message> mQueue; 1.208 + 1.209 + static StaticRefPtr<nsIFile> sGreDir; 1.210 + static DebugOnly<bool> sGreDirCached; 1.211 +}; 1.212 + 1.213 +#ifdef MOZ_NUWA_PROCESS 1.214 +class GeckoExistingProcessHost MOZ_FINAL : public GeckoChildProcessHost 1.215 +{ 1.216 +public: 1.217 + GeckoExistingProcessHost(GeckoProcessType aProcessType, 1.218 + base::ProcessHandle aProcess, 1.219 + const FileDescriptor& aFileDescriptor, 1.220 + ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT); 1.221 + 1.222 + ~GeckoExistingProcessHost(); 1.223 + 1.224 + virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(), 1.225 + base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()) MOZ_OVERRIDE; 1.226 + 1.227 + virtual void InitializeChannel() MOZ_OVERRIDE; 1.228 + 1.229 +private: 1.230 + base::ProcessHandle mExistingProcessHandle; 1.231 + mozilla::ipc::FileDescriptor mExistingFileDescriptor; 1.232 +}; 1.233 +#endif /* MOZ_NUWA_PROCESS */ 1.234 + 1.235 +} /* namespace ipc */ 1.236 +} /* namespace mozilla */ 1.237 + 1.238 +#endif /* __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ */