Index: mojo/service_manager/service_manager.cc |
diff --git a/mojo/service_manager/service_manager.cc b/mojo/service_manager/service_manager.cc |
index 51efd41feddd0c18205f30f0c4dd24e5a8fce0cf..b0ef1e87417f7736ad8890397c8fa67ffd7f179c 100644 |
--- a/mojo/service_manager/service_manager.cc |
+++ b/mojo/service_manager/service_manager.cc |
@@ -2,18 +2,21 @@ |
// 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/public/cpp/application/connect.h" |
#include "mojo/public/interfaces/application/application.mojom.h" |
#include "mojo/public/interfaces/application/shell.mojom.h" |
#include "mojo/service_manager/service_loader.h" |
+#include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h" |
namespace mojo { |
@@ -33,7 +36,52 @@ class StubServiceProvider : public InterfaceImpl<ServiceProvider> { |
ScopedMessagePipeHandle client_handle) MOJO_OVERRIDE {} |
}; |
-} |
+} // namespace |
+ |
+class ServiceManager::LoadCallbacksImpl : public ServiceLoader::LoadCallbacks { |
+ public: |
+ LoadCallbacksImpl(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 ~LoadCallbacksImpl() { |
+ } |
+ |
+ // LoadCallbacks 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: |
@@ -76,6 +124,21 @@ 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()); |
+ mojo::ConnectToService(service_provider_impl.client(), &content_handler); |
+ } |
+ |
+ StubServiceProvider service_provider_impl; |
+ ContentHandlerPtr content_handler; |
+}; |
+ |
// static |
ServiceManager::TestAPI::TestAPI(ServiceManager* manager) : manager_(manager) { |
} |
@@ -92,10 +155,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_); |
TerminateShellConnections(); |
STLDeleteValues(&url_to_loader_); |
STLDeleteValues(&scheme_to_loader_); |
@@ -117,15 +183,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<LoadCallbacksImpl> callbacks( |
+ new LoadCallbacksImpl(weak_ptr_factory_.GetWeakPtr(), |
+ url, |
+ requestor_url, |
+ service_provider.Pass())); |
+ GetLoaderForURL(url)->Load(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, |
@@ -135,6 +210,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); |