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

Side by Side Diff: tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate

Issue 2042033002: Add zone task support to http-requests. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comments. Created 4 years, 5 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
« no previous file with comments | « tools/dom/scripts/htmlrenamer.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of $LIBRARYNAME; 5 part of $LIBRARYNAME;
6 6
7 /**
8 * A task specification for HTTP requests.
9 *
10 * This specification is not available when an HTTP request is sent through
11 * direct use of [HttpRequest.send]. See [HttpRequestSendTaskSpecification].
12 *
13 * A task created from this specification is a `Future<HttpRequest>`.
14 *
15 * *Experimental*. This class may disappear without notice.
16 */
17 class HttpRequestTaskSpecification extends TaskSpecification {
18 /// The URL of the request.
19 final String url;
20
21 /// The HTTP request method.
22 ///
23 /// By default (when `null`) this is a `"GET"` request. Alternatively, the
24 /// method can be `"POST"`, `"PUT"`, `"DELETE"`, etc.
25 final String method;
26
27 /// Whether the request should send credentials. Credentials are only useful
28 /// for cross-origin requests.
29 ///
30 /// See [HttpRequest.request] for more information.
31 final bool withCredentials;
32
33 /// The desired response format.
34 ///
35 /// Supported types are:
36 /// - `""`: (same as `"text"`),
37 /// - `"arraybuffer"`,
38 /// - `"blob"`,
39 /// - `"document"`,
40 /// - `"json"`,
41 /// - `"text"`
42 ///
43 /// When no value is provided (when equal to `null`) defaults to `""`.
44 final String responseType;
45
46 /// The desired MIME type.
47 ///
48 /// This overrides the default MIME type which is set up to transfer textual
49 /// data.
50 final String mimeType;
51
52 /// The request headers that should be sent with the request.
53 final Map<String, String> requestHeaders;
54
55 /// The data that is sent with the request.
56 ///
57 /// When data is provided (the value is not `null`), it must be a
58 /// [ByteBuffer], [Blob], [Document], [String], or [FormData].
59 final dynamic sendData;
60
61 /// The function that is invoked on progress updates. This function is
62 /// registered as an event listener on the created [HttpRequest] object, and
63 /// thus has its own task. Further invocations of the progress function do
64 /// *not* use the HTTP request task as task object.
65 ///
66 /// Creating an HTTP request automatically registers the on-progress listener.
67 final ZoneUnaryCallback<dynamic, ProgressEvent> onProgress;
68
69 HttpRequestTaskSpecification(this.url,
70 {String this.method, bool this.withCredentials, String this.responseType,
71 String this.mimeType, Map<String, String> this.requestHeaders,
72 this.sendData,
73 void this.onProgress(ProgressEvent e)});
74
75 String get name => "dart.html.http-request";
76 bool get isOneShot => true;
77 }
78
79 /**
80 * A task specification for HTTP requests that are initiated through a direct
81 * invocation of [HttpRequest.send].
82 *
83 * This specification serves as signal to zones that an HTTP request has been
84 * initiated. The created task is the [request] object itself, and
85 * no callback is ever executed in this task.
86 *
87 * Note that event listeners on the HTTP request are also registered in the
88 * zone (although with their own task creations), and that a zone can thus
89 * detect when the HTTP request returns.
90 *
91 * HTTP requests that are initiated through `request` methods don't use
92 * this class but use [HttpRequestTaskSpecification].
93 *
94 * *Experimental*. This class may disappear without notice.
95 */
96 class HttpRequestSendTaskSpecification extends TaskSpecification {
97 final HttpRequest request;
98 final dynamic sendData;
99
100 HttpRequestSendTaskSpecification(this.request, this.sendData);
101
102 String get name => "dart.html.http-request-send";
103
104 /**
105 * No callback is ever executed in an HTTP request send task.
106 */
107 bool get isOneShot => false;
108 }
109
7 /** 110 /**
8 * A client-side XHR request for getting data from a URL, 111 * A client-side XHR request for getting data from a URL,
9 * formally known as XMLHttpRequest. 112 * formally known as XMLHttpRequest.
10 * 113 *
11 * HttpRequest can be used to obtain data from HTTP and FTP protocols, 114 * HttpRequest can be used to obtain data from HTTP and FTP protocols,
12 * and is useful for AJAX-style page updates. 115 * and is useful for AJAX-style page updates.
13 * 116 *
14 * The simplest way to get the contents of a text file, such as a 117 * The simplest way to get the contents of a text file, such as a
15 * JSON-formatted file, is with [getString]. 118 * JSON-formatted file, is with [getString].
16 * For example, the following code gets the contents of a JSON file 119 * For example, the following code gets the contents of a JSON file
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 * with appropriate permissions in their manifest. Requests to file:// URIs 286 * with appropriate permissions in their manifest. Requests to file:// URIs
184 * will also never fail- the Future will always complete successfully, even 287 * will also never fail- the Future will always complete successfully, even
185 * when the file cannot be found. 288 * when the file cannot be found.
186 * 289 *
187 * See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access _authentication). 290 * See also: [authorization headers](http://en.wikipedia.org/wiki/Basic_access _authentication).
188 */ 291 */
189 static Future<HttpRequest> request(String url, 292 static Future<HttpRequest> request(String url,
190 {String method, bool withCredentials, String responseType, 293 {String method, bool withCredentials, String responseType,
191 String mimeType, Map<String, String> requestHeaders, sendData, 294 String mimeType, Map<String, String> requestHeaders, sendData,
192 void onProgress(ProgressEvent e)}) { 295 void onProgress(ProgressEvent e)}) {
296 var spec = new HttpRequestTaskSpecification(
297 url, method: method,
298 withCredentials: withCredentials,
299 responseType: responseType,
300 mimeType: mimeType,
301 requestHeaders: requestHeaders,
302 sendData: sendData,
303 onProgress: onProgress);
304
305 if (identical(Zone.current, Zone.ROOT)) {
306 return _createHttpRequestTask(spec, null);
307 }
308 return Zone.current.createTask(_createHttpRequestTask, spec);
309 }
310
311 static Future<HttpRequest> _createHttpRequestTask(
312 HttpRequestTaskSpecification spec, Zone zone) {
313 String url = spec.url;
314 String method = spec.method;
315 bool withCredentials = spec.withCredentials;
316 String responseType = spec.responseType;
317 String mimeType = spec.mimeType;
318 Map<String, String> requestHeaders = spec.requestHeaders;
319 var sendData = spec.sendData;
320 var onProgress = spec.onProgress;
321
193 var completer = new Completer<HttpRequest>(); 322 var completer = new Completer<HttpRequest>();
323 var task = completer.future;
194 324
195 var xhr = new HttpRequest(); 325 var xhr = new HttpRequest();
196 if (method == null) { 326 if (method == null) {
197 method = 'GET'; 327 method = 'GET';
198 } 328 }
199 xhr.open(method, url, async: true); 329 xhr.open(method, url, async: true);
200 330
201 if (withCredentials != null) { 331 if (withCredentials != null) {
202 xhr.withCredentials = withCredentials; 332 xhr.withCredentials = withCredentials;
203 } 333 }
(...skipping 19 matching lines...) Expand all
223 xhr.onLoad.listen((e) { 353 xhr.onLoad.listen((e) {
224 var accepted = xhr.status >= 200 && xhr.status < 300; 354 var accepted = xhr.status >= 200 && xhr.status < 300;
225 var fileUri = xhr.status == 0; // file:// URIs have status of 0. 355 var fileUri = xhr.status == 0; // file:// URIs have status of 0.
226 var notModified = xhr.status == 304; 356 var notModified = xhr.status == 304;
227 // Redirect status is specified up to 307, but others have been used in 357 // Redirect status is specified up to 307, but others have been used in
228 // practice. Notably Google Drive uses 308 Resume Incomplete for 358 // practice. Notably Google Drive uses 308 Resume Incomplete for
229 // resumable uploads, and it's also been used as a redirect. The 359 // resumable uploads, and it's also been used as a redirect. The
230 // redirect case will be handled by the browser before it gets to us, 360 // redirect case will be handled by the browser before it gets to us,
231 // so if we see it we should pass it through to the user. 361 // so if we see it we should pass it through to the user.
232 var unknownRedirect = xhr.status > 307 && xhr.status < 400; 362 var unknownRedirect = xhr.status > 307 && xhr.status < 400;
233 363
234 if (accepted || fileUri || notModified || unknownRedirect) { 364 var isSuccessful = accepted || fileUri || notModified || unknownRedirect;
365
366 if (zone == null && isSuccessful) {
235 completer.complete(xhr); 367 completer.complete(xhr);
368 } else if (zone == null) {
369 completer.completeError(e);
370 } else if (isSuccessful) {
371 zone.runTask((task, value) {
372 completer.complete(value);
373 }, task, xhr);
236 } else { 374 } else {
237 completer.completeError(e); 375 zone.runTask((task, error) {
376 completer.completeError(error);
377 }, task, e);
238 } 378 }
239 }); 379 });
240 380
241 xhr.onError.listen(completer.completeError); 381 if (zone == null) {
382 xhr.onError.listen(completer.completeError);
383 } else {
384 xhr.onError.listen((error) {
385 zone.runTask((task, error) {
386 completer.completeError(error);
387 }, task, error);
388 });
389 }
242 390
243 if (sendData != null) { 391 if (sendData != null) {
244 xhr.send(sendData); 392 // TODO(floitsch): should we go through 'send()' and have nested tasks?
393 xhr._send(sendData);
245 } else { 394 } else {
246 xhr.send(); 395 xhr._send();
247 } 396 }
248 397
249 return completer.future; 398 return task;
250 } 399 }
251 400
252 /** 401 /**
253 * Checks to see if the Progress event is supported on the current platform. 402 * Checks to see if the Progress event is supported on the current platform.
254 */ 403 */
255 static bool get supportsProgressEvent { 404 static bool get supportsProgressEvent {
256 $if DART2JS 405 $if DART2JS
257 var xhr = new HttpRequest(); 406 var xhr = new HttpRequest();
258 return JS('bool', '("onprogress" in #)', xhr); 407 return JS('bool', '("onprogress" in #)', xhr);
259 $else 408 $else
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 * cross-origin support is not required then [request] should be used instead. 458 * cross-origin support is not required then [request] should be used instead.
310 */ 459 */
311 @Experimental() 460 @Experimental()
312 static Future<String> requestCrossOrigin(String url, 461 static Future<String> requestCrossOrigin(String url,
313 {String method, String sendData}) { 462 {String method, String sendData}) {
314 if (supportsCrossOrigin) { 463 if (supportsCrossOrigin) {
315 return request(url, method: method, sendData: sendData).then((xhr) { 464 return request(url, method: method, sendData: sendData).then((xhr) {
316 return xhr.responseText; 465 return xhr.responseText;
317 }); 466 });
318 } 467 }
468 // TODO(floitsch): the following code doesn't go through task zones.
469 // Since 'XDomainRequest' is an IE9 feature we should probably just remove
470 // it.
319 $if DART2JS 471 $if DART2JS
320 var completer = new Completer<String>(); 472 var completer = new Completer<String>();
321 if (method == null) { 473 if (method == null) {
322 method = 'GET'; 474 method = 'GET';
323 } 475 }
324 var xhr = JS('var', 'new XDomainRequest()'); 476 var xhr = JS('var', 'new XDomainRequest()');
325 JS('', '#.open(#, #)', xhr, method, url); 477 JS('', '#.open(#, #)', xhr, method, url);
326 JS('', '#.onload = #', xhr, convertDartClosureToJS((e) { 478 JS('', '#.onload = #', xhr, convertDartClosureToJS((e) {
327 var response = JS('String', '#.responseText', xhr); 479 var response = JS('String', '#.responseText', xhr);
328 completer.complete(response); 480 completer.complete(response);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 * 541 *
390 * By default the request is done asyncronously, with no user or password 542 * By default the request is done asyncronously, with no user or password
391 * authentication information. If `async` is false, the request will be send 543 * authentication information. If `async` is false, the request will be send
392 * synchronously. 544 * synchronously.
393 * 545 *
394 * Calling `open` again on a currently active request is equivalent to 546 * Calling `open` again on a currently active request is equivalent to
395 * calling `abort`. 547 * calling `abort`.
396 * 548 *
397 * Note: Most simple HTTP requests can be accomplished using the [getString], 549 * Note: Most simple HTTP requests can be accomplished using the [getString],
398 * [request], [requestCrossOrigin], or [postFormData] methods. Use of this 550 * [request], [requestCrossOrigin], or [postFormData] methods. Use of this
399 * `open` method is intended only for more complext HTTP requests where 551 * `open` method is intended only for more complex HTTP requests where
400 * finer-grained control is needed. 552 * finer-grained control is needed.
401 */ 553 */
402 @DomName('XMLHttpRequest.open') 554 @DomName('XMLHttpRequest.open')
403 @DocsEditable() 555 @DocsEditable()
404 $if JSINTEROP 556 $if JSINTEROP
405 void open(String method, String url, {bool async, String user, String password }) { 557 void open(String method, String url, {bool async, String user, String password }) {
406 if (async == null && user == null && password == null) { 558 if (async == null && user == null && password == null) {
407 _blink.BlinkXMLHttpRequest.instance.open_Callback_2_(this, method, url); 559 _blink.BlinkXMLHttpRequest.instance.open_Callback_2_(this, method, url);
408 } else { 560 } else {
409 _blink.BlinkXMLHttpRequest.instance.open_Callback_5_(this, method, url, as ync, user, password); 561 _blink.BlinkXMLHttpRequest.instance.open_Callback_5_(this, method, url, as ync, user, password);
410 } 562 }
411 } 563 }
412 $else 564 $else
413 void open(String method, String url, {bool async, String user, String password }) native; 565 void open(String method, String url, {bool async, String user, String password }) native;
414 $endif 566 $endif
415 567
568 /**
569 * Sends the request with any given `data`.
570 *
571 * Note: Most simple HTTP requests can be accomplished using the [getString],
572 * [request], [requestCrossOrigin], or [postFormData] methods. Use of this
573 * `send` method is intended only for more complex HTTP requests where
574 * finer-grained control is needed.
575 *
576 * ## Other resources
577 *
578 * * [XMLHttpRequest.send](https://developer.mozilla.org/en-US/docs/DOM/XMLHtt pRequest#send%28%29)
579 * from MDN.
580 */
581 @DomName('XMLHttpRequest.send')
582 @DocsEditable()
583 void send([body_OR_data]) {
584 if (identical(Zone.current, Zone.ROOT)) {
585 _send(body_OR_data);
586 } else {
587 Zone.current.createTask(_createHttpRequestSendTask,
588 new HttpRequestSendTaskSpecification(this, body_OR_data));
589 }
590 }
591
592 static HttpRequest _createHttpRequestSendTask(
593 HttpRequestSendTaskSpecification spec, Zone zone) {
594 spec.request._send(spec.sendData);
595 return spec.request;
596 }
597
416 $!MEMBERS 598 $!MEMBERS
417 } 599 }
OLDNEW
« no previous file with comments | « tools/dom/scripts/htmlrenamer.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698