summaryrefslogtreecommitdiffstats
path: root/mojo/shell/runner/host/child_process_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/shell/runner/host/child_process_base.cc')
-rw-r--r--mojo/shell/runner/host/child_process_base.cc234
1 files changed, 15 insertions, 219 deletions
diff --git a/mojo/shell/runner/host/child_process_base.cc b/mojo/shell/runner/host/child_process_base.cc
index 538cf7d..e6b9a25 100644
--- a/mojo/shell/runner/host/child_process_base.cc
+++ b/mojo/shell/runner/host/child_process_base.cc
@@ -4,99 +4,28 @@
#include "mojo/shell/runner/host/child_process_base.h"
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/debug/stack_trace.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/thread_task_runner_handle.h"
#include "base/threading/thread.h"
-#include "base/threading/thread_checker.h"
#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/process_delegate.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/message_pump/message_pump_mojo.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/system/core.h"
-#include "mojo/shell/public/interfaces/shell_client_factory.mojom.h"
-#include "mojo/shell/runner/common/switches.h"
-#include "mojo/shell/runner/init.h"
+#include "mojo/shell/runner/common/client_util.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 {
+// Should be created and initialized on the main thread and kept alive as long
+// a Mojo application is running in the current process.
+class ScopedAppContext : public edk::ProcessDelegate {
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();
- if (!run_after_.is_null())
- run_after_.Run();
- }
-
- Unblocker GetUnblocker() { return Unblocker(this); }
-
- private:
- base::WaitableEvent event_;
- base::Closure run_after_;
-
- DISALLOW_COPY_AND_ASSIGN(Blocker);
-};
-
-// AppContext ------------------------------------------------------------------
-
-class ChildControllerImpl;
-
-// Should be created and initialized on the main thread.
-class AppContext : public edk::ProcessDelegate {
- public:
- AppContext()
- : io_thread_("io_thread"), controller_thread_("controller_thread") {}
- ~AppContext() override {}
-
- void Init() {
+ ScopedAppContext()
+ : io_thread_("io_thread"), wait_for_shutdown_event_(true, false) {
// Initialize Mojo before starting any threads.
edk::Init();
@@ -106,170 +35,37 @@ class AppContext : public edk::ProcessDelegate {
io_runner_ = io_thread_.task_runner().get();
CHECK(io_runner_.get());
- // This must be created before controller_thread_ since MessagePumpMojo will
- // create a message pipe which requires this code to be run first.
edk::InitIPCSupport(this, io_runner_);
+ edk::SetParentPipeHandleFromCommandLine();
}
- void StartControllerThread() {
- // 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_.task_runner().get();
- CHECK(controller_runner_.get());
- }
-
- 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();
- }
-
- ChildControllerImpl* controller() const { return controller_.get(); }
-
- void set_controller(scoped_ptr<ChildControllerImpl> controller) {
- controller_ = std::move(controller);
- }
-
- private:
- void ShutdownOnControllerThread() {
- // First, destroy the controller.
- controller_.reset();
-
- // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete().
+ ~ScopedAppContext() override {
edk::ShutdownIPCSupport();
+ wait_for_shutdown_event_.Wait();
}
+ private:
// ProcessDelegate implementation.
void OnShutdownComplete() override {
- shutdown_unblocker_.Unblock(base::Closure());
+ wait_for_shutdown_event_.Signal();
}
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<ChildControllerImpl> controller_;
-
// Used to unblock the main thread on shutdown.
- Blocker::Unblocker shutdown_unblocker_;
+ base::WaitableEvent wait_for_shutdown_event_;
- DISALLOW_COPY_AND_ASSIGN(AppContext);
+ DISALLOW_COPY_AND_ASSIGN(ScopedAppContext);
};
-// ChildControllerImpl ------------------------------------------------------
-
-class ChildControllerImpl : public mojom::ShellClientFactory {
- public:
- ~ChildControllerImpl() override {
- DCHECK(thread_checker_.CalledOnValidThread());
- }
-
- // To be executed on the controller thread. Creates the |ChildController|,
- // etc.
- static void Init(AppContext* app_context,
- const RunCallback& run_callback,
- ScopedMessagePipeHandle host_message_pipe,
- const Blocker::Unblocker& unblocker) {
- DCHECK(app_context);
- DCHECK(host_message_pipe.is_valid());
-
- DCHECK(!app_context->controller());
-
- scoped_ptr<ChildControllerImpl> impl(
- new ChildControllerImpl(app_context, run_callback, unblocker));
-
- impl->Bind(std::move(host_message_pipe));
-
- app_context->set_controller(std::move(impl));
- }
-
- void Bind(ScopedMessagePipeHandle handle) {
- binding_.Bind(std::move(handle));
- binding_.set_connection_error_handler([this]() { OnConnectionError(); });
- }
-
- void OnConnectionError() {
- // A connection error means the connection to the shell is lost. This is not
- // recoverable.
- LOG(ERROR) << "Connection error to the shell.";
- _exit(1);
- }
-
- // |mojom::ShellClientFactory| methods:
- void CreateShellClient(mojom::ShellClientRequest request,
- const String& name) override {
- DCHECK(thread_checker_.CalledOnValidThread());
- unblocker_.Unblock(base::Bind(run_callback_, base::Passed(&request)));
- }
-
- private:
- ChildControllerImpl(AppContext* app_context,
- const RunCallback& run_callback,
- const Blocker::Unblocker& unblocker)
- : run_callback_(run_callback), unblocker_(unblocker), binding_(this) {}
-
- base::ThreadChecker thread_checker_;
- RunCallback run_callback_;
- Blocker::Unblocker unblocker_;
-
- Binding<mojom::ShellClientFactory> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl);
-};
-
-ScopedMessagePipeHandle InitializeHostMessagePipe(
- edk::ScopedPlatformHandle platform_channel,
- scoped_refptr<base::TaskRunner> io_task_runner) {
- edk::SetParentPipeHandle(std::move(platform_channel));
- std::string primordial_pipe_token =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kPrimordialPipeToken);
- return edk::CreateChildMessagePipe(primordial_pipe_token);
-}
-
} // namespace
void ChildProcessMain(const RunCallback& callback) {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- edk::ScopedPlatformHandle platform_channel =
- edk::PlatformChannelPair::PassClientHandleFromParentProcess(command_line);
- CHECK(platform_channel.is_valid());
-
DCHECK(!base::MessageLoop::current());
- Blocker blocker;
- AppContext app_context;
- app_context.Init();
- app_context.StartControllerThread();
-
- ScopedMessagePipeHandle host_pipe = InitializeHostMessagePipe(
- std::move(platform_channel), app_context.io_runner());
- app_context.controller_runner()->PostTask(
- FROM_HERE, base::Bind(&ChildControllerImpl::Init, &app_context, callback,
- base::Passed(&host_pipe), blocker.GetUnblocker()));
-
- // This will block, then run whatever the controller wants.
- blocker.Block();
-
- app_context.Shutdown();
+ ScopedAppContext app_context;
+ callback.Run(GetShellClientRequestFromCommandLine());
}
} // namespace shell