| Index: mojo/public/cpp/shell/service.h
|
| diff --git a/mojo/public/cpp/shell/service.h b/mojo/public/cpp/shell/service.h
|
| index 7dd08ffa70903abda725513609b92b32bda3dccb..d71b7247aa608d5d0096bd2c510a35170b73fbf1 100644
|
| --- a/mojo/public/cpp/shell/service.h
|
| +++ b/mojo/public/cpp/shell/service.h
|
| @@ -5,10 +5,13 @@
|
| #ifndef MOJO_PUBLIC_SHELL_SERVICE_H_
|
| #define MOJO_PUBLIC_SHELL_SERVICE_H_
|
|
|
| +#include <assert.h>
|
| +
|
| #include <vector>
|
|
|
| +#include "mojo/public/cpp/bindings/allocation_scope.h"
|
| #include "mojo/public/cpp/bindings/error_handler.h"
|
| -#include "mojo/public/cpp/bindings/remote_ptr.h"
|
| +#include "mojo/public/cpp/bindings/interface_ptr.h"
|
| #include "mojo/public/cpp/system/core.h"
|
| #include "mojo/public/interfaces/shell/shell.mojom.h"
|
|
|
| @@ -19,11 +22,9 @@
|
| // class FooImpl : public Foo {
|
| // public:
|
| // FooImpl();
|
| -// void Initialize(ServiceConnector<FooImpl>* service_connector,
|
| -// ScopedMessagePipeHandle client_handle
|
| +// void Initialize();
|
| // private:
|
| // ServiceConnector<FooImpl>* service_connector_;
|
| -// RemotePtr<FooPeer> client_;
|
| // };
|
| //
|
| //
|
| @@ -66,8 +67,8 @@ class ServiceConnectorBase {
|
| public:
|
| class Owner : public ShellClient {
|
| public:
|
| - Owner(ScopedShellHandle shell_handle);
|
| - ~Owner();
|
| + Owner(ScopedMessagePipeHandle shell_handle);
|
| + virtual ~Owner();
|
| Shell* shell() { return shell_.get(); }
|
| virtual void AddServiceConnector(
|
| internal::ServiceConnectorBase* service_connector) = 0;
|
| @@ -79,7 +80,7 @@ class ServiceConnectorBase {
|
| Owner* owner) {
|
| service_connector->owner_ = owner;
|
| }
|
| - RemotePtr<Shell> shell_;
|
| + ShellPtr shell_;
|
| };
|
| ServiceConnectorBase() : owner_(NULL) {}
|
| virtual ~ServiceConnectorBase();
|
| @@ -92,33 +93,35 @@ class ServiceConnectorBase {
|
| };
|
| } // namespace internal
|
|
|
| -template <class ServiceImpl, typename Context=void>
|
| +template <class ConnectionImpl, typename Context=void>
|
| class ServiceConnector : public internal::ServiceConnectorBase {
|
| public:
|
| + typedef typename ConnectionImpl::Interface Interface;
|
| +
|
| ServiceConnector(Context* context = NULL) : context_(context) {}
|
|
|
| virtual ~ServiceConnector() {
|
| - for (typename ServiceList::iterator it = services_.begin();
|
| - it != services_.end(); ++it) {
|
| + ConnectionList doomed;
|
| + doomed.swap(connections_);
|
| + for (typename ConnectionList::iterator it = doomed.begin();
|
| + it != doomed.end(); ++it) {
|
| delete *it;
|
| }
|
| + assert(connections_.empty()); // No one should have added more!
|
| }
|
|
|
| virtual void AcceptConnection(const std::string& url,
|
| - ScopedMessagePipeHandle client_handle)
|
| - MOJO_OVERRIDE {
|
| - ServiceImpl* service = new ServiceImpl();
|
| - service->Initialize(this, client_handle.Pass());
|
| - services_.push_back(service);
|
| + ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
|
| + connections_.push_back(new ConnectionWrapper(this, handle.Pass()));
|
| }
|
|
|
| - void RemoveService(ServiceImpl* service) {
|
| - for (typename ServiceList::iterator it = services_.begin();
|
| - it != services_.end(); ++it) {
|
| - if (*it == service) {
|
| - services_.erase(it);
|
| - delete service;
|
| - if (services_.empty())
|
| + void RemoveConnection(Interface* impl) {
|
| + for (typename ConnectionList::iterator it = connections_.begin();
|
| + it != connections_.end(); ++it) {
|
| + if ((*it)->get() == impl) {
|
| + delete *it;
|
| + connections_.erase(it);
|
| + if (connections_.empty())
|
| owner_->RemoveServiceConnector(this);
|
| return;
|
| }
|
| @@ -128,8 +131,34 @@ class ServiceConnector : public internal::ServiceConnectorBase {
|
| Context* context() const { return context_; }
|
|
|
| private:
|
| - typedef std::vector<ServiceImpl*> ServiceList;
|
| - ServiceList services_;
|
| + class ConnectionWrapper : public ErrorHandler {
|
| + public:
|
| + ConnectionWrapper(ServiceConnector<ConnectionImpl, Context>* connector,
|
| + ScopedMessagePipeHandle handle)
|
| + : connector_(connector) {
|
| + ConnectionImpl* impl = new ConnectionImpl();
|
| + impl->set_connector(connector_);
|
| +
|
| + ptr_.Bind(impl);
|
| + ptr_.ConfigureStub(handle.Pass());
|
| + ptr_.set_error_handler(this);
|
| +
|
| + impl->Initialize();
|
| + }
|
| +
|
| + Interface* get() { return ptr_.get(); }
|
| +
|
| + private:
|
| + virtual void OnError() MOJO_OVERRIDE {
|
| + connector_->RemoveConnection(ptr_.get());
|
| + }
|
| +
|
| + InterfacePtr<Interface> ptr_;
|
| + ServiceConnector<ConnectionImpl, Context>* connector_;
|
| + };
|
| +
|
| + typedef std::vector<ConnectionWrapper*> ConnectionList;
|
| + ConnectionList connections_;
|
| Context* context_;
|
| };
|
|
|
| @@ -137,49 +166,47 @@ class ServiceConnector : public internal::ServiceConnectorBase {
|
| // ServiceInterface: Service interface.
|
| // ServiceImpl: Implementation of Service interface.
|
| // Context: Optional type of shared context.
|
| -template <class ServiceInterface, class ServiceImpl, typename Context=void>
|
| +template <class ServiceInterface, class ConnectionImpl, typename Context=void>
|
| class ServiceConnection : public ServiceInterface {
|
| public:
|
| + typedef ServiceInterface Interface;
|
| +
|
| virtual ~ServiceConnection() {}
|
|
|
| protected:
|
| - ServiceConnection() : reaper_(this), service_connector_(NULL) {}
|
| -
|
| - void Initialize(ServiceConnector<ServiceImpl, Context>* service_connector,
|
| - ScopedMessagePipeHandle client_handle) {
|
| - service_connector_ = service_connector;
|
| - client_.reset(
|
| - MakeScopedHandle(
|
| - InterfaceHandle<typename ServiceInterface::_Peer>(
|
| - client_handle.release().value())).Pass(),
|
| - this,
|
| - &reaper_);
|
| + ServiceConnection() : service_connector_(NULL) {}
|
| +
|
| + // Shadow this method in ConnectionImpl to perform one-time initialization.
|
| + // At the time this is called, shell() and context() will be available.
|
| + // NOTE: Do not call the base class Initialize. It will always be a no-op.
|
| + void Initialize() {}
|
| +
|
| + Shell* shell() {
|
| + return service_connector_->shell();
|
| }
|
|
|
| - Shell* shell() { return service_connector_->shell(); }
|
| - Context* context() const { return service_connector_->context(); }
|
| - typename ServiceInterface::_Peer* client() { return client_.get(); }
|
| + Context* context() const {
|
| + return service_connector_->context();
|
| + }
|
|
|
| private:
|
| - // The Reaper class allows us to handle errors on the client proxy without
|
| - // polluting the name space of the ServiceConnection<> class.
|
| - class Reaper : public ErrorHandler {
|
| - public:
|
| - Reaper(ServiceConnection<ServiceInterface, ServiceImpl, Context>* service)
|
| - : service_(service) {}
|
| - virtual void OnError() {
|
| - service_->service_connector_->RemoveService(
|
| - static_cast<ServiceImpl*>(service_));
|
| - }
|
| - private:
|
| - ServiceConnection<ServiceInterface, ServiceImpl, Context>* service_;
|
| - };
|
| - friend class ServiceConnector<ServiceImpl, Context>;
|
| - Reaper reaper_;
|
| - ServiceConnector<ServiceImpl, Context>* service_connector_;
|
| - RemotePtr<typename ServiceInterface::_Peer> client_;
|
| + friend class ServiceConnector<ConnectionImpl, Context>;
|
| + void set_connector(ServiceConnector<ConnectionImpl, Context>* connector) {
|
| + service_connector_ = connector;
|
| + }
|
| + ServiceConnector<ConnectionImpl, Context>* service_connector_;
|
| };
|
|
|
| +template <typename Interface>
|
| +inline void ConnectTo(Shell* shell, const std::string& url,
|
| + InterfacePtr<Interface>* ptr) {
|
| + MessagePipe pipe;
|
| + *ptr = MakeProxy<Interface>(pipe.handle0.Pass());
|
| +
|
| + AllocationScope scope;
|
| + shell->Connect(url, pipe.handle1.Pass());
|
| +}
|
| +
|
| } // namespace mojo
|
|
|
| #endif // MOJO_PUBLIC_SHELL_SERVICE_H_
|
|
|