OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/mojo/mojo_shell_context.h" | 5 #include "content/browser/mojo/mojo_shell_context.h" |
6 | 6 |
7 #include <unordered_map> | 7 #include <unordered_map> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/macros.h" | 13 #include "base/macros.h" |
14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
15 #include "base/path_service.h" | 15 #include "base/path_service.h" |
16 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
17 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
18 #include "content/browser/gpu/gpu_process_host.h" | 18 #include "content/browser/gpu/gpu_process_host.h" |
| 19 #include "content/browser/mojo/browser_shell_connection.h" |
19 #include "content/browser/mojo/constants.h" | 20 #include "content/browser/mojo/constants.h" |
20 #include "content/common/gpu_process_launch_causes.h" | 21 #include "content/common/gpu_process_launch_causes.h" |
21 #include "content/common/mojo/mojo_shell_connection_impl.h" | 22 #include "content/common/mojo/mojo_shell_connection_impl.h" |
22 #include "content/common/mojo/static_loader.h" | |
23 #include "content/common/process_control.mojom.h" | 23 #include "content/common/process_control.mojom.h" |
24 #include "content/grit/content_resources.h" | 24 #include "content/grit/content_resources.h" |
25 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/content_browser_client.h" | 26 #include "content/public/browser/content_browser_client.h" |
27 #include "content/public/browser/utility_process_host.h" | 27 #include "content/public/browser/utility_process_host.h" |
28 #include "content/public/browser/utility_process_host_client.h" | 28 #include "content/public/browser/utility_process_host_client.h" |
29 #include "content/public/common/content_client.h" | 29 #include "content/public/common/content_client.h" |
30 #include "content/public/common/content_switches.h" | 30 #include "content/public/common/content_switches.h" |
31 #include "content/public/common/service_registry.h" | 31 #include "content/public/common/service_registry.h" |
32 #include "mojo/public/cpp/bindings/interface_request.h" | 32 #include "mojo/public/cpp/bindings/interface_request.h" |
33 #include "mojo/public/cpp/bindings/string.h" | 33 #include "mojo/public/cpp/bindings/string.h" |
34 #include "services/catalog/factory.h" | 34 #include "services/catalog/factory.h" |
35 #include "services/catalog/manifest_provider.h" | 35 #include "services/catalog/manifest_provider.h" |
36 #include "services/catalog/store.h" | 36 #include "services/catalog/store.h" |
37 #include "services/shell/connect_params.h" | 37 #include "services/shell/connect_params.h" |
38 #include "services/shell/loader.h" | |
39 #include "services/shell/native_runner.h" | 38 #include "services/shell/native_runner.h" |
40 #include "services/shell/public/cpp/identity.h" | 39 #include "services/shell/public/cpp/identity.h" |
41 #include "services/shell/public/cpp/shell_client.h" | 40 #include "services/shell/public/cpp/shell_client.h" |
42 #include "services/shell/public/interfaces/connector.mojom.h" | 41 #include "services/shell/public/interfaces/connector.mojom.h" |
| 42 #include "services/shell/public/interfaces/shell_client.mojom.h" |
| 43 #include "services/shell/public/interfaces/shell_client_factory.mojom.h" |
43 #include "services/shell/runner/host/in_process_native_runner.h" | 44 #include "services/shell/runner/host/in_process_native_runner.h" |
44 #include "services/user/public/cpp/constants.h" | 45 #include "services/user/public/cpp/constants.h" |
45 | 46 |
46 namespace content { | 47 namespace content { |
47 | 48 |
48 namespace { | 49 namespace { |
49 | 50 |
50 // An extra set of apps to register on initialization, if set by a test. | 51 // An extra set of apps to register on initialization, if set by a test. |
51 const MojoShellContext::StaticApplicationMap* g_applications_for_test; | 52 const MojoShellContext::StaticApplicationMap* g_applications_for_test; |
52 | 53 |
(...skipping 10 matching lines...) Expand all Loading... |
63 | 64 |
64 ServiceRegistry* services = process_host->GetServiceRegistry(); | 65 ServiceRegistry* services = process_host->GetServiceRegistry(); |
65 services->ConnectToRemoteService(std::move(request)); | 66 services->ConnectToRemoteService(std::move(request)); |
66 } | 67 } |
67 | 68 |
68 void OnApplicationLoaded(const std::string& name, bool success) { | 69 void OnApplicationLoaded(const std::string& name, bool success) { |
69 if (!success) | 70 if (!success) |
70 LOG(ERROR) << "Failed to launch Mojo application for " << name; | 71 LOG(ERROR) << "Failed to launch Mojo application for " << name; |
71 } | 72 } |
72 | 73 |
73 // This launches a utility process and forwards the Load request the | 74 void LaunchAppInUtilityProcess(const std::string& app_name, |
74 // mojom::ProcessControl service there. The utility process is sandboxed iff | 75 const base::string16& process_name, |
75 // |use_sandbox| is true. | 76 bool use_sandbox, |
76 class UtilityProcessLoader : public shell::Loader { | 77 shell::mojom::ShellClientRequest request) { |
77 public: | 78 mojom::ProcessControlPtr process_control; |
78 UtilityProcessLoader(const base::string16& process_name, bool use_sandbox) | 79 mojom::ProcessControlRequest process_request = |
79 : process_name_(process_name), use_sandbox_(use_sandbox) {} | 80 mojo::GetProxy(&process_control); |
80 ~UtilityProcessLoader() override {} | 81 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 82 base::Bind(&StartUtilityProcessOnIOThread, |
| 83 base::Passed(&process_request), |
| 84 process_name, use_sandbox)); |
| 85 process_control->LoadApplication(app_name, std::move(request), |
| 86 base::Bind(&OnApplicationLoaded, app_name)); |
| 87 } |
81 | 88 |
82 private: | 89 #if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
83 // shell::Loader: | |
84 void Load(const std::string& name, | |
85 shell::mojom::ShellClientRequest request) override { | |
86 mojom::ProcessControlPtr process_control; | |
87 auto process_request = mojo::GetProxy(&process_control); | |
88 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
89 base::Bind(&StartUtilityProcessOnIOThread, | |
90 base::Passed(&process_request), | |
91 process_name_, use_sandbox_)); | |
92 process_control->LoadApplication(name, std::move(request), | |
93 base::Bind(&OnApplicationLoaded, name)); | |
94 } | |
95 | |
96 const base::string16 process_name_; | |
97 const bool use_sandbox_; | |
98 | |
99 DISALLOW_COPY_AND_ASSIGN(UtilityProcessLoader); | |
100 }; | |
101 | 90 |
102 // Request mojom::ProcessControl from GPU process host. Must be called on IO | 91 // Request mojom::ProcessControl from GPU process host. Must be called on IO |
103 // thread. | 92 // thread. |
104 void RequestGpuProcessControl( | 93 void RequestGpuProcessControl( |
105 mojo::InterfaceRequest<mojom::ProcessControl> request) { | 94 mojo::InterfaceRequest<mojom::ProcessControl> request) { |
106 BrowserChildProcessHostDelegate* process_host = | 95 BrowserChildProcessHostDelegate* process_host = |
107 GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 96 GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
108 CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP); | 97 CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP); |
109 if (!process_host) { | 98 if (!process_host) { |
110 DLOG(ERROR) << "GPU process host not available."; | 99 DLOG(ERROR) << "GPU process host not available."; |
111 return; | 100 return; |
112 } | 101 } |
113 | 102 |
114 // TODO(xhwang): It's possible that |process_host| is non-null, but the actual | 103 // TODO(xhwang): It's possible that |process_host| is non-null, but the actual |
115 // process is dead. In that case, |request| will be dropped and application | 104 // process is dead. In that case, |request| will be dropped and application |
116 // load requests through mojom::ProcessControl will also fail. Make sure we | 105 // load requests through mojom::ProcessControl will also fail. Make sure we |
117 // handle | 106 // handle |
118 // these cases correctly. | 107 // these cases correctly. |
119 process_host->GetServiceRegistry()->ConnectToRemoteService( | 108 process_host->GetServiceRegistry()->ConnectToRemoteService( |
120 std::move(request)); | 109 std::move(request)); |
121 } | 110 } |
122 | 111 |
123 // Forwards the load request to the GPU process. | 112 void LaunchAppInGpuProcess(const std::string& app_name, |
124 class GpuProcessLoader : public shell::Loader { | 113 shell::mojom::ShellClientRequest request) { |
125 public: | 114 mojom::ProcessControlPtr process_control; |
126 GpuProcessLoader() {} | 115 mojom::ProcessControlRequest process_request = |
127 ~GpuProcessLoader() override {} | 116 mojo::GetProxy(&process_control); |
| 117 BrowserThread::PostTask( |
| 118 BrowserThread::IO, FROM_HERE, |
| 119 base::Bind(&RequestGpuProcessControl, base::Passed(&process_request))); |
| 120 process_control->LoadApplication(app_name, std::move(request), |
| 121 base::Bind(&OnApplicationLoaded, app_name)); |
| 122 } |
128 | 123 |
129 private: | 124 #endif // ENABLE_MOJO_MEDIA_IN_GPU_PROCESS |
130 // shell::Loader: | |
131 void Load(const std::string& name, | |
132 shell::mojom::ShellClientRequest request) override { | |
133 mojom::ProcessControlPtr process_control; | |
134 auto process_request = mojo::GetProxy(&process_control); | |
135 BrowserThread::PostTask( | |
136 BrowserThread::IO, FROM_HERE, | |
137 base::Bind(&RequestGpuProcessControl, base::Passed(&process_request))); | |
138 process_control->LoadApplication(name, std::move(request), | |
139 base::Bind(&OnApplicationLoaded, name)); | |
140 } | |
141 | |
142 DISALLOW_COPY_AND_ASSIGN(GpuProcessLoader); | |
143 }; | |
144 | 125 |
145 } // namespace | 126 } // namespace |
146 | 127 |
147 // A ManifestProvider which resolves application names to builtin manifest | 128 // A ManifestProvider which resolves application names to builtin manifest |
148 // resources for the catalog service to consume. | 129 // resources for the catalog service to consume. |
149 class MojoShellContext::BuiltinManifestProvider | 130 class MojoShellContext::BuiltinManifestProvider |
150 : public catalog::ManifestProvider { | 131 : public catalog::ManifestProvider { |
151 public: | 132 public: |
152 BuiltinManifestProvider() {} | 133 BuiltinManifestProvider() {} |
153 ~BuiltinManifestProvider() override {} | 134 ~BuiltinManifestProvider() override {} |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 } | 190 } |
210 } | 191 } |
211 | 192 |
212 private: | 193 private: |
213 MojoShellContext* shell_context_; | 194 MojoShellContext* shell_context_; |
214 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 195 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
215 | 196 |
216 DISALLOW_COPY_AND_ASSIGN(Proxy); | 197 DISALLOW_COPY_AND_ASSIGN(Proxy); |
217 }; | 198 }; |
218 | 199 |
| 200 // Used to attach an existing ShellClient instance as a listener on the global |
| 201 // MojoShellConnection. |
| 202 // TODO(rockot): Find a way to get rid of this. |
| 203 class ShellConnectionListener : public MojoShellConnection::Listener { |
| 204 public: |
| 205 ShellConnectionListener(std::unique_ptr<shell::ShellClient> client) |
| 206 : client_(std::move(client)) {} |
| 207 ~ShellConnectionListener() override {} |
| 208 |
| 209 private: |
| 210 // MojoShellConnection::Listener: |
| 211 bool AcceptConnection(shell::Connection* connection) override { |
| 212 return client_->AcceptConnection(connection); |
| 213 } |
| 214 |
| 215 std::unique_ptr<shell::ShellClient> client_; |
| 216 |
| 217 DISALLOW_COPY_AND_ASSIGN(ShellConnectionListener); |
| 218 }; |
| 219 |
219 // static | 220 // static |
220 base::LazyInstance<std::unique_ptr<MojoShellContext::Proxy>> | 221 base::LazyInstance<std::unique_ptr<MojoShellContext::Proxy>> |
221 MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER; | 222 MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER; |
222 | 223 |
223 void MojoShellContext::SetApplicationsForTest( | 224 void MojoShellContext::SetApplicationsForTest( |
224 const StaticApplicationMap* apps) { | 225 const StaticApplicationMap* apps) { |
225 g_applications_for_test = apps; | 226 g_applications_for_test = apps; |
226 } | 227 } |
227 | 228 |
228 MojoShellContext::MojoShellContext() { | 229 MojoShellContext::MojoShellContext() { |
(...skipping 13 matching lines...) Expand all Loading... |
242 manifest_provider_->AddManifestResource("mojo:catalog", | 243 manifest_provider_->AddManifestResource("mojo:catalog", |
243 IDR_MOJO_CATALOG_MANIFEST); | 244 IDR_MOJO_CATALOG_MANIFEST); |
244 manifest_provider_->AddManifestResource(user_service::kUserServiceName, | 245 manifest_provider_->AddManifestResource(user_service::kUserServiceName, |
245 IDR_MOJO_PROFILE_MANIFEST); | 246 IDR_MOJO_PROFILE_MANIFEST); |
246 | 247 |
247 catalog_.reset(new catalog::Factory(file_task_runner.get(), nullptr, | 248 catalog_.reset(new catalog::Factory(file_task_runner.get(), nullptr, |
248 manifest_provider_.get())); | 249 manifest_provider_.get())); |
249 shell_.reset(new shell::Shell(std::move(native_runner_factory), | 250 shell_.reset(new shell::Shell(std::move(native_runner_factory), |
250 catalog_->TakeShellClient())); | 251 catalog_->TakeShellClient())); |
251 | 252 |
| 253 if (!IsRunningInMojoShell()) { |
| 254 MojoShellConnection::Create( |
| 255 shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName), |
| 256 false /* is_external */); |
| 257 } |
| 258 |
| 259 std::unique_ptr<BrowserShellConnection> browser_shell_connection( |
| 260 new BrowserShellConnection); |
| 261 |
252 StaticApplicationMap apps; | 262 StaticApplicationMap apps; |
253 GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps); | 263 GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps); |
254 if (g_applications_for_test) { | 264 if (g_applications_for_test) { |
255 // Add testing apps to the map, potentially overwriting whatever the | 265 // Add testing apps to the map, potentially overwriting whatever the |
256 // browser client registered. | 266 // browser client registered. |
257 for (const auto& entry : *g_applications_for_test) | 267 for (const auto& entry : *g_applications_for_test) |
258 apps[entry.first] = entry.second; | 268 apps[entry.first] = entry.second; |
259 } | 269 } |
260 for (const auto& entry : apps) { | 270 for (const auto& entry : apps) { |
261 shell_->SetLoaderForName(base::WrapUnique(new StaticLoader(entry.second)), | 271 browser_shell_connection->AddEmbeddedApplication( |
262 entry.first); | 272 entry.first, entry.second, nullptr); |
263 } | 273 } |
264 | 274 |
265 ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps; | 275 ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps; |
266 GetContentClient() | 276 GetContentClient() |
267 ->browser() | 277 ->browser() |
268 ->RegisterOutOfProcessMojoApplications(&sandboxed_apps); | 278 ->RegisterOutOfProcessMojoApplications(&sandboxed_apps); |
269 for (const auto& app : sandboxed_apps) { | 279 for (const auto& app : sandboxed_apps) { |
270 shell_->SetLoaderForName(base::WrapUnique(new UtilityProcessLoader( | 280 browser_shell_connection->AddShellClientRequestHandler( |
271 app.second, true /* use_sandbox */)), | 281 app.first, |
272 app.first); | 282 base::Bind(&LaunchAppInUtilityProcess, app.first, app.second, |
| 283 true /* use_sandbox */)); |
273 } | 284 } |
274 | 285 |
275 ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps; | 286 ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps; |
276 GetContentClient() | 287 GetContentClient() |
277 ->browser() | 288 ->browser() |
278 ->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps); | 289 ->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps); |
279 for (const auto& app : unsandboxed_apps) { | 290 for (const auto& app : unsandboxed_apps) { |
280 shell_->SetLoaderForName(base::WrapUnique(new UtilityProcessLoader( | 291 browser_shell_connection->AddShellClientRequestHandler( |
281 app.second, false /* use_sandbox */)), | 292 app.first, |
282 app.first); | 293 base::Bind(&LaunchAppInUtilityProcess, app.first, app.second, |
| 294 false /* use_sandbox */)); |
283 } | 295 } |
284 | 296 |
285 #if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 297 #if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
286 shell_->SetLoaderForName(base::WrapUnique(new GpuProcessLoader), | 298 browser_shell_connection->AddShellClientRequestHandler( |
287 "mojo:media"); | 299 "mojo:media", base::Bind(&LaunchAppInGpuProcess, "mojo:media")); |
288 #endif | 300 #endif |
289 | 301 |
290 if (!IsRunningInMojoShell()) { | 302 // Attach our ShellClientFactory implementation to the global connection. |
291 MojoShellConnection::Create( | 303 MojoShellConnection* shell_connection = MojoShellConnection::Get(); |
292 shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName), | 304 CHECK(shell_connection); |
293 false /* is_external */); | 305 shell_connection->AddListener( |
294 } | 306 new ShellConnectionListener(std::move(browser_shell_connection))); |
295 } | 307 } |
296 | 308 |
297 MojoShellContext::~MojoShellContext() { | 309 MojoShellContext::~MojoShellContext() { |
298 if (!IsRunningInMojoShell()) | 310 if (!IsRunningInMojoShell()) |
299 MojoShellConnectionImpl::Destroy(); | 311 MojoShellConnectionImpl::Destroy(); |
300 } | 312 } |
301 | 313 |
302 // static | 314 // static |
303 void MojoShellContext::ConnectToApplication( | 315 void MojoShellContext::ConnectToApplication( |
304 const std::string& user_id, | 316 const std::string& user_id, |
(...skipping 18 matching lines...) Expand all Loading... |
323 shell::Identity source_id(requestor_name, user_id); | 335 shell::Identity source_id(requestor_name, user_id); |
324 params->set_source(source_id); | 336 params->set_source(source_id); |
325 params->set_target(shell::Identity(name, user_id)); | 337 params->set_target(shell::Identity(name, user_id)); |
326 params->set_remote_interfaces(std::move(request)); | 338 params->set_remote_interfaces(std::move(request)); |
327 params->set_local_interfaces(std::move(exposed_services)); | 339 params->set_local_interfaces(std::move(exposed_services)); |
328 params->set_connect_callback(callback); | 340 params->set_connect_callback(callback); |
329 shell_->Connect(std::move(params)); | 341 shell_->Connect(std::move(params)); |
330 } | 342 } |
331 | 343 |
332 } // namespace content | 344 } // namespace content |
OLD | NEW |