Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: mojo/runner/host/child_process.cc

Issue 1387963004: Create a broker interface for the new Mojo EDK so that the browser can create and duplicate messa... (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: presubmit whitespace error Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/runner/host/child_process.h" 5 #include "mojo/runner/host/child_process.h"
6 6
7 #include "base/base_switches.h" 7 #include "base/base_switches.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/i18n/icu_util.h" 12 #include "base/i18n/icu_util.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h" 16 #include "base/memory/ref_counted.h"
17 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h" 18 #include "base/message_loop/message_loop.h"
19 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
20 #include "base/synchronization/waitable_event.h" 20 #include "base/synchronization/waitable_event.h"
21 #include "base/thread_task_runner_handle.h" 21 #include "base/thread_task_runner_handle.h"
22 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
23 #include "base/threading/thread_checker.h" 23 #include "base/threading/thread_checker.h"
24 #include "mojo/edk/embedder/embedder.h"
25 #include "mojo/edk/embedder/platform_channel_pair.h"
24 #include "mojo/message_pump/message_pump_mojo.h" 26 #include "mojo/message_pump/message_pump_mojo.h"
25 #include "mojo/public/cpp/bindings/binding.h" 27 #include "mojo/public/cpp/bindings/binding.h"
26 #include "mojo/public/cpp/system/core.h" 28 #include "mojo/public/cpp/system/core.h"
27 #include "mojo/runner/child/child_controller.mojom.h" 29 #include "mojo/runner/child/child_controller.mojom.h"
28 #include "mojo/runner/host/native_application_support.h" 30 #include "mojo/runner/host/native_application_support.h"
29 #include "mojo/runner/host/switches.h" 31 #include "mojo/runner/host/switches.h"
30 #include "mojo/runner/init.h" 32 #include "mojo/runner/init.h"
31 #include "third_party/mojo/src/mojo/edk/embedder/embedder.h" 33 #include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
32 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" 34 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
33 #include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h" 35 #include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h"
34 #include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" 36 #include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
35 37
36 #if defined(OS_LINUX) && !defined(OS_ANDROID) 38 #if defined(OS_LINUX) && !defined(OS_ANDROID)
37 #include "base/rand_util.h" 39 #include "base/rand_util.h"
38 #include "base/sys_info.h" 40 #include "base/sys_info.h"
39 #include "mojo/runner/host/linux_sandbox.h" 41 #include "mojo/runner/host/linux_sandbox.h"
40 #endif 42 #endif
41 43
42 namespace mojo { 44 namespace mojo {
43 namespace runner { 45 namespace runner {
44 46
45 namespace { 47 namespace {
46 48
49 void DidCreateChannel(embedder::ChannelInfo* channel_info) {
50 DVLOG(2) << "ChildControllerImpl::DidCreateChannel()";
51 }
52
47 // Blocker --------------------------------------------------------------------- 53 // Blocker ---------------------------------------------------------------------
48 54
49 // Blocks a thread until another thread unblocks it, at which point it unblocks 55 // Blocks a thread until another thread unblocks it, at which point it unblocks
50 // and runs a closure provided by that thread. 56 // and runs a closure provided by that thread.
51 class Blocker { 57 class Blocker {
52 public: 58 public:
53 class Unblocker { 59 class Unblocker {
54 public: 60 public:
55 explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {} 61 explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {}
56 ~Unblocker() {} 62 ~Unblocker() {}
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 // Should be created and initialized on the main thread. 101 // Should be created and initialized on the main thread.
96 // TODO(use_chrome_edk) 102 // TODO(use_chrome_edk)
97 // class AppContext : public edk::ProcessDelegate { 103 // class AppContext : public edk::ProcessDelegate {
98 class AppContext : public embedder::ProcessDelegate { 104 class AppContext : public embedder::ProcessDelegate {
99 public: 105 public:
100 AppContext() 106 AppContext()
101 : io_thread_("io_thread"), controller_thread_("controller_thread") {} 107 : io_thread_("io_thread"), controller_thread_("controller_thread") {}
102 ~AppContext() override {} 108 ~AppContext() override {}
103 109
104 void Init() { 110 void Init() {
111 #if defined(OS_WIN)
112 embedder::PreInitializeChildProcess();
113 #endif
114
105 // Initialize Mojo before starting any threads. 115 // Initialize Mojo before starting any threads.
106 embedder::Init(); 116 embedder::Init();
107 117
108 // Create and start our I/O thread. 118 // Create and start our I/O thread.
109 base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); 119 base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0);
110 CHECK(io_thread_.StartWithOptions(io_thread_options)); 120 CHECK(io_thread_.StartWithOptions(io_thread_options));
111 io_runner_ = io_thread_.task_runner().get(); 121 io_runner_ = io_thread_.task_runner().get();
112 CHECK(io_runner_.get()); 122 CHECK(io_runner_.get());
113 123
114 // TODO(vtl): This should be SLAVE, not NONE. 124 // TODO(vtl): This should be SLAVE, not NONE.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 DCHECK(thread_checker_.CalledOnValidThread()); 196 DCHECK(thread_checker_.CalledOnValidThread());
187 197
188 // TODO(vtl): Pass in the result from |MainMain()|. 198 // TODO(vtl): Pass in the result from |MainMain()|.
189 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED); 199 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED);
190 } 200 }
191 201
192 // To be executed on the controller thread. Creates the |ChildController|, 202 // To be executed on the controller thread. Creates the |ChildController|,
193 // etc. 203 // etc.
194 static void Init(AppContext* app_context, 204 static void Init(AppContext* app_context,
195 base::NativeLibrary app_library, 205 base::NativeLibrary app_library,
196 embedder::ScopedPlatformHandle platform_channel, 206 ScopedMessagePipeHandle host_message_pipe,
197 const Blocker::Unblocker& unblocker) { 207 const Blocker::Unblocker& unblocker) {
198 DCHECK(app_context); 208 DCHECK(app_context);
199 DCHECK(platform_channel.is_valid()); 209 DCHECK(host_message_pipe.is_valid());
200 210
201 DCHECK(!app_context->controller()); 211 DCHECK(!app_context->controller());
202 212
203 scoped_ptr<ChildControllerImpl> impl( 213 scoped_ptr<ChildControllerImpl> impl(
204 new ChildControllerImpl(app_context, app_library, unblocker)); 214 new ChildControllerImpl(app_context, app_library, unblocker));
205 215
206 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
207 platform_channel.Pass(),
208 base::Bind(&ChildControllerImpl::DidCreateChannel,
209 base::Unretained(impl.get())),
210 base::ThreadTaskRunnerHandle::Get()));
211
212 impl->Bind(host_message_pipe.Pass()); 216 impl->Bind(host_message_pipe.Pass());
213 217
214 app_context->set_controller(impl.Pass()); 218 app_context->set_controller(impl.Pass());
215 } 219 }
216 220
217 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); } 221 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
218 222
219 void OnConnectionError() { 223 void OnConnectionError() {
220 // A connection error means the connection to the shell is lost. This is not 224 // A connection error means the connection to the shell is lost. This is not
221 // recoverable. 225 // recoverable.
(...skipping 22 matching lines...) Expand all
244 base::NativeLibrary app_library, 248 base::NativeLibrary app_library,
245 const Blocker::Unblocker& unblocker) 249 const Blocker::Unblocker& unblocker)
246 : app_context_(app_context), 250 : app_context_(app_context),
247 app_library_(app_library), 251 app_library_(app_library),
248 unblocker_(unblocker), 252 unblocker_(unblocker),
249 channel_info_(nullptr), 253 channel_info_(nullptr),
250 binding_(this) { 254 binding_(this) {
251 binding_.set_connection_error_handler([this]() { OnConnectionError(); }); 255 binding_.set_connection_error_handler([this]() { OnConnectionError(); });
252 } 256 }
253 257
254 // Callback for |embedder::CreateChannel()|.
255 void DidCreateChannel(embedder::ChannelInfo* channel_info) {
256 DVLOG(2) << "ChildControllerImpl::DidCreateChannel()";
257 DCHECK(thread_checker_.CalledOnValidThread());
258 channel_info_ = channel_info;
259 }
260
261 static void StartAppOnMainThread( 258 static void StartAppOnMainThread(
262 base::NativeLibrary app_library, 259 base::NativeLibrary app_library,
263 InterfaceRequest<Application> application_request) { 260 InterfaceRequest<Application> application_request) {
264 if (!RunNativeApplication(app_library, application_request.Pass())) { 261 if (!RunNativeApplication(app_library, application_request.Pass())) {
265 LOG(ERROR) << "Failure to RunNativeApplication()"; 262 LOG(ERROR) << "Failure to RunNativeApplication()";
266 } 263 }
267 } 264 }
268 265
269 base::ThreadChecker thread_checker_; 266 base::ThreadChecker thread_checker_;
270 AppContext* const app_context_; 267 AppContext* const app_context_;
271 base::NativeLibrary app_library_; 268 base::NativeLibrary app_library_;
272 Blocker::Unblocker unblocker_; 269 Blocker::Unblocker unblocker_;
273 StartAppCallback on_app_complete_; 270 StartAppCallback on_app_complete_;
274 271
275 embedder::ChannelInfo* channel_info_; 272 embedder::ChannelInfo* channel_info_;
276 Binding<ChildController> binding_; 273 Binding<ChildController> binding_;
277 274
278 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); 275 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl);
279 }; 276 };
280 277
278 #if defined(OS_LINUX) && !defined(OS_ANDROID)
279 scoped_ptr<mojo::runner::LinuxSandbox> InitializeSandbox() {
280 using sandbox::syscall_broker::BrokerFilePermission;
281 // Warm parts of base in the copy of base in the mojo runner.
282 base::RandUint64();
283 base::SysInfo::AmountOfPhysicalMemory();
284 base::SysInfo::MaxSharedMemorySize();
285 base::SysInfo::NumberOfProcessors();
286
287 // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to
288 // spy on other shared memory using processes. This is a temporary hack
289 // so that we have some sandbox until we have proper shared memory
290 // support integrated into mojo.
291 std::vector<BrokerFilePermission> permissions;
292 permissions.push_back(
293 BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/"));
294 scoped_ptr<mojo::runner::LinuxSandbox> sandbox(
295 new mojo::runner::LinuxSandbox(permissions));
296 sandbox->Warmup();
297 sandbox->EngageNamespaceSandbox();
298 sandbox->EngageSeccompSandbox();
299 sandbox->Seal();
300 return sandbox.Pass();
301 }
302 #endif
303
304 ScopedMessagePipeHandle InitializeHostMessagePipe(
305 embedder::ScopedPlatformHandle platform_channel,
306 scoped_refptr<base::TaskRunner> io_task_runner) {
307 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
308 platform_channel.Pass(), base::Bind(&DidCreateChannel), io_task_runner));
309
310 #if defined(OS_WIN)
311 if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) {
312 // When using the new Mojo EDK, each message pipe is backed by a platform
313 // handle. The one platform handle that comes on the command line is used
314 // to bind to the ChildController interface. However we also want a
315 // platform handle to setup the communication channel by which we exchange
316 // handles to/from tokens, which is needed for sandboxed Windows
317 // processes.
318 char token_serializer_handle[10];
319 MojoHandleSignalsState state;
320 MojoResult rv =
321 MojoWait(host_message_pipe.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
322 MOJO_DEADLINE_INDEFINITE, &state);
323 CHECK_EQ(MOJO_RESULT_OK, rv);
324 uint32_t num_bytes = arraysize(token_serializer_handle);
325 rv = MojoReadMessage(host_message_pipe.get().value(),
326 token_serializer_handle, &num_bytes, nullptr, 0,
327 MOJO_READ_MESSAGE_FLAG_NONE);
328 CHECK_EQ(MOJO_RESULT_OK, rv);
329
330 edk::ScopedPlatformHandle token_serializer_channel =
331 edk::PlatformChannelPair::PassClientHandleFromParentProcessFromString(
332 std::string(token_serializer_handle, num_bytes));
333 CHECK(token_serializer_channel.is_valid());
334 embedder::SetParentPipeHandle(token_serializer_channel.release().handle);
335 }
336 #endif
337
338 return host_message_pipe.Pass();
339 }
340
281 } // namespace 341 } // namespace
282 342
283 int ChildProcessMain() { 343 int ChildProcessMain() {
284 DVLOG(2) << "ChildProcessMain()"; 344 DVLOG(2) << "ChildProcessMain()";
285 const base::CommandLine& command_line = 345 const base::CommandLine& command_line =
286 *base::CommandLine::ForCurrentProcess(); 346 *base::CommandLine::ForCurrentProcess();
287 347
288 #if defined(OS_LINUX) && !defined(OS_ANDROID) 348 #if defined(OS_LINUX) && !defined(OS_ANDROID)
289 using sandbox::syscall_broker::BrokerFilePermission;
290 scoped_ptr<mojo::runner::LinuxSandbox> sandbox; 349 scoped_ptr<mojo::runner::LinuxSandbox> sandbox;
291 #endif 350 #endif
292 base::NativeLibrary app_library = 0; 351 base::NativeLibrary app_library = 0;
293 if (command_line.HasSwitch(switches::kChildProcess)) { 352 // Load the application library before we engage the sandbox.
294 // Load the application library before we engage the sandbox. 353 app_library = mojo::runner::LoadNativeApplication(
295 app_library = mojo::runner::LoadNativeApplication( 354 command_line.GetSwitchValuePath(switches::kChildProcess));
296 command_line.GetSwitchValuePath(switches::kChildProcess));
297 355
298 base::i18n::InitializeICU(); 356 base::i18n::InitializeICU();
299 CallLibraryEarlyInitialization(app_library); 357 CallLibraryEarlyInitialization(app_library);
300
301 #if defined(OS_LINUX) && !defined(OS_ANDROID) 358 #if defined(OS_LINUX) && !defined(OS_ANDROID)
302 if (command_line.HasSwitch(switches::kEnableSandbox)) { 359 if (command_line.HasSwitch(switches::kEnableSandbox))
303 // Warm parts of base in the copy of base in the mojo runner. 360 sandbox = InitializeSandbox();
304 base::RandUint64();
305 base::SysInfo::AmountOfPhysicalMemory();
306 base::SysInfo::MaxSharedMemorySize();
307 base::SysInfo::NumberOfProcessors();
308
309 // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to
310 // spy on other shared memory using processes. This is a temporary hack
311 // so that we have some sandbox until we have proper shared memory
312 // support integrated into mojo.
313 std::vector<BrokerFilePermission> permissions;
314 permissions.push_back(
315 BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/"));
316 sandbox.reset(new mojo::runner::LinuxSandbox(permissions));
317 sandbox->Warmup();
318 sandbox->EngageNamespaceSandbox();
319 sandbox->EngageSeccompSandbox();
320 sandbox->Seal();
321 }
322 #endif 361 #endif
323 }
324 362
325 embedder::ScopedPlatformHandle platform_channel = 363 embedder::ScopedPlatformHandle platform_channel =
326 embedder::PlatformChannelPair::PassClientHandleFromParentProcess( 364 embedder::PlatformChannelPair::PassClientHandleFromParentProcess(
327 command_line); 365 command_line);
328 CHECK(platform_channel.is_valid()); 366 CHECK(platform_channel.is_valid());
329 367
330 DCHECK(!base::MessageLoop::current()); 368 DCHECK(!base::MessageLoop::current());
331 369
332 AppContext app_context; 370 AppContext app_context;
333 app_context.Init(); 371 app_context.Init();
372 ScopedMessagePipeHandle host_message_pipe = InitializeHostMessagePipe(
373 platform_channel.Pass(), app_context.io_runner());
334 Blocker blocker; 374 Blocker blocker;
335 app_context.controller_runner()->PostTask( 375 app_context.controller_runner()->PostTask(
336 FROM_HERE, 376 FROM_HERE,
337 base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context), 377 base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context),
338 base::Unretained(app_library), base::Passed(&platform_channel), 378 base::Unretained(app_library),
339 blocker.GetUnblocker())); 379 base::Passed(&host_message_pipe), blocker.GetUnblocker()));
340 // This will block, then run whatever the controller wants. 380 // This will block, then run whatever the controller wants.
341 blocker.Block(); 381 blocker.Block();
342 382
343 app_context.Shutdown(); 383 app_context.Shutdown();
344 384
345 return 0; 385 return 0;
346 } 386 }
347 387
348 } // namespace runner 388 } // namespace runner
349 } // namespace mojo 389 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698