Index: third_party/mojo/src/mojo/public/dart/lib/src/proxy.dart |
diff --git a/third_party/mojo/src/mojo/public/dart/src/proxy.dart b/third_party/mojo/src/mojo/public/dart/lib/src/proxy.dart |
similarity index 55% |
rename from third_party/mojo/src/mojo/public/dart/src/proxy.dart |
rename to third_party/mojo/src/mojo/public/dart/lib/src/proxy.dart |
index 863e734d8df5f301078154f2c01cf4312f9ffa49..528e13a1d9c55b9a00bfeb9ddd31bdb7a22c605c 100644 |
--- a/third_party/mojo/src/mojo/public/dart/src/proxy.dart |
+++ b/third_party/mojo/src/mojo/public/dart/lib/src/proxy.dart |
@@ -13,6 +13,10 @@ class ProxyCloseException { |
abstract class Proxy extends core.MojoEventStreamListener { |
Map<int, Completer> _completerMap; |
int _nextId = 0; |
+ int _version = 0; |
+ /// Version of this interface that the remote side supports. Updated when a |
+ /// call to [queryVersion] or [requireVersion] is made. |
+ int get version => _version; |
Proxy.fromEndpoint(core.MojoMessagePipeEndpoint endpoint) |
: _completerMap = {}, |
@@ -39,6 +43,10 @@ abstract class Proxy extends core.MojoEventStreamListener { |
result = endpoint.read(bytes, result.bytesRead, handles); |
assert(result.status.isOk || result.status.isResourceExhausted); |
var message = new ServiceMessage.fromMessage(new Message(bytes, handles)); |
+ if (ControlMessageHandler.isControlMessage(message)) { |
+ _handleControlMessageResponse(message); |
+ return; |
+ } |
handleResponse(message); |
} |
@@ -96,6 +104,63 @@ abstract class Proxy extends core.MojoEventStreamListener { |
var superString = super.toString(); |
return "Proxy(${superString})"; |
} |
+ |
+ /// Queries the max version that the remote side supports. |
+ /// Updates [version]. |
+ Future<int> queryVersion() async { |
+ var params = new icm.RunMessageParams(); |
+ params.reserved0 = 16; |
+ params.reserved1 = 0; |
+ params.queryVersion = new icm.QueryVersion(); |
+ var response = await |
+ sendMessageWithRequestId(params, |
+ icm.kRunMessageId, |
+ -1, |
+ MessageHeader.kMessageExpectsResponse); |
+ _version = response.queryVersionResult.version; |
+ return _version; |
+ } |
+ |
+ /// If the remote side doesn't support the [requiredVersion], it will close |
+ /// its end of the message pipe asynchronously. This does nothing if it's |
+ /// already known that the remote side supports [requiredVersion]. |
+ /// Updates [version]. |
+ void requireVersion(int requiredVersion) { |
+ if (requiredVersion <= _version) { |
+ // Already supported. |
+ return; |
+ } |
+ |
+ // If the remote end doesn't close the pipe, we know that it supports |
+ // required version. |
+ _version = requiredVersion; |
+ |
+ var params = new icm.RunOrClosePipeMessageParams(); |
+ params.reserved0 = 16; |
+ params.reserved1 = 0; |
+ params.requireVersion = new icm.RequireVersion(); |
+ params.requireVersion.version = requiredVersion; |
+ // TODO(johnmccutchan): We've set _version above but if this sendMessage |
+ // throws an exception we may not have sent the RunOrClose message. Should |
+ // we reset _version in that case? |
+ sendMessage(params, icm.kRunOrClosePipeMessageId); |
+ } |
+ |
+ _handleControlMessageResponse(ServiceMessage message) { |
+ // We only expect to see Run messages. |
+ assert(message.header.type == icm.kRunMessageId); |
+ var response = icm.RunResponseMessageParams.deserialize(message.payload); |
+ if (!message.header.hasRequestId) { |
+ throw 'Expected a message with a valid request Id.'; |
+ } |
+ Completer c = completerMap[message.header.requestId]; |
+ if (c == null) { |
+ throw 'Message had unknown request Id: ${message.header.requestId}'; |
+ } |
+ completerMap.remove(message.header.requestId); |
+ assert(!c.isCompleted); |
+ c.complete(response); |
+ } |
} |
// Generated Proxy classes implement this interface. |