Index: extensions/renderer/resources/data_sender.js |
diff --git a/extensions/renderer/resources/data_sender.js b/extensions/renderer/resources/data_sender.js |
index ee1abb33ab0b98d29639f21c8ae9098e500d2a24..d750ed2f51bcbb648f2a85ac26c59b2da8ba92cb 100644 |
--- a/extensions/renderer/resources/data_sender.js |
+++ b/extensions/renderer/resources/data_sender.js |
@@ -5,9 +5,10 @@ |
define('data_sender', [ |
'async_waiter', |
'device/serial/data_stream.mojom', |
+ 'device/serial/data_stream_serialization.mojom', |
'mojo/public/js/bindings/core', |
'mojo/public/js/bindings/router', |
-], function(asyncWaiter, dataStreamMojom, core, routerModule) { |
+], function(asyncWaiter, dataStreamMojom, serialization, core, routerModule) { |
/** |
* @module data_sender |
*/ |
@@ -170,30 +171,55 @@ define('data_sender', [ |
* @alias module:data_sender.DataSender |
*/ |
function DataSender(handle, bufferSize, fatalErrorValue) { |
- /** |
- * The [Router]{@link module:mojo/public/js/bindings/router.Router} for the |
- * connection to the DataSink. |
- * @private |
- */ |
- this.router_ = new routerModule.Router(handle); |
- /** |
- * The connection to the DataSink. |
- * @private |
- */ |
- this.sink_ = new dataStreamMojom.DataSinkProxy(this.router_); |
- this.router_.setIncomingReceiver(this); |
var dataPipeOptions = { |
flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, |
elementNumBytes: 1, |
capacityNumBytes: bufferSize, |
}; |
var sendPipe = core.createDataPipe(dataPipeOptions); |
+ this.init_(handle, sendPipe.producerHandle, fatalErrorValue); |
this.sink_.init(sendPipe.consumerHandle); |
+ } |
+ |
+ DataSender.prototype = |
+ $Object.create(dataStreamMojom.DataSinkClientStub.prototype); |
+ |
+ /** |
+ * Closes this DataSender. |
+ */ |
+ DataSender.prototype.close = function() { |
+ if (this.shutDown_) |
+ return; |
+ this.shutDown_ = true; |
+ this.waiter_.stop(); |
+ this.router_.close(); |
+ core.close(this.sendPipe_); |
+ while (this.pendingSends_.length) { |
+ this.pendingSends_.pop().reportBytesSentAndError( |
+ 0, this.fatalErrorValue_); |
+ } |
+ while (this.sendsAwaitingAck_.length) { |
+ this.sendsAwaitingAck_.pop().reportBytesSentAndError( |
+ 0, this.fatalErrorValue_); |
+ } |
+ this.callCancelCallback_(); |
+ }; |
+ |
+ /** |
+ * Initialize this DataSender. |
+ * @param {MojoHandle} sink A handle to the DataSink |
+ * @param {MojoHandle} dataPipe A handle to use for sending data to the |
+ * DataSink. |
+ * @param {number} fatalErrorValue The error to dispatch in the event of a |
+ * fatal error. |
+ * @private |
+ */ |
+ DataSender.prototype.init_ = function(sink, dataPipe, fatalErrorValue) { |
/** |
* The handle to the data pipe to use for sending data. |
* @private |
*/ |
- this.sendPipe_ = sendPipe.producerHandle; |
+ this.sendPipe_ = dataPipe; |
/** |
* The error to be dispatched in the event of a fatal error. |
* @type {number} |
@@ -201,6 +227,24 @@ define('data_sender', [ |
*/ |
this.fatalErrorValue_ = fatalErrorValue; |
/** |
+ * Whether this DataReceiver has shut down. |
+ * @type {boolean} |
+ * @private |
+ */ |
+ this.shutDown_ = false; |
+ /** |
+ * The [Router]{@link module:mojo/public/js/bindings/router.Router} for the |
+ * connection to the DataSink. |
+ * @private |
+ */ |
+ this.router_ = new routerModule.Router(sink); |
+ /** |
+ * The connection to the DataSink. |
+ * @private |
+ */ |
+ this.sink_ = new dataStreamMojom.DataSinkProxy(this.router_); |
+ this.router_.setIncomingReceiver(this); |
+ /** |
* The async waiter used to wait for |
* {@link module:data_sender.DataSender#sendPipe_} to be writable. |
* @type module:async_waiter.AsyncWaiter |
@@ -222,45 +266,78 @@ define('data_sender', [ |
* @private |
*/ |
this.sendsAwaitingAck_ = []; |
+ |
/** |
* The callback that will resolve a pending cancel if one is in progress. |
* @type Function |
* @private |
*/ |
this.pendingCancel_ = null; |
+ |
/** |
- * Whether this DataReceiver has shut down. |
- * @type {boolean} |
+ * The promise that will be resolved when a pending cancel completes if one |
+ * is in progress. |
+ * @type Promise.<> |
* @private |
*/ |
- this.shutDown_ = false; |
- } |
- |
- DataSender.prototype = |
- $Object.create(dataStreamMojom.DataSinkClientStub.prototype); |
+ this.cancelPromise = null; |
+ }; |
/** |
- * Closes this DataSender. |
+ * Serializes this DataSender. |
+ * This will cancel any sends in progress before the returned promise |
+ * resolves. |
+ * @return {Promise.<?SerializedDataSender>} A promise that will resolve to |
+ * the serialization of this DataSender. If this DataSender has shut down, |
+ * the promise will resolve to null. |
*/ |
- DataSender.prototype.close = function() { |
+ DataSender.prototype.serialize = function() { |
if (this.shutDown_) |
- return; |
- this.shutDown_ = true; |
- this.waiter_.stop(); |
- this.router_.close(); |
- core.close(this.sendPipe_); |
- while (this.pendingSends_.length) { |
- this.pendingSends_.pop().reportBytesSentAndError( |
- 0, this.fatalErrorValue_); |
- } |
- while (this.sendsAwaitingAck_.length) { |
- this.sendsAwaitingAck_.pop().reportBytesSentAndError( |
- 0, this.fatalErrorValue_); |
+ return Promise.resolve(null); |
+ |
+ var readyToSerialize = Promise.resolve(); |
+ if (this.pendingSends_.length) { |
+ if (this.pendingCancel_) |
+ readyToSerialize = this.cancelPromise_; |
+ else |
+ readyToSerialize = this.cancel(this.fatalErrorValue_); |
} |
- if (this.pendingCancel_) { |
- this.pendingCancel_(); |
- this.pendingCancel_ = null; |
+ return readyToSerialize.then(function() { |
+ this.waiter_.stop(); |
+ var serialized = new serialization.SerializedDataSender(); |
+ serialized.sink = this.router_.connector_.handle_, |
+ serialized.data_pipe = this.sendPipe_, |
+ serialized.fatal_error_value = this.fatalErrorValue_, |
+ this.router_.connector_.handle_ = null; |
+ this.router_.close(); |
+ this.shutDown_ = true; |
+ return serialized; |
+ }.bind(this)); |
+ }; |
+ |
+ /** |
+ * Deserializes a SerializedDataSender. |
+ * @param {?SerializedDataSender} serialized The serialized DataSender. |
+ * @return {DataSender} The deserialized DataSender. |
+ */ |
+ DataSender.deserialize = function(serialized) { |
+ var sender = $Object.create(DataSender.prototype); |
+ sender.deserialize_(serialized); |
+ return sender; |
+ }; |
+ |
+ /** |
+ * Deserializes a SerializedDataSender into this DataSender. |
+ * @param {?SerializedDataSender} serialized The serialized DataSender. |
+ * @private |
+ */ |
+ DataSender.prototype.deserialize_ = function(serialized) { |
+ if (!serialized) { |
+ this.shutDown_ = true; |
+ return; |
} |
+ this.init_( |
+ serialized.sink, serialized.data_pipe, serialized.fatal_error_value); |
}; |
/** |
@@ -301,9 +378,10 @@ define('data_sender', [ |
return Promise.resolve(); |
this.sink_.cancel(error); |
- return new Promise(function(resolve) { |
+ this.cancelPromise_ = new Promise(function(resolve) { |
this.pendingCancel_ = resolve; |
}.bind(this)); |
+ return this.cancelPromise_; |
}; |
/** |
@@ -337,6 +415,7 @@ define('data_sender', [ |
*/ |
DataSender.prototype.callCancelCallback_ = function() { |
if (this.pendingCancel_) { |
+ this.cancelPromise_ = null; |
this.pendingCancel_(); |
this.pendingCancel_ = null; |
} |