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