// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "mojo/service_manager/service_manager.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" #include "mojo/public/bindings/allocation_scope.h" #include "mojo/public/bindings/error_handler.h" #include "mojo/public/bindings/remote_ptr.h" #include "mojo/service_manager/service_loader.h" namespace mojo { class ServiceManager::ServiceFactory : public Shell, public ErrorHandler { public: ServiceFactory(ServiceManager* manager, const GURL& url) : manager_(manager), url_(url) { InterfacePipe pipe; shell_client_.reset(pipe.handle_to_peer.Pass(), this, this); manager_->GetLoaderForURL(url)->LoadService(manager_, url, pipe.handle_to_self.Pass()); } virtual ~ServiceFactory() {} void ConnectToClient(ScopedMessagePipeHandle handle) { if (handle.is_valid()) { AllocationScope scope; shell_client_->AcceptConnection(url_.spec(), handle.Pass()); } } virtual void Connect(const String& url, ScopedMessagePipeHandle client_pipe) OVERRIDE { manager_->Connect(GURL(url.To()), client_pipe.Pass()); } virtual void OnError() OVERRIDE { manager_->RemoveServiceFactory(this); } const GURL& url() const { return url_; } private: ServiceManager* const manager_; const GURL url_; RemotePtr shell_client_; DISALLOW_COPY_AND_ASSIGN(ServiceFactory); }; bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const { return manager_->url_to_service_factory_.find(url) != manager_->url_to_service_factory_.end(); } ServiceManager::ServiceManager() : default_loader_(NULL) { } ServiceManager::~ServiceManager() { for (ServiceFactoryMap::iterator it = url_to_service_factory_.begin(); it != url_to_service_factory_.end(); ++it) { delete it->second; } url_to_service_factory_.clear(); } // static ServiceManager* GetInstance() { static base::LazyInstance instance = LAZY_INSTANCE_INITIALIZER; return &instance.Get(); } void ServiceManager::SetLoaderForURL(ServiceLoader* loader, const GURL& gurl) { DCHECK(url_to_loader_.find(gurl) == url_to_loader_.end()); url_to_loader_[gurl] = loader; } ServiceLoader* ServiceManager::GetLoaderForURL(const GURL& gurl) { LoaderMap::const_iterator it = url_to_loader_.find(gurl); if (it != url_to_loader_.end()) return it->second; DCHECK(default_loader_); return default_loader_; } void ServiceManager::Connect(const GURL& url, ScopedMessagePipeHandle client_handle) { ServiceFactoryMap::const_iterator service_it = url_to_service_factory_.find(url); ServiceFactory* service_factory; if (service_it != url_to_service_factory_.end()) { service_factory = service_it->second; } else { service_factory = new ServiceFactory(this, url); url_to_service_factory_[url] = service_factory; } service_factory->ConnectToClient(client_handle.Pass()); } void ServiceManager::RemoveServiceFactory(ServiceFactory* service_factory) { ServiceFactoryMap::iterator it = url_to_service_factory_.find(service_factory->url()); DCHECK(it != url_to_service_factory_.end()); delete it->second; url_to_service_factory_.erase(it); } } // namespace mojo