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 <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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 void ApplicationManager::ConnectToApplication( | 117 void ApplicationManager::ConnectToApplication( |
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); |
qsr
2015/02/27 17:17:43
Don't you need to modify those methods to keep the
Aaron Boodman
2015/02/28 19:08:23
I don't follow you.
qsr
2015/03/02 08:51:31
I think URLResolver::ApplyMappings needs to be upd
Aaron Boodman
2015/03/02 15:36:36
Perhaps. I think that should be a separate change
| |
116 if (ConnectToRunningApplication(mapped_url, requestor_url, &services, | 128 if (ConnectToRunningApplication(mapped_url, requestor_url, |
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(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 Loading... | |
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( |
164 const GURL& application_url, | 176 const GURL& resolved_url, |
165 const GURL& requestor_url, | 177 const GURL& requestor_url, |
166 InterfaceRequest<ServiceProvider>* services, | 178 InterfaceRequest<ServiceProvider>* services, |
167 ServiceProviderPtr* exposed_services) { | 179 ServiceProviderPtr* exposed_services) { |
180 GURL application_url = StripQueryFromURL(resolved_url); | |
168 ShellImpl* shell_impl = GetShellImpl(application_url); | 181 ShellImpl* shell_impl = GetShellImpl(application_url); |
169 if (!shell_impl) | 182 if (!shell_impl) |
170 return false; | 183 return false; |
171 | 184 |
172 ConnectToClient(shell_impl, application_url, requestor_url, services->Pass(), | 185 ConnectToClient(shell_impl, resolved_url, requestor_url, |
173 exposed_services->Pass()); | 186 services->Pass(), exposed_services->Pass()); |
174 return true; | 187 return true; |
175 } | 188 } |
176 | 189 |
177 bool ApplicationManager::ConnectToApplicationWithLoader( | 190 bool ApplicationManager::ConnectToApplicationWithLoader( |
178 const GURL& requested_url, | 191 const GURL& requested_url, |
179 const GURL& resolved_url, | 192 const GURL& resolved_url, |
180 const GURL& requestor_url, | 193 const GURL& requestor_url, |
181 InterfaceRequest<ServiceProvider>* services, | 194 InterfaceRequest<ServiceProvider>* services, |
182 ServiceProviderPtr* exposed_services, | 195 ServiceProviderPtr* exposed_services, |
183 ApplicationLoader* loader) { | 196 ApplicationLoader* loader) { |
184 if (!loader) | 197 if (!loader) |
185 return false; | 198 return false; |
186 | 199 |
187 loader->Load(resolved_url, | 200 loader->Load(resolved_url, |
188 RegisterShell(requested_url, resolved_url, requestor_url, | 201 RegisterShell(requested_url, resolved_url, requestor_url, |
189 services->Pass(), exposed_services->Pass())); | 202 services->Pass(), exposed_services->Pass())); |
190 return true; | 203 return true; |
191 } | 204 } |
192 | 205 |
193 InterfaceRequest<Application> ApplicationManager::RegisterShell( | 206 InterfaceRequest<Application> ApplicationManager::RegisterShell( |
194 const GURL& requested_url, | 207 const GURL& requested_url, |
195 const GURL& resolved_url, | 208 GURL resolved_url, |
196 const GURL& requestor_url, | 209 const GURL& requestor_url, |
197 InterfaceRequest<ServiceProvider> services, | 210 InterfaceRequest<ServiceProvider> services, |
198 ServiceProviderPtr exposed_services) { | 211 ServiceProviderPtr exposed_services) { |
212 resolved_url = StripQueryFromURL(resolved_url); | |
213 | |
199 ApplicationPtr application; | 214 ApplicationPtr application; |
200 InterfaceRequest<Application> application_request = GetProxy(&application); | 215 InterfaceRequest<Application> application_request = GetProxy(&application); |
201 ShellImpl* shell = | 216 ShellImpl* shell = |
202 new ShellImpl(application.Pass(), this, requested_url, resolved_url); | 217 new ShellImpl(application.Pass(), this, requested_url, resolved_url); |
203 url_to_shell_impl_[resolved_url] = shell; | 218 url_to_shell_impl_[resolved_url] = shell; |
204 shell->InitializeApplication(GetArgsForURL(requested_url)); | 219 shell->InitializeApplication(GetArgsForURL(requested_url)); |
205 ConnectToClient(shell, resolved_url, requestor_url, services.Pass(), | 220 ConnectToClient(shell, resolved_url, requestor_url, |
206 exposed_services.Pass()); | 221 services.Pass(), exposed_services.Pass()); |
207 return application_request.Pass(); | 222 return application_request.Pass(); |
208 } | 223 } |
209 | 224 |
210 ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) { | 225 ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) { |
211 const auto& shell_it = url_to_shell_impl_.find(url); | 226 const auto& shell_it = url_to_shell_impl_.find(url); |
212 if (shell_it != url_to_shell_impl_.end()) | 227 if (shell_it != url_to_shell_impl_.end()) |
213 return shell_it->second; | 228 return shell_it->second; |
214 return nullptr; | 229 return nullptr; |
215 } | 230 } |
216 | 231 |
217 void ApplicationManager::ConnectToClient( | 232 void ApplicationManager::ConnectToClient( |
218 ShellImpl* shell_impl, | 233 ShellImpl* shell_impl, |
219 const GURL& url, | 234 const GURL& resolved_url, |
220 const GURL& requestor_url, | 235 const GURL& requestor_url, |
221 InterfaceRequest<ServiceProvider> services, | 236 InterfaceRequest<ServiceProvider> services, |
222 ServiceProviderPtr exposed_services) { | 237 ServiceProviderPtr exposed_services) { |
223 shell_impl->ConnectToClient(requestor_url, services.Pass(), | 238 shell_impl->ConnectToClient(resolved_url, requestor_url, services.Pass(), |
224 exposed_services.Pass()); | 239 exposed_services.Pass()); |
225 } | 240 } |
226 | 241 |
227 void ApplicationManager::HandleFetchCallback( | 242 void ApplicationManager::HandleFetchCallback( |
228 const GURL& requested_url, | 243 const GURL& requested_url, |
229 const GURL& requestor_url, | 244 const GURL& requestor_url, |
230 InterfaceRequest<ServiceProvider> services, | 245 InterfaceRequest<ServiceProvider> services, |
231 ServiceProviderPtr exposed_services, | 246 ServiceProviderPtr exposed_services, |
232 NativeRunner::CleanupBehavior cleanup_behavior, | 247 NativeRunner::CleanupBehavior cleanup_behavior, |
233 scoped_ptr<Fetcher> fetcher) { | 248 scoped_ptr<Fetcher> fetcher) { |
234 if (!fetcher) { | 249 if (!fetcher) { |
235 // Network error. Drop |application_request| to tell requestor. | 250 // Network error. Drop |application_request| to tell requestor. |
236 return; | 251 return; |
237 } | 252 } |
238 | 253 |
239 GURL redirect_url = fetcher->GetRedirectURL(); | 254 GURL redirect_url = fetcher->GetRedirectURL(); |
240 if (!redirect_url.is_empty()) { | 255 if (!redirect_url.is_empty()) { |
241 // And around we go again... Whee! | 256 // And around we go again... Whee! |
242 ConnectToApplication(redirect_url, requestor_url, services.Pass(), | 257 ConnectToApplication(redirect_url, requestor_url, services.Pass(), |
243 exposed_services.Pass()); | 258 exposed_services.Pass()); |
244 return; | 259 return; |
245 } | 260 } |
246 | 261 |
247 // We already checked if the application was running before we fetched it, but | 262 // 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 | 263 // 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. | 264 // have two copies of the app running, so check again. |
250 // | 265 // |
251 // Also, it's possible the original URL was redirected to an app that is | 266 // Also, it's possible the original URL was redirected to an app that is |
252 // already running. | 267 // already running. |
253 if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services, | 268 if (ConnectToRunningApplication(fetcher->GetURL(), |
269 requestor_url, &services, | |
254 &exposed_services)) { | 270 &exposed_services)) { |
255 return; | 271 return; |
256 } | 272 } |
257 | 273 |
258 InterfaceRequest<Application> application_request( | 274 InterfaceRequest<Application> request( |
259 RegisterShell(requested_url, fetcher->GetURL(), requestor_url, | 275 RegisterShell(requested_url, fetcher->GetURL(), requestor_url, |
260 services.Pass(), exposed_services.Pass())); | 276 services.Pass(), exposed_services.Pass())); |
261 | 277 |
262 // If the response begins with a #!mojo <content-handler-url>, use it. | 278 // If the response begins with a #!mojo <content-handler-url>, use it. |
263 GURL content_handler_url; | 279 GURL content_handler_url; |
264 std::string shebang; | 280 std::string shebang; |
265 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { | 281 if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { |
266 LoadWithContentHandler( | 282 LoadWithContentHandler( |
267 content_handler_url, application_request.Pass(), | 283 content_handler_url, request.Pass(), |
268 fetcher->AsURLResponse(blocking_pool_, | 284 fetcher->AsURLResponse(blocking_pool_, |
269 static_cast<int>(shebang.size()))); | 285 static_cast<int>(shebang.size()))); |
270 return; | 286 return; |
271 } | 287 } |
272 | 288 |
273 MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(fetcher->MimeType()); | 289 MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(fetcher->MimeType()); |
274 if (iter != mime_type_to_url_.end()) { | 290 if (iter != mime_type_to_url_.end()) { |
275 LoadWithContentHandler(iter->second, application_request.Pass(), | 291 LoadWithContentHandler(iter->second, request.Pass(), |
276 fetcher->AsURLResponse(blocking_pool_, 0)); | 292 fetcher->AsURLResponse(blocking_pool_, 0)); |
277 return; | 293 return; |
278 } | 294 } |
279 | 295 |
280 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo | 296 // 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 | 297 // application. That could either mean looking for the platform-specific dll |
282 // header, or looking for some specific mojo signature prepended to the | 298 // header, or looking for some specific mojo signature prepended to the |
283 // library. | 299 // library. |
284 | 300 |
285 fetcher->AsPath(blocking_pool_, | 301 fetcher->AsPath( |
286 base::Bind(&ApplicationManager::RunNativeApplication, | 302 blocking_pool_, |
287 weak_ptr_factory_.GetWeakPtr(), | 303 base::Bind(&ApplicationManager::RunNativeApplication, |
288 base::Passed(application_request.Pass()), | 304 weak_ptr_factory_.GetWeakPtr(), base::Passed(request.Pass()), |
289 cleanup_behavior, base::Passed(fetcher.Pass()))); | 305 cleanup_behavior, base::Passed(fetcher.Pass()))); |
290 } | 306 } |
291 | 307 |
292 void ApplicationManager::RunNativeApplication( | 308 void ApplicationManager::RunNativeApplication( |
293 InterfaceRequest<Application> application_request, | 309 InterfaceRequest<Application> application_request, |
294 NativeRunner::CleanupBehavior cleanup_behavior, | 310 NativeRunner::CleanupBehavior cleanup_behavior, |
295 scoped_ptr<Fetcher> fetcher, | 311 scoped_ptr<Fetcher> fetcher, |
296 const base::FilePath& path, | 312 const base::FilePath& path, |
297 bool path_exists) { | 313 bool path_exists) { |
298 // We only passed fetcher to keep it alive. Done with it now. | 314 // We only passed fetcher to keep it alive. Done with it now. |
299 fetcher.reset(); | 315 fetcher.reset(); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 return Array<String>::From(args_it->second); | 439 return Array<String>::From(args_it->second); |
424 return Array<String>(); | 440 return Array<String>(); |
425 } | 441 } |
426 | 442 |
427 void ApplicationManager::CleanupRunner(NativeRunner* runner) { | 443 void ApplicationManager::CleanupRunner(NativeRunner* runner) { |
428 native_runners_.erase( | 444 native_runners_.erase( |
429 std::find(native_runners_.begin(), native_runners_.end(), runner)); | 445 std::find(native_runners_.begin(), native_runners_.end(), runner)); |
430 } | 446 } |
431 | 447 |
432 } // namespace mojo | 448 } // namespace mojo |
OLD | NEW |