service_connector.h revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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
15namespace mojo {
16namespace internal {
17
18template <class ServiceImpl, typename Context>
19class ServiceConnector;
20
21// Specialization of ServiceConnection.
22// ServiceImpl: Subclass of InterfaceImpl<...>.
23// Context: Type of shared context.
24template <class ServiceImpl, typename Context>
25class 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
35private:
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
49template <typename ServiceImpl, typename Context>
50struct ServiceConstructor {
51  static ServiceConnection<ServiceImpl, Context>* New(Context* context) {
52    return new ServiceConnection<ServiceImpl, Context>(context);
53  }
54};
55
56template <typename ServiceImpl>
57struct ServiceConstructor<ServiceImpl, void> {
58 public:
59  static ServiceConnection<ServiceImpl, void>* New(void* context) {
60    return new ServiceConnection<ServiceImpl, void>();
61  }
62};
63
64class 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
81template <class ServiceImpl, typename Context=void>
82class 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