Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: mojo/public/cpp/shell/service.h

Issue 265793015: Mojo: Replace RemotePtr with InterfacePtr and InterfaceImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Force InterfaceImpl subclasses to implement OnConnectionError Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MOJO_PUBLIC_SHELL_SERVICE_H_ 5 #ifndef MOJO_PUBLIC_SHELL_SERVICE_H_
6 #define MOJO_PUBLIC_SHELL_SERVICE_H_ 6 #define MOJO_PUBLIC_SHELL_SERVICE_H_
7 7
8 #include <assert.h>
9
8 #include <vector> 10 #include <vector>
9 11
10 #include "mojo/public/cpp/bindings/error_handler.h" 12 #include "mojo/public/cpp/bindings/allocation_scope.h"
11 #include "mojo/public/cpp/bindings/remote_ptr.h"
12 #include "mojo/public/cpp/system/core.h"
13 #include "mojo/public/interfaces/shell/shell.mojom.h" 13 #include "mojo/public/interfaces/shell/shell.mojom.h"
14 14
15 // Utility classes for creating ShellClients that vend service instances. 15 // Utility classes for creating ShellClients that vend service instances.
16 // To use define a class that implements your specific server api, e.g. FooImpl 16 // To use define a class that implements your specific server api, e.g. FooImpl
17 // to implement a service named Foo. That class must define an empty constructor 17 // to implement a service named Foo. That class must define an empty constructor
18 // and the Initialize() method. 18 // and the Initialize() method.
19 // class FooImpl : public Foo { 19 // class FooImpl : public Foo {
20 // public: 20 // public:
21 // FooImpl(); 21 // FooImpl();
22 // void Initialize(ServiceConnector<FooImpl>* service_connector, 22 // void Initialize();
23 // ScopedMessagePipeHandle client_handle
24 // private: 23 // private:
25 // ServiceConnector<FooImpl>* service_connector_; 24 // ServiceConnector<FooImpl>* service_connector_;
26 // RemotePtr<FooPeer> client_;
27 // }; 25 // };
28 // 26 //
29 // 27 //
30 // To simplify further FooImpl can use the ServiceConnection<> template. 28 // To simplify further FooImpl can use the ServiceConnection<> template.
31 // class FooImpl : public ServiceConnection<Foo, FooImpl> { 29 // class FooImpl : public ServiceConnection<Foo, FooImpl> {
32 // public: 30 // public:
33 // FooImpl(); 31 // FooImpl();
34 // ... 32 // ...
35 // <Foo implementation> 33 // <Foo implementation>
36 // }; 34 // };
(...skipping 22 matching lines...) Expand all
59 // Context: Optional type of shared context.v 57 // Context: Optional type of shared context.v
60 // 58 //
61 // 59 //
62 namespace mojo { 60 namespace mojo {
63 61
64 namespace internal { 62 namespace internal {
65 class ServiceConnectorBase { 63 class ServiceConnectorBase {
66 public: 64 public:
67 class Owner : public ShellClient { 65 class Owner : public ShellClient {
68 public: 66 public:
69 Owner(ScopedShellHandle shell_handle); 67 Owner(ScopedMessagePipeHandle shell_handle);
70 ~Owner(); 68 virtual ~Owner();
71 Shell* shell() { return shell_.get(); } 69 Shell* shell() { return shell_.get(); }
72 virtual void AddServiceConnector( 70 virtual void AddServiceConnector(
73 internal::ServiceConnectorBase* service_connector) = 0; 71 internal::ServiceConnectorBase* service_connector) = 0;
74 virtual void RemoveServiceConnector( 72 virtual void RemoveServiceConnector(
75 internal::ServiceConnectorBase* service_connector) = 0; 73 internal::ServiceConnectorBase* service_connector) = 0;
76 74
77 protected: 75 protected:
78 void set_service_connector_owner(ServiceConnectorBase* service_connector, 76 void set_service_connector_owner(ServiceConnectorBase* service_connector,
79 Owner* owner) { 77 Owner* owner) {
80 service_connector->owner_ = owner; 78 service_connector->owner_ = owner;
81 } 79 }
82 RemotePtr<Shell> shell_; 80 ShellPtr shell_;
83 }; 81 };
84 ServiceConnectorBase() : owner_(NULL) {} 82 ServiceConnectorBase() : owner_(NULL) {}
85 virtual ~ServiceConnectorBase(); 83 virtual ~ServiceConnectorBase();
86 Shell* shell() { return owner_->shell(); } 84 Shell* shell() { return owner_->shell(); }
87 virtual void AcceptConnection(const std::string& url, 85 virtual void AcceptConnection(const std::string& url,
88 ScopedMessagePipeHandle client_handle) = 0; 86 ScopedMessagePipeHandle client_handle) = 0;
89 87
90 protected: 88 protected:
91 Owner* owner_; 89 Owner* owner_;
92 }; 90 };
93 } // namespace internal 91 } // namespace internal
94 92
95 template <class ServiceImpl, typename Context=void> 93 template <class ServiceImpl, typename Context=void>
96 class ServiceConnector : public internal::ServiceConnectorBase { 94 class ServiceConnector : public internal::ServiceConnectorBase {
97 public: 95 public:
96 typedef typename ServiceImpl::Interface Interface;
97
98 ServiceConnector(Context* context = NULL) : context_(context) {} 98 ServiceConnector(Context* context = NULL) : context_(context) {}
99 99
100 virtual ~ServiceConnector() { 100 virtual ~ServiceConnector() {
101 for (typename ServiceList::iterator it = services_.begin(); 101 ConnectionList doomed;
102 it != services_.end(); ++it) { 102 doomed.swap(connections_);
103 for (typename ConnectionList::iterator it = doomed.begin();
104 it != doomed.end(); ++it) {
103 delete *it; 105 delete *it;
104 } 106 }
107 assert(connections_.empty()); // No one should have added more!
105 } 108 }
106 109
107 virtual void AcceptConnection(const std::string& url, 110 virtual void AcceptConnection(const std::string& url,
108 ScopedMessagePipeHandle client_handle) 111 ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
109 MOJO_OVERRIDE { 112 ServiceImpl* impl = BindToPipe(new ServiceImpl(), handle.Pass());
110 ServiceImpl* service = new ServiceImpl(); 113 impl->set_connector(this);
111 service->Initialize(this, client_handle.Pass()); 114
112 services_.push_back(service); 115 connections_.push_back(impl);
116
117 impl->Initialize();
113 } 118 }
114 119
115 void RemoveService(ServiceImpl* service) { 120 void RemoveConnection(ServiceImpl* impl) {
116 for (typename ServiceList::iterator it = services_.begin(); 121 // Called from ~ServiceImpl, in response to a connection error.
117 it != services_.end(); ++it) { 122 for (typename ConnectionList::iterator it = connections_.begin();
118 if (*it == service) { 123 it != connections_.end(); ++it) {
119 services_.erase(it); 124 if (*it == impl) {
120 delete service; 125 connections_.erase(it);
121 if (services_.empty()) 126 if (connections_.empty())
122 owner_->RemoveServiceConnector(this); 127 owner_->RemoveServiceConnector(this);
123 return; 128 return;
124 } 129 }
125 } 130 }
126 } 131 }
127 132
128 Context* context() const { return context_; } 133 Context* context() const { return context_; }
129 134
130 private: 135 private:
131 typedef std::vector<ServiceImpl*> ServiceList; 136 typedef std::vector<ServiceImpl*> ConnectionList;
132 ServiceList services_; 137 ConnectionList connections_;
133 Context* context_; 138 Context* context_;
134 }; 139 };
135 140
136 // Specialization of ServiceConnection. 141 // Specialization of ServiceConnection.
137 // ServiceInterface: Service interface. 142 // ServiceInterface: Service interface.
138 // ServiceImpl: Implementation of Service interface. 143 // ServiceImpl: Subclass of ServiceConnection<...>.
139 // Context: Optional type of shared context. 144 // Context: Optional type of shared context.
140 template <class ServiceInterface, class ServiceImpl, typename Context=void> 145 template <class ServiceInterface, class ServiceImpl, typename Context=void>
141 class ServiceConnection : public ServiceInterface { 146 class ServiceConnection : public InterfaceImpl<ServiceInterface> {
142 public: 147 public:
143 virtual ~ServiceConnection() {} 148 typedef ServiceInterface Interface;
DaveMoore 2014/05/08 18:27:30 What uses this?
144 149
145 protected: 150 protected:
146 ServiceConnection() : reaper_(this), service_connector_(NULL) {} 151 // NOTE: shell() and context() are not available at construction time.
152 // Initialize() will be called once those are available.
153 ServiceConnection() : service_connector_(NULL) {}
147 154
148 void Initialize(ServiceConnector<ServiceImpl, Context>* service_connector, 155 virtual ~ServiceConnection() {
149 ScopedMessagePipeHandle client_handle) { 156 service_connector_->RemoveConnection(static_cast<ServiceImpl*>(this));
150 service_connector_ = service_connector;
151 client_.reset(
152 MakeScopedHandle(
153 InterfaceHandle<typename ServiceInterface::_Peer>(
154 client_handle.release().value())).Pass(),
155 this,
156 &reaper_);
157 } 157 }
158 158
159 Shell* shell() { return service_connector_->shell(); } 159 virtual void OnConnectionError() MOJO_OVERRIDE {
160 Context* context() const { return service_connector_->context(); } 160 delete this;
DaveMoore 2014/05/08 18:27:30 I prefer the model where the delete always happens
161 typename ServiceInterface::_Peer* client() { return client_.get(); } 161 }
162
163 // Shadow this method in ServiceImpl to perform one-time initialization.
164 // At the time this is called, shell() and context() will be available.
165 // NOTE: No need to call the base class Initialize from your subclass. It
166 // will always be a no-op.
167 void Initialize() {}
168
169 Shell* shell() {
170 return service_connector_->shell();
171 }
172
173 Context* context() const {
174 return service_connector_->context();
175 }
162 176
163 private: 177 private:
164 // The Reaper class allows us to handle errors on the client proxy without
165 // polluting the name space of the ServiceConnection<> class.
166 class Reaper : public ErrorHandler {
167 public:
168 Reaper(ServiceConnection<ServiceInterface, ServiceImpl, Context>* service)
169 : service_(service) {}
170 virtual void OnError() {
171 service_->service_connector_->RemoveService(
172 static_cast<ServiceImpl*>(service_));
173 }
174 private:
175 ServiceConnection<ServiceInterface, ServiceImpl, Context>* service_;
176 };
177 friend class ServiceConnector<ServiceImpl, Context>; 178 friend class ServiceConnector<ServiceImpl, Context>;
178 Reaper reaper_; 179
180 // Called shortly after this class is instantiated.
181 void set_connector(ServiceConnector<ServiceImpl, Context>* connector) {
182 service_connector_ = connector;
183 }
184
179 ServiceConnector<ServiceImpl, Context>* service_connector_; 185 ServiceConnector<ServiceImpl, Context>* service_connector_;
180 RemotePtr<typename ServiceInterface::_Peer> client_;
DaveMoore 2014/05/08 18:27:30 Could we somehow preserve having the client_ store
181 }; 186 };
182 187
188 template <typename Interface>
189 inline void ConnectTo(Shell* shell, const std::string& url,
190 InterfacePtr<Interface>* ptr) {
191 MessagePipe pipe;
192 ptr->Bind(pipe.handle0.Pass());
193
194 AllocationScope scope;
195 shell->Connect(url, pipe.handle1.Pass());
196 }
197
183 } // namespace mojo 198 } // namespace mojo
184 199
185 #endif // MOJO_PUBLIC_SHELL_SERVICE_H_ 200 #endif // MOJO_PUBLIC_SHELL_SERVICE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698