16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/application_manager/application_manager.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdio.h>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/lazy_instance.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/macros.h"
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/stl_util.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/application_manager/application_loader.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "mojo/common/common_type_converters.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/public/cpp/application/connect.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/public/interfaces/application/application.mojom.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/public/interfaces/application/shell.mojom.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace mojo {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace {
24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Used by TestAPI.
25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool has_created_instance = false;
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass StubServiceProvider : public InterfaceImpl<ServiceProvider> {
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ServiceProvider* GetRemoteServiceProvider() { return client(); }
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void ConnectToService(const String& service_name,
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                ScopedMessagePipeHandle client_handle)
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      MOJO_OVERRIDE {}
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciApplicationManager::Delegate::~Delegate() {}
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ApplicationManager::LoadCallbacksImpl
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : public ApplicationLoader::LoadCallbacks {
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  LoadCallbacksImpl(base::WeakPtr<ApplicationManager> manager,
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    const GURL& requested_url,
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    const GURL& requestor_url,
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    ServiceProviderPtr service_provider)
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : manager_(manager),
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        requested_url_(requested_url),
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        requestor_url_(requestor_url),
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        service_provider_(service_provider.Pass()) {}
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~LoadCallbacksImpl() {}
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // LoadCallbacks implementation
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ScopedMessagePipeHandle RegisterApplication() OVERRIDE {
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ScopedMessagePipeHandle shell_handle;
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (manager_) {
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      manager_->RegisterLoadedApplication(requested_url_,
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          requestor_url_,
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          service_provider_.Pass(),
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          &shell_handle);
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return shell_handle.Pass();
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void LoadWithContentHandler(const GURL& content_handler_url,
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      URLResponsePtr url_response) OVERRIDE {
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (manager_) {
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      manager_->LoadWithContentHandler(requested_url_,
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                       requestor_url_,
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                       content_handler_url,
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       url_response.Pass(),
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                       service_provider_.Pass());
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::WeakPtr<ApplicationManager> manager_;
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL requested_url_;
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL requestor_url_;
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ServiceProviderPtr service_provider_;
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ApplicationManager::ShellImpl : public InterfaceImpl<Shell> {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ShellImpl(ApplicationManager* manager, const GURL& url)
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      : manager_(manager), url_(url) {}
89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~ShellImpl() {}
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void ConnectToClient(const GURL& requestor_url,
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                       ServiceProviderPtr service_provider) {
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    client()->AcceptConnection(String::From(requestor_url),
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               service_provider.Pass());
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // ServiceProvider implementation:
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void ConnectToApplication(
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const String& app_url,
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      InterfaceRequest<ServiceProvider> in_service_provider) OVERRIDE {
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ServiceProviderPtr out_service_provider;
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    out_service_provider.Bind(in_service_provider.PassMessagePipe());
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    manager_->ConnectToApplication(
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        app_url.To<GURL>(), url_, out_service_provider.Pass());
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const GURL& url() const { return url_; }
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1110de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  virtual void OnConnectionError() OVERRIDE {
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    manager_->OnShellImplError(this);
1130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
1140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ApplicationManager* const manager_;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const GURL url_;
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ShellImpl);
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)struct ApplicationManager::ContentHandlerConnection {
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ContentHandlerConnection(ApplicationManager* manager,
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           const GURL& content_handler_url) {
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceProviderPtr service_provider;
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    BindToProxy(&service_provider_impl, &service_provider);
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    manager->ConnectToApplication(
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        content_handler_url, GURL(), service_provider.Pass());
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    mojo::ConnectToService(service_provider_impl.client(), &content_handler);
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  StubServiceProvider service_provider_impl;
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ContentHandlerPtr content_handler;
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager)
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : manager_(manager) {
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ApplicationManager::TestAPI::~TestAPI() {
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ApplicationManager::TestAPI::HasCreatedInstance() {
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return has_created_instance;
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ApplicationManager::TestAPI::HasFactoryForURL(const GURL& url) const {
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return manager_->url_to_shell_impl_.find(url) !=
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         manager_->url_to_shell_impl_.end();
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ApplicationManager::ApplicationManager()
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : delegate_(NULL),
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      interceptor_(NULL),
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_ptr_factory_(this) {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ApplicationManager::~ApplicationManager() {
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  STLDeleteValues(&url_to_content_handler_);
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TerminateShellConnections();
1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  STLDeleteValues(&url_to_loader_);
1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  STLDeleteValues(&scheme_to_loader_);
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::TerminateShellConnections() {
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  STLDeleteValues(&url_to_shell_impl_);
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ApplicationManager* ApplicationManager::GetInstance() {
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  static base::LazyInstance<ApplicationManager> instance =
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      LAZY_INSTANCE_INITIALIZER;
173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  has_created_instance = true;
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return &instance.Get();
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::ConnectToApplication(
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const GURL& url,
1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const GURL& requestor_url,
1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ServiceProviderPtr service_provider) {
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  URLToShellImplMap::const_iterator shell_it = url_to_shell_impl_.find(url);
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (shell_it != url_to_shell_impl_.end()) {
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ConnectToClient(
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        shell_it->second, url, requestor_url, service_provider.Pass());
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<LoadCallbacksImpl> callbacks(
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new LoadCallbacksImpl(weak_ptr_factory_.GetWeakPtr(),
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            url,
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            requestor_url,
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            service_provider.Pass()));
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetLoaderForURL(url)->Load(this, url, callbacks);
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::ConnectToClient(ShellImpl* shell_impl,
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                         const GURL& url,
1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                         const GURL& requestor_url,
1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                         ServiceProviderPtr service_provider) {
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (interceptor_) {
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    shell_impl->ConnectToClient(
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        requestor_url,
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        interceptor_->OnConnectToClient(url, service_provider.Pass()));
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else {
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    shell_impl->ConnectToClient(requestor_url, service_provider.Pass());
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::RegisterLoadedApplication(
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GURL& url,
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GURL& requestor_url,
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceProviderPtr service_provider,
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ScopedMessagePipeHandle* shell_handle) {
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ShellImpl* shell_impl = NULL;
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  URLToShellImplMap::iterator iter = url_to_shell_impl_.find(url);
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (iter != url_to_shell_impl_.end()) {
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // This can happen because services are loaded asynchronously. So if we get
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // two requests for the same service close to each other, we might get here
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // and find that we already have it.
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    shell_impl = iter->second;
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    MessagePipe pipe;
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    URLToArgsMap::const_iterator args_it = url_to_args_.find(url);
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Array<String> args;
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (args_it != url_to_args_.end())
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      args = Array<String>::From(args_it->second);
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    shell_impl = WeakBindToPipe(new ShellImpl(this, url), pipe.handle1.Pass());
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    url_to_shell_impl_[url] = shell_impl;
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *shell_handle = pipe.handle0.Pass();
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    shell_impl->client()->Initialize(args.Pass());
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ConnectToClient(shell_impl, url, requestor_url, service_provider.Pass());
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::LoadWithContentHandler(
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GURL& content_url,
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GURL& requestor_url,
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GURL& content_handler_url,
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    URLResponsePtr url_response,
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceProviderPtr service_provider) {
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ContentHandlerConnection* connection = NULL;
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  URLToContentHandlerMap::iterator iter =
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      url_to_content_handler_.find(content_handler_url);
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (iter != url_to_content_handler_.end()) {
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    connection = iter->second;
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    connection = new ContentHandlerConnection(this, content_handler_url);
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    url_to_content_handler_[content_handler_url] = connection;
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  InterfaceRequest<ServiceProvider> spir;
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spir.Bind(service_provider.PassMessagePipe());
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  connection->content_handler->OnConnect(
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content_url.spec(), url_response.Pass(), spir.Pass());
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader,
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                         const GURL& url) {
2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  URLToLoaderMap::iterator it = url_to_loader_.find(url);
2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (it != url_to_loader_.end())
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    delete it->second;
2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  url_to_loader_[url] = loader.release();
264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::SetLoaderForScheme(
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<ApplicationLoader> loader,
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& scheme) {
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme);
2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (it != scheme_to_loader_.end())
2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    delete it->second;
2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scheme_to_loader_[scheme] = loader.release();
273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ApplicationManager::SetArgsForURL(const std::vector<std::string>& args,
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       const GURL& url) {
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  url_to_args_[url] = args;
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::SetInterceptor(Interceptor* interceptor) {
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  interceptor_ = interceptor;
282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ApplicationLoader* ApplicationManager::GetLoaderForURL(const GURL& url) {
285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  URLToLoaderMap::const_iterator url_it = url_to_loader_.find(url);
286effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (url_it != url_to_loader_.end())
287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return url_it->second;
288effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SchemeToLoaderMap::const_iterator scheme_it =
289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      scheme_to_loader_.find(url.scheme());
290effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (scheme_it != scheme_to_loader_.end())
291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return scheme_it->second;
2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return default_loader_.get();
293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) {
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Called from ~ShellImpl, so we do not need to call Destroy here.
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const GURL url = shell_impl->url();
298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  URLToShellImplMap::iterator it = url_to_shell_impl_.find(url);
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(it != url_to_shell_impl_.end());
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete it->second;
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  url_to_shell_impl_.erase(it);
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ApplicationLoader* loader = GetLoaderForURL(url);
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (loader)
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    loader->OnApplicationError(this, url);
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (delegate_)
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delegate_->OnApplicationError(url);
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName(
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const GURL& application_url,
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& interface_name) {
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  StubServiceProvider* stub_sp = new StubServiceProvider;
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ServiceProviderPtr spp;
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  BindToProxy(stub_sp, &spp);
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ConnectToApplication(application_url, GURL(), spp.Pass());
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MessagePipe pipe;
3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  stub_sp->GetRemoteServiceProvider()->ConnectToService(interface_name,
3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                                        pipe.handle1.Pass());
319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return pipe.handle0.Pass();
320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace mojo
322