data_receiver.js revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found in the LICENSE file.
403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)define('data_receiver', [
603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    'async_waiter',
703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    'device/serial/data_stream.mojom',
803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    'mojo/public/js/bindings/core',
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    'mojo/public/js/bindings/router',
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)], function(asyncWaiter, dataStream, core, router) {
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @module data_receiver
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @typedef module:data_receiver~PendingError
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @type {Object}
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @property {number} error - the error
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @property {number} offset - the location of the error
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @private
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * A pending receive operation.
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @constructor
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @alias module:data_receiver~PendingReceive
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @private
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  function PendingReceive() {
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The promise that will be resolved or rejected when this receive completes
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * or fails, respectively.
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type {Promise.<ArrayBuffer>}
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.promise_ = new Promise(function(resolve, reject) {
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      /**
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       * The callback to call with the data received on success.
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       * @type {Function}
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       * @private
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       */
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.dataCallback_ = resolve;
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      /**
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       * The callback to call with the error on failure.
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       * @type {Function}
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       * @private
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       */
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.errorCallback_ = reject;
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }.bind(this));
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Returns the promise that will be resolved when this operation completes or
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * rejected if an error occurs.
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @return {Promise.<ArrayBuffer>} A promise to the data received.
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PendingReceive.prototype.getPromise = function() {
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return this.promise_;
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Dispatches received data to the promise returned by
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * [getPromise]{@link module:data_receiver.PendingReceive#getPromise}.
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {ArrayBuffer} data The data to dispatch.
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PendingReceive.prototype.dispatchData = function(data) {
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.dataCallback_(data);
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Dispatches an error if the offset of the error has been reached.
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {module:data_receiver~PendingError} error The error to dispatch.
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {number} bytesReceived The number of bytes that have been received.
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PendingReceive.prototype.dispatchError = function(error, bytesReceived) {
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (bytesReceived != error.offset)
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return false;
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var e = new Error();
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    e.error = error.error;
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.errorCallback_(e);
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return true;
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Unconditionally dispatches an error.
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {number} error The error to dispatch.
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  PendingReceive.prototype.dispatchFatalError = function(error) {
9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var e = new Error();
9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    e.error = error;
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.errorCallback_(e);
9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * A DataReceiver that receives data from a DataSource.
9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {MojoHandle} handle The handle to the DataSource.
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {number} bufferSize How large a buffer the data pipe should use.
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {number} fatalErrorValue The receive error value to report in the
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   *     event of a fatal error.
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @constructor
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @alias module:data_receiver.DataReceiver
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  function DataReceiver(handle, bufferSize, fatalErrorValue) {
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The [Router]{@link module:mojo/public/js/bindings/router.Router} for the
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * connection to the DataSource.
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.router_ = new router.Router(handle);
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The connection to the DataSource.
11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.source_ = new dataStream.DataSourceProxy(this.router_);
11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.router_.setIncomingReceiver(this);
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var dataPipeOptions = {
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      elementNumBytes: 1,
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      capacityNumBytes: bufferSize,
12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    };
12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var receivePipe = core.createDataPipe(dataPipeOptions);
12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.source_.init(receivePipe.producerHandle);
12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The handle to the data pipe to use for receiving data.
12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.receivePipe_ = receivePipe.consumerHandle;
12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The current receive operation.
13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type {module:data_receiver~PendingReceive}
13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.receive_ = null;
13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The error to be dispatched in the event of a fatal error.
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type {number}
13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.fatalErrorValue_ = fatalErrorValue;
14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The async waiter used to wait for
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * {@link module:data_receiver.DataReceiver#receivePipe_} to be readable.
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type module:async_waiter.AsyncWaiter
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.waiter_ = new asyncWaiter.AsyncWaiter(this.receivePipe_,
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               core.HANDLE_SIGNAL_READABLE,
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               this.onHandleReady_.bind(this));
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The number of bytes received from the DataSource.
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type {number}
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.bytesReceived_ = 0;
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * The pending error if there is one.
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type module:data_receiver~PendingError
15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.pendingError_ = null;
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * Whether the DataSource is paused.
16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type {boolean}
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.paused_ = false;
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * Whether this DataReceiver has shut down.
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type {boolean}
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @private
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.shutDown_ = false;
17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DataReceiver.prototype =
17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      $Object.create(dataStream.DataSourceClientStub.prototype);
17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Closes this DataReceiver.
18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DataReceiver.prototype.close = function() {
18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.shutDown_)
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.shutDown_ = true;
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.router_.close();
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.waiter_.stop();
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    core.close(this.receivePipe_);
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.receive_) {
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.receive_.dispatchFatalError(this.fatalErrorValue_);
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.receive_ = null;
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
19603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Receive data from the DataSource.
19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @return {Promise.<ArrayBuffer>} A promise to the received data. If an error
19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   *     occurs, the promise will reject with an Error object with a property
19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   *     error containing the error code.
20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @throws Will throw if this has encountered a fatal error or another receive
20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   *     is in progress.
20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DataReceiver.prototype.receive = function() {
20403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.shutDown_)
20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      throw new Error('System error');
20603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.receive_)
20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      throw new Error('Receive already in progress.');
20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var receive = new PendingReceive();
20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var promise = receive.getPromise();
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.pendingError_ &&
21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        receive.dispatchError(this.pendingError_, this.bytesReceived_)) {
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.pendingError_ = null;
21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.paused_ = true;
21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return promise;
21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.paused_) {
21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.source_.resume();
21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.paused_ = false;
21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.receive_ = receive;
22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.waiter_.start();
22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return promise;
22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Invoked when |handle_| is ready to read. Reads from the data pipe if the
22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * wait is successful.
22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {number} waitResult The result of the asynchronous wait.
22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @private
23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DataReceiver.prototype.onHandleReady_ = function(waitResult) {
23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (waitResult != core.RESULT_OK || !this.receive_) {
23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.close();
23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var result = core.readData(this.receivePipe_, core.READ_DATA_FLAG_NONE);
23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (result.result == core.RESULT_OK) {
23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // TODO(sammc): Handle overflow in the same fashion as the C++ receiver.
23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.bytesReceived_ += result.buffer.byteLength;
24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.receive_.dispatchData(result.buffer);
24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.receive_ = null;
24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else if (result.result == core.RESULT_SHOULD_WAIT) {
24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.waiter_.start();
24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.close();
24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  /**
25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * Invoked by the DataSource when an error is encountered.
25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {number} offset The location at which the error occurred.
25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @param {number} error The error that occurred.
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   * @private
25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)   */
25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DataReceiver.prototype.onError = function(offset, error) {
25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.shutDown_)
25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    /**
26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     * @type module:data_receiver~PendingError
26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)     */
26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    var pendingError = {
26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      error: error,
26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      offset: offset,
26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    };
26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (this.receive_ &&
26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        this.receive_.dispatchError(pendingError, this.bytesReceived_)) {
26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.receive_ = null;
26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.waiter_.stop();
27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this.paused_ = true;
27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    this.pendingError_ = pendingError;
27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return {DataReceiver: DataReceiver};
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)});
278