OLD | NEW |
---|---|
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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 m_exceptionCode(0), | 230 m_exceptionCode(0), |
231 m_progressEventThrottle( | 231 m_progressEventThrottle( |
232 XMLHttpRequestProgressEventThrottle::create(this)), | 232 XMLHttpRequestProgressEventThrottle::create(this)), |
233 m_responseTypeCode(ResponseTypeDefault), | 233 m_responseTypeCode(ResponseTypeDefault), |
234 m_isolatedWorldSecurityOrigin(isolatedWorldSecurityOrigin), | 234 m_isolatedWorldSecurityOrigin(isolatedWorldSecurityOrigin), |
235 m_eventDispatchRecursionLevel(0), | 235 m_eventDispatchRecursionLevel(0), |
236 m_async(true), | 236 m_async(true), |
237 m_includeCredentials(false), | 237 m_includeCredentials(false), |
238 m_parsedResponse(false), | 238 m_parsedResponse(false), |
239 m_error(false), | 239 m_error(false), |
240 m_uploadEventsAllowed(true), | 240 m_uploadListenerFlag(false), |
241 m_uploadComplete(false), | 241 m_uploadCompleteFlag(false), |
242 m_sameOriginRequest(true), | 242 m_sameOriginRequest(true), |
243 m_downloadingToFile(false), | 243 m_downloadingToFile(false), |
244 m_responseTextOverflow(false) {} | 244 m_responseTextOverflow(false) {} |
245 | 245 |
246 XMLHttpRequest::~XMLHttpRequest() {} | 246 XMLHttpRequest::~XMLHttpRequest() {} |
247 | 247 |
248 Document* XMLHttpRequest::document() const { | 248 Document* XMLHttpRequest::document() const { |
249 DCHECK(getExecutionContext()->isDocument()); | 249 DCHECK(getExecutionContext()->isDocument()); |
250 return toDocument(getExecutionContext()); | 250 return toDocument(getExecutionContext()); |
251 } | 251 } |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
615 << ", " << async << ")"; | 615 << ", " << async << ")"; |
616 | 616 |
617 DCHECK(validateOpenArguments(method, url, exceptionState)); | 617 DCHECK(validateOpenArguments(method, url, exceptionState)); |
618 | 618 |
619 if (!internalAbort()) | 619 if (!internalAbort()) |
620 return; | 620 return; |
621 | 621 |
622 State previousState = m_state; | 622 State previousState = m_state; |
623 m_state = kUnsent; | 623 m_state = kUnsent; |
624 m_error = false; | 624 m_error = false; |
625 m_uploadComplete = false; | 625 m_uploadCompleteFlag = false; |
626 | 626 |
627 if (!ContentSecurityPolicy::shouldBypassMainWorld(getExecutionContext()) && | 627 if (!ContentSecurityPolicy::shouldBypassMainWorld(getExecutionContext()) && |
628 !getExecutionContext()->contentSecurityPolicy()->allowConnectToSource( | 628 !getExecutionContext()->contentSecurityPolicy()->allowConnectToSource( |
629 url)) { | 629 url)) { |
630 // We can safely expose the URL to JavaScript, as these checks happen | 630 // We can safely expose the URL to JavaScript, as these checks happen |
631 // synchronously before redirection. JavaScript receives no new information. | 631 // synchronously before redirection. JavaScript receives no new information. |
632 exceptionState.throwSecurityError( | 632 exceptionState.throwSecurityError( |
633 "Refused to connect to '" + url.elidedString() + | 633 "Refused to connect to '" + url.elidedString() + |
634 "' because it violates the document's Content Security Policy."); | 634 "' because it violates the document's Content Security Policy."); |
635 return; | 635 return; |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
933 if (!m_async) { | 933 if (!m_async) { |
934 throwForLoadFailureIfNeeded( | 934 throwForLoadFailureIfNeeded( |
935 exceptionState, "'GET' is the only method allowed for 'blob:' URLs."); | 935 exceptionState, "'GET' is the only method allowed for 'blob:' URLs."); |
936 } | 936 } |
937 return; | 937 return; |
938 } | 938 } |
939 | 939 |
940 DCHECK(getExecutionContext()); | 940 DCHECK(getExecutionContext()); |
941 ExecutionContext& executionContext = *getExecutionContext(); | 941 ExecutionContext& executionContext = *getExecutionContext(); |
942 | 942 |
943 // The presence of upload event listeners forces us to use preflighting | 943 m_uploadListenerFlag = false; |
yhirano
2016/10/20 11:27:54
In the spec this flag is initialized in open funct
| |
944 // because POSTing to an URL that does not permit cross origin requests should | |
945 // look exactly like POSTing to an URL that does not respond at all. | |
946 // Also, only async requests support upload progress events. | |
947 bool uploadEvents = false; | |
948 if (m_async) { | 944 if (m_async) { |
949 InspectorInstrumentation::asyncTaskScheduled( | 945 InspectorInstrumentation::asyncTaskScheduled( |
950 &executionContext, "XMLHttpRequest.send", this, true); | 946 &executionContext, "XMLHttpRequest.send", this, true); |
947 | |
951 dispatchProgressEvent(EventTypeNames::loadstart, 0, 0); | 948 dispatchProgressEvent(EventTypeNames::loadstart, 0, 0); |
952 if (httpBody && m_upload) { | 949 |
953 uploadEvents = m_upload->hasEventListeners(); | 950 // For optimization, we set the upload listener flag only when m_async is |
951 // true unlike the spec. | |
952 if (m_upload && m_upload->hasEventListeners()) { | |
953 m_uploadListenerFlag = true; | |
954 | |
954 m_upload->dispatchEvent( | 955 m_upload->dispatchEvent( |
955 ProgressEvent::create(EventTypeNames::loadstart, false, 0, 0)); | 956 ProgressEvent::create(EventTypeNames::loadstart, false, 0, 0)); |
956 } | 957 } |
957 } | 958 } |
958 | 959 |
959 m_sameOriginRequest = getSecurityOrigin()->canRequestNoSuborigin(m_url); | 960 m_sameOriginRequest = getSecurityOrigin()->canRequestNoSuborigin(m_url); |
960 | 961 |
961 if (!m_sameOriginRequest && m_includeCredentials) | 962 if (!m_sameOriginRequest && m_includeCredentials) |
962 UseCounter::count(&executionContext, | 963 UseCounter::count(&executionContext, |
963 UseCounter::XMLHttpRequestCrossOriginWithCredentials); | 964 UseCounter::XMLHttpRequestCrossOriginWithCredentials); |
964 | 965 |
965 // We also remember whether upload events should be allowed for this request | |
966 // in case the upload listeners are added after the request is started. | |
967 m_uploadEventsAllowed = | |
968 m_sameOriginRequest || uploadEvents || | |
969 !FetchUtils::isSimpleRequest(m_method, m_requestHeaders); | |
970 | |
971 ResourceRequest request(m_url); | 966 ResourceRequest request(m_url); |
972 request.setHTTPMethod(m_method); | 967 request.setHTTPMethod(m_method); |
973 request.setRequestContext(WebURLRequest::RequestContextXMLHttpRequest); | 968 request.setRequestContext(WebURLRequest::RequestContextXMLHttpRequest); |
974 request.setFetchCredentialsMode( | 969 request.setFetchCredentialsMode( |
975 m_includeCredentials ? WebURLRequest::FetchCredentialsModeInclude | 970 m_includeCredentials ? WebURLRequest::FetchCredentialsModeInclude |
976 : WebURLRequest::FetchCredentialsModeSameOrigin); | 971 : WebURLRequest::FetchCredentialsModeSameOrigin); |
977 request.setSkipServiceWorker(m_isolatedWorldSecurityOrigin.get() | 972 request.setSkipServiceWorker(m_isolatedWorldSecurityOrigin.get() |
978 ? WebURLRequest::SkipServiceWorker::All | 973 ? WebURLRequest::SkipServiceWorker::All |
979 : WebURLRequest::SkipServiceWorker::None); | 974 : WebURLRequest::SkipServiceWorker::None); |
980 request.setExternalRequestStateFromRequestorAddressSpace( | 975 request.setExternalRequestStateFromRequestorAddressSpace( |
981 executionContext.securityContext().addressSpace()); | 976 executionContext.securityContext().addressSpace()); |
982 | 977 |
983 InspectorInstrumentation::willLoadXHR( | 978 InspectorInstrumentation::willLoadXHR( |
984 &executionContext, this, this, m_method, m_url, m_async, | 979 &executionContext, this, this, m_method, m_url, m_async, |
985 httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, | 980 httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, |
986 m_includeCredentials); | 981 m_includeCredentials); |
987 | 982 |
988 if (httpBody) { | 983 if (httpBody) { |
989 DCHECK_NE(m_method, HTTPNames::GET); | 984 DCHECK_NE(m_method, HTTPNames::GET); |
990 DCHECK_NE(m_method, HTTPNames::HEAD); | 985 DCHECK_NE(m_method, HTTPNames::HEAD); |
991 request.setHTTPBody(std::move(httpBody)); | 986 request.setHTTPBody(std::move(httpBody)); |
992 } | 987 } |
993 | 988 |
994 if (m_requestHeaders.size() > 0) | 989 if (m_requestHeaders.size() > 0) |
995 request.addHTTPHeaderFields(m_requestHeaders); | 990 request.addHTTPHeaderFields(m_requestHeaders); |
996 | 991 |
997 ThreadableLoaderOptions options; | 992 ThreadableLoaderOptions options; |
998 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; | 993 options.preflightPolicy = |
994 m_uploadListenerFlag ? ForcePreflight : ConsiderPreflight; | |
999 options.crossOriginRequestPolicy = UseAccessControl; | 995 options.crossOriginRequestPolicy = UseAccessControl; |
1000 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; | 996 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; |
1001 options.contentSecurityPolicyEnforcement = | 997 options.contentSecurityPolicyEnforcement = |
1002 ContentSecurityPolicy::shouldBypassMainWorld(&executionContext) | 998 ContentSecurityPolicy::shouldBypassMainWorld(&executionContext) |
1003 ? DoNotEnforceContentSecurityPolicy | 999 ? DoNotEnforceContentSecurityPolicy |
1004 : EnforceContentSecurityPolicy; | 1000 : EnforceContentSecurityPolicy; |
1005 options.timeoutMilliseconds = m_timeoutMilliseconds; | 1001 options.timeoutMilliseconds = m_timeoutMilliseconds; |
1006 | 1002 |
1007 ResourceLoaderOptions resourceLoaderOptions; | 1003 ResourceLoaderOptions resourceLoaderOptions; |
1008 resourceLoaderOptions.allowCredentials = | 1004 resourceLoaderOptions.allowCredentials = |
(...skipping 12 matching lines...) Expand all Loading... | |
1021 request.setDownloadToFile(true); | 1017 request.setDownloadToFile(true); |
1022 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; | 1018 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; |
1023 } | 1019 } |
1024 | 1020 |
1025 m_exceptionCode = 0; | 1021 m_exceptionCode = 0; |
1026 m_error = false; | 1022 m_error = false; |
1027 | 1023 |
1028 if (m_async) { | 1024 if (m_async) { |
1029 UseCounter::count(&executionContext, | 1025 UseCounter::count(&executionContext, |
1030 UseCounter::XMLHttpRequestAsynchronous); | 1026 UseCounter::XMLHttpRequestAsynchronous); |
1031 if (m_upload) | 1027 |
1028 // The presence of upload event listeners forces us to use preflighting | |
1029 // because POSTing to an URL that does not permit cross origin requests | |
1030 // should look exactly like POSTing to an URL that does not respond at all. | |
1031 // Also, only async requests support upload progress events. | |
1032 if (m_uploadListenerFlag) | |
1032 request.setReportUploadProgress(true); | 1033 request.setReportUploadProgress(true); |
1033 | 1034 |
1034 DCHECK(!m_loader); | 1035 DCHECK(!m_loader); |
1035 m_loader = ThreadableLoader::create(executionContext, this, options, | 1036 m_loader = ThreadableLoader::create(executionContext, this, options, |
1036 resourceLoaderOptions); | 1037 resourceLoaderOptions); |
1037 m_loader->start(request); | 1038 m_loader->start(request); |
1038 | 1039 |
1039 return; | 1040 return; |
1040 } | 1041 } |
1041 | 1042 |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1237 return; | 1238 return; |
1238 } | 1239 } |
1239 | 1240 |
1240 // With m_error set, the state change steps are minimal: any pending | 1241 // With m_error set, the state change steps are minimal: any pending |
1241 // progress event is flushed + a readystatechange is dispatched. | 1242 // progress event is flushed + a readystatechange is dispatched. |
1242 // No new progress events dispatched; as required, that happens at | 1243 // No new progress events dispatched; as required, that happens at |
1243 // the end here. | 1244 // the end here. |
1244 DCHECK(m_error); | 1245 DCHECK(m_error); |
1245 changeState(kDone); | 1246 changeState(kDone); |
1246 | 1247 |
1247 if (!m_uploadComplete) { | 1248 if (!m_uploadCompleteFlag) { |
1248 m_uploadComplete = true; | 1249 m_uploadCompleteFlag = true; |
yhirano
2016/10/20 11:27:54
Is substituting unconditionally enough?
| |
1249 if (m_upload && m_uploadEventsAllowed) | 1250 |
1251 if (m_uploadListenerFlag) { | |
1252 DCHECK(m_upload); | |
1250 m_upload->handleRequestError(type); | 1253 m_upload->handleRequestError(type); |
1254 } | |
1251 } | 1255 } |
1252 | 1256 |
1253 // Note: The below event dispatch may be called while |hasPendingActivity() == | 1257 // Note: The below event dispatch may be called while |hasPendingActivity() == |
1254 // false|, when |handleRequestError| is called after |internalAbort()|. This | 1258 // false|, when |handleRequestError| is called after |internalAbort()|. This |
1255 // is safe, however, as |this| will be kept alive from a strong ref | 1259 // is safe, however, as |this| will be kept alive from a strong ref |
1256 // |Event::m_target|. | 1260 // |Event::m_target|. |
1257 dispatchProgressEvent(EventTypeNames::progress, receivedLength, | 1261 dispatchProgressEvent(EventTypeNames::progress, receivedLength, |
1258 expectedLength); | 1262 expectedLength); |
1259 dispatchProgressEvent(type, receivedLength, expectedLength); | 1263 dispatchProgressEvent(type, receivedLength, expectedLength); |
1260 dispatchProgressEvent(EventTypeNames::loadend, receivedLength, | 1264 dispatchProgressEvent(EventTypeNames::loadend, receivedLength, |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1625 return; | 1629 return; |
1626 | 1630 |
1627 if (status() >= 200 && status() < 300) { | 1631 if (status() >= 200 && status() < 300) { |
1628 document()->frame()->page()->chromeClient().ajaxSucceeded( | 1632 document()->frame()->page()->chromeClient().ajaxSucceeded( |
1629 document()->frame()); | 1633 document()->frame()); |
1630 } | 1634 } |
1631 } | 1635 } |
1632 | 1636 |
1633 void XMLHttpRequest::didSendData(unsigned long long bytesSent, | 1637 void XMLHttpRequest::didSendData(unsigned long long bytesSent, |
1634 unsigned long long totalBytesToBeSent) { | 1638 unsigned long long totalBytesToBeSent) { |
1639 DCHECK(m_async); | |
yhirano
2016/10/20 12:17:02
You call setReportUploadProgress only when m_uploa
| |
1635 NETWORK_DVLOG(1) << this << " didSendData(" << bytesSent << ", " | 1640 NETWORK_DVLOG(1) << this << " didSendData(" << bytesSent << ", " |
1636 << totalBytesToBeSent << ")"; | 1641 << totalBytesToBeSent << ")"; |
1637 ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel); | 1642 ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel); |
1638 | 1643 |
1639 if (!m_upload) | 1644 if (m_uploadListenerFlag) { |
1640 return; | 1645 DCHECK(m_upload); |
1646 m_upload->dispatchProgressEvent(bytesSent, totalBytesToBeSent); | |
1647 } | |
1641 | 1648 |
yhirano
2016/10/20 12:17:02
Not related to this CL but we may need an early-re
| |
1642 if (m_uploadEventsAllowed) | 1649 // TODO(tyoshino): Since AsyncResourceHandler doesn't send us any |
yhirano
2016/10/20 11:27:54
"Since" is not needed?
| |
1643 m_upload->dispatchProgressEvent(bytesSent, totalBytesToBeSent); | 1650 // notification when the total size is 0. Therefore, we cannot depend on |
1651 // didSendData() invocation to dispatch the progress events for "process | |
1652 // request end-of-body" hook as specified in the XHR spec. Fix this. | |
1653 if (bytesSent == totalBytesToBeSent && !m_uploadCompleteFlag) { | |
1654 m_uploadCompleteFlag = true; | |
1644 | 1655 |
1645 if (bytesSent == totalBytesToBeSent && !m_uploadComplete) { | 1656 if (m_uploadListenerFlag) { |
1646 m_uploadComplete = true; | 1657 DCHECK(m_upload); |
1647 if (m_uploadEventsAllowed) | |
1648 m_upload->dispatchEventAndLoadEnd(EventTypeNames::load, true, bytesSent, | 1658 m_upload->dispatchEventAndLoadEnd(EventTypeNames::load, true, bytesSent, |
1649 totalBytesToBeSent); | 1659 totalBytesToBeSent); |
1660 } | |
1661 | |
1662 return; | |
yhirano
2016/10/20 11:27:54
This statement is redundant.
| |
1650 } | 1663 } |
1651 } | 1664 } |
1652 | 1665 |
1653 void XMLHttpRequest::didReceiveResponse( | 1666 void XMLHttpRequest::didReceiveResponse( |
1654 unsigned long identifier, | 1667 unsigned long identifier, |
1655 const ResourceResponse& response, | 1668 const ResourceResponse& response, |
1656 std::unique_ptr<WebDataConsumerHandle> handle) { | 1669 std::unique_ptr<WebDataConsumerHandle> handle) { |
1657 ALLOW_UNUSED_LOCAL(handle); | 1670 ALLOW_UNUSED_LOCAL(handle); |
1658 DCHECK(!handle); | 1671 DCHECK(!handle); |
1659 NETWORK_DVLOG(1) << this << " didReceiveResponse(" << identifier << ")"; | 1672 NETWORK_DVLOG(1) << this << " didReceiveResponse(" << identifier << ")"; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1856 visitor->traceWrappers(m_responseLegacyStream); | 1869 visitor->traceWrappers(m_responseLegacyStream); |
1857 visitor->traceWrappers(m_responseDocument); | 1870 visitor->traceWrappers(m_responseDocument); |
1858 visitor->traceWrappers(m_responseArrayBuffer); | 1871 visitor->traceWrappers(m_responseArrayBuffer); |
1859 } | 1872 } |
1860 | 1873 |
1861 std::ostream& operator<<(std::ostream& ostream, const XMLHttpRequest* xhr) { | 1874 std::ostream& operator<<(std::ostream& ostream, const XMLHttpRequest* xhr) { |
1862 return ostream << "XMLHttpRequest " << static_cast<const void*>(xhr); | 1875 return ostream << "XMLHttpRequest " << static_cast<const void*>(xhr); |
1863 } | 1876 } |
1864 | 1877 |
1865 } // namespace blink | 1878 } // namespace blink |
OLD | NEW |