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, |
81 | 82 base::Bind(&StartUtilityProcessOnIOThread, |
82 private: | 83 base::Passed(&process_request), |
83 // shell::Loader: | 84 process_name, use_sandbox)); |
84 void Load(const std::string& name, | 85 process_control->LoadApplication(app_name, std::move(request), |
85 shell::mojom::ShellClientRequest request) override { | 86 base::Bind(&OnApplicationLoaded, app_name)); |
86 mojom::ProcessControlPtr process_control; | 87 } |
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 | 88 |
102 // Request mojom::ProcessControl from GPU process host. Must be called on IO | 89 // Request mojom::ProcessControl from GPU process host. Must be called on IO |
103 // thread. | 90 // thread. |
104 void RequestGpuProcessControl( | 91 void RequestGpuProcessControl( |
105 mojo::InterfaceRequest<mojom::ProcessControl> request) { | 92 mojo::InterfaceRequest<mojom::ProcessControl> request) { |
106 BrowserChildProcessHostDelegate* process_host = | 93 BrowserChildProcessHostDelegate* process_host = |
107 GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 94 GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
108 CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP); | 95 CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP); |
109 if (!process_host) { | 96 if (!process_host) { |
110 DLOG(ERROR) << "GPU process host not available."; | 97 DLOG(ERROR) << "GPU process host not available."; |
111 return; | 98 return; |
112 } | 99 } |
113 | 100 |
114 // TODO(xhwang): It's possible that |process_host| is non-null, but the actual | 101 // 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 | 102 // process is dead. In that case, |request| will be dropped and application |
116 // load requests through mojom::ProcessControl will also fail. Make sure we | 103 // load requests through mojom::ProcessControl will also fail. Make sure we |
117 // handle | 104 // handle |
118 // these cases correctly. | 105 // these cases correctly. |
119 process_host->GetServiceRegistry()->ConnectToRemoteService( | 106 process_host->GetServiceRegistry()->ConnectToRemoteService( |
120 std::move(request)); | 107 std::move(request)); |
121 } | 108 } |
122 | 109 |
123 // Forwards the load request to the GPU process. | 110 void LaunchAppInGpuProcess(const std::string& app_name, |
124 class GpuProcessLoader : public shell::Loader { | 111 shell::mojom::ShellClientRequest request) { |
125 public: | 112 mojom::ProcessControlPtr process_control; |
126 GpuProcessLoader() {} | 113 mojom::ProcessControlRequest process_request = |
127 ~GpuProcessLoader() override {} | 114 mojo::GetProxy(&process_control); |
128 | 115 BrowserThread::PostTask( |
129 private: | 116 BrowserThread::IO, FROM_HERE, |
130 // shell::Loader: | 117 base::Bind(&RequestGpuProcessControl, base::Passed(&process_request))); |
131 void Load(const std::string& name, | 118 process_control->LoadApplication(app_name, std::move(request), |
132 shell::mojom::ShellClientRequest request) override { | 119 base::Bind(&OnApplicationLoaded, app_name)); |
133 mojom::ProcessControlPtr process_control; | 120 } |
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 | 121 |
145 } // namespace | 122 } // namespace |
146 | 123 |
147 // A ManifestProvider which resolves application names to builtin manifest | 124 // A ManifestProvider which resolves application names to builtin manifest |
148 // resources for the catalog service to consume. | 125 // resources for the catalog service to consume. |
149 class MojoShellContext::BuiltinManifestProvider | 126 class MojoShellContext::BuiltinManifestProvider |
150 : public catalog::ManifestProvider { | 127 : public catalog::ManifestProvider { |
151 public: | 128 public: |
152 BuiltinManifestProvider() {} | 129 BuiltinManifestProvider() {} |
153 ~BuiltinManifestProvider() override {} | 130 ~BuiltinManifestProvider() override {} |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 } | 186 } |
210 } | 187 } |
211 | 188 |
212 private: | 189 private: |
213 MojoShellContext* shell_context_; | 190 MojoShellContext* shell_context_; |
214 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 191 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
215 | 192 |
216 DISALLOW_COPY_AND_ASSIGN(Proxy); | 193 DISALLOW_COPY_AND_ASSIGN(Proxy); |
217 }; | 194 }; |
218 | 195 |
| 196 // Used to attach an existing ShellClient instance as a listener on the global |
| 197 // MojoShellConnection. |
| 198 // TODO(rockot): Find a way to get rid of this. |
| 199 class ShellConnectionListener : public MojoShellConnection::Listener { |
| 200 public: |
| 201 ShellConnectionListener(std::unique_ptr<shell::ShellClient> client) |
| 202 : client_(std::move(client)) {} |
| 203 ~ShellConnectionListener() override {} |
| 204 |
| 205 private: |
| 206 // MojoShellConnection::Listener: |
| 207 bool AcceptConnection(shell::Connection* connection) override { |
| 208 return client_->AcceptConnection(connection); |
| 209 } |
| 210 |
| 211 std::unique_ptr<shell::ShellClient> client_; |
| 212 |
| 213 DISALLOW_COPY_AND_ASSIGN(ShellConnectionListener); |
| 214 }; |
| 215 |
219 // static | 216 // static |
220 base::LazyInstance<std::unique_ptr<MojoShellContext::Proxy>> | 217 base::LazyInstance<std::unique_ptr<MojoShellContext::Proxy>> |
221 MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER; | 218 MojoShellContext::proxy_ = LAZY_INSTANCE_INITIALIZER; |
222 | 219 |
223 void MojoShellContext::SetApplicationsForTest( | 220 void MojoShellContext::SetApplicationsForTest( |
224 const StaticApplicationMap* apps) { | 221 const StaticApplicationMap* apps) { |
225 g_applications_for_test = apps; | 222 g_applications_for_test = apps; |
226 } | 223 } |
227 | 224 |
228 MojoShellContext::MojoShellContext() { | 225 MojoShellContext::MojoShellContext() { |
(...skipping 13 matching lines...) Expand all Loading... |
242 manifest_provider_->AddManifestResource("mojo:catalog", | 239 manifest_provider_->AddManifestResource("mojo:catalog", |
243 IDR_MOJO_CATALOG_MANIFEST); | 240 IDR_MOJO_CATALOG_MANIFEST); |
244 manifest_provider_->AddManifestResource(user_service::kUserServiceName, | 241 manifest_provider_->AddManifestResource(user_service::kUserServiceName, |
245 IDR_MOJO_PROFILE_MANIFEST); | 242 IDR_MOJO_PROFILE_MANIFEST); |
246 | 243 |
247 catalog_.reset(new catalog::Factory(file_task_runner.get(), nullptr, | 244 catalog_.reset(new catalog::Factory(file_task_runner.get(), nullptr, |
248 manifest_provider_.get())); | 245 manifest_provider_.get())); |
249 shell_.reset(new shell::Shell(std::move(native_runner_factory), | 246 shell_.reset(new shell::Shell(std::move(native_runner_factory), |
250 catalog_->TakeShellClient())); | 247 catalog_->TakeShellClient())); |
251 | 248 |
| 249 if (!IsRunningInMojoShell()) { |
| 250 MojoShellConnection::Create( |
| 251 shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName), |
| 252 false /* is_external */); |
| 253 } |
| 254 |
| 255 std::unique_ptr<BrowserShellConnection> browser_shell_connection( |
| 256 new BrowserShellConnection); |
| 257 |
252 StaticApplicationMap apps; | 258 StaticApplicationMap apps; |
253 GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps); | 259 GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps); |
254 if (g_applications_for_test) { | 260 if (g_applications_for_test) { |
255 // Add testing apps to the map, potentially overwriting whatever the | 261 // Add testing apps to the map, potentially overwriting whatever the |
256 // browser client registered. | 262 // browser client registered. |
257 for (const auto& entry : *g_applications_for_test) | 263 for (const auto& entry : *g_applications_for_test) |
258 apps[entry.first] = entry.second; | 264 apps[entry.first] = entry.second; |
259 } | 265 } |
260 for (const auto& entry : apps) { | 266 for (const auto& entry : apps) { |
261 shell_->SetLoaderForName(base::WrapUnique(new StaticLoader(entry.second)), | 267 browser_shell_connection->AddEmbeddedApplication( |
262 entry.first); | 268 entry.first, entry.second, nullptr); |
263 } | 269 } |
264 | 270 |
265 ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps; | 271 ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps; |
266 GetContentClient() | 272 GetContentClient() |
267 ->browser() | 273 ->browser() |
268 ->RegisterOutOfProcessMojoApplications(&sandboxed_apps); | 274 ->RegisterOutOfProcessMojoApplications(&sandboxed_apps); |
269 for (const auto& app : sandboxed_apps) { | 275 for (const auto& app : sandboxed_apps) { |
270 shell_->SetLoaderForName(base::WrapUnique(new UtilityProcessLoader( | 276 browser_shell_connection->AddShellClientRequestHandler( |
271 app.second, true /* use_sandbox */)), | 277 app.first, |
272 app.first); | 278 base::Bind(&LaunchAppInUtilityProcess, app.first, app.second, |
| 279 true /* use_sandbox */)); |
273 } | 280 } |
274 | 281 |
275 ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps; | 282 ContentBrowserClient::OutOfProcessMojoApplicationMap unsandboxed_apps; |
276 GetContentClient() | 283 GetContentClient() |
277 ->browser() | 284 ->browser() |
278 ->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps); | 285 ->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps); |
279 for (const auto& app : unsandboxed_apps) { | 286 for (const auto& app : unsandboxed_apps) { |
280 shell_->SetLoaderForName(base::WrapUnique(new UtilityProcessLoader( | 287 browser_shell_connection->AddShellClientRequestHandler( |
281 app.second, false /* use_sandbox */)), | 288 app.first, |
282 app.first); | 289 base::Bind(&LaunchAppInUtilityProcess, app.first, app.second, |
| 290 false /* use_sandbox */)); |
283 } | 291 } |
284 | 292 |
285 #if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 293 #if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
286 shell_->SetLoaderForName(base::WrapUnique(new GpuProcessLoader), | 294 browser_shell_connection->AddShellClientRequestHandler( |
287 "mojo:media"); | 295 "mojo:media", base::Bind(&LaunchAppInGpuProcess, "mojo:media")); |
288 #endif | 296 #endif |
289 | 297 |
290 if (!IsRunningInMojoShell()) { | 298 // Attach our ShellClientFactory implementation to the global connection. |
291 MojoShellConnection::Create( | 299 MojoShellConnection* shell_connection = MojoShellConnection::Get(); |
292 shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName), | 300 CHECK(shell_connection); |
293 false /* is_external */); | 301 shell_connection->AddListener( |
294 } | 302 new ShellConnectionListener(std::move(browser_shell_connection))); |
295 } | 303 } |
296 | 304 |
297 MojoShellContext::~MojoShellContext() { | 305 MojoShellContext::~MojoShellContext() { |
298 if (!IsRunningInMojoShell()) | 306 if (!IsRunningInMojoShell()) |
299 MojoShellConnectionImpl::Destroy(); | 307 MojoShellConnectionImpl::Destroy(); |
300 } | 308 } |
301 | 309 |
302 // static | 310 // static |
303 void MojoShellContext::ConnectToApplication( | 311 void MojoShellContext::ConnectToApplication( |
304 const std::string& user_id, | 312 const std::string& user_id, |
(...skipping 18 matching lines...) Expand all Loading... |
323 shell::Identity source_id(requestor_name, user_id); | 331 shell::Identity source_id(requestor_name, user_id); |
324 params->set_source(source_id); | 332 params->set_source(source_id); |
325 params->set_target(shell::Identity(name, user_id)); | 333 params->set_target(shell::Identity(name, user_id)); |
326 params->set_remote_interfaces(std::move(request)); | 334 params->set_remote_interfaces(std::move(request)); |
327 params->set_local_interfaces(std::move(exposed_services)); | 335 params->set_local_interfaces(std::move(exposed_services)); |
328 params->set_connect_callback(callback); | 336 params->set_connect_callback(callback); |
329 shell_->Connect(std::move(params)); | 337 shell_->Connect(std::move(params)); |
330 } | 338 } |
331 | 339 |
332 } // namespace content | 340 } // namespace content |
OLD | NEW |