summaryrefslogtreecommitdiffstats
path: root/content/browser/mojo
diff options
context:
space:
mode:
authorrockot <rockot@chromium.org>2015-06-04 17:30:52 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-05 00:32:18 +0000
commitb814a5850da5aa473ad526eef4b41a82b05037a0 (patch)
treed1730ed4fccfc7fda63bd51f30891a95e61ba915 /content/browser/mojo
parent87c39e56c03c089751e4ae22dcea9ca7cf17c741 (diff)
downloadchromium_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.cc28
-rw-r--r--content/browser/mojo/mojo_app_connection_impl.h34
-rw-r--r--content/browser/mojo/mojo_shell_context.cc178
-rw-r--r--content/browser/mojo/mojo_shell_context.h70
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_