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

Side by Side Diff: shell/application_manager/application_manager.cc

Issue 943053003: Simple multi-url support for mojo apps (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 9 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
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 <stdio.h> 7 #include <stdio.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h"
14 #include "mojo/public/cpp/bindings/binding.h" 15 #include "mojo/public/cpp/bindings/binding.h"
15 #include "mojo/public/cpp/bindings/error_handler.h" 16 #include "mojo/public/cpp/bindings/error_handler.h"
16 #include "mojo/public/interfaces/application/shell.mojom.h" 17 #include "mojo/public/interfaces/application/shell.mojom.h"
17 #include "mojo/services/content_handler/public/interfaces/content_handler.mojom. h" 18 #include "mojo/services/content_handler/public/interfaces/content_handler.mojom. h"
18 #include "shell/application_manager/fetcher.h" 19 #include "shell/application_manager/fetcher.h"
19 #include "shell/application_manager/local_fetcher.h" 20 #include "shell/application_manager/local_fetcher.h"
20 #include "shell/application_manager/network_fetcher.h" 21 #include "shell/application_manager/network_fetcher.h"
21 22
22 namespace mojo { 23 namespace mojo {
23 24
24 namespace { 25 namespace {
25 // Used by TestAPI. 26 // Used by TestAPI.
26 bool has_created_instance = false; 27 bool has_created_instance = false;
28
29 GURL StripQueryFromURL(const GURL& url) {
30 GURL::Replacements repl;
31 repl.SetQueryStr("");
32 std::string result = url.ReplaceComponents(repl).spec();
33
34 // Remove the dangling '?' because it's ugly.
35 base::ReplaceChars(result, "?", "", &result);
36 return GURL(result);
37 }
38
27 } // namespace 39 } // namespace
28 40
29 ApplicationManager::Delegate::~Delegate() { 41 ApplicationManager::Delegate::~Delegate() {
30 } 42 }
31 43
32 void ApplicationManager::Delegate::OnApplicationError(const GURL& url) { 44 void ApplicationManager::Delegate::OnApplicationError(const GURL& url) {
33 LOG(ERROR) << "Communication error with application: " << url.spec(); 45 LOG(ERROR) << "Communication error with application: " << url.spec();
34 } 46 }
35 47
36 GURL ApplicationManager::Delegate::ResolveURL(const GURL& url) { 48 GURL ApplicationManager::Delegate::ResolveURL(const GURL& url) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 const GURL& requested_url, 118 const GURL& requested_url,
107 const GURL& requestor_url, 119 const GURL& requestor_url,
108 InterfaceRequest<ServiceProvider> services, 120 InterfaceRequest<ServiceProvider> services,
109 ServiceProviderPtr exposed_services) { 121 ServiceProviderPtr exposed_services) {
110 DCHECK(requested_url.is_valid()); 122 DCHECK(requested_url.is_valid());
111 123
112 // We check both the mapped and resolved urls for existing shell_impls because 124 // We check both the mapped and resolved urls for existing shell_impls because
113 // external applications can be registered for the unresolved mojo:foo urls. 125 // external applications can be registered for the unresolved mojo:foo urls.
114 126
115 GURL mapped_url = delegate_->ResolveMappings(requested_url); 127 GURL mapped_url = delegate_->ResolveMappings(requested_url);
116 if (ConnectToRunningApplication(mapped_url, requestor_url, &services, 128 if (ConnectToRunningApplication(requested_url, mapped_url, requestor_url,
qsr 2015/02/27 15:01:41 I think the URL that the application see should be
Aaron Boodman 2015/02/27 16:54:44 Done.
117 &exposed_services)) { 129 &services, &exposed_services)) {
118 return; 130 return;
119 } 131 }
120 132
121 GURL resolved_url = delegate_->ResolveURL(mapped_url); 133 GURL resolved_url = delegate_->ResolveURL(mapped_url);
122 if (ConnectToRunningApplication(resolved_url, requestor_url, &services, 134 if (ConnectToRunningApplication(requested_url, resolved_url, requestor_url,
123 &exposed_services)) { 135 &services, &exposed_services)) {
124 return; 136 return;
125 } 137 }
126 138
127 if (ConnectToApplicationWithLoader(requested_url, mapped_url, requestor_url, 139 if (ConnectToApplicationWithLoader(requested_url, mapped_url, requestor_url,
128 &services, &exposed_services, 140 &services, &exposed_services,
129 GetLoaderForURL(mapped_url))) { 141 GetLoaderForURL(mapped_url))) {
130 return; 142 return;
131 } 143 }
132 144
133 if (ConnectToApplicationWithLoader(requested_url, resolved_url, requestor_url, 145 if (ConnectToApplicationWithLoader(requested_url, resolved_url, requestor_url,
(...skipping 20 matching lines...) Expand all
154 } 166 }
155 167
156 if (!network_service_) 168 if (!network_service_)
157 ConnectToService(GURL("mojo:network_service"), &network_service_); 169 ConnectToService(GURL("mojo:network_service"), &network_service_);
158 170
159 new NetworkFetcher(disable_cache_, resolved_url, network_service_.get(), 171 new NetworkFetcher(disable_cache_, resolved_url, network_service_.get(),
160 base::Bind(callback, NativeRunner::DeleteAppPath)); 172 base::Bind(callback, NativeRunner::DeleteAppPath));
161 } 173 }
162 174
163 bool ApplicationManager::ConnectToRunningApplication( 175 bool ApplicationManager::ConnectToRunningApplication(
176 const GURL& requested_url,
164 const GURL& application_url, 177 const GURL& application_url,
165 const GURL& requestor_url, 178 const GURL& requestor_url,
166 InterfaceRequest<ServiceProvider>* services, 179 InterfaceRequest<ServiceProvider>* services,
167 ServiceProviderPtr* exposed_services) { 180 ServiceProviderPtr* exposed_services) {
168 ShellImpl* shell_impl = GetShellImpl(application_url); 181 ShellImpl* shell_impl = GetShellImpl(application_url);
qsr 2015/02/27 15:01:41 Any reason you do not always strip the query here?
Aaron Boodman 2015/02/27 16:54:44 Done.
169 if (!shell_impl) 182 if (!shell_impl) {
170 return false; 183 shell_impl = GetShellImpl(StripQueryFromURL(application_url));
184 if (!shell_impl || !shell_impl->handles_query())
185 return false;
186 }
171 187
172 ConnectToClient(shell_impl, application_url, requestor_url, services->Pass(), 188 ConnectToClient(shell_impl, requested_url, application_url, requestor_url,
173 exposed_services->Pass()); 189 services->Pass(), exposed_services->Pass());
174 return true; 190 return true;
175 } 191 }
176 192
177 bool ApplicationManager::ConnectToApplicationWithLoader( 193 bool ApplicationManager::ConnectToApplicationWithLoader(
178 const GURL& requested_url, 194 const GURL& requested_url,
179 const GURL& resolved_url, 195 const GURL& resolved_url,
180 const GURL& requestor_url, 196 const GURL& requestor_url,
181 InterfaceRequest<ServiceProvider>* services, 197 InterfaceRequest<ServiceProvider>* services,
182 ServiceProviderPtr* exposed_services, 198 ServiceProviderPtr* exposed_services,
183 ApplicationLoader* loader) { 199 ApplicationLoader* loader) {
184 if (!loader) 200 if (!loader)
185 return false; 201 return false;
186 202
187 loader->Load(resolved_url, 203 loader->Load(resolved_url,
188 RegisterShell(requested_url, resolved_url, requestor_url, 204 RegisterShell(requested_url, resolved_url, requestor_url,
189 services->Pass(), exposed_services->Pass())); 205 services->Pass(), exposed_services->Pass(),
206 ShellImpl::SHELL_DOES_NOT_HANDLE_QUERY));
190 return true; 207 return true;
191 } 208 }
192 209
193 InterfaceRequest<Application> ApplicationManager::RegisterShell( 210 InterfaceRequest<Application> ApplicationManager::RegisterShell(
194 const GURL& requested_url, 211 const GURL& requested_url,
195 const GURL& resolved_url, 212 GURL resolved_url,
196 const GURL& requestor_url, 213 const GURL& requestor_url,
197 InterfaceRequest<ServiceProvider> services, 214 InterfaceRequest<ServiceProvider> services,
198 ServiceProviderPtr exposed_services) { 215 ServiceProviderPtr exposed_services,
216 ShellImpl::QueryHandlingBehavior query_behavior) {
217 if (query_behavior == ShellImpl::SHELL_HANDLES_QUERY)
218 resolved_url = StripQueryFromURL(resolved_url);
219
199 ApplicationPtr application; 220 ApplicationPtr application;
200 InterfaceRequest<Application> application_request = GetProxy(&application); 221 InterfaceRequest<Application> application_request = GetProxy(&application);
201 ShellImpl* shell = 222 ShellImpl* shell = new ShellImpl(application.Pass(), this, requested_url,
202 new ShellImpl(application.Pass(), this, requested_url, resolved_url); 223 resolved_url, query_behavior);
203 url_to_shell_impl_[resolved_url] = shell; 224 url_to_shell_impl_[resolved_url] = shell;
204 shell->InitializeApplication(GetArgsForURL(requested_url)); 225 shell->InitializeApplication(GetArgsForURL(requested_url));
205 ConnectToClient(shell, resolved_url, requestor_url, services.Pass(), 226 ConnectToClient(shell, requested_url, resolved_url, requestor_url,
206 exposed_services.Pass()); 227 services.Pass(), exposed_services.Pass());
207 return application_request.Pass(); 228 return application_request.Pass();
208 } 229 }
209 230
210 ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) { 231 ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) {
211 const auto& shell_it = url_to_shell_impl_.find(url); 232 const auto& shell_it = url_to_shell_impl_.find(url);
212 if (shell_it != url_to_shell_impl_.end()) 233 if (shell_it != url_to_shell_impl_.end())
213 return shell_it->second; 234 return shell_it->second;
214 return nullptr; 235 return nullptr;
215 } 236 }
216 237
217 void ApplicationManager::ConnectToClient( 238 void ApplicationManager::ConnectToClient(
218 ShellImpl* shell_impl, 239 ShellImpl* shell_impl,
219 const GURL& url, 240 const GURL& requested_url,
241 const GURL& resolved_url, // TODO(aa): Remove
qsr 2015/02/27 15:01:41 I think that it is requested_url that we can do wi
Aaron Boodman 2015/02/27 16:54:44 Done.
220 const GURL& requestor_url, 242 const GURL& requestor_url,
221 InterfaceRequest<ServiceProvider> services, 243 InterfaceRequest<ServiceProvider> services,
222 ServiceProviderPtr exposed_services) { 244 ServiceProviderPtr exposed_services) {
223 shell_impl->ConnectToClient(requestor_url, services.Pass(), 245 shell_impl->ConnectToClient(requested_url, requestor_url, services.Pass(),
224 exposed_services.Pass()); 246 exposed_services.Pass());
225 } 247 }
226 248
227 void ApplicationManager::HandleFetchCallback( 249 void ApplicationManager::HandleFetchCallback(
228 const GURL& requested_url, 250 const GURL& requested_url,
229 const GURL& requestor_url, 251 const GURL& requestor_url,
230 InterfaceRequest<ServiceProvider> services, 252 InterfaceRequest<ServiceProvider> services,
231 ServiceProviderPtr exposed_services, 253 ServiceProviderPtr exposed_services,
232 NativeRunner::CleanupBehavior cleanup_behavior, 254 NativeRunner::CleanupBehavior cleanup_behavior,
233 scoped_ptr<Fetcher> fetcher) { 255 scoped_ptr<Fetcher> fetcher) {
234 if (!fetcher) { 256 if (!fetcher) {
235 // Network error. Drop |application_request| to tell requestor. 257 // Network error. Drop |application_request| to tell requestor.
236 return; 258 return;
237 } 259 }
238 260
239 GURL redirect_url = fetcher->GetRedirectURL(); 261 GURL redirect_url = fetcher->GetRedirectURL();
240 if (!redirect_url.is_empty()) { 262 if (!redirect_url.is_empty()) {
241 // And around we go again... Whee! 263 // And around we go again... Whee!
242 ConnectToApplication(redirect_url, requestor_url, services.Pass(), 264 ConnectToApplication(redirect_url, requestor_url, services.Pass(),
243 exposed_services.Pass()); 265 exposed_services.Pass());
244 return; 266 return;
245 } 267 }
246 268
247 // We already checked if the application was running before we fetched it, but 269 // We already checked if the application was running before we fetched it, but
248 // it might have started while the fetch was outstanding. We don't want to 270 // it might have started while the fetch was outstanding. We don't want to
249 // have two copies of the app running, so check again. 271 // have two copies of the app running, so check again.
250 // 272 //
251 // Also, it's possible the original URL was redirected to an app that is 273 // Also, it's possible the original URL was redirected to an app that is
252 // already running. 274 // already running.
253 if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services, 275 if (ConnectToRunningApplication(requested_url, fetcher->GetURL(),
276 requestor_url, &services,
254 &exposed_services)) { 277 &exposed_services)) {
255 return; 278 return;
256 } 279 }
257 280
258 InterfaceRequest<Application> application_request(
259 RegisterShell(requested_url, fetcher->GetURL(), requestor_url,
260 services.Pass(), exposed_services.Pass()));
261
262 // If the response begins with a #!mojo <content-handler-url>, use it. 281 // If the response begins with a #!mojo <content-handler-url>, use it.
263 GURL content_handler_url; 282 GURL content_handler_url;
264 std::string shebang; 283 std::string shebang;
265 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { 284 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) {
266 LoadWithContentHandler( 285 LoadWithContentHandler(
267 content_handler_url, application_request.Pass(), 286 content_handler_url,
287 // #!mojo means this is a first-class mojo application, so it handles
288 // queries.
289 RegisterShell(requested_url, fetcher->GetURL(), requestor_url,
290 services.Pass(), exposed_services.Pass(),
291 ShellImpl::SHELL_HANDLES_QUERY),
268 fetcher->AsURLResponse(blocking_pool_, 292 fetcher->AsURLResponse(blocking_pool_,
269 static_cast<int>(shebang.size()))); 293 static_cast<int>(shebang.size())));
270 return; 294 return;
271 } 295 }
272 296
273 MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(fetcher->MimeType()); 297 MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(fetcher->MimeType());
274 if (iter != mime_type_to_url_.end()) { 298 if (iter != mime_type_to_url_.end()) {
275 LoadWithContentHandler(iter->second, application_request.Pass(), 299 // Legacy content doesn't get automatic query handling.
276 fetcher->AsURLResponse(blocking_pool_, 0)); 300 LoadWithContentHandler(
301 iter->second,
302 RegisterShell(requested_url, fetcher->GetURL(), requestor_url,
303 services.Pass(), exposed_services.Pass(),
304 ShellImpl::SHELL_DOES_NOT_HANDLE_QUERY),
305 fetcher->AsURLResponse(blocking_pool_, 0));
277 return; 306 return;
278 } 307 }
279 308
280 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo 309 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo
281 // application. That could either mean looking for the platform-specific dll 310 // application. That could either mean looking for the platform-specific dll
282 // header, or looking for some specific mojo signature prepended to the 311 // header, or looking for some specific mojo signature prepended to the
283 // library. 312 // library.
284 313
285 fetcher->AsPath(blocking_pool_, 314 fetcher->AsPath(
286 base::Bind(&ApplicationManager::RunNativeApplication, 315 blocking_pool_,
287 weak_ptr_factory_.GetWeakPtr(), 316 base::Bind(
288 base::Passed(application_request.Pass()), 317 &ApplicationManager::RunNativeApplication,
289 cleanup_behavior, base::Passed(fetcher.Pass()))); 318 weak_ptr_factory_.GetWeakPtr(),
319 base::Passed(RegisterShell(requested_url, fetcher->GetURL(),
320 requestor_url, services.Pass(),
321 exposed_services.Pass(),
322 ShellImpl::SHELL_HANDLES_QUERY).Pass()),
323 cleanup_behavior, base::Passed(fetcher.Pass())));
290 } 324 }
291 325
292 void ApplicationManager::RunNativeApplication( 326 void ApplicationManager::RunNativeApplication(
293 InterfaceRequest<Application> application_request, 327 InterfaceRequest<Application> application_request,
294 NativeRunner::CleanupBehavior cleanup_behavior, 328 NativeRunner::CleanupBehavior cleanup_behavior,
295 scoped_ptr<Fetcher> fetcher, 329 scoped_ptr<Fetcher> fetcher,
296 const base::FilePath& path, 330 const base::FilePath& path,
297 bool path_exists) { 331 bool path_exists) {
298 // We only passed fetcher to keep it alive. Done with it now. 332 // We only passed fetcher to keep it alive. Done with it now.
299 fetcher.reset(); 333 fetcher.reset();
(...skipping 15 matching lines...) Expand all
315 349
316 void ApplicationManager::RegisterExternalApplication( 350 void ApplicationManager::RegisterExternalApplication(
317 const GURL& url, 351 const GURL& url,
318 const std::vector<std::string>& args, 352 const std::vector<std::string>& args,
319 ApplicationPtr application) { 353 ApplicationPtr application) {
320 const auto& args_it = url_to_args_.find(url); 354 const auto& args_it = url_to_args_.find(url);
321 if (args_it != url_to_args_.end()) { 355 if (args_it != url_to_args_.end()) {
322 LOG(WARNING) << "--args-for provided for external application " << url 356 LOG(WARNING) << "--args-for provided for external application " << url
323 << " <ignored>"; 357 << " <ignored>";
324 } 358 }
325 ShellImpl* shell_impl = new ShellImpl(application.Pass(), this, url, url); 359 ShellImpl* shell_impl = new ShellImpl(application.Pass(), this, url, url,
360 ShellImpl::SHELL_DOES_NOT_HANDLE_QUERY);
326 url_to_shell_impl_[url] = shell_impl; 361 url_to_shell_impl_[url] = shell_impl;
327 shell_impl->InitializeApplication(Array<String>::From(args)); 362 shell_impl->InitializeApplication(Array<String>::From(args));
328 } 363 }
329 364
330 void ApplicationManager::RegisterContentHandler( 365 void ApplicationManager::RegisterContentHandler(
331 const std::string& mime_type, 366 const std::string& mime_type,
332 const GURL& content_handler_url) { 367 const GURL& content_handler_url) {
333 DCHECK(content_handler_url.is_valid()) 368 DCHECK(content_handler_url.is_valid())
334 << "Content handler URL is invalid for mime type " << mime_type; 369 << "Content handler URL is invalid for mime type " << mime_type;
335 mime_type_to_url_[mime_type] = content_handler_url; 370 mime_type_to_url_[mime_type] = content_handler_url;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 return Array<String>::From(args_it->second); 458 return Array<String>::From(args_it->second);
424 return Array<String>(); 459 return Array<String>();
425 } 460 }
426 461
427 void ApplicationManager::CleanupRunner(NativeRunner* runner) { 462 void ApplicationManager::CleanupRunner(NativeRunner* runner) {
428 native_runners_.erase( 463 native_runners_.erase(
429 std::find(native_runners_.begin(), native_runners_.end(), runner)); 464 std::find(native_runners_.begin(), native_runners_.end(), runner));
430 } 465 }
431 466
432 } // namespace mojo 467 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698