Commit 1f675b46 authored by Takashi Toyoshima's avatar Takashi Toyoshima Committed by Commit Bot

OOR-CORS: store more information to CORSErrorStatus on preflight errors

Current implementation does not store rejected method or header
information to CORSErrorStatus on CORS-preflight checks, and
results in missing hint parameter on CreateErrorString() in Blink.
This patch provides required information to generate right error
messages, and fixes some crashed layout tests.

Bug: 803766, 836741
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Change-Id: If4de6b916a77d204812a7b010e39080bf059bc9e
Tbr: kinuko@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/1030670
Commit-Queue: Takashi Toyoshima <toyoshim@chromium.org>
Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554642}
parent 3a175efb
...@@ -150,34 +150,19 @@ std::unique_ptr<PreflightResult> CreatePreflightResult( ...@@ -150,34 +150,19 @@ std::unique_ptr<PreflightResult> CreatePreflightResult(
detected_error); detected_error);
} }
base::Optional<mojom::CORSError> CheckPreflightResult( base::Optional<CORSErrorStatus> CheckPreflightResult(
PreflightResult* result, PreflightResult* result,
const ResourceRequest& original_request, const ResourceRequest& original_request) {
scoped_refptr<net::HttpResponseHeaders>* error_header) {
DCHECK(error_header);
base::Optional<mojom::CORSError> error = base::Optional<mojom::CORSError> error =
result->EnsureAllowedCrossOriginMethod(original_request.method); result->EnsureAllowedCrossOriginMethod(original_request.method);
if (error) if (error)
return error; return CORSErrorStatus(*error, original_request.method);
std::string detected_error_header; std::string detected_error_header;
error = result->EnsureAllowedCrossOriginHeaders(original_request.headers, error = result->EnsureAllowedCrossOriginHeaders(original_request.headers,
&detected_error_header); &detected_error_header);
if (error) { if (error)
// Gather information to report the error's details. return CORSErrorStatus(*error, detected_error_header);
DCHECK(!detected_error_header.empty());
std::string header_value;
bool found = original_request.headers.GetHeader(detected_error_header,
&header_value);
DCHECK(found);
// Status line below is dummy to construct a response header instance.
*error_header =
base::MakeRefCounted<net::HttpResponseHeaders>(base::StringPrintf(
"HTTP/1.0 200 OK\n%s: %s", detected_error_header.c_str(),
header_value.c_str()));
return error;
}
return base::nullopt; return base::nullopt;
} }
...@@ -291,27 +276,25 @@ class PreflightController::PreflightLoader final { ...@@ -291,27 +276,25 @@ class PreflightController::PreflightLoader final {
std::unique_ptr<PreflightResult> result = CreatePreflightResult( std::unique_ptr<PreflightResult> result = CreatePreflightResult(
final_url, head, original_request_, &detected_error); final_url, head, original_request_, &detected_error);
scoped_refptr<net::HttpResponseHeaders> error_header; base::Optional<CORSErrorStatus> detected_error_status;
if (result) { if (result) {
// Preflight succeeded. Check |original_request_| with |result|. // Preflight succeeded. Check |original_request_| with |result|.
DCHECK(!detected_error); DCHECK(!detected_error);
detected_error = detected_error_status =
CheckPreflightResult(result.get(), original_request_, &error_header); CheckPreflightResult(result.get(), original_request_);
} else {
DCHECK(detected_error);
detected_error_status = CORSErrorStatus(*detected_error);
} }
// TODO(toyoshim): Check the spec if we cache |result| regardless of // TODO(toyoshim): Check the spec if we cache |result| regardless of
// following checks. // following checks.
if (!detected_error) { if (!detected_error_status) {
controller_->AppendToCache(*original_request_.request_initiator, controller_->AppendToCache(*original_request_.request_initiator,
original_request_.url, std::move(result)); original_request_.url, std::move(result));
} }
if (detected_error) { std::move(completion_callback_).Run(detected_error_status);
std::move(completion_callback_)
.Run(CORSErrorStatus(*detected_error, error_header));
} else {
std::move(completion_callback_).Run(base::nullopt);
}
RemoveFromController(); RemoveFromController();
// |this| is deleted here. // |this| is deleted here.
......
...@@ -19,18 +19,15 @@ CORSErrorStatus::CORSErrorStatus(const CORSErrorStatus& status) = default; ...@@ -19,18 +19,15 @@ CORSErrorStatus::CORSErrorStatus(const CORSErrorStatus& status) = default;
CORSErrorStatus::CORSErrorStatus(network::mojom::CORSError error) CORSErrorStatus::CORSErrorStatus(network::mojom::CORSError error)
: cors_error(error) {} : cors_error(error) {}
CORSErrorStatus::CORSErrorStatus( CORSErrorStatus::CORSErrorStatus(network::mojom::CORSError error,
network::mojom::CORSError error, const std::string& failed_parameter)
scoped_refptr<net::HttpResponseHeaders> headers) : cors_error(error), failed_parameter(failed_parameter) {}
: CORSErrorStatus(error) {
related_response_headers = headers;
}
CORSErrorStatus::~CORSErrorStatus() = default; CORSErrorStatus::~CORSErrorStatus() = default;
bool CORSErrorStatus::operator==(const CORSErrorStatus& rhs) const { bool CORSErrorStatus::operator==(const CORSErrorStatus& rhs) const {
return cors_error == rhs.cors_error && return cors_error == rhs.cors_error &&
related_response_headers == rhs.related_response_headers; failed_parameter == rhs.failed_parameter;
} }
} // namespace network } // namespace network
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_ERROR_STATUS_H_ #ifndef SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_ERROR_STATUS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_ERROR_STATUS_H_ #define SERVICES_NETWORK_PUBLIC_CPP_CORS_CORS_ERROR_STATUS_H_
#include <string>
#include "base/component_export.h" #include "base/component_export.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
...@@ -22,9 +24,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) CORSErrorStatus { ...@@ -22,9 +24,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) CORSErrorStatus {
CORSErrorStatus(const CORSErrorStatus& status); CORSErrorStatus(const CORSErrorStatus& status);
explicit CORSErrorStatus(network::mojom::CORSError error); explicit CORSErrorStatus(network::mojom::CORSError error);
CORSErrorStatus( CORSErrorStatus(network::mojom::CORSError error,
network::mojom::CORSError error, const std::string& failed_parameter);
scoped_refptr<net::HttpResponseHeaders> related_response_headers);
~CORSErrorStatus(); ~CORSErrorStatus();
...@@ -33,9 +34,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) CORSErrorStatus { ...@@ -33,9 +34,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) CORSErrorStatus {
network::mojom::CORSError cors_error; network::mojom::CORSError cors_error;
// Partial HTTP response headers including status line that will be useful to // Contains request method name, or header name that didn't pass a CORS check.
// generate a human readable error message. std::string failed_parameter;
scoped_refptr<net::HttpResponseHeaders> related_response_headers;
}; };
} // namespace network } // namespace network
......
...@@ -277,7 +277,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::RequestContextFrameType, ...@@ -277,7 +277,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(network::mojom::RequestContextFrameType,
IPC_STRUCT_TRAITS_BEGIN(network::CORSErrorStatus) IPC_STRUCT_TRAITS_BEGIN(network::CORSErrorStatus)
IPC_STRUCT_TRAITS_MEMBER(cors_error) IPC_STRUCT_TRAITS_MEMBER(cors_error)
IPC_STRUCT_TRAITS_MEMBER(related_response_headers) IPC_STRUCT_TRAITS_MEMBER(failed_parameter)
IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(network::URLLoaderCompletionStatus) IPC_STRUCT_TRAITS_BEGIN(network::URLLoaderCompletionStatus)
......
...@@ -1228,18 +1228,6 @@ crbug.com/826878 [ Mac ] virtual/color_space/fast/canvas/color-space/toDataURL-c ...@@ -1228,18 +1228,6 @@ crbug.com/826878 [ Mac ] virtual/color_space/fast/canvas/color-space/toDataURL-c
# Total 2098 # Total 2098
# Counts skip: 2 crash: 14 text: 67 image: 1 pass: 2005 timeout: 9 # Counts skip: 2 crash: 14 text: 67 image: 1 pass: 2005 timeout: 9
# Release build only wpt test crashes on CORS-preflight. Should be fixed soon.
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-preflight-star.any.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-preflight-star.any.worker.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-preflight.any.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-preflight.any.worker.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect-preflight.any.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect-preflight.any.worker.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Crash ]
crbug.com/836741 [ Release ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Crash ]
# Skipped tests in dictionary order. # Skipped tests in dictionary order.
crbug.com/757165 [ Win ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Skip ] crbug.com/757165 [ Win ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Skip ]
crbug.com/691944 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ] crbug.com/691944 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ]
...@@ -1285,20 +1273,17 @@ crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/simple-cross- ...@@ -1285,20 +1273,17 @@ crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/simple-cross-
crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Timeout ] crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Timeout ]
# Failing tests in dictionary order. # Failing tests in dictionary order.
crbug.com/736308 [ Debug ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect-preflight.any.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect-preflight.any.html [ Failure ]
crbug.com/736308 [ Debug ] virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect-preflight.any.worker.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect-preflight.any.worker.html [ Failure ]
crbug.com/736308 virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect.any.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect.any.html [ Failure ]
crbug.com/736308 virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect.any.worker.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-redirect.any.worker.html [ Failure ]
crbug.com/802835 virtual/outofblink-cors/external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html [ Failure ] crbug.com/802835 virtual/outofblink-cors/external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html [ Failure ]
crbug.com/802835 virtual/outofblink-cors/external/wpt/fetch/corb/img-png-mislabeled-as-html-nosniff.tentative.sub.html [ Failure ]
crbug.com/802835 virtual/outofblink-cors/external/wpt/fetch/corb/preload-image-png-mislabeled-as-html-nosniff.tentative.sub.html [ Failure ]
crbug.com/802835 virtual/outofblink-cors/external/wpt/fetch/corb/script-html-correctly-labeled.tentative.sub.html [ Failure ]
crbug.com/745327 virtual/outofblink-cors/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html [ Failure Pass ] crbug.com/745327 virtual/outofblink-cors/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html [ Failure Pass ]
crbug.com/834183 virtual/outofblink-cors/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html [ Failure Pass ] crbug.com/834183 virtual/outofblink-cors/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html [ Failure Pass ]
crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-image-cache.https.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-image-cache.https.html [ Failure ]
crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-image.https.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-image.https.html [ Failure ]
crbug.com/736308 [ Debug ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Failure ]
crbug.com/736308 [ Debug ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Failure ]
crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https.html [ Failure ]
crbug.com/595993 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Failure ] crbug.com/595993 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Failure ]
crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-request-html-imports.https.html [ Failure ] crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-request-html-imports.https.html [ Failure ]
......
...@@ -1116,20 +1116,15 @@ void DocumentThreadableLoader::DispatchDidFail(const ResourceError& error) { ...@@ -1116,20 +1116,15 @@ void DocumentThreadableLoader::DispatchDidFail(const ResourceError& error) {
if (error.CORSErrorStatus()) { if (error.CORSErrorStatus()) {
DCHECK(out_of_blink_cors_); DCHECK(out_of_blink_cors_);
// TODO(toyoshim): Should consider to pass correct arguments instead of // TODO(toyoshim): Should consider to pass correct arguments instead of
// WebURL() and WebHTTPHeaderMap() to GetErrorString(). // KURL(), 0, and HTTPHeaderMap() to GetErrorString().
// We still need plumbing required information. // We still need plumbing some more information.
const int response_code =
error.CORSErrorStatus()->related_response_headers
? error.CORSErrorStatus()->related_response_headers->response_code()
: 0;
GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
kJSMessageSource, kErrorMessageLevel, kJSMessageSource, kErrorMessageLevel,
"Failed to load " + error.FailingURL() + ": " + "Failed to load " + error.FailingURL() + ": " +
CORS::GetErrorString(CORS::ErrorParameter::Create( CORS::GetErrorString(
error.CORSErrorStatus()->cors_error, CORS::ErrorParameter::Create(
KURL(error.FailingURL()), KURL(), *error.CORSErrorStatus(), KURL(error.FailingURL()), KURL(),
response_code, HTTPHeaderMap(), 0, HTTPHeaderMap(), *GetSecurityOrigin(), request_context_))
*GetSecurityOrigin(), request_context_))
.Utf8() .Utf8()
.data())); .data()));
} }
......
...@@ -37,15 +37,25 @@ ErrorParameter CreateWrongParameter(network::mojom::CORSError error) { ...@@ -37,15 +37,25 @@ ErrorParameter CreateWrongParameter(network::mojom::CORSError error) {
// static // static
ErrorParameter ErrorParameter::Create( ErrorParameter ErrorParameter::Create(
const network::mojom::CORSError error, const network::CORSErrorStatus& error_status,
const KURL& first_url, const KURL& first_url,
const KURL& second_url, const KURL& second_url,
const int status_code, const int status_code,
const HTTPHeaderMap& header_map, const HTTPHeaderMap& header_map,
const SecurityOrigin& origin, const SecurityOrigin& origin,
const WebURLRequest::RequestContext context) { const WebURLRequest::RequestContext context) {
return ErrorParameter(error, first_url, second_url, status_code, header_map, String hint;
origin, context, String(), false); switch (error_status.cors_error) {
case network::mojom::CORSError::kMethodDisallowedByPreflightResponse:
case network::mojom::CORSError::kHeaderDisallowedByPreflightResponse:
DCHECK(!error_status.failed_parameter.empty());
hint = String(error_status.failed_parameter.c_str());
break;
default:
break;
}
return ErrorParameter(error_status.cors_error, first_url, second_url,
status_code, header_map, origin, context, hint, false);
} }
// static // static
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_CORS_CORS_ERROR_STRING_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_CORS_CORS_ERROR_STRING_H_
#include "base/macros.h" #include "base/macros.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/mojom/cors.mojom-shared.h" #include "services/network/public/mojom/cors.mojom-shared.h"
#include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/platform_export.h"
...@@ -23,7 +24,7 @@ namespace CORS { ...@@ -23,7 +24,7 @@ namespace CORS {
struct PLATFORM_EXPORT ErrorParameter { struct PLATFORM_EXPORT ErrorParameter {
// Creates an ErrorParameter for generic cases. Use this function if |error| // Creates an ErrorParameter for generic cases. Use this function if |error|
// can contain any. // can contain any.
static ErrorParameter Create(const network::mojom::CORSError, static ErrorParameter Create(const network::CORSErrorStatus&,
const KURL& first_url, const KURL& first_url,
const KURL& second_url, const KURL& second_url,
const int status_code, const int status_code,
......
...@@ -308,7 +308,8 @@ bool ResourceLoader::WillFollowRedirect( ...@@ -308,7 +308,8 @@ bool ResourceLoader::WillFollowRedirect(
if (!unused_preload) { if (!unused_preload) {
Context().AddErrorConsoleMessage( Context().AddErrorConsoleMessage(
CORS::GetErrorString(CORS::ErrorParameter::Create( CORS::GetErrorString(CORS::ErrorParameter::Create(
*cors_error, redirect_response.Url(), new_url, network::CORSErrorStatus(*cors_error),
redirect_response.Url(), new_url,
redirect_response.HttpStatusCode(), redirect_response.HttpStatusCode(),
redirect_response.HttpHeaderFields(), *source_origin.get(), redirect_response.HttpHeaderFields(), *source_origin.get(),
resource_->LastResourceRequest().GetRequestContext())), resource_->LastResourceRequest().GetRequestContext())),
...@@ -487,7 +488,7 @@ CORSStatus ResourceLoader::DetermineCORSStatus(const ResourceResponse& response, ...@@ -487,7 +488,7 @@ CORSStatus ResourceLoader::DetermineCORSStatus(const ResourceResponse& response,
error_msg.Append(source_origin->ToString()); error_msg.Append(source_origin->ToString());
error_msg.Append("' has been blocked by CORS policy: "); error_msg.Append("' has been blocked by CORS policy: ");
error_msg.Append(CORS::GetErrorString(CORS::ErrorParameter::Create( error_msg.Append(CORS::GetErrorString(CORS::ErrorParameter::Create(
*cors_error, initial_request.Url(), KURL(), network::CORSErrorStatus(*cors_error), initial_request.Url(), KURL(),
response_for_access_control.HttpStatusCode(), response_for_access_control.HttpStatusCode(),
response_for_access_control.HttpHeaderFields(), *source_origin, response_for_access_control.HttpHeaderFields(), *source_origin,
initial_request.GetRequestContext()))); initial_request.GetRequestContext())));
......
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