service_manager.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
1// Copyright 2013 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 5#include <stdio.h> 6 7#include "mojo/service_manager/service_manager.h" 8 9#include "base/lazy_instance.h" 10#include "base/logging.h" 11#include "base/macros.h" 12#include "base/stl_util.h" 13#include "mojo/public/cpp/bindings/allocation_scope.h" 14#include "mojo/public/cpp/bindings/error_handler.h" 15#include "mojo/public/cpp/bindings/remote_ptr.h" 16#include "mojo/service_manager/service_loader.h" 17 18namespace mojo { 19 20namespace { 21// Used by TestAPI. 22bool has_created_instance = false; 23} 24 25class ServiceManager::ServiceFactory : public Shell, public ErrorHandler { 26 public: 27 ServiceFactory(ServiceManager* manager, const GURL& url) 28 : manager_(manager), 29 url_(url) { 30 InterfacePipe<Shell> pipe; 31 shell_client_.reset(pipe.handle_to_peer.Pass(), this, this); 32 manager_->GetLoaderForURL(url)->LoadService(manager_, 33 url, 34 pipe.handle_to_self.Pass()); 35 } 36 37 virtual ~ServiceFactory() {} 38 39 void ConnectToClient(ScopedMessagePipeHandle handle) { 40 if (handle.is_valid()) { 41 AllocationScope scope; 42 shell_client_->AcceptConnection(url_.spec(), handle.Pass()); 43 } 44 } 45 46 virtual void Connect(const String& url, 47 ScopedMessagePipeHandle client_pipe) OVERRIDE { 48 manager_->Connect(GURL(url.To<std::string>()), client_pipe.Pass()); 49 } 50 51 virtual void OnError() OVERRIDE { 52 manager_->OnServiceFactoryError(this); 53 } 54 55 const GURL& url() const { return url_; } 56 57 private: 58 ServiceManager* const manager_; 59 const GURL url_; 60 RemotePtr<ShellClient> shell_client_; 61 DISALLOW_COPY_AND_ASSIGN(ServiceFactory); 62}; 63 64// static 65bool ServiceManager::TestAPI::HasCreatedInstance() { 66 return has_created_instance; 67} 68 69bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const { 70 return manager_->url_to_service_factory_.find(url) != 71 manager_->url_to_service_factory_.end(); 72} 73 74ServiceManager::ServiceManager() 75 : interceptor_(NULL) { 76} 77 78ServiceManager::~ServiceManager() { 79 STLDeleteValues(&url_to_service_factory_); 80 STLDeleteValues(&url_to_loader_); 81 STLDeleteValues(&scheme_to_loader_); 82} 83 84// static 85ServiceManager* ServiceManager::GetInstance() { 86 static base::LazyInstance<ServiceManager> instance = 87 LAZY_INSTANCE_INITIALIZER; 88 has_created_instance = true; 89 return &instance.Get(); 90} 91 92void ServiceManager::Connect(const GURL& url, 93 ScopedMessagePipeHandle client_handle) { 94 URLToServiceFactoryMap::const_iterator service_it = 95 url_to_service_factory_.find(url); 96 ServiceFactory* service_factory; 97 if (service_it != url_to_service_factory_.end()) { 98 service_factory = service_it->second; 99 } else { 100 service_factory = new ServiceFactory(this, url); 101 url_to_service_factory_[url] = service_factory; 102 } 103 if (interceptor_) { 104 service_factory->ConnectToClient( 105 interceptor_->OnConnectToClient(url, client_handle.Pass())); 106 } else { 107 service_factory->ConnectToClient(client_handle.Pass()); 108 } 109} 110 111void ServiceManager::SetLoaderForURL(scoped_ptr<ServiceLoader> loader, 112 const GURL& url) { 113 URLToLoaderMap::iterator it = url_to_loader_.find(url); 114 if (it != url_to_loader_.end()) 115 delete it->second; 116 url_to_loader_[url] = loader.release(); 117} 118 119void ServiceManager::SetLoaderForScheme(scoped_ptr<ServiceLoader> loader, 120 const std::string& scheme) { 121 SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme); 122 if (it != scheme_to_loader_.end()) 123 delete it->second; 124 scheme_to_loader_[scheme] = loader.release(); 125} 126 127void ServiceManager::SetInterceptor(Interceptor* interceptor) { 128 interceptor_ = interceptor; 129} 130 131ServiceLoader* ServiceManager::GetLoaderForURL(const GURL& url) { 132 URLToLoaderMap::const_iterator url_it = url_to_loader_.find(url); 133 if (url_it != url_to_loader_.end()) 134 return url_it->second; 135 SchemeToLoaderMap::const_iterator scheme_it = 136 scheme_to_loader_.find(url.scheme()); 137 if (scheme_it != scheme_to_loader_.end()) 138 return scheme_it->second; 139 DCHECK(default_loader_); 140 return default_loader_.get(); 141} 142 143void ServiceManager::OnServiceFactoryError(ServiceFactory* service_factory) { 144 const GURL url = service_factory->url(); 145 URLToServiceFactoryMap::iterator it = url_to_service_factory_.find(url); 146 DCHECK(it != url_to_service_factory_.end()); 147 delete it->second; 148 url_to_service_factory_.erase(it); 149 GetLoaderForURL(url)->OnServiceError(this, url); 150} 151 152} // namespace mojo 153