service_connector.h revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/interfaces/service_provider/service_provider.mojom.h"
13
14namespace mojo {
15namespace internal {
16
17template <class ServiceImpl, typename Context>
18class ServiceConnector;
19
20// Specialization of ServiceConnection.
21// ServiceImpl: Subclass of InterfaceImpl<...>.
22// Context: Type of shared context.
23template <class ServiceImpl, typename Context>
24class ServiceConnection : public ServiceImpl {
25 public:
26  ServiceConnection() : ServiceImpl() {}
27  ServiceConnection(Context* context) : ServiceImpl(context) {}
28
29  virtual void OnConnectionError() MOJO_OVERRIDE {
30    service_connector_->RemoveConnection(static_cast<ServiceImpl*>(this));
31    ServiceImpl::OnConnectionError();
32  }
33
34private:
35  friend class ServiceConnector<ServiceImpl, Context>;
36
37  // Called shortly after this class is instantiated.
38  void set_service_connector(
39      ServiceConnector<ServiceImpl, Context>* connector) {
40    service_connector_ = connector;
41  }
42
43  ServiceConnector<ServiceImpl, Context>* service_connector_;
44};
45
46template <typename ServiceImpl, typename Context>
47struct ServiceConstructor {
48  static ServiceConnection<ServiceImpl, Context>* New(Context* context) {
49    return new ServiceConnection<ServiceImpl, Context>(context);
50  }
51};
52
53template <typename ServiceImpl>
54struct ServiceConstructor<ServiceImpl, void> {
55 public:
56  static ServiceConnection<ServiceImpl, void>* New(void* context) {
57    return new ServiceConnection<ServiceImpl, void>();
58  }
59};
60
61class ServiceConnectorBase {
62 public:
63  class Owner : public ServiceProvider {
64   public:
65    Owner();
66    Owner(ScopedMessagePipeHandle service_provider_handle);
67    virtual ~Owner();
68    virtual void AddServiceConnector(
69        internal::ServiceConnectorBase* service_connector) = 0;
70    virtual void RemoveServiceConnector(
71        internal::ServiceConnectorBase* service_connector) = 0;
72
73   protected:
74    void set_service_connector_owner(ServiceConnectorBase* service_connector,
75                                     Owner* owner) {
76      service_connector->owner_ = owner;
77    }
78    ServiceProviderPtr service_provider_;
79  };
80  ServiceConnectorBase() : owner_(NULL) {}
81  virtual ~ServiceConnectorBase();
82  virtual void ConnectToService(const std::string& url,
83                                ScopedMessagePipeHandle client_handle) = 0;
84
85 protected:
86  Owner* owner_;
87};
88
89template <class ServiceImpl, typename Context=void>
90class ServiceConnector : public internal::ServiceConnectorBase {
91 public:
92  ServiceConnector(Context* context = NULL) : context_(context) {}
93
94  virtual ~ServiceConnector() {
95    ConnectionList doomed;
96    doomed.swap(connections_);
97    for (typename ConnectionList::iterator it = doomed.begin();
98         it != doomed.end(); ++it) {
99      delete *it;
100    }
101    assert(connections_.empty());  // No one should have added more!
102  }
103
104  virtual void ConnectToService(const std::string& url,
105                                ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
106    ServiceConnection<ServiceImpl, Context>* impl =
107        ServiceConstructor<ServiceImpl, Context>::New(context_);
108    impl->set_service_connector(this);
109    BindToPipe(impl, handle.Pass());
110
111    connections_.push_back(impl);
112  }
113
114  void RemoveConnection(ServiceImpl* impl) {
115    // Called from ~ServiceImpl, in response to a connection error.
116    for (typename ConnectionList::iterator it = connections_.begin();
117         it != connections_.end(); ++it) {
118      if (*it == impl) {
119        delete impl;
120        connections_.erase(it);
121        if (connections_.empty())
122          owner_->RemoveServiceConnector(this);
123        return;
124      }
125    }
126  }
127
128  Context* context() const { return context_; }
129
130 private:
131  typedef std::vector<ServiceImpl*> ConnectionList;
132  ConnectionList connections_;
133  Context* context_;
134};
135
136}  // namespace internal
137}  // namespace mojo
138
139#endif  // MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_
140