| // 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. |
| |
| #ifndef MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_ |
| #define MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_ |
| |
| #include <assert.h> |
| |
| #include <vector> |
| |
| #include "mojo/public/interfaces/service_provider/service_provider.mojom.h" |
| |
| namespace mojo { |
| class ApplicationConnection; |
| |
| namespace internal { |
| |
| template <class ServiceImpl, typename Context> |
| class ServiceConnector; |
| |
| // Specialization of ServiceConnection. |
| // ServiceImpl: Subclass of InterfaceImpl<...>. |
| // Context: Type of shared context. |
| template <class ServiceImpl, typename Context> |
| class ServiceConnection : public ServiceImpl { |
| public: |
| explicit ServiceConnection(ApplicationConnection* connection) |
| : ServiceImpl(connection) {} |
| ServiceConnection(ApplicationConnection* connection, |
| Context* context) : ServiceImpl(connection, context) {} |
| |
| virtual void OnConnectionError() MOJO_OVERRIDE { |
| service_connector_->RemoveConnection(static_cast<ServiceImpl*>(this)); |
| ServiceImpl::OnConnectionError(); |
| } |
| |
| private: |
| friend class ServiceConnector<ServiceImpl, Context>; |
| |
| // Called shortly after this class is instantiated. |
| void set_service_connector( |
| ServiceConnector<ServiceImpl, Context>* connector) { |
| service_connector_ = connector; |
| } |
| |
| ServiceConnector<ServiceImpl, Context>* service_connector_; |
| |
| MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnection); |
| }; |
| |
| template <typename ServiceImpl, typename Context> |
| struct ServiceConstructor { |
| static ServiceConnection<ServiceImpl, Context>* New( |
| ApplicationConnection* connection, |
| Context* context) { |
| return new ServiceConnection<ServiceImpl, Context>( |
| connection, context); |
| } |
| }; |
| |
| template <typename ServiceImpl> |
| struct ServiceConstructor<ServiceImpl, void> { |
| public: |
| static ServiceConnection<ServiceImpl, void>* New( |
| ApplicationConnection* connection, |
| void* context) { |
| return new ServiceConnection<ServiceImpl, void>(connection); |
| } |
| }; |
| |
| class ServiceConnectorBase { |
| public: |
| ServiceConnectorBase(const std::string& name); |
| virtual ~ServiceConnectorBase(); |
| virtual void ConnectToService(const std::string& name, |
| ScopedMessagePipeHandle client_handle) = 0; |
| std::string name() const { return name_; } |
| void set_application_connection(ApplicationConnection* connection) { |
| application_connection_ = connection; } |
| |
| protected: |
| std::string name_; |
| ApplicationConnection* application_connection_; |
| |
| MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnectorBase); |
| }; |
| |
| template <class ServiceImpl, typename Context=void> |
| class ServiceConnector : public internal::ServiceConnectorBase { |
| public: |
| ServiceConnector(const std::string& name, Context* context = NULL) |
| : ServiceConnectorBase(name), context_(context) {} |
| |
| virtual ~ServiceConnector() { |
| 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 ConnectToService(const std::string& name, |
| ScopedMessagePipeHandle handle) MOJO_OVERRIDE { |
| ServiceConnection<ServiceImpl, Context>* impl = |
| ServiceConstructor<ServiceImpl, Context>::New(application_connection_, |
| context_); |
| impl->set_service_connector(this); |
| BindToPipe(impl, handle.Pass()); |
| |
| connections_.push_back(impl); |
| } |
| |
| void RemoveConnection(ServiceImpl* impl) { |
| // Called from ~ServiceImpl, in response to a connection error. |
| for (typename ConnectionList::iterator it = connections_.begin(); |
| it != connections_.end(); ++it) { |
| if (*it == impl) { |
| delete impl; |
| connections_.erase(it); |
| return; |
| } |
| } |
| } |
| |
| Context* context() const { return context_; } |
| |
| private: |
| typedef std::vector<ServiceImpl*> ConnectionList; |
| ConnectionList connections_; |
| Context* context_; |
| |
| MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnector); |
| }; |
| |
| } // namespace internal |
| } // namespace mojo |
| |
| #endif // MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_ |