Line data Source code
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 :
20 : #include "nsCOMPtr.h"
21 : #include "nsXULAppAPI.h" // for GeckoProcessType
22 : #include "nsString.h"
23 :
24 : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
25 : #include "sandboxBroker.h"
26 : #endif
27 :
28 : namespace mozilla {
29 : namespace ipc {
30 :
31 : class GeckoChildProcessHost : public ChildProcessHost
32 : {
33 : protected:
34 : typedef mozilla::Monitor Monitor;
35 : typedef std::vector<std::string> StringVector;
36 :
37 : public:
38 : typedef base::ChildPrivileges ChildPrivileges;
39 : typedef base::ProcessHandle ProcessHandle;
40 :
41 : static ChildPrivileges DefaultChildPrivileges();
42 :
43 : explicit GeckoChildProcessHost(GeckoProcessType aProcessType,
44 : ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT);
45 :
46 : ~GeckoChildProcessHost();
47 :
48 : static nsresult GetArchitecturesForBinary(const char *path, uint32_t *result);
49 :
50 : static uint32_t GetSupportedArchitecturesForProcessType(GeckoProcessType type);
51 :
52 : static uint32_t GetUniqueID();
53 :
54 : // Block until the IPC channel for our subprocess is initialized,
55 : // but no longer. The child process may or may not have been
56 : // created when this method returns.
57 : bool AsyncLaunch(StringVector aExtraOpts=StringVector(),
58 : base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture());
59 :
60 : virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0);
61 :
62 : // Block until the IPC channel for our subprocess is initialized and
63 : // the OS process is created. The subprocess may or may not have
64 : // connected back to us when this method returns.
65 : //
66 : // NB: on POSIX, this method is relatively cheap, and doesn't
67 : // require disk IO. On win32 however, it requires at least the
68 : // analogue of stat(). This difference induces a semantic
69 : // difference in this method: on POSIX, when we return, we know the
70 : // subprocess has been created, but we don't know whether its
71 : // executable image can be loaded. On win32, we do know that when
72 : // we return. But we don't know if dynamic linking succeeded on
73 : // either platform.
74 : bool LaunchAndWaitForProcessHandle(StringVector aExtraOpts=StringVector());
75 :
76 : // Block until the child process has been created and it connects to
77 : // the IPC channel, meaning it's fully initialized. (Or until an
78 : // error occurs.)
79 : bool SyncLaunch(StringVector aExtraOpts=StringVector(),
80 : int32_t timeoutMs=0,
81 : base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture());
82 :
83 : virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
84 : base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture());
85 :
86 : virtual void OnChannelConnected(int32_t peer_pid);
87 : virtual void OnMessageReceived(IPC::Message&& aMsg);
88 : virtual void OnChannelError();
89 : virtual void GetQueuedMessages(std::queue<IPC::Message>& queue);
90 :
91 : virtual void InitializeChannel();
92 :
93 0 : virtual bool CanShutdown() { return true; }
94 :
95 6 : IPC::Channel* GetChannel() {
96 6 : return channelp();
97 : }
98 :
99 : // Returns a "borrowed" handle to the child process - the handle returned
100 : // by this function must not be closed by the caller.
101 2 : ProcessHandle GetChildProcessHandle() {
102 2 : return mChildProcessHandle;
103 : }
104 :
105 : GeckoProcessType GetProcessType() {
106 : return mProcessType;
107 : }
108 :
109 : #ifdef XP_MACOSX
110 : task_t GetChildTask() {
111 : return mChildTask;
112 : }
113 : #endif
114 :
115 : /**
116 : * Must run on the IO thread. Cause the OS process to exit and
117 : * ensure its OS resources are cleaned up.
118 : */
119 : void Join();
120 :
121 : // For bug 943174: Skip the EnsureProcessTerminated call in the destructor.
122 : void SetAlreadyDead();
123 :
124 1 : static void EnableSameExecutableForContentProc() { sRunSelfAsContentProc = true; }
125 :
126 : protected:
127 : GeckoProcessType mProcessType;
128 : ChildPrivileges mPrivileges;
129 : Monitor mMonitor;
130 : FilePath mProcessPath;
131 :
132 : // This value must be accessed while holding mMonitor.
133 : enum {
134 : // This object has been constructed, but the OS process has not
135 : // yet.
136 : CREATING_CHANNEL = 0,
137 : // The IPC channel for our subprocess has been created, but the OS
138 : // process has still not been created.
139 : CHANNEL_INITIALIZED,
140 : // The OS process has been created, but it hasn't yet connected to
141 : // our IPC channel.
142 : PROCESS_CREATED,
143 : // The process is launched and connected to our IPC channel. All
144 : // is well.
145 : PROCESS_CONNECTED,
146 : PROCESS_ERROR
147 : } mProcessState;
148 :
149 : static int32_t mChildCounter;
150 :
151 : void PrepareLaunch();
152 :
153 : #ifdef XP_WIN
154 : void InitWindowsGroupID();
155 : nsString mGroupId;
156 :
157 : #ifdef MOZ_SANDBOX
158 : SandboxBroker mSandboxBroker;
159 : std::vector<std::wstring> mAllowedFilesRead;
160 : bool mEnableSandboxLogging;
161 : int32_t mSandboxLevel;
162 : #endif
163 : #endif // XP_WIN
164 :
165 : #if defined(OS_POSIX)
166 : base::file_handle_mapping_vector mFileMap;
167 : #endif
168 :
169 : ProcessHandle mChildProcessHandle;
170 : #if defined(OS_MACOSX)
171 : task_t mChildTask;
172 : #endif
173 :
174 : bool OpenPrivilegedHandle(base::ProcessId aPid);
175 :
176 : private:
177 : DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost);
178 :
179 : // Does the actual work for AsyncLaunch, on the IO thread.
180 : bool PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts,
181 : base::ProcessArchitecture arch);
182 :
183 : bool RunPerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
184 : base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture());
185 :
186 : enum class BinaryPathType {
187 : Self,
188 : PluginContainer
189 : };
190 :
191 : static BinaryPathType GetPathToBinary(FilePath& exePath, GeckoProcessType processType);
192 :
193 : // The buffer is passed to preserve its lifetime until we are done
194 : // with launching the sub-process.
195 : void SetChildLogName(const char* varName, const char* origLogName,
196 : nsACString &buffer);
197 :
198 : // In between launching the subprocess and handing off its IPC
199 : // channel, there's a small window of time in which *we* might still
200 : // be the channel listener, and receive messages. That's bad
201 : // because we have no idea what to do with those messages. So queue
202 : // them here until we hand off the eventual listener.
203 : //
204 : // FIXME/cjones: this strongly indicates bad design. Shame on us.
205 : std::queue<IPC::Message> mQueue;
206 :
207 : // Remember original env values so we can restore it (there is no other
208 : // simple way how to change environment of a child process than to modify
209 : // the current environment).
210 : nsCString mRestoreOrigNSPRLogName;
211 : nsCString mRestoreOrigMozLogName;
212 :
213 : static uint32_t sNextUniqueID;
214 :
215 : static bool sRunSelfAsContentProc;
216 :
217 : #if defined(MOZ_WIDGET_ANDROID)
218 : void LaunchAndroidService(const char* type,
219 : const std::vector<std::string>& argv,
220 : const base::file_handle_mapping_vector& fds_to_remap,
221 : ProcessHandle* process_handle);
222 : #endif // defined(MOZ_WIDGET_ANDROID)
223 :
224 : };
225 :
226 : } /* namespace ipc */
227 : } /* namespace mozilla */
228 :
229 : #endif /* __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ */
|