OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "mojo/application_manager/application_manager.h" | |
6 | |
7 #include <stdio.h> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/lazy_instance.h" | |
11 #include "base/logging.h" | |
12 #include "base/macros.h" | |
13 #include "base/stl_util.h" | |
14 #include "mojo/application_manager/application_loader.h" | |
15 #include "mojo/public/cpp/application/connect.h" | |
16 #include "mojo/public/cpp/bindings/binding.h" | |
17 #include "mojo/public/cpp/bindings/error_handler.h" | |
18 #include "mojo/public/interfaces/application/shell.mojom.h" | |
19 #include "mojo/services/content_handler/public/interfaces/content_handler.mojom.
h" | |
20 | |
21 namespace mojo { | |
22 | |
23 namespace { | |
24 // Used by TestAPI. | |
25 bool has_created_instance = false; | |
26 | |
27 class StubServiceProvider : public InterfaceImpl<ServiceProvider> { | |
28 public: | |
29 ServiceProvider* GetRemoteServiceProvider() { return client(); } | |
30 | |
31 private: | |
32 void ConnectToService(const String& service_name, | |
33 ScopedMessagePipeHandle client_handle) override {} | |
34 }; | |
35 | |
36 } // namespace | |
37 | |
38 | |
39 ApplicationManager::Delegate::~Delegate() { | |
40 } | |
41 | |
42 void ApplicationManager::Delegate::OnApplicationError(const GURL& url) { | |
43 LOG(ERROR) << "Communication error with application: " << url.spec(); | |
44 } | |
45 | |
46 GURL ApplicationManager::Delegate::ResolveURL(const GURL& url) { | |
47 return url; | |
48 } | |
49 | |
50 class ApplicationManager::ContentHandlerConnection : public ErrorHandler { | |
51 public: | |
52 ContentHandlerConnection(ApplicationManager* manager, | |
53 const GURL& content_handler_url) | |
54 : manager_(manager), content_handler_url_(content_handler_url) { | |
55 ServiceProviderPtr services; | |
56 manager->ConnectToApplication(content_handler_url, GURL(), | |
57 GetProxy(&services), nullptr); | |
58 mojo::ConnectToService(services.get(), &content_handler_); | |
59 content_handler_.set_error_handler(this); | |
60 } | |
61 | |
62 ContentHandler* content_handler() { return content_handler_.get(); } | |
63 | |
64 GURL content_handler_url() { return content_handler_url_; } | |
65 | |
66 private: | |
67 // ErrorHandler implementation: | |
68 void OnConnectionError() override { manager_->OnContentHandlerError(this); } | |
69 | |
70 ApplicationManager* manager_; | |
71 GURL content_handler_url_; | |
72 ContentHandlerPtr content_handler_; | |
73 | |
74 DISALLOW_COPY_AND_ASSIGN(ContentHandlerConnection); | |
75 }; | |
76 | |
77 // static | |
78 ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager) | |
79 : manager_(manager) { | |
80 } | |
81 | |
82 ApplicationManager::TestAPI::~TestAPI() { | |
83 } | |
84 | |
85 bool ApplicationManager::TestAPI::HasCreatedInstance() { | |
86 return has_created_instance; | |
87 } | |
88 | |
89 bool ApplicationManager::TestAPI::HasFactoryForURL(const GURL& url) const { | |
90 return manager_->url_to_shell_impl_.find(url) != | |
91 manager_->url_to_shell_impl_.end(); | |
92 } | |
93 | |
94 ApplicationManager::ApplicationManager(Delegate* delegate) | |
95 : delegate_(delegate), | |
96 weak_ptr_factory_(this) { | |
97 } | |
98 | |
99 ApplicationManager::~ApplicationManager() { | |
100 STLDeleteValues(&url_to_content_handler_); | |
101 TerminateShellConnections(); | |
102 STLDeleteValues(&url_to_loader_); | |
103 STLDeleteValues(&scheme_to_loader_); | |
104 } | |
105 | |
106 void ApplicationManager::TerminateShellConnections() { | |
107 STLDeleteValues(&url_to_shell_impl_); | |
108 } | |
109 | |
110 void ApplicationManager::ConnectToApplication( | |
111 const GURL& requested_url, | |
112 const GURL& requestor_url, | |
113 InterfaceRequest<ServiceProvider> services, | |
114 ServiceProviderPtr exposed_services) { | |
115 DCHECK(requested_url.is_valid()); | |
116 ApplicationLoader* loader = GetLoaderForURL(requested_url, | |
117 DONT_INCLUDE_DEFAULT_LOADER); | |
118 if (loader) { | |
119 ConnectToApplicationImpl(requested_url, requested_url, requestor_url, | |
120 services.Pass(), exposed_services.Pass(), loader); | |
121 return; | |
122 } | |
123 | |
124 GURL resolved_url = delegate_->ResolveURL(requested_url); | |
125 loader = GetLoaderForURL(resolved_url, INCLUDE_DEFAULT_LOADER); | |
126 if (loader) { | |
127 ConnectToApplicationImpl(requested_url, resolved_url, requestor_url, | |
128 services.Pass(), exposed_services.Pass(), loader); | |
129 return; | |
130 } | |
131 | |
132 LOG(WARNING) << "Could not find loader to load application: " | |
133 << requested_url.spec(); | |
134 } | |
135 | |
136 void ApplicationManager::ConnectToApplicationImpl( | |
137 const GURL& requested_url, | |
138 const GURL& resolved_url, | |
139 const GURL& requestor_url, | |
140 InterfaceRequest<ServiceProvider> services, | |
141 ServiceProviderPtr exposed_services, | |
142 ApplicationLoader* loader) { | |
143 ShellImpl* shell = nullptr; | |
144 URLToShellImplMap::const_iterator shell_it = | |
145 url_to_shell_impl_.find(resolved_url); | |
146 if (shell_it != url_to_shell_impl_.end()) { | |
147 shell = shell_it->second; | |
148 } else { | |
149 MessagePipe pipe; | |
150 shell = | |
151 new ShellImpl(pipe.handle0.Pass(), this, requested_url, resolved_url); | |
152 url_to_shell_impl_[resolved_url] = shell; | |
153 shell->client()->Initialize(GetArgsForURL(requested_url)); | |
154 | |
155 loader->Load(this, resolved_url, pipe.handle1.Pass(), | |
156 base::Bind(&ApplicationManager::LoadWithContentHandler, | |
157 weak_ptr_factory_.GetWeakPtr())); | |
158 } | |
159 ConnectToClient(shell, resolved_url, requestor_url, services.Pass(), | |
160 exposed_services.Pass()); | |
161 } | |
162 | |
163 void ApplicationManager::ConnectToClient( | |
164 ShellImpl* shell_impl, | |
165 const GURL& url, | |
166 const GURL& requestor_url, | |
167 InterfaceRequest<ServiceProvider> services, | |
168 ServiceProviderPtr exposed_services) { | |
169 shell_impl->ConnectToClient(requestor_url, services.Pass(), | |
170 exposed_services.Pass()); | |
171 } | |
172 | |
173 void ApplicationManager::RegisterExternalApplication( | |
174 const GURL& url, | |
175 ScopedMessagePipeHandle shell_handle) { | |
176 ShellImpl* shell_impl = new ShellImpl(shell_handle.Pass(), this, url, url); | |
177 url_to_shell_impl_[url] = shell_impl; | |
178 shell_impl->client()->Initialize(GetArgsForURL(url)); | |
179 } | |
180 | |
181 void ApplicationManager::LoadWithContentHandler( | |
182 const GURL& content_handler_url, | |
183 ScopedMessagePipeHandle shell_handle, | |
184 URLResponsePtr url_response) { | |
185 ContentHandlerConnection* connection = NULL; | |
186 URLToContentHandlerMap::iterator iter = | |
187 url_to_content_handler_.find(content_handler_url); | |
188 if (iter != url_to_content_handler_.end()) { | |
189 connection = iter->second; | |
190 } else { | |
191 connection = new ContentHandlerConnection(this, content_handler_url); | |
192 url_to_content_handler_[content_handler_url] = connection; | |
193 } | |
194 | |
195 connection->content_handler()->StartApplication( | |
196 MakeProxy<Shell>(shell_handle.Pass()), url_response.Pass()); | |
197 } | |
198 | |
199 void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, | |
200 const GURL& url) { | |
201 URLToLoaderMap::iterator it = url_to_loader_.find(url); | |
202 if (it != url_to_loader_.end()) | |
203 delete it->second; | |
204 url_to_loader_[url] = loader.release(); | |
205 } | |
206 | |
207 void ApplicationManager::SetLoaderForScheme( | |
208 scoped_ptr<ApplicationLoader> loader, | |
209 const std::string& scheme) { | |
210 SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme); | |
211 if (it != scheme_to_loader_.end()) | |
212 delete it->second; | |
213 scheme_to_loader_[scheme] = loader.release(); | |
214 } | |
215 | |
216 void ApplicationManager::SetArgsForURL(const std::vector<std::string>& args, | |
217 const GURL& url) { | |
218 url_to_args_[url] = args; | |
219 } | |
220 | |
221 ApplicationLoader* ApplicationManager::GetLoaderForURL( | |
222 const GURL& url, IncludeDefaultLoader include_default_loader) { | |
223 auto url_it = url_to_loader_.find(url); | |
224 if (url_it != url_to_loader_.end()) | |
225 return url_it->second; | |
226 auto scheme_it = scheme_to_loader_.find(url.scheme()); | |
227 if (scheme_it != scheme_to_loader_.end()) | |
228 return scheme_it->second; | |
229 if (include_default_loader == INCLUDE_DEFAULT_LOADER) | |
230 return default_loader_.get(); | |
231 return NULL; | |
232 } | |
233 | |
234 void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) { | |
235 // Called from ~ShellImpl, so we do not need to call Destroy here. | |
236 const GURL url = shell_impl->url(); | |
237 const GURL requested_url = shell_impl->requested_url(); | |
238 // Remove the shell. | |
239 URLToShellImplMap::iterator it = url_to_shell_impl_.find(url); | |
240 DCHECK(it != url_to_shell_impl_.end()); | |
241 delete it->second; | |
242 url_to_shell_impl_.erase(it); | |
243 ApplicationLoader* loader = GetLoaderForURL(requested_url, | |
244 INCLUDE_DEFAULT_LOADER); | |
245 if (loader) | |
246 loader->OnApplicationError(this, url); | |
247 delegate_->OnApplicationError(requested_url); | |
248 } | |
249 | |
250 void ApplicationManager::OnContentHandlerError( | |
251 ContentHandlerConnection* content_handler) { | |
252 // Remove the mapping to the content handler. | |
253 auto it = | |
254 url_to_content_handler_.find(content_handler->content_handler_url()); | |
255 DCHECK(it != url_to_content_handler_.end()); | |
256 delete it->second; | |
257 url_to_content_handler_.erase(it); | |
258 } | |
259 | |
260 ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( | |
261 const GURL& application_url, | |
262 const std::string& interface_name) { | |
263 ServiceProviderPtr services; | |
264 ConnectToApplication(application_url, GURL(), GetProxy(&services), nullptr); | |
265 MessagePipe pipe; | |
266 services->ConnectToService(interface_name, pipe.handle1.Pass()); | |
267 return pipe.handle0.Pass(); | |
268 } | |
269 | |
270 Array<String> ApplicationManager::GetArgsForURL(const GURL& url) { | |
271 URLToArgsMap::const_iterator args_it = url_to_args_.find(url); | |
272 if (args_it != url_to_args_.end()) | |
273 return Array<String>::From(args_it->second); | |
274 return Array<String>(); | |
275 } | |
276 } // namespace mojo | |
OLD | NEW |