Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(313)

Side by Side Diff: content/browser/mojo/mojo_shell_context.cc

Issue 2163883005: WIP: Obtain Bootstrap from utility process Service (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "content/browser/mojo/mojo_shell_context.h"
6
7 #include <unordered_map>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/lazy_instance.h"
13 #include "base/macros.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/path_service.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "content/browser/gpu/gpu_process_host.h"
19 #include "content/browser/mojo/constants.h"
20 #include "content/common/gpu_process_launch_causes.h"
21 #include "content/common/mojo/mojo_shell_connection_impl.h"
22 #include "content/common/process_control.mojom.h"
23 #include "content/grit/content_resources.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/content_browser_client.h"
26 #include "content/public/browser/utility_process_host.h"
27 #include "content/public/browser/utility_process_host_client.h"
28 #include "content/public/common/content_client.h"
29 #include "content/public/common/content_switches.h"
30 #include "mojo/edk/embedder/embedder.h"
31 #include "mojo/public/cpp/bindings/interface_request.h"
32 #include "mojo/public/cpp/bindings/string.h"
33 #include "services/catalog/catalog.h"
34 #include "services/catalog/manifest_provider.h"
35 #include "services/catalog/store.h"
36 #include "services/shell/connect_params.h"
37 #include "services/shell/native_runner.h"
38 #include "services/shell/public/cpp/connector.h"
39 #include "services/shell/public/cpp/identity.h"
40 #include "services/shell/public/cpp/service.h"
41 #include "services/shell/public/interfaces/connector.mojom.h"
42 #include "services/shell/public/interfaces/service.mojom.h"
43 #include "services/shell/public/interfaces/service_factory.mojom.h"
44 #include "services/shell/runner/common/client_util.h"
45 #include "services/shell/runner/host/in_process_native_runner.h"
46 #include "services/user/public/cpp/constants.h"
47
48 namespace content {
49
50 namespace {
51
52 base::LazyInstance<std::unique_ptr<shell::Connector>>::Leaky
53 g_io_thread_connector = LAZY_INSTANCE_INITIALIZER;
54
55 void DestroyConnectorOnIOThread() { g_io_thread_connector.Get().reset(); }
56
57 void StartUtilityProcessOnIOThread(
58 mojo::InterfaceRequest<mojom::ProcessControl> request,
59 const base::string16& process_name,
60 bool use_sandbox) {
61 UtilityProcessHost* process_host =
62 UtilityProcessHost::Create(nullptr, nullptr);
63 process_host->SetName(process_name);
64 if (!use_sandbox)
65 process_host->DisableSandbox();
66 process_host->Start();
67
68 process_host->GetRemoteInterfaces()->GetInterface(std::move(request));
69 }
70
71 void OnApplicationLoaded(const std::string& name, bool success) {
72 if (!success)
73 LOG(ERROR) << "Failed to launch Mojo application for " << name;
74 }
75
76 void LaunchAppInUtilityProcess(const std::string& app_name,
77 const base::string16& process_name,
78 bool use_sandbox,
79 shell::mojom::ServiceRequest request) {
80 mojom::ProcessControlPtr process_control;
81 mojom::ProcessControlRequest process_request =
82 mojo::GetProxy(&process_control);
83 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
84 base::Bind(&StartUtilityProcessOnIOThread,
85 base::Passed(&process_request),
86 process_name, use_sandbox));
87 process_control->LoadApplication(app_name, std::move(request),
88 base::Bind(&OnApplicationLoaded, app_name));
89 }
90
91 #if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
92
93 // Request mojom::ProcessControl from GPU process host. Must be called on IO
94 // thread.
95 void RequestGpuProcessControl(
96 mojo::InterfaceRequest<mojom::ProcessControl> request) {
97 BrowserChildProcessHostDelegate* process_host =
98 GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
99 CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP);
100 if (!process_host) {
101 DLOG(ERROR) << "GPU process host not available.";
102 return;
103 }
104
105 // TODO(xhwang): It's possible that |process_host| is non-null, but the actual
106 // process is dead. In that case, |request| will be dropped and application
107 // load requests through mojom::ProcessControl will also fail. Make sure we
108 // handle
109 // these cases correctly.
110 process_host->GetRemoteInterfaces()->GetInterface(std::move(request));
111 }
112
113 void LaunchAppInGpuProcess(const std::string& app_name,
114 shell::mojom::ServiceRequest request) {
115 mojom::ProcessControlPtr process_control;
116 mojom::ProcessControlRequest process_request =
117 mojo::GetProxy(&process_control);
118 BrowserThread::PostTask(
119 BrowserThread::IO, FROM_HERE,
120 base::Bind(&RequestGpuProcessControl, base::Passed(&process_request)));
121 process_control->LoadApplication(app_name, std::move(request),
122 base::Bind(&OnApplicationLoaded, app_name));
123 }
124
125 #endif // ENABLE_MOJO_MEDIA_IN_GPU_PROCESS
126
127 } // namespace
128
129 // A ManifestProvider which resolves application names to builtin manifest
130 // resources for the catalog service to consume.
131 class MojoShellContext::BuiltinManifestProvider
132 : public catalog::ManifestProvider {
133 public:
134 BuiltinManifestProvider() {}
135 ~BuiltinManifestProvider() override {}
136
137 void AddManifestResource(const std::string& name, int resource_id) {
138 auto result = manifest_resources_.insert(
139 std::make_pair(name, resource_id));
140 DCHECK(result.second);
141 }
142
143 void AddManifests(std::unique_ptr<
144 ContentBrowserClient::MojoApplicationManifestMap> manifests) {
145 manifests_ = std::move(manifests);
146 }
147
148 private:
149 // catalog::ManifestProvider:
150 bool GetApplicationManifest(const base::StringPiece& name,
151 std::string* manifest_contents) override {
152 auto it = manifest_resources_.find(name.as_string());
153 if (it != manifest_resources_.end()) {
154 *manifest_contents =
155 GetContentClient()
156 ->GetDataResource(it->second, ui::ScaleFactor::SCALE_FACTOR_NONE)
157 .as_string();
158 DCHECK(!manifest_contents->empty());
159 return true;
160 }
161 auto manifest_it = manifests_->find(name.as_string());
162 if (manifest_it != manifests_->end()) {
163 *manifest_contents = manifest_it->second;
164 DCHECK(!manifest_contents->empty());
165 return true;
166 }
167 return false;
168 }
169
170 std::unordered_map<std::string, int> manifest_resources_;
171 std::unique_ptr<ContentBrowserClient::MojoApplicationManifestMap> manifests_;
172
173 DISALLOW_COPY_AND_ASSIGN(BuiltinManifestProvider);
174 };
175
176 // Thread-safe proxy providing access to the shell context from any thread.
177 class MojoShellContext::Proxy {
178 public:
179 Proxy(MojoShellContext* shell_context)
180 : shell_context_(shell_context),
181 task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
182
183 ~Proxy() {}
184
185 void ConnectToApplication(
186 const std::string& user_id,
187 const std::string& name,
188 const std::string& requestor_name,
189 shell::mojom::InterfaceProviderRequest request,
190 shell::mojom::InterfaceProviderPtr exposed_services,
191 const shell::mojom::Connector::ConnectCallback& callback) {
192 if (task_runner_ == base::ThreadTaskRunnerHandle::Get()) {
193 if (shell_context_) {
194 shell_context_->ConnectToApplicationOnOwnThread(
195 user_id, name, requestor_name, std::move(request),
196 std::move(exposed_services), callback);
197 }
198 } else {
199 // |shell_context_| outlives the main MessageLoop, so it's safe for it to
200 // be unretained here.
201 task_runner_->PostTask(
202 FROM_HERE,
203 base::Bind(&MojoShellContext::ConnectToApplicationOnOwnThread,
204 base::Unretained(shell_context_), user_id, name,
205 requestor_name, base::Passed(&request),
206 base::Passed(&exposed_services), callback));
207 }
208 }
209
210 private:
211 MojoShellContext* shell_context_;
212 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
213
214 DISALLOW_COPY_AND_ASSIGN(Proxy);
215 };
216
217 // static
218 base::LazyInstance<std::unique_ptr<MojoShellContext::Proxy>>
219 MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER;
220
221 MojoShellContext::MojoShellContext() {
222 proxy_.Get().reset(new Proxy(this));
223
224 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner =
225 BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE);
226 std::unique_ptr<shell::NativeRunnerFactory> native_runner_factory(
227 new shell::InProcessNativeRunnerFactory(
228 BrowserThread::GetBlockingPool()));
229
230 // Allow the embedder to register additional Mojo application manifests
231 // beyond the default ones below.
232 std::unique_ptr<ContentBrowserClient::MojoApplicationManifestMap> manifests(
233 new ContentBrowserClient::MojoApplicationManifestMap);
234 GetContentClient()->browser()->RegisterMojoApplicationManifests(
235 manifests.get());
236
237 manifest_provider_.reset(new BuiltinManifestProvider);
238 manifest_provider_->AddManifests(std::move(manifests));
239 manifest_provider_->AddManifestResource(kBrowserMojoApplicationName,
240 IDR_MOJO_CONTENT_BROWSER_MANIFEST);
241 manifest_provider_->AddManifestResource(kGpuMojoApplicationName,
242 IDR_MOJO_CONTENT_GPU_MANIFEST);
243 manifest_provider_->AddManifestResource(kRendererMojoApplicationName,
244 IDR_MOJO_CONTENT_RENDERER_MANIFEST);
245 manifest_provider_->AddManifestResource(kUtilityMojoApplicationName,
246 IDR_MOJO_CONTENT_UTILITY_MANIFEST);
247 manifest_provider_->AddManifestResource("mojo:catalog",
248 IDR_MOJO_CATALOG_MANIFEST);
249 manifest_provider_->AddManifestResource(user_service::kUserServiceName,
250 IDR_MOJO_PROFILE_MANIFEST);
251
252 catalog_.reset(new catalog::Catalog(file_task_runner.get(), nullptr,
253 manifest_provider_.get()));
254
255 shell::mojom::ServiceRequest request;
256 if (shell::ShellIsRemote()) {
257 mojo::edk::SetParentPipeHandleFromCommandLine();
258 request = shell::GetServiceRequestFromCommandLine();
259 } else {
260 service_manager_.reset(new shell::ServiceManager(
261 std::move(native_runner_factory), catalog_->TakeService()));
262 request =
263 service_manager_->StartEmbedderService(kBrowserMojoApplicationName);
264 }
265 MojoShellConnection::SetForProcess(MojoShellConnection::Create(
266 std::move(request),
267 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
268
269 ContentBrowserClient::StaticMojoApplicationMap apps;
270 GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps);
271 for (const auto& entry : apps) {
272 MojoShellConnection::GetForProcess()->AddEmbeddedService(entry.first,
273 entry.second);
274 }
275
276 // This is safe to assign directly from any thread, because MojoShellContext
277 // must be constructed before anyone can call GetConnectorForIOThread().
278 g_io_thread_connector.Get() =
279 MojoShellConnection::GetForProcess()->GetConnector()->Clone();
280
281 MojoShellConnection::GetForProcess()->Start();
282
283 ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps;
284 GetContentClient()
285 ->browser()
286 ->RegisterOutOfProcessMojoApplications(&sandboxed_apps);
287 for (const auto& app : sandboxed_apps) {
288 MojoShellConnection::GetForProcess()->AddServiceRequestHandler(
289 app.first,
290 base::Bind(&LaunchAppInUtilityProcess, app.first, app.second,
291 true /* use_sandbox */));
292 }
293
294 ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps;
295 GetContentClient()
296 ->browser()
297 ->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps);
298 for (const auto& app : unsandboxed_apps) {
299 MojoShellConnection::GetForProcess()->AddServiceRequestHandler(
300 app.first,
301 base::Bind(&LaunchAppInUtilityProcess, app.first, app.second,
302 false /* use_sandbox */));
303 }
304
305 #if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
306 MojoShellConnection::GetForProcess()->AddServiceRequestHandler(
307 "mojo:media", base::Bind(&LaunchAppInGpuProcess, "mojo:media"));
308 #endif
309 }
310
311 MojoShellContext::~MojoShellContext() {
312 if (MojoShellConnection::GetForProcess())
313 MojoShellConnection::DestroyForProcess();
314 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
315 base::Bind(&DestroyConnectorOnIOThread));
316 catalog_.reset();
317 }
318
319 // static
320 void MojoShellContext::ConnectToApplication(
321 const std::string& user_id,
322 const std::string& name,
323 const std::string& requestor_name,
324 shell::mojom::InterfaceProviderRequest request,
325 shell::mojom::InterfaceProviderPtr exposed_services,
326 const shell::mojom::Connector::ConnectCallback& callback) {
327 proxy_.Get()->ConnectToApplication(user_id, name, requestor_name,
328 std::move(request),
329 std::move(exposed_services), callback);
330 }
331
332 // static
333 shell::Connector* MojoShellContext::GetConnectorForIOThread() {
334 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
335 return g_io_thread_connector.Get().get();
336 }
337
338 void MojoShellContext::ConnectToApplicationOnOwnThread(
339 const std::string& user_id,
340 const std::string& name,
341 const std::string& requestor_name,
342 shell::mojom::InterfaceProviderRequest request,
343 shell::mojom::InterfaceProviderPtr exposed_services,
344 const shell::mojom::Connector::ConnectCallback& callback) {
345 std::unique_ptr<shell::ConnectParams> params(new shell::ConnectParams);
346 shell::Identity source_id(requestor_name, user_id);
347 params->set_source(source_id);
348 params->set_target(shell::Identity(name, user_id));
349 params->set_remote_interfaces(std::move(request));
350 params->set_local_interfaces(std::move(exposed_services));
351 params->set_connect_callback(callback);
352 service_manager_->Connect(std::move(params));
353 }
354
355 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/mojo/mojo_shell_context.h ('k') | content/browser/mojo/service_manager_context_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698