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

Side by Side Diff: extensions/renderer/resources/data_receiver.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: clean up jsdoc 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_receiver', [ 5 define('data_receiver', [
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, dataStream, core, router) { 11 ], function(asyncWaiter, dataStream, serialization, core, router) {
11 /** 12 /**
12 * @module data_receiver 13 * @module data_receiver
13 */ 14 */
14 15
15 /** 16 /**
16 * @typedef module:data_receiver~PendingError
17 * @type {Object}
18 * @property {number} error - the error
19 * @property {number} offset - the location of the error
20 * @private
21 */
22
23 /**
24 * A pending receive operation. 17 * A pending receive operation.
25 * @constructor 18 * @constructor
26 * @alias module:data_receiver~PendingReceive 19 * @alias module:data_receiver~PendingReceive
27 * @private 20 * @private
28 */ 21 */
29 function PendingReceive() { 22 function PendingReceive() {
30 /** 23 /**
31 * The promise that will be resolved or rejected when this receive completes 24 * The promise that will be resolved or rejected when this receive completes
32 * or fails, respectively. 25 * or fails, respectively.
33 * @type {Promise.<ArrayBuffer>} 26 * @type {!Promise.<ArrayBuffer>}
34 * @private 27 * @private
35 */ 28 */
36 this.promise_ = new Promise(function(resolve, reject) { 29 this.promise_ = new Promise(function(resolve, reject) {
37 /** 30 /**
38 * The callback to call with the data received on success. 31 * The callback to call with the data received on success.
39 * @type {Function} 32 * @type {Function}
40 * @private 33 * @private
41 */ 34 */
42 this.dataCallback_ = resolve; 35 this.dataCallback_ = resolve;
43 /** 36 /**
(...skipping 10 matching lines...) Expand all
54 * rejected if an error occurs. 47 * rejected if an error occurs.
55 * @return {Promise.<ArrayBuffer>} A promise to the data received. 48 * @return {Promise.<ArrayBuffer>} A promise to the data received.
56 */ 49 */
57 PendingReceive.prototype.getPromise = function() { 50 PendingReceive.prototype.getPromise = function() {
58 return this.promise_; 51 return this.promise_;
59 }; 52 };
60 53
61 /** 54 /**
62 * Dispatches received data to the promise returned by 55 * Dispatches received data to the promise returned by
63 * [getPromise]{@link module:data_receiver.PendingReceive#getPromise}. 56 * [getPromise]{@link module:data_receiver.PendingReceive#getPromise}.
64 * @param {ArrayBuffer} data The data to dispatch. 57 * @param {!ArrayBuffer} data The data to dispatch.
65 */ 58 */
66 PendingReceive.prototype.dispatchData = function(data) { 59 PendingReceive.prototype.dispatchData = function(data) {
67 this.dataCallback_(data); 60 this.dataCallback_(data);
68 }; 61 };
69 62
70 /** 63 /**
71 * Dispatches an error if the offset of the error has been reached. 64 * Dispatches an error if the offset of the error has been reached.
72 * @param {module:data_receiver~PendingError} error The error to dispatch. 65 * @param {!PendingReceiveError} error The error to dispatch.
73 * @param {number} bytesReceived The number of bytes that have been received. 66 * @param {number} bytesReceived The number of bytes that have been received.
74 */ 67 */
75 PendingReceive.prototype.dispatchError = function(error, bytesReceived) { 68 PendingReceive.prototype.dispatchError = function(error, bytesReceived) {
76 if (bytesReceived != error.offset) 69 if (bytesReceived != error.offset)
77 return false; 70 return false;
78 71
79 var e = new Error(); 72 var e = new Error();
80 e.error = error.error; 73 e.error = error.error;
81 this.errorCallback_(e); 74 this.errorCallback_(e);
82 return true; 75 return true;
83 }; 76 };
84 77
85 /** 78 /**
86 * Unconditionally dispatches an error. 79 * Unconditionally dispatches an error.
87 * @param {number} error The error to dispatch. 80 * @param {number} error The error to dispatch.
88 */ 81 */
89 PendingReceive.prototype.dispatchFatalError = function(error) { 82 PendingReceive.prototype.dispatchFatalError = function(error) {
90 var e = new Error(); 83 var e = new Error();
91 e.error = error; 84 e.error = error;
92 this.errorCallback_(e); 85 this.errorCallback_(e);
93 }; 86 };
94 87
95 /** 88 /**
96 * A DataReceiver that receives data from a DataSource. 89 * A DataReceiver that receives data from a DataSource.
97 * @param {MojoHandle} handle The handle to the DataSource. 90 * @param {!MojoHandle} handle The handle to the DataSource.
98 * @param {number} bufferSize How large a buffer the data pipe should use. 91 * @param {number} bufferSize How large a buffer the data pipe should use.
99 * @param {number} fatalErrorValue The receive error value to report in the 92 * @param {number} fatalErrorValue The receive error value to report in the
100 * event of a fatal error. 93 * event of a fatal error.
101 * @constructor 94 * @constructor
102 * @alias module:data_receiver.DataReceiver 95 * @alias module:data_receiver.DataReceiver
103 */ 96 */
104 function DataReceiver(handle, bufferSize, fatalErrorValue) { 97 function DataReceiver(handle, bufferSize, fatalErrorValue) {
98 var dataPipeOptions = {
99 flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
100 elementNumBytes: 1,
101 capacityNumBytes: bufferSize,
102 };
103 var receivePipe = core.createDataPipe(dataPipeOptions);
104 this.init_(
105 handle, receivePipe.consumerHandle, fatalErrorValue, 0, null, false);
106 this.source_.init(receivePipe.producerHandle);
107 }
108
109 DataReceiver.prototype =
110 $Object.create(dataStream.DataSourceClientStub.prototype);
111
112 /**
113 * Closes this DataReceiver.
114 */
115 DataReceiver.prototype.close = function() {
116 if (this.shutDown_)
117 return;
118 this.shutDown_ = true;
119 this.router_.close();
120 this.waiter_.stop();
121 core.close(this.receivePipe_);
122 if (this.receive_) {
123 this.receive_.dispatchFatalError(this.fatalErrorValue_);
124 this.receive_ = null;
125 }
126 };
127
128 /**
129 * Initialize this DataReceiver.
130 * @param {!MojoHandle} source A handle to the DataSource
131 * @param {!MojoHandle} dataPipe A handle to use for receiving data from the
132 * DataSource.
133 * @param {number} fatalErrorValue The error to dispatch in the event of a
134 * fatal error.
135 * @param {number} bytesReceived The number of bytes already received.
136 * @param {PendingReceiveError} pendingError The pending error if there is
137 * one.
138 * @param {boolean} paused Whether the DataSource is paused.
139 * @private
140 */
141 DataReceiver.prototype.init_ = function(source,
142 dataPipe,
143 fatalErrorValue,
144 bytesReceived,
145 pendingError,
146 paused) {
105 /** 147 /**
106 * The [Router]{@link module:mojo/public/js/bindings/router.Router} for the 148 * The [Router]{@link module:mojo/public/js/bindings/router.Router} for the
107 * connection to the DataSource. 149 * connection to the DataSource.
108 * @private 150 * @private
109 */ 151 */
110 this.router_ = new router.Router(handle); 152 this.router_ = new router.Router(source);
111 /** 153 /**
112 * The connection to the DataSource. 154 * The connection to the DataSource.
113 * @private 155 * @private
114 */ 156 */
115 this.source_ = new dataStream.DataSourceProxy(this.router_); 157 this.source_ = new dataStream.DataSourceProxy(this.router_);
116 this.router_.setIncomingReceiver(this); 158 this.router_.setIncomingReceiver(this);
117 var dataPipeOptions = {
118 flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
119 elementNumBytes: 1,
120 capacityNumBytes: bufferSize,
121 };
122 var receivePipe = core.createDataPipe(dataPipeOptions);
123 this.source_.init(receivePipe.producerHandle);
124 /** 159 /**
125 * The handle to the data pipe to use for receiving data. 160 * The handle to the data pipe to use for receiving data.
126 * @private 161 * @private
127 */ 162 */
128 this.receivePipe_ = receivePipe.consumerHandle; 163 this.receivePipe_ = dataPipe;
129 /** 164 /**
130 * The current receive operation. 165 * The current receive operation.
131 * @type {module:data_receiver~PendingReceive} 166 * @type {module:data_receiver~PendingReceive}
132 * @private 167 * @private
133 */ 168 */
134 this.receive_ = null; 169 this.receive_ = null;
135 /** 170 /**
136 * The error to be dispatched in the event of a fatal error. 171 * The error to be dispatched in the event of a fatal error.
137 * @type {number} 172 * @const {number}
138 * @private 173 * @private
139 */ 174 */
140 this.fatalErrorValue_ = fatalErrorValue; 175 this.fatalErrorValue_ = fatalErrorValue;
141 /** 176 /**
142 * The async waiter used to wait for 177 * The async waiter used to wait for
143 * {@link module:data_receiver.DataReceiver#receivePipe_} to be readable. 178 * |[receivePipe_]{@link module:data_receiver.DataReceiver#receivePipe_}| to
144 * @type module:async_waiter.AsyncWaiter 179 * be readable.
180 * @type {!module:async_waiter.AsyncWaiter}
145 * @private 181 * @private
146 */ 182 */
147 this.waiter_ = new asyncWaiter.AsyncWaiter(this.receivePipe_, 183 this.waiter_ = new asyncWaiter.AsyncWaiter(this.receivePipe_,
148 core.HANDLE_SIGNAL_READABLE, 184 core.HANDLE_SIGNAL_READABLE,
149 this.onHandleReady_.bind(this)); 185 this.onHandleReady_.bind(this));
150 /** 186 /**
151 * The number of bytes received from the DataSource. 187 * The number of bytes received from the DataSource.
152 * @type {number} 188 * @type {number}
153 * @private 189 * @private
154 */ 190 */
155 this.bytesReceived_ = 0; 191 this.bytesReceived_ = bytesReceived;
156 /** 192 /**
157 * The pending error if there is one. 193 * The pending error if there is one.
158 * @type module:data_receiver~PendingError 194 * @type {PendingReceiveError}
159 * @private 195 * @private
160 */ 196 */
161 this.pendingError_ = null; 197 this.pendingError_ = pendingError;
162 /** 198 /**
163 * Whether the DataSource is paused. 199 * Whether the DataSource is paused.
164 * @type {boolean} 200 * @type {boolean}
165 * @private 201 * @private
166 */ 202 */
167 this.paused_ = false; 203 this.paused_ = paused;
168 /** 204 /**
169 * Whether this DataReceiver has shut down. 205 * Whether this DataReceiver has shut down.
170 * @type {boolean} 206 * @type {boolean}
171 * @private 207 * @private
172 */ 208 */
173 this.shutDown_ = false; 209 this.shutDown_ = false;
174 } 210 };
175
176 DataReceiver.prototype =
177 $Object.create(dataStream.DataSourceClientStub.prototype);
178 211
179 /** 212 /**
180 * Closes this DataReceiver. 213 * Serializes this DataReceiver.
214 * This will cancel a receive if one is in progress.
215 * @return {!Promise.<SerializedDataReceiver>} A promise that will resolve to
216 * the serialization of this DataReceiver. If this DataReceiver has shut
217 * down, the promise will resolve to null.
181 */ 218 */
182 DataReceiver.prototype.close = function() { 219 DataReceiver.prototype.serialize = function() {
183 if (this.shutDown_) 220 if (this.shutDown_)
184 return; 221 return Promise.resolve(null);
185 this.shutDown_ = true; 222
186 this.router_.close();
187 this.waiter_.stop(); 223 this.waiter_.stop();
188 core.close(this.receivePipe_);
189 if (this.receive_) { 224 if (this.receive_) {
190 this.receive_.dispatchFatalError(this.fatalErrorValue_); 225 this.receive_.dispatchFatalError(this.fatalErrorValue_);
191 this.receive_ = null; 226 this.receive_ = null;
192 } 227 }
228 var serialized = new serialization.SerializedDataReceiver();
229 serialized.source = this.router_.connector_.handle_;
230 serialized.data_pipe = this.receivePipe_;
231 serialized.fatal_error_value = this.fatalErrorValue_;
232 serialized.bytes_received = this.bytesReceived_;
233 serialized.paused = this.paused_;
234 serialized.pending_error = this.pendingError_;
235 this.router_.connector_.handle_ = null;
236 this.router_.close();
237 this.shutDown_ = true;
238 return Promise.resolve(serialized);
193 }; 239 };
194 240
195 /** 241 /**
242 * Deserializes a SerializedDataReceiver.
243 * @param {SerializedDataReceiver} serialized The serialized DataReceiver.
244 * @return {!DataReceiver} The deserialized DataReceiver.
245 */
246 DataReceiver.deserialize = function(serialized) {
247 var receiver = $Object.create(DataReceiver.prototype);
248 receiver.deserialize_(serialized);
249 return receiver;
250 };
251
252 /**
253 * Deserializes a SerializedDataReceiver into this DataReceiver.
254 * @param {SerializedDataReceiver} serialized The serialized DataReceiver.
255 * @private
256 */
257 DataReceiver.prototype.deserialize_ = function(serialized) {
258 if (!serialized) {
259 this.shutDown_ = true;
260 return;
261 }
262 this.init_(serialized.source,
263 serialized.data_pipe,
264 serialized.fatal_error_value,
265 serialized.bytes_received,
266 serialized.pending_error,
267 serialized.paused);
268 };
269
270 /**
196 * Receive data from the DataSource. 271 * Receive data from the DataSource.
197 * @return {Promise.<ArrayBuffer>} A promise to the received data. If an error 272 * @return {Promise.<ArrayBuffer>} A promise to the received data. If an error
198 * occurs, the promise will reject with an Error object with a property 273 * occurs, the promise will reject with an Error object with a property
199 * error containing the error code. 274 * error containing the error code.
200 * @throws Will throw if this has encountered a fatal error or another receive 275 * @throws Will throw if this has encountered a fatal error or another receive
201 * is in progress. 276 * is in progress.
202 */ 277 */
203 DataReceiver.prototype.receive = function() { 278 DataReceiver.prototype.receive = function() {
204 if (this.shutDown_) 279 if (this.shutDown_)
205 throw new Error('System error'); 280 throw new Error('DataReceiver has been closed');
206 if (this.receive_) 281 if (this.receive_)
207 throw new Error('Receive already in progress.'); 282 throw new Error('Receive already in progress.');
208 var receive = new PendingReceive(); 283 var receive = new PendingReceive();
209 var promise = receive.getPromise(); 284 var promise = receive.getPromise();
210 if (this.pendingError_ && 285 if (this.pendingError_ &&
211 receive.dispatchError(this.pendingError_, this.bytesReceived_)) { 286 receive.dispatchError(this.pendingError_, this.bytesReceived_)) {
212 this.pendingError_ = null; 287 this.pendingError_ = null;
213 this.paused_ = true; 288 this.paused_ = true;
214 return promise; 289 return promise;
215 } 290 }
216 if (this.paused_) { 291 if (this.paused_) {
217 this.source_.resume(); 292 this.source_.resume();
218 this.paused_ = false; 293 this.paused_ = false;
219 } 294 }
220 this.receive_ = receive; 295 this.receive_ = receive;
221 this.waiter_.start(); 296 this.waiter_.start();
222 return promise; 297 return promise;
223 }; 298 };
224 299
225 /** 300 /**
226 * Invoked when |handle_| is ready to read. Reads from the data pipe if the 301 * Invoked when
227 * wait is successful. 302 * |[receivePipe_]{@link module:data_receiver.DataReceiver#receivePipe_}| is
303 * ready to read. Reads from the data pipe if the wait is successful.
228 * @param {number} waitResult The result of the asynchronous wait. 304 * @param {number} waitResult The result of the asynchronous wait.
229 * @private 305 * @private
230 */ 306 */
231 DataReceiver.prototype.onHandleReady_ = function(waitResult) { 307 DataReceiver.prototype.onHandleReady_ = function(waitResult) {
232 if (waitResult != core.RESULT_OK || !this.receive_) { 308 if (waitResult != core.RESULT_OK || !this.receive_) {
233 this.close(); 309 this.close();
234 return; 310 return;
235 } 311 }
236 var result = core.readData(this.receivePipe_, core.READ_DATA_FLAG_NONE); 312 var result = core.readData(this.receivePipe_, core.READ_DATA_FLAG_NONE);
237 if (result.result == core.RESULT_OK) { 313 if (result.result == core.RESULT_OK) {
(...skipping 11 matching lines...) Expand all
249 /** 325 /**
250 * Invoked by the DataSource when an error is encountered. 326 * Invoked by the DataSource when an error is encountered.
251 * @param {number} offset The location at which the error occurred. 327 * @param {number} offset The location at which the error occurred.
252 * @param {number} error The error that occurred. 328 * @param {number} error The error that occurred.
253 * @private 329 * @private
254 */ 330 */
255 DataReceiver.prototype.onError = function(offset, error) { 331 DataReceiver.prototype.onError = function(offset, error) {
256 if (this.shutDown_) 332 if (this.shutDown_)
257 return; 333 return;
258 334
259 /** 335 var pendingError = new serialization.PendingReceiveError();
260 * @type module:data_receiver~PendingError 336 pendingError.error = error;
261 */ 337 pendingError.offset = offset;
262 var pendingError = {
263 error: error,
264 offset: offset,
265 };
266 if (this.receive_ && 338 if (this.receive_ &&
267 this.receive_.dispatchError(pendingError, this.bytesReceived_)) { 339 this.receive_.dispatchError(pendingError, this.bytesReceived_)) {
268 this.receive_ = null; 340 this.receive_ = null;
269 this.waiter_.stop(); 341 this.waiter_.stop();
270 this.paused_ = true; 342 this.paused_ = true;
271 return; 343 return;
272 } 344 }
273 this.pendingError_ = pendingError; 345 this.pendingError_ = pendingError;
274 }; 346 };
275 347
276 return {DataReceiver: DataReceiver}; 348 return {DataReceiver: DataReceiver};
277 }); 349 });
OLDNEW
« no previous file with comments | « extensions/renderer/resources/async_waiter.js ('k') | extensions/renderer/resources/data_sender.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698