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

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: rebase 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
12 #include "mojo/public/cpp/bindings/allocation_scope.h"
10 #include "mojo/public/cpp/bindings/error_handler.h" 13 #include "mojo/public/cpp/bindings/error_handler.h"
11 #include "mojo/public/cpp/bindings/remote_ptr.h" 14 #include "mojo/public/cpp/bindings/interface_ptr.h"
12 #include "mojo/public/cpp/system/core.h" 15 #include "mojo/public/cpp/system/core.h"
13 #include "mojo/public/interfaces/shell/shell.mojom.h" 16 #include "mojo/public/interfaces/shell/shell.mojom.h"
14 17
15 // Utility classes for creating ShellClients that vend service instances. 18 // Utility classes for creating ShellClients that vend service instances.
16 // To use define a class that implements your specific server api, e.g. FooImpl 19 // 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 20 // to implement a service named Foo. That class must define an empty constructor
18 // and the Initialize() method. 21 // and the Initialize() method.
19 // class FooImpl : public Foo { 22 // class FooImpl : public Foo {
20 // public: 23 // public:
21 // FooImpl(); 24 // FooImpl();
22 // void Initialize(ServiceConnector<FooImpl>* service_connector, 25 // void Initialize();
23 // ScopedMessagePipeHandle client_handle
24 // private: 26 // private:
25 // ServiceConnector<FooImpl>* service_connector_; 27 // ServiceConnector<FooImpl>* service_connector_;
26 // RemotePtr<FooPeer> client_;
27 // }; 28 // };
28 // 29 //
29 // 30 //
30 // To simplify further FooImpl can use the ServiceConnection<> template. 31 // To simplify further FooImpl can use the ServiceConnection<> template.
31 // class FooImpl : public ServiceConnection<Foo, FooImpl> { 32 // class FooImpl : public ServiceConnection<Foo, FooImpl> {
32 // public: 33 // public:
33 // FooImpl(); 34 // FooImpl();
34 // ... 35 // ...
35 // <Foo implementation> 36 // <Foo implementation>
36 // }; 37 // };
(...skipping 22 matching lines...) Expand all
59 // Context: Optional type of shared context.v 60 // Context: Optional type of shared context.v
60 // 61 //
61 // 62 //
62 namespace mojo { 63 namespace mojo {
63 64
64 namespace internal { 65 namespace internal {
65 class ServiceConnectorBase { 66 class ServiceConnectorBase {
66 public: 67 public:
67 class Owner : public ShellClient { 68 class Owner : public ShellClient {
68 public: 69 public:
69 Owner(ScopedShellHandle shell_handle); 70 Owner(ScopedMessagePipeHandle shell_handle);
70 ~Owner(); 71 virtual ~Owner();
71 Shell* shell() { return shell_.get(); } 72 Shell* shell() { return shell_.get(); }
72 virtual void AddServiceConnector( 73 virtual void AddServiceConnector(
73 internal::ServiceConnectorBase* service_connector) = 0; 74 internal::ServiceConnectorBase* service_connector) = 0;
74 virtual void RemoveServiceConnector( 75 virtual void RemoveServiceConnector(
75 internal::ServiceConnectorBase* service_connector) = 0; 76 internal::ServiceConnectorBase* service_connector) = 0;
76 77
77 protected: 78 protected:
78 void set_service_connector_owner(ServiceConnectorBase* service_connector, 79 void set_service_connector_owner(ServiceConnectorBase* service_connector,
79 Owner* owner) { 80 Owner* owner) {
80 service_connector->owner_ = owner; 81 service_connector->owner_ = owner;
81 } 82 }
82 RemotePtr<Shell> shell_; 83 ShellPtr shell_;
83 }; 84 };
84 ServiceConnectorBase() : owner_(NULL) {} 85 ServiceConnectorBase() : owner_(NULL) {}
85 virtual ~ServiceConnectorBase(); 86 virtual ~ServiceConnectorBase();
86 Shell* shell() { return owner_->shell(); } 87 Shell* shell() { return owner_->shell(); }
87 virtual void AcceptConnection(const std::string& url, 88 virtual void AcceptConnection(const std::string& url,
88 ScopedMessagePipeHandle client_handle) = 0; 89 ScopedMessagePipeHandle client_handle) = 0;
89 90
90 protected: 91 protected:
91 Owner* owner_; 92 Owner* owner_;
92 }; 93 };
93 } // namespace internal 94 } // namespace internal
94 95
95 template <class ServiceImpl, typename Context=void> 96 template <class ConnectionImpl, typename Context=void>
96 class ServiceConnector : public internal::ServiceConnectorBase { 97 class ServiceConnector : public internal::ServiceConnectorBase {
97 public: 98 public:
99 typedef typename ConnectionImpl::Interface Interface;
100
98 ServiceConnector(Context* context = NULL) : context_(context) {} 101 ServiceConnector(Context* context = NULL) : context_(context) {}
99 102
100 virtual ~ServiceConnector() { 103 virtual ~ServiceConnector() {
101 for (typename ServiceList::iterator it = services_.begin(); 104 ConnectionList doomed;
102 it != services_.end(); ++it) { 105 doomed.swap(connections_);
106 for (typename ConnectionList::iterator it = doomed.begin();
107 it != doomed.end(); ++it) {
103 delete *it; 108 delete *it;
104 } 109 }
110 assert(connections_.empty()); // No one should have added more!
105 } 111 }
106 112
107 virtual void AcceptConnection(const std::string& url, 113 virtual void AcceptConnection(const std::string& url,
108 ScopedMessagePipeHandle client_handle) 114 ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
109 MOJO_OVERRIDE { 115 connections_.push_back(new ConnectionWrapper(this, handle.Pass()));
110 ServiceImpl* service = new ServiceImpl();
111 service->Initialize(this, client_handle.Pass());
112 services_.push_back(service);
113 } 116 }
114 117
115 void RemoveService(ServiceImpl* service) { 118 void RemoveConnection(Interface* impl) {
116 for (typename ServiceList::iterator it = services_.begin(); 119 for (typename ConnectionList::iterator it = connections_.begin();
117 it != services_.end(); ++it) { 120 it != connections_.end(); ++it) {
118 if (*it == service) { 121 if ((*it)->get() == impl) {
119 services_.erase(it); 122 delete *it;
120 delete service; 123 connections_.erase(it);
121 if (services_.empty()) 124 if (connections_.empty())
122 owner_->RemoveServiceConnector(this); 125 owner_->RemoveServiceConnector(this);
123 return; 126 return;
124 } 127 }
125 } 128 }
126 } 129 }
127 130
128 Context* context() const { return context_; } 131 Context* context() const { return context_; }
129 132
130 private: 133 private:
131 typedef std::vector<ServiceImpl*> ServiceList; 134 class ConnectionWrapper : public ErrorHandler {
132 ServiceList services_; 135 public:
136 ConnectionWrapper(ServiceConnector<ConnectionImpl, Context>* connector,
137 ScopedMessagePipeHandle handle)
138 : connector_(connector) {
139 ConnectionImpl* impl = new ConnectionImpl();
140 impl->set_connector(connector_);
141
142 ptr_.Bind(impl);
143 ptr_.ConfigureStub(handle.Pass());
144 ptr_.set_error_handler(this);
145
146 impl->Initialize();
147 }
148
149 Interface* get() { return ptr_.get(); }
150
151 private:
152 virtual void OnError() MOJO_OVERRIDE {
153 connector_->RemoveConnection(ptr_.get());
154 }
155
156 InterfacePtr<Interface> ptr_;
157 ServiceConnector<ConnectionImpl, Context>* connector_;
158 };
159
160 typedef std::vector<ConnectionWrapper*> ConnectionList;
161 ConnectionList connections_;
133 Context* context_; 162 Context* context_;
134 }; 163 };
135 164
136 // Specialization of ServiceConnection. 165 // Specialization of ServiceConnection.
137 // ServiceInterface: Service interface. 166 // ServiceInterface: Service interface.
138 // ServiceImpl: Implementation of Service interface. 167 // ServiceImpl: Implementation of Service interface.
139 // Context: Optional type of shared context. 168 // Context: Optional type of shared context.
140 template <class ServiceInterface, class ServiceImpl, typename Context=void> 169 template <class ServiceInterface, class ConnectionImpl, typename Context=void>
141 class ServiceConnection : public ServiceInterface { 170 class ServiceConnection : public ServiceInterface {
142 public: 171 public:
172 typedef ServiceInterface Interface;
173
143 virtual ~ServiceConnection() {} 174 virtual ~ServiceConnection() {}
144 175
145 protected: 176 protected:
146 ServiceConnection() : reaper_(this), service_connector_(NULL) {} 177 ServiceConnection() : service_connector_(NULL) {}
147 178
148 void Initialize(ServiceConnector<ServiceImpl, Context>* service_connector, 179 // Shadow this method in ConnectionImpl to perform one-time initialization.
149 ScopedMessagePipeHandle client_handle) { 180 // At the time this is called, shell() and context() will be available.
150 service_connector_ = service_connector; 181 // NOTE: Do not call the base class Initialize. It will always be a no-op.
151 client_.reset( 182 void Initialize() {}
152 MakeScopedHandle( 183
153 InterfaceHandle<typename ServiceInterface::_Peer>( 184 Shell* shell() {
154 client_handle.release().value())).Pass(), 185 return service_connector_->shell();
155 this,
156 &reaper_);
157 } 186 }
158 187
159 Shell* shell() { return service_connector_->shell(); } 188 Context* context() const {
160 Context* context() const { return service_connector_->context(); } 189 return service_connector_->context();
161 typename ServiceInterface::_Peer* client() { return client_.get(); } 190 }
162 191
163 private: 192 private:
164 // The Reaper class allows us to handle errors on the client proxy without 193 friend class ServiceConnector<ConnectionImpl, Context>;
165 // polluting the name space of the ServiceConnection<> class. 194 void set_connector(ServiceConnector<ConnectionImpl, Context>* connector) {
166 class Reaper : public ErrorHandler { 195 service_connector_ = connector;
167 public: 196 }
168 Reaper(ServiceConnection<ServiceInterface, ServiceImpl, Context>* service) 197 ServiceConnector<ConnectionImpl, Context>* service_connector_;
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 Reaper reaper_;
179 ServiceConnector<ServiceImpl, Context>* service_connector_;
180 RemotePtr<typename ServiceInterface::_Peer> client_;
181 }; 198 };
182 199
200 template <typename Interface>
201 inline void ConnectTo(Shell* shell, const std::string& url,
202 InterfacePtr<Interface>* ptr) {
203 MessagePipe pipe;
204 *ptr = MakeProxy<Interface>(pipe.handle0.Pass());
205
206 AllocationScope scope;
207 shell->Connect(url, pipe.handle1.Pass());
208 }
209
183 } // namespace mojo 210 } // namespace mojo
184 211
185 #endif // MOJO_PUBLIC_SHELL_SERVICE_H_ 212 #endif // MOJO_PUBLIC_SHELL_SERVICE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698