| 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 |