Source: transport/micro-forwarder-transport.js

/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <[email protected]>
 * @author: Wentao Shang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * A copy of the GNU Lesser General Public License is in the file COPYING.
 */

/**
 * A MicroForwarderTransport extends Transport to connect to the browser's
 * micro forwarder service. This assumes that the MicroForwarder extensions has
 * been installed.
 * @param {function} onReceivedObject (optional) If supplied and the received
 * object type field is not "Buffer" then just call this.onReceivedObject(obj).
 * @constructor
 */
var MicroForwarderTransport = function MicroForwarderTransport(onReceivedObject)
{
  // Call the base constructor.
  Transport.call(this);

  this.elementReader = null;
  this.connectionInfo = null; // Read by Face.
  this.onReceivedObject = onReceivedObject;

  var thisTransport = this;
  window.addEventListener("message", function(event) {
    // We only accept messages from ourselves
    if (event.source != window)
      return;

    if (event.data.type && (event.data.type == "FromMicroForwarderStub")) {
      var obj = event.data.object;
      if (obj.type && obj.type == "Buffer") {
        if (thisTransport.elementReader != null)
          thisTransport.elementReader.onReceivedData(new Buffer(obj.data));
      }
      else {
        if (thisTransport.onReceivedObject)
          thisTransport.onReceivedObject(obj);
      }
    }
  }, false);
};

MicroForwarderTransport.prototype = new Transport();
MicroForwarderTransport.prototype.name = "MicroForwarderTransport";

/**
 * Create a new MicroForwarderTransport.ConnectionInfo which extends
 * Transport.ConnectionInfo to hold info for the micro forwarer connection.
 */
MicroForwarderTransport.ConnectionInfo = function MicroForwarderTransportConnectionInfo()
{
  // Call the base constructor.
  Transport.ConnectionInfo .call(this);
};

MicroForwarderTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
MicroForwarderTransport.ConnectionInfo.prototype.name = "MicroForwarderTransport.ConnectionInfo";

/**
 * Check if the fields of this MicroForwarderTransport.ConnectionInfo equal the other
 * MicroForwarderTransport.ConnectionInfo.
 * @param {MicroForwarderTransport.ConnectionInfo} The other object to check.
 * @returns {boolean} True if the objects have equal fields, false if not.
 */
MicroForwarderTransport.ConnectionInfo.prototype.equals = function(other)
{
  if (other == null)
    return false;
  return true;
};

MicroForwarderTransport.ConnectionInfo.prototype.toString = function()
{
  return "{}";
};

/**
 * Determine whether this transport connecting according to connectionInfo is to
 * a node on the current machine. Unix transports are always local.
 * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo This is ignored.
 * @param {function} onResult This calls onResult(true) because micro forwarder
 * transports are always local.
 * @param {function} onError This is ignored.
 */
MicroForwarderTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
{
  onResult(true);
};

/**
 * Connect to the micro forwarder according to the info in connectionInfo.
 * Listen on the connection to read an entire packet element and call
 * elementListener.onReceivedElement(element). However, if the received object
 * type field is not "Buffer" then just call this.onReceivedObject(obj).
 * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo
 * @param {object} elementListener The elementListener with function
 * onReceivedElement which must remain valid during the life of this object.
 * @param {function} onopenCallback Once connected, call onopenCallback().
 * @param {type} onclosedCallback If the connection is closed by the remote host,
 * call onclosedCallback().
 */
MicroForwarderTransport.prototype.connect = function
  (connectionInfo, elementListener, onopenCallback, onclosedCallback)
{
  // The window listener is already set up.
  this.elementReader = new ElementReader(elementListener);
  this.connectionInfo = connectionInfo;
  onopenCallback();
};

/**
 * Send the JavaScript over the connection created by connect.
 * @param {object} obj The object to send. It should have a field "type". If
 * "type" is "Buffer" then it is processed like an NDN packet.
 */
MicroForwarderTransport.prototype.sendObject = function(obj)
{
  window.postMessage({
    type: "FromMicroForwarderTransport",
    object: obj
  }, "*");
};

/**
 * Send the buffer over the connection created by connect.
 * @param {Buffer} buffer The bytes to send.
 */
MicroForwarderTransport.prototype.send = function(buffer)
{
  if (this.connectionInfo == null) {
    console.log("MicroForwarderTransport connection is not established.");
    return;
  }

  this.sendObject(buffer.toJSON());
};