summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorjam <jam@chromium.org>2015-04-06 15:30:00 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-06 22:31:05 +0000
commitedc54e0f7f19fbd76a84d470fec909631740c560 (patch)
tree8eea48b9bf96670b5d9f945b01d37e502e035dad /mojo
parent7f9a9aac8a45e36e4b8d1621b9b50ffca91cf38b (diff)
downloadchromium_src-edc54e0f7f19fbd76a84d470fec909631740c560.zip
chromium_src-edc54e0f7f19fbd76a84d470fec909631740c560.tar.gz
chromium_src-edc54e0f7f19fbd76a84d470fec909631740c560.tar.bz2
Simplify some mojo_shell code.
-make desktop/main.cc be a near empty file that calls out to separate files for main ("launcher" per naming discussions) or child process -remove ChildProcess and derived classs; one method is enough -remove unused mojo/shell/launcher_main.cc -use a more reasonable size window on desktop Review URL: https://codereview.chromium.org/1065433002 Cr-Commit-Position: refs/heads/master@{#323964}
Diffstat (limited to 'mojo')
-rw-r--r--mojo/services/kiosk_wm/kiosk_wm.cc3
-rw-r--r--mojo/shell/BUILD.gn34
-rw-r--r--mojo/shell/app_child_process.cc302
-rw-r--r--mojo/shell/app_child_process.h30
-rw-r--r--mojo/shell/child_process.cc298
-rw-r--r--mojo/shell/child_process.h44
-rw-r--r--mojo/shell/desktop/launcher_process.cc170
-rw-r--r--mojo/shell/desktop/launcher_process.h17
-rw-r--r--mojo/shell/desktop/main.cc173
-rw-r--r--mojo/shell/launcher_main.cc116
-rw-r--r--mojo/shell/shell_test_main.cc7
-rw-r--r--mojo/shell/switches.cc6
-rw-r--r--mojo/shell/switches.h1
13 files changed, 491 insertions, 710 deletions
diff --git a/mojo/services/kiosk_wm/kiosk_wm.cc b/mojo/services/kiosk_wm/kiosk_wm.cc
index 9aa2aab..28b5b5e 100644
--- a/mojo/services/kiosk_wm/kiosk_wm.cc
+++ b/mojo/services/kiosk_wm/kiosk_wm.cc
@@ -55,8 +55,7 @@ void KioskWM::OnEmbed(
root_ = root;
root_->AddObserver(this);
- // Resize to match the Nexus 5 aspect ratio:
- window_manager_app_->SetViewportSize(gfx::Size(320, 640));
+ window_manager_app_->SetViewportSize(gfx::Size(1280, 800));
content_ = root->view_manager()->CreateView();
content_->SetBounds(root_->bounds());
diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn
index c121d57..1dbe6ad 100644
--- a/mojo/shell/BUILD.gn
+++ b/mojo/shell/BUILD.gn
@@ -20,10 +20,6 @@ group("shell") {
":tests",
]
- if (!is_win) {
- deps += [ ":mojo_launcher" ]
- }
-
if (is_android) {
deps += [
":mojo_shell_apk",
@@ -58,7 +54,11 @@ executable("mojo_shell") {
]
if (!is_android) {
- sources += [ "desktop/main.cc" ]
+ sources += [
+ "desktop/launcher_process.cc",
+ "desktop/launcher_process.h",
+ "desktop/main.cc",
+ ]
} else {
sources += [
"android/library_loader.cc",
@@ -79,23 +79,6 @@ executable("mojo_shell") {
}
}
-executable("mojo_launcher") {
- sources = [
- "launcher_main.cc",
- ]
-
- deps = [
- ":init",
- ":in_process_native_runner",
- "//base",
- "//build/config/sanitizers:deps",
- "//mojo/common",
- "//third_party/mojo/src/mojo/edk/system",
- "//mojo/environment:chromium",
- "//url",
- ]
-}
-
source_set("init") {
sources = [
"init.cc",
@@ -125,8 +108,6 @@ source_set("in_process_native_runner") {
source_set("lib") {
sources = [
- "app_child_process.cc",
- "app_child_process.h",
"app_child_process_host.cc",
"app_child_process_host.h",
"child_process.cc",
@@ -463,8 +444,9 @@ mojo_native_application("apptests") {
"//third_party/mojo/src/mojo/public/cpp/bindings:callback",
"//third_party/mojo/src/mojo/public/cpp/environment",
"//third_party/mojo/src/mojo/public/cpp/system:system",
- # "//mojo/services/http_server/public/cpp",
- # "//mojo/services/http_server/public/interfaces",
+
+ #"//mojo/services/http_server/public/cpp",
+ #"//mojo/services/http_server/public/interfaces",
"//mojo/services/network/public/interfaces",
"//mojo/shell/test:bindings",
]
diff --git a/mojo/shell/app_child_process.cc b/mojo/shell/app_child_process.cc
deleted file mode 100644
index 546c28c..0000000
--- a/mojo/shell/app_child_process.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-// 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/bind.h"
-#include "base/callback_helpers.h"
-#include "base/files/file_path.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker.h"
-#include "mojo/common/message_pump_mojo.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/process_delegate.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/public/cpp/system/core.h"
-#include "mojo/shell/app_child_process.mojom.h"
-#include "mojo/shell/native_application_support.h"
-
-namespace mojo {
-namespace shell {
-
-namespace {
-
-// Blocker ---------------------------------------------------------------------
-
-// Blocks a thread until another thread unblocks it, at which point it unblocks
-// and runs a closure provided by that thread.
-class Blocker {
- public:
- class Unblocker {
- public:
- explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {}
- ~Unblocker() {}
-
- void Unblock(base::Closure run_after) {
- DCHECK(blocker_);
- DCHECK(blocker_->run_after_.is_null());
- blocker_->run_after_ = run_after;
- blocker_->event_.Signal();
- blocker_ = nullptr;
- }
-
- private:
- Blocker* blocker_;
-
- // Copy and assign allowed.
- };
-
- Blocker() : event_(true, false) {}
- ~Blocker() {}
-
- void Block() {
- DCHECK(run_after_.is_null());
- event_.Wait();
- run_after_.Run();
- }
-
- Unblocker GetUnblocker() { return Unblocker(this); }
-
- private:
- base::WaitableEvent event_;
- base::Closure run_after_;
-
- DISALLOW_COPY_AND_ASSIGN(Blocker);
-};
-
-// AppContext ------------------------------------------------------------------
-
-class AppChildControllerImpl;
-
-// Should be created and initialized on the main thread.
-class AppContext : public embedder::ProcessDelegate {
- public:
- AppContext()
- : io_thread_("io_thread"), controller_thread_("controller_thread") {}
- ~AppContext() override {}
-
- void Init() {
- // Initialize Mojo before starting any threads.
- embedder::Init(make_scoped_ptr(new embedder::SimplePlatformSupport()));
-
- // Create and start our I/O thread.
- base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0);
- CHECK(io_thread_.StartWithOptions(io_thread_options));
- io_runner_ = io_thread_.message_loop_proxy().get();
- CHECK(io_runner_.get());
-
- // Create and start our controller thread.
- base::Thread::Options controller_thread_options;
- controller_thread_options.message_loop_type =
- base::MessageLoop::TYPE_CUSTOM;
- controller_thread_options.message_pump_factory =
- base::Bind(&common::MessagePumpMojo::Create);
- CHECK(controller_thread_.StartWithOptions(controller_thread_options));
- controller_runner_ = controller_thread_.message_loop_proxy().get();
- CHECK(controller_runner_.get());
-
- // TODO(vtl): This should be SLAVE, not NONE.
- embedder::InitIPCSupport(embedder::ProcessType::NONE, controller_runner_,
- this, io_runner_,
- embedder::ScopedPlatformHandle());
- }
-
- void Shutdown() {
- Blocker blocker;
- shutdown_unblocker_ = blocker.GetUnblocker();
- controller_runner_->PostTask(
- FROM_HERE, base::Bind(&AppContext::ShutdownOnControllerThread,
- base::Unretained(this)));
- blocker.Block();
- }
-
- base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); }
-
- base::SingleThreadTaskRunner* controller_runner() const {
- return controller_runner_.get();
- }
-
- AppChildControllerImpl* controller() const { return controller_.get(); }
-
- void set_controller(scoped_ptr<AppChildControllerImpl> controller) {
- controller_ = controller.Pass();
- }
-
- private:
- void ShutdownOnControllerThread() {
- // First, destroy the controller.
- controller_.reset();
-
- // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete().
- embedder::ShutdownIPCSupport();
- }
-
- // ProcessDelegate implementation.
- void OnShutdownComplete() override {
- shutdown_unblocker_.Unblock(base::Closure());
- }
-
- base::Thread io_thread_;
- scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
-
- base::Thread controller_thread_;
- scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
-
- // Accessed only on the controller thread.
- scoped_ptr<AppChildControllerImpl> controller_;
-
- // Used to unblock the main thread on shutdown.
- Blocker::Unblocker shutdown_unblocker_;
-
- DISALLOW_COPY_AND_ASSIGN(AppContext);
-};
-
-// AppChildControllerImpl ------------------------------------------------------
-
-class AppChildControllerImpl : public AppChildController, public ErrorHandler {
- public:
- ~AppChildControllerImpl() override {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // TODO(vtl): Pass in the result from |MainMain()|.
- on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED);
- }
-
- // To be executed on the controller thread. Creates the |AppChildController|,
- // etc.
- static void Init(AppContext* app_context,
- embedder::ScopedPlatformHandle platform_channel,
- const Blocker::Unblocker& unblocker) {
- DCHECK(app_context);
- DCHECK(platform_channel.is_valid());
-
- DCHECK(!app_context->controller());
-
- scoped_ptr<AppChildControllerImpl> impl(
- new AppChildControllerImpl(app_context, unblocker));
-
- ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
- platform_channel.Pass(), app_context->io_runner(),
- base::Bind(&AppChildControllerImpl::DidCreateChannel,
- base::Unretained(impl.get())),
- base::MessageLoopProxy::current()));
-
- impl->Bind(host_message_pipe.Pass());
-
- app_context->set_controller(impl.Pass());
- }
-
- void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
-
- // |ErrorHandler| methods:
- void OnConnectionError() override {
- // A connection error means the connection to the shell is lost. This is not
- // recoverable.
- LOG(ERROR) << "Connection error to the shell.";
- _exit(1);
- }
-
- // |AppChildController| methods:
- void StartApp(const String& app_path,
- bool clean_app_path,
- InterfaceRequest<Application> application_request,
- const StartAppCallback& on_app_complete) override {
- DVLOG(2) << "AppChildControllerImpl::StartApp(" << app_path << ", ...)";
- DCHECK(thread_checker_.CalledOnValidThread());
-
- on_app_complete_ = on_app_complete;
- unblocker_.Unblock(base::Bind(&AppChildControllerImpl::StartAppOnMainThread,
- base::FilePath::FromUTF8Unsafe(app_path),
- clean_app_path
- ? NativeApplicationCleanup::DELETE
- : NativeApplicationCleanup::DONT_DELETE,
- base::Passed(&application_request)));
- }
-
- void ExitNow(int32_t exit_code) override {
- DVLOG(2) << "AppChildControllerImpl::ExitNow(" << exit_code << ")";
- _exit(exit_code);
- }
-
- private:
- AppChildControllerImpl(AppContext* app_context,
- const Blocker::Unblocker& unblocker)
- : app_context_(app_context),
- unblocker_(unblocker),
- channel_info_(nullptr),
- binding_(this) {
- binding_.set_error_handler(this);
- }
-
- // Callback for |embedder::CreateChannel()|.
- void DidCreateChannel(embedder::ChannelInfo* channel_info) {
- DVLOG(2) << "AppChildControllerImpl::DidCreateChannel()";
- DCHECK(thread_checker_.CalledOnValidThread());
- channel_info_ = channel_info;
- }
-
- static void StartAppOnMainThread(
- const base::FilePath& app_path,
- NativeApplicationCleanup cleanup,
- InterfaceRequest<Application> application_request) {
- // TODO(vtl): This is copied from in_process_native_runner.cc.
- DVLOG(2) << "Loading/running Mojo app from " << app_path.value()
- << " out of process";
-
- // We intentionally don't unload the native library as its lifetime is the
- // same as that of the process.
- base::NativeLibrary app_library = LoadNativeApplication(app_path, cleanup);
- RunNativeApplication(app_library, application_request.Pass());
- }
-
- base::ThreadChecker thread_checker_;
- AppContext* const app_context_;
- Blocker::Unblocker unblocker_;
- StartAppCallback on_app_complete_;
-
- embedder::ChannelInfo* channel_info_;
- Binding<AppChildController> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(AppChildControllerImpl);
-};
-
-} // namespace
-
-// AppChildProcess -------------------------------------------------------------
-
-AppChildProcess::AppChildProcess() {
-}
-
-AppChildProcess::~AppChildProcess() {
-}
-
-void AppChildProcess::Main() {
- DVLOG(2) << "AppChildProcess::Main()";
-
- DCHECK(!base::MessageLoop::current());
-
- AppContext app_context;
- app_context.Init();
-
- Blocker blocker;
- app_context.controller_runner()->PostTask(
- FROM_HERE,
- base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context),
- base::Passed(platform_channel()), blocker.GetUnblocker()));
- // This will block, then run whatever the controller wants.
- blocker.Block();
-
- app_context.Shutdown();
-}
-
-} // namespace shell
-} // namespace mojo
diff --git a/mojo/shell/app_child_process.h b/mojo/shell/app_child_process.h
deleted file mode 100644
index d63afda..0000000
--- a/mojo/shell/app_child_process.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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 SHELL_APP_CHILD_PROCESS_H_
-#define SHELL_APP_CHILD_PROCESS_H_
-
-#include "base/macros.h"
-#include "mojo/shell/child_process.h"
-
-namespace mojo {
-namespace shell {
-
-// An implementation of |ChildProcess| for an app child process, which runs a
-// single app (loaded from the file system) on its main thread.
-class AppChildProcess : public ChildProcess {
- public:
- AppChildProcess();
- ~AppChildProcess() override;
-
- void Main() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AppChildProcess);
-};
-
-} // namespace shell
-} // namespace mojo
-
-#endif // SHELL_APP_CHILD_PROCESS_H_
diff --git a/mojo/shell/child_process.cc b/mojo/shell/child_process.cc
index 1140c14..e5438b1 100644
--- a/mojo/shell/child_process.cc
+++ b/mojo/shell/child_process.cc
@@ -4,36 +4,302 @@
#include "mojo/shell/child_process.h"
+#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/location.h"
#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "mojo/common/message_pump_mojo.h"
+#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/shell/app_child_process.h"
+#include "mojo/edk/embedder/process_delegate.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/edk/embedder/simple_platform_support.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/shell/app_child_process.mojom.h"
+#include "mojo/shell/native_application_support.h"
#include "mojo/shell/switches.h"
namespace mojo {
namespace shell {
-ChildProcess::~ChildProcess() {
-}
+namespace {
+
+// Blocker ---------------------------------------------------------------------
+
+// Blocks a thread until another thread unblocks it, at which point it unblocks
+// and runs a closure provided by that thread.
+class Blocker {
+ public:
+ class Unblocker {
+ public:
+ explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {}
+ ~Unblocker() {}
+
+ void Unblock(base::Closure run_after) {
+ DCHECK(blocker_);
+ DCHECK(blocker_->run_after_.is_null());
+ blocker_->run_after_ = run_after;
+ blocker_->event_.Signal();
+ blocker_ = nullptr;
+ }
+
+ private:
+ Blocker* blocker_;
+
+ // Copy and assign allowed.
+ };
+
+ Blocker() : event_(true, false) {}
+ ~Blocker() {}
+
+ void Block() {
+ DCHECK(run_after_.is_null());
+ event_.Wait();
+ run_after_.Run();
+ }
+
+ Unblocker GetUnblocker() { return Unblocker(this); }
+
+ private:
+ base::WaitableEvent event_;
+ base::Closure run_after_;
+
+ DISALLOW_COPY_AND_ASSIGN(Blocker);
+};
+
+// AppContext ------------------------------------------------------------------
+
+class AppChildControllerImpl;
+
+// Should be created and initialized on the main thread.
+class AppContext : public embedder::ProcessDelegate {
+ public:
+ AppContext()
+ : io_thread_("io_thread"), controller_thread_("controller_thread") {}
+ ~AppContext() override {}
+
+ void Init() {
+ // Initialize Mojo before starting any threads.
+ embedder::Init(make_scoped_ptr(new embedder::SimplePlatformSupport()));
+
+ // Create and start our I/O thread.
+ base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0);
+ CHECK(io_thread_.StartWithOptions(io_thread_options));
+ io_runner_ = io_thread_.message_loop_proxy().get();
+ CHECK(io_runner_.get());
+
+ // Create and start our controller thread.
+ base::Thread::Options controller_thread_options;
+ controller_thread_options.message_loop_type =
+ base::MessageLoop::TYPE_CUSTOM;
+ controller_thread_options.message_pump_factory =
+ base::Bind(&common::MessagePumpMojo::Create);
+ CHECK(controller_thread_.StartWithOptions(controller_thread_options));
+ controller_runner_ = controller_thread_.message_loop_proxy().get();
+ CHECK(controller_runner_.get());
+
+ // TODO(vtl): This should be SLAVE, not NONE.
+ embedder::InitIPCSupport(embedder::ProcessType::NONE, controller_runner_,
+ this, io_runner_,
+ embedder::ScopedPlatformHandle());
+ }
+
+ void Shutdown() {
+ Blocker blocker;
+ shutdown_unblocker_ = blocker.GetUnblocker();
+ controller_runner_->PostTask(
+ FROM_HERE, base::Bind(&AppContext::ShutdownOnControllerThread,
+ base::Unretained(this)));
+ blocker.Block();
+ }
+
+ base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); }
+
+ base::SingleThreadTaskRunner* controller_runner() const {
+ return controller_runner_.get();
+ }
+
+ AppChildControllerImpl* controller() const { return controller_.get(); }
+
+ void set_controller(scoped_ptr<AppChildControllerImpl> controller) {
+ controller_ = controller.Pass();
+ }
+
+ private:
+ void ShutdownOnControllerThread() {
+ // First, destroy the controller.
+ controller_.reset();
+
+ // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete().
+ embedder::ShutdownIPCSupport();
+ }
+
+ // ProcessDelegate implementation.
+ void OnShutdownComplete() override {
+ shutdown_unblocker_.Unblock(base::Closure());
+ }
+
+ base::Thread io_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
+
+ base::Thread controller_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
-// static
-scoped_ptr<ChildProcess> ChildProcess::Create(
- const base::CommandLine& command_line) {
- if (!command_line.HasSwitch(switches::kChildProcess))
- return scoped_ptr<ChildProcess>();
+ // Accessed only on the controller thread.
+ scoped_ptr<AppChildControllerImpl> controller_;
- scoped_ptr<ChildProcess> rv(new AppChildProcess());
- if (!rv)
- return nullptr;
+ // Used to unblock the main thread on shutdown.
+ Blocker::Unblocker shutdown_unblocker_;
- rv->platform_channel_ =
+ DISALLOW_COPY_AND_ASSIGN(AppContext);
+};
+
+// AppChildControllerImpl ------------------------------------------------------
+
+class AppChildControllerImpl : public AppChildController, public ErrorHandler {
+ public:
+ ~AppChildControllerImpl() override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // TODO(vtl): Pass in the result from |MainMain()|.
+ on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED);
+ }
+
+ // To be executed on the controller thread. Creates the |AppChildController|,
+ // etc.
+ static void Init(AppContext* app_context,
+ embedder::ScopedPlatformHandle platform_channel,
+ const Blocker::Unblocker& unblocker) {
+ DCHECK(app_context);
+ DCHECK(platform_channel.is_valid());
+
+ DCHECK(!app_context->controller());
+
+ scoped_ptr<AppChildControllerImpl> impl(
+ new AppChildControllerImpl(app_context, unblocker));
+
+ ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
+ platform_channel.Pass(), app_context->io_runner(),
+ base::Bind(&AppChildControllerImpl::DidCreateChannel,
+ base::Unretained(impl.get())),
+ base::MessageLoopProxy::current()));
+
+ impl->Bind(host_message_pipe.Pass());
+
+ app_context->set_controller(impl.Pass());
+ }
+
+ void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
+
+ // |ErrorHandler| methods:
+ void OnConnectionError() override {
+ // A connection error means the connection to the shell is lost. This is not
+ // recoverable.
+ LOG(ERROR) << "Connection error to the shell.";
+ _exit(1);
+ }
+
+ // |AppChildController| methods:
+ void StartApp(const String& app_path,
+ bool clean_app_path,
+ InterfaceRequest<Application> application_request,
+ const StartAppCallback& on_app_complete) override {
+ DVLOG(2) << "AppChildControllerImpl::StartApp(" << app_path << ", ...)";
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ on_app_complete_ = on_app_complete;
+ unblocker_.Unblock(base::Bind(&AppChildControllerImpl::StartAppOnMainThread,
+ base::FilePath::FromUTF8Unsafe(app_path),
+ clean_app_path
+ ? NativeApplicationCleanup::DELETE
+ : NativeApplicationCleanup::DONT_DELETE,
+ base::Passed(&application_request)));
+ }
+
+ void ExitNow(int32_t exit_code) override {
+ DVLOG(2) << "AppChildControllerImpl::ExitNow(" << exit_code << ")";
+ _exit(exit_code);
+ }
+
+ private:
+ AppChildControllerImpl(AppContext* app_context,
+ const Blocker::Unblocker& unblocker)
+ : app_context_(app_context),
+ unblocker_(unblocker),
+ channel_info_(nullptr),
+ binding_(this) {
+ binding_.set_error_handler(this);
+ }
+
+ // Callback for |embedder::CreateChannel()|.
+ void DidCreateChannel(embedder::ChannelInfo* channel_info) {
+ DVLOG(2) << "AppChildControllerImpl::DidCreateChannel()";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ channel_info_ = channel_info;
+ }
+
+ static void StartAppOnMainThread(
+ const base::FilePath& app_path,
+ NativeApplicationCleanup cleanup,
+ InterfaceRequest<Application> application_request) {
+ // TODO(vtl): This is copied from in_process_native_runner.cc.
+ DVLOG(2) << "Loading/running Mojo app from " << app_path.value()
+ << " out of process";
+
+ // We intentionally don't unload the native library as its lifetime is the
+ // same as that of the process.
+ base::NativeLibrary app_library = LoadNativeApplication(app_path, cleanup);
+ RunNativeApplication(app_library, application_request.Pass());
+ }
+
+ base::ThreadChecker thread_checker_;
+ AppContext* const app_context_;
+ Blocker::Unblocker unblocker_;
+ StartAppCallback on_app_complete_;
+
+ embedder::ChannelInfo* channel_info_;
+ Binding<AppChildController> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppChildControllerImpl);
+};
+
+} // namespace
+
+int ChildProcessMain() {
+ DVLOG(2) << "ChildProcessMain()";
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ embedder::ScopedPlatformHandle platform_channel =
embedder::PlatformChannelPair::PassClientHandleFromParentProcess(
command_line);
- CHECK(rv->platform_channel_.is_valid());
- return rv;
-}
+ CHECK(platform_channel.is_valid());
+
+ DCHECK(!base::MessageLoop::current());
+
+ AppContext app_context;
+ app_context.Init();
+
+ Blocker blocker;
+ app_context.controller_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context),
+ base::Passed(&platform_channel), blocker.GetUnblocker()));
+ // This will block, then run whatever the controller wants.
+ blocker.Block();
+
+ app_context.Shutdown();
-ChildProcess::ChildProcess() {
+ return 0;
}
} // namespace shell
diff --git a/mojo/shell/child_process.h b/mojo/shell/child_process.h
index 3da1c8f..c0cc431 100644
--- a/mojo/shell/child_process.h
+++ b/mojo/shell/child_process.h
@@ -2,50 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SHELL_CHILD_PROCESS_H_
-#define SHELL_CHILD_PROCESS_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-
-namespace base {
-class CommandLine;
-}
+#ifndef MOJO_SHELL_CHILD_PROCESS_H_
+#define MOJO_SHELL_CHILD_PROCESS_H_
namespace mojo {
namespace shell {
-// A base class for child processes -- i.e., code that is actually run within
-// the child process. (Instances are manufactured by |Create()|.)
-class ChildProcess {
- public:
- virtual ~ChildProcess();
-
- // Returns null if the command line doesn't indicate that this is a child
- // process. |main()| should call this, and if it returns non-null it should
- // call |Main()| (without a message loop on the current thread).
- static scoped_ptr<ChildProcess> Create(const base::CommandLine& command_line);
-
- // To be implemented by subclasses. This is the "entrypoint" for a child
- // process. Run with no message loop for the main thread.
- virtual void Main() = 0;
-
- protected:
- ChildProcess();
-
- embedder::ScopedPlatformHandle* platform_channel() {
- return &platform_channel_;
- }
-
- private:
- // Available in |Main()| (after a successful |Create()|).
- embedder::ScopedPlatformHandle platform_channel_;
-
- DISALLOW_COPY_AND_ASSIGN(ChildProcess);
-};
+// Main method for a child process.
+int ChildProcessMain();
} // namespace shell
} // namespace mojo
-#endif // SHELL_CHILD_PROCESS_H_
+#endif // MOJO_SHELL_CHILD_PROCESS_H_
diff --git a/mojo/shell/desktop/launcher_process.cc b/mojo/shell/desktop/launcher_process.cc
new file mode 100644
index 0000000..f6bb6de
--- /dev/null
+++ b/mojo/shell/desktop/launcher_process.cc
@@ -0,0 +1,170 @@
+// Copyright 2013 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 <stdio.h>
+#include <string.h>
+
+#include <algorithm>
+#include <iostream>
+
+#include "base/base_switches.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/trace_event/trace_event.h"
+#include "mojo/shell/command_line_util.h"
+#include "mojo/shell/context.h"
+#include "mojo/shell/switches.h"
+
+namespace mojo {
+namespace shell {
+namespace {
+
+void Usage() {
+ std::cerr << "Launch Mojo applications.\n";
+ std::cerr
+ << "Usage: mojo_shell"
+ << " [--" << switches::kArgsFor << "=<mojo-app>]"
+ << " [--" << switches::kContentHandlers << "=<handlers>]"
+ << " [--" << switches::kDisableCache << "]"
+ << " [--" << switches::kEnableMultiprocess << "]"
+ << " [--" << switches::kOrigin << "=<url-lib-path>]"
+ << " [--" << switches::kTraceStartup << "]"
+ << " [--" << switches::kURLMappings << "=from1=to1,from2=to2]"
+ << " [--" << switches::kPredictableAppFilenames << "]"
+ << " [--" << switches::kWaitForDebugger << "]"
+ << " <mojo-app> ...\n\n"
+ << "A <mojo-app> is a Mojo URL or a Mojo URL and arguments within "
+ << "quotes.\n"
+ << "Example: mojo_shell \"mojo:js_standalone test.js\".\n"
+ << "<url-lib-path> is searched for shared libraries named by mojo URLs.\n"
+ << "The value of <handlers> is a comma separated list like:\n"
+ << "text/html,mojo:html_viewer,"
+ << "application/javascript,mojo:js_content_handler\n";
+}
+
+// Whether we're currently tracing.
+bool g_tracing = false;
+
+// Number of tracing blocks written.
+uint32_t g_blocks = 0;
+
+// Trace file, if open.
+FILE* g_trace_file = nullptr;
+
+void WriteTraceDataCollected(
+ base::WaitableEvent* event,
+ const scoped_refptr<base::RefCountedString>& events_str,
+ bool has_more_events) {
+ if (g_blocks) {
+ fwrite(",", 1, 1, g_trace_file);
+ }
+
+ ++g_blocks;
+ fwrite(events_str->data().c_str(), 1, events_str->data().length(),
+ g_trace_file);
+ if (!has_more_events) {
+ static const char kEnd[] = "]}";
+ fwrite(kEnd, 1, strlen(kEnd), g_trace_file);
+ PCHECK(fclose(g_trace_file) == 0);
+ g_trace_file = nullptr;
+ event->Signal();
+ }
+}
+
+void EndTraceAndFlush(base::WaitableEvent* event) {
+ g_trace_file = fopen("mojo_shell.trace", "w+");
+ PCHECK(g_trace_file);
+ static const char kStart[] = "{\"traceEvents\":[";
+ fwrite(kStart, 1, strlen(kStart), g_trace_file);
+ base::trace_event::TraceLog::GetInstance()->SetDisabled();
+ base::trace_event::TraceLog::GetInstance()->Flush(
+ base::Bind(&WriteTraceDataCollected, base::Unretained(event)));
+}
+
+void StopTracingAndFlushToDisk() {
+ g_tracing = false;
+ base::trace_event::TraceLog::GetInstance()->SetDisabled();
+ base::WaitableEvent flush_complete_event(false, false);
+ // TraceLog::Flush requires a message loop but we've already shut ours down.
+ // Spin up a new thread to flush things out.
+ base::Thread flush_thread("mojo_shell_trace_event_flush");
+ flush_thread.Start();
+ flush_thread.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(EndTraceAndFlush, base::Unretained(&flush_complete_event)));
+ flush_complete_event.Wait();
+}
+
+} // namespace
+
+int LauncherProcessMain(int argc, char** argv) {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ const std::set<std::string> all_switches = switches::GetAllSwitches();
+ const base::CommandLine::SwitchMap switches = command_line.GetSwitches();
+ bool found_unknown_switch = false;
+ for (const auto& s : switches) {
+ if (all_switches.find(s.first) == all_switches.end()) {
+ std::cerr << "unknown switch: " << s.first << std::endl;
+ found_unknown_switch = true;
+ }
+ }
+
+ if (found_unknown_switch || command_line.HasSwitch(switches::kHelp) ||
+ command_line.GetArgs().empty()) {
+ Usage();
+ return 0;
+ }
+
+ if (command_line.HasSwitch(switches::kTraceStartup)) {
+ g_tracing = true;
+ base::trace_event::CategoryFilter category_filter(
+ command_line.GetSwitchValueASCII(switches::kTraceStartup));
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ category_filter, base::trace_event::TraceLog::RECORDING_MODE,
+ base::trace_event::TraceOptions(base::trace_event::RECORD_UNTIL_FULL));
+ }
+
+ // We want the shell::Context to outlive the MessageLoop so that pipes are
+ // all gracefully closed / error-out before we try to shut the Context down.
+ mojo::shell::Context shell_context;
+ {
+ base::MessageLoop message_loop;
+ if (!shell_context.Init()) {
+ Usage();
+ return 0;
+ }
+ if (g_tracing) {
+ message_loop.PostDelayedTask(FROM_HERE,
+ base::Bind(StopTracingAndFlushToDisk),
+ base::TimeDelta::FromSeconds(5));
+ }
+
+ // The mojo_shell --args-for command-line switch is handled specially
+ // because it can appear more than once. The base::CommandLine class
+ // collapses multiple occurrences of the same switch.
+ for (int i = 1; i < argc; i++) {
+ ApplyApplicationArgs(&shell_context, argv[i]);
+ }
+
+ message_loop.PostTask(
+ FROM_HERE,
+ base::Bind(&mojo::shell::RunCommandLineApps, &shell_context));
+ message_loop.Run();
+
+ // Must be called before |message_loop| is destroyed.
+ shell_context.Shutdown();
+ }
+
+ if (g_tracing)
+ StopTracingAndFlushToDisk();
+ return 0;
+}
+
+} // namespace shell
+} // namespace mojo
diff --git a/mojo/shell/desktop/launcher_process.h b/mojo/shell/desktop/launcher_process.h
new file mode 100644
index 0000000..caed878
--- /dev/null
+++ b/mojo/shell/desktop/launcher_process.h
@@ -0,0 +1,17 @@
+// Copyright 2015 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_LAUNCHER_PROCESS_H_
+#define MOJO_SHELL_LAUNCHER_PROCESS_H_
+
+namespace mojo {
+namespace shell {
+
+// Main method for the launcher process.
+int LauncherProcessMain(int argc, char** argv);
+
+} // namespace shell
+} // namespace mojo
+
+#endif // MOJO_SHELL_LAUNCHER_PROCESS_H_
diff --git a/mojo/shell/desktop/main.cc b/mojo/shell/desktop/main.cc
index 9214985..ca89c5d 100644
--- a/mojo/shell/desktop/main.cc
+++ b/mojo/shell/desktop/main.cc
@@ -2,184 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <stdio.h>
-#include <string.h>
-
-#include <algorithm>
-#include <iostream>
-
#include "base/at_exit.h"
-#include "base/base_switches.h"
-#include "base/bind.h"
#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/trace_event/trace_event.h"
#include "mojo/shell/child_process.h"
-#include "mojo/shell/command_line_util.h"
-#include "mojo/shell/context.h"
+#include "mojo/shell/desktop/launcher_process.h"
#include "mojo/shell/init.h"
#include "mojo/shell/switches.h"
-namespace {
-
-void Usage() {
- std::cerr << "Launch Mojo applications.\n";
- std::cerr
- << "Usage: mojo_shell"
- << " [--" << switches::kArgsFor << "=<mojo-app>]"
- << " [--" << switches::kContentHandlers << "=<handlers>]"
- << " [--" << switches::kEnableExternalApplications << "]"
- << " [--" << switches::kDisableCache << "]"
- << " [--" << switches::kEnableMultiprocess << "]"
- << " [--" << switches::kOrigin << "=<url-lib-path>]"
- << " [--" << switches::kTraceStartup << "]"
- << " [--" << switches::kURLMappings << "=from1=to1,from2=to2]"
- << " [--" << switches::kPredictableAppFilenames << "]"
- << " [--" << switches::kWaitForDebugger << "]"
- << " <mojo-app> ...\n\n"
- << "A <mojo-app> is a Mojo URL or a Mojo URL and arguments within "
- << "quotes.\n"
- << "Example: mojo_shell \"mojo:js_standalone test.js\".\n"
- << "<url-lib-path> is searched for shared libraries named by mojo URLs.\n"
- << "The value of <handlers> is a comma separated list like:\n"
- << "text/html,mojo:html_viewer,"
- << "application/javascript,mojo:js_content_handler\n";
-}
-
-// Whether we're currently tracing.
-bool g_tracing = false;
-
-// Number of tracing blocks written.
-uint32_t g_blocks = 0;
-
-// Trace file, if open.
-FILE* g_trace_file = nullptr;
-
-void WriteTraceDataCollected(
- base::WaitableEvent* event,
- const scoped_refptr<base::RefCountedString>& events_str,
- bool has_more_events) {
- if (g_blocks) {
- fwrite(",", 1, 1, g_trace_file);
- }
-
- ++g_blocks;
- fwrite(events_str->data().c_str(), 1, events_str->data().length(),
- g_trace_file);
- if (!has_more_events) {
- static const char kEnd[] = "]}";
- fwrite(kEnd, 1, strlen(kEnd), g_trace_file);
- PCHECK(fclose(g_trace_file) == 0);
- g_trace_file = nullptr;
- event->Signal();
- }
-}
-
-void EndTraceAndFlush(base::WaitableEvent* event) {
- g_trace_file = fopen("mojo_shell.trace", "w+");
- PCHECK(g_trace_file);
- static const char kStart[] = "{\"traceEvents\":[";
- fwrite(kStart, 1, strlen(kStart), g_trace_file);
- base::trace_event::TraceLog::GetInstance()->SetDisabled();
- base::trace_event::TraceLog::GetInstance()->Flush(
- base::Bind(&WriteTraceDataCollected, base::Unretained(event)));
-}
-
-void StopTracingAndFlushToDisk() {
- g_tracing = false;
- base::trace_event::TraceLog::GetInstance()->SetDisabled();
- base::WaitableEvent flush_complete_event(false, false);
- // TraceLog::Flush requires a message loop but we've already shut ours down.
- // Spin up a new thread to flush things out.
- base::Thread flush_thread("mojo_shell_trace_event_flush");
- flush_thread.Start();
- flush_thread.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(EndTraceAndFlush, base::Unretained(&flush_complete_event)));
- flush_complete_event.Wait();
-}
-
-} // namespace
-
int main(int argc, char** argv) {
base::AtExitManager at_exit;
base::CommandLine::Init(argc, argv);
mojo::shell::InitializeLogging();
- // TODO(vtl): Unify parent and child process cases to the extent possible.
- if (scoped_ptr<mojo::shell::ChildProcess> child_process =
- mojo::shell::ChildProcess::Create(
- *base::CommandLine::ForCurrentProcess())) {
- child_process->Main();
- } else {
- // Only check the command line for the main process.
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
-
- const std::set<std::string> all_switches = switches::GetAllSwitches();
- const base::CommandLine::SwitchMap switches = command_line.GetSwitches();
- bool found_unknown_switch = false;
- for (const auto& s : switches) {
- if (all_switches.find(s.first) == all_switches.end()) {
- std::cerr << "unknown switch: " << s.first << std::endl;
- found_unknown_switch = true;
- }
- }
-
- if (found_unknown_switch ||
- (!command_line.HasSwitch(switches::kEnableExternalApplications) &&
- (command_line.HasSwitch(switches::kHelp) ||
- command_line.GetArgs().empty()))) {
- Usage();
- return 0;
- }
-
- if (command_line.HasSwitch(switches::kTraceStartup)) {
- g_tracing = true;
- base::trace_event::CategoryFilter category_filter(
- command_line.GetSwitchValueASCII(switches::kTraceStartup));
- base::trace_event::TraceLog::GetInstance()->SetEnabled(
- category_filter, base::trace_event::TraceLog::RECORDING_MODE,
- base::trace_event::TraceOptions(
- base::trace_event::RECORD_UNTIL_FULL));
- }
-
- // We want the shell::Context to outlive the MessageLoop so that pipes are
- // all gracefully closed / error-out before we try to shut the Context down.
- mojo::shell::Context shell_context;
- {
- base::MessageLoop message_loop;
- if (!shell_context.Init()) {
- Usage();
- return 0;
- }
- if (g_tracing) {
- message_loop.PostDelayedTask(FROM_HERE,
- base::Bind(StopTracingAndFlushToDisk),
- base::TimeDelta::FromSeconds(5));
- }
-
- // The mojo_shell --args-for command-line switch is handled specially
- // because it can appear more than once. The base::CommandLine class
- // collapses multiple occurrences of the same switch.
- for (int i = 1; i < argc; i++) {
- ApplyApplicationArgs(&shell_context, argv[i]);
- }
-
- message_loop.PostTask(
- FROM_HERE,
- base::Bind(&mojo::shell::RunCommandLineApps, &shell_context));
- message_loop.Run();
-
- // Must be called before |message_loop| is destroyed.
- shell_context.Shutdown();
- }
- }
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kChildProcess))
+ return mojo::shell::ChildProcessMain();
- if (g_tracing)
- StopTracingAndFlushToDisk();
- return 0;
+ return mojo::shell::LauncherProcessMain(argc, argv);
}
diff --git a/mojo/shell/launcher_main.cc b/mojo/shell/launcher_main.cc
deleted file mode 100644
index dfe634c..0000000
--- a/mojo/shell/launcher_main.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// 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 "base/at_exit.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/string_split.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/process_delegate.h"
-#include "mojo/edk/embedder/simple_platform_support.h"
-#include "mojo/shell/in_process_native_runner.h"
-#include "mojo/shell/init.h"
-#include "mojo/shell/native_application_support.h"
-#include "url/gurl.h"
-
-namespace mojo {
-namespace shell {
-
-const char kAppArgs[] = "app-args";
-const char kAppPath[] = "app-path";
-const char kAppURL[] = "app-url";
-const char kShellPath[] = "shell-path";
-
-class Launcher : public embedder::ProcessDelegate {
- public:
- explicit Launcher(const base::CommandLine& command_line)
- : app_path_(command_line.GetSwitchValuePath(kAppPath)),
- app_url_(command_line.GetSwitchValueASCII(kAppURL)),
- loop_(base::MessageLoop::TYPE_IO) {
- // TODO(vtl): I guess this should be SLAVE, not NONE?
- embedder::InitIPCSupport(embedder::ProcessType::NONE, loop_.task_runner(),
- this, loop_.task_runner(),
- embedder::ScopedPlatformHandle());
-
- base::SplitStringAlongWhitespace(command_line.GetSwitchValueASCII(kAppArgs),
- &app_args_);
- }
-
- ~Launcher() override {
- DCHECK(!application_request_.is_pending());
-
- embedder::ShutdownIPCSupportOnIOThread();
- }
-
- bool Connect() { return false; }
-
- bool Register() {
- return application_request_.is_pending();
- }
-
- void Run() {
- DCHECK(application_request_.is_pending());
- InProcessNativeRunner service_runner(nullptr);
- base::RunLoop run_loop;
- service_runner.Start(app_path_, NativeApplicationCleanup::DONT_DELETE,
- application_request_.Pass(), run_loop.QuitClosure());
- run_loop.Run();
- }
-
- private:
- void OnRegistered(base::RunLoop* run_loop,
- InterfaceRequest<Application> application_request) {
- application_request_ = application_request.Pass();
- run_loop->Quit();
- }
-
- // embedder::ProcessDelegate implementation:
- void OnShutdownComplete() override {
- NOTREACHED(); // Not called since we use ShutdownIPCSupportOnIOThread().
- }
-
- const base::FilePath app_path_;
- const GURL app_url_;
- std::vector<std::string> app_args_;
- base::MessageLoop loop_;
- InterfaceRequest<Application> application_request_;
-
- DISALLOW_COPY_AND_ASSIGN(Launcher);
-};
-
-} // namespace shell
-} // namespace mojo
-
-int main(int argc, char** argv) {
- base::AtExitManager at_exit;
- mojo::embedder::Init(
- make_scoped_ptr(new mojo::embedder::SimplePlatformSupport()));
-
- base::CommandLine::Init(argc, argv);
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- mojo::shell::InitializeLogging();
-
- mojo::shell::Launcher launcher(*command_line);
- if (!launcher.Connect()) {
- LOG(ERROR) << "Failed to connect on socket "
- << command_line->GetSwitchValueASCII(mojo::shell::kShellPath);
- return 1;
- }
-
- if (!launcher.Register()) {
- LOG(ERROR) << "Error registering "
- << command_line->GetSwitchValueASCII(mojo::shell::kAppURL);
- return 1;
- }
-
- launcher.Run();
- return 0;
-}
diff --git a/mojo/shell/shell_test_main.cc b/mojo/shell/shell_test_main.cc
index 179eb41..47b6c09 100644
--- a/mojo/shell/shell_test_main.cc
+++ b/mojo/shell/shell_test_main.cc
@@ -19,11 +19,8 @@ int main(int argc, char** argv) {
if (command_line.HasSwitch(switches::kChildProcess)) {
base::AtExitManager at_exit;
- scoped_ptr<mojo::shell::ChildProcess> child_process =
- mojo::shell::ChildProcess::Create(command_line);
- CHECK(child_process);
- child_process->Main();
- return 0;
+
+ return mojo::shell::ChildProcessMain();
}
base::TestSuite test_suite(argc, argv);
diff --git a/mojo/shell/switches.cc b/mojo/shell/switches.cc
index 6aa5cda..2150b19 100644
--- a/mojo/shell/switches.cc
+++ b/mojo/shell/switches.cc
@@ -35,11 +35,6 @@ const char kDisableCache[] = "disable-cache";
// If set apps downloaded are not deleted.
const char kDontDeleteOnDownload[] = "dont-delete-on-download";
-// Allow externally-running applications to discover, connect to, and register
-// themselves with the shell.
-// TODO(cmasone): Work in progress. Once we're sure this works, remove.
-const char kEnableExternalApplications[] = "enable-external-applications";
-
// 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.
@@ -85,7 +80,6 @@ const char* kSwitchArray[] = {kV,
kContentHandlers,
kDisableCache,
kDontDeleteOnDownload,
- kEnableExternalApplications,
kEnableMultiprocess,
kForceInProcess,
kHelp,
diff --git a/mojo/shell/switches.h b/mojo/shell/switches.h
index 5c8056f..52267fe 100644
--- a/mojo/shell/switches.h
+++ b/mojo/shell/switches.h
@@ -18,7 +18,6 @@ extern const char kChildProcess[];
extern const char kContentHandlers[];
extern const char kDisableCache[];
extern const char kDontDeleteOnDownload[];
-extern const char kEnableExternalApplications[];
extern const char kEnableMultiprocess[];
extern const char kForceInProcess[];
extern const char kHelp[];