Chromium Code Reviews| Index: mojo/service_manager/service_manager.cc |
| diff --git a/mojo/service_manager/service_manager.cc b/mojo/service_manager/service_manager.cc |
| index 0f13cfde6b375231d69db0fdd336a8d5a1f18788..6676cc6679f4b0cade83e74483eb6c80df7b2106 100644 |
| --- a/mojo/service_manager/service_manager.cc |
| +++ b/mojo/service_manager/service_manager.cc |
| @@ -2,16 +2,18 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include <stdio.h> |
| - |
| #include "mojo/service_manager/service_manager.h" |
| +#include <stdio.h> |
| + |
| +#include "base/bind.h" |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/stl_util.h" |
| #include "mojo/common/common_type_converters.h" |
| #include "mojo/service_manager/service_loader.h" |
| +#include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h" |
| namespace mojo { |
| @@ -31,7 +33,54 @@ class StubServiceProvider : public InterfaceImpl<ServiceProvider> { |
| ScopedMessagePipeHandle client_handle) MOJO_OVERRIDE {} |
| }; |
| -} |
| +} // namespace |
| + |
| +class ServiceManager::LoadServiceCallbacksImpl |
| + : public ServiceLoader::LoadServiceCallbacks { |
| + public: |
| + LoadServiceCallbacksImpl(base::WeakPtr<ServiceManager> manager, |
| + const GURL& requested_url, |
| + const GURL& requestor_url, |
| + ServiceProviderPtr service_provider) |
| + : manager_(manager), |
| + requested_url_(requested_url), |
| + requestor_url_(requestor_url), |
| + service_provider_(service_provider.Pass()) { |
| + } |
| + |
| + private: |
| + virtual ~LoadServiceCallbacksImpl() { |
| + } |
| + |
| + // LoadServiceCallbacks implementation |
| + virtual ScopedMessagePipeHandle RegisterApplication() OVERRIDE { |
| + ScopedMessagePipeHandle shell_handle; |
| + if (manager_) { |
| + manager_->RegisterLoadedApplication(requested_url_, |
| + requestor_url_, |
| + service_provider_.Pass(), |
| + &shell_handle); |
| + } |
| + return shell_handle.Pass(); |
| + } |
| + |
| + virtual void LoadWithContentHandler( |
| + const GURL& content_handler_url, |
| + URLResponsePtr content) OVERRIDE { |
| + if (manager_) { |
| + manager_->LoadWithContentHandler(requested_url_, |
| + requestor_url_, |
| + content_handler_url, |
| + content.Pass(), |
| + service_provider_.Pass()); |
| + } |
| + } |
| + |
| + base::WeakPtr<ServiceManager> manager_; |
| + GURL requested_url_; |
| + GURL requestor_url_; |
| + ServiceProviderPtr service_provider_; |
| +}; |
| class ServiceManager::ShellImpl : public InterfaceImpl<Shell> { |
| public: |
| @@ -74,6 +123,24 @@ class ServiceManager::ShellImpl : public InterfaceImpl<Shell> { |
| DISALLOW_COPY_AND_ASSIGN(ShellImpl); |
| }; |
| +struct ServiceManager::ContentHandlerConnection { |
| + ContentHandlerConnection(ServiceManager* manager, |
| + const GURL& content_handler_url) { |
| + ServiceProviderPtr service_provider; |
| + BindToProxy(&service_provider_impl, &service_provider); |
| + manager->ConnectToApplication(content_handler_url, |
| + GURL(), |
| + service_provider.Pass()); |
| + MessagePipe pipe; |
| + content_handler.Bind(pipe.handle0.Pass()); |
| + service_provider_impl.client()->ConnectToService(ContentHandler::Name_, |
| + pipe.handle1.Pass()); |
| + } |
| + |
| + StubServiceProvider service_provider_impl; |
| + ContentHandlerPtr content_handler; |
| +}; |
| + |
| // static |
| ServiceManager::TestAPI::TestAPI(ServiceManager* manager) : manager_(manager) { |
| } |
| @@ -90,10 +157,13 @@ bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const { |
| manager_->url_to_shell_impl_.end(); |
| } |
| -ServiceManager::ServiceManager() : interceptor_(NULL) { |
| +ServiceManager::ServiceManager() |
| + : interceptor_(NULL), |
| + weak_ptr_factory_(this) { |
| } |
| ServiceManager::~ServiceManager() { |
| + STLDeleteValues(&url_to_content_handler_); |
|
tim (not reviewing)
2014/08/05 20:45:55
Are connections you're adding here for content han
Aaron Boodman
2014/08/05 22:45:34
Yes, content handlers are also normal mojo applica
|
| TerminateShellConnections(); |
| STLDeleteValues(&url_to_loader_); |
| STLDeleteValues(&scheme_to_loader_); |
| @@ -115,15 +185,24 @@ void ServiceManager::ConnectToApplication(const GURL& url, |
| const GURL& requestor_url, |
| ServiceProviderPtr service_provider) { |
| URLToShellImplMap::const_iterator shell_it = url_to_shell_impl_.find(url); |
| - ShellImpl* shell_impl; |
| if (shell_it != url_to_shell_impl_.end()) { |
| - shell_impl = shell_it->second; |
| - } else { |
| - MessagePipe pipe; |
| - GetLoaderForURL(url)->LoadService(this, url, pipe.handle0.Pass()); |
| - shell_impl = WeakBindToPipe(new ShellImpl(this, url), pipe.handle1.Pass()); |
| - url_to_shell_impl_[url] = shell_impl; |
| + ConnectToClient(shell_it->second, url, requestor_url, |
| + service_provider.Pass()); |
| + return; |
| } |
| + |
| + scoped_refptr<LoadServiceCallbacksImpl> callbacks( |
| + new LoadServiceCallbacksImpl(weak_ptr_factory_.GetWeakPtr(), |
| + url, |
| + requestor_url, |
| + service_provider.Pass())); |
| + GetLoaderForURL(url)->LoadService(this, url, callbacks); |
| +} |
| + |
| +void ServiceManager::ConnectToClient(ShellImpl* shell_impl, |
| + const GURL& url, |
| + const GURL& requestor_url, |
| + ServiceProviderPtr service_provider) { |
| if (interceptor_) { |
| shell_impl->ConnectToClient( |
| requestor_url, |
| @@ -133,6 +212,48 @@ void ServiceManager::ConnectToApplication(const GURL& url, |
| } |
| } |
| +void ServiceManager::RegisterLoadedApplication( |
| + const GURL& url, |
| + const GURL& requestor_url, |
| + ServiceProviderPtr service_provider, |
| + ScopedMessagePipeHandle* shell_handle) { |
| + ShellImpl* shell_impl = NULL; |
| + URLToShellImplMap::iterator iter = url_to_shell_impl_.find(url); |
| + if (iter != url_to_shell_impl_.end()) { |
| + // This can happen because services are loaded asynchronously. So if we get |
| + // two requests for the same service close to each other, we might get here |
| + // and find that we already have it. |
| + shell_impl = iter->second; |
| + } else { |
| + MessagePipe pipe; |
| + shell_impl = WeakBindToPipe(new ShellImpl(this, url), pipe.handle1.Pass()); |
| + url_to_shell_impl_[url] = shell_impl; |
| + *shell_handle = pipe.handle0.Pass(); |
| + } |
| + |
| + ConnectToClient(shell_impl, url, requestor_url, service_provider.Pass()); |
| +} |
| + |
| +void ServiceManager::LoadWithContentHandler( |
| + const GURL& content_url, |
| + const GURL& requestor_url, |
| + const GURL& content_handler_url, |
| + URLResponsePtr content, |
| + ServiceProviderPtr service_provider) { |
| + ContentHandlerConnection* connection = NULL; |
| + URLToContentHandlerMap::iterator iter = |
| + url_to_content_handler_.find(content_handler_url); |
| + if (iter != url_to_content_handler_.end()) { |
| + connection = iter->second; |
| + } else { |
| + connection = new ContentHandlerConnection(this, content_handler_url); |
| + url_to_content_handler_[content_handler_url] = connection; |
| + } |
| + connection->content_handler->OnConnect(content_url.spec(), |
| + content.Pass(), |
| + service_provider.Pass()); |
| +} |
| + |
| void ServiceManager::SetLoaderForURL(scoped_ptr<ServiceLoader> loader, |
| const GURL& url) { |
| URLToLoaderMap::iterator it = url_to_loader_.find(url); |