blob: 6e7b9657786238f255fcfc1039c404c548eaafb0 [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// Copyright 2014 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
Przemysław Pietrzkiewicz6384d092015-01-15 16:03:17 -08005#include "shell/application_manager/application_manager.h"
James Robinson646469d2014-10-03 15:33:28 -07006
James Robinson646469d2014-10-03 15:33:28 -07007#include "base/bind.h"
Scott Violetef1cb8c2015-03-13 14:01:39 -07008#include "base/command_line.h"
James Robinson646469d2014-10-03 15:33:28 -07009#include "base/logging.h"
10#include "base/macros.h"
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -080011#include "base/strings/string_util.h"
James Robinson6bbb9e02015-03-27 13:42:35 -070012#include "base/trace_event/trace_event.h"
James Robinson43fd6832014-11-12 16:24:27 -080013#include "mojo/public/cpp/bindings/binding.h"
Viet-Trung Luu08e339a2015-10-10 01:03:09 -070014#include "mojo/services/authenticating_url_loader_interceptor/interfaces/authenticating_url_loader_interceptor_meta_factory.mojom.h"
15#include "mojo/services/authentication/interfaces/authentication.mojom.h"
16#include "mojo/services/content_handler/interfaces/content_handler.mojom.h"
Aaron Boodman5e7f9042015-02-24 17:37:34 -080017#include "shell/application_manager/fetcher.h"
18#include "shell/application_manager/local_fetcher.h"
19#include "shell/application_manager/network_fetcher.h"
Benjamin Lerman05eccab2015-03-05 15:29:39 +010020#include "shell/application_manager/query_util.h"
Viet-Trung Luu3f2970c2015-03-05 10:21:56 -080021#include "shell/application_manager/shell_impl.h"
James Robinson646469d2014-10-03 15:33:28 -070022
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070023using mojo::Application;
24using mojo::ApplicationPtr;
25using mojo::InterfaceRequest;
26using mojo::ServiceProvider;
27using mojo::ServiceProviderPtr;
28
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -080029namespace shell {
James Robinson646469d2014-10-03 15:33:28 -070030
31namespace {
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -080032
James Robinson646469d2014-10-03 15:33:28 -070033// Used by TestAPI.
34bool has_created_instance = false;
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -080035
Benjamin Lermanacf32fb2015-03-24 10:54:37 +010036std::vector<std::string> Concatenate(const std::vector<std::string>& v1,
37 const std::vector<std::string>& v2) {
38 if (!v1.size())
39 return v2;
40 if (!v2.size())
41 return v1;
42 std::vector<std::string> result(v1);
43 result.insert(result.end(), v1.begin(), v1.end());
44 return result;
45}
46
James Robinson646469d2014-10-03 15:33:28 -070047} // namespace
48
Viet-Trung Luu01e64cf2015-07-08 09:55:53 -070049class ApplicationManager::ContentHandlerConnection {
Benjamin Lerman7c057142014-10-31 18:23:10 +010050 public:
James Robinson646469d2014-10-03 15:33:28 -070051 ContentHandlerConnection(ApplicationManager* manager,
Benjamin Lerman7c057142014-10-31 18:23:10 +010052 const GURL& content_handler_url)
53 : manager_(manager), content_handler_url_(content_handler_url) {
Viet-Trung Luue377a9e2015-04-09 13:53:21 -070054 ServiceProviderPtr services;
James Robinson3217bf32015-01-14 14:33:07 -080055 manager->ConnectToApplication(content_handler_url, GURL(),
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -070056 mojo::GetProxy(&services), nullptr,
Benjamin Lerman993869e2015-03-24 13:35:28 +010057 base::Closure());
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -070058 mojo::MessagePipe pipe;
yzshen5bae2232015-05-04 14:47:01 -070059 content_handler_.Bind(
60 mojo::InterfacePtrInfo<mojo::ContentHandler>(pipe.handle0.Pass(), 0u));
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -070061 services->ConnectToService(mojo::ContentHandler::Name_,
62 pipe.handle1.Pass());
Viet-Trung Luu01e64cf2015-07-08 09:55:53 -070063 content_handler_.set_connection_error_handler(
64 [this]() { manager_->OnContentHandlerError(this); });
James Robinson646469d2014-10-03 15:33:28 -070065 }
Viet-Trung Luu01e64cf2015-07-08 09:55:53 -070066 ~ContentHandlerConnection() {}
James Robinson646469d2014-10-03 15:33:28 -070067
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -070068 mojo::ContentHandler* content_handler() { return content_handler_.get(); }
Benjamin Lerman7c057142014-10-31 18:23:10 +010069
70 GURL content_handler_url() { return content_handler_url_; }
71
72 private:
Benjamin Lerman7c057142014-10-31 18:23:10 +010073 ApplicationManager* manager_;
74 GURL content_handler_url_;
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -070075 mojo::ContentHandlerPtr content_handler_;
Benjamin Lerman7c057142014-10-31 18:23:10 +010076
77 DISALLOW_COPY_AND_ASSIGN(ContentHandlerConnection);
James Robinson646469d2014-10-03 15:33:28 -070078};
79
80// static
81ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager)
82 : manager_(manager) {
83}
84
85ApplicationManager::TestAPI::~TestAPI() {
86}
87
88bool ApplicationManager::TestAPI::HasCreatedInstance() {
89 return has_created_instance;
90}
91
92bool ApplicationManager::TestAPI::HasFactoryForURL(const GURL& url) const {
Benjamin Lerman71f56072015-03-12 15:04:50 +010093 return manager_->identity_to_shell_impl_.find(Identity(url)) !=
94 manager_->identity_to_shell_impl_.end();
James Robinson646469d2014-10-03 15:33:28 -070095}
96
Viet-Trung Luu988b4be2015-05-15 13:00:15 -070097ApplicationManager::ApplicationManager(const Options& options,
98 Delegate* delegate)
99 : options_(options),
100 delegate_(delegate),
Viet-Trung Luu768bef72015-05-14 15:20:45 -0700101 blocking_pool_(nullptr),
Colin Blundell8ca4d652015-06-05 16:41:30 +0200102 initialized_authentication_interceptor_(false),
Viet-Trung Luu768bef72015-05-14 15:20:45 -0700103 weak_ptr_factory_(this) {
James Robinson646469d2014-10-03 15:33:28 -0700104}
105
106ApplicationManager::~ApplicationManager() {
James Robinson646469d2014-10-03 15:33:28 -0700107}
108
109void ApplicationManager::TerminateShellConnections() {
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700110 identity_to_shell_impl_.clear();
James Robinson646469d2014-10-03 15:33:28 -0700111}
112
James Robinson646469d2014-10-03 15:33:28 -0700113void ApplicationManager::ConnectToApplication(
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800114 const GURL& requested_url,
James Robinson646469d2014-10-03 15:33:28 -0700115 const GURL& requestor_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700116 InterfaceRequest<ServiceProvider> services,
117 ServiceProviderPtr exposed_services,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100118 const base::Closure& on_application_end) {
119 ConnectToApplicationWithParameters(
120 requested_url, requestor_url, services.Pass(), exposed_services.Pass(),
121 on_application_end, std::vector<std::string>());
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100122}
123
124void ApplicationManager::ConnectToApplicationWithParameters(
125 const GURL& requested_url,
126 const GURL& requestor_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700127 InterfaceRequest<ServiceProvider> services,
128 ServiceProviderPtr exposed_services,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100129 const base::Closure& on_application_end,
Benjamin Lerman128ca7d2015-03-24 12:02:49 +0100130 const std::vector<std::string>& pre_redirect_parameters) {
Benjamin Lerman93545662015-08-03 11:51:19 +0200131 TRACE_EVENT_INSTANT2(
James Robinson6bbb9e02015-03-27 13:42:35 -0700132 "mojo_shell", "ApplicationManager::ConnectToApplicationWithParameters",
Benjamin Lerman93545662015-08-03 11:51:19 +0200133 TRACE_EVENT_SCOPE_THREAD, "requested_url", requested_url.spec(),
134 "requestor_url", requestor_url.spec());
Alexandre Zani22190df2014-11-21 10:02:28 -0800135 DCHECK(requested_url.is_valid());
Dave Moore0504d062015-01-23 15:33:29 -0800136
137 // We check both the mapped and resolved urls for existing shell_impls because
138 // external applications can be registered for the unresolved mojo:foo urls.
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800139
140 GURL mapped_url = delegate_->ResolveMappings(requested_url);
141 if (ConnectToRunningApplication(mapped_url, requestor_url, &services,
142 &exposed_services)) {
Dave Moore0504d062015-01-23 15:33:29 -0800143 return;
144 }
145
Benjamin Lerman605969e2015-04-30 13:51:04 +0200146 GURL resolved_url = delegate_->ResolveMojoURL(mapped_url);
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800147 if (ConnectToRunningApplication(resolved_url, requestor_url, &services,
148 &exposed_services)) {
Dave Moore0504d062015-01-23 15:33:29 -0800149 return;
150 }
151
Benjamin Lerman128ca7d2015-03-24 12:02:49 +0100152 // The application is not running, let's compute the parameters.
153 std::vector<std::string> parameters =
154 Concatenate(pre_redirect_parameters, GetArgsForURL(resolved_url));
155
Benjamin Lerman993869e2015-03-24 13:35:28 +0100156 if (ConnectToApplicationWithLoader(mapped_url, requestor_url, &services,
157 &exposed_services, on_application_end,
158 parameters, GetLoaderForURL(mapped_url))) {
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800159 return;
160 }
161
Benjamin Lerman993869e2015-03-24 13:35:28 +0100162 if (ConnectToApplicationWithLoader(
163 resolved_url, requestor_url, &services, &exposed_services,
164 on_application_end, parameters, GetLoaderForURL(resolved_url))) {
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800165 return;
166 }
167
Benjamin Lerman993869e2015-03-24 13:35:28 +0100168 if (ConnectToApplicationWithLoader(resolved_url, requestor_url, &services,
169 &exposed_services, on_application_end,
170 parameters, default_loader_.get())) {
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800171 return;
172 }
173
Benjamin Lerman993869e2015-03-24 13:35:28 +0100174 auto callback = base::Bind(
175 &ApplicationManager::HandleFetchCallback, weak_ptr_factory_.GetWeakPtr(),
176 requestor_url, base::Passed(services.Pass()),
Benjamin Lerman4abbaff2015-09-01 16:24:06 +0200177 base::Passed(exposed_services.Pass()), on_application_end, parameters);
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800178
179 if (resolved_url.SchemeIsFile()) {
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200180 new LocalFetcher(resolved_url, GetBaseURLAndQuery(resolved_url, nullptr),
181 callback);
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800182 return;
183 }
184
Colin Blundell82e1c7e2015-05-26 15:37:46 +0200185 if (!url_response_disk_cache_) {
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200186 ConnectToService(GURL("mojo:url_response_disk_cache"),
187 &url_response_disk_cache_);
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200188 ConnectToService(GURL("mojo:network_service"), &network_service_);
189 ConnectToService(GURL("mojo:network_service"),
190 &authenticating_network_service_);
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200191 }
Scott Violetef1cb8c2015-03-13 14:01:39 -0700192
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200193 mojo::NetworkService* network_service = authenticating_network_service_.get();
Colin Blundell82e1c7e2015-05-26 15:37:46 +0200194
Colin Blundell8ca4d652015-06-05 16:41:30 +0200195 // NOTE: Attempting to initialize the apps used authentication for while
196 // connecting to those apps would result in a recursive loop, so it has to be
197 // explicitly avoided here. What this means in practice is that these apps
198 // cannot themselves require authentication to obtain.
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200199 if (EndsWith(resolved_url.path(), "/authentication.mojo", true) ||
200 EndsWith(resolved_url.path(),
201 "/authenticating_url_loader_interceptor.mojo", true)) {
202 network_service = network_service_.get();
203 } else if (!initialized_authentication_interceptor_) {
Colin Blundell82e1c7e2015-05-26 15:37:46 +0200204 authentication::AuthenticationServicePtr authentication_service;
205 ConnectToService(GURL("mojo:authentication"), &authentication_service);
Colin Blundellcde1f382015-06-08 14:13:54 +0200206 mojo::AuthenticatingURLLoaderInterceptorMetaFactoryPtr
207 interceptor_meta_factory;
208 ConnectToService(GURL("mojo:authenticating_url_loader_interceptor"),
209 &interceptor_meta_factory);
Colin Blundell8ca4d652015-06-05 16:41:30 +0200210 mojo::URLLoaderInterceptorFactoryPtr interceptor_factory;
Colin Blundellcde1f382015-06-08 14:13:54 +0200211 interceptor_meta_factory->CreateURLLoaderInterceptorFactory(
Colin Blundell8ca4d652015-06-05 16:41:30 +0200212 GetProxy(&interceptor_factory), authentication_service.Pass());
Benjamin Lermand15e3f42015-09-17 11:26:18 +0200213 authenticating_network_service_->RegisterURLLoaderInterceptor(
214 interceptor_factory.Pass());
Colin Blundell8ca4d652015-06-05 16:41:30 +0200215 initialized_authentication_interceptor_ = true;
Colin Blundell82e1c7e2015-05-26 15:37:46 +0200216 }
217
Benjamin Lerman9a258502015-09-17 16:53:28 +0200218 new NetworkFetcher(options_.disable_cache, options_.force_offline_by_default,
219 resolved_url, url_response_disk_cache_.get(),
220 network_service, callback);
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800221}
222
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800223bool ApplicationManager::ConnectToRunningApplication(
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -0800224 const GURL& resolved_url,
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800225 const GURL& requestor_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700226 InterfaceRequest<ServiceProvider>* services,
227 ServiceProviderPtr* exposed_services) {
Benjamin Lerman05eccab2015-03-05 15:29:39 +0100228 GURL application_url = GetBaseURLAndQuery(resolved_url, nullptr);
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800229 ShellImpl* shell_impl = GetShellImpl(application_url);
230 if (!shell_impl)
231 return false;
232
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -0800233 ConnectToClient(shell_impl, resolved_url, requestor_url, services->Pass(),
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800234 exposed_services->Pass());
235 return true;
236}
237
238bool ApplicationManager::ConnectToApplicationWithLoader(
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800239 const GURL& resolved_url,
240 const GURL& requestor_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700241 InterfaceRequest<ServiceProvider>* services,
242 ServiceProviderPtr* exposed_services,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100243 const base::Closure& on_application_end,
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100244 const std::vector<std::string>& parameters,
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800245 ApplicationLoader* loader) {
246 if (!loader)
247 return false;
248
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100249 loader->Load(
250 resolved_url,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100251 RegisterShell(resolved_url, requestor_url, services->Pass(),
252 exposed_services->Pass(), on_application_end, parameters));
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800253 return true;
254}
255
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700256InterfaceRequest<Application> ApplicationManager::RegisterShell(
Benjamin Lerman51701292014-11-21 10:53:37 +0100257 const GURL& resolved_url,
258 const GURL& requestor_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700259 InterfaceRequest<ServiceProvider> services,
260 ServiceProviderPtr exposed_services,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100261 const base::Closure& on_application_end,
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100262 const std::vector<std::string>& parameters) {
Benjamin Lerman71f56072015-03-12 15:04:50 +0100263 Identity app_identity(resolved_url);
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -0800264
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -0700265 mojo::ApplicationPtr application;
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700266 InterfaceRequest<Application> application_request =
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -0700267 mojo::GetProxy(&application);
Dave Moore0504d062015-01-23 15:33:29 -0800268 ShellImpl* shell =
Benjamin Lerman993869e2015-03-24 13:35:28 +0100269 new ShellImpl(application.Pass(), this, app_identity, on_application_end);
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700270 identity_to_shell_impl_[app_identity] = make_scoped_ptr(shell);
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -0700271 shell->InitializeApplication(mojo::Array<mojo::String>::From(parameters));
James Robinson3217bf32015-01-14 14:33:07 -0800272 ConnectToClient(shell, resolved_url, requestor_url, services.Pass(),
273 exposed_services.Pass());
Viet-Trung Luub792c802015-10-27 11:27:35 -0700274 return application_request;
James Robinson646469d2014-10-03 15:33:28 -0700275}
276
Dave Moore0504d062015-01-23 15:33:29 -0800277ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) {
Benjamin Lerman71f56072015-03-12 15:04:50 +0100278 const auto& shell_it = identity_to_shell_impl_.find(Identity(url));
279 if (shell_it != identity_to_shell_impl_.end())
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700280 return shell_it->second.get();
Dave Moore0504d062015-01-23 15:33:29 -0800281 return nullptr;
282}
283
James Robinson3217bf32015-01-14 14:33:07 -0800284void ApplicationManager::ConnectToClient(
285 ShellImpl* shell_impl,
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -0800286 const GURL& resolved_url,
James Robinson3217bf32015-01-14 14:33:07 -0800287 const GURL& requestor_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700288 InterfaceRequest<ServiceProvider> services,
289 ServiceProviderPtr exposed_services) {
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -0800290 shell_impl->ConnectToClient(resolved_url, requestor_url, services.Pass(),
James Robinson3217bf32015-01-14 14:33:07 -0800291 exposed_services.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700292}
293
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800294void ApplicationManager::HandleFetchCallback(
Aaron Boodmandf23d132015-02-25 13:43:19 -0800295 const GURL& requestor_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700296 InterfaceRequest<ServiceProvider> services,
297 ServiceProviderPtr exposed_services,
Benjamin Lerman993869e2015-03-24 13:35:28 +0100298 const base::Closure& on_application_end,
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100299 const std::vector<std::string>& parameters,
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800300 scoped_ptr<Fetcher> fetcher) {
301 if (!fetcher) {
302 // Network error. Drop |application_request| to tell requestor.
303 return;
304 }
305
Aaron Boodmandf23d132015-02-25 13:43:19 -0800306 GURL redirect_url = fetcher->GetRedirectURL();
307 if (!redirect_url.is_empty()) {
308 // And around we go again... Whee!
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100309 ConnectToApplicationWithParameters(redirect_url, requestor_url,
310 services.Pass(), exposed_services.Pass(),
Benjamin Lerman993869e2015-03-24 13:35:28 +0100311 on_application_end, parameters);
Aaron Boodmandf23d132015-02-25 13:43:19 -0800312 return;
313 }
314
315 // We already checked if the application was running before we fetched it, but
316 // it might have started while the fetch was outstanding. We don't want to
317 // have two copies of the app running, so check again.
318 //
319 // Also, it's possible the original URL was redirected to an app that is
320 // already running.
321 if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services,
322 &exposed_services)) {
323 return;
324 }
325
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700326 InterfaceRequest<Application> request(
Benjamin Lerman993869e2015-03-24 13:35:28 +0100327 RegisterShell(fetcher->GetURL(), requestor_url, services.Pass(),
328 exposed_services.Pass(), on_application_end, parameters));
Aaron Boodmandf23d132015-02-25 13:43:19 -0800329
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800330 // If the response begins with a #!mojo <content-handler-url>, use it.
Aaron Boodmandf23d132015-02-25 13:43:19 -0800331 GURL content_handler_url;
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800332 std::string shebang;
Aaron Boodmandf23d132015-02-25 13:43:19 -0800333 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) {
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800334 LoadWithContentHandler(
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -0800335 content_handler_url, request.Pass(),
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800336 fetcher->AsURLResponse(blocking_pool_,
337 static_cast<int>(shebang.size())));
338 return;
339 }
340
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700341 auto it = mime_type_to_url_.find(fetcher->MimeType());
342 if (it != mime_type_to_url_.end()) {
343 LoadWithContentHandler(it->second, request.Pass(),
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800344 fetcher->AsURLResponse(blocking_pool_, 0));
345 return;
346 }
347
348 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo
349 // application. That could either mean looking for the platform-specific dll
350 // header, or looking for some specific mojo signature prepended to the
351 // library.
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800352 // TODO(vtl): (Maybe this should be done by the factory/runner?)
353
Viet-Trung Luu915cdc52015-03-09 09:55:30 -0700354 GURL base_resolved_url = GetBaseURLAndQuery(fetcher->GetURL(), nullptr);
Viet-Trung Luu64bb17c2015-10-02 17:02:04 -0700355 NativeApplicationOptions options;
Viet-Trung Luu915cdc52015-03-09 09:55:30 -0700356 if (url_to_native_options_.find(base_resolved_url) !=
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800357 url_to_native_options_.end()) {
358 DVLOG(2) << "Applying stored native options to resolved URL "
Benjamin Lerman993869e2015-03-24 13:35:28 +0100359 << fetcher->GetURL();
Viet-Trung Luu915cdc52015-03-09 09:55:30 -0700360 options = url_to_native_options_[base_resolved_url];
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800361 }
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800362
Benjamin Lerman4abbaff2015-09-01 16:24:06 +0200363 TRACE_EVENT_ASYNC_BEGIN1("mojo_shell", "ApplicationManager::RetrievePath",
364 fetcher.get(), "url", fetcher->GetURL().spec());
Aaron Boodmanb34bcbf2015-03-02 10:05:31 -0800365 fetcher->AsPath(
366 blocking_pool_,
367 base::Bind(&ApplicationManager::RunNativeApplication,
368 weak_ptr_factory_.GetWeakPtr(), base::Passed(request.Pass()),
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200369 options, base::Passed(fetcher.Pass())));
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800370}
371
372void ApplicationManager::RunNativeApplication(
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700373 InterfaceRequest<Application> application_request,
Viet-Trung Luu64bb17c2015-10-02 17:02:04 -0700374 const NativeApplicationOptions& options,
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800375 scoped_ptr<Fetcher> fetcher,
376 const base::FilePath& path,
377 bool path_exists) {
Benjamin Lerman4abbaff2015-09-01 16:24:06 +0200378 TRACE_EVENT_ASYNC_END0("mojo_shell", "ApplicationManager::RetrievePath",
379 fetcher.get());
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800380 // We only passed fetcher to keep it alive. Done with it now.
381 fetcher.reset();
382
383 DCHECK(application_request.is_pending());
384
385 if (!path_exists) {
386 LOG(ERROR) << "Library not started because library path '" << path.value()
387 << "' does not exist.";
388 return;
389 }
390
James Robinson6bbb9e02015-03-27 13:42:35 -0700391 TRACE_EVENT1("mojo_shell", "ApplicationManager::RunNativeApplication", "path",
392 path.AsUTF8Unsafe());
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800393 NativeRunner* runner = native_runner_factory_->Create(options).release();
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800394 native_runners_.push_back(runner);
Benjamin Lerman5d429aa2015-05-07 16:21:00 +0200395 runner->Start(path, application_request.Pass(),
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800396 base::Bind(&ApplicationManager::CleanupRunner,
397 weak_ptr_factory_.GetWeakPtr(), runner));
398}
399
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800400void ApplicationManager::RegisterContentHandler(
401 const std::string& mime_type,
402 const GURL& content_handler_url) {
403 DCHECK(content_handler_url.is_valid())
404 << "Content handler URL is invalid for mime type " << mime_type;
405 mime_type_to_url_[mime_type] = content_handler_url;
406}
407
James Robinson646469d2014-10-03 15:33:28 -0700408void ApplicationManager::LoadWithContentHandler(
James Robinson646469d2014-10-03 15:33:28 -0700409 const GURL& content_handler_url,
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700410 InterfaceRequest<Application> application_request,
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -0700411 mojo::URLResponsePtr url_response) {
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -0800412 ContentHandlerConnection* connection = nullptr;
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700413 auto it = url_to_content_handler_.find(content_handler_url);
414 if (it != url_to_content_handler_.end()) {
415 connection = it->second.get();
James Robinson646469d2014-10-03 15:33:28 -0700416 } else {
417 connection = new ContentHandlerConnection(this, content_handler_url);
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700418 url_to_content_handler_[content_handler_url] = make_scoped_ptr(connection);
James Robinson646469d2014-10-03 15:33:28 -0700419 }
420
James Robinsone5ae9e42015-01-26 17:53:08 -0800421 connection->content_handler()->StartApplication(application_request.Pass(),
422 url_response.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700423}
424
425void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader,
426 const GURL& url) {
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700427 url_to_loader_[url] = loader.Pass();
James Robinson646469d2014-10-03 15:33:28 -0700428}
429
430void ApplicationManager::SetLoaderForScheme(
431 scoped_ptr<ApplicationLoader> loader,
432 const std::string& scheme) {
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700433 scheme_to_loader_[scheme] = loader.Pass();
James Robinson646469d2014-10-03 15:33:28 -0700434}
435
436void ApplicationManager::SetArgsForURL(const std::vector<std::string>& args,
437 const GURL& url) {
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100438 url_to_args_[url].insert(url_to_args_[url].end(), args.begin(), args.end());
439 GURL mapped_url = delegate_->ResolveMappings(url);
440 if (mapped_url != url) {
441 url_to_args_[mapped_url].insert(url_to_args_[mapped_url].end(),
442 args.begin(), args.end());
443 }
Benjamin Lerman605969e2015-04-30 13:51:04 +0200444 GURL resolved_url = delegate_->ResolveMojoURL(mapped_url);
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100445 if (resolved_url != mapped_url) {
446 url_to_args_[resolved_url].insert(url_to_args_[resolved_url].end(),
447 args.begin(), args.end());
448 }
James Robinson646469d2014-10-03 15:33:28 -0700449}
450
Viet-Trung Luu64bb17c2015-10-02 17:02:04 -0700451NativeApplicationOptions* ApplicationManager::GetNativeApplicationOptionsForURL(
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800452 const GURL& url) {
Viet-Trung Luu915cdc52015-03-09 09:55:30 -0700453 DCHECK(!url.has_query()); // Precondition.
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800454 // Apply mappings and resolution to get the resolved URL.
Benjamin Lerman605969e2015-04-30 13:51:04 +0200455 GURL resolved_url =
456 delegate_->ResolveMojoURL(delegate_->ResolveMappings(url));
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800457 // TODO(vtl): We should probably also remove/disregard the query string (and
458 // maybe canonicalize in other ways).
Viet-Trung Luu64bb17c2015-10-02 17:02:04 -0700459 DCHECK(!resolved_url.has_query()); // Still shouldn't have query.
460 return &url_to_native_options_[resolved_url];
Viet-Trung Luufbf0a4e2015-03-04 14:37:27 -0800461}
462
Aaron Boodmanbfc11182015-02-19 12:42:19 -0800463ApplicationLoader* ApplicationManager::GetLoaderForURL(const GURL& url) {
Benjamin Lerman05eccab2015-03-05 15:29:39 +0100464 auto url_it = url_to_loader_.find(GetBaseURLAndQuery(url, nullptr));
James Robinson646469d2014-10-03 15:33:28 -0700465 if (url_it != url_to_loader_.end())
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700466 return url_it->second.get();
Aaron Boodmancd7b9112014-11-06 21:44:49 -0800467 auto scheme_it = scheme_to_loader_.find(url.scheme());
James Robinson646469d2014-10-03 15:33:28 -0700468 if (scheme_it != scheme_to_loader_.end())
Viet-Trung Luub3cadd22015-05-14 15:57:05 -0700469 return scheme_it->second.get();
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -0800470 return nullptr;
James Robinson646469d2014-10-03 15:33:28 -0700471}
472
473void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) {
474 // Called from ~ShellImpl, so we do not need to call Destroy here.
Benjamin Lerman71f56072015-03-12 15:04:50 +0100475 const Identity identity = shell_impl->identity();
Benjamin Lerman993869e2015-03-24 13:35:28 +0100476 base::Closure on_application_end = shell_impl->on_application_end();
Benjamin Lerman7c057142014-10-31 18:23:10 +0100477 // Remove the shell.
Benjamin Lerman71f56072015-03-12 15:04:50 +0100478 auto it = identity_to_shell_impl_.find(identity);
479 DCHECK(it != identity_to_shell_impl_.end());
Benjamin Lerman71f56072015-03-12 15:04:50 +0100480 identity_to_shell_impl_.erase(it);
Benjamin Lerman993869e2015-03-24 13:35:28 +0100481 if (!on_application_end.is_null())
482 on_application_end.Run();
James Robinson646469d2014-10-03 15:33:28 -0700483}
484
Benjamin Lerman7c057142014-10-31 18:23:10 +0100485void ApplicationManager::OnContentHandlerError(
486 ContentHandlerConnection* content_handler) {
487 // Remove the mapping to the content handler.
488 auto it =
489 url_to_content_handler_.find(content_handler->content_handler_url());
490 DCHECK(it != url_to_content_handler_.end());
Benjamin Lerman7c057142014-10-31 18:23:10 +0100491 url_to_content_handler_.erase(it);
492}
493
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -0700494mojo::ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName(
James Robinson646469d2014-10-03 15:33:28 -0700495 const GURL& application_url,
496 const std::string& interface_name) {
Viet-Trung Luue377a9e2015-04-09 13:53:21 -0700497 ServiceProviderPtr services;
Viet-Trung Luubd07e3a2015-04-09 12:43:29 -0700498 ConnectToApplication(application_url, GURL(), mojo::GetProxy(&services),
499 nullptr, base::Closure());
500 mojo::MessagePipe pipe;
James Robinson3217bf32015-01-14 14:33:07 -0800501 services->ConnectToService(interface_name, pipe.handle1.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700502 return pipe.handle0.Pass();
503}
Benjamin Lerman7c057142014-10-31 18:23:10 +0100504
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100505std::vector<std::string> ApplicationManager::GetArgsForURL(const GURL& url) {
Dave Moorec5ee10b2015-01-29 09:44:24 -0800506 const auto& args_it = url_to_args_.find(url);
Benjamin Lerman7c057142014-10-31 18:23:10 +0100507 if (args_it != url_to_args_.end())
Benjamin Lermanacf32fb2015-03-24 10:54:37 +0100508 return args_it->second;
509 return std::vector<std::string>();
Benjamin Lerman7c057142014-10-31 18:23:10 +0100510}
Aaron Boodman5e7f9042015-02-24 17:37:34 -0800511
512void ApplicationManager::CleanupRunner(NativeRunner* runner) {
513 native_runners_.erase(
514 std::find(native_runners_.begin(), native_runners_.end(), runner));
515}
516
Viet-Trung Luu36faa4d2015-03-04 18:08:18 -0800517} // namespace shell