// Copyright 2014 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/bindings/router", [ "mojo/public/js/bindings/codec", "mojo/public/js/bindings/connector", ], function(codec, connector) { function Router(handle) { this.connector_ = new connector.Connector(handle); this.incomingReceiver_ = null; this.nextRequestID_ = 0; this.responders_ = {}; this.connector_.setIncomingReceiver({ accept: this.handleIncomingMessage_.bind(this), }); this.connector_.setErrorHandler({ onError: this.handleConnectionError_.bind(this), }); } Router.prototype.close = function() { this.responders_ = {}; // Drop any responders. this.connector_.close(); }; Router.prototype.accept = function(message) { this.connector_.accept(message); }; Router.prototype.reject = function(message) { // TODO(mpcomplete): no way to trasmit errors over a Connection. }; Router.prototype.acceptWithResponder = function(message, responder) { // 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.connector_.accept(message); this.responders_[requestID] = responder; // TODO(mpcomplete): accept should return a Promise too, maybe? if (result) return Promise.resolve(); return Promise.reject(Error("Connection error")); }; Router.prototype.setIncomingReceiver = function(receiver) { this.incomingReceiver_ = receiver; }; Router.prototype.encounteredError = function() { return this.connector_.encounteredError(); }; Router.prototype.handleIncomingMessage_ = function(message) { var flags = message.getFlags(); if (flags & codec.kMessageExpectsResponse) { if (this.incomingReceiver_) { this.incomingReceiver_.acceptWithResponder(message, this); } else { // If we receive a request expecting a response when the client is not // listening, then we have no choice but to tear down the pipe. this.close(); } } else if (flags & codec.kMessageIsResponse) { var reader = new codec.MessageReader(message); var requestID = reader.requestID; var responder = this.responders_[requestID]; delete this.responders_[requestID]; responder.accept(message); } else { if (this.incomingReceiver_) this.incomingReceiver_.accept(message); } }; Router.prototype.handleConnectionError_ = function(result) { for (var each in this.responders_) this.responders_[each].reject(result); this.close(); }; var exports = {}; exports.Router = Router; return exports; });