| Index: mojo/public/js/lib/interface_endpoint_client.js
|
| diff --git a/mojo/public/js/lib/interface_endpoint_client.js b/mojo/public/js/lib/interface_endpoint_client.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..631c52ec911c168410c6ff98402cdb21d4433875
|
| --- /dev/null
|
| +++ b/mojo/public/js/lib/interface_endpoint_client.js
|
| @@ -0,0 +1,232 @@
|
| +// 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.
|
| +
|
| +define("mojo/public/js/lib/interface_endpoint_client", [
|
| + "console",
|
| + "mojo/public/js/codec",
|
| + "mojo/public/js/lib/control_message_handler",
|
| + "mojo/public/js/lib/control_message_proxy",
|
| + "mojo/public/js/lib/interface_endpoint_handle",
|
| + "mojo/public/js/validator",
|
| + "timer",
|
| +], function(console,
|
| + codec,
|
| + controlMessageHandler,
|
| + controlMessageProxy,
|
| + interfaceEndpointHandle,
|
| + validator,
|
| + timer) {
|
| +
|
| + var ControlMessageHandler = controlMessageHandler.ControlMessageHandler;
|
| + var ControlMessageProxy = controlMessageProxy.ControlMessageProxy;
|
| + var MessageReader = codec.MessageReader;
|
| + var Validator = validator.Validator;
|
| + var InterfaceEndpointHandle = interfaceEndpointHandle.InterfaceEndpointHandle;
|
| +
|
| + function InterfaceEndpointClient(interfaceEndpointHandle, receiver,
|
| + interfaceVersion) {
|
| + this.controller_ = null;
|
| + this.encounteredError_ = false;
|
| + this.handle_ = interfaceEndpointHandle;
|
| + this.incomingReceiver_ = receiver;
|
| +
|
| + if (interfaceVersion !== undefined) {
|
| + this.controlMessageHandler_ = new ControlMessageHandler(
|
| + interfaceVersion);
|
| + } else {
|
| + this.controlMessageProxy_ = new 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 ===
|
| + InterfaceEndpointHandle.AssociationEvent.ASSOCIATED) {
|
| + this.initControllerIfNecessary_();
|
| + } else if (associationEvent ===
|
| + InterfaceEndpointHandle.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 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 (this.encounteredError_) {
|
| + return false;
|
| + }
|
| +
|
| + this.initControllerIfNecessary_();
|
| + return this.controller_.sendMessage(message);
|
| + };
|
| +
|
| + InterfaceEndpointClient.prototype.acceptAndExpectResponse = function(
|
| + message) {
|
| + 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) {
|
| + var noError = validator.validationError.NONE;
|
| + var messageValidator = new Validator(message);
|
| + 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 {
|
| + validator.reportValidationError(err);
|
| + return false;
|
| + }
|
| + };
|
| +
|
| + InterfaceEndpointClient.prototype.handleValidIncomingMessage_ = function(
|
| + message) {
|
| + if (validator.isTestingMode()) {
|
| + return true;
|
| + }
|
| +
|
| + if (this.encounteredError_) {
|
| + return false;
|
| + }
|
| +
|
| + var ok = false;
|
| +
|
| + if (message.expectsResponse()) {
|
| + if (controlMessageHandler.isControlMessage(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 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 (controlMessageHandler.isControlMessage(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);
|
| + };
|
| +
|
| + var exports = {};
|
| + exports.InterfaceEndpointClient = InterfaceEndpointClient;
|
| +
|
| + return exports;
|
| +});
|
|
|