• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5define("mojo/public/js/bindings/connector", [
6  "mojo/public/js/bindings/buffer",
7  "mojo/public/js/bindings/codec",
8  "mojo/public/js/bindings/core",
9  "mojo/public/js/bindings/support",
10], function(buffer, codec, core, support) {
11
12  function Connector(handle) {
13    this.handle_ = handle;
14    this.dropWrites_ = false;
15    this.error_ = false;
16    this.incomingReceiver_ = null;
17    this.readWaitCookie_ = null;
18    this.errorHandler_ = null;
19
20    this.waitToReadMore_();
21  }
22
23  Connector.prototype.close = function() {
24    if (this.readWaitCookie_) {
25      support.cancelWait(this.readWaitCookie_);
26      this.readWaitCookie_ = null;
27    }
28    if (this.handle_ != null) {
29      core.close(this.handle_);
30      this.handle_ = null;
31    }
32  };
33
34  Connector.prototype.accept = function(message) {
35    if (this.error_)
36      return false;
37
38    if (this.dropWrites_)
39      return true;
40
41    var result = core.writeMessage(this.handle_,
42                                   new Uint8Array(message.buffer.arrayBuffer),
43                                   message.handles,
44                                   core.WRITE_MESSAGE_FLAG_NONE);
45    switch (result) {
46      case core.RESULT_OK:
47        // The handles were successfully transferred, so we don't own them
48        // anymore.
49        message.handles = [];
50        break;
51      case core.RESULT_FAILED_PRECONDITION:
52        // There's no point in continuing to write to this pipe since the other
53        // end is gone. Avoid writing any future messages. Hide write failures
54        // from the caller since we'd like them to continue consuming any
55        // backlog of incoming messages before regarding the message pipe as
56        // closed.
57        this.dropWrites_ = true;
58        break;
59      default:
60        // This particular write was rejected, presumably because of bad input.
61        // The pipe is not necessarily in a bad state.
62        return false;
63    }
64    return true;
65  };
66
67  Connector.prototype.setIncomingReceiver = function(receiver) {
68    this.incomingReceiver_ = receiver;
69  };
70
71  Connector.prototype.setErrorHandler = function(handler) {
72    this.errorHandler_ = handler;
73  };
74
75  Connector.prototype.encounteredError = function() {
76    return this.error_;
77  };
78
79  Connector.prototype.waitToReadMore_ = function() {
80    this.readWaitCookie_ = support.asyncWait(this.handle_,
81                                             core.HANDLE_SIGNAL_READABLE,
82                                             this.readMore_.bind(this));
83  };
84
85  Connector.prototype.readMore_ = function(result) {
86    for (;;) {
87      var read = core.readMessage(this.handle_,
88                                  core.READ_MESSAGE_FLAG_NONE);
89      if (read.result == core.RESULT_SHOULD_WAIT) {
90        this.waitToReadMore_();
91        return;
92      }
93      if (read.result != core.RESULT_OK) {
94        this.error_ = true;
95        if (this.errorHandler_)
96          this.errorHandler_.onError(read.result);
97        return;
98      }
99      var messageBuffer = new buffer.Buffer(read.buffer);
100      var message = new codec.Message(messageBuffer, read.handles);
101      if (this.incomingReceiver_) {
102          this.incomingReceiver_.accept(message);
103      }
104    }
105  };
106
107  // The TestConnector subclass is only intended to be used in unit tests. It
108  // enables delivering a message to the pipe's handle without an async wait.
109
110  function TestConnector(handle) {
111    Connector.call(this, handle);
112  }
113
114  TestConnector.prototype = Object.create(Connector.prototype);
115
116  TestConnector.prototype.waitToReadMore_ = function() {
117  };
118
119  TestConnector.prototype.deliverMessage = function() {
120    this.readMore_(core.RESULT_OK);
121  }
122
123  var exports = {};
124  exports.Connector = Connector;
125  exports.TestConnector = TestConnector;
126  return exports;
127});
128