Chromium Code Reviews| 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 |