Roll src/third_party/WebKit f298044:aa8346d (svn 202628:202629)
[chromium-blink-merge.git] / content / browser / mojo / mojo_shell_context.cc
blob45d22736742fe971715d74a4394e3d77398cc440
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/mojo/mojo_shell_context.h"
7 #include "base/lazy_instance.h"
8 #include "base/macros.h"
9 #include "base/path_service.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/common/process_control.mojom.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/content_browser_client.h"
15 #include "content/public/browser/utility_process_host.h"
16 #include "content/public/browser/utility_process_host_client.h"
17 #include "content/public/common/content_client.h"
18 #include "content/public/common/service_registry.h"
19 #include "mojo/application/public/cpp/application_delegate.h"
20 #include "mojo/common/url_type_converters.h"
21 #include "mojo/package_manager/package_manager_impl.h"
22 #include "mojo/shell/application_loader.h"
23 #include "mojo/shell/connect_to_application_params.h"
24 #include "mojo/shell/identity.h"
25 #include "mojo/shell/static_application_loader.h"
26 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
27 #include "third_party/mojo/src/mojo/public/cpp/bindings/string.h"
29 #if defined(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
30 #include "media/mojo/services/mojo_media_application.h"
31 #endif
33 namespace content {
35 namespace {
37 // An extra set of apps to register on initialization, if set by a test.
38 const MojoShellContext::StaticApplicationMap* g_applications_for_test;
40 void StartProcessOnIOThread(mojo::InterfaceRequest<ProcessControl> request,
41 const base::string16& process_name,
42 bool use_sandbox) {
43 UtilityProcessHost* process_host =
44 UtilityProcessHost::Create(nullptr, nullptr);
45 process_host->SetName(process_name);
46 if (!use_sandbox)
47 process_host->DisableSandbox();
48 process_host->StartMojoMode();
50 ServiceRegistry* services = process_host->GetServiceRegistry();
51 services->ConnectToRemoteService(request.Pass());
54 void OnApplicationLoaded(const GURL& url, bool success) {
55 if (!success)
56 LOG(ERROR) << "Failed to launch Mojo application for " << url.spec();
59 // The default loader to use for all applications. This does nothing but drop
60 // the Application request.
61 class DefaultApplicationLoader : public mojo::shell::ApplicationLoader {
62 public:
63 DefaultApplicationLoader() {}
64 ~DefaultApplicationLoader() override {}
66 private:
67 // mojo::shell::ApplicationLoader:
68 void Load(
69 const GURL& url,
70 mojo::InterfaceRequest<mojo::Application> application_request) override {}
72 DISALLOW_COPY_AND_ASSIGN(DefaultApplicationLoader);
75 // This launches a utility process and forwards the Load request the
76 // ProcessControl service there. The utility process is sandboxed iff
77 // |use_sandbox| is true.
78 class UtilityProcessLoader : public mojo::shell::ApplicationLoader {
79 public:
80 UtilityProcessLoader(const base::string16& process_name, bool use_sandbox)
81 : process_name_(process_name), use_sandbox_(use_sandbox) {}
82 ~UtilityProcessLoader() override {}
84 private:
85 // mojo::shell::ApplicationLoader:
86 void Load(
87 const GURL& url,
88 mojo::InterfaceRequest<mojo::Application> application_request) override {
89 ProcessControlPtr process_control;
90 auto process_request = mojo::GetProxy(&process_control);
91 BrowserThread::PostTask(
92 BrowserThread::IO, FROM_HERE,
93 base::Bind(&StartProcessOnIOThread, base::Passed(&process_request),
94 process_name_, use_sandbox_));
95 process_control->LoadApplication(url.spec(), application_request.Pass(),
96 base::Bind(&OnApplicationLoaded, url));
99 const base::string16 process_name_;
100 const bool use_sandbox_;
102 DISALLOW_COPY_AND_ASSIGN(UtilityProcessLoader);
105 } // namespace
107 // Thread-safe proxy providing access to the shell context from any thread.
108 class MojoShellContext::Proxy {
109 public:
110 Proxy(MojoShellContext* shell_context)
111 : shell_context_(shell_context),
112 task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
114 ~Proxy() {}
116 void ConnectToApplication(
117 const GURL& url,
118 const GURL& requestor_url,
119 mojo::InterfaceRequest<mojo::ServiceProvider> request,
120 mojo::ServiceProviderPtr exposed_services,
121 const mojo::shell::CapabilityFilter& filter,
122 const mojo::Shell::ConnectToApplicationCallback& callback) {
123 if (task_runner_ == base::ThreadTaskRunnerHandle::Get()) {
124 if (shell_context_) {
125 shell_context_->ConnectToApplicationOnOwnThread(
126 url, requestor_url, request.Pass(), exposed_services.Pass(), filter,
127 callback);
129 } else {
130 // |shell_context_| outlives the main MessageLoop, so it's safe for it to
131 // be unretained here.
132 task_runner_->PostTask(
133 FROM_HERE,
134 base::Bind(&MojoShellContext::ConnectToApplicationOnOwnThread,
135 base::Unretained(shell_context_), url, requestor_url,
136 base::Passed(&request), base::Passed(&exposed_services),
137 filter, callback));
141 private:
142 MojoShellContext* shell_context_;
143 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
145 DISALLOW_COPY_AND_ASSIGN(Proxy);
148 // static
149 base::LazyInstance<scoped_ptr<MojoShellContext::Proxy>>
150 MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER;
152 void MojoShellContext::SetApplicationsForTest(
153 const StaticApplicationMap* apps) {
154 g_applications_for_test = apps;
157 MojoShellContext::MojoShellContext() {
158 proxy_.Get().reset(new Proxy(this));
160 // Construct with an empty filepath since mojo: urls can't be registered now
161 // the url scheme registry is locked.
162 scoped_ptr<mojo::package_manager::PackageManagerImpl> package_manager(
163 new mojo::package_manager::PackageManagerImpl(base::FilePath()));
164 application_manager_.reset(
165 new mojo::shell::ApplicationManager(package_manager.Pass()));
167 application_manager_->set_default_loader(
168 scoped_ptr<mojo::shell::ApplicationLoader>(new DefaultApplicationLoader));
170 StaticApplicationMap apps;
171 GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps);
172 if (g_applications_for_test) {
173 // Add testing apps to the map, potentially overwriting whatever the
174 // browser client registered.
175 for (const auto& entry : *g_applications_for_test)
176 apps[entry.first] = entry.second;
178 for (const auto& entry : apps) {
179 application_manager_->SetLoaderForURL(
180 scoped_ptr<mojo::shell::ApplicationLoader>(
181 new mojo::shell::StaticApplicationLoader(entry.second)),
182 entry.first);
185 ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps;
186 GetContentClient()
187 ->browser()
188 ->RegisterOutOfProcessMojoApplications(&sandboxed_apps);
189 for (const auto& app : sandboxed_apps) {
190 application_manager_->SetLoaderForURL(
191 scoped_ptr<mojo::shell::ApplicationLoader>(
192 new UtilityProcessLoader(app.second, true /* use_sandbox */)),
193 app.first);
196 ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps;
197 GetContentClient()
198 ->browser()
199 ->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps);
200 for (const auto& app : unsandboxed_apps) {
201 application_manager_->SetLoaderForURL(
202 scoped_ptr<mojo::shell::ApplicationLoader>(
203 new UtilityProcessLoader(app.second, false /* use_sandbox */)),
204 app.first);
207 #if (ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
208 application_manager_->SetLoaderForURL(
209 scoped_ptr<mojo::shell::ApplicationLoader>(
210 new mojo::shell::StaticApplicationLoader(
211 base::Bind(&media::MojoMediaApplication::CreateApp))),
212 media::MojoMediaApplication::AppUrl());
213 #endif
216 MojoShellContext::~MojoShellContext() {
219 // static
220 void MojoShellContext::ConnectToApplication(
221 const GURL& url,
222 const GURL& requestor_url,
223 mojo::InterfaceRequest<mojo::ServiceProvider> request,
224 mojo::ServiceProviderPtr exposed_services,
225 const mojo::shell::CapabilityFilter& filter,
226 const mojo::Shell::ConnectToApplicationCallback& callback) {
227 proxy_.Get()->ConnectToApplication(url, requestor_url, request.Pass(),
228 exposed_services.Pass(), filter, callback);
231 void MojoShellContext::ConnectToApplicationOnOwnThread(
232 const GURL& url,
233 const GURL& requestor_url,
234 mojo::InterfaceRequest<mojo::ServiceProvider> request,
235 mojo::ServiceProviderPtr exposed_services,
236 const mojo::shell::CapabilityFilter& filter,
237 const mojo::Shell::ConnectToApplicationCallback& callback) {
238 scoped_ptr<mojo::shell::ConnectToApplicationParams> params(
239 new mojo::shell::ConnectToApplicationParams);
240 params->set_originator_identity(mojo::shell::Identity(requestor_url));
241 params->set_originator_filter(mojo::shell::GetPermissiveCapabilityFilter());
242 params->SetURLInfo(url);
243 params->set_services(request.Pass());
244 params->set_exposed_services(exposed_services.Pass());
245 params->set_filter(filter);
246 params->set_on_application_end(base::Bind(&base::DoNothing));
247 params->set_connect_callback(callback);
248 application_manager_->ConnectToApplication(params.Pass());
251 } // namespace content