summaryrefslogtreecommitdiffstats
path: root/mojo/shell
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-18 00:05:15 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-18 00:05:15 +0000
commit4e5592998c1a879c85c179543180c65e9dfe4855 (patch)
tree240d0aac9601a2d281ae47422eff62658b595638 /mojo/shell
parentd33df0e0371af7afa8f4f4f0102a1a669c2e40df (diff)
downloadchromium_src-4e5592998c1a879c85c179543180c65e9dfe4855.zip
chromium_src-4e5592998c1a879c85c179543180c65e9dfe4855.tar.gz
chromium_src-4e5592998c1a879c85c179543180c65e9dfe4855.tar.bz2
Mojo: More scaffolding to run apps out of process.
(Next: mojom for communication between the parent and the child.) R=davemoore@chromium.org Review URL: https://codereview.chromium.org/197873027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@257540 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/shell')
-rw-r--r--mojo/shell/app_child_process.cc27
-rw-r--r--mojo/shell/app_child_process.h28
-rw-r--r--mojo/shell/app_child_process_host.cc29
-rw-r--r--mojo/shell/app_child_process_host.h39
-rw-r--r--mojo/shell/child_process.cc4
-rw-r--r--mojo/shell/child_process.h4
-rw-r--r--mojo/shell/child_process_host.cc20
-rw-r--r--mojo/shell/child_process_host.h40
-rw-r--r--mojo/shell/context.cc11
-rw-r--r--mojo/shell/desktop/mojo_main.cc37
-rw-r--r--mojo/shell/dynamic_service_loader.cc4
-rw-r--r--mojo/shell/dynamic_service_runner.h9
-rw-r--r--mojo/shell/in_process_dynamic_service_runner.cc3
-rw-r--r--mojo/shell/in_process_dynamic_service_runner.h2
-rw-r--r--mojo/shell/out_of_process_dynamic_service_runner.cc55
-rw-r--r--mojo/shell/out_of_process_dynamic_service_runner.h50
-rw-r--r--mojo/shell/switches.cc5
-rw-r--r--mojo/shell/switches.h1
18 files changed, 328 insertions, 40 deletions
diff --git a/mojo/shell/app_child_process.cc b/mojo/shell/app_child_process.cc
new file mode 100644
index 0000000..ea2f3f7
--- /dev/null
+++ b/mojo/shell/app_child_process.cc
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/shell/app_child_process.h"
+
+#include "base/logging.h"
+
+namespace mojo {
+namespace shell {
+
+AppChildProcess::AppChildProcess() {
+}
+
+AppChildProcess::~AppChildProcess() {
+}
+
+void AppChildProcess::Main() {
+ VLOG(2) << "AppChildProcess::Main()";
+
+ // TODO(vtl)
+
+ platform_channel()->reset();
+}
+
+} // namespace shell
+} // namespace mojo
diff --git a/mojo/shell/app_child_process.h b/mojo/shell/app_child_process.h
new file mode 100644
index 0000000..6665612
--- /dev/null
+++ b/mojo/shell/app_child_process.h
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SHELL_APP_CHILD_PROCESS_H_
+#define MOJO_SHELL_APP_CHILD_PROCESS_H_
+
+#include "base/macros.h"
+#include "mojo/shell/child_process.h"
+
+namespace mojo {
+namespace shell {
+
+class AppChildProcess : public ChildProcess {
+ public:
+ AppChildProcess();
+ virtual ~AppChildProcess();
+
+ virtual void Main() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AppChildProcess);
+};
+
+} // namespace shell
+} // namespace mojo
+
+#endif // MOJO_SHELL_APP_CHILD_PROCESS_H_
diff --git a/mojo/shell/app_child_process_host.cc b/mojo/shell/app_child_process_host.cc
new file mode 100644
index 0000000..288b1aa
--- /dev/null
+++ b/mojo/shell/app_child_process_host.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/shell/app_child_process_host.h"
+
+namespace mojo {
+namespace shell {
+
+AppChildProcessHost::AppChildProcessHost(Context* context,
+ AppDelegate* app_delegate)
+ : ChildProcessHost(context, this, ChildProcess::TYPE_APP),
+ app_delegate_(app_delegate) {
+}
+
+AppChildProcessHost::~AppChildProcessHost() {
+}
+
+void AppChildProcessHost::DidStart(bool success) {
+ if (!success) {
+ app_delegate_->DidTerminate();
+ return;
+ }
+
+ // TODO(vtl): What else?
+}
+
+} // namespace shell
+} // namespace mojo
diff --git a/mojo/shell/app_child_process_host.h b/mojo/shell/app_child_process_host.h
new file mode 100644
index 0000000..0ce5330
--- /dev/null
+++ b/mojo/shell/app_child_process_host.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SHELL_APP_CHILD_PROCESS_HOST_H_
+#define MOJO_SHELL_APP_CHILD_PROCESS_HOST_H_
+
+#include "base/macros.h"
+#include "mojo/shell/child_process_host.h"
+
+namespace mojo {
+namespace shell {
+
+// Note: After |Start()|, this object must remain alive until the delegate's
+// |DidTerminate()| is called.
+class AppChildProcessHost : public ChildProcessHost,
+ public ChildProcessHost::Delegate {
+ public:
+ class AppDelegate {
+ public:
+ virtual void DidTerminate() = 0;
+ };
+
+ AppChildProcessHost(Context* context, AppDelegate* app_delegate);
+ virtual ~AppChildProcessHost();
+
+ private:
+ // |ChildProcessHost::Delegate| method:
+ virtual void DidStart(bool success) OVERRIDE;
+
+ AppDelegate* const app_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppChildProcessHost);
+};
+
+} // namespace shell
+} // namespace mojo
+
+#endif // MOJO_SHELL_APP_CHILD_PROCESS_HOST_H_
diff --git a/mojo/shell/child_process.cc b/mojo/shell/child_process.cc
index 89a289a..90338f5 100644
--- a/mojo/shell/child_process.cc
+++ b/mojo/shell/child_process.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
+#include "mojo/shell/app_child_process.h"
#include "mojo/shell/switches.h"
#include "mojo/shell/test_child_process.h"
#include "mojo/system/embedder/platform_channel_pair.h"
@@ -31,6 +32,9 @@ scoped_ptr<ChildProcess> ChildProcess::Create(const CommandLine& command_line) {
case TYPE_TEST:
rv.reset(new TestChildProcess());
break;
+ case TYPE_APP:
+ rv.reset(new AppChildProcess());
+ break;
default:
CHECK(false) << "Invalid child process type";
break;
diff --git a/mojo/shell/child_process.h b/mojo/shell/child_process.h
index 0e5ba0b..bf7a09e 100644
--- a/mojo/shell/child_process.h
+++ b/mojo/shell/child_process.h
@@ -22,7 +22,9 @@ class ChildProcess {
public:
enum Type {
// TODO(vtl): Add real types here.
- TYPE_TEST
+ TYPE_TEST,
+ // Hosts a single app (see app_child_process(_host).*).
+ TYPE_APP
};
// Returns null if the command line doesn't indicate that this is a child
diff --git a/mojo/shell/child_process_host.cc b/mojo/shell/child_process_host.cc
index 66b7572..9d52fa2 100644
--- a/mojo/shell/child_process_host.cc
+++ b/mojo/shell/child_process_host.cc
@@ -22,10 +22,14 @@
namespace mojo {
namespace shell {
-ChildProcessHost::ChildProcessHost(Context* context, ChildProcess::Type type)
- : process_launch_task_runner_(context->task_runners()->blocking_pool()),
+ChildProcessHost::ChildProcessHost(Context* context,
+ Delegate* delegate,
+ ChildProcess::Type type)
+ : context_(context),
+ delegate_(delegate),
type_(type),
child_process_handle_(base::kNullProcessHandle) {
+ DCHECK(delegate);
}
ChildProcessHost::~ChildProcessHost() {
@@ -36,13 +40,15 @@ ChildProcessHost::~ChildProcessHost() {
}
}
-void ChildProcessHost::Start(DidStartCallback callback) {
+void ChildProcessHost::Start() {
DCHECK_EQ(child_process_handle_, base::kNullProcessHandle);
CHECK(base::PostTaskAndReplyWithResult(
- process_launch_task_runner_,
+ context_->task_runners()->blocking_pool(),
FROM_HERE,
base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)),
- callback));
+ base::Bind(&ChildProcessHost::DidLaunch, base::Unretained(this))));
+//FIXME move the platform channel pair to here, so we get the server channel
+// immediately
}
int ChildProcessHost::Join() {
@@ -91,5 +97,9 @@ bool ChildProcessHost::DoLaunch() {
return true;
}
+void ChildProcessHost::DidLaunch(bool success) {
+ delegate_->DidStart(success);
+}
+
} // namespace shell
} // namespace mojo
diff --git a/mojo/shell/child_process_host.h b/mojo/shell/child_process_host.h
index b815c3b..d289627 100644
--- a/mojo/shell/child_process_host.h
+++ b/mojo/shell/child_process_host.h
@@ -5,17 +5,11 @@
#ifndef MOJO_SHELL_CHILD_PROCESS_HOST_H_
#define MOJO_SHELL_CHILD_PROCESS_HOST_H_
-#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/process/process_handle.h"
#include "mojo/shell/child_process.h" // For |ChildProcess::Type|.
#include "mojo/system/embedder/scoped_platform_handle.h"
-namespace base {
-class TaskRunner;
-}
-
namespace mojo {
namespace shell {
@@ -32,12 +26,22 @@ class Context;
// Note: Does not currently work on Windows before Vista.
class ChildProcessHost {
public:
- ChildProcessHost(Context* context, ChildProcess::Type type);
- ~ChildProcessHost();
-
- // |Start()|s a
- typedef base::Callback<void(bool success)> DidStartCallback;
- void Start(DidStartCallback callback);
+ class Delegate {
+ public:
+ virtual void DidStart(bool success) = 0;
+ };
+
+ ChildProcessHost(Context* context,
+ Delegate* delegate,
+ ChildProcess::Type type);
+ virtual ~ChildProcessHost();
+
+ // |Start()|s the child process; calls the delegate's |DidStart()| (on the
+ // thread on which |Start()| was called) when the child has been started (or
+ // failed to start). After calling |Start()|, this object must not be
+ // destroyed until |DidStart()| has been called.
+ // TODO(vtl): Consider using weak pointers and removing this requirement.
+ void Start();
// Waits for the child process to terminate, and returns its exit code.
// Note: If |Start()| has been called, this must not be called until the
@@ -48,16 +52,22 @@ class ChildProcessHost {
return &platform_channel_;
}
+ protected:
+ Context* context() const {
+ return context_;
+ }
+
private:
bool DoLaunch();
+ void DidLaunch(bool success);
- scoped_refptr<base::TaskRunner> process_launch_task_runner_;
+ Context* const context_;
+ Delegate* const delegate_;
const ChildProcess::Type type_;
base::ProcessHandle child_process_handle_;
- // Platform-specific "pipe" to the child process.
- // Valid after the |Start()| callback has been completed (successfully).
+ // Platform-specific "pipe" to the child process. Valid after |Start()|.
embedder::ScopedPlatformHandle platform_channel_;
DISALLOW_COPY_AND_ASSIGN(ChildProcessHost);
diff --git a/mojo/shell/context.cc b/mojo/shell/context.cc
index 924c34d..1b97e5e 100644
--- a/mojo/shell/context.cc
+++ b/mojo/shell/context.cc
@@ -4,10 +4,13 @@
#include "mojo/shell/context.h"
+#include "base/command_line.h"
#include "mojo/gles2/gles2_support_impl.h"
#include "mojo/shell/dynamic_service_loader.h"
#include "mojo/shell/in_process_dynamic_service_runner.h"
#include "mojo/shell/network_delegate.h"
+#include "mojo/shell/out_of_process_dynamic_service_runner.h"
+#include "mojo/shell/switches.h"
#include "mojo/system/embedder/embedder.h"
namespace mojo {
@@ -24,8 +27,12 @@ Context::Context()
embedder::Init();
gles2::GLES2SupportImpl::Init();
- scoped_ptr<DynamicServiceRunnerFactory> runner_factory(
- new InProcessDynamicServiceRunnerFactory());
+ scoped_ptr<DynamicServiceRunnerFactory> runner_factory;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableMultiprocess))
+ runner_factory.reset(new OutOfProcessDynamicServiceRunnerFactory());
+ else
+ runner_factory.reset(new InProcessDynamicServiceRunnerFactory());
dynamic_service_loader_.reset(
new DynamicServiceLoader(this, runner_factory.Pass()));
service_manager_.set_default_loader(dynamic_service_loader_.get());
diff --git a/mojo/shell/desktop/mojo_main.cc b/mojo/shell/desktop/mojo_main.cc
index df05b6d..03a549c 100644
--- a/mojo/shell/desktop/mojo_main.cc
+++ b/mojo/shell/desktop/mojo_main.cc
@@ -3,24 +3,32 @@
// found in the LICENSE file.
#include "base/at_exit.h"
-#include "base/bind.h" // TODO(vtl): Remove.
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/macros.h" // TODO(vtl): Remove.
#include "base/message_loop/message_loop.h"
+#include "mojo/common/message_pump_mojo.h"
#include "mojo/shell/child_process.h"
#include "mojo/shell/child_process_host.h" // TODO(vtl): Remove.
#include "mojo/shell/context.h"
#include "mojo/shell/init.h"
#include "mojo/shell/run.h"
+#include "mojo/system/embedder/embedder.h"
#include "ui/gl/gl_surface.h"
namespace {
// TODO(vtl): Remove.
-void DidStartTestChild(base::MessageLoop* message_loop, bool success) {
- VLOG(2) << "DidStartTestChild: success = " << success;
- message_loop->QuitWhenIdle();
-}
+class TestChildProcessHostDelegate
+ : public mojo::shell::ChildProcessHost::Delegate {
+ public:
+ TestChildProcessHostDelegate() {}
+ virtual ~TestChildProcessHostDelegate() {}
+ virtual void DidStart(bool success) OVERRIDE {
+ VLOG(2) << "TestChildProcessHostDelegate::DidStart: success = " << success;
+ base::MessageLoop::current()->QuitWhenIdle();
+ }
+};
} // namespace
@@ -31,13 +39,18 @@ int main(int argc, char** argv) {
// TODO(vtl): Move this a proper test (and remove includes marked "remove").
if (CommandLine::ForCurrentProcess()->HasSwitch("run-test-child")) {
- base::MessageLoop message_loop;
+ base::MessageLoop message_loop(
+ scoped_ptr<base::MessagePump>(new mojo::common::MessagePumpMojo()));
+
mojo::shell::Context context;
+ TestChildProcessHostDelegate child_process_host_delegate;
mojo::shell::ChildProcessHost child_process_host(
- &context, mojo::shell::ChildProcess::TYPE_TEST);
- child_process_host.Start(base::Bind(&DidStartTestChild, &message_loop));
+ &context, &child_process_host_delegate,
+ mojo::shell::ChildProcess::TYPE_TEST);
+ child_process_host.Start();
message_loop.Run();
- VLOG(2) << "Joined child: exit_code = " << child_process_host.Join();
+ int exit_code = child_process_host.Join();
+ VLOG(2) << "Joined child: exit_code = " << exit_code;
return 0;
}
@@ -45,7 +58,11 @@ int main(int argc, char** argv) {
if (scoped_ptr<mojo::shell::ChildProcess> child_process =
mojo::shell::ChildProcess::Create(
*CommandLine::ForCurrentProcess())) {
- base::MessageLoop message_loop;
+ // TODO(vtl): Consider making a |Context| for child processes, and
+ // initializing stuff there.
+ mojo::embedder::Init();
+ base::MessageLoop message_loop(
+ scoped_ptr<base::MessagePump>(new mojo::common::MessagePumpMojo()));
message_loop.PostTask(
FROM_HERE,
base::Bind(&mojo::shell::ChildProcess::Run,
diff --git a/mojo/shell/dynamic_service_loader.cc b/mojo/shell/dynamic_service_loader.cc
index 43766b7..b5a7ac4 100644
--- a/mojo/shell/dynamic_service_loader.cc
+++ b/mojo/shell/dynamic_service_loader.cc
@@ -109,8 +109,8 @@ void DynamicServiceLoader::LoadService(ServiceManager* manager,
const GURL& url,
ScopedShellHandle service_handle) {
DCHECK(url_to_load_context_.find(url) == url_to_load_context_.end());
- url_to_load_context_[url] = new LoadContext(this, url, service_handle.Pass(),
- runner_factory_->Create());
+ url_to_load_context_[url] = new LoadContext(
+ this, url, service_handle.Pass(), runner_factory_->Create(context_));
}
void DynamicServiceLoader::AppCompleted(const GURL& url) {
diff --git a/mojo/shell/dynamic_service_runner.h b/mojo/shell/dynamic_service_runner.h
index d9742cc..bd0e74f 100644
--- a/mojo/shell/dynamic_service_runner.h
+++ b/mojo/shell/dynamic_service_runner.h
@@ -17,6 +17,8 @@ class FilePath;
namespace mojo {
namespace shell {
+class Context;
+
class DynamicServiceRunner {
public:
virtual ~DynamicServiceRunner() {}
@@ -30,7 +32,7 @@ class DynamicServiceRunner {
class DynamicServiceRunnerFactory {
public:
virtual ~DynamicServiceRunnerFactory() {}
- virtual scoped_ptr<DynamicServiceRunner> Create() = 0;
+ virtual scoped_ptr<DynamicServiceRunner> Create(Context* context) = 0;
};
// A generic factory.
@@ -39,8 +41,9 @@ class DynamicServiceRunnerFactoryImpl : public DynamicServiceRunnerFactory {
public:
DynamicServiceRunnerFactoryImpl() {}
virtual ~DynamicServiceRunnerFactoryImpl() {}
- virtual scoped_ptr<DynamicServiceRunner> Create() OVERRIDE {
- return scoped_ptr<DynamicServiceRunner>(new DynamicServiceRunnerImpl());
+ virtual scoped_ptr<DynamicServiceRunner> Create(Context* context) OVERRIDE {
+ return scoped_ptr<DynamicServiceRunner>(
+ new DynamicServiceRunnerImpl(context));
}
};
diff --git a/mojo/shell/in_process_dynamic_service_runner.cc b/mojo/shell/in_process_dynamic_service_runner.cc
index 34a1142..e366158 100644
--- a/mojo/shell/in_process_dynamic_service_runner.cc
+++ b/mojo/shell/in_process_dynamic_service_runner.cc
@@ -13,7 +13,8 @@
namespace mojo {
namespace shell {
-InProcessDynamicServiceRunner::InProcessDynamicServiceRunner()
+InProcessDynamicServiceRunner::InProcessDynamicServiceRunner(
+ Context* /*context*/)
: thread_(this, "app_thread") {
}
diff --git a/mojo/shell/in_process_dynamic_service_runner.h b/mojo/shell/in_process_dynamic_service_runner.h
index 129df46..ea674cd 100644
--- a/mojo/shell/in_process_dynamic_service_runner.h
+++ b/mojo/shell/in_process_dynamic_service_runner.h
@@ -18,7 +18,7 @@ class InProcessDynamicServiceRunner
: public DynamicServiceRunner,
public base::DelegateSimpleThread::Delegate {
public:
- InProcessDynamicServiceRunner();
+ explicit InProcessDynamicServiceRunner(Context* context);
virtual ~InProcessDynamicServiceRunner();
// |DynamicServiceRunner| method:
diff --git a/mojo/shell/out_of_process_dynamic_service_runner.cc b/mojo/shell/out_of_process_dynamic_service_runner.cc
new file mode 100644
index 0000000..9c085c1
--- /dev/null
+++ b/mojo/shell/out_of_process_dynamic_service_runner.cc
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/shell/out_of_process_dynamic_service_runner.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/scoped_native_library.h"
+
+namespace mojo {
+namespace shell {
+
+OutOfProcessDynamicServiceRunner::OutOfProcessDynamicServiceRunner(
+ Context* context)
+ : context_(context) {
+}
+
+OutOfProcessDynamicServiceRunner::~OutOfProcessDynamicServiceRunner() {
+ if (app_child_process_host_) {
+ // TODO(vtl): Race condition: If |AppChildProcessHost::DidStart()| hasn't
+ // been called yet, we shouldn't call |Join()| here. (Until |DidStart()|, we
+ // may not have a child process to wait on.) Probably we should fix
+ // |Join()|.
+ app_child_process_host_->Join();
+ }
+}
+
+void OutOfProcessDynamicServiceRunner::Start(
+ const base::FilePath& app_path,
+ ScopedShellHandle service_handle,
+ const base::Closure& app_completed_callback) {
+ app_path_ = app_path;
+
+ DCHECK(!service_handle_.is_valid());
+ service_handle_ = service_handle.Pass();
+
+ DCHECK(app_completed_callback_.is_null());
+ app_completed_callback_ = app_completed_callback;
+
+ app_child_process_host_.reset(new AppChildProcessHost(context_, this));
+ app_child_process_host_->Start();
+//FIXME app_child_process_host_->StartApp();
+}
+
+void OutOfProcessDynamicServiceRunner::DidTerminate() {
+ app_completed_callback_.Run();
+ app_completed_callback_.Reset();
+ app_child_process_host_.reset();
+}
+
+} // namespace shell
+} // namespace mojo
diff --git a/mojo/shell/out_of_process_dynamic_service_runner.h b/mojo/shell/out_of_process_dynamic_service_runner.h
new file mode 100644
index 0000000..0970acd
--- /dev/null
+++ b/mojo/shell/out_of_process_dynamic_service_runner.h
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SHELL_OUT_OF_PROCESS_DYNAMIC_SERVICE_RUNNER_H_
+#define MOJO_SHELL_OUT_OF_PROCESS_DYNAMIC_SERVICE_RUNNER_H_
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "mojo/shell/app_child_process_host.h"
+#include "mojo/shell/dynamic_service_runner.h"
+
+namespace mojo {
+namespace shell {
+
+class OutOfProcessDynamicServiceRunner
+ : public DynamicServiceRunner,
+ public AppChildProcessHost::AppDelegate {
+ public:
+ explicit OutOfProcessDynamicServiceRunner(Context* context);
+ virtual ~OutOfProcessDynamicServiceRunner();
+
+ // |DynamicServiceRunner| method:
+ virtual void Start(const base::FilePath& app_path,
+ ScopedShellHandle service_handle,
+ const base::Closure& app_completed_callback) OVERRIDE;
+
+ private:
+ // |AppChildProcessHost::AppDelegate| method:
+ virtual void DidTerminate() OVERRIDE;
+
+ Context* const context_;
+
+ base::FilePath app_path_;
+ ScopedShellHandle service_handle_;
+ base::Closure app_completed_callback_;
+
+ scoped_ptr<AppChildProcessHost> app_child_process_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(OutOfProcessDynamicServiceRunner);
+};
+
+typedef DynamicServiceRunnerFactoryImpl<OutOfProcessDynamicServiceRunner>
+ OutOfProcessDynamicServiceRunnerFactory;
+
+} // namespace shell
+} // namespace mojo
+
+#endif // MOJO_SHELL_OUT_OF_PROCESS_DYNAMIC_SERVICE_RUNNER_H_
diff --git a/mojo/shell/switches.cc b/mojo/shell/switches.cc
index a073c4a..09429e2 100644
--- a/mojo/shell/switches.cc
+++ b/mojo/shell/switches.cc
@@ -14,6 +14,11 @@ const char kChildProcessType[] = "child-process-type";
// instructions.
const char kDisableCache[] = "disable-cache";
+// Load apps in separate processes.
+// TODO(vtl): Work in progress; doesn't work. Flip this to "disable" (or maybe
+// change it to "single-process") when it works.
+const char kEnableMultiprocess[] = "enable-multiprocess";
+
const char kOrigin[] = "origin";
} // namespace switches
diff --git a/mojo/shell/switches.h b/mojo/shell/switches.h
index 066f3de..c0e78b8 100644
--- a/mojo/shell/switches.h
+++ b/mojo/shell/switches.h
@@ -11,6 +11,7 @@ namespace switches {
// alongside the definition of their values in the .cc file.
extern const char kChildProcessType[];
extern const char kDisableCache[];
+extern const char kEnableMultiprocess[];
extern const char kOrigin[];
} // namespace switches