Add suggestion to use "no-cors" with Fetch fails CORS check.

See https://code.google.com/p/chromium/issues/detail?id=452745#c17 for details.

BUG=452745

Review URL: https://codereview.chromium.org/1300083002

git-svn-id: svn://svn.chromium.org/blink/trunk@201949 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent ff95fa93
CONSOLE ERROR: Fetch API cannot load http://localhost:8000/fetch/resources/doctype.html. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. CONSOLE ERROR: Fetch API cannot load http://localhost:8000/fetch/resources/doctype.html. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
CONSOLE ERROR: Fetch API cannot load http://localhost:8000/fetch/resources/redirect-loop.php?Count=100&ACAOrigin=*. Redirect failed. CONSOLE ERROR: Fetch API cannot load http://localhost:8000/fetch/resources/redirect-loop.php?Count=100&ACAOrigin=*. Redirect failed.
This is a testharness.js-based test. This is a testharness.js-based test.
PASS fetch() with 200 should not output error messages PASS fetch() with 200 should not output error messages
......
...@@ -129,7 +129,7 @@ static String buildAccessControlFailureMessage(const String& detail, SecurityOri ...@@ -129,7 +129,7 @@ static String buildAccessControlFailureMessage(const String& detail, SecurityOri
return detail + " Origin '" + securityOrigin->toString() + "' is therefore not allowed access."; return detail + " Origin '" + securityOrigin->toString() + "' is therefore not allowed access.";
} }
bool passesAccessControlCheck(const ResourceResponse& response, StoredCredentials includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription) bool passesAccessControlCheck(const ResourceResponse& response, StoredCredentials includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription, WebURLRequest::RequestContext context)
{ {
AtomicallyInitializedStaticReference(AtomicString, allowOriginHeaderName, (new AtomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral))); AtomicallyInitializedStaticReference(AtomicString, allowOriginHeaderName, (new AtomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral)));
AtomicallyInitializedStaticReference(AtomicString, allowCredentialsHeaderName, (new AtomicString("access-control-allow-credentials", AtomicString::ConstructFromLiteral))); AtomicallyInitializedStaticReference(AtomicString, allowCredentialsHeaderName, (new AtomicString("access-control-allow-credentials", AtomicString::ConstructFromLiteral)));
...@@ -158,6 +158,9 @@ bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential ...@@ -158,6 +158,9 @@ bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential
if (isInterestingStatusCode(statusCode)) if (isInterestingStatusCode(statusCode))
errorDescription.append(" The response had HTTP status code " + String::number(statusCode) + "."); errorDescription.append(" The response had HTTP status code " + String::number(statusCode) + ".");
if (context == WebURLRequest::RequestContextFetch)
errorDescription.append(" If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.");
return false; return false;
} }
...@@ -172,6 +175,8 @@ bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential ...@@ -172,6 +175,8 @@ bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential
detail = "The 'Access-Control-Allow-Origin' header has a value '" + allowOriginHeaderValue + "' that is not equal to the supplied origin."; detail = "The 'Access-Control-Allow-Origin' header has a value '" + allowOriginHeaderValue + "' that is not equal to the supplied origin.";
} }
errorDescription = buildAccessControlFailureMessage(detail, securityOrigin); errorDescription = buildAccessControlFailureMessage(detail, securityOrigin);
if (context == WebURLRequest::RequestContextFetch)
errorDescription.append(" Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.");
return false; return false;
} }
...@@ -246,7 +251,7 @@ bool CrossOriginAccessControl::handleRedirect(SecurityOrigin* securityOrigin, Re ...@@ -246,7 +251,7 @@ bool CrossOriginAccessControl::handleRedirect(SecurityOrigin* securityOrigin, Re
bool allowRedirect = isLegalRedirectLocation(newURL, errorDescription); bool allowRedirect = isLegalRedirectLocation(newURL, errorDescription);
if (allowRedirect) { if (allowRedirect) {
// Step 5: perform resource sharing access check. // Step 5: perform resource sharing access check.
allowRedirect = passesAccessControlCheck(redirectResponse, withCredentials, securityOrigin, errorDescription); allowRedirect = passesAccessControlCheck(redirectResponse, withCredentials, securityOrigin, errorDescription, newRequest.requestContext());
if (allowRedirect) { if (allowRedirect) {
RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(originalURL); RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(originalURL);
// Step 6: if the request URL origin is not same origin as the original URL's, // Step 6: if the request URL origin is not same origin as the original URL's,
......
...@@ -59,7 +59,7 @@ CORE_EXPORT bool isOnAccessControlResponseHeaderWhitelist(const String&); ...@@ -59,7 +59,7 @@ CORE_EXPORT bool isOnAccessControlResponseHeaderWhitelist(const String&);
void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin*, StoredCredentials); void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin*, StoredCredentials);
ResourceRequest createAccessControlPreflightRequest(const ResourceRequest&, SecurityOrigin*); ResourceRequest createAccessControlPreflightRequest(const ResourceRequest&, SecurityOrigin*);
bool passesAccessControlCheck(const ResourceResponse&, StoredCredentials, SecurityOrigin*, String& errorDescription); bool passesAccessControlCheck(const ResourceResponse&, StoredCredentials, SecurityOrigin*, String& errorDescription, WebURLRequest::RequestContext requestType);
bool passesPreflightStatusCheck(const ResourceResponse&, String& errorDescription); bool passesPreflightStatusCheck(const ResourceResponse&, String& errorDescription);
CORE_EXPORT void parseAccessControlExposeHeadersAllowList(const String& headerValue, HTTPHeaderSet&); CORE_EXPORT void parseAccessControlExposeHeadersAllowList(const String& headerValue, HTTPHeaderSet&);
......
...@@ -328,7 +328,7 @@ bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin) const ...@@ -328,7 +328,7 @@ bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin) const
bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin, String& errorDescription) const bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin, String& errorDescription) const
{ {
return blink::passesAccessControlCheck(m_response, resourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials, securityOrigin, errorDescription); return blink::passesAccessControlCheck(m_response, resourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials, securityOrigin, errorDescription, resourceRequest().requestContext());
} }
bool Resource::isEligibleForIntegrityCheck(SecurityOrigin* securityOrigin) const bool Resource::isEligibleForIntegrityCheck(SecurityOrigin* securityOrigin) const
......
...@@ -380,7 +380,7 @@ void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ ...@@ -380,7 +380,7 @@ void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
// The redirect response must pass the access control check if the // The redirect response must pass the access control check if the
// original request was not same-origin. // original request was not same-origin.
allowRedirect = CrossOriginAccessControl::isLegalRedirectLocation(request.url(), accessControlErrorDescription) allowRedirect = CrossOriginAccessControl::isLegalRedirectLocation(request.url(), accessControlErrorDescription)
&& (m_sameOriginRequest || passesAccessControlCheck(redirectResponse, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription)); && (m_sameOriginRequest || passesAccessControlCheck(redirectResponse, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription, m_requestContext));
} }
if (allowRedirect) { if (allowRedirect) {
...@@ -469,7 +469,7 @@ void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r ...@@ -469,7 +469,7 @@ void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r
{ {
String accessControlErrorDescription; String accessControlErrorDescription;
if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription)) { if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription, m_requestContext)) {
handlePreflightFailure(response.url().string(), "Response to preflight request doesn't pass access control check: " + accessControlErrorDescription); handlePreflightFailure(response.url().string(), "Response to preflight request doesn't pass access control check: " + accessControlErrorDescription);
return; return;
} }
...@@ -543,7 +543,7 @@ void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re ...@@ -543,7 +543,7 @@ void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re
if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) { if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) {
String accessControlErrorDescription; String accessControlErrorDescription;
if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription)) { if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription, m_requestContext)) {
reportResponseReceived(identifier, response); reportResponseReceived(identifier, response);
m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, response.url().string(), accessControlErrorDescription)); m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, response.url().string(), accessControlErrorDescription));
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment