OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "shell/application_manager/application_manager.h" | 5 #include "shell/application_manager/application_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 } | 57 } |
58 | 58 |
59 } // namespace | 59 } // namespace |
60 | 60 |
61 class ApplicationManager::ContentHandlerConnection { | 61 class ApplicationManager::ContentHandlerConnection { |
62 public: | 62 public: |
63 ContentHandlerConnection(ApplicationManager* manager, Identity identity) | 63 ContentHandlerConnection(ApplicationManager* manager, Identity identity) |
64 : manager_(manager), identity_(identity) { | 64 : manager_(manager), identity_(identity) { |
65 ServiceProviderPtr services; | 65 ServiceProviderPtr services; |
66 manager->ConnectToApplication(identity_.url, GURL(), | 66 manager->ConnectToApplication(identity_.url, GURL(), |
67 mojo::GetProxy(&services), nullptr, | 67 mojo::GetProxy(&services), base::Closure()); |
68 base::Closure()); | |
69 mojo::MessagePipe pipe; | 68 mojo::MessagePipe pipe; |
70 content_handler_.Bind( | 69 content_handler_.Bind( |
71 mojo::InterfaceHandle<mojo::ContentHandler>(pipe.handle0.Pass(), 0u)); | 70 mojo::InterfaceHandle<mojo::ContentHandler>(pipe.handle0.Pass(), 0u)); |
72 services->ConnectToService(mojo::ContentHandler::Name_, | 71 services->ConnectToService(mojo::ContentHandler::Name_, |
73 pipe.handle1.Pass()); | 72 pipe.handle1.Pass()); |
74 content_handler_.set_connection_error_handler( | 73 content_handler_.set_connection_error_handler( |
75 [this]() { manager_->OnContentHandlerError(this); }); | 74 [this]() { manager_->OnContentHandlerError(this); }); |
76 } | 75 } |
77 ~ContentHandlerConnection() {} | 76 ~ContentHandlerConnection() {} |
78 | 77 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 } | 120 } |
122 | 121 |
123 void ApplicationManager::TerminateShellConnections() { | 122 void ApplicationManager::TerminateShellConnections() { |
124 identity_to_shell_impl_.clear(); | 123 identity_to_shell_impl_.clear(); |
125 } | 124 } |
126 | 125 |
127 void ApplicationManager::ConnectToApplication( | 126 void ApplicationManager::ConnectToApplication( |
128 const GURL& requested_url, | 127 const GURL& requested_url, |
129 const GURL& requestor_url, | 128 const GURL& requestor_url, |
130 InterfaceRequest<ServiceProvider> services, | 129 InterfaceRequest<ServiceProvider> services, |
131 mojo::InterfaceHandle<ServiceProvider> exposed_services, | |
132 const base::Closure& on_application_end) { | 130 const base::Closure& on_application_end) { |
133 ConnectToApplicationWithParameters( | 131 ConnectToApplicationWithParameters(requested_url, requestor_url, |
134 requested_url, requestor_url, services.Pass(), exposed_services.Pass(), | 132 services.Pass(), on_application_end, |
135 on_application_end, std::vector<std::string>()); | 133 std::vector<std::string>()); |
136 } | 134 } |
137 | 135 |
138 void ApplicationManager::ConnectToApplicationWithParameters( | 136 void ApplicationManager::ConnectToApplicationWithParameters( |
139 const GURL& requested_url, | 137 const GURL& requested_url, |
140 const GURL& requestor_url, | 138 const GURL& requestor_url, |
141 InterfaceRequest<ServiceProvider> services, | 139 InterfaceRequest<ServiceProvider> services, |
142 mojo::InterfaceHandle<mojo::ServiceProvider> exposed_services, | |
143 const base::Closure& on_application_end, | 140 const base::Closure& on_application_end, |
144 const std::vector<std::string>& pre_redirect_parameters) { | 141 const std::vector<std::string>& pre_redirect_parameters) { |
145 TRACE_EVENT_INSTANT2( | 142 TRACE_EVENT_INSTANT2( |
146 "mojo_shell", "ApplicationManager::ConnectToApplicationWithParameters", | 143 "mojo_shell", "ApplicationManager::ConnectToApplicationWithParameters", |
147 TRACE_EVENT_SCOPE_THREAD, "requested_url", requested_url.spec(), | 144 TRACE_EVENT_SCOPE_THREAD, "requested_url", requested_url.spec(), |
148 "requestor_url", requestor_url.spec()); | 145 "requestor_url", requestor_url.spec()); |
149 DCHECK(requested_url.is_valid()); | 146 DCHECK(requested_url.is_valid()); |
150 | 147 |
151 // We check both the mapped and resolved urls for existing shell_impls because | 148 // We check both the mapped and resolved urls for existing shell_impls because |
152 // external applications can be registered for the unresolved mojo:foo urls. | 149 // external applications can be registered for the unresolved mojo:foo urls. |
153 | 150 |
154 GURL mapped_url = delegate_->ResolveMappings(requested_url); | 151 GURL mapped_url = delegate_->ResolveMappings(requested_url); |
155 if (ConnectToRunningApplication(mapped_url, requestor_url, &services, | 152 if (ConnectToRunningApplication(mapped_url, requestor_url, &services)) |
156 &exposed_services)) { | |
157 return; | 153 return; |
158 } | |
159 | 154 |
160 GURL resolved_url = delegate_->ResolveMojoURL(mapped_url); | 155 GURL resolved_url = delegate_->ResolveMojoURL(mapped_url); |
161 if (ConnectToRunningApplication(resolved_url, requestor_url, &services, | 156 if (ConnectToRunningApplication(resolved_url, requestor_url, &services)) |
162 &exposed_services)) { | |
163 return; | 157 return; |
164 } | |
165 | 158 |
166 // The application is not running, let's compute the parameters. | 159 // The application is not running, let's compute the parameters. |
167 std::vector<std::string> parameters = | 160 std::vector<std::string> parameters = |
168 Concatenate(pre_redirect_parameters, GetArgsForURL(resolved_url)); | 161 Concatenate(pre_redirect_parameters, GetArgsForURL(resolved_url)); |
169 | 162 |
170 if (ConnectToApplicationWithLoader(mapped_url, requestor_url, &services, | 163 if (ConnectToApplicationWithLoader(mapped_url, requestor_url, &services, |
171 &exposed_services, on_application_end, | 164 on_application_end, parameters, |
172 parameters, GetLoaderForURL(mapped_url))) { | 165 GetLoaderForURL(mapped_url))) |
173 return; | 166 return; |
174 } | |
175 | |
176 if (ConnectToApplicationWithLoader( | |
177 resolved_url, requestor_url, &services, &exposed_services, | |
178 on_application_end, parameters, GetLoaderForURL(resolved_url))) { | |
179 return; | |
180 } | |
181 | 167 |
182 if (ConnectToApplicationWithLoader(resolved_url, requestor_url, &services, | 168 if (ConnectToApplicationWithLoader(resolved_url, requestor_url, &services, |
183 &exposed_services, on_application_end, | 169 on_application_end, parameters, |
184 parameters, default_loader_.get())) { | 170 GetLoaderForURL(resolved_url))) |
185 return; | 171 return; |
186 } | |
187 | 172 |
188 auto callback = base::Bind( | 173 if (ConnectToApplicationWithLoader(resolved_url, requestor_url, &services, |
189 &ApplicationManager::HandleFetchCallback, weak_ptr_factory_.GetWeakPtr(), | 174 on_application_end, parameters, |
190 requestor_url, base::Passed(services.Pass()), | 175 default_loader_.get())) |
191 base::Passed(exposed_services.Pass()), on_application_end, parameters); | 176 return; |
| 177 |
| 178 auto callback = |
| 179 base::Bind(&ApplicationManager::HandleFetchCallback, |
| 180 weak_ptr_factory_.GetWeakPtr(), requestor_url, |
| 181 base::Passed(services.Pass()), on_application_end, parameters); |
192 | 182 |
193 if (resolved_url.SchemeIsFile()) { | 183 if (resolved_url.SchemeIsFile()) { |
194 new LocalFetcher(resolved_url, GetBaseURLAndQuery(resolved_url, nullptr), | 184 new LocalFetcher(resolved_url, GetBaseURLAndQuery(resolved_url, nullptr), |
195 callback); | 185 callback); |
196 return; | 186 return; |
197 } | 187 } |
198 | 188 |
199 if (!url_response_disk_cache_) { | 189 if (!url_response_disk_cache_) { |
200 ConnectToService(GURL("mojo:url_response_disk_cache"), | 190 ConnectToService(GURL("mojo:url_response_disk_cache"), |
201 &url_response_disk_cache_); | 191 &url_response_disk_cache_); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 } | 225 } |
236 | 226 |
237 new NetworkFetcher(options_.disable_cache, options_.force_offline_by_default, | 227 new NetworkFetcher(options_.disable_cache, options_.force_offline_by_default, |
238 resolved_url, url_response_disk_cache_.get(), | 228 resolved_url, url_response_disk_cache_.get(), |
239 network_service, callback); | 229 network_service, callback); |
240 } | 230 } |
241 | 231 |
242 bool ApplicationManager::ConnectToRunningApplication( | 232 bool ApplicationManager::ConnectToRunningApplication( |
243 const GURL& resolved_url, | 233 const GURL& resolved_url, |
244 const GURL& requestor_url, | 234 const GURL& requestor_url, |
245 InterfaceRequest<ServiceProvider>* services, | 235 InterfaceRequest<ServiceProvider>* services) { |
246 mojo::InterfaceHandle<mojo::ServiceProvider>* exposed_services) { | |
247 GURL application_url = GetBaseURLAndQuery(resolved_url, nullptr); | 236 GURL application_url = GetBaseURLAndQuery(resolved_url, nullptr); |
248 ShellImpl* shell_impl = GetShellImpl(application_url); | 237 ShellImpl* shell_impl = GetShellImpl(application_url); |
249 if (!shell_impl) | 238 if (!shell_impl) |
250 return false; | 239 return false; |
251 | 240 |
252 DCHECK(!GetNativeApplicationOptionsForURL(application_url) | 241 DCHECK(!GetNativeApplicationOptionsForURL(application_url) |
253 ->new_process_per_connection); | 242 ->new_process_per_connection); |
254 | 243 |
255 ConnectToClient(shell_impl, resolved_url, requestor_url, services->Pass(), | 244 ConnectToClient(shell_impl, resolved_url, requestor_url, services->Pass()); |
256 exposed_services->Pass()); | |
257 return true; | 245 return true; |
258 } | 246 } |
259 | 247 |
260 bool ApplicationManager::ConnectToApplicationWithLoader( | 248 bool ApplicationManager::ConnectToApplicationWithLoader( |
261 const GURL& resolved_url, | 249 const GURL& resolved_url, |
262 const GURL& requestor_url, | 250 const GURL& requestor_url, |
263 InterfaceRequest<ServiceProvider>* services, | 251 InterfaceRequest<ServiceProvider>* services, |
264 mojo::InterfaceHandle<mojo::ServiceProvider>* exposed_services, | |
265 const base::Closure& on_application_end, | 252 const base::Closure& on_application_end, |
266 const std::vector<std::string>& parameters, | 253 const std::vector<std::string>& parameters, |
267 ApplicationLoader* loader) { | 254 ApplicationLoader* loader) { |
268 if (!loader) | 255 if (!loader) |
269 return false; | 256 return false; |
270 | 257 |
271 loader->Load( | 258 loader->Load(resolved_url, |
272 resolved_url, | 259 RegisterShell(resolved_url, requestor_url, services->Pass(), |
273 RegisterShell(resolved_url, requestor_url, services->Pass(), | 260 on_application_end, parameters)); |
274 exposed_services->Pass(), on_application_end, parameters)); | |
275 return true; | 261 return true; |
276 } | 262 } |
277 | 263 |
278 Identity ApplicationManager::MakeApplicationIdentity(const GURL& resolved_url, | 264 Identity ApplicationManager::MakeApplicationIdentity(const GURL& resolved_url, |
279 bool strip_query) { | 265 bool strip_query) { |
280 static uint64_t unique_id_number = 1; | 266 static uint64_t unique_id_number = 1; |
281 GURL stripped_url = GetBaseURLAndQuery(resolved_url, nullptr); | 267 GURL stripped_url = GetBaseURLAndQuery(resolved_url, nullptr); |
282 GURL url = strip_query ? stripped_url : resolved_url; | 268 GURL url = strip_query ? stripped_url : resolved_url; |
283 bool new_process_per_connection = | 269 bool new_process_per_connection = |
284 GetNativeApplicationOptionsForURL(stripped_url) | 270 GetNativeApplicationOptionsForURL(stripped_url) |
285 ->new_process_per_connection; | 271 ->new_process_per_connection; |
286 return new_process_per_connection | 272 return new_process_per_connection |
287 ? Identity(url, base::Uint64ToString(unique_id_number++)) | 273 ? Identity(url, base::Uint64ToString(unique_id_number++)) |
288 : Identity(url); | 274 : Identity(url); |
289 } | 275 } |
290 | 276 |
291 InterfaceRequest<Application> ApplicationManager::RegisterShell( | 277 InterfaceRequest<Application> ApplicationManager::RegisterShell( |
292 const GURL& resolved_url, | 278 const GURL& resolved_url, |
293 const GURL& requestor_url, | 279 const GURL& requestor_url, |
294 InterfaceRequest<ServiceProvider> services, | 280 InterfaceRequest<ServiceProvider> services, |
295 mojo::InterfaceHandle<mojo::ServiceProvider> exposed_services, | |
296 const base::Closure& on_application_end, | 281 const base::Closure& on_application_end, |
297 const std::vector<std::string>& parameters) { | 282 const std::vector<std::string>& parameters) { |
298 Identity app_identity = MakeApplicationIdentity(resolved_url); | 283 Identity app_identity = MakeApplicationIdentity(resolved_url); |
299 | 284 |
300 mojo::ApplicationPtr application; | 285 mojo::ApplicationPtr application; |
301 InterfaceRequest<Application> application_request = | 286 InterfaceRequest<Application> application_request = |
302 mojo::GetProxy(&application); | 287 mojo::GetProxy(&application); |
303 ShellImpl* shell = | 288 ShellImpl* shell = |
304 new ShellImpl(application.Pass(), this, app_identity, on_application_end); | 289 new ShellImpl(application.Pass(), this, app_identity, on_application_end); |
305 identity_to_shell_impl_[app_identity] = make_scoped_ptr(shell); | 290 identity_to_shell_impl_[app_identity] = make_scoped_ptr(shell); |
306 shell->InitializeApplication(mojo::Array<mojo::String>::From(parameters)); | 291 shell->InitializeApplication(mojo::Array<mojo::String>::From(parameters)); |
307 ConnectToClient(shell, resolved_url, requestor_url, services.Pass(), | 292 ConnectToClient(shell, resolved_url, requestor_url, services.Pass()); |
308 exposed_services.Pass()); | |
309 return application_request; | 293 return application_request; |
310 } | 294 } |
311 | 295 |
312 // Note: If a service was created with a unique ID, intending to be unique | 296 // Note: If a service was created with a unique ID, intending to be unique |
313 // (such that multiple requests for a service result in unique processes), then | 297 // (such that multiple requests for a service result in unique processes), then |
314 // 'GetShellImpl' should return nullptr. | 298 // 'GetShellImpl' should return nullptr. |
315 ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) { | 299 ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) { |
316 DCHECK(!url.has_query()); | 300 DCHECK(!url.has_query()); |
317 const auto& shell_it = identity_to_shell_impl_.find(Identity(url)); | 301 const auto& shell_it = identity_to_shell_impl_.find(Identity(url)); |
318 if (shell_it != identity_to_shell_impl_.end()) | 302 if (shell_it != identity_to_shell_impl_.end()) |
319 return shell_it->second.get(); | 303 return shell_it->second.get(); |
320 return nullptr; | 304 return nullptr; |
321 } | 305 } |
322 | 306 |
323 void ApplicationManager::ConnectToClient( | 307 void ApplicationManager::ConnectToClient( |
324 ShellImpl* shell_impl, | 308 ShellImpl* shell_impl, |
325 const GURL& resolved_url, | 309 const GURL& resolved_url, |
326 const GURL& requestor_url, | 310 const GURL& requestor_url, |
327 InterfaceRequest<ServiceProvider> services, | 311 InterfaceRequest<ServiceProvider> services) { |
328 mojo::InterfaceHandle<mojo::ServiceProvider> exposed_services) { | 312 shell_impl->ConnectToClient(resolved_url, requestor_url, services.Pass()); |
329 shell_impl->ConnectToClient(resolved_url, requestor_url, services.Pass(), | |
330 exposed_services.Pass()); | |
331 } | 313 } |
332 | 314 |
333 void ApplicationManager::HandleFetchCallback( | 315 void ApplicationManager::HandleFetchCallback( |
334 const GURL& requestor_url, | 316 const GURL& requestor_url, |
335 InterfaceRequest<ServiceProvider> services, | 317 InterfaceRequest<ServiceProvider> services, |
336 mojo::InterfaceHandle<mojo::ServiceProvider> exposed_services, | |
337 const base::Closure& on_application_end, | 318 const base::Closure& on_application_end, |
338 const std::vector<std::string>& parameters, | 319 const std::vector<std::string>& parameters, |
339 scoped_ptr<Fetcher> fetcher) { | 320 scoped_ptr<Fetcher> fetcher) { |
340 if (!fetcher) { | 321 if (!fetcher) { |
341 // Network error. Drop |application_request| to tell requestor. | 322 // Network error. Drop |application_request| to tell requestor. |
342 return; | 323 return; |
343 } | 324 } |
344 | 325 |
345 GURL redirect_url = fetcher->GetRedirectURL(); | 326 GURL redirect_url = fetcher->GetRedirectURL(); |
346 if (!redirect_url.is_empty()) { | 327 if (!redirect_url.is_empty()) { |
347 // And around we go again... Whee! | 328 // And around we go again... Whee! |
348 ConnectToApplicationWithParameters(redirect_url, requestor_url, | 329 ConnectToApplicationWithParameters(redirect_url, requestor_url, |
349 services.Pass(), exposed_services.Pass(), | 330 services.Pass(), on_application_end, |
350 on_application_end, parameters); | 331 parameters); |
351 return; | 332 return; |
352 } | 333 } |
353 | 334 |
354 // We already checked if the application was running before we fetched it, but | 335 // We already checked if the application was running before we fetched it, but |
355 // it might have started while the fetch was outstanding. We don't want to | 336 // it might have started while the fetch was outstanding. We don't want to |
356 // have two copies of the app running, so check again. | 337 // have two copies of the app running, so check again. |
357 // | 338 // |
358 // Also, it's possible the original URL was redirected to an app that is | 339 // Also, it's possible the original URL was redirected to an app that is |
359 // already running. | 340 // already running. |
360 if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services, | 341 if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services)) |
361 &exposed_services)) { | |
362 return; | 342 return; |
363 } | |
364 | 343 |
365 InterfaceRequest<Application> request( | 344 InterfaceRequest<Application> request( |
366 RegisterShell(fetcher->GetURL(), requestor_url, services.Pass(), | 345 RegisterShell(fetcher->GetURL(), requestor_url, services.Pass(), |
367 exposed_services.Pass(), on_application_end, parameters)); | 346 on_application_end, parameters)); |
368 | 347 |
369 // If the response begins with a #!mojo <content-handler-url>, use it. | 348 // If the response begins with a #!mojo <content-handler-url>, use it. |
370 GURL content_handler_url; | 349 GURL content_handler_url; |
371 std::string shebang; | 350 std::string shebang; |
372 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { | 351 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { |
373 LoadWithContentHandler( | 352 LoadWithContentHandler( |
374 content_handler_url, request.Pass(), | 353 content_handler_url, request.Pass(), |
375 fetcher->AsURLResponse(blocking_pool_, | 354 fetcher->AsURLResponse(blocking_pool_, |
376 static_cast<int>(shebang.size()))); | 355 static_cast<int>(shebang.size()))); |
377 return; | 356 return; |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 auto it = identity_to_content_handler_.find(content_handler->identity()); | 510 auto it = identity_to_content_handler_.find(content_handler->identity()); |
532 DCHECK(it != identity_to_content_handler_.end()); | 511 DCHECK(it != identity_to_content_handler_.end()); |
533 identity_to_content_handler_.erase(it); | 512 identity_to_content_handler_.erase(it); |
534 } | 513 } |
535 | 514 |
536 mojo::ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( | 515 mojo::ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( |
537 const GURL& application_url, | 516 const GURL& application_url, |
538 const std::string& interface_name) { | 517 const std::string& interface_name) { |
539 ServiceProviderPtr services; | 518 ServiceProviderPtr services; |
540 ConnectToApplication(application_url, GURL(), mojo::GetProxy(&services), | 519 ConnectToApplication(application_url, GURL(), mojo::GetProxy(&services), |
541 nullptr, base::Closure()); | 520 base::Closure()); |
542 mojo::MessagePipe pipe; | 521 mojo::MessagePipe pipe; |
543 services->ConnectToService(interface_name, pipe.handle1.Pass()); | 522 services->ConnectToService(interface_name, pipe.handle1.Pass()); |
544 return pipe.handle0.Pass(); | 523 return pipe.handle0.Pass(); |
545 } | 524 } |
546 | 525 |
547 std::vector<std::string> ApplicationManager::GetArgsForURL(const GURL& url) { | 526 std::vector<std::string> ApplicationManager::GetArgsForURL(const GURL& url) { |
548 GURL base_url = GetBaseURLAndQuery(url, nullptr); | 527 GURL base_url = GetBaseURLAndQuery(url, nullptr); |
549 const auto& args_it = url_to_args_.find(base_url); | 528 const auto& args_it = url_to_args_.find(base_url); |
550 if (args_it != url_to_args_.end()) | 529 if (args_it != url_to_args_.end()) |
551 return args_it->second; | 530 return args_it->second; |
552 return std::vector<std::string>(); | 531 return std::vector<std::string>(); |
553 } | 532 } |
554 | 533 |
555 void ApplicationManager::CleanupRunner(NativeRunner* runner) { | 534 void ApplicationManager::CleanupRunner(NativeRunner* runner) { |
556 native_runners_.erase( | 535 native_runners_.erase( |
557 std::find(native_runners_.begin(), native_runners_.end(), runner)); | 536 std::find(native_runners_.begin(), native_runners_.end(), runner)); |
558 } | 537 } |
559 | 538 |
560 } // namespace shell | 539 } // namespace shell |
OLD | NEW |