Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / mojo / service_manager / service_manager.cc
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/service_manager/service_loader.h"
14
15 namespace mojo {
16
17 namespace {
18 // Used by TestAPI.
19 bool has_created_instance = false;
20 }
21
22 class ServiceManager::ServiceFactory : public InterfaceImpl<ServiceProvider> {
23  public:
24   ServiceFactory(ServiceManager* manager, const GURL& url)
25       : manager_(manager),
26         url_(url) {
27   }
28
29   virtual ~ServiceFactory() {
30   }
31
32   void ConnectToClient(const std::string& service_name,
33                        ScopedMessagePipeHandle handle,
34                        const GURL& requestor_url) {
35     if (handle.is_valid()) {
36       client()->ConnectToService(
37           url_.spec(), service_name, handle.Pass(), requestor_url.spec());
38     }
39   }
40
41   // ServiceProvider implementation:
42   virtual void ConnectToService(const String& service_url,
43                                 const String& service_name,
44                                 ScopedMessagePipeHandle client_pipe,
45                                 const String& requestor_url) OVERRIDE {
46     // Ignore provided requestor_url and use url from connection.
47     manager_->ConnectToService(
48         GURL(service_url), service_name, client_pipe.Pass(), url_);
49   }
50
51   const GURL& url() const { return url_; }
52
53  private:
54   virtual void OnConnectionError() OVERRIDE {
55     manager_->OnServiceFactoryError(this);
56   }
57
58   ServiceManager* const manager_;
59   const GURL url_;
60
61   DISALLOW_COPY_AND_ASSIGN(ServiceFactory);
62 };
63
64 class ServiceManager::TestAPI::TestServiceProviderConnection
65     : public InterfaceImpl<ServiceProvider> {
66  public:
67   explicit TestServiceProviderConnection(ServiceManager* manager)
68       : manager_(manager) {}
69   virtual ~TestServiceProviderConnection() {}
70
71   virtual void OnConnectionError() OVERRIDE {
72     // TODO(darin): How should we handle this error?
73   }
74
75   // ServiceProvider:
76   virtual void ConnectToService(const String& service_url,
77                                 const String& service_name,
78                                 ScopedMessagePipeHandle client_pipe,
79                                 const String& requestor_url) OVERRIDE {
80     manager_->ConnectToService(GURL(service_url),
81                                service_name,
82                                client_pipe.Pass(),
83                                GURL(requestor_url));
84   }
85
86  private:
87   ServiceManager* manager_;
88
89   DISALLOW_COPY_AND_ASSIGN(TestServiceProviderConnection);
90 };
91
92 // static
93 ServiceManager::TestAPI::TestAPI(ServiceManager* manager) : manager_(manager) {
94 }
95
96 ServiceManager::TestAPI::~TestAPI() {
97 }
98
99 bool ServiceManager::TestAPI::HasCreatedInstance() {
100   return has_created_instance;
101 }
102
103 ScopedMessagePipeHandle ServiceManager::TestAPI::GetServiceProviderHandle() {
104   MessagePipe pipe;
105   service_provider_.reset(
106       BindToPipe(new TestServiceProviderConnection(manager_),
107                  pipe.handle0.Pass()));
108   return pipe.handle1.Pass();
109 }
110
111 bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const {
112   return manager_->url_to_service_factory_.find(url) !=
113          manager_->url_to_service_factory_.end();
114 }
115
116 ServiceManager::ServiceManager()
117     : interceptor_(NULL) {
118 }
119
120 ServiceManager::~ServiceManager() {
121   STLDeleteValues(&url_to_service_factory_);
122   STLDeleteValues(&url_to_loader_);
123   STLDeleteValues(&scheme_to_loader_);
124 }
125
126 // static
127 ServiceManager* ServiceManager::GetInstance() {
128   static base::LazyInstance<ServiceManager> instance =
129       LAZY_INSTANCE_INITIALIZER;
130   has_created_instance = true;
131   return &instance.Get();
132 }
133
134 void ServiceManager::ConnectToService(const GURL& url,
135                                       const std::string& name,
136                                       ScopedMessagePipeHandle client_handle,
137                                       const GURL& requestor_url) {
138   URLToServiceFactoryMap::const_iterator service_it =
139       url_to_service_factory_.find(url);
140   ServiceFactory* service_factory;
141   if (service_it != url_to_service_factory_.end()) {
142     service_factory = service_it->second;
143   } else {
144     MessagePipe pipe;
145     GetLoaderForURL(url)->LoadService(this, url, pipe.handle0.Pass());
146
147     service_factory =
148         BindToPipe(new ServiceFactory(this, url), pipe.handle1.Pass());
149
150     url_to_service_factory_[url] = service_factory;
151   }
152   if (interceptor_) {
153     service_factory->ConnectToClient(
154         name,
155         interceptor_->OnConnectToClient(url, client_handle.Pass()),
156         requestor_url);
157   } else {
158     service_factory->ConnectToClient(name, client_handle.Pass(), requestor_url);
159   }
160 }
161
162 void ServiceManager::SetLoaderForURL(scoped_ptr<ServiceLoader> loader,
163                                      const GURL& url) {
164   URLToLoaderMap::iterator it = url_to_loader_.find(url);
165   if (it != url_to_loader_.end())
166     delete it->second;
167   url_to_loader_[url] = loader.release();
168 }
169
170 void ServiceManager::SetLoaderForScheme(scoped_ptr<ServiceLoader> loader,
171                                         const std::string& scheme) {
172   SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme);
173   if (it != scheme_to_loader_.end())
174     delete it->second;
175   scheme_to_loader_[scheme] = loader.release();
176 }
177
178 void ServiceManager::SetInterceptor(Interceptor* interceptor) {
179   interceptor_ = interceptor;
180 }
181
182 ServiceLoader* ServiceManager::GetLoaderForURL(const GURL& url) {
183   URLToLoaderMap::const_iterator url_it = url_to_loader_.find(url);
184   if (url_it != url_to_loader_.end())
185     return url_it->second;
186   SchemeToLoaderMap::const_iterator scheme_it =
187       scheme_to_loader_.find(url.scheme());
188   if (scheme_it != scheme_to_loader_.end())
189     return scheme_it->second;
190   DCHECK(default_loader_);
191   return default_loader_.get();
192 }
193
194 void ServiceManager::OnServiceFactoryError(ServiceFactory* service_factory) {
195   // Called from ~ServiceFactory, so we do not need to call Destroy here.
196   const GURL url = service_factory->url();
197   URLToServiceFactoryMap::iterator it = url_to_service_factory_.find(url);
198   DCHECK(it != url_to_service_factory_.end());
199   delete it->second;
200   url_to_service_factory_.erase(it);
201   ServiceLoader* loader = GetLoaderForURL(url);
202   if (loader)
203     loader->OnServiceError(this, url);
204 }
205
206 }  // namespace mojo