/src/mozilla-central/ipc/glue/GeckoChildProcessHost.h
Line | Count | Source (jump to first uncovered line) |
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 __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ |
8 | | #define __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ |
9 | | |
10 | | #include "base/file_path.h" |
11 | | #include "base/process_util.h" |
12 | | #include "base/waitable_event.h" |
13 | | #include "chrome/common/child_process_host.h" |
14 | | |
15 | | #include "mozilla/DebugOnly.h" |
16 | | #include "mozilla/ipc/FileDescriptor.h" |
17 | | #include "mozilla/Monitor.h" |
18 | | #include "mozilla/StaticPtr.h" |
19 | | #include "mozilla/UniquePtr.h" |
20 | | |
21 | | #include "nsCOMPtr.h" |
22 | | #include "nsXULAppAPI.h" // for GeckoProcessType |
23 | | #include "nsString.h" |
24 | | |
25 | | #if defined(XP_WIN) && defined(MOZ_SANDBOX) |
26 | | #include "sandboxBroker.h" |
27 | | #endif |
28 | | |
29 | | namespace mozilla { |
30 | | namespace ipc { |
31 | | |
32 | | class GeckoChildProcessHost : public ChildProcessHost |
33 | | { |
34 | | protected: |
35 | | typedef mozilla::Monitor Monitor; |
36 | | typedef std::vector<std::string> StringVector; |
37 | | |
38 | | public: |
39 | | typedef base::ProcessHandle ProcessHandle; |
40 | | |
41 | | explicit GeckoChildProcessHost(GeckoProcessType aProcessType, |
42 | | bool aIsFileContent = false); |
43 | | |
44 | | ~GeckoChildProcessHost(); |
45 | | |
46 | | static uint32_t GetUniqueID(); |
47 | | |
48 | | // Does not block. The IPC channel may not be initialized yet, and |
49 | | // the child process may or may not have been created when this |
50 | | // method returns. |
51 | | bool AsyncLaunch(StringVector aExtraOpts=StringVector()); |
52 | | |
53 | | virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0); |
54 | | |
55 | | // Block until the IPC channel for our subprocess is initialized and |
56 | | // the OS process is created. The subprocess may or may not have |
57 | | // connected back to us when this method returns. |
58 | | // |
59 | | // NB: on POSIX, this method is relatively cheap, and doesn't |
60 | | // require disk IO. On win32 however, it requires at least the |
61 | | // analogue of stat(). This difference induces a semantic |
62 | | // difference in this method: on POSIX, when we return, we know the |
63 | | // subprocess has been created, but we don't know whether its |
64 | | // executable image can be loaded. On win32, we do know that when |
65 | | // we return. But we don't know if dynamic linking succeeded on |
66 | | // either platform. |
67 | | bool LaunchAndWaitForProcessHandle(StringVector aExtraOpts=StringVector()); |
68 | | |
69 | | // Block until the child process has been created and it connects to |
70 | | // the IPC channel, meaning it's fully initialized. (Or until an |
71 | | // error occurs.) |
72 | | bool SyncLaunch(StringVector aExtraOpts=StringVector(), |
73 | | int32_t timeoutMs=0); |
74 | | |
75 | | virtual void OnProcessHandleReady(ProcessHandle aProcessHandle); |
76 | | virtual void OnProcessLaunchError(); |
77 | | virtual void OnChannelConnected(int32_t peer_pid) override; |
78 | | virtual void OnMessageReceived(IPC::Message&& aMsg) override; |
79 | | virtual void OnChannelError() override; |
80 | | virtual void GetQueuedMessages(std::queue<IPC::Message>& queue) override; |
81 | | |
82 | | virtual void InitializeChannel(); |
83 | | |
84 | 0 | virtual bool CanShutdown() override { return true; } |
85 | | |
86 | 0 | IPC::Channel* GetChannel() { |
87 | 0 | return channelp(); |
88 | 0 | } |
89 | | |
90 | | // Returns a "borrowed" handle to the child process - the handle returned |
91 | | // by this function must not be closed by the caller. |
92 | | ProcessHandle GetChildProcessHandle() { |
93 | | return mChildProcessHandle; |
94 | | } |
95 | | |
96 | | GeckoProcessType GetProcessType() { |
97 | | return mProcessType; |
98 | | } |
99 | | |
100 | | #ifdef XP_MACOSX |
101 | | task_t GetChildTask() { |
102 | | return mChildTask; |
103 | | } |
104 | | #endif |
105 | | |
106 | | #ifdef XP_WIN |
107 | | void AddHandleToShare(HANDLE aHandle) { |
108 | | mLaunchOptions->handles_to_inherit.push_back(aHandle); |
109 | | } |
110 | | #else |
111 | | void AddFdToRemap(int aSrcFd, int aDstFd) { |
112 | | mLaunchOptions->fds_to_remap.push_back(std::make_pair(aSrcFd, aDstFd)); |
113 | | } |
114 | | #endif |
115 | | |
116 | | /** |
117 | | * Must run on the IO thread. Cause the OS process to exit and |
118 | | * ensure its OS resources are cleaned up. |
119 | | */ |
120 | | void Join(); |
121 | | |
122 | | // For bug 943174: Skip the EnsureProcessTerminated call in the destructor. |
123 | | void SetAlreadyDead(); |
124 | | |
125 | | static void EnableSameExecutableForContentProc() { sRunSelfAsContentProc = true; } |
126 | | |
127 | | protected: |
128 | | GeckoProcessType mProcessType; |
129 | | bool mIsFileContent; |
130 | | Monitor mMonitor; |
131 | | FilePath mProcessPath; |
132 | | // GeckoChildProcessHost holds the launch options so they can be set |
133 | | // up on the main thread using main-thread-only APIs like prefs, and |
134 | | // then used for the actual launch on another thread. This pointer |
135 | | // is set to null to free the options after the child is launched. |
136 | | UniquePtr<base::LaunchOptions> mLaunchOptions; |
137 | | |
138 | | // This value must be accessed while holding mMonitor. |
139 | | enum { |
140 | | // This object has been constructed, but the OS process has not |
141 | | // yet. |
142 | | CREATING_CHANNEL = 0, |
143 | | // The IPC channel for our subprocess has been created, but the OS |
144 | | // process has still not been created. |
145 | | CHANNEL_INITIALIZED, |
146 | | // The OS process has been created, but it hasn't yet connected to |
147 | | // our IPC channel. |
148 | | PROCESS_CREATED, |
149 | | // The process is launched and connected to our IPC channel. All |
150 | | // is well. |
151 | | PROCESS_CONNECTED, |
152 | | PROCESS_ERROR |
153 | | } mProcessState; |
154 | | |
155 | | static int32_t mChildCounter; |
156 | | |
157 | | void PrepareLaunch(); |
158 | | |
159 | | #ifdef XP_WIN |
160 | | void InitWindowsGroupID(); |
161 | | nsString mGroupId; |
162 | | |
163 | | #ifdef MOZ_SANDBOX |
164 | | SandboxBroker mSandboxBroker; |
165 | | std::vector<std::wstring> mAllowedFilesRead; |
166 | | bool mEnableSandboxLogging; |
167 | | int32_t mSandboxLevel; |
168 | | #endif |
169 | | #endif // XP_WIN |
170 | | |
171 | | ProcessHandle mChildProcessHandle; |
172 | | #if defined(OS_MACOSX) |
173 | | task_t mChildTask; |
174 | | #endif |
175 | | |
176 | | bool OpenPrivilegedHandle(base::ProcessId aPid); |
177 | | |
178 | | private: |
179 | | DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost); |
180 | | |
181 | | // Does the actual work for AsyncLaunch, on the IO thread. |
182 | | // (TODO, bug 1487287: move this to its own thread(s).) |
183 | | bool PerformAsyncLaunch(StringVector aExtraOpts); |
184 | | |
185 | | // Also called on the I/O thread; creates channel, launches, and |
186 | | // consolidates error handling. |
187 | | bool RunPerformAsyncLaunch(StringVector aExtraOpts); |
188 | | |
189 | | enum class BinaryPathType { |
190 | | Self, |
191 | | PluginContainer |
192 | | }; |
193 | | |
194 | | static BinaryPathType GetPathToBinary(FilePath& exePath, GeckoProcessType processType); |
195 | | |
196 | | // The buffer is passed to preserve its lifetime until we are done |
197 | | // with launching the sub-process. |
198 | | void GetChildLogName(const char* origLogName, nsACString &buffer); |
199 | | |
200 | | // In between launching the subprocess and handing off its IPC |
201 | | // channel, there's a small window of time in which *we* might still |
202 | | // be the channel listener, and receive messages. That's bad |
203 | | // because we have no idea what to do with those messages. So queue |
204 | | // them here until we hand off the eventual listener. |
205 | | // |
206 | | // FIXME/cjones: this strongly indicates bad design. Shame on us. |
207 | | std::queue<IPC::Message> mQueue; |
208 | | |
209 | | // Set this up before we're called from a different thread. |
210 | | #if defined(OS_LINUX) |
211 | | nsCString mTmpDirName; |
212 | | #endif |
213 | | |
214 | | static uint32_t sNextUniqueID; |
215 | | |
216 | | static bool sRunSelfAsContentProc; |
217 | | |
218 | | #if defined(MOZ_WIDGET_ANDROID) |
219 | | void LaunchAndroidService(const char* type, |
220 | | const std::vector<std::string>& argv, |
221 | | const base::file_handle_mapping_vector& fds_to_remap, |
222 | | ProcessHandle* process_handle); |
223 | | #endif // defined(MOZ_WIDGET_ANDROID) |
224 | | |
225 | | }; |
226 | | |
227 | | } /* namespace ipc */ |
228 | | } /* namespace mozilla */ |
229 | | |
230 | | #endif /* __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ */ |