diff options
author | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-27 23:41:34 +0000 |
---|---|---|
committer | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-27 23:41:34 +0000 |
commit | fadab2ebbefc8dfcec3b25dc6324612a3b9ff565 (patch) | |
tree | d9d4aa7ca0b84bef47c22c7c7aacc1af340a7984 /mojo/service_manager | |
parent | 33fdddfddcca933851c1a3044d0d881cd5455dfd (diff) | |
download | chromium_src-fadab2ebbefc8dfcec3b25dc6324612a3b9ff565.zip chromium_src-fadab2ebbefc8dfcec3b25dc6324612a3b9ff565.tar.gz chromium_src-fadab2ebbefc8dfcec3b25dc6324612a3b9ff565.tar.bz2 |
Move service_manager to top level dir
BUG=None
TEST=Existing
TBR=darin
Review URL: https://codereview.chromium.org/180243020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@253973 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/service_manager')
-rw-r--r-- | mojo/service_manager/service_manager.cc | 106 | ||||
-rw-r--r-- | mojo/service_manager/service_manager.h | 73 | ||||
-rw-r--r-- | mojo/service_manager/service_manager_unittest.cc | 138 | ||||
-rw-r--r-- | mojo/service_manager/test.mojom | 17 |
4 files changed, 334 insertions, 0 deletions
diff --git a/mojo/service_manager/service_manager.cc b/mojo/service_manager/service_manager.cc new file mode 100644 index 0000000..bfc2bd7 --- /dev/null +++ b/mojo/service_manager/service_manager.cc @@ -0,0 +1,106 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/service_manager/service_manager.h" + +#include "base/logging.h" +#include "mojo/public/bindings/allocation_scope.h" +#include "mojo/public/bindings/error_handler.h" +#include "mojo/public/bindings/remote_ptr.h" + +namespace mojo { +namespace shell { + +class ServiceManager::ServiceFactory : public Shell, public ErrorHandler { + public: + ServiceFactory(ServiceManager* manager, const GURL& url) + : manager_(manager), + url_(url) { + InterfacePipe<Shell> pipe; + shell_client_.reset(pipe.handle_to_peer.Pass(), this, this); + manager_->GetLoaderForURL(url)->Load(url, pipe.handle_to_self.Pass()); + } + virtual ~ServiceFactory() {} + + void ConnectToClient(ScopedMessagePipeHandle handle) { + if (handle.is_valid()) { + AllocationScope scope; + shell_client_->AcceptConnection(url_.spec(), handle.Pass()); + } + } + + virtual void Connect(const String& url, + ScopedMessagePipeHandle client_pipe) MOJO_OVERRIDE { + manager_->Connect(GURL(url.To<std::string>()), client_pipe.Pass()); + } + + virtual void OnError() MOJO_OVERRIDE { + manager_->RemoveServiceFactory(this); + } + + const GURL& url() const { return url_; } + + private: + ServiceManager* const manager_; + const GURL url_; + RemotePtr<ShellClient> shell_client_; + DISALLOW_COPY_AND_ASSIGN(ServiceFactory); +}; + +ServiceManager::Loader::Loader() {} +ServiceManager::Loader::~Loader() {} + +bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const { + return manager_->url_to_service_factory_.find(url) != + manager_->url_to_service_factory_.end(); +} + +ServiceManager::ServiceManager() : default_loader_(NULL) { +} + +ServiceManager::~ServiceManager() { + for (ServiceFactoryMap::iterator it = url_to_service_factory_.begin(); + it != url_to_service_factory_.end(); ++it) { + delete it->second; + } + url_to_service_factory_.clear(); +} + +void ServiceManager::SetLoaderForURL(Loader* loader, const GURL& gurl) { + DCHECK(url_to_loader_.find(gurl) == url_to_loader_.end()); + url_to_loader_[gurl] = loader; +} + +ServiceManager::Loader* ServiceManager::GetLoaderForURL(const GURL& gurl) { + LoaderMap::const_iterator it = url_to_loader_.find(gurl); + if (it != url_to_loader_.end()) + return it->second; + DCHECK(default_loader_); + return default_loader_; +} + +void ServiceManager::Connect(const GURL& url, + ScopedMessagePipeHandle client_handle) { + ServiceFactoryMap::const_iterator service_it = + url_to_service_factory_.find(url); + ServiceFactory* service_factory; + if (service_it != url_to_service_factory_.end()) { + service_factory = service_it->second; + } else { + service_factory = new ServiceFactory(this, url); + url_to_service_factory_[url] = service_factory; + } + service_factory->ConnectToClient(client_handle.Pass()); +} + +void ServiceManager::RemoveServiceFactory(ServiceFactory* service_factory) { + ServiceFactoryMap::iterator it = + url_to_service_factory_.find(service_factory->url()); + DCHECK(it != url_to_service_factory_.end()); + delete it->second; + url_to_service_factory_.erase(it); +} + +} // namespace shell +} // namespace mojo diff --git a/mojo/service_manager/service_manager.h b/mojo/service_manager/service_manager.h new file mode 100644 index 0000000..4c7cfd58 --- /dev/null +++ b/mojo/service_manager/service_manager.h @@ -0,0 +1,73 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_SERVICE_MANAGER_SERVICE_MANAGER_H_ +#define MOJO_SERVICE_MANAGER_SERVICE_MANAGER_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "mojo/public/shell/shell.mojom.h" +#include "mojo/public/system/core_cpp.h" +#include "url/gurl.h" + +namespace mojo { +namespace shell { + +class ServiceManager { + public: + // Interface to allowing default loading behavior to be overridden for a + // specific url. + class Loader { + public: + virtual ~Loader(); + virtual void Load(const GURL& url, ScopedShellHandle service_handle) = 0; + protected: + Loader(); + }; + + // API for testing. + class TestAPI { + private: + friend class ServiceManagerTest; + explicit TestAPI(ServiceManager* manager) : manager_(manager) {} + // Returns true if there is a ServiceFactory for this URL. + bool HasFactoryForURL(const GURL& url) const; + + ServiceManager* manager_; + }; + + ServiceManager(); + ~ServiceManager(); + + // Sets the default Loader to be used if not overridden by SetLoaderForURL(). + // Does not take ownership of |loader|. + void set_default_loader(Loader* loader) { default_loader_ = loader; } + // Sets a Loader to be used for a specific url. + // Does not take ownership of |loader|. + void SetLoaderForURL(Loader* loader, const GURL& gurl); + // Returns the Loader to use for a url (using default if not overridden.) + Loader* GetLoaderForURL(const GURL& gurl); + // Loads a service if necessary and establishes a new client connection. + void Connect(const GURL& url, ScopedMessagePipeHandle client_handle); + + private: + class ServiceFactory; + + // Removes a ServiceFactory when it no longer has any connections. + void RemoveServiceFactory(ServiceFactory* service_factory); + + Loader* default_loader_; + typedef std::map<GURL, ServiceFactory*> ServiceFactoryMap; + ServiceFactoryMap url_to_service_factory_; + typedef std::map<GURL, Loader*> LoaderMap; + LoaderMap url_to_loader_; + DISALLOW_COPY_AND_ASSIGN(ServiceManager); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SERVICE_MANAGER_SERVICE_MANAGER_H_ diff --git a/mojo/service_manager/service_manager_unittest.cc b/mojo/service_manager/service_manager_unittest.cc new file mode 100644 index 0000000..fba2044 --- /dev/null +++ b/mojo/service_manager/service_manager_unittest.cc @@ -0,0 +1,138 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/bindings/allocation_scope.h" +#include "mojo/public/bindings/remote_ptr.h" +#include "mojo/public/environment/environment.h" +#include "mojo/public/shell/application.h" +#include "mojo/public/shell/shell.mojom.h" +#include "mojo/public/utility/run_loop.h" +#include "mojo/service_manager/service_manager.h" +#include "mojo/service_manager/test.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace { + +const char kTestURLString[] = "test:testService"; + +struct TestContext { + TestContext() : num_impls(0) {} + std::string last_test_string; + int num_impls; +}; + +class TestServiceImpl : + public Service<TestService, TestServiceImpl, TestContext> { + public: + TestServiceImpl() {} + + virtual ~TestServiceImpl() { + --context()->num_impls; + } + + virtual void Test(const mojo::String& test_string) OVERRIDE { + context()->last_test_string = test_string.To<std::string>(); + client()->AckTest(); + } + + void Initialize(ServiceFactory<TestServiceImpl, TestContext>* service_factory, + ScopedMessagePipeHandle client_handle) { + Service<TestService, TestServiceImpl, TestContext>::Initialize( + service_factory, client_handle.Pass()); + ++context()->num_impls; + } +}; + +class TestClientImpl : public TestClient { + public: + explicit TestClientImpl(ScopedTestServiceHandle service_handle) + : service_(service_handle.Pass(), this), + quit_after_ack_(false) { + } + + virtual ~TestClientImpl() {} + + virtual void AckTest() OVERRIDE { + if (quit_after_ack_) + mojo::RunLoop::current()->Quit(); + } + + void Test(std::string test_string) { + AllocationScope scope; + quit_after_ack_ = true; + service_->Test(mojo::String(test_string)); + } + + private: + RemotePtr<TestService> service_; + bool quit_after_ack_; + DISALLOW_COPY_AND_ASSIGN(TestClientImpl); +}; +} // namespace + +class ServiceManagerTest : public testing::Test, + public ServiceManager::Loader { + public: + ServiceManagerTest() {} + + virtual ~ServiceManagerTest() {} + + virtual void SetUp() OVERRIDE { + GURL test_url(kTestURLString); + service_manager_.reset(new ServiceManager); + service_manager_->SetLoaderForURL(this, test_url); + + InterfacePipe<TestService, AnyInterface> pipe; + test_client_.reset(new TestClientImpl(pipe.handle_to_self.Pass())); + service_manager_->Connect(test_url, pipe.handle_to_peer.Pass()); + } + + virtual void TearDown() OVERRIDE { + test_client_.reset(NULL); + test_app_.reset(NULL); + service_manager_.reset(NULL); + } + + virtual void Load(const GURL& url, + ScopedShellHandle shell_handle) OVERRIDE { + test_app_.reset(new Application(shell_handle.Pass())); + test_app_->AddServiceFactory( + new ServiceFactory<TestServiceImpl, TestContext>(&context_)); + } + + bool HasFactoryForTestURL() { + ServiceManager::TestAPI manager_test_api(service_manager_.get()); + return manager_test_api.HasFactoryForURL(GURL(kTestURLString)); + } + + protected: + mojo::Environment env_; + mojo::RunLoop loop_; + TestContext context_; + scoped_ptr<Application> test_app_; + scoped_ptr<TestClientImpl> test_client_; + scoped_ptr<ServiceManager> service_manager_; + DISALLOW_COPY_AND_ASSIGN(ServiceManagerTest); +}; + +TEST_F(ServiceManagerTest, Basic) { + test_client_->Test("test"); + loop_.Run(); + EXPECT_EQ(std::string("test"), context_.last_test_string); +} + +TEST_F(ServiceManagerTest, ClientError) { + test_client_->Test("test"); + EXPECT_TRUE(HasFactoryForTestURL()); + loop_.Run(); + EXPECT_EQ(1, context_.num_impls); + test_client_.reset(NULL); + loop_.Run(); + EXPECT_EQ(0, context_.num_impls); + EXPECT_FALSE(HasFactoryForTestURL()); +} +} // namespace shell +} // namespace mojo diff --git a/mojo/service_manager/test.mojom b/mojo/service_manager/test.mojom new file mode 100644 index 0000000..59ebfa9 --- /dev/null +++ b/mojo/service_manager/test.mojom @@ -0,0 +1,17 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module mojo { + +[Peer=TestClient] +interface TestService { + Test(string test_string); +}; + +[Peer=TestService] +interface TestClient { + AckTest(); +}; + +} |