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.
7 #include "mojo/service_manager/service_manager.h"
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/common/common_type_converters.h"
14 #include "mojo/service_manager/service_loader.h"
20 bool has_created_instance
= false;
22 class StubServiceProvider
: public InterfaceImpl
<ServiceProvider
> {
24 ServiceProvider
* GetRemoteServiceProvider() {
29 virtual void ConnectToService(
30 const String
& service_name
,
31 ScopedMessagePipeHandle client_handle
) MOJO_OVERRIDE
{}
36 class ServiceManager::ShellImpl
: public InterfaceImpl
<Shell
> {
38 ShellImpl(ServiceManager
* manager
, const GURL
& url
)
43 virtual ~ShellImpl() {
46 void ConnectToClient(const GURL
& requestor_url
,
47 ServiceProviderPtr service_provider
) {
48 client()->AcceptConnection(String::From(requestor_url
),
49 service_provider
.Pass());
52 // ServiceProvider implementation:
53 virtual void ConnectToApplication(
54 const String
& app_url
,
55 InterfaceRequest
<ServiceProvider
> in_service_provider
) OVERRIDE
{
56 ServiceProviderPtr out_service_provider
;
57 out_service_provider
.Bind(in_service_provider
.PassMessagePipe());
58 manager_
->ConnectToApplication(
61 out_service_provider
.Pass());
64 const GURL
& url() const { return url_
; }
67 virtual void OnConnectionError() OVERRIDE
{
68 manager_
->OnShellImplError(this);
71 ServiceManager
* const manager_
;
74 DISALLOW_COPY_AND_ASSIGN(ShellImpl
);
78 ServiceManager::TestAPI::TestAPI(ServiceManager
* manager
) : manager_(manager
) {
81 ServiceManager::TestAPI::~TestAPI() {
84 bool ServiceManager::TestAPI::HasCreatedInstance() {
85 return has_created_instance
;
88 bool ServiceManager::TestAPI::HasFactoryForURL(const GURL
& url
) const {
89 return manager_
->url_to_shell_impl_
.find(url
) !=
90 manager_
->url_to_shell_impl_
.end();
93 ServiceManager::ServiceManager() : interceptor_(NULL
) {
96 ServiceManager::~ServiceManager() {
97 STLDeleteValues(&url_to_shell_impl_
);
98 STLDeleteValues(&url_to_loader_
);
99 STLDeleteValues(&scheme_to_loader_
);
103 ServiceManager
* ServiceManager::GetInstance() {
104 static base::LazyInstance
<ServiceManager
> instance
=
105 LAZY_INSTANCE_INITIALIZER
;
106 has_created_instance
= true;
107 return &instance
.Get();
110 void ServiceManager::ConnectToApplication(const GURL
& url
,
111 const GURL
& requestor_url
,
112 ServiceProviderPtr service_provider
) {
113 URLToShellImplMap::const_iterator shell_it
= url_to_shell_impl_
.find(url
);
114 ShellImpl
* shell_impl
;
115 if (shell_it
!= url_to_shell_impl_
.end()) {
116 shell_impl
= shell_it
->second
;
119 GetLoaderForURL(url
)->LoadService(this, url
, pipe
.handle0
.Pass());
120 shell_impl
= BindToPipe(new ShellImpl(this, url
), pipe
.handle1
.Pass());
121 url_to_shell_impl_
[url
] = shell_impl
;
124 shell_impl
->ConnectToClient(
126 interceptor_
->OnConnectToClient(url
, service_provider
.Pass()));
128 shell_impl
->ConnectToClient(requestor_url
, service_provider
.Pass());
132 void ServiceManager::SetLoaderForURL(scoped_ptr
<ServiceLoader
> loader
,
134 URLToLoaderMap::iterator it
= url_to_loader_
.find(url
);
135 if (it
!= url_to_loader_
.end())
137 url_to_loader_
[url
] = loader
.release();
140 void ServiceManager::SetLoaderForScheme(scoped_ptr
<ServiceLoader
> loader
,
141 const std::string
& scheme
) {
142 SchemeToLoaderMap::iterator it
= scheme_to_loader_
.find(scheme
);
143 if (it
!= scheme_to_loader_
.end())
145 scheme_to_loader_
[scheme
] = loader
.release();
148 void ServiceManager::SetInterceptor(Interceptor
* interceptor
) {
149 interceptor_
= interceptor
;
152 ServiceLoader
* ServiceManager::GetLoaderForURL(const GURL
& url
) {
153 URLToLoaderMap::const_iterator url_it
= url_to_loader_
.find(url
);
154 if (url_it
!= url_to_loader_
.end())
155 return url_it
->second
;
156 SchemeToLoaderMap::const_iterator scheme_it
=
157 scheme_to_loader_
.find(url
.scheme());
158 if (scheme_it
!= scheme_to_loader_
.end())
159 return scheme_it
->second
;
160 DCHECK(default_loader_
);
161 return default_loader_
.get();
164 void ServiceManager::OnShellImplError(ShellImpl
* shell_impl
) {
165 // Called from ~ShellImpl, so we do not need to call Destroy here.
166 const GURL url
= shell_impl
->url();
167 URLToShellImplMap::iterator it
= url_to_shell_impl_
.find(url
);
168 DCHECK(it
!= url_to_shell_impl_
.end());
170 url_to_shell_impl_
.erase(it
);
171 ServiceLoader
* loader
= GetLoaderForURL(url
);
173 loader
->OnServiceError(this, url
);
176 ScopedMessagePipeHandle
ServiceManager::ConnectToServiceByName(
177 const GURL
& application_url
,
178 const std::string
& interface_name
) {
179 StubServiceProvider
* stub_sp
= new StubServiceProvider
;
180 ServiceProviderPtr spp
;
181 BindToProxy(stub_sp
, &spp
);
182 ConnectToApplication(application_url
, GURL(), spp
.Pass());
184 stub_sp
->GetRemoteServiceProvider()->ConnectToService(
185 interface_name
, pipe
.handle1
.Pass());
186 return pipe
.handle0
.Pass();