summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorben <ben@chromium.org>2015-11-15 04:13:09 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-15 12:14:44 +0000
commit03b7b9d5d01d4b23362a1b9fcd13900fbb11286c (patch)
tree71181e958a9510ce5aa9de3e00c5b9e96b5ca410 /content
parente9b72dd87754ca5a4af39509070ae682c5e5bc14 (diff)
downloadchromium_src-03b7b9d5d01d4b23362a1b9fcd13900fbb11286c.zip
chromium_src-03b7b9d5d01d4b23362a1b9fcd13900fbb11286c.tar.gz
chromium_src-03b7b9d5d01d4b23362a1b9fcd13900fbb11286c.tar.bz2
Move Shell connection to content.
I want to be able to use Mojo in content, so I think it makes sense that the shell bind step lives in content too. 1. Moves MojoRunnerState to content/common and renames it to MojoShellConnection. This class will be available in any process that creates an impl prior to running the main message loop. 2. Modifies ChildProcessLauncher to create a platform channel pair and put the client handle on the command line of the child process, and registers the server handle with the external shell. This will allow the child process to bind an Application request if it wants. TODO: What if the child process doesn't bind it? What happens to the instance created in the external shell? TODO: ChildProcessLauncher is a convenient chokepoint. It means the shell handle is passed to all child processes created by content. Do we want to do this? I think it's OK for now since this code is only triggered if Chrome itself is run from within the external shell. Before we can move this to production I think CreateInstanceForHandle is going to have to take a CapabilityFilter. R=jam@chromium.org http://crbug.com/551253 Review URL: https://codereview.chromium.org/1442893002 Cr-Commit-Position: refs/heads/master@{#359770}
Diffstat (limited to 'content')
-rw-r--r--content/browser/BUILD.gn3
-rw-r--r--content/browser/DEPS2
-rw-r--r--content/browser/browser_main_loop.cc26
-rw-r--r--content/browser/child_process_launcher.cc62
-rw-r--r--content/browser/child_process_launcher.h9
-rw-r--r--content/common/BUILD.gn13
-rw-r--r--content/common/mojo/DEPS3
-rw-r--r--content/common/mojo/mojo_shell_connection_impl.cc95
-rw-r--r--content/common/mojo/mojo_shell_connection_impl.h65
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/public/common/mojo_shell_connection.h59
11 files changed, 336 insertions, 2 deletions
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index d97c5cb..9990e72 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -104,6 +104,8 @@ source_set("browser") {
],
".")
+ defines += [ "MOJO_SHELL_CLIENT" ]
+
# Non-iOS deps.
deps += [
"//cc",
@@ -417,6 +419,7 @@ source_set("browser") {
"//ui/aura",
"//ui/aura_extra",
"//ui/strings",
+ "//ui/views/mus:for_component",
"//ui/wm",
]
} else { # Not aura.
diff --git a/content/browser/DEPS b/content/browser/DEPS
index d29e52f..298ec09 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -2,6 +2,7 @@ include_rules = [
# Allow inclusion of specific components that we depend on. We may only
# depend on components which we share with the mojo html_viewer.
"+components/mime_util",
+ "+components/mus/public/interfaces",
"+components/scheduler/common",
"+components/tracing",
"+components/url_formatter",
@@ -20,6 +21,7 @@ include_rules = [
"+mojo",
"+sql",
"+ui/aura_extra",
+ "+ui/views/mus", # http://crbug.com/555767
"+ui/webui",
"+win8/util",
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 8566b99..0747cdb 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -170,6 +170,14 @@
#include "crypto/nss_util.h"
#endif
+#if defined(MOJO_SHELL_CLIENT)
+#include "components/mus/public/interfaces/window_manager.mojom.h"
+#include "content/common/mojo/mojo_shell_connection_impl.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/converters/network/network_type_converters.h"
+#include "ui/views/mus/window_manager_connection.h"
+#endif
+
// One of the linux specific headers defines this as a macro.
#ifdef DestroyAll
#undef DestroyAll
@@ -903,6 +911,21 @@ int BrowserMainLoop::CreateThreads() {
}
int BrowserMainLoop::PreMainMessageLoopRun() {
+#if defined(MOJO_SHELL_CLIENT)
+ if (IsRunningInMojoShell()) {
+ MojoShellConnectionImpl::Create();
+#if defined(USE_AURA)
+ mus::mojom::WindowManagerPtr window_manager;
+ mojo::ApplicationImpl* application =
+ MojoShellConnection::Get()->GetApplication();
+ application->ConnectToService(
+ mojo::URLRequest::From(std::string("mojo:example_wm")),
+ &window_manager);
+ views::WindowManagerConnection::Create(window_manager.Pass(), application);
+#endif
+ }
+#endif
+
if (parts_) {
TRACE_EVENT0("startup",
"BrowserMainLoop::CreateThreads:PreMainMessageLoopRun");
@@ -949,6 +972,9 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
true));
+#if defined(MOJO_SHELL_CLIENT)
+ MojoShellConnection::Destroy();
+#endif
mojo_ipc_support_.reset();
mojo_shell_context_.reset();
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index 53d21fd..830d5b9 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -13,6 +13,7 @@
#include "base/metrics/histogram.h"
#include "base/process/process.h"
#include "base/profiler/scoped_tracker.h"
+#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -47,6 +48,17 @@
#include "gin/v8_initializer.h"
#endif
+#if defined(MOJO_SHELL_CLIENT)
+#include "base/thread_task_runner_handle.h"
+#include "content/public/common/mojo_shell_connection.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/converters/network/network_type_converters.h"
+#include "mojo/shell/application_manager.mojom.h"
+#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
+#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
+#endif
+
namespace content {
namespace {
@@ -321,7 +333,11 @@ void SetProcessBackgroundedOnLauncherThread(base::Process process,
#endif
}
-} // anonymous namespace
+#if defined(MOJO_SHELL_CLIENT)
+void DidCreateChannel(mojo::embedder::ChannelInfo* info) {}
+#endif
+
+} // namespace
ChildProcessLauncher::ChildProcessLauncher(
SandboxedProcessLauncherDelegate* delegate,
@@ -364,6 +380,10 @@ void ChildProcessLauncher::Launch(
int child_process_id) {
DCHECK(CalledOnValidThread());
+#if defined(MOJO_SHELL_CLIENT)
+ CreateMojoShellChannel(cmd_line, child_process_id);
+#endif
+
#if defined(OS_ANDROID)
// Android only supports renderer, sandboxed utility and gpu.
std::string process_type =
@@ -503,6 +523,46 @@ void ChildProcessLauncher::Notify(
}
}
+#if defined(MOJO_SHELL_CLIENT)
+void ChildProcessLauncher::CreateMojoShellChannel(
+ base::CommandLine* command_line,
+ int child_process_id) {
+ // Some process types get created before the main message loop.
+ if (!MojoShellConnection::Get())
+ return;
+
+ // Create the channel to be shared with the target process.
+ mojo::embedder::HandlePassingInformation handle_passing_info;
+ mojo::embedder::PlatformChannelPair platform_channel_pair;
+
+ // Give one end to the shell so that it can create an instance.
+ mojo::embedder::ScopedPlatformHandle platform_channel =
+ platform_channel_pair.PassServerHandle();
+ mojo::ScopedMessagePipeHandle handle(mojo::embedder::CreateChannel(
+ platform_channel.Pass(), base::Bind(&DidCreateChannel),
+ base::ThreadTaskRunnerHandle::Get()));
+ mojo::shell::mojom::ApplicationManagerPtr application_manager;
+ MojoShellConnection::Get()->GetApplication()->ConnectToService(
+ mojo::URLRequest::From(std::string("mojo:shell")),
+ &application_manager);
+ // The content of the URL/qualifier we pass is actually meaningless, it's only
+ // important that they're unique per process.
+ // TODO(beng): We need to specify a restrictive CapabilityFilter here that
+ // matches the needs of the target process. Figure out where that
+ // specification is best determined (not here, this is a common
+ // chokepoint for all process types) and how to wire it through.
+ // http://crbug.com/555393
+ application_manager->CreateInstanceForHandle(
+ mojo::ScopedHandle(mojo::Handle(handle.release().value())),
+ "exe:chrome_renderer", // See above about how this string is meaningless.
+ base::IntToString(child_process_id));
+
+ // Put the other end on the command line used to launch the target.
+ platform_channel_pair.PrepareToPassClientHandleToChildProcess(
+ command_line, &handle_passing_info);
+}
+#endif // defined(MOJO_SHELL_CLIENT)
+
bool ChildProcessLauncher::IsStarting() {
// TODO(crbug.com/469248): This fails in some tests.
// DCHECK(CalledOnValidThread());
diff --git a/content/browser/child_process_launcher.h b/content/browser/child_process_launcher.h
index 2d647f4..768367d 100644
--- a/content/browser/child_process_launcher.h
+++ b/content/browser/child_process_launcher.h
@@ -107,6 +107,15 @@ class CONTENT_EXPORT ChildProcessLauncher : public base::NonThreadSafe {
#endif
base::Process process);
+#if defined(MOJO_SHELL_CLIENT)
+ // When this process is run from an external Mojo shell, this function will
+ // create a channel and pass one end to the spawned process and register the
+ // other end with the external shell, allowing the spawned process to bind an
+ // Application request from the shell.
+ void CreateMojoShellChannel(base::CommandLine* command_line,
+ int child_process_id);
+#endif
+
Client* client_;
BrowserThread::ID client_thread_id_;
base::Process process_;
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 2b9778b..fbe711a 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -133,6 +133,13 @@ source_set("common") {
".",
"//content")
+ # These files are only built in a GN build because they bring in
+ # dependencies that don't build with GYP.
+ sources += [
+ "mojo/mojo_shell_connection_impl.cc",
+ "mojo/mojo_shell_connection_impl.h",
+ ]
+
configs += [
"//content:content_implementation",
"//build/config:precompiled_headers",
@@ -146,10 +153,14 @@ source_set("common") {
deps = [
"//base",
"//build/util:webkit_version",
+ "//components/mus/public/interfaces",
"//components/tracing",
"//components/tracing:startup_tracing",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/common:gles2_utils",
+ "//mojo/application/public/cpp",
+ "//mojo/converters/network",
+ "//mojo/runner/child:lib",
"//net",
"//skia",
"//third_party/icu",
@@ -197,7 +208,7 @@ source_set("common") {
]
}
- defines = []
+ defines = [ "MOJO_SHELL_CLIENT" ]
include_dirs = []
libs = []
ldflags = []
diff --git a/content/common/mojo/DEPS b/content/common/mojo/DEPS
index c6b0111..a8c7fc4 100644
--- a/content/common/mojo/DEPS
+++ b/content/common/mojo/DEPS
@@ -1,3 +1,6 @@
include_rules = [
+ "+mojo/application/public/cpp",
"+mojo/application/public/interfaces",
+ "+mojo/converters/network",
+ "+mojo/runner/child",
]
diff --git a/content/common/mojo/mojo_shell_connection_impl.cc b/content/common/mojo/mojo_shell_connection_impl.cc
new file mode 100644
index 0000000..5125df3
--- /dev/null
+++ b/content/common/mojo/mojo_shell_connection_impl.cc
@@ -0,0 +1,95 @@
+// 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.
+
+#include "content/common/mojo/mojo_shell_connection_impl.h"
+
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/threading/thread_local.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/converters/network/network_type_converters.h"
+#include "mojo/runner/child/runner_connection.h"
+
+namespace content {
+namespace {
+using MojoShellConnectionPtr =
+ base::ThreadLocalPointer<MojoShellConnectionImpl>;
+
+// Env is thread local so that aura may be used on multiple threads.
+base::LazyInstance<MojoShellConnectionPtr>::Leaky lazy_tls_ptr =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+bool IsRunningInMojoShell() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ "mojo-platform-channel-handle");
+}
+
+// static
+void MojoShellConnectionImpl::Create() {
+ DCHECK(IsRunningInMojoShell());
+ DCHECK(!lazy_tls_ptr.Pointer()->Get());
+ MojoShellConnectionImpl* connection = new MojoShellConnectionImpl;
+ lazy_tls_ptr.Pointer()->Set(connection);
+ connection->WaitForShell();
+}
+
+MojoShellConnectionImpl::MojoShellConnectionImpl() : initialized_(false) {}
+MojoShellConnectionImpl::~MojoShellConnectionImpl() {}
+
+void MojoShellConnectionImpl::WaitForShell() {
+ mojo::InterfaceRequest<mojo::Application> application_request;
+ runner_connection_.reset(
+ mojo::runner::RunnerConnection::ConnectToRunner(&application_request));
+ application_impl_.reset(new mojo::ApplicationImpl(
+ this, application_request.Pass()));
+ application_impl_->WaitForInitialize();
+}
+
+void MojoShellConnectionImpl::Initialize(mojo::ApplicationImpl* application) {
+ initialized_ = true;
+}
+
+bool MojoShellConnectionImpl::ConfigureIncomingConnection(
+ mojo::ApplicationConnection* connection) {
+ bool found = false;
+ for (auto listener : listeners_)
+ found |= listener->ConfigureIncomingConnection(connection);
+ return found;
+}
+
+mojo::ApplicationImpl* MojoShellConnectionImpl::GetApplication() {
+ DCHECK(initialized_);
+ return application_impl_.get();
+}
+
+void MojoShellConnectionImpl::AddListener(Listener* listener) {
+ DCHECK(std::find(listeners_.begin(), listeners_.end(), listener) ==
+ listeners_.end());
+ listeners_.push_back(listener);
+}
+
+void MojoShellConnectionImpl::RemoveListener(Listener* listener) {
+ auto it = std::find(listeners_.begin(), listeners_.end(), listener);
+ DCHECK(it != listeners_.end());
+ listeners_.erase(it);
+}
+
+// static
+MojoShellConnection* MojoShellConnection::Get() {
+ return lazy_tls_ptr.Pointer()->Get();
+}
+
+// static
+void MojoShellConnection::Destroy() {
+ // This joins the shell controller thread.
+ delete Get();
+ lazy_tls_ptr.Pointer()->Set(nullptr);
+}
+
+MojoShellConnection::~MojoShellConnection() {}
+
+} // namespace content
diff --git a/content/common/mojo/mojo_shell_connection_impl.h b/content/common/mojo/mojo_shell_connection_impl.h
new file mode 100644
index 0000000..484e2ab7
--- /dev/null
+++ b/content/common/mojo/mojo_shell_connection_impl.h
@@ -0,0 +1,65 @@
+// 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 CONTENT_COMMON_MOJO_SHELL_CONNECTION_IMPL_H_
+#define CONTENT_COMMON_MOJO_SHELL_CONNECTION_IMPL_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/common/mojo_shell_connection.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+
+namespace mojo {
+namespace runner {
+class RunnerConnection;
+}
+}
+
+namespace content {
+
+// Returns true if the Chrome browser process was launched from the external
+// Mojo shell.
+bool IsRunningInMojoShell();
+
+class MojoShellConnectionImpl : public MojoShellConnection,
+ public mojo::ApplicationDelegate {
+ public:
+ // Creates an instance of this class and stuffs it in TLS on the calling
+ // thread. Retrieve it using MojoShellConnection::Get(). Blocks the calling
+ // thread until calling GetApplication() will return an Initialized()
+ // application with a bound ShellPtr.
+ static void Create();
+
+ private:
+ MojoShellConnectionImpl();
+ ~MojoShellConnectionImpl() override;
+
+ // mojo::ApplicationDelegate:
+ void Initialize(mojo::ApplicationImpl* application) override;
+ bool ConfigureIncomingConnection(
+ mojo::ApplicationConnection* connection) override;
+
+ // MojoShellConnection:
+ mojo::ApplicationImpl* GetApplication() override;
+ void AddListener(Listener* listener) override;
+ void RemoveListener(Listener* listener) override;
+
+ // Blocks the calling thread until a connection to the spawning shell is
+ // established, an Application request from it is bound, and the Initialize()
+ // method on that application is called.
+ void WaitForShell();
+
+ bool initialized_;
+ scoped_ptr<mojo::runner::RunnerConnection> runner_connection_;
+ scoped_ptr<mojo::ApplicationImpl> application_impl_;
+ std::vector<Listener*> listeners_;
+
+ DISALLOW_COPY_AND_ASSIGN(MojoShellConnectionImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_MOJO_SHELL_CONNECTION_IMPL_H_
diff --git a/content/content_common.gypi b/content/content_common.gypi
index f9236da..7a04d5e 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -91,6 +91,7 @@
'public/common/message_port_types.h',
'public/common/mojo_channel_switches.cc',
'public/common/mojo_channel_switches.h',
+ 'public/common/mojo_shell_connection.h',
'public/common/navigator_connect_client.cc',
'public/common/navigator_connect_client.h',
'public/common/origin_util.h',
diff --git a/content/public/common/mojo_shell_connection.h b/content/public/common/mojo_shell_connection.h
new file mode 100644
index 0000000..af4cce1
--- /dev/null
+++ b/content/public/common/mojo_shell_connection.h
@@ -0,0 +1,59 @@
+// 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 CONTENT_PUBLIC_COMMON_MOJO_SHELL_CONNECTION_H_
+#define CONTENT_PUBLIC_COMMON_MOJO_SHELL_CONNECTION_H_
+
+#include "content/common/content_export.h"
+
+namespace mojo {
+class ApplicationConnection;
+class ApplicationImpl;
+}
+
+namespace content {
+
+// Encapsulates a connection to a spawning external Mojo shell.
+// Access an instance by calling Get(), on the thread the Shell connection is
+// bound. Clients can implement Listener, which allows them to register services
+// to expose to inbound connections. Clients should call this any time after
+// the main message loop is created but not yet run (e.g. in the browser process
+// this object is created in PreMainMessageLoopRun(), so the BrowserMainParts
+// impl can access this in its implementation of that same method.
+class CONTENT_EXPORT MojoShellConnection {
+ public:
+ // Override to add additional services to inbound connections.
+ class Listener {
+ public:
+ virtual bool ConfigureIncomingConnection(
+ mojo::ApplicationConnection* connection) = 0;
+
+ protected:
+ virtual ~Listener() {}
+ };
+
+ // Will return null if no connection has been established (either because it
+ // hasn't happened yet or the application was not spawned from the external
+ // Mojo shell.
+ static MojoShellConnection* Get();
+
+ // Destroys the connection. Must be called on the thread the connection was
+ // created on.
+ static void Destroy();
+
+ // Returns an Initialized() ApplicationImpl.
+ virtual mojo::ApplicationImpl* GetApplication() = 0;
+
+ // [De]Register an impl of Listener that will be consulted when the wrapped
+ // ApplicationImpl exposes services to inbound connections.
+ virtual void AddListener(Listener* listener) = 0;
+ virtual void RemoveListener(Listener* listener) = 0;
+
+ protected:
+ virtual ~MojoShellConnection();
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_MOJO_SHELL_CONNECTION_H_