Index: mojo/public/js/new_bindings/lib/interface_endpoint_client.js |
diff --git a/mojo/public/js/new_bindings/lib/interface_endpoint_client.js b/mojo/public/js/new_bindings/lib/interface_endpoint_client.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ef555298ba97f6f55d0622853e46d9447f09ca23 |
--- /dev/null |
+++ b/mojo/public/js/new_bindings/lib/interface_endpoint_client.js |
@@ -0,0 +1,221 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+(function() { |
+ var internal = mojo.internal; |
+ |
+ function InterfaceEndpointClient(interfaceEndpointHandle, receiver, |
+ interfaceVersion) { |
+ this.controller_ = null; |
+ this.encounteredError_ = false; |
+ this.handle_ = interfaceEndpointHandle; |
+ this.incomingReceiver_ = receiver; |
+ |
+ if (interfaceVersion !== undefined) { |
+ this.controlMessageHandler_ = new internal.ControlMessageHandler( |
+ interfaceVersion); |
+ } else { |
+ this.controlMessageProxy_ = new internal.ControlMessageProxy(this); |
+ } |
+ |
+ this.nextRequestID_ = 0; |
+ this.completers_ = new Map(); |
+ this.payloadValidators_ = []; |
+ this.connectionErrorHandler_ = null; |
+ |
+ if (interfaceEndpointHandle.pendingAssociation()) { |
+ interfaceEndpointHandle.setAssociationEventHandler( |
+ this.onAssociationEvent.bind(this)); |
+ } else { |
+ this.initControllerIfNecessary_(); |
+ } |
+ } |
+ |
+ InterfaceEndpointClient.prototype.initControllerIfNecessary_ = function() { |
+ if (this.controller_ || this.handle_.pendingAssociation()) { |
+ return; |
+ } |
+ |
+ this.controller_ = this.handle_.groupController().attachEndpointClient( |
+ this.handle_, this); |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.onAssociationEvent = function( |
+ associationEvent) { |
+ if (associationEvent === internal.AssociationEvent.ASSOCIATED) { |
+ this.initControllerIfNecessary_(); |
+ } else if (associationEvent === |
+ internal.AssociationEvent.PEER_CLOSED_BEFORE_ASSOCIATION) { |
+ timer.createOneShot(0, this.notifyError.bind(this, |
+ this.handle_.disconnectReason())); |
+ } |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.passHandle = function() { |
+ if (!this.handle_.isValid()) { |
+ return new internal.InterfaceEndpointHandle(); |
+ } |
+ |
+ // Used to clear the previously set callback. |
+ this.handle_.setAssociationEventHandler(undefined); |
+ |
+ if (this.controller_) { |
+ this.controller_ = null; |
+ this.handle_.groupController().detachEndpointClient(this.handle_); |
+ } |
+ var handle = this.handle_; |
+ this.handle_ = null; |
+ return handle; |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.close = function(reason) { |
+ var handle = this.passHandle(); |
+ handle.reset(reason); |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.accept = function(message) { |
+ if (message.associatedEndpointHandles.length > 0) { |
+ message.serializeAssociatedEndpointHandles( |
+ this.handle_.groupController()); |
+ } |
+ |
+ if (this.encounteredError_) { |
+ return false; |
+ } |
+ |
+ this.initControllerIfNecessary_(); |
+ return this.controller_.sendMessage(message); |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.acceptAndExpectResponse = function( |
+ message) { |
+ if (message.associatedEndpointHandles.length > 0) { |
+ message.serializeAssociatedEndpointHandles( |
+ this.handle_.groupController()); |
+ } |
+ |
+ if (this.encounteredError_) { |
+ return Promise.reject(); |
+ } |
+ |
+ this.initControllerIfNecessary_(); |
+ |
+ // Reserve 0 in case we want it to convey special meaning in the future. |
+ var requestID = this.nextRequestID_++; |
+ if (requestID === 0) |
+ requestID = this.nextRequestID_++; |
+ |
+ message.setRequestID(requestID); |
+ var result = this.controller_.sendMessage(message); |
+ if (!result) |
+ return Promise.reject(Error("Connection error")); |
+ |
+ var completer = {}; |
+ this.completers_.set(requestID, completer); |
+ return new Promise(function(resolve, reject) { |
+ completer.resolve = resolve; |
+ completer.reject = reject; |
+ }); |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.setPayloadValidators = function( |
+ payloadValidators) { |
+ this.payloadValidators_ = payloadValidators; |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.setIncomingReceiver = function(receiver) { |
+ this.incomingReceiver_ = receiver; |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.setConnectionErrorHandler = function( |
+ handler) { |
+ this.connectionErrorHandler_ = handler; |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.handleIncomingMessage = function(message, |
+ messageValidator) { |
+ var noError = internal.validationError.NONE; |
+ var err = noError; |
+ for (var i = 0; err === noError && i < this.payloadValidators_.length; ++i) |
+ err = this.payloadValidators_[i](messageValidator); |
+ |
+ if (err == noError) { |
+ return this.handleValidIncomingMessage_(message); |
+ } else { |
+ internal.reportValidationError(err); |
+ return false; |
+ } |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.handleValidIncomingMessage_ = function( |
+ message) { |
+ if (internal.isTestingMode()) { |
+ return true; |
+ } |
+ |
+ if (this.encounteredError_) { |
+ return false; |
+ } |
+ |
+ var ok = false; |
+ |
+ if (message.expectsResponse()) { |
+ if (internal.isInterfaceControlMessage(message) && |
+ this.controlMessageHandler_) { |
+ ok = this.controlMessageHandler_.acceptWithResponder(message, this); |
+ } else if (this.incomingReceiver_) { |
+ ok = this.incomingReceiver_.acceptWithResponder(message, this); |
+ } |
+ } else if (message.isResponse()) { |
+ var reader = new internal.MessageReader(message); |
+ var requestID = reader.requestID; |
+ var completer = this.completers_.get(requestID); |
+ if (completer) { |
+ this.completers_.delete(requestID); |
+ completer.resolve(message); |
+ ok = true; |
+ } else { |
+ console.log("Unexpected response with request ID: " + requestID); |
+ } |
+ } else { |
+ if (internal.isInterfaceControlMessage(message) && |
+ this.controlMessageHandler_) { |
+ ok = this.controlMessageHandler_.accept(message); |
+ } else if (this.incomingReceiver_) { |
+ ok = this.incomingReceiver_.accept(message); |
+ } |
+ } |
+ return ok; |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.notifyError = function(reason) { |
+ if (this.encounteredError_) { |
+ return; |
+ } |
+ this.encounteredError_ = true; |
+ |
+ this.completers_.forEach(function(value) { |
+ value.reject(); |
+ }); |
+ this.completers_.clear(); // Drop any responders. |
+ |
+ if (this.connectionErrorHandler_) { |
+ this.connectionErrorHandler_(reason); |
+ } |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.queryVersion = function() { |
+ return this.controlMessageProxy_.queryVersion(); |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.requireVersion = function(version) { |
+ this.controlMessageProxy_.requireVersion(version); |
+ }; |
+ |
+ InterfaceEndpointClient.prototype.getEncounteredError = function() { |
+ return this.encounteredError_; |
+ }; |
+ |
+ internal.InterfaceEndpointClient = InterfaceEndpointClient; |
+})(); |