Commit d0994aa8 authored by Yutaka Hirano's avatar Yutaka Hirano Committed by Commit Bot

[OOR-CORS] Have PreflightResult functions return CORSErrorStatus

...instead of mojom::CORSError. Currently they return a mojom::CORSError
and callers need to compose a CORSErrorStatus from it. That requires
callers to know which specific errors are returned from the function,
which is not good.

Bug: 736308
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: I5b0dfaf5b906e0203c9a72ebaef759a8fafa4ad3
Reviewed-on: https://chromium-review.googlesource.com/1147681Reviewed-by: default avatarAdam Rice <ricea@chromium.org>
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577443}
parent 247d632e
...@@ -169,18 +169,12 @@ std::unique_ptr<PreflightResult> CreatePreflightResult( ...@@ -169,18 +169,12 @@ std::unique_ptr<PreflightResult> CreatePreflightResult(
base::Optional<CORSErrorStatus> CheckPreflightResult( base::Optional<CORSErrorStatus> CheckPreflightResult(
PreflightResult* result, PreflightResult* result,
const ResourceRequest& original_request) { const ResourceRequest& original_request) {
base::Optional<mojom::CORSError> error = base::Optional<CORSErrorStatus> status =
result->EnsureAllowedCrossOriginMethod(original_request.method); result->EnsureAllowedCrossOriginMethod(original_request.method);
if (error) if (status)
return CORSErrorStatus(*error, original_request.method); return status;
std::string detected_error_header;
error = result->EnsureAllowedCrossOriginHeaders(original_request.headers,
&detected_error_header);
if (error)
return CORSErrorStatus(*error, detected_error_header);
return base::nullopt; return result->EnsureAllowedCrossOriginHeaders(original_request.headers);
} }
// TODO(toyoshim): Remove this class once the Network Service is enabled. // TODO(toyoshim): Remove this class once the Network Service is enabled.
......
...@@ -112,8 +112,7 @@ PreflightResult::PreflightResult( ...@@ -112,8 +112,7 @@ PreflightResult::PreflightResult(
PreflightResult::~PreflightResult() = default; PreflightResult::~PreflightResult() = default;
base::Optional<mojom::CORSError> base::Optional<CORSErrorStatus> PreflightResult::EnsureAllowedCrossOriginMethod(
PreflightResult::EnsureAllowedCrossOriginMethod(
const std::string& method) const { const std::string& method) const {
// Request method is normalized to upper case, and comparison is performed in // Request method is normalized to upper case, and comparison is performed in
// case-sensitive way, that means access control header should provide an // case-sensitive way, that means access control header should provide an
...@@ -127,13 +126,13 @@ PreflightResult::EnsureAllowedCrossOriginMethod( ...@@ -127,13 +126,13 @@ PreflightResult::EnsureAllowedCrossOriginMethod(
if (!credentials_ && methods_.find("*") != methods_.end()) if (!credentials_ && methods_.find("*") != methods_.end())
return base::nullopt; return base::nullopt;
return mojom::CORSError::kMethodDisallowedByPreflightResponse; return CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
method);
} }
base::Optional<mojom::CORSError> base::Optional<CORSErrorStatus>
PreflightResult::EnsureAllowedCrossOriginHeaders( PreflightResult::EnsureAllowedCrossOriginHeaders(
const net::HttpRequestHeaders& headers, const net::HttpRequestHeaders& headers) const {
std::string* detected_header) const {
if (!credentials_ && headers_.find("*") != headers_.end()) if (!credentials_ && headers_.find("*") != headers_.end())
return base::nullopt; return base::nullopt;
...@@ -149,9 +148,8 @@ PreflightResult::EnsureAllowedCrossOriginHeaders( ...@@ -149,9 +148,8 @@ PreflightResult::EnsureAllowedCrossOriginHeaders(
// fine. // fine.
if (IsForbiddenHeader(key)) if (IsForbiddenHeader(key))
continue; continue;
if (detected_header) return CORSErrorStatus(
*detected_header = header.key; mojom::CORSError::kHeaderDisallowedByPreflightResponse, header.key);
return mojom::CORSError::kHeaderDisallowedByPreflightResponse;
} }
} }
return base::nullopt; return base::nullopt;
...@@ -172,7 +170,7 @@ bool PreflightResult::EnsureAllowedRequest( ...@@ -172,7 +170,7 @@ bool PreflightResult::EnsureAllowedRequest(
if (EnsureAllowedCrossOriginMethod(method)) if (EnsureAllowedCrossOriginMethod(method))
return false; return false;
if (EnsureAllowedCrossOriginHeaders(headers, nullptr)) if (EnsureAllowedCrossOriginHeaders(headers))
return false; return false;
return true; return true;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/component_export.h" #include "base/component_export.h"
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/optional.h" #include "base/optional.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 "services/network/public/mojom/fetch_api.mojom-shared.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h"
...@@ -45,19 +46,17 @@ class COMPONENT_EXPORT(NETWORK_CPP) PreflightResult final { ...@@ -45,19 +46,17 @@ class COMPONENT_EXPORT(NETWORK_CPP) PreflightResult final {
~PreflightResult(); ~PreflightResult();
// Checks if the given |method| is allowed by the CORS-preflight response. // Checks if the given |method| is allowed by the CORS-preflight response.
base::Optional<mojom::CORSError> EnsureAllowedCrossOriginMethod( base::Optional<CORSErrorStatus> EnsureAllowedCrossOriginMethod(
const std::string& method) const; const std::string& method) const;
// Checks if the given all |headers| are allowed by the CORS-preflight // Checks if the given all |headers| are allowed by the CORS-preflight
// response. |detected_header| indicates the disallowed header name if the // response.
// pointer is valid.
// This does not reject when the headers contain forbidden headers // This does not reject when the headers contain forbidden headers
// (https://fetch.spec.whatwg.org/#forbidden-header-name) because they may be // (https://fetch.spec.whatwg.org/#forbidden-header-name) because they may be
// added by the user agent. They must be checked separately and rejected for // added by the user agent. They must be checked separately and rejected for
// JavaScript-initiated requests. // JavaScript-initiated requests.
base::Optional<mojom::CORSError> EnsureAllowedCrossOriginHeaders( base::Optional<CORSErrorStatus> EnsureAllowedCrossOriginHeaders(
const net::HttpRequestHeaders& headers, const net::HttpRequestHeaders& headers) const;
std::string* detected_header) const;
// Checks if the given combination of |credentials_mode|, |method|, and // Checks if the given combination of |credentials_mode|, |method|, and
// |headers| is allowed by the CORS-preflight response. // |headers| is allowed by the CORS-preflight response.
......
...@@ -26,7 +26,7 @@ struct TestCase { ...@@ -26,7 +26,7 @@ struct TestCase {
const std::string request_headers; const std::string request_headers;
const mojom::FetchCredentialsMode request_credentials_mode; const mojom::FetchCredentialsMode request_credentials_mode;
const base::Optional<mojom::CORSError> expected_result; const base::Optional<CORSErrorStatus> expected_result;
}; };
const TestCase method_cases[] = { const TestCase method_cases[] = {
...@@ -67,29 +67,36 @@ const TestCase method_cases[] = { ...@@ -67,29 +67,36 @@ const TestCase method_cases[] = {
// Not found in the preflight response and the safe lit. // Not found in the preflight response and the safe lit.
{"", "", mojom::FetchCredentialsMode::kOmit, "OPTIONS", "", {"", "", mojom::FetchCredentialsMode::kOmit, "OPTIONS", "",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kMethodDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
"OPTIONS")},
{"", "", mojom::FetchCredentialsMode::kOmit, "PUT", "", {"", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kMethodDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
"PUT")},
{"", "", mojom::FetchCredentialsMode::kOmit, "DELETE", "", {"", "", mojom::FetchCredentialsMode::kOmit, "DELETE", "",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kMethodDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
"DELETE")},
{"GET", "", mojom::FetchCredentialsMode::kOmit, "PUT", "", {"GET", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kMethodDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
"PUT")},
{"GET, POST, DELETE", "", mojom::FetchCredentialsMode::kOmit, "PUT", "", {"GET, POST, DELETE", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kMethodDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
"PUT")},
// Request method is normalized to upper-case, but allowed methods is not. // Request method is normalized to upper-case, but allowed methods is not.
// Comparison is in case-sensitive, that means allowed methods should be in // Comparison is in case-sensitive, that means allowed methods should be in
// upper case. // upper case.
{"put", "", mojom::FetchCredentialsMode::kOmit, "PUT", "", {"put", "", mojom::FetchCredentialsMode::kOmit, "PUT", "",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kMethodDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
"PUT")},
{"put", "", mojom::FetchCredentialsMode::kOmit, "put", "", {"put", "", mojom::FetchCredentialsMode::kOmit, "put", "",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kMethodDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kMethodDisallowedByPreflightResponse,
"put")},
{"PUT", "", mojom::FetchCredentialsMode::kOmit, "put", "", {"PUT", "", mojom::FetchCredentialsMode::kOmit, "put", "",
mojom::FetchCredentialsMode::kOmit, base::nullopt}, mojom::FetchCredentialsMode::kOmit, base::nullopt},
// ... But, GET is always allowed by the safe list. // ... But, GET is always allowed by the safe list.
...@@ -117,7 +124,8 @@ const TestCase header_cases[] = { ...@@ -117,7 +124,8 @@ const TestCase header_cases[] = {
mojom::FetchCredentialsMode::kOmit, base::nullopt}, mojom::FetchCredentialsMode::kOmit, base::nullopt},
{"GET", "*", mojom::FetchCredentialsMode::kInclude, "GET", "xyzzy:t", {"GET", "*", mojom::FetchCredentialsMode::kInclude, "GET", "xyzzy:t",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kHeaderDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
"xyzzy")},
// Forbidden headers can pass. // Forbidden headers can pass.
{"GET", "", mojom::FetchCredentialsMode::kOmit, "GET", {"GET", "", mojom::FetchCredentialsMode::kOmit, "GET",
...@@ -126,13 +134,16 @@ const TestCase header_cases[] = { ...@@ -126,13 +134,16 @@ const TestCase header_cases[] = {
// Not found in the preflight response and the safe list. // Not found in the preflight response and the safe list.
{"GET", "", mojom::FetchCredentialsMode::kOmit, "GET", "X-MY-HEADER:t", {"GET", "", mojom::FetchCredentialsMode::kOmit, "GET", "X-MY-HEADER:t",
mojom::FetchCredentialsMode::kOmit, mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kHeaderDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
"X-MY-HEADER")},
{"GET", "X-SOME-OTHER-HEADER", mojom::FetchCredentialsMode::kOmit, "GET", {"GET", "X-SOME-OTHER-HEADER", mojom::FetchCredentialsMode::kOmit, "GET",
"X-MY-HEADER:t", mojom::FetchCredentialsMode::kOmit, "X-MY-HEADER:t", mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kHeaderDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
"X-MY-HEADER")},
{"GET", "X-MY-HEADER", mojom::FetchCredentialsMode::kOmit, "GET", {"GET", "X-MY-HEADER", mojom::FetchCredentialsMode::kOmit, "GET",
"X-MY-HEADER:t\r\nY-MY-HEADER:t", mojom::FetchCredentialsMode::kOmit, "X-MY-HEADER:t\r\nY-MY-HEADER:t", mojom::FetchCredentialsMode::kOmit,
mojom::CORSError::kHeaderDisallowedByPreflightResponse}, CORSErrorStatus(mojom::CORSError::kHeaderDisallowedByPreflightResponse,
"Y-MY-HEADER")},
}; };
TEST_F(PreflightResultTest, MaxAge) { TEST_F(PreflightResultTest, MaxAge) {
...@@ -177,7 +188,7 @@ TEST_F(PreflightResultTest, EnsureHeaders) { ...@@ -177,7 +188,7 @@ TEST_F(PreflightResultTest, EnsureHeaders) {
net::HttpRequestHeaders headers; net::HttpRequestHeaders headers;
headers.AddHeadersFromString(test.request_headers); headers.AddHeadersFromString(test.request_headers);
EXPECT_EQ(test.expected_result, EXPECT_EQ(test.expected_result,
result->EnsureAllowedCrossOriginHeaders(headers, nullptr)); result->EnsureAllowedCrossOriginHeaders(headers));
} }
} }
......
...@@ -146,6 +146,7 @@ bool EnsurePreflightResultAndCacheOnSuccess( ...@@ -146,6 +146,7 @@ bool EnsurePreflightResultAndCacheOnSuccess(
DCHECK(error_description); DCHECK(error_description);
base::Optional<network::mojom::CORSError> error; base::Optional<network::mojom::CORSError> error;
base::Optional<network::CORSErrorStatus> status;
std::unique_ptr<network::cors::PreflightResult> result = std::unique_ptr<network::cors::PreflightResult> result =
network::cors::PreflightResult::Create( network::cors::PreflightResult::Create(
...@@ -164,23 +165,22 @@ bool EnsurePreflightResultAndCacheOnSuccess( ...@@ -164,23 +165,22 @@ bool EnsurePreflightResultAndCacheOnSuccess(
return false; return false;
} }
error = result->EnsureAllowedCrossOriginMethod( status = result->EnsureAllowedCrossOriginMethod(
std::string(request_method.Ascii().data())); std::string(request_method.Ascii().data()));
if (error) { if (status) {
*error_description = CORS::GetErrorString( *error_description = CORS::GetErrorString(
CORS::ErrorParameter::CreateForPreflightResponseCheck(*error, CORS::ErrorParameter::CreateForPreflightResponseCheck(
request_method)); status->cors_error, request_method));
return false; return false;
} }
std::string detected_error_header; status = result->EnsureAllowedCrossOriginHeaders(
error = result->EnsureAllowedCrossOriginHeaders( *CreateNetHttpRequestHeaders(request_header_map));
*CreateNetHttpRequestHeaders(request_header_map), &detected_error_header); if (status) {
if (error) {
*error_description = CORS::GetErrorString( *error_description = CORS::GetErrorString(
CORS::ErrorParameter::CreateForPreflightResponseCheck( CORS::ErrorParameter::CreateForPreflightResponseCheck(
*error, String(detected_error_header.data(), status->cors_error, String(status->failed_parameter.data(),
detected_error_header.length()))); status->failed_parameter.length())));
return false; return false;
} }
......
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