OLD | NEW |
| (Empty) |
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/bindings/allocation_scope.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 | |
47 template <typename ServiceImpl, typename Context> | |
48 struct ServiceConstructor { | |
49 static ServiceConnection<ServiceImpl, Context>* New(Context* context) { | |
50 return new ServiceConnection<ServiceImpl, Context>(context); | |
51 } | |
52 }; | |
53 | |
54 template <typename ServiceImpl> | |
55 struct ServiceConstructor<ServiceImpl, void> { | |
56 public: | |
57 static ServiceConnection<ServiceImpl, void>* New(void* context) { | |
58 return new ServiceConnection<ServiceImpl, void>(); | |
59 } | |
60 }; | |
61 | |
62 class ServiceConnectorBase { | |
63 public: | |
64 class Owner : public ServiceProvider { | |
65 public: | |
66 Owner(ScopedMessagePipeHandle service_provider_handle); | |
67 virtual ~Owner(); | |
68 ServiceProvider* service_provider() { return service_provider_.get(); } | |
69 virtual void AddServiceConnector( | |
70 internal::ServiceConnectorBase* service_connector) = 0; | |
71 virtual void RemoveServiceConnector( | |
72 internal::ServiceConnectorBase* service_connector) = 0; | |
73 | |
74 protected: | |
75 void set_service_connector_owner(ServiceConnectorBase* service_connector, | |
76 Owner* owner) { | |
77 service_connector->owner_ = owner; | |
78 } | |
79 ServiceProviderPtr service_provider_; | |
80 }; | |
81 ServiceConnectorBase() : owner_(NULL) {} | |
82 virtual ~ServiceConnectorBase(); | |
83 ServiceProvider* service_provider() { return owner_->service_provider(); } | |
84 virtual void ConnectToService(const std::string& url, | |
85 ScopedMessagePipeHandle client_handle) = 0; | |
86 | |
87 protected: | |
88 Owner* owner_; | |
89 }; | |
90 | |
91 template <class ServiceImpl, typename Context=void> | |
92 class ServiceConnector : public internal::ServiceConnectorBase { | |
93 public: | |
94 ServiceConnector(Context* context = NULL) : context_(context) {} | |
95 | |
96 virtual ~ServiceConnector() { | |
97 ConnectionList doomed; | |
98 doomed.swap(connections_); | |
99 for (typename ConnectionList::iterator it = doomed.begin(); | |
100 it != doomed.end(); ++it) { | |
101 delete *it; | |
102 } | |
103 assert(connections_.empty()); // No one should have added more! | |
104 } | |
105 | |
106 virtual void ConnectToService(const std::string& url, | |
107 ScopedMessagePipeHandle handle) MOJO_OVERRIDE { | |
108 ServiceConnection<ServiceImpl, Context>* impl = | |
109 ServiceConstructor<ServiceImpl, Context>::New(context_); | |
110 impl->set_service_connector(this); | |
111 BindToPipe(impl, handle.Pass()); | |
112 | |
113 connections_.push_back(impl); | |
114 } | |
115 | |
116 void RemoveConnection(ServiceImpl* impl) { | |
117 // Called from ~ServiceImpl, in response to a connection error. | |
118 for (typename ConnectionList::iterator it = connections_.begin(); | |
119 it != connections_.end(); ++it) { | |
120 if (*it == impl) { | |
121 delete impl; | |
122 connections_.erase(it); | |
123 if (connections_.empty()) | |
124 owner_->RemoveServiceConnector(this); | |
125 return; | |
126 } | |
127 } | |
128 } | |
129 | |
130 Context* context() const { return context_; } | |
131 | |
132 private: | |
133 typedef std::vector<ServiceImpl*> ConnectionList; | |
134 ConnectionList connections_; | |
135 Context* context_; | |
136 }; | |
137 | |
138 } // namespace internal | |
139 } // namespace mojo | |
140 | |
141 #endif // MOJO_PUBLIC_CPP_APPLICATION_LIB_SERVICE_CONNECTOR_H_ | |
OLD | NEW |