OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/application_manager/application_manager.h" | 5 #include "mojo/application_manager/application_manager.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "mojo/application_manager/application_loader.h" | 14 #include "mojo/application_manager/application_loader.h" |
15 #include "mojo/common/common_type_converters.h" | 15 #include "mojo/common/common_type_converters.h" |
16 #include "mojo/public/cpp/application/connect.h" | 16 #include "mojo/public/cpp/application/connect.h" |
| 17 #include "mojo/public/cpp/bindings/error_handler.h" |
17 #include "mojo/public/interfaces/application/application.mojom.h" | 18 #include "mojo/public/interfaces/application/application.mojom.h" |
18 #include "mojo/public/interfaces/application/shell.mojom.h" | 19 #include "mojo/public/interfaces/application/shell.mojom.h" |
19 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom.
h" | 20 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom.
h" |
20 | 21 |
21 namespace mojo { | 22 namespace mojo { |
22 | 23 |
23 namespace { | 24 namespace { |
24 // Used by TestAPI. | 25 // Used by TestAPI. |
25 bool has_created_instance = false; | 26 bool has_created_instance = false; |
26 | 27 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 | 109 |
109 private: | 110 private: |
110 void OnConnectionError() override { manager_->OnShellImplError(this); } | 111 void OnConnectionError() override { manager_->OnShellImplError(this); } |
111 | 112 |
112 ApplicationManager* const manager_; | 113 ApplicationManager* const manager_; |
113 const GURL url_; | 114 const GURL url_; |
114 | 115 |
115 DISALLOW_COPY_AND_ASSIGN(ShellImpl); | 116 DISALLOW_COPY_AND_ASSIGN(ShellImpl); |
116 }; | 117 }; |
117 | 118 |
118 struct ApplicationManager::ContentHandlerConnection { | 119 class ApplicationManager::ContentHandlerConnection : public ErrorHandler { |
| 120 public: |
119 ContentHandlerConnection(ApplicationManager* manager, | 121 ContentHandlerConnection(ApplicationManager* manager, |
120 const GURL& content_handler_url) { | 122 const GURL& content_handler_url) |
| 123 : manager_(manager), content_handler_url_(content_handler_url) { |
121 ServiceProviderPtr service_provider; | 124 ServiceProviderPtr service_provider; |
122 BindToProxy(&service_provider_impl, &service_provider); | 125 WeakBindToProxy(&service_provider_impl_, &service_provider); |
123 manager->ConnectToApplication( | 126 manager->ConnectToApplication( |
124 content_handler_url, GURL(), service_provider.Pass()); | 127 content_handler_url, GURL(), service_provider.Pass()); |
125 mojo::ConnectToService(service_provider_impl.client(), &content_handler); | 128 mojo::ConnectToService(service_provider_impl_.client(), &content_handler_); |
| 129 content_handler_.set_error_handler(this); |
126 } | 130 } |
127 | 131 |
128 StubServiceProvider service_provider_impl; | 132 ContentHandler* content_handler() { return content_handler_.get(); } |
129 ContentHandlerPtr content_handler; | 133 |
| 134 GURL content_handler_url() { return content_handler_url_; } |
| 135 |
| 136 private: |
| 137 // ErrorHandler implementation: |
| 138 void OnConnectionError() override { manager_->OnContentHandlerError(this); } |
| 139 |
| 140 ApplicationManager* manager_; |
| 141 GURL content_handler_url_; |
| 142 StubServiceProvider service_provider_impl_; |
| 143 ContentHandlerPtr content_handler_; |
| 144 |
| 145 DISALLOW_COPY_AND_ASSIGN(ContentHandlerConnection); |
130 }; | 146 }; |
131 | 147 |
132 // static | 148 // static |
133 ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager) | 149 ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager) |
134 : manager_(manager) { | 150 : manager_(manager) { |
135 } | 151 } |
136 | 152 |
137 ApplicationManager::TestAPI::~TestAPI() { | 153 ApplicationManager::TestAPI::~TestAPI() { |
138 } | 154 } |
139 | 155 |
(...skipping 14 matching lines...) Expand all Loading... |
154 | 170 |
155 ApplicationManager::~ApplicationManager() { | 171 ApplicationManager::~ApplicationManager() { |
156 STLDeleteValues(&url_to_content_handler_); | 172 STLDeleteValues(&url_to_content_handler_); |
157 TerminateShellConnections(); | 173 TerminateShellConnections(); |
158 STLDeleteValues(&url_to_loader_); | 174 STLDeleteValues(&url_to_loader_); |
159 STLDeleteValues(&scheme_to_loader_); | 175 STLDeleteValues(&scheme_to_loader_); |
160 } | 176 } |
161 | 177 |
162 void ApplicationManager::TerminateShellConnections() { | 178 void ApplicationManager::TerminateShellConnections() { |
163 STLDeleteValues(&url_to_shell_impl_); | 179 STLDeleteValues(&url_to_shell_impl_); |
| 180 STLDeleteElements(&content_shell_impls_); |
164 } | 181 } |
165 | 182 |
166 // static | 183 // static |
167 ApplicationManager* ApplicationManager::GetInstance() { | 184 ApplicationManager* ApplicationManager::GetInstance() { |
168 static base::LazyInstance<ApplicationManager> instance = | 185 static base::LazyInstance<ApplicationManager> instance = |
169 LAZY_INSTANCE_INITIALIZER; | 186 LAZY_INSTANCE_INITIALIZER; |
170 has_created_instance = true; | 187 has_created_instance = true; |
171 return &instance.Get(); | 188 return &instance.Get(); |
172 } | 189 } |
173 | 190 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 ScopedMessagePipeHandle* shell_handle) { | 234 ScopedMessagePipeHandle* shell_handle) { |
218 ShellImpl* shell_impl = NULL; | 235 ShellImpl* shell_impl = NULL; |
219 URLToShellImplMap::iterator iter = url_to_shell_impl_.find(url); | 236 URLToShellImplMap::iterator iter = url_to_shell_impl_.find(url); |
220 if (iter != url_to_shell_impl_.end()) { | 237 if (iter != url_to_shell_impl_.end()) { |
221 // This can happen because services are loaded asynchronously. So if we get | 238 // This can happen because services are loaded asynchronously. So if we get |
222 // two requests for the same service close to each other, we might get here | 239 // two requests for the same service close to each other, we might get here |
223 // and find that we already have it. | 240 // and find that we already have it. |
224 shell_impl = iter->second; | 241 shell_impl = iter->second; |
225 } else { | 242 } else { |
226 MessagePipe pipe; | 243 MessagePipe pipe; |
227 URLToArgsMap::const_iterator args_it = url_to_args_.find(url); | |
228 Array<String> args; | |
229 if (args_it != url_to_args_.end()) | |
230 args = Array<String>::From(args_it->second); | |
231 shell_impl = WeakBindToPipe(new ShellImpl(this, url), pipe.handle1.Pass()); | 244 shell_impl = WeakBindToPipe(new ShellImpl(this, url), pipe.handle1.Pass()); |
232 url_to_shell_impl_[url] = shell_impl; | 245 url_to_shell_impl_[url] = shell_impl; |
233 *shell_handle = pipe.handle0.Pass(); | 246 *shell_handle = pipe.handle0.Pass(); |
234 shell_impl->client()->Initialize(args.Pass()); | 247 shell_impl->client()->Initialize(GetArgsForURL(url)); |
235 } | 248 } |
236 | 249 |
237 ConnectToClient(shell_impl, url, requestor_url, service_provider.Pass()); | 250 ConnectToClient(shell_impl, url, requestor_url, service_provider.Pass()); |
238 } | 251 } |
239 | 252 |
240 void ApplicationManager::LoadWithContentHandler( | 253 void ApplicationManager::LoadWithContentHandler( |
241 const GURL& content_url, | 254 const GURL& content_url, |
242 const GURL& requestor_url, | 255 const GURL& requestor_url, |
243 const GURL& content_handler_url, | 256 const GURL& content_handler_url, |
244 URLResponsePtr url_response, | 257 URLResponsePtr url_response, |
245 ServiceProviderPtr service_provider) { | 258 ServiceProviderPtr service_provider) { |
246 ContentHandlerConnection* connection = NULL; | 259 ContentHandlerConnection* connection = NULL; |
247 URLToContentHandlerMap::iterator iter = | 260 URLToContentHandlerMap::iterator iter = |
248 url_to_content_handler_.find(content_handler_url); | 261 url_to_content_handler_.find(content_handler_url); |
249 if (iter != url_to_content_handler_.end()) { | 262 if (iter != url_to_content_handler_.end()) { |
250 connection = iter->second; | 263 connection = iter->second; |
251 } else { | 264 } else { |
252 connection = new ContentHandlerConnection(this, content_handler_url); | 265 connection = new ContentHandlerConnection(this, content_handler_url); |
253 url_to_content_handler_[content_handler_url] = connection; | 266 url_to_content_handler_[content_handler_url] = connection; |
254 } | 267 } |
255 | 268 |
256 InterfaceRequest<ServiceProvider> spir; | 269 ShellPtr shell_proxy; |
257 spir.Bind(service_provider.PassMessagePipe()); | 270 ShellImpl* shell_impl = |
258 connection->content_handler->OnConnect( | 271 WeakBindToProxy(new ShellImpl(this, content_url), &shell_proxy); |
259 requestor_url.spec(), url_response.Pass(), spir.Pass()); | 272 content_shell_impls_.insert(shell_impl); |
| 273 shell_impl->client()->Initialize(GetArgsForURL(content_url)); |
| 274 |
| 275 connection->content_handler()->StartApplication(shell_proxy.Pass(), |
| 276 url_response.Pass()); |
| 277 ConnectToClient( |
| 278 shell_impl, content_url, requestor_url, service_provider.Pass()); |
260 } | 279 } |
261 | 280 |
262 void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, | 281 void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, |
263 const GURL& url) { | 282 const GURL& url) { |
264 URLToLoaderMap::iterator it = url_to_loader_.find(url); | 283 URLToLoaderMap::iterator it = url_to_loader_.find(url); |
265 if (it != url_to_loader_.end()) | 284 if (it != url_to_loader_.end()) |
266 delete it->second; | 285 delete it->second; |
267 url_to_loader_[url] = loader.release(); | 286 url_to_loader_[url] = loader.release(); |
268 } | 287 } |
269 | 288 |
(...skipping 21 matching lines...) Expand all Loading... |
291 return url_it->second; | 310 return url_it->second; |
292 SchemeToLoaderMap::const_iterator scheme_it = | 311 SchemeToLoaderMap::const_iterator scheme_it = |
293 scheme_to_loader_.find(url.scheme()); | 312 scheme_to_loader_.find(url.scheme()); |
294 if (scheme_it != scheme_to_loader_.end()) | 313 if (scheme_it != scheme_to_loader_.end()) |
295 return scheme_it->second; | 314 return scheme_it->second; |
296 return default_loader_.get(); | 315 return default_loader_.get(); |
297 } | 316 } |
298 | 317 |
299 void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) { | 318 void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) { |
300 // Called from ~ShellImpl, so we do not need to call Destroy here. | 319 // Called from ~ShellImpl, so we do not need to call Destroy here. |
| 320 auto content_shell_it = content_shell_impls_.find(shell_impl); |
| 321 if (content_shell_it != content_shell_impls_.end()) { |
| 322 delete (*content_shell_it); |
| 323 content_shell_impls_.erase(content_shell_it); |
| 324 return; |
| 325 } |
301 const GURL url = shell_impl->url(); | 326 const GURL url = shell_impl->url(); |
| 327 // Remove the shell. |
302 URLToShellImplMap::iterator it = url_to_shell_impl_.find(url); | 328 URLToShellImplMap::iterator it = url_to_shell_impl_.find(url); |
303 DCHECK(it != url_to_shell_impl_.end()); | 329 DCHECK(it != url_to_shell_impl_.end()); |
304 delete it->second; | 330 delete it->second; |
305 url_to_shell_impl_.erase(it); | 331 url_to_shell_impl_.erase(it); |
306 ApplicationLoader* loader = GetLoaderForURL(url); | 332 ApplicationLoader* loader = GetLoaderForURL(url); |
307 if (loader) | 333 if (loader) |
308 loader->OnApplicationError(this, url); | 334 loader->OnApplicationError(this, url); |
309 if (delegate_) | 335 if (delegate_) |
310 delegate_->OnApplicationError(url); | 336 delegate_->OnApplicationError(url); |
311 } | 337 } |
312 | 338 |
| 339 void ApplicationManager::OnContentHandlerError( |
| 340 ContentHandlerConnection* content_handler) { |
| 341 // Remove the mapping to the content handler. |
| 342 auto it = |
| 343 url_to_content_handler_.find(content_handler->content_handler_url()); |
| 344 DCHECK(it != url_to_content_handler_.end()); |
| 345 delete it->second; |
| 346 url_to_content_handler_.erase(it); |
| 347 } |
| 348 |
313 ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( | 349 ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( |
314 const GURL& application_url, | 350 const GURL& application_url, |
315 const std::string& interface_name) { | 351 const std::string& interface_name) { |
316 StubServiceProvider* stub_sp = new StubServiceProvider; | 352 StubServiceProvider* stub_sp = new StubServiceProvider; |
317 ServiceProviderPtr spp; | 353 ServiceProviderPtr spp; |
318 BindToProxy(stub_sp, &spp); | 354 BindToProxy(stub_sp, &spp); |
319 ConnectToApplication(application_url, GURL(), spp.Pass()); | 355 ConnectToApplication(application_url, GURL(), spp.Pass()); |
320 MessagePipe pipe; | 356 MessagePipe pipe; |
321 stub_sp->GetRemoteServiceProvider()->ConnectToService(interface_name, | 357 stub_sp->GetRemoteServiceProvider()->ConnectToService(interface_name, |
322 pipe.handle1.Pass()); | 358 pipe.handle1.Pass()); |
323 return pipe.handle0.Pass(); | 359 return pipe.handle0.Pass(); |
324 } | 360 } |
| 361 |
| 362 Array<String> ApplicationManager::GetArgsForURL(const GURL& url) { |
| 363 URLToArgsMap::const_iterator args_it = url_to_args_.find(url); |
| 364 if (args_it != url_to_args_.end()) |
| 365 return Array<String>::From(args_it->second); |
| 366 return Array<String>(); |
| 367 } |
325 } // namespace mojo | 368 } // namespace mojo |
OLD | NEW |