Use NetworkLoadChecker to handle synchronous HTTP loads
https://bugs.webkit.org/show_bug.cgi?id=184240
Reviewed by Chris Dumez.
LayoutTests/imported/w3c:
* web-platform-tests/cors/request-headers-expected.txt:
* web-platform-tests/XMLHttpRequest/access-control-and-redirects-expected.txt:
* web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader-expected.txt:
* web-platform-tests/XMLHttpRequest/send-authentication-cors-setrequestheader-no-cred-expected.txt:
Source/WebCore:
Update LoaderStrategy::loadResourceSynchronously to pass FetchOptions directly.
Update various call sites accordingly. This allows NetworkProcess to do all necessary checks.
Add an option to disable security checks if NetworkProcess does it for WebProcess.
This option will be also used for regular asynchronous loads in future patches.
Update DocumentThreadableLoader to bypass preflighting and response validation checks in case they are done in NetworkProcess.
Covered by existing and rebased tests.
* loader/CrossOriginPreflightChecker.cpp:
(WebCore::CrossOriginPreflightChecker::doPreflight):
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
(WebCore::DocumentThreadableLoader::loadRequest):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadResourceSynchronously):
* loader/FrameLoader.h:
* loader/LoaderStrategy.h:
* xml/XSLTProcessorLibxslt.cpp:
(WebCore::docLoaderFunc):
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::openFunc):
Source/WebKit:
For every NetworkResourceLoader synchronous load, we create a NetworkLoadChecker.
NetworkLoadChecker handles all security checks in that case.
This allows supporting cross-origin loads for synchronous XHR.
Updated NetworkCORSPreflightChecker to return the result as a ResourceError.
This is used to convey any error message from NetworkProcess to the JS console.
Ensure NetworkCORSPreflightChecker computes correctly Access-Control-Request-Headers value
by providing the headers set by the application plus Referrer/Origin.
* NetworkProcess/NetworkCORSPreflightChecker.cpp:
(WebKit::NetworkCORSPreflightChecker::~NetworkCORSPreflightChecker):
(WebKit::NetworkCORSPreflightChecker::willPerformHTTPRedirection):
(WebKit::NetworkCORSPreflightChecker::didReceiveChallenge):
(WebKit::NetworkCORSPreflightChecker::didCompleteWithError):
(WebKit::NetworkCORSPreflightChecker::wasBlocked):
(WebKit::NetworkCORSPreflightChecker::cannotShowURL):
* NetworkProcess/NetworkLoadChecker.cpp:
(WebKit::NetworkLoadChecker::checkCORSRequestWithPreflight):
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::NetworkResourceLoader):
(WebKit::NetworkResourceLoader::retrieveCacheEntry):
(WebKit::NetworkResourceLoader::didReceiveResponse):
(WebKit::NetworkResourceLoader::willSendRedirectedRequest):
(WebKit::NetworkResourceLoader::continueWillSendRequest):
(WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
(WebKit::NetworkResourceLoader::validateCacheEntry):
* NetworkProcess/NetworkResourceLoader.h:
* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::loadResourceSynchronously):
* WebProcess/Network/WebLoaderStrategy.h:
Source/WebKitLegacy:
* WebCoreSupport/WebResourceLoadScheduler.cpp:
(WebResourceLoadScheduler::loadResourceSynchronously):
* WebCoreSupport/WebResourceLoadScheduler.h:
LayoutTests:
* http/tests/xmlhttprequest/access-control-preflight-not-successful-expected.txt:
* http/wpt/beacon/cors/cors-preflight-blob-failure.html: Fix buggy assertion.
Test should check for actual request header and not header name in Access-Control-Request-Headers.
* http/wpt/beacon/cors/cors-preflight-blob-success.html: Ditto.
* platform/mac-wk1/http/tests/xmlhttprequest/access-control-and-redirects-expected.txt: Added.
* platform/mac-wk1/http/tests/xmlhttprequest/access-control-preflight-not-successful-expected.txt: Added.
* platform/mac-wk1/http/tests/xmlhttprequest/cross-origin-no-authorization-expected.txt: Added.
* platform/mac-wk1/imported/w3c/web-platform-tests/XMLHttpRequest/access-control-and-redirects-expected.txt: Added.
* platform/win/http/tests/xmlhttprequest/access-control-and-redirects-expected.txt: Added.
* platform/win/http/tests/xmlhttprequest/access-control-preflight-not-successful-expected.txt: Added.
* platform/win/http/tests/xmlhttprequest/cross-origin-no-authorization-expected.txt: Added.
* platform/mac-highsierra-wk2/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader-expected.txt.
* platform/mac-highsierra-wk2/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-setrequestheader-no-cred-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-setrequestheader-no-cred-expected.txt.
* platform/mac-wk1/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader-expected.txt.
* platform/mac-wk1/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-setrequestheader-no-cred-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-setrequestheader-no-cred-expected.txt.
* platform/mac-wk1/imported/w3c/web-platform-tests/cors/request-headers-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/cors/request-headers-expected.txt.
* platform/win/http/tests/xmlhttprequest/access-control-and-redirects-expected.txt:
* platform/win/http/tests/xmlhttprequest/access-control-preflight-not-successful-expected.txt:
* platform/win/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader-expected.txt.
* platform/win/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-setrequestheader-no-cred-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/XMLHttpRequest/send-authentication-cors-setrequestheader-no-cred-expected.txt.
* platform/win/imported/w3c/web-platform-tests/cors/request-headers-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/cors/request-headers-expected.txt.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@230681 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/loader/DocumentThreadableLoader.cpp b/Source/WebCore/loader/DocumentThreadableLoader.cpp
index 502000f..240daa1 100644
--- a/Source/WebCore/loader/DocumentThreadableLoader.cpp
+++ b/Source/WebCore/loader/DocumentThreadableLoader.cpp
@@ -44,6 +44,7 @@
#include "FrameLoader.h"
#include "InspectorInstrumentation.h"
#include "LoadTiming.h"
+#include "LoaderStrategy.h"
#include "Performance.h"
#include "ProgressTracker.h"
#include "ResourceError.h"
@@ -106,6 +107,10 @@
// Setting a referrer header is only supported in the async code path.
ASSERT(m_async || m_referrer.isEmpty());
+ // No need to do preflight if the network stack will do it for us.
+ if (!m_async && platformStrategies()->loaderStrategy()->isDoingLoadingSecurityChecks())
+ m_options.preflightPolicy = PreventPreflight;
+
// Referrer and Origin headers should be set after the preflight if any.
ASSERT(!request.hasHTTPReferrer() && !request.hasHTTPOrigin());
@@ -116,7 +121,7 @@
ASSERT(!request.httpHeaderFields().contains(HTTPHeaderName::Origin));
// Copy headers if we need to replay the request after a redirection.
- if (m_async && m_options.mode == FetchOptions::Mode::Cors)
+ if (!m_async || m_options.mode == FetchOptions::Mode::Cors)
m_originalHeaders = request.httpHeaderFields();
#if ENABLE(SERVICE_WORKER)
@@ -509,7 +514,7 @@
auto& frameLoader = m_document.frame()->loader();
if (!frameLoader.mixedContentChecker().canRunInsecureContent(m_document.securityOrigin(), requestURL))
return;
- identifier = frameLoader.loadResourceSynchronously(request, m_options.storedCredentialsPolicy, m_options.clientCredentialPolicy, error, response, data);
+ identifier = frameLoader.loadResourceSynchronously(request, m_options.clientCredentialPolicy, m_options, *m_originalHeaders, error, response, data);
}
loadTiming.setResponseEnd(MonotonicTime::now());
@@ -526,32 +531,34 @@
return;
}
- // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the
- // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was
- // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials.
- bool didRedirect = requestURL != response.url();
- if (didRedirect) {
- if (!isAllowedByContentSecurityPolicy(response.url(), ContentSecurityPolicy::RedirectResponseReceived::Yes)) {
- reportContentSecurityPolicyError(requestURL);
- return;
- }
- if (!isAllowedRedirect(response.url())) {
- reportCrossOriginResourceSharingError(requestURL);
- return;
- }
- }
-
- if (!m_sameOriginRequest) {
- if (m_options.mode == FetchOptions::Mode::NoCors)
- response.setTainting(ResourceResponse::Tainting::Opaque);
- else {
- ASSERT(m_options.mode == FetchOptions::Mode::Cors);
- response.setTainting(ResourceResponse::Tainting::Cors);
- String accessControlErrorDescription;
- if (!passesAccessControlCheck(response, m_options.storedCredentialsPolicy, securityOrigin(), accessControlErrorDescription)) {
- logErrorAndFail(ResourceError(errorDomainWebKitInternal, 0, response.url(), accessControlErrorDescription, ResourceError::Type::AccessControl));
+ if (!platformStrategies()->loaderStrategy()->isDoingLoadingSecurityChecks()) {
+ // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the
+ // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was
+ // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials.
+ bool didRedirect = requestURL != response.url();
+ if (didRedirect) {
+ if (!isAllowedByContentSecurityPolicy(response.url(), ContentSecurityPolicy::RedirectResponseReceived::Yes)) {
+ reportContentSecurityPolicyError(requestURL);
return;
}
+ if (!isAllowedRedirect(response.url())) {
+ reportCrossOriginResourceSharingError(requestURL);
+ return;
+ }
+ }
+
+ if (!m_sameOriginRequest) {
+ if (m_options.mode == FetchOptions::Mode::NoCors)
+ response.setTainting(ResourceResponse::Tainting::Opaque);
+ else {
+ ASSERT(m_options.mode == FetchOptions::Mode::Cors);
+ response.setTainting(ResourceResponse::Tainting::Cors);
+ String accessControlErrorDescription;
+ if (!passesAccessControlCheck(response, m_options.storedCredentialsPolicy, securityOrigin(), accessControlErrorDescription)) {
+ logErrorAndFail(ResourceError(errorDomainWebKitInternal, 0, response.url(), accessControlErrorDescription, ResourceError::Type::AccessControl));
+ return;
+ }
+ }
}
}
didReceiveResponse(identifier, response);