Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: extensions/renderer/resources/data_sender.js

Issue 571333002: Add serialization support to the JS DataSender and DataReceiver. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@stash-service
Patch Set: address comments Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 define('data_sender', [ 5 define('data_sender', [
6 'async_waiter', 6 'async_waiter',
7 'device/serial/data_stream.mojom', 7 'device/serial/data_stream.mojom',
8 'device/serial/data_stream_serialization.mojom',
8 'mojo/public/js/bindings/core', 9 'mojo/public/js/bindings/core',
9 'mojo/public/js/bindings/router', 10 'mojo/public/js/bindings/router',
10 ], function(asyncWaiter, dataStreamMojom, core, routerModule) { 11 ], function(asyncWaiter, dataStreamMojom, serialization, core, routerModule) {
11 /** 12 /**
12 * @module data_sender 13 * @module data_sender
13 */ 14 */
14 15
15 /** 16 /**
16 * A pending send operation. 17 * A pending send operation.
17 * @param {ArrayBuffer} data The data to be sent. 18 * @param {ArrayBuffer} data The data to be sent.
18 * @constructor 19 * @constructor
19 * @alias module:data_sender~PendingSend 20 * @alias module:data_sender~PendingSend
20 * @private 21 * @private
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 /** 164 /**
164 * A DataSender that sends data to a DataSink. 165 * A DataSender that sends data to a DataSink.
165 * @param {MojoHandle} handle The handle to the DataSink. 166 * @param {MojoHandle} handle The handle to the DataSink.
166 * @param {number} bufferSize How large a buffer the data pipe should use. 167 * @param {number} bufferSize How large a buffer the data pipe should use.
167 * @param {number} fatalErrorValue The send error value to report in the 168 * @param {number} fatalErrorValue The send error value to report in the
168 * event of a fatal error. 169 * event of a fatal error.
169 * @constructor 170 * @constructor
170 * @alias module:data_sender.DataSender 171 * @alias module:data_sender.DataSender
171 */ 172 */
172 function DataSender(handle, bufferSize, fatalErrorValue) { 173 function DataSender(handle, bufferSize, fatalErrorValue) {
173 /**
174 * The [Router]{@link module:mojo/public/js/bindings/router.Router} for the
175 * connection to the DataSink.
176 * @private
177 */
178 this.router_ = new routerModule.Router(handle);
179 /**
180 * The connection to the DataSink.
181 * @private
182 */
183 this.sink_ = new dataStreamMojom.DataSinkProxy(this.router_);
184 this.router_.setIncomingReceiver(this);
185 var dataPipeOptions = { 174 var dataPipeOptions = {
186 flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 175 flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
187 elementNumBytes: 1, 176 elementNumBytes: 1,
188 capacityNumBytes: bufferSize, 177 capacityNumBytes: bufferSize,
189 }; 178 };
190 var sendPipe = core.createDataPipe(dataPipeOptions); 179 var sendPipe = core.createDataPipe(dataPipeOptions);
180 this.init_(handle, sendPipe.producerHandle, fatalErrorValue);
191 this.sink_.init(sendPipe.consumerHandle); 181 this.sink_.init(sendPipe.consumerHandle);
182 }
183
184 DataSender.prototype =
185 $Object.create(dataStreamMojom.DataSinkClientStub.prototype);
186
187 /**
188 * Closes this DataSender.
189 */
190 DataSender.prototype.close = function() {
191 if (this.shutDown_)
192 return;
193 this.shutDown_ = true;
194 this.waiter_.stop();
195 this.router_.close();
196 core.close(this.sendPipe_);
197 while (this.pendingSends_.length) {
198 this.pendingSends_.pop().reportBytesSentAndError(
199 0, this.fatalErrorValue_);
200 }
201 while (this.sendsAwaitingAck_.length) {
202 this.sendsAwaitingAck_.pop().reportBytesSentAndError(
203 0, this.fatalErrorValue_);
204 }
205 this.callCancelCallback_();
206 };
207
208 /**
209 * Initialize this DataSender.
210 * @param {MojoHandle} sink A handle to the DataSink
211 * @param {MojoHandle} dataPipe A handle to use for sending data to the
212 * DataSink.
213 * @param {number} fatalErrorValue The error to dispatch in the event of a
214 * fatal error.
215 * @private
216 */
217 DataSender.prototype.init_ = function(sink, dataPipe, fatalErrorValue) {
192 /** 218 /**
193 * The handle to the data pipe to use for sending data. 219 * The handle to the data pipe to use for sending data.
194 * @private 220 * @private
195 */ 221 */
196 this.sendPipe_ = sendPipe.producerHandle; 222 this.sendPipe_ = dataPipe;
197 /** 223 /**
198 * The error to be dispatched in the event of a fatal error. 224 * The error to be dispatched in the event of a fatal error.
199 * @type {number} 225 * @type {number}
200 * @private 226 * @private
201 */ 227 */
202 this.fatalErrorValue_ = fatalErrorValue; 228 this.fatalErrorValue_ = fatalErrorValue;
203 /** 229 /**
230 * Whether this DataReceiver has shut down.
231 * @type {boolean}
232 * @private
233 */
234 this.shutDown_ = false;
235 /**
236 * The [Router]{@link module:mojo/public/js/bindings/router.Router} for the
237 * connection to the DataSink.
238 * @private
239 */
240 this.router_ = new routerModule.Router(sink);
241 /**
242 * The connection to the DataSink.
243 * @private
244 */
245 this.sink_ = new dataStreamMojom.DataSinkProxy(this.router_);
246 this.router_.setIncomingReceiver(this);
247 /**
204 * The async waiter used to wait for 248 * The async waiter used to wait for
205 * {@link module:data_sender.DataSender#sendPipe_} to be writable. 249 * {@link module:data_sender.DataSender#sendPipe_} to be writable.
206 * @type module:async_waiter.AsyncWaiter 250 * @type module:async_waiter.AsyncWaiter
207 * @private 251 * @private
208 */ 252 */
209 this.waiter_ = new asyncWaiter.AsyncWaiter( 253 this.waiter_ = new asyncWaiter.AsyncWaiter(
210 this.sendPipe_, core.HANDLE_SIGNAL_WRITABLE, 254 this.sendPipe_, core.HANDLE_SIGNAL_WRITABLE,
211 this.onHandleReady_.bind(this)); 255 this.onHandleReady_.bind(this));
212 /** 256 /**
213 * A queue of sends that have not fully written their data to the data pipe. 257 * A queue of sends that have not fully written their data to the data pipe.
214 * @type module:data_sender~PendingSend[] 258 * @type module:data_sender~PendingSend[]
215 * @private 259 * @private
216 */ 260 */
217 this.pendingSends_ = []; 261 this.pendingSends_ = [];
218 /** 262 /**
219 * A queue of sends that have written their data to the data pipe, but have 263 * A queue of sends that have written their data to the data pipe, but have
220 * not been received by the DataSink. 264 * not been received by the DataSink.
221 * @type module:data_sender~PendingSend[] 265 * @type module:data_sender~PendingSend[]
222 * @private 266 * @private
223 */ 267 */
224 this.sendsAwaitingAck_ = []; 268 this.sendsAwaitingAck_ = [];
269
225 /** 270 /**
226 * The callback that will resolve a pending cancel if one is in progress. 271 * The callback that will resolve a pending cancel if one is in progress.
227 * @type Function 272 * @type Function
228 * @private 273 * @private
229 */ 274 */
230 this.pendingCancel_ = null; 275 this.pendingCancel_ = null;
276
231 /** 277 /**
232 * Whether this DataReceiver has shut down. 278 * The promise that will be resolved when a pending cancel completes if one
233 * @type {boolean} 279 * is in progress.
280 * @type Promise.<>
234 * @private 281 * @private
235 */ 282 */
236 this.shutDown_ = false; 283 this.cancelPromise = null;
237 }
238
239 DataSender.prototype =
240 $Object.create(dataStreamMojom.DataSinkClientStub.prototype);
241
242 /**
243 * Closes this DataSender.
244 */
245 DataSender.prototype.close = function() {
246 if (this.shutDown_)
247 return;
248 this.shutDown_ = true;
249 this.waiter_.stop();
250 this.router_.close();
251 core.close(this.sendPipe_);
252 while (this.pendingSends_.length) {
253 this.pendingSends_.pop().reportBytesSentAndError(
254 0, this.fatalErrorValue_);
255 }
256 while (this.sendsAwaitingAck_.length) {
257 this.sendsAwaitingAck_.pop().reportBytesSentAndError(
258 0, this.fatalErrorValue_);
259 }
260 if (this.pendingCancel_) {
261 this.pendingCancel_();
262 this.pendingCancel_ = null;
263 }
264 }; 284 };
265 285
266 /** 286 /**
287 * Serializes this DataSender.
288 * This will cancel any sends in progress before the returned promise
289 * resolves.
290 * @return {Promise.<?SerializedDataSender>} A promise that will resolve to
291 * the serialization of this DataSender. If this DataSender has shut down,
292 * the promise will resolve to null.
293 */
294 DataSender.prototype.serialize = function() {
295 if (this.shutDown_)
296 return Promise.resolve(null);
297
298 var readyToSerialize = Promise.resolve();
299 if (this.pendingSends_.length) {
300 if (this.pendingCancel_)
301 readyToSerialize = this.cancelPromise_;
302 else
303 readyToSerialize = this.cancel(this.fatalErrorValue_);
304 }
305 return readyToSerialize.then(function() {
306 this.waiter_.stop();
307 var serialized = new serialization.SerializedDataSender();
308 serialized.sink = this.router_.connector_.handle_,
309 serialized.data_pipe = this.sendPipe_,
310 serialized.fatal_error_value = this.fatalErrorValue_,
311 this.router_.connector_.handle_ = null;
312 this.router_.close();
313 this.shutDown_ = true;
314 return serialized;
315 }.bind(this));
316 };
317
318 /**
319 * Deserializes a SerializedDataSender.
320 * @param {?SerializedDataSender} serialized The serialized DataSender.
321 * @return {DataSender} The deserialized DataSender.
322 */
323 DataSender.deserialize = function(serialized) {
324 var sender = $Object.create(DataSender.prototype);
325 sender.deserialize_(serialized);
326 return sender;
327 };
328
329 /**
330 * Deserializes a SerializedDataSender into this DataSender.
331 * @param {?SerializedDataSender} serialized The serialized DataSender.
332 * @private
333 */
334 DataSender.prototype.deserialize_ = function(serialized) {
335 if (!serialized) {
336 this.shutDown_ = true;
337 return;
338 }
339 this.init_(
340 serialized.sink, serialized.data_pipe, serialized.fatal_error_value);
341 };
342
343 /**
267 * Sends data to the DataSink. 344 * Sends data to the DataSink.
268 * @return {Promise.<number>} A promise to the number of bytes sent. If an 345 * @return {Promise.<number>} A promise to the number of bytes sent. If an
269 * error occurs, the promise will reject with an Error object with a 346 * error occurs, the promise will reject with an Error object with a
270 * property error containing the error code. 347 * property error containing the error code.
271 * @throws Will throw if this has encountered a fatal error or a cancel is in 348 * @throws Will throw if this has encountered a fatal error or a cancel is in
272 * progress. 349 * progress.
273 */ 350 */
274 DataSender.prototype.send = function(data) { 351 DataSender.prototype.send = function(data) {
275 if (this.shutDown_) 352 if (this.shutDown_)
276 throw new Error('DataSender has been closed'); 353 throw new Error('DataSender has been closed');
(...skipping 17 matching lines...) Expand all
294 */ 371 */
295 DataSender.prototype.cancel = function(error) { 372 DataSender.prototype.cancel = function(error) {
296 if (this.shutDown_) 373 if (this.shutDown_)
297 throw new Error('DataSender has been closed'); 374 throw new Error('DataSender has been closed');
298 if (this.pendingCancel_) 375 if (this.pendingCancel_)
299 throw new Error('Cancel already in progress'); 376 throw new Error('Cancel already in progress');
300 if (this.pendingSends_.length + this.sendsAwaitingAck_.length == 0) 377 if (this.pendingSends_.length + this.sendsAwaitingAck_.length == 0)
301 return Promise.resolve(); 378 return Promise.resolve();
302 379
303 this.sink_.cancel(error); 380 this.sink_.cancel(error);
304 return new Promise(function(resolve) { 381 this.cancelPromise_ = new Promise(function(resolve) {
305 this.pendingCancel_ = resolve; 382 this.pendingCancel_ = resolve;
306 }.bind(this)); 383 }.bind(this));
384 return this.cancelPromise_;
307 }; 385 };
308 386
309 /** 387 /**
310 * Invoked when |handle_| is ready to write. Writes to the data pipe if the 388 * Invoked when |handle_| is ready to write. Writes to the data pipe if the
311 * wait is successful. 389 * wait is successful.
312 * @param {number} waitResult The result of the asynchronous wait. 390 * @param {number} waitResult The result of the asynchronous wait.
313 * @private 391 * @private
314 */ 392 */
315 DataSender.prototype.onHandleReady_ = function(result) { 393 DataSender.prototype.onHandleReady_ = function(result) {
316 if (result != core.RESULT_OK) { 394 if (result != core.RESULT_OK) {
(...skipping 13 matching lines...) Expand all
330 } 408 }
331 } 409 }
332 }; 410 };
333 411
334 /** 412 /**
335 * Calls and clears the pending cancel callback if one is pending. 413 * Calls and clears the pending cancel callback if one is pending.
336 * @private 414 * @private
337 */ 415 */
338 DataSender.prototype.callCancelCallback_ = function() { 416 DataSender.prototype.callCancelCallback_ = function() {
339 if (this.pendingCancel_) { 417 if (this.pendingCancel_) {
418 this.cancelPromise_ = null;
340 this.pendingCancel_(); 419 this.pendingCancel_();
341 this.pendingCancel_ = null; 420 this.pendingCancel_ = null;
342 } 421 }
343 }; 422 };
344 423
345 /** 424 /**
346 * Invoked by the DataSink to report that data has been successfully sent. 425 * Invoked by the DataSink to report that data has been successfully sent.
347 * @param {number} numBytes The number of bytes sent. 426 * @param {number} numBytes The number of bytes sent.
348 * @private 427 * @private
349 */ 428 */
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 // Note: Only the first PendingSend in |pendingSends_| will have data to 467 // Note: Only the first PendingSend in |pendingSends_| will have data to
389 // flush as only the first can have written data to the data pipe. 468 // flush as only the first can have written data to the data pipe.
390 bytesToFlush += result.bytesToFlush; 469 bytesToFlush += result.bytesToFlush;
391 } 470 }
392 this.callCancelCallback_(); 471 this.callCancelCallback_();
393 return Promise.resolve({bytes_to_flush: bytesToFlush}); 472 return Promise.resolve({bytes_to_flush: bytesToFlush});
394 }; 473 };
395 474
396 return {DataSender: DataSender}; 475 return {DataSender: DataSender};
397 }); 476 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698