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_ |