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

Side by Side Diff: third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp

Issue 2496933002: XMLHttpRequest: implement "send() flag" tracking and updating per spec. (Closed)
Patch Set: add missing field initialization Created 4 years, 1 month 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 | « third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h ('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 /* 1 /*
2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org> 3 * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org>
4 * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org> 4 * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org>
5 * Copyright (C) 2008, 2011 Google Inc. All rights reserved. 5 * Copyright (C) 2008, 2011 Google Inc. All rights reserved.
6 * Copyright (C) 2012 Intel Corporation 6 * Copyright (C) 2012 Intel Corporation
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public 9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 m_isolatedWorldSecurityOrigin(isolatedWorldSecurityOrigin), 239 m_isolatedWorldSecurityOrigin(isolatedWorldSecurityOrigin),
240 m_eventDispatchRecursionLevel(0), 240 m_eventDispatchRecursionLevel(0),
241 m_async(true), 241 m_async(true),
242 m_includeCredentials(false), 242 m_includeCredentials(false),
243 m_parsedResponse(false), 243 m_parsedResponse(false),
244 m_error(false), 244 m_error(false),
245 m_uploadEventsAllowed(true), 245 m_uploadEventsAllowed(true),
246 m_uploadComplete(false), 246 m_uploadComplete(false),
247 m_sameOriginRequest(true), 247 m_sameOriginRequest(true),
248 m_downloadingToFile(false), 248 m_downloadingToFile(false),
249 m_responseTextOverflow(false) {} 249 m_responseTextOverflow(false),
250 m_sendFlag(false) {}
250 251
251 XMLHttpRequest::~XMLHttpRequest() {} 252 XMLHttpRequest::~XMLHttpRequest() {}
252 253
253 Document* XMLHttpRequest::document() const { 254 Document* XMLHttpRequest::document() const {
254 DCHECK(getExecutionContext()->isDocument()); 255 DCHECK(getExecutionContext()->isDocument());
255 return toDocument(getExecutionContext()); 256 return toDocument(getExecutionContext());
256 } 257 }
257 258
258 SecurityOrigin* XMLHttpRequest::getSecurityOrigin() const { 259 SecurityOrigin* XMLHttpRequest::getSecurityOrigin() const {
259 return m_isolatedWorldSecurityOrigin 260 return m_isolatedWorldSecurityOrigin
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 dispatchProgressEventFromSnapshot(EventTypeNames::load); 546 dispatchProgressEventFromSnapshot(EventTypeNames::load);
546 dispatchProgressEventFromSnapshot(EventTypeNames::loadend); 547 dispatchProgressEventFromSnapshot(EventTypeNames::loadend);
547 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), 548 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
548 "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", 549 "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data",
549 InspectorUpdateCountersEvent::data()); 550 InspectorUpdateCountersEvent::data());
550 } 551 }
551 } 552 }
552 553
553 void XMLHttpRequest::setWithCredentials(bool value, 554 void XMLHttpRequest::setWithCredentials(bool value,
554 ExceptionState& exceptionState) { 555 ExceptionState& exceptionState) {
555 if (m_state > kOpened || m_loader) { 556 if (m_state > kOpened || m_sendFlag) {
556 exceptionState.throwDOMException( 557 exceptionState.throwDOMException(
557 InvalidStateError, 558 InvalidStateError,
558 "The value may only be set if the object's state is UNSENT or OPENED."); 559 "The value may only be set if the object's state is UNSENT or OPENED.");
559 return; 560 return;
560 } 561 }
561 562
562 m_includeCredentials = value; 563 m_includeCredentials = value;
563 } 564 }
564 565
565 void XMLHttpRequest::open(const AtomicString& method, 566 void XMLHttpRequest::open(const AtomicString& method,
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 UseCounter::XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload); 662 UseCounter::XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload);
662 } 663 }
663 664
664 m_method = FetchUtils::normalizeMethod(method); 665 m_method = FetchUtils::normalizeMethod(method);
665 666
666 m_url = url; 667 m_url = url;
667 668
668 m_async = async; 669 m_async = async;
669 670
670 DCHECK(!m_loader); 671 DCHECK(!m_loader);
672 m_sendFlag = false;
671 673
672 // Check previous state to avoid dispatching readyState event 674 // Check previous state to avoid dispatching readyState event
673 // when calling open several times in a row. 675 // when calling open several times in a row.
674 if (previousState != kOpened) 676 if (previousState != kOpened)
675 changeState(kOpened); 677 changeState(kOpened);
676 else 678 else
677 m_state = kOpened; 679 m_state = kOpened;
678 } 680 }
679 681
680 bool XMLHttpRequest::initSend(ExceptionState& exceptionState) { 682 bool XMLHttpRequest::initSend(ExceptionState& exceptionState) {
681 if (!getExecutionContext()) { 683 if (!getExecutionContext()) {
682 handleNetworkError(); 684 handleNetworkError();
683 throwForLoadFailureIfNeeded(exceptionState, 685 throwForLoadFailureIfNeeded(exceptionState,
684 "Document is already detached."); 686 "Document is already detached.");
685 return false; 687 return false;
686 } 688 }
687 689
688 if (m_state != kOpened || m_loader) { 690 if (m_state != kOpened || m_sendFlag) {
689 exceptionState.throwDOMException(InvalidStateError, 691 exceptionState.throwDOMException(InvalidStateError,
690 "The object's state must be OPENED."); 692 "The object's state must be OPENED.");
691 return false; 693 return false;
692 } 694 }
693 695
694 if (!m_async) { 696 if (!m_async) {
695 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 697 v8::Isolate* isolate = v8::Isolate::GetCurrent();
696 if (isolate && v8::MicrotasksScope::IsRunningMicrotasks(isolate)) { 698 if (isolate && v8::MicrotasksScope::IsRunningMicrotasks(isolate)) {
697 UseCounter::count(getExecutionContext(), 699 UseCounter::count(getExecutionContext(),
698 UseCounter::During_Microtask_SyncXHR); 700 UseCounter::During_Microtask_SyncXHR);
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 if (!m_async) { 924 if (!m_async) {
923 throwForLoadFailureIfNeeded( 925 throwForLoadFailureIfNeeded(
924 exceptionState, "'GET' is the only method allowed for 'blob:' URLs."); 926 exceptionState, "'GET' is the only method allowed for 'blob:' URLs.");
925 } 927 }
926 return; 928 return;
927 } 929 }
928 930
929 DCHECK(getExecutionContext()); 931 DCHECK(getExecutionContext());
930 ExecutionContext& executionContext = *getExecutionContext(); 932 ExecutionContext& executionContext = *getExecutionContext();
931 933
934 m_sendFlag = true;
932 // The presence of upload event listeners forces us to use preflighting 935 // The presence of upload event listeners forces us to use preflighting
933 // because POSTing to an URL that does not permit cross origin requests should 936 // because POSTing to an URL that does not permit cross origin requests should
934 // look exactly like POSTing to an URL that does not respond at all. 937 // look exactly like POSTing to an URL that does not respond at all.
935 // Also, only async requests support upload progress events. 938 // Also, only async requests support upload progress events.
936 bool uploadEvents = false; 939 bool uploadEvents = false;
937 if (m_async) { 940 if (m_async) {
938 InspectorInstrumentation::asyncTaskScheduled( 941 InspectorInstrumentation::asyncTaskScheduled(
939 &executionContext, "XMLHttpRequest.send", this, true); 942 &executionContext, "XMLHttpRequest.send", this, true);
940 dispatchProgressEvent(EventTypeNames::loadstart, 0, 0); 943 dispatchProgressEvent(EventTypeNames::loadstart, 0, 0);
941 if (httpBody && m_upload) { 944 if (httpBody && m_upload) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 m_exceptionCode = 0; 1028 m_exceptionCode = 0;
1026 m_error = false; 1029 m_error = false;
1027 1030
1028 if (m_async) { 1031 if (m_async) {
1029 UseCounter::count(&executionContext, 1032 UseCounter::count(&executionContext,
1030 UseCounter::XMLHttpRequestAsynchronous); 1033 UseCounter::XMLHttpRequestAsynchronous);
1031 if (m_upload) 1034 if (m_upload)
1032 request.setReportUploadProgress(true); 1035 request.setReportUploadProgress(true);
1033 1036
1034 DCHECK(!m_loader); 1037 DCHECK(!m_loader);
1038 DCHECK(m_sendFlag);
1035 m_loader = ThreadableLoader::create(executionContext, this, options, 1039 m_loader = ThreadableLoader::create(executionContext, this, options,
1036 resourceLoaderOptions); 1040 resourceLoaderOptions);
1037 m_loader->start(request); 1041 m_loader->start(request);
1038 1042
1039 return; 1043 return;
1040 } 1044 }
1041 1045
1042 // Use count for XHR synchronous requests. 1046 // Use count for XHR synchronous requests.
1043 UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous); 1047 UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous);
1044 ThreadableLoader::loadResourceSynchronously(executionContext, request, *this, 1048 ThreadableLoader::loadResourceSynchronously(executionContext, request, *this,
1045 options, resourceLoaderOptions); 1049 options, resourceLoaderOptions);
1046 1050
1047 throwForLoadFailureIfNeeded(exceptionState, String()); 1051 throwForLoadFailureIfNeeded(exceptionState, String());
1048 } 1052 }
1049 1053
1050 void XMLHttpRequest::abort() { 1054 void XMLHttpRequest::abort() {
1051 NETWORK_DVLOG(1) << this << " abort()"; 1055 NETWORK_DVLOG(1) << this << " abort()";
1052 1056
1053 // internalAbort() clears |m_loader|. Compute |sendFlag| now.
1054 //
1055 // |sendFlag| corresponds to "the send() flag" defined in the XHR spec.
1056 //
1057 // |sendFlag| is only set when we have an active, asynchronous loader.
1058 // Don't use it as "the send() flag" when the XHR is in sync mode.
1059 bool sendFlag = m_loader.get();
1060
1061 // internalAbort() clears the response. Save the data needed for 1057 // internalAbort() clears the response. Save the data needed for
1062 // dispatching ProgressEvents. 1058 // dispatching ProgressEvents.
1063 long long expectedLength = m_response.expectedContentLength(); 1059 long long expectedLength = m_response.expectedContentLength();
1064 long long receivedLength = m_receivedLength; 1060 long long receivedLength = m_receivedLength;
1065 1061
1066 if (!internalAbort()) 1062 if (!internalAbort())
1067 return; 1063 return;
1068 1064
1069 // The script never gets any chance to call abort() on a sync XHR between 1065 // The script never gets any chance to call abort() on a sync XHR between
1070 // send() call and transition to the DONE state. It's because a sync XHR 1066 // send() call and transition to the DONE state. It's because a sync XHR
1071 // doesn't dispatch any event between them. So, if |m_async| is false, we 1067 // doesn't dispatch any event between them. So, if |m_async| is false, we
1072 // can skip the "request error steps" (defined in the XHR spec) without any 1068 // can skip the "request error steps" (defined in the XHR spec) without any
1073 // state check. 1069 // state check.
1074 // 1070 //
1075 // FIXME: It's possible open() is invoked in internalAbort() and |m_async| 1071 // FIXME: It's possible open() is invoked in internalAbort() and |m_async|
1076 // becomes true by that. We should implement more reliable treatment for 1072 // becomes true by that. We should implement more reliable treatment for
1077 // nested method invocations at some point. 1073 // nested method invocations at some point.
1078 if (m_async) { 1074 if (m_async) {
1079 if ((m_state == kOpened && sendFlag) || m_state == kHeadersReceived || 1075 if ((m_state == kOpened && m_sendFlag) || m_state == kHeadersReceived ||
1080 m_state == kLoading) { 1076 m_state == kLoading) {
1081 DCHECK(!m_loader); 1077 DCHECK(!m_loader);
1082 handleRequestError(0, EventTypeNames::abort, receivedLength, 1078 handleRequestError(0, EventTypeNames::abort, receivedLength,
1083 expectedLength); 1079 expectedLength);
1084 } 1080 }
1085 } 1081 }
1086 m_state = kUnsent; 1082 m_state = kUnsent;
1087 } 1083 }
1088 1084
1089 void XMLHttpRequest::clearVariablesForLoading() { 1085 void XMLHttpRequest::clearVariablesForLoading() {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 1214
1219 void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, 1215 void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode,
1220 const AtomicString& type, 1216 const AtomicString& type,
1221 long long receivedLength, 1217 long long receivedLength,
1222 long long expectedLength) { 1218 long long expectedLength) {
1223 NETWORK_DVLOG(1) << this << " handleRequestError()"; 1219 NETWORK_DVLOG(1) << this << " handleRequestError()";
1224 1220
1225 InspectorInstrumentation::didFailXHRLoading(getExecutionContext(), this, this, 1221 InspectorInstrumentation::didFailXHRLoading(getExecutionContext(), this, this,
1226 m_method, m_url); 1222 m_method, m_url);
1227 1223
1224 m_sendFlag = false;
1228 if (!m_async) { 1225 if (!m_async) {
1229 DCHECK(exceptionCode); 1226 DCHECK(exceptionCode);
1230 m_state = kDone; 1227 m_state = kDone;
1231 m_exceptionCode = exceptionCode; 1228 m_exceptionCode = exceptionCode;
1232 return; 1229 return;
1233 } 1230 }
1234 1231
1235 // With m_error set, the state change steps are minimal: any pending 1232 // With m_error set, the state change steps are minimal: any pending
1236 // progress event is flushed + a readystatechange is dispatched. 1233 // progress event is flushed + a readystatechange is dispatched.
1237 // No new progress events dispatched; as required, that happens at 1234 // No new progress events dispatched; as required, that happens at
(...skipping 26 matching lines...) Expand all
1264 "MimeType cannot be overridden when the state is LOADING or DONE."); 1261 "MimeType cannot be overridden when the state is LOADING or DONE.");
1265 return; 1262 return;
1266 } 1263 }
1267 1264
1268 m_mimeTypeOverride = mimeType; 1265 m_mimeTypeOverride = mimeType;
1269 } 1266 }
1270 1267
1271 void XMLHttpRequest::setRequestHeader(const AtomicString& name, 1268 void XMLHttpRequest::setRequestHeader(const AtomicString& name,
1272 const AtomicString& value, 1269 const AtomicString& value,
1273 ExceptionState& exceptionState) { 1270 ExceptionState& exceptionState) {
1274 if (m_state != kOpened || m_loader) { 1271 if (m_state != kOpened || m_sendFlag) {
1275 exceptionState.throwDOMException(InvalidStateError, 1272 exceptionState.throwDOMException(InvalidStateError,
1276 "The object's state must be OPENED."); 1273 "The object's state must be OPENED.");
1277 return; 1274 return;
1278 } 1275 }
1279 1276
1280 if (!isValidHTTPToken(name)) { 1277 if (!isValidHTTPToken(name)) {
1281 exceptionState.throwDOMException( 1278 exceptionState.throwDOMException(
1282 SyntaxError, "'" + name + "' is not a valid HTTP header field name."); 1279 SyntaxError, "'" + name + "' is not a valid HTTP header field name.");
1283 return; 1280 return;
1284 } 1281 }
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 if (m_loader) { 1599 if (m_loader) {
1603 const bool hasError = m_error; 1600 const bool hasError = m_error;
1604 // Set |m_error| in order to suppress the cancel notification (see 1601 // Set |m_error| in order to suppress the cancel notification (see
1605 // XMLHttpRequest::didFail). 1602 // XMLHttpRequest::didFail).
1606 m_error = true; 1603 m_error = true;
1607 m_loader->cancel(); 1604 m_loader->cancel();
1608 m_error = hasError; 1605 m_error = hasError;
1609 m_loader = nullptr; 1606 m_loader = nullptr;
1610 } 1607 }
1611 1608
1609 m_sendFlag = false;
1612 changeState(kDone); 1610 changeState(kDone);
1613 1611
1614 if (!getExecutionContext() || !getExecutionContext()->isDocument() || 1612 if (!getExecutionContext() || !getExecutionContext()->isDocument() ||
1615 !document() || !document()->frame() || !document()->frame()->page()) 1613 !document() || !document()->frame() || !document()->frame()->page())
1616 return; 1614 return;
1617 1615
1618 if (status() >= 200 && status() < 300) { 1616 if (status() >= 200 && status() < 300) {
1619 document()->frame()->page()->chromeClient().ajaxSucceeded( 1617 document()->frame()->page()->chromeClient().ajaxSucceeded(
1620 document()->frame()); 1618 document()->frame());
1621 } 1619 }
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1841 visitor->traceWrappers(m_responseDocument); 1839 visitor->traceWrappers(m_responseDocument);
1842 visitor->traceWrappers(m_responseArrayBuffer); 1840 visitor->traceWrappers(m_responseArrayBuffer);
1843 XMLHttpRequestEventTarget::traceWrappers(visitor); 1841 XMLHttpRequestEventTarget::traceWrappers(visitor);
1844 } 1842 }
1845 1843
1846 std::ostream& operator<<(std::ostream& ostream, const XMLHttpRequest* xhr) { 1844 std::ostream& operator<<(std::ostream& ostream, const XMLHttpRequest* xhr) {
1847 return ostream << "XMLHttpRequest " << static_cast<const void*>(xhr); 1845 return ostream << "XMLHttpRequest " << static_cast<const void*>(xhr);
1848 } 1846 }
1849 1847
1850 } // namespace blink 1848 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698