| 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 |