diff options
author | rockot <rockot@chromium.org> | 2015-06-04 17:30:52 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-05 00:32:18 +0000 |
commit | b814a5850da5aa473ad526eef4b41a82b05037a0 (patch) | |
tree | d1730ed4fccfc7fda63bd51f30891a95e61ba915 /content/browser/mojo | |
parent | 87c39e56c03c089751e4ae22dcea9ca7cf17c741 (diff) | |
download | chromium_src-b814a5850da5aa473ad526eef4b41a82b05037a0.zip chromium_src-b814a5850da5aa473ad526eef4b41a82b05037a0.tar.gz chromium_src-b814a5850da5aa473ad526eef4b41a82b05037a0.tar.bz2 |
Embed a mojo ApplicationManager in content/browser
This embeds mojo/shell's ApplicationManager in content/browser
and provides a way for arbitrary browser code to connect to
Mojo apps as if the browser itself were a Mojo app.
This is a basic implementation of Mojo app support which only
loads static apps either in the browser process or a (per-app)
utility process.
Future CLs will address connection to apps from arbitrary render
frames (i.e. connection requests which include the requestor's
origin) as well as refactoring the utility process code further
so that it serves strictly as a Mojo app runner.
BUG=492422
Review URL: https://codereview.chromium.org/1149833007
Cr-Commit-Position: refs/heads/master@{#332974}
Diffstat (limited to 'content/browser/mojo')
-rw-r--r-- | content/browser/mojo/mojo_app_connection_impl.cc | 28 | ||||
-rw-r--r-- | content/browser/mojo/mojo_app_connection_impl.h | 34 | ||||
-rw-r--r-- | content/browser/mojo/mojo_shell_context.cc | 178 | ||||
-rw-r--r-- | content/browser/mojo/mojo_shell_context.h | 70 |
4 files changed, 310 insertions, 0 deletions
diff --git a/content/browser/mojo/mojo_app_connection_impl.cc b/content/browser/mojo/mojo_app_connection_impl.cc new file mode 100644 index 0000000..d643bbf --- /dev/null +++ b/content/browser/mojo/mojo_app_connection_impl.cc @@ -0,0 +1,28 @@ +// 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/browser/mojo/mojo_app_connection_impl.h" + +#include "content/browser/mojo/mojo_shell_context.h" + +namespace content { + +scoped_ptr<MojoAppConnection> MojoAppConnection::Create(const GURL& url) { + return scoped_ptr<MojoAppConnection>(new MojoAppConnectionImpl(url)); +} + +MojoAppConnectionImpl::MojoAppConnectionImpl(const GURL& url) { + MojoShellContext::ConnectToApplication(url, mojo::GetProxy(&services_)); +} + +MojoAppConnectionImpl::~MojoAppConnectionImpl() { +} + +void MojoAppConnectionImpl::ConnectToService( + const std::string& service_name, + mojo::ScopedMessagePipeHandle handle) { + services_->ConnectToService(service_name, handle.Pass()); +} + +} // namespace content diff --git a/content/browser/mojo/mojo_app_connection_impl.h b/content/browser/mojo/mojo_app_connection_impl.h new file mode 100644 index 0000000..4628acc --- /dev/null +++ b/content/browser/mojo/mojo_app_connection_impl.h @@ -0,0 +1,34 @@ +// 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_BROWSER_MOJO_MOJO_APP_CONNECTION_IMPL_H_ +#define CONTENT_BROWSER_MOJO_MOJO_APP_CONNECTION_IMPL_H_ + +#include "base/macros.h" +#include "content/public/browser/mojo_app_connection.h" +#include "mojo/application/public/interfaces/service_provider.mojom.h" + +class GURL; + +namespace content { + +// Implementation of the app connection mechanism provided to browser code. +class MojoAppConnectionImpl : public MojoAppConnection { + public: + explicit MojoAppConnectionImpl(const GURL& url); + ~MojoAppConnectionImpl() override; + + private: + // MojoAppConnection: + void ConnectToService(const std::string& service_name, + mojo::ScopedMessagePipeHandle handle) override; + + mojo::ServiceProviderPtr services_; + + DISALLOW_COPY_AND_ASSIGN(MojoAppConnectionImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_MOJO_MOJO_APP_CONNECTION_IMPL_H_ diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc new file mode 100644 index 0000000..49e66a9 --- /dev/null +++ b/content/browser/mojo/mojo_shell_context.cc @@ -0,0 +1,178 @@ +// 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/browser/mojo/mojo_shell_context.h" + +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "base/single_thread_task_runner.h" +#include "base/strings/utf_string_conversions.h" +#include "base/thread_task_runner_handle.h" +#include "content/common/process_control.mojom.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/utility_process_host.h" +#include "content/public/browser/utility_process_host_client.h" +#include "content/public/common/content_client.h" +#include "content/public/common/service_registry.h" +#include "mojo/application/public/cpp/application_delegate.h" +#include "mojo/common/url_type_converters.h" +#include "mojo/services/network/public/interfaces/url_loader.mojom.h" +#include "mojo/shell/application_loader.h" +#include "mojo/shell/static_application_loader.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/string.h" + +namespace content { + +namespace { + +// Virtual app URL to use as the requestor identity when connecting from browser +// code to a Mojo app via the shell proxy. +const char kBrowserAppUrl[] = "system:content_browser"; + +// An extra set of apps to register on initialization, if set by a test. +const MojoShellContext::StaticApplicationMap* g_applications_for_test; + +void StartProcessOnIOThread(mojo::InterfaceRequest<ProcessControl> request) { + UtilityProcessHost* process_host = + UtilityProcessHost::Create(nullptr, nullptr); + // TODO(rockot): Make it possible for the embedder to associate app URLs with + // app names so we can have more meaningful process names here. + process_host->SetName(base::UTF8ToUTF16("Mojo Application")); + process_host->StartMojoMode(); + ServiceRegistry* services = process_host->GetServiceRegistry(); + services->ConnectToRemoteService(request.Pass()); +} + +void OnApplicationLoaded(const GURL& url, bool success) { + if (!success) + LOG(ERROR) << "Failed to launch Mojo application for " << url.spec(); +} + +// The default loader to use for all applications. This launches a utility +// process and forwards the Load request the ProcessControl service there. +class UtilityProcessLoader : public mojo::shell::ApplicationLoader { + public: + UtilityProcessLoader() {} + ~UtilityProcessLoader() override {} + + private: + // mojo::shell::ApplicationLoader: + void Load( + const GURL& url, + mojo::InterfaceRequest<mojo::Application> application_request) override { + ProcessControlPtr process_control; + auto process_request = mojo::GetProxy(&process_control); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&StartProcessOnIOThread, base::Passed(&process_request))); + process_control->LoadApplication(url.spec(), application_request.Pass(), + base::Bind(&OnApplicationLoaded, url)); + } + + DISALLOW_COPY_AND_ASSIGN(UtilityProcessLoader); +}; + +} // namespace + +// Thread-safe proxy providing access to the shell context from any thread. +class MojoShellContext::Proxy { + public: + Proxy(MojoShellContext* shell_context) + : shell_context_(shell_context), + task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + + ~Proxy() {} + + void ConnectToApplication( + const GURL& url, + mojo::InterfaceRequest<mojo::ServiceProvider> request) { + if (task_runner_ == base::ThreadTaskRunnerHandle::Get()) { + if (shell_context_) + shell_context_->ConnectToApplicationOnOwnThread(url, request.Pass()); + } else { + // |shell_context_| outlives the main MessageLoop, so it's safe for it to + // be unretained here. + task_runner_->PostTask( + FROM_HERE, + base::Bind(&MojoShellContext::ConnectToApplicationOnOwnThread, + base::Unretained(shell_context_), url, + base::Passed(&request))); + } + } + + private: + MojoShellContext* shell_context_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + + DISALLOW_COPY_AND_ASSIGN(Proxy); +}; + +// static +base::LazyInstance<scoped_ptr<MojoShellContext::Proxy>> + MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER; + +void MojoShellContext::SetApplicationsForTest( + const StaticApplicationMap* apps) { + g_applications_for_test = apps; +} + +MojoShellContext::MojoShellContext() + : application_manager_(new mojo::shell::ApplicationManager(this)) { + proxy_.Get().reset(new Proxy(this)); + application_manager_->set_default_loader( + scoped_ptr<mojo::shell::ApplicationLoader>(new UtilityProcessLoader)); + + StaticApplicationMap apps; + GetContentClient()->browser()->RegisterMojoApplications(&apps); + if (g_applications_for_test) { + // Add testing apps to the map, potentially overwriting whatever the + // browser client registered. + for (const auto& entry : *g_applications_for_test) + apps[entry.first] = entry.second; + } + for (const auto& entry : apps) { + application_manager_->SetLoaderForURL( + scoped_ptr<mojo::shell::ApplicationLoader>( + new mojo::shell::StaticApplicationLoader(entry.second)), + entry.first); + } +} + +MojoShellContext::~MojoShellContext() { +} + +// static +void MojoShellContext::ConnectToApplication( + const GURL& url, + mojo::InterfaceRequest<mojo::ServiceProvider> request) { + proxy_.Get()->ConnectToApplication(url, request.Pass()); +} + +void MojoShellContext::ConnectToApplicationOnOwnThread( + const GURL& url, + mojo::InterfaceRequest<mojo::ServiceProvider> request) { + mojo::URLRequestPtr url_request = mojo::URLRequest::New(); + url_request->url = mojo::String::From(url); + application_manager_->ConnectToApplication( + url_request.Pass(), GURL(kBrowserAppUrl), request.Pass(), + mojo::ServiceProviderPtr(), base::Bind(&base::DoNothing)); +} + +GURL MojoShellContext::ResolveMappings(const GURL& url) { + return url; +} + +GURL MojoShellContext::ResolveMojoURL(const GURL& url) { + return url; +} + +bool MojoShellContext::CreateFetcher( + const GURL& url, + const mojo::shell::Fetcher::FetchCallback& loader_callback) { + return false; +} + +} // namespace content diff --git a/content/browser/mojo/mojo_shell_context.h b/content/browser/mojo/mojo_shell_context.h new file mode 100644 index 0000000..b0ac5b1 --- /dev/null +++ b/content/browser/mojo/mojo_shell_context.h @@ -0,0 +1,70 @@ +// 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_BROWSER_MOJO_MOJO_SHELL_CONTEXT_H_ +#define CONTENT_BROWSER_MOJO_MOJO_SHELL_CONTEXT_H_ + +#include <map> + +#include "base/callback_forward.h" +#include "base/compiler_specific.h" +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "content/common/content_export.h" +#include "mojo/shell/application_manager.h" + +class GURL; + +namespace mojo { +class ApplicationDelegate; +} + +namespace content { + +// MojoShellContext hosts the browser's ApplicationManager, coordinating +// app registration and interconnection. +class CONTENT_EXPORT MojoShellContext + : public NON_EXPORTED_BASE(mojo::shell::ApplicationManager::Delegate) { + public: + using StaticApplicationMap = + std::map<GURL, base::Callback<scoped_ptr<mojo::ApplicationDelegate>()>>; + + MojoShellContext(); + ~MojoShellContext() override; + + // Connects an application at |url| and gets a handle to its exposed services. + // This is only intended for use in browser code that's not part of some Mojo + // application. May be called from any thread. + static void ConnectToApplication( + const GURL& url, + mojo::InterfaceRequest<mojo::ServiceProvider> request); + + static void SetApplicationsForTest(const StaticApplicationMap* apps); + + private: + class Proxy; + friend class Proxy; + + void ConnectToApplicationOnOwnThread( + const GURL& url, + mojo::InterfaceRequest<mojo::ServiceProvider> request); + + // mojo::shell::ApplicationManager::Delegate: + GURL ResolveMappings(const GURL& url) override; + GURL ResolveMojoURL(const GURL& url) override; + bool CreateFetcher( + const GURL& url, + const mojo::shell::Fetcher::FetchCallback& loader_callback) override; + + static base::LazyInstance<scoped_ptr<Proxy>> proxy_; + + scoped_ptr<mojo::shell::ApplicationManager> application_manager_; + + DISALLOW_COPY_AND_ASSIGN(MojoShellContext); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_MOJO_MOJO_SHELL_CONTEXT_H_ |