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

Side by Side Diff: mojo/public/dart/mojo/lib/src/proxy.dart

Issue 1441033002: Move mojo and mojom from mojo/public/dart to mojo/dart/packages (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 1 month 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
OLDNEW
(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 part of bindings;
6
7 class ProxyError {
8 final String message;
9 ProxyError(this.message);
10 String toString() => "ProxyError: $message";
11 }
12
13 abstract class Proxy extends core.MojoEventHandler {
14 Map<int, Completer> _completerMap = {};
15 Completer _errorCompleter = new Completer();
16 Set<Completer> _errorCompleters;
17 int _nextId = 0;
18 int _version = 0;
19 int _pendingCount = 0;
20
21 Proxy.fromEndpoint(core.MojoMessagePipeEndpoint endpoint)
22 : super.fromEndpoint(endpoint);
23
24 Proxy.fromHandle(core.MojoHandle handle) : super.fromHandle(handle);
25
26 Proxy.unbound() : super.unbound();
27
28 void handleResponse(ServiceMessage reader);
29
30 /// If there is an error in using this proxy, this future completes with
31 /// a ProxyError.
32 Future get errorFuture => _errorCompleter.future;
33
34 /// Version of this interface that the remote side supports. Updated when a
35 /// call to [queryVersion] or [requireVersion] is made.
36 int get version => _version;
37
38 void handleRead() {
39 var result = endpoint.queryAndRead();
40 if ((result.data == null) || (result.dataLength == 0)) {
41 proxyError("Read from message pipe endpoint failed");
42 return;
43 }
44 try {
45 var message = new ServiceMessage.fromMessage(new Message(result.data,
46 result.handles, result.dataLength, result.handlesLength));
47 _pendingCount--;
48 if (ControlMessageHandler.isControlMessage(message)) {
49 _handleControlMessageResponse(message);
50 return;
51 }
52 handleResponse(message);
53 } on MojoCodecError catch (e) {
54 proxyError(e.toString());
55 close(immediate: true);
56 }
57 }
58
59 void handleWrite() {
60 proxyError("Unexpected writable signal");
61 }
62
63 @override
64 Future close({bool immediate: false}) {
65 // Drop the completers for outstanding calls. The Futures will never
66 // complete.
67 _completerMap.clear();
68
69 // Signal to any pending calls that the Proxy is closed.
70 if (_pendingCount > 0) {
71 proxyError("The Proxy is closed.");
72 }
73
74 return super.close(immediate: immediate);
75 }
76
77 void sendMessage(Struct message, int name) {
78 if (!isBound) {
79 proxyError("The Proxy is closed.");
80 return;
81 }
82 if (!isOpen) {
83 beginHandlingEvents();
84 }
85 var header = new MessageHeader(name);
86 var serviceMessage = message.serializeWithHeader(header);
87 endpoint.write(serviceMessage.buffer, serviceMessage.buffer.lengthInBytes,
88 serviceMessage.handles);
89 if (!endpoint.status.isOk) {
90 proxyError("Write to message pipe endpoint failed.");
91 }
92 }
93
94 Future sendMessageWithRequestId(Struct message, int name, int id, int flags) {
95 var completer = new Completer();
96 if (!isBound) {
97 proxyError("The Proxy is closed.");
98 return completer.future;
99 }
100 if (!isOpen) {
101 beginHandlingEvents();
102 }
103 if (id == -1) {
104 id = _nextId++;
105 }
106
107 var header = new MessageHeader.withRequestId(name, flags, id);
108 var serviceMessage = message.serializeWithHeader(header);
109 endpoint.write(serviceMessage.buffer, serviceMessage.buffer.lengthInBytes,
110 serviceMessage.handles);
111
112 if (endpoint.status.isOk) {
113 _completerMap[id] = completer;
114 _pendingCount++;
115 } else {
116 proxyError("Write to message pipe endpoint failed.");
117 }
118 return completer.future;
119 }
120
121 // Need a getter for this for access in subclasses.
122 Map<int, Completer> get completerMap => _completerMap;
123
124 String toString() {
125 var superString = super.toString();
126 return "Proxy(${superString})";
127 }
128
129 /// Queries the max version that the remote side supports.
130 /// Updates [version].
131 Future<int> queryVersion() async {
132 var params = new icm.RunMessageParams();
133 params.reserved0 = 16;
134 params.reserved1 = 0;
135 params.queryVersion = new icm.QueryVersion();
136 var response = await sendMessageWithRequestId(
137 params, icm.kRunMessageId, -1, MessageHeader.kMessageExpectsResponse);
138 _version = response.queryVersionResult.version;
139 return _version;
140 }
141
142 /// If the remote side doesn't support the [requiredVersion], it will close
143 /// its end of the message pipe asynchronously. This does nothing if it's
144 /// already known that the remote side supports [requiredVersion].
145 /// Updates [version].
146 void requireVersion(int requiredVersion) {
147 if (requiredVersion <= _version) {
148 // Already supported.
149 return;
150 }
151
152 // If the remote end doesn't close the pipe, we know that it supports
153 // required version.
154 _version = requiredVersion;
155
156 var params = new icm.RunOrClosePipeMessageParams();
157 params.reserved0 = 16;
158 params.reserved1 = 0;
159 params.requireVersion = new icm.RequireVersion();
160 params.requireVersion.version = requiredVersion;
161 // TODO(johnmccutchan): We've set _version above but if this sendMessage
162 // fails we may not have sent the RunOrClose message. Should
163 // we reset _version in that case?
164 sendMessage(params, icm.kRunOrClosePipeMessageId);
165 }
166
167 void proxyError(String msg) {
168 if (!_errorCompleter.isCompleted) {
169 errorFuture.whenComplete(() {
170 _errorCompleter = new Completer();
171 });
172 _errorCompleter.complete(new ProxyError(msg));
173 }
174 }
175
176 /// [responseOrError] returns a [Future] that completes to whatever [f]
177 /// completes to unless [errorFuture] completes first. When [errorFuture]
178 /// completes first, the [Future] returned by [responseOrError] completes with
179 /// an error using the object that [errorFuture] completed with.
180 ///
181 /// Example usage:
182 ///
183 /// try {
184 /// result = await MyProxy.responseOrError(MyProxy.ptr.call(a,b,c));
185 /// } catch (e) {
186 /// ...
187 /// }
188 Future responseOrError(Future f) {
189 assert(f != null);
190 if (_errorCompleters == null) {
191 _errorCompleters = new Set<Completer>();
192 errorFuture.then((e) {
193 for (var completer in _errorCompleters) {
194 assert(!completer.isCompleted);
195 completer.completeError(e);
196 }
197 _errorCompleters.clear();
198 _errorCompleters = null;
199 });
200 }
201
202 Completer callCompleter = new Completer();
203 f.then((callResult) {
204 if (!callCompleter.isCompleted) {
205 _errorCompleters.remove(callCompleter);
206 callCompleter.complete(callResult);
207 }
208 });
209 _errorCompleters.add(callCompleter);
210 return callCompleter.future;
211 }
212
213 _handleControlMessageResponse(ServiceMessage message) {
214 // We only expect to see Run messages.
215 if (message.header.type != icm.kRunMessageId) {
216 proxyError("Unexpected header type in control message response: "
217 "${message.header.type}");
218 return;
219 }
220
221 var response = icm.RunResponseMessageParams.deserialize(message.payload);
222 if (!message.header.hasRequestId) {
223 proxyError("Expected a message with a valid request Id.");
224 return;
225 }
226 Completer c = completerMap[message.header.requestId];
227 if (c == null) {
228 proxyError("Message had unknown request Id: ${message.header.requestId}");
229 return;
230 }
231 completerMap.remove(message.header.requestId);
232 if (c.isCompleted) {
233 proxyError("Control message response completer already completed");
234 return;
235 }
236 c.complete(response);
237 }
238 }
239
240 // Generated Proxy classes implement this interface.
241 abstract class ProxyBase {
242 final Proxy impl = null;
243 final String name = null;
244 }
245
246 abstract class ServiceConnector {
247 void connectToService(String url, ProxyBase proxy);
248 }
OLDNEW
« no previous file with comments | « mojo/public/dart/mojo/lib/src/message_pipe.dart ('k') | mojo/public/dart/mojo/lib/src/struct.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698