[Android] Enable input event stream validation
[chromium-blink-merge.git] / mojo / application_manager / application_manager.cc
blobb0a300eb4b6c1b17e237dfc5f77a4129242e4b30
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.
5 #include "mojo/application_manager/application_manager.h"
7 #include <stdio.h>
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/common/common_type_converters.h"
16 #include "mojo/public/cpp/application/connect.h"
17 #include "mojo/public/interfaces/application/application.mojom.h"
18 #include "mojo/public/interfaces/application/shell.mojom.h"
19 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h"
21 namespace mojo {
23 namespace {
24 // Used by TestAPI.
25 bool has_created_instance = false;
27 class StubServiceProvider : public InterfaceImpl<ServiceProvider> {
28 public:
29 ServiceProvider* GetRemoteServiceProvider() { return client(); }
31 private:
32 virtual void ConnectToService(const String& service_name,
33 ScopedMessagePipeHandle client_handle)
34 MOJO_OVERRIDE {}
37 } // namespace
39 ApplicationManager::Delegate::~Delegate() {}
41 class ApplicationManager::LoadCallbacksImpl
42 : public ApplicationLoader::LoadCallbacks {
43 public:
44 LoadCallbacksImpl(base::WeakPtr<ApplicationManager> manager,
45 const GURL& requested_url,
46 const GURL& requestor_url,
47 ServiceProviderPtr service_provider)
48 : manager_(manager),
49 requested_url_(requested_url),
50 requestor_url_(requestor_url),
51 service_provider_(service_provider.Pass()) {}
53 private:
54 virtual ~LoadCallbacksImpl() {}
56 // LoadCallbacks implementation
57 virtual ScopedMessagePipeHandle RegisterApplication() OVERRIDE {
58 ScopedMessagePipeHandle shell_handle;
59 if (manager_) {
60 manager_->RegisterLoadedApplication(requested_url_,
61 requestor_url_,
62 service_provider_.Pass(),
63 &shell_handle);
65 return shell_handle.Pass();
68 virtual void LoadWithContentHandler(const GURL& content_handler_url,
69 URLResponsePtr url_response) OVERRIDE {
70 if (manager_) {
71 manager_->LoadWithContentHandler(requested_url_,
72 requestor_url_,
73 content_handler_url,
74 url_response.Pass(),
75 service_provider_.Pass());
79 base::WeakPtr<ApplicationManager> manager_;
80 GURL requested_url_;
81 GURL requestor_url_;
82 ServiceProviderPtr service_provider_;
85 class ApplicationManager::ShellImpl : public InterfaceImpl<Shell> {
86 public:
87 ShellImpl(ApplicationManager* manager, const GURL& url)
88 : manager_(manager), url_(url) {}
90 virtual ~ShellImpl() {}
92 void ConnectToClient(const GURL& requestor_url,
93 ServiceProviderPtr service_provider) {
94 client()->AcceptConnection(String::From(requestor_url),
95 service_provider.Pass());
98 // ServiceProvider implementation:
99 virtual void ConnectToApplication(
100 const String& app_url,
101 InterfaceRequest<ServiceProvider> in_service_provider) OVERRIDE {
102 ServiceProviderPtr out_service_provider;
103 out_service_provider.Bind(in_service_provider.PassMessagePipe());
104 manager_->ConnectToApplication(
105 app_url.To<GURL>(), url_, out_service_provider.Pass());
108 const GURL& url() const { return url_; }
110 private:
111 virtual void OnConnectionError() OVERRIDE {
112 manager_->OnShellImplError(this);
115 ApplicationManager* const manager_;
116 const GURL url_;
118 DISALLOW_COPY_AND_ASSIGN(ShellImpl);
121 struct ApplicationManager::ContentHandlerConnection {
122 ContentHandlerConnection(ApplicationManager* manager,
123 const GURL& content_handler_url) {
124 ServiceProviderPtr service_provider;
125 BindToProxy(&service_provider_impl, &service_provider);
126 manager->ConnectToApplication(
127 content_handler_url, GURL(), service_provider.Pass());
128 mojo::ConnectToService(service_provider_impl.client(), &content_handler);
131 StubServiceProvider service_provider_impl;
132 ContentHandlerPtr content_handler;
135 // static
136 ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager)
137 : manager_(manager) {
140 ApplicationManager::TestAPI::~TestAPI() {
143 bool ApplicationManager::TestAPI::HasCreatedInstance() {
144 return has_created_instance;
147 bool ApplicationManager::TestAPI::HasFactoryForURL(const GURL& url) const {
148 return manager_->url_to_shell_impl_.find(url) !=
149 manager_->url_to_shell_impl_.end();
152 ApplicationManager::ApplicationManager()
153 : delegate_(NULL),
154 interceptor_(NULL),
155 weak_ptr_factory_(this) {
158 ApplicationManager::~ApplicationManager() {
159 STLDeleteValues(&url_to_content_handler_);
160 TerminateShellConnections();
161 STLDeleteValues(&url_to_loader_);
162 STLDeleteValues(&scheme_to_loader_);
165 void ApplicationManager::TerminateShellConnections() {
166 STLDeleteValues(&url_to_shell_impl_);
169 // static
170 ApplicationManager* ApplicationManager::GetInstance() {
171 static base::LazyInstance<ApplicationManager> instance =
172 LAZY_INSTANCE_INITIALIZER;
173 has_created_instance = true;
174 return &instance.Get();
177 void ApplicationManager::ConnectToApplication(
178 const GURL& url,
179 const GURL& requestor_url,
180 ServiceProviderPtr service_provider) {
181 URLToShellImplMap::const_iterator shell_it = url_to_shell_impl_.find(url);
182 if (shell_it != url_to_shell_impl_.end()) {
183 ConnectToClient(
184 shell_it->second, url, requestor_url, service_provider.Pass());
185 return;
188 scoped_refptr<LoadCallbacksImpl> callbacks(
189 new LoadCallbacksImpl(weak_ptr_factory_.GetWeakPtr(),
190 url,
191 requestor_url,
192 service_provider.Pass()));
193 GetLoaderForURL(url)->Load(this, url, callbacks);
196 void ApplicationManager::ConnectToClient(ShellImpl* shell_impl,
197 const GURL& url,
198 const GURL& requestor_url,
199 ServiceProviderPtr service_provider) {
200 if (interceptor_) {
201 shell_impl->ConnectToClient(
202 requestor_url,
203 interceptor_->OnConnectToClient(url, service_provider.Pass()));
204 } else {
205 shell_impl->ConnectToClient(requestor_url, service_provider.Pass());
209 void ApplicationManager::RegisterLoadedApplication(
210 const GURL& url,
211 const GURL& requestor_url,
212 ServiceProviderPtr service_provider,
213 ScopedMessagePipeHandle* shell_handle) {
214 ShellImpl* shell_impl = NULL;
215 URLToShellImplMap::iterator iter = url_to_shell_impl_.find(url);
216 if (iter != url_to_shell_impl_.end()) {
217 // This can happen because services are loaded asynchronously. So if we get
218 // two requests for the same service close to each other, we might get here
219 // and find that we already have it.
220 shell_impl = iter->second;
221 } else {
222 MessagePipe pipe;
223 shell_impl = WeakBindToPipe(new ShellImpl(this, url), pipe.handle1.Pass());
224 url_to_shell_impl_[url] = shell_impl;
225 *shell_handle = pipe.handle0.Pass();
228 ConnectToClient(shell_impl, url, requestor_url, service_provider.Pass());
231 void ApplicationManager::LoadWithContentHandler(
232 const GURL& content_url,
233 const GURL& requestor_url,
234 const GURL& content_handler_url,
235 URLResponsePtr url_response,
236 ServiceProviderPtr service_provider) {
237 ContentHandlerConnection* connection = NULL;
238 URLToContentHandlerMap::iterator iter =
239 url_to_content_handler_.find(content_handler_url);
240 if (iter != url_to_content_handler_.end()) {
241 connection = iter->second;
242 } else {
243 connection = new ContentHandlerConnection(this, content_handler_url);
244 url_to_content_handler_[content_handler_url] = connection;
247 InterfaceRequest<ServiceProvider> spir;
248 spir.Bind(service_provider.PassMessagePipe());
249 connection->content_handler->OnConnect(
250 content_url.spec(), url_response.Pass(), spir.Pass());
253 void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader,
254 const GURL& url) {
255 URLToLoaderMap::iterator it = url_to_loader_.find(url);
256 if (it != url_to_loader_.end())
257 delete it->second;
258 url_to_loader_[url] = loader.release();
261 void ApplicationManager::SetLoaderForScheme(
262 scoped_ptr<ApplicationLoader> loader,
263 const std::string& scheme) {
264 SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme);
265 if (it != scheme_to_loader_.end())
266 delete it->second;
267 scheme_to_loader_[scheme] = loader.release();
270 void ApplicationManager::SetInterceptor(Interceptor* interceptor) {
271 interceptor_ = interceptor;
274 ApplicationLoader* ApplicationManager::GetLoaderForURL(const GURL& url) {
275 URLToLoaderMap::const_iterator url_it = url_to_loader_.find(url);
276 if (url_it != url_to_loader_.end())
277 return url_it->second;
278 SchemeToLoaderMap::const_iterator scheme_it =
279 scheme_to_loader_.find(url.scheme());
280 if (scheme_it != scheme_to_loader_.end())
281 return scheme_it->second;
282 return default_loader_.get();
285 void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) {
286 // Called from ~ShellImpl, so we do not need to call Destroy here.
287 const GURL url = shell_impl->url();
288 URLToShellImplMap::iterator it = url_to_shell_impl_.find(url);
289 DCHECK(it != url_to_shell_impl_.end());
290 delete it->second;
291 url_to_shell_impl_.erase(it);
292 ApplicationLoader* loader = GetLoaderForURL(url);
293 if (loader)
294 loader->OnApplicationError(this, url);
295 if (delegate_)
296 delegate_->OnApplicationError(url);
299 ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName(
300 const GURL& application_url,
301 const std::string& interface_name) {
302 StubServiceProvider* stub_sp = new StubServiceProvider;
303 ServiceProviderPtr spp;
304 BindToProxy(stub_sp, &spp);
305 ConnectToApplication(application_url, GURL(), spp.Pass());
306 MessagePipe pipe;
307 stub_sp->GetRemoteServiceProvider()->ConnectToService(interface_name,
308 pipe.handle1.Pass());
309 return pipe.handle0.Pass();
311 } // namespace mojo