diff options
author | ben <ben@chromium.org> | 2015-11-15 04:13:09 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-15 12:14:44 +0000 |
commit | 03b7b9d5d01d4b23362a1b9fcd13900fbb11286c (patch) | |
tree | 71181e958a9510ce5aa9de3e00c5b9e96b5ca410 /content | |
parent | e9b72dd87754ca5a4af39509070ae682c5e5bc14 (diff) | |
download | chromium_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.gn | 3 | ||||
-rw-r--r-- | content/browser/DEPS | 2 | ||||
-rw-r--r-- | content/browser/browser_main_loop.cc | 26 | ||||
-rw-r--r-- | content/browser/child_process_launcher.cc | 62 | ||||
-rw-r--r-- | content/browser/child_process_launcher.h | 9 | ||||
-rw-r--r-- | content/common/BUILD.gn | 13 | ||||
-rw-r--r-- | content/common/mojo/DEPS | 3 | ||||
-rw-r--r-- | content/common/mojo/mojo_shell_connection_impl.cc | 95 | ||||
-rw-r--r-- | content/common/mojo/mojo_shell_connection_impl.h | 65 | ||||
-rw-r--r-- | content/content_common.gypi | 1 | ||||
-rw-r--r-- | content/public/common/mojo_shell_connection.h | 59 |
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_ |