Javascript  |  98行  |  2.85 KB

// Copyright 2013 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/apps/js/bindings/codec",
  "mojo/apps/js/bindings/core",
  "mojo/apps/js/bindings/support",
], function(codec, core, support) {

  function Connector(handle) {
    this.handle_ = handle;
    this.error_ = false;
    this.incomingReceiver_ = null;
    this.readWaitCookie_ = null;
  }

  Connector.prototype.close = function() {
    if (this.readWaitCookie_) {
      support.cancelWait(this.readWaitCookie_);
      this.readWaitCookie_ = null;
    }
    if (this.handle_ != core.kInvalidHandle) {
      core.close(this.handle_);
      this.handle_ = core.kInvalidHandle;
    }
  };

  Connector.prototype.accept = function(message) {
    if (this.error_)
      return false;
    this.write_(message);
    return !this.error_;
  };

  Connector.prototype.setIncomingReceiver = function(receiver) {
    this.incomingReceiver_ = receiver;
    if (this.incomingReceiver_)
      this.waitToReadMore_();
  };

  Connector.prototype.write_ = function(message) {
    var result = core.writeMessage(this.handle_,
                                   message.memory,
                                   message.handles,
                                   core.WRITE_MESSAGE_FLAG_NONE);
    if (result != core.RESULT_OK) {
      this.error_ = true
      return;
    }
    // The handles were successfully transferred, so we don't own them anymore.
    message.handles = [];
  };

  Connector.prototype.waitToReadMore_ = function() {
    this.readWaitCookie_ = support.asyncWait(this.handle_,
                                             core.WAIT_FLAG_READABLE,
                                             this.readMore_.bind(this));
  };

  Connector.prototype.readMore_ = function(result) {
    for (;;) {
      var read = core.readMessage(this.handle_,
                                  core.READ_MESSAGE_FLAG_NONE);
      if (read.result == core.RESULT_NOT_FOUND) {
        this.waitToReadMore_();
        return;
      }
      if (read.result != core.RESULT_OK) {
        this.error_ = true;
        return;
      }
      // TODO(abarth): Should core.readMessage return a Uint8Array?
      var memory = new Uint8Array(read.buffer);
      var message = new codec.Message(memory, read.handles);
      this.incomingReceiver_.accept(message);
    }
  };

  function Connection(handle, localFactory, remoteFactory) {
    this.connector_ = new Connector(handle);
    this.remote = new remoteFactory(this.connector_);
    this.local = new localFactory(this.remote);
    this.connector_.setIncomingReceiver(this.local);
  }

  Connection.prototype.close = function() {
    this.connector_.close();
    this.connector_ = null;
    this.local = null;
    this.remote = null;
  };

  var exports = {};
  exports.Connection = Connection;
  return exports;
});