Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / content / browser / mojo / mojo_shell_context.cc
blob2817731da4426a5d1201b013c9091e1ee9c84142
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/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "content/common/process_control.mojom.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/browser/utility_process_host.h"
15 #include "content/public/browser/utility_process_host_client.h"
16 #include "content/public/common/content_client.h"
17 #include "content/public/common/service_registry.h"
18 #include "mojo/application/public/cpp/application_delegate.h"
19 #include "mojo/common/url_type_converters.h"
20 #include "mojo/shell/application_loader.h"
21 #include "mojo/shell/connect_to_application_params.h"
22 #include "mojo/shell/identity.h"
23 #include "mojo/shell/static_application_loader.h"
24 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
25 #include "third_party/mojo/src/mojo/public/cpp/bindings/string.h"
27 #if defined(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
28 #include "media/mojo/services/mojo_media_application.h"
29 #endif
31 namespace content {
33 namespace {
35 // An extra set of apps to register on initialization, if set by a test.
36 const MojoShellContext::StaticApplicationMap* g_applications_for_test;
38 void StartProcessOnIOThread(mojo::InterfaceRequest<ProcessControl> request,
39 const base::string16& process_name,
40 bool use_sandbox) {
41 UtilityProcessHost* process_host =
42 UtilityProcessHost::Create(nullptr, nullptr);
43 process_host->SetName(process_name);
44 if (!use_sandbox)
45 process_host->DisableSandbox();
46 process_host->StartMojoMode();
48 ServiceRegistry* services = process_host->GetServiceRegistry();
49 services->ConnectToRemoteService(request.Pass());
52 void OnApplicationLoaded(const GURL& url, bool success) {
53 if (!success)
54 LOG(ERROR) << "Failed to launch Mojo application for " << url.spec();
57 // The default loader to use for all applications. This does nothing but drop
58 // the Application request.
59 class DefaultApplicationLoader : public mojo::shell::ApplicationLoader {
60 public:
61 DefaultApplicationLoader() {}
62 ~DefaultApplicationLoader() override {}
64 private:
65 // mojo::shell::ApplicationLoader:
66 void Load(
67 const GURL& url,
68 mojo::InterfaceRequest<mojo::Application> application_request) override {}
70 DISALLOW_COPY_AND_ASSIGN(DefaultApplicationLoader);
73 // This launches a utility process and forwards the Load request the
74 // ProcessControl service there. The utility process is sandboxed iff
75 // |use_sandbox| is true.
76 class UtilityProcessLoader : public mojo::shell::ApplicationLoader {
77 public:
78 UtilityProcessLoader(const base::string16& process_name, bool use_sandbox)
79 : process_name_(process_name), use_sandbox_(use_sandbox) {}
80 ~UtilityProcessLoader() override {}
82 private:
83 // mojo::shell::ApplicationLoader:
84 void Load(
85 const GURL& url,
86 mojo::InterfaceRequest<mojo::Application> application_request) override {
87 ProcessControlPtr process_control;
88 auto process_request = mojo::GetProxy(&process_control);
89 BrowserThread::PostTask(
90 BrowserThread::IO, FROM_HERE,
91 base::Bind(&StartProcessOnIOThread, base::Passed(&process_request),
92 process_name_, use_sandbox_));
93 process_control->LoadApplication(url.spec(), application_request.Pass(),
94 base::Bind(&OnApplicationLoaded, url));
97 const base::string16 process_name_;
98 const bool use_sandbox_;
100 DISALLOW_COPY_AND_ASSIGN(UtilityProcessLoader);
103 } // namespace
105 // Thread-safe proxy providing access to the shell context from any thread.
106 class MojoShellContext::Proxy {
107 public:
108 Proxy(MojoShellContext* shell_context)
109 : shell_context_(shell_context),
110 task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
112 ~Proxy() {}
114 void ConnectToApplication(
115 const GURL& url,
116 const GURL& requestor_url,
117 mojo::InterfaceRequest<mojo::ServiceProvider> request,
118 mojo::ServiceProviderPtr exposed_services,
119 const mojo::shell::CapabilityFilter& filter,
120 const mojo::Shell::ConnectToApplicationCallback& callback) {
121 if (task_runner_ == base::ThreadTaskRunnerHandle::Get()) {
122 if (shell_context_) {
123 shell_context_->ConnectToApplicationOnOwnThread(
124 url, requestor_url, request.Pass(), exposed_services.Pass(), filter,
125 callback);
127 } else {
128 // |shell_context_| outlives the main MessageLoop, so it's safe for it to
129 // be unretained here.
130 task_runner_->PostTask(
131 FROM_HERE,
132 base::Bind(&MojoShellContext::ConnectToApplicationOnOwnThread,
133 base::Unretained(shell_context_), url, requestor_url,
134 base::Passed(&request), base::Passed(&exposed_services),
135 filter, callback));
139 private:
140 MojoShellContext* shell_context_;
141 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
143 DISALLOW_COPY_AND_ASSIGN(Proxy);
146 // static
147 base::LazyInstance<scoped_ptr<MojoShellContext::Proxy>>
148 MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER;
150 void MojoShellContext::SetApplicationsForTest(
151 const StaticApplicationMap* apps) {
152 g_applications_for_test = apps;
155 MojoShellContext::MojoShellContext()
156 : application_manager_(new mojo::shell::ApplicationManager(this)) {
157 proxy_.Get().reset(new Proxy(this));
159 application_manager_->set_default_loader(
160 scoped_ptr<mojo::shell::ApplicationLoader>(new DefaultApplicationLoader));
162 StaticApplicationMap apps;
163 GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps);
164 if (g_applications_for_test) {
165 // Add testing apps to the map, potentially overwriting whatever the
166 // browser client registered.
167 for (const auto& entry : *g_applications_for_test)
168 apps[entry.first] = entry.second;
170 for (const auto& entry : apps) {
171 application_manager_->SetLoaderForURL(
172 scoped_ptr<mojo::shell::ApplicationLoader>(
173 new mojo::shell::StaticApplicationLoader(entry.second)),
174 entry.first);
177 ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps;
178 GetContentClient()
179 ->browser()
180 ->RegisterOutOfProcessMojoApplications(&sandboxed_apps);
181 for (const auto& app : sandboxed_apps) {
182 application_manager_->SetLoaderForURL(
183 scoped_ptr<mojo::shell::ApplicationLoader>(
184 new UtilityProcessLoader(app.second, true /* use_sandbox */)),
185 app.first);
188 ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps;
189 GetContentClient()
190 ->browser()
191 ->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps);
192 for (const auto& app : unsandboxed_apps) {
193 application_manager_->SetLoaderForURL(
194 scoped_ptr<mojo::shell::ApplicationLoader>(
195 new UtilityProcessLoader(app.second, false /* use_sandbox */)),
196 app.first);
199 #if (ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
200 application_manager_->SetLoaderForURL(
201 scoped_ptr<mojo::shell::ApplicationLoader>(
202 new mojo::shell::StaticApplicationLoader(
203 base::Bind(&media::MojoMediaApplication::CreateApp))),
204 media::MojoMediaApplication::AppUrl());
205 #endif
208 MojoShellContext::~MojoShellContext() {
211 // static
212 void MojoShellContext::ConnectToApplication(
213 const GURL& url,
214 const GURL& requestor_url,
215 mojo::InterfaceRequest<mojo::ServiceProvider> request,
216 mojo::ServiceProviderPtr exposed_services,
217 const mojo::shell::CapabilityFilter& filter,
218 const mojo::Shell::ConnectToApplicationCallback& callback) {
219 proxy_.Get()->ConnectToApplication(url, requestor_url, request.Pass(),
220 exposed_services.Pass(), filter, callback);
223 void MojoShellContext::ConnectToApplicationOnOwnThread(
224 const GURL& url,
225 const GURL& requestor_url,
226 mojo::InterfaceRequest<mojo::ServiceProvider> request,
227 mojo::ServiceProviderPtr exposed_services,
228 const mojo::shell::CapabilityFilter& filter,
229 const mojo::Shell::ConnectToApplicationCallback& callback) {
230 scoped_ptr<mojo::shell::ConnectToApplicationParams> params(
231 new mojo::shell::ConnectToApplicationParams);
232 params->set_originator_identity(mojo::shell::Identity(requestor_url));
233 params->set_originator_filter(mojo::shell::GetPermissiveCapabilityFilter());
234 params->SetURLInfo(url);
235 params->set_services(request.Pass());
236 params->set_exposed_services(exposed_services.Pass());
237 params->set_filter(filter);
238 params->set_on_application_end(base::Bind(&base::DoNothing));
239 params->set_connect_callback(callback);
240 application_manager_->ConnectToApplication(params.Pass());
243 GURL MojoShellContext::ResolveMappings(const GURL& url) {
244 return url;
247 GURL MojoShellContext::ResolveMojoURL(const GURL& url) {
248 return url;
251 bool MojoShellContext::CreateFetcher(
252 const GURL& url,
253 const mojo::shell::Fetcher::FetchCallback& loader_callback) {
254 return false;
257 } // namespace content