1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/shell/app_child_process.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/bind.h"
8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/callback_helpers.h"
9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/files/file_path.h"
1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/location.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h"
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/macros.h"
1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/memory/ref_counted.h"
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/message_loop/message_loop.h"
16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/scoped_native_library.h"
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/single_thread_task_runner.h"
18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/synchronization/waitable_event.h"
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/threading/thread.h"
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/threading/thread_checker.h"
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "mojo/common/message_pump_mojo.h"
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "mojo/embedder/embedder.h"
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "mojo/embedder/simple_platform_support.h"
24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "mojo/public/cpp/system/core.h"
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "mojo/shell/app_child_process.mojom.h"
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace mojo {
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace shell {
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace {
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Blocker ---------------------------------------------------------------------
33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Blocks a thread until another thread unblocks it, at which point it unblocks
35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// and runs a closure provided by that thread.
36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass Blocker {
37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public:
38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  class Unblocker {
39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   public:
40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ~Unblocker() {}
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    void Unblock(base::Closure run_after) {
43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      DCHECK(blocker_);
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      DCHECK(blocker_->run_after_.is_null());
45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      blocker_->run_after_ = run_after;
46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      blocker_->event_.Signal();
47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      blocker_ = NULL;
48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch   private:
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    friend class Blocker;
52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    Unblocker(Blocker* blocker) : blocker_(blocker) {
53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      DCHECK(blocker_);
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    Blocker* blocker_;
57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Copy and assign allowed.
59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  };
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Blocker() : event_(true, false) {}
62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ~Blocker() {}
63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void Block() {
65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DCHECK(run_after_.is_null());
66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    event_.Wait();
67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    run_after_.Run();
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Unblocker GetUnblocker() {
71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return Unblocker(this);
72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private:
75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::WaitableEvent event_;
76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::Closure run_after_;
77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DISALLOW_COPY_AND_ASSIGN(Blocker);
79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch};
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// AppContext ------------------------------------------------------------------
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass AppChildControllerImpl;
84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)static void DestroyController(scoped_ptr<AppChildControllerImpl> controller) {
860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
870de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Should be created and initialized on the main thread.
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)class AppContext {
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public:
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  AppContext()
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      : io_thread_("io_thread"),
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        controller_thread_("controller_thread") {}
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ~AppContext() {}
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void Init() {
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Initialize Mojo before starting any threads.
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>(
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        new mojo::embedder::SimplePlatformSupport()));
10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Create and start our I/O thread.
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0);
10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    CHECK(io_thread_.StartWithOptions(io_thread_options));
10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    io_runner_ = io_thread_.message_loop_proxy().get();
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(io_runner_.get());
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Create and start our controller thread.
10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    base::Thread::Options controller_thread_options;
10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    controller_thread_options.message_loop_type =
11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        base::MessageLoop::TYPE_CUSTOM;
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    controller_thread_options.message_pump_factory =
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        base::Bind(&common::MessagePumpMojo::Create);
11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    CHECK(controller_thread_.StartWithOptions(controller_thread_options));
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    controller_runner_ = controller_thread_.message_loop_proxy().get();
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(controller_runner_.get());
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  void Shutdown() {
1190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    controller_runner_->PostTask(
1200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        FROM_HERE,
1210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        base::Bind(&DestroyController, base::Passed(&controller_)));
1220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
1230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::SingleThreadTaskRunner* io_runner() const {
12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return io_runner_.get();
12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::SingleThreadTaskRunner* controller_runner() const {
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return controller_runner_.get();
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  AppChildControllerImpl* controller() const {
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return controller_.get();
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void set_controller(scoped_ptr<AppChildControllerImpl> controller) {
13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    controller_ = controller.Pass();
13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private:
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Accessed only on the controller thread.
142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // IMPORTANT: This must be BEFORE |controller_thread_|, so that the controller
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // thread gets joined (and thus |controller_| reset) before |controller_| is
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // destroyed.
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_ptr<AppChildControllerImpl> controller_;
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
14723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::Thread io_thread_;
14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
14923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::Thread controller_thread_;
15123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
15223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
15323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AppContext);
15423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)};
15523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
15623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// AppChildControllerImpl ------------------------------------------------------
15723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)class AppChildControllerImpl : public InterfaceImpl<AppChildController> {
15923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public:
16023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual ~AppChildControllerImpl() {
16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(thread_checker_.CalledOnValidThread());
1620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    // TODO(vtl): Pass in the result from |MainMain()|.
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    client()->AppCompleted(MOJO_RESULT_UNIMPLEMENTED);
16523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
16623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
16723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // To be executed on the controller thread. Creates the |AppChildController|,
16823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // etc.
16923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  static void Init(
17023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      AppContext* app_context,
17123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      embedder::ScopedPlatformHandle platform_channel,
172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const Blocker::Unblocker& unblocker) {
17323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(app_context);
17423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(platform_channel.is_valid());
17523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
17623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(!app_context->controller());
177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    scoped_ptr<AppChildControllerImpl> impl(
1790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        new AppChildControllerImpl(app_context, unblocker));
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
1820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        platform_channel.Pass(),
1830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        app_context->io_runner(),
1840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        base::Bind(&AppChildControllerImpl::DidCreateChannel,
1850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                   base::Unretained(impl.get())),
1860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)        base::MessageLoopProxy::current()));
187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    BindToPipe(impl.get(), host_message_pipe.Pass());
18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    app_context->set_controller(impl.Pass());
1910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
1920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  virtual void OnConnectionError() OVERRIDE {
1940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    // TODO(darin): How should we handle a connection error here?
1950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
1960de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1970de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // |AppChildController| methods:
19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void StartApp(const String& app_path,
19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                        ScopedMessagePipeHandle service) OVERRIDE {
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(2) << "AppChildControllerImpl::StartApp(" << app_path << ", ...)";
201effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
203effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    unblocker_.Unblock(base::Bind(&AppChildControllerImpl::StartAppOnMainThread,
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  base::FilePath::FromUTF8Unsafe(app_path),
205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                  base::Passed(&service)));
20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private:
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  AppChildControllerImpl(AppContext* app_context,
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         const Blocker::Unblocker& unblocker)
21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      : app_context_(app_context),
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        unblocker_(unblocker),
21323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        channel_info_(NULL) {
21423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
21623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Callback for |embedder::CreateChannel()|.
217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void DidCreateChannel(embedder::ChannelInfo* channel_info) {
21823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DVLOG(2) << "AppChildControllerImpl::DidCreateChannel()";
21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(thread_checker_.CalledOnValidThread());
22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    channel_info_ = channel_info;
22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  static void StartAppOnMainThread(const base::FilePath& app_path,
224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                   ScopedMessagePipeHandle service) {
225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // TODO(vtl): This is copied from in_process_dynamic_service_runner.cc.
226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DVLOG(2) << "Loading/running Mojo app from " << app_path.value()
227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch             << " out of process";
228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    do {
230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::NativeLibraryLoadError load_error;
231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::ScopedNativeLibrary app_library(
232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          base::LoadNativeLibrary(app_path, &load_error));
233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (!app_library.is_valid()) {
234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        LOG(ERROR) << "Failed to load library (error: " << load_error.ToString()
235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   << ")";
236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        break;
237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      typedef MojoResult (*MojoMainFunction)(MojoHandle);
240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>(
241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          app_library.GetFunctionPointer("MojoMain"));
242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (!main_function) {
243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        LOG(ERROR) << "Entrypoint MojoMain not found";
244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        break;
245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // TODO(vtl): Report the result back to our parent process.
248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // |MojoMain()| takes ownership of the service handle.
249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      MojoResult result = main_function(service.release().value());
250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (result < MOJO_RESULT_OK)
251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        LOG(ERROR) << "MojoMain returned an error: " << result;
252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    } while (false);
253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::ThreadChecker thread_checker_;
25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  AppContext* const app_context_;
257effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Blocker::Unblocker unblocker_;
25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  embedder::ChannelInfo* channel_info_;
26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AppChildControllerImpl);
26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)};
26323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
26423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace
26523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// AppChildProcess -------------------------------------------------------------
26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppChildProcess::AppChildProcess() {
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppChildProcess::~AppChildProcess() {
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppChildProcess::Main() {
27523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DVLOG(2) << "AppChildProcess::Main()";
27623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
27723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  AppContext app_context;
27823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  app_context.Init();
27923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  Blocker blocker;
281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  app_context.controller_runner()->PostTask(
282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      FROM_HERE,
283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context),
284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 base::Passed(platform_channel()), blocker.GetUnblocker()));
285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // This will block, then run whatever the controller wants.
286effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  blocker.Block();
287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  app_context.Shutdown();
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace shell
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace mojo
293