Home | History | Annotate | Download | only in lib
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_
      6 #define MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_
      7 
      8 #include <assert.h>
      9 
     10 #include <vector>
     11 
     12 #include "mojo/public/cpp/application/lib/service_registry.h"
     13 #include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
     14 
     15 namespace mojo {
     16 namespace internal {
     17 
     18 template <class ServiceImpl, typename Context>
     19 class ServiceConnector;
     20 
     21 // Specialization of ServiceConnection.
     22 // ServiceImpl: Subclass of InterfaceImpl<...>.
     23 // Context: Type of shared context.
     24 template <class ServiceImpl, typename Context>
     25 class ServiceConnection : public ServiceImpl {
     26  public:
     27   ServiceConnection() : ServiceImpl() {}
     28   ServiceConnection(Context* context) : ServiceImpl(context) {}
     29 
     30   virtual void OnConnectionError() MOJO_OVERRIDE {
     31     service_connector_->RemoveConnection(static_cast<ServiceImpl*>(this));
     32     ServiceImpl::OnConnectionError();
     33   }
     34 
     35 private:
     36   friend class ServiceConnector<ServiceImpl, Context>;
     37 
     38   // Called shortly after this class is instantiated.
     39   void set_service_connector(
     40       ServiceConnector<ServiceImpl, Context>* connector) {
     41     service_connector_ = connector;
     42   }
     43 
     44   ServiceConnector<ServiceImpl, Context>* service_connector_;
     45 
     46   MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnection);
     47 };
     48 
     49 template <typename ServiceImpl, typename Context>
     50 struct ServiceConstructor {
     51   static ServiceConnection<ServiceImpl, Context>* New(Context* context) {
     52     return new ServiceConnection<ServiceImpl, Context>(context);
     53   }
     54 };
     55 
     56 template <typename ServiceImpl>
     57 struct ServiceConstructor<ServiceImpl, void> {
     58  public:
     59   static ServiceConnection<ServiceImpl, void>* New(void* context) {
     60     return new ServiceConnection<ServiceImpl, void>();
     61   }
     62 };
     63 
     64 class ServiceConnectorBase {
     65  public:
     66   ServiceConnectorBase(const std::string& name);
     67   virtual ~ServiceConnectorBase();
     68   virtual void ConnectToService(const std::string& url,
     69                                 const std::string& name,
     70                                 ScopedMessagePipeHandle client_handle) = 0;
     71   std::string name() const { return name_; }
     72   void set_registry(ServiceRegistry* registry) { registry_ = registry; }
     73 
     74  protected:
     75   std::string name_;
     76   ServiceRegistry* registry_;
     77 
     78   MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnectorBase);
     79 };
     80 
     81 template <class ServiceImpl, typename Context=void>
     82 class ServiceConnector : public internal::ServiceConnectorBase {
     83  public:
     84   ServiceConnector(const std::string& name, Context* context = NULL)
     85       : ServiceConnectorBase(name), context_(context) {}
     86 
     87   virtual ~ServiceConnector() {
     88     ConnectionList doomed;
     89     doomed.swap(connections_);
     90     for (typename ConnectionList::iterator it = doomed.begin();
     91          it != doomed.end(); ++it) {
     92       delete *it;
     93     }
     94     assert(connections_.empty());  // No one should have added more!
     95   }
     96 
     97   virtual void ConnectToService(const std::string& url,
     98                                 const std::string& name,
     99                                 ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
    100     ServiceConnection<ServiceImpl, Context>* impl =
    101         ServiceConstructor<ServiceImpl, Context>::New(context_);
    102     impl->set_service_connector(this);
    103     BindToPipe(impl, handle.Pass());
    104 
    105     connections_.push_back(impl);
    106   }
    107 
    108   void RemoveConnection(ServiceImpl* impl) {
    109     // Called from ~ServiceImpl, in response to a connection error.
    110     for (typename ConnectionList::iterator it = connections_.begin();
    111          it != connections_.end(); ++it) {
    112       if (*it == impl) {
    113         delete impl;
    114         connections_.erase(it);
    115         return;
    116       }
    117     }
    118   }
    119 
    120   Context* context() const { return context_; }
    121 
    122  private:
    123   typedef std::vector<ServiceImpl*> ConnectionList;
    124   ConnectionList connections_;
    125   Context* context_;
    126 
    127   MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnector);
    128 };
    129 
    130 }  // namespace internal
    131 }  // namespace mojo
    132 
    133 #endif  // MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_
    134