• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ServiceConnection()27   ServiceConnection() : ServiceImpl() {}
ServiceConnection(Context * context)28   ServiceConnection(Context* context) : ServiceImpl(context) {}
29 
OnConnectionError()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.
set_service_connector(ServiceConnector<ServiceImpl,Context> * connector)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 {
NewServiceConstructor51   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