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

OOR-CORS: Remove unused CORS method plumbing

As some of methods in blink::cors:: are not used any more,
this patch removes them from the Blink.

Bug: 1053866
Change-Id: If3565084c20ba805d8b7d6a253366d67599c121f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2550141
Commit-Queue: Takashi Toyoshima <toyoshim@chromium.org>
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Auto-Submit: Takashi Toyoshima <toyoshim@chromium.org>
Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829224}
parent 36a38113
...@@ -4,79 +4,20 @@ ...@@ -4,79 +4,20 @@
#include "third_party/blink/renderer/platform/loader/cors/cors.h" #include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include <memory>
#include <string> #include <string>
#include <utility>
#include "net/http/http_util.h" #include "net/http/http_util.h"
#include "services/network/public/cpp/cors/cors.h" #include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/cors/preflight_cache.h"
#include "services/network/public/cpp/request_mode.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/network/http_names.h" #include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace blink { namespace blink {
namespace { namespace {
base::Optional<std::string> GetHeaderValue(const HTTPHeaderMap& header_map,
const AtomicString& header_name) {
if (header_map.Contains(header_name)) {
return header_map.Get(header_name).Latin1();
}
return base::nullopt;
}
network::cors::PreflightCache& GetPerThreadPreflightCache() {
DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<network::cors::PreflightCache>,
cache, ());
return *cache;
}
base::Optional<std::string> GetOptionalHeaderValue(
const HTTPHeaderMap& header_map,
const AtomicString& header_name) {
const AtomicString& result = header_map.Get(header_name);
if (result.IsNull())
return base::nullopt;
return result.Ascii();
}
std::unique_ptr<net::HttpRequestHeaders> CreateNetHttpRequestHeaders(
const HTTPHeaderMap& header_map) {
std::unique_ptr<net::HttpRequestHeaders> request_headers =
std::make_unique<net::HttpRequestHeaders>();
for (HTTPHeaderMap::const_iterator i = header_map.begin(),
end = header_map.end();
i != end; ++i) {
DCHECK(!i->key.IsNull());
DCHECK(!i->value.IsNull());
request_headers->SetHeader(i->key.Ascii(), i->value.Ascii());
}
return request_headers;
}
url::Origin AsUrlOrigin(const SecurityOrigin& origin) {
// "file:" origin is treated like an opaque unique origin when
// allow-file-access-from-files is not specified. Such origin is not
// opaque (i.e., IsOpaque() returns false) but still serializes to
// "null".
return origin.ToString() == "null" ? url::Origin() : origin.ToUrlOrigin();
}
// A parser for the value of the Access-Control-Expose-Headers header. // A parser for the value of the Access-Control-Expose-Headers header.
class HTTPHeaderNameListParser { class HTTPHeaderNameListParser {
STACK_ALLOCATED(); STACK_ALLOCATED();
...@@ -159,165 +100,10 @@ class HTTPHeaderNameListParser { ...@@ -159,165 +100,10 @@ class HTTPHeaderNameListParser {
namespace cors { namespace cors {
base::Optional<network::CorsErrorStatus> CheckAccess(
const KURL& response_url,
const HTTPHeaderMap& response_header,
network::mojom::CredentialsMode credentials_mode,
const SecurityOrigin& origin) {
return network::cors::CheckAccess(
response_url,
GetHeaderValue(response_header, http_names::kAccessControlAllowOrigin),
GetHeaderValue(response_header,
http_names::kAccessControlAllowCredentials),
credentials_mode, AsUrlOrigin(origin));
}
base::Optional<network::CorsErrorStatus> CheckPreflightAccess(
const KURL& response_url,
const int response_status_code,
const HTTPHeaderMap& response_header,
network::mojom::CredentialsMode actual_credentials_mode,
const SecurityOrigin& origin) {
return network::cors::CheckPreflightAccess(
response_url, response_status_code,
GetHeaderValue(response_header, http_names::kAccessControlAllowOrigin),
GetHeaderValue(response_header,
http_names::kAccessControlAllowCredentials),
actual_credentials_mode, AsUrlOrigin(origin));
}
base::Optional<network::CorsErrorStatus> CheckRedirectLocation(
const KURL& url,
network::mojom::RequestMode request_mode,
const SecurityOrigin* origin,
CorsFlag cors_flag) {
base::Optional<url::Origin> origin_to_pass;
if (origin)
origin_to_pass = AsUrlOrigin(*origin);
// Blink-side implementations rewrite the origin instead of setting the
// tainted flag.
return network::cors::CheckRedirectLocation(
url, request_mode, origin_to_pass, cors_flag == CorsFlag::Set, false);
}
base::Optional<network::CorsErrorStatus> CheckExternalPreflight(
const HTTPHeaderMap& response_header) {
return network::cors::CheckExternalPreflight(
GetHeaderValue(response_header, http_names::kAccessControlAllowExternal));
}
bool IsCorsEnabledRequestMode(network::mojom::RequestMode request_mode) { bool IsCorsEnabledRequestMode(network::mojom::RequestMode request_mode) {
return network::cors::IsCorsEnabledRequestMode(request_mode); return network::cors::IsCorsEnabledRequestMode(request_mode);
} }
base::Optional<network::CorsErrorStatus> EnsurePreflightResultAndCacheOnSuccess(
const HTTPHeaderMap& response_header_map,
const String& origin,
const KURL& request_url,
const String& request_method,
const HTTPHeaderMap& request_header_map,
network::mojom::CredentialsMode request_credentials_mode) {
DCHECK(!origin.IsNull());
DCHECK(!request_method.IsNull());
base::Optional<network::mojom::CorsError> error;
std::unique_ptr<network::cors::PreflightResult> result =
network::cors::PreflightResult::Create(
request_credentials_mode,
GetOptionalHeaderValue(response_header_map,
http_names::kAccessControlAllowMethods),
GetOptionalHeaderValue(response_header_map,
http_names::kAccessControlAllowHeaders),
GetOptionalHeaderValue(response_header_map,
http_names::kAccessControlMaxAge),
&error);
if (error)
return network::CorsErrorStatus(*error);
base::Optional<network::CorsErrorStatus> status;
status = result->EnsureAllowedCrossOriginMethod(request_method.Ascii());
if (status)
return status;
// |is_revalidating| is not needed for blink-side CORS.
constexpr bool is_revalidating = false;
status = result->EnsureAllowedCrossOriginHeaders(
*CreateNetHttpRequestHeaders(request_header_map), is_revalidating);
if (status)
return status;
GetPerThreadPreflightCache().AppendEntry(
url::Origin::Create(GURL(origin.Ascii())), request_url,
net::NetworkIsolationKey(), std::move(result));
return base::nullopt;
}
bool CheckIfRequestCanSkipPreflight(
const String& origin,
const KURL& url,
network::mojom::CredentialsMode credentials_mode,
const String& method,
const HTTPHeaderMap& request_header_map) {
DCHECK(!origin.IsNull());
DCHECK(!method.IsNull());
// |is_revalidating| is not needed for blink-side CORS.
constexpr bool is_revalidating = false;
return GetPerThreadPreflightCache().CheckIfRequestCanSkipPreflight(
url::Origin::Create(GURL(origin.Ascii())), url,
net::NetworkIsolationKey(), credentials_mode, method.Ascii(),
*CreateNetHttpRequestHeaders(request_header_map), is_revalidating);
}
// Keep this in sync with the identical function
// network::cors::CorsURLLoader::CalculateResponseTainting.
//
// This is the same as that function except using KURL and SecurityOrigin
// instead of GURL and url::Origin. We can't combine them because converting
// SecurityOrigin to url::Origin loses information about origins that are
// allowed by SecurityPolicy.
//
// This function also doesn't use a |tainted_origin| flag because Blink loaders
// mutate the origin instead of using such a flag.
network::mojom::FetchResponseType CalculateResponseTainting(
const KURL& url,
network::mojom::RequestMode request_mode,
const SecurityOrigin* origin,
const SecurityOrigin* isolated_world_origin,
CorsFlag cors_flag) {
if (url.ProtocolIsData())
return network::mojom::FetchResponseType::kBasic;
if (cors_flag == CorsFlag::Set) {
DCHECK(IsCorsEnabledRequestMode(request_mode));
return network::mojom::FetchResponseType::kCors;
}
if (!origin) {
// This is actually not defined in the fetch spec, but in this case CORS
// is disabled so no one should care this value.
return network::mojom::FetchResponseType::kBasic;
}
if (request_mode == network::mojom::RequestMode::kNoCors) {
bool can_request = origin->CanRequest(url);
if (!can_request && isolated_world_origin)
can_request = isolated_world_origin->CanRequest(url);
if (!can_request)
return network::mojom::FetchResponseType::kOpaque;
}
return network::mojom::FetchResponseType::kBasic;
}
bool CalculateCredentialsFlag(
network::mojom::CredentialsMode credentials_mode,
network::mojom::FetchResponseType response_tainting) {
return network::cors::CalculateCredentialsFlag(credentials_mode,
response_tainting);
}
bool IsCorsSafelistedMethod(const String& method) { bool IsCorsSafelistedMethod(const String& method) {
DCHECK(!method.IsNull()); DCHECK(!method.IsNull());
return network::cors::IsCorsSafelistedMethod(method.Latin1()); return network::cors::IsCorsSafelistedMethod(method.Latin1());
...@@ -327,9 +113,10 @@ bool IsCorsSafelistedContentType(const String& media_type) { ...@@ -327,9 +113,10 @@ bool IsCorsSafelistedContentType(const String& media_type) {
return network::cors::IsCorsSafelistedContentType(media_type.Latin1()); return network::cors::IsCorsSafelistedContentType(media_type.Latin1());
} }
bool IsNoCorsSafelistedHeaderName(const String& name) { bool IsNoCorsSafelistedHeader(const String& name, const String& value) {
DCHECK(!name.IsNull()); DCHECK(!name.IsNull());
return network::cors::IsNoCorsSafelistedHeaderName(name.Latin1()); DCHECK(!value.IsNull());
return network::cors::IsNoCorsSafelistedHeader(name.Latin1(), value.Latin1());
} }
bool IsPrivilegedNoCorsHeaderName(const String& name) { bool IsPrivilegedNoCorsHeaderName(const String& name) {
...@@ -337,23 +124,9 @@ bool IsPrivilegedNoCorsHeaderName(const String& name) { ...@@ -337,23 +124,9 @@ bool IsPrivilegedNoCorsHeaderName(const String& name) {
return network::cors::IsPrivilegedNoCorsHeaderName(name.Latin1()); return network::cors::IsPrivilegedNoCorsHeaderName(name.Latin1());
} }
bool IsNoCorsSafelistedHeader(const String& name, const String& value) { bool IsNoCorsSafelistedHeaderName(const String& name) {
DCHECK(!name.IsNull()); DCHECK(!name.IsNull());
DCHECK(!value.IsNull()); return network::cors::IsNoCorsSafelistedHeaderName(name.Latin1());
return network::cors::IsNoCorsSafelistedHeader(name.Latin1(), value.Latin1());
}
Vector<String> CorsUnsafeRequestHeaderNames(const HTTPHeaderMap& headers) {
net::HttpRequestHeaders::HeaderVector in;
for (const auto& entry : headers) {
in.push_back(net::HttpRequestHeaders::HeaderKeyValuePair(
entry.key.Latin1(), entry.value.Latin1()));
}
Vector<String> header_names;
for (const auto& name : network::cors::CorsUnsafeRequestHeaderNames(in))
header_names.push_back(WebString::FromLatin1(name));
return header_names;
} }
PLATFORM_EXPORT Vector<String> PrivilegedNoCorsHeaderNames() { PLATFORM_EXPORT Vector<String> PrivilegedNoCorsHeaderNames() {
...@@ -368,8 +141,13 @@ bool IsForbiddenHeaderName(const String& name) { ...@@ -368,8 +141,13 @@ bool IsForbiddenHeaderName(const String& name) {
} }
bool ContainsOnlyCorsSafelistedHeaders(const HTTPHeaderMap& header_map) { bool ContainsOnlyCorsSafelistedHeaders(const HTTPHeaderMap& header_map) {
Vector<String> header_names = CorsUnsafeRequestHeaderNames(header_map); net::HttpRequestHeaders::HeaderVector in;
return header_names.IsEmpty(); for (const auto& entry : header_map) {
in.push_back(net::HttpRequestHeaders::HeaderKeyValuePair(
entry.key.Latin1(), entry.value.Latin1()));
}
return network::cors::CorsUnsafeRequestHeaderNames(in).empty();
} }
bool ContainsOnlyCorsSafelistedOrForbiddenHeaders( bool ContainsOnlyCorsSafelistedOrForbiddenHeaders(
......
...@@ -31,78 +31,17 @@ enum class CorsFlag : uint8_t { ...@@ -31,78 +31,17 @@ enum class CorsFlag : uint8_t {
namespace cors { namespace cors {
// Thin wrapper functions below are for calling ::network::cors functions from // Thin wrapper functions below are for calling ::network::cors functions from
// Blink core. Once Out-of-renderer CORS is enabled, following functions will // Blink core.
// be removed.
PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckAccess(
const KURL&,
const HTTPHeaderMap&,
network::mojom::CredentialsMode,
const SecurityOrigin&);
PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckPreflightAccess(
const KURL&,
const int response_status_code,
const HTTPHeaderMap&,
network::mojom::CredentialsMode,
const SecurityOrigin&);
PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckRedirectLocation(
const KURL&,
network::mojom::RequestMode,
const SecurityOrigin*,
CorsFlag);
PLATFORM_EXPORT base::Optional<network::CorsErrorStatus> CheckExternalPreflight(
const HTTPHeaderMap&);
PLATFORM_EXPORT bool IsCorsEnabledRequestMode(network::mojom::RequestMode); PLATFORM_EXPORT bool IsCorsEnabledRequestMode(network::mojom::RequestMode);
PLATFORM_EXPORT base::Optional<network::CorsErrorStatus>
EnsurePreflightResultAndCacheOnSuccess(
const HTTPHeaderMap& response_header_map,
const String& origin,
const KURL& request_url,
const String& request_method,
const HTTPHeaderMap& request_header_map,
network::mojom::CredentialsMode request_credentials_mode);
PLATFORM_EXPORT bool CheckIfRequestCanSkipPreflight(
const String& origin,
const KURL&,
network::mojom::CredentialsMode,
const String& method,
const HTTPHeaderMap& request_header_map);
// Returns the response tainting value
// (https://fetch.spec.whatwg.org/#concept-request-response-tainting) for a
// request and the CORS flag, as specified in
// https://fetch.spec.whatwg.org/#main-fetch.
PLATFORM_EXPORT network::mojom::FetchResponseType CalculateResponseTainting(
const KURL& url,
network::mojom::RequestMode request_mode,
const SecurityOrigin* origin,
const SecurityOrigin* isolated_world_origin,
CorsFlag cors_flag);
PLATFORM_EXPORT bool CalculateCredentialsFlag(
network::mojom::CredentialsMode credentials_mode,
network::mojom::FetchResponseType response_tainting);
// Thin wrapper functions that will not be removed even after out-of-renderer
// CORS is enabled.
PLATFORM_EXPORT bool IsCorsSafelistedMethod(const String& method); PLATFORM_EXPORT bool IsCorsSafelistedMethod(const String& method);
PLATFORM_EXPORT bool IsCorsSafelistedContentType(const String&); PLATFORM_EXPORT bool IsCorsSafelistedContentType(const String&);
PLATFORM_EXPORT bool IsNoCorsSafelistedHeader(const String& name, PLATFORM_EXPORT bool IsNoCorsSafelistedHeader(const String& name,
const String& value); const String& value);
PLATFORM_EXPORT bool IsPrivilegedNoCorsHeaderName(const String& name); PLATFORM_EXPORT bool IsPrivilegedNoCorsHeaderName(const String& name);
PLATFORM_EXPORT bool IsNoCorsSafelistedHeaderName(const String& name); PLATFORM_EXPORT bool IsNoCorsSafelistedHeaderName(const String& name);
PLATFORM_EXPORT Vector<String> CorsUnsafeRequestHeaderNames(
const HTTPHeaderMap& headers);
PLATFORM_EXPORT Vector<String> PrivilegedNoCorsHeaderNames(); PLATFORM_EXPORT Vector<String> PrivilegedNoCorsHeaderNames();
PLATFORM_EXPORT bool IsForbiddenHeaderName(const String& name); PLATFORM_EXPORT bool IsForbiddenHeaderName(const String& name);
PLATFORM_EXPORT bool ContainsOnlyCorsSafelistedHeaders(const HTTPHeaderMap&); PLATFORM_EXPORT bool ContainsOnlyCorsSafelistedHeaders(const HTTPHeaderMap&);
PLATFORM_EXPORT bool ContainsOnlyCorsSafelistedOrForbiddenHeaders(
const HTTPHeaderMap&);
PLATFORM_EXPORT bool IsOkStatus(int status); PLATFORM_EXPORT bool IsOkStatus(int status);
...@@ -114,7 +53,6 @@ PLATFORM_EXPORT bool IsOkStatus(int status); ...@@ -114,7 +53,6 @@ PLATFORM_EXPORT bool IsOkStatus(int status);
// |kNavigate|. // |kNavigate|.
// This should be identical to CalculateCorsFlag defined in // This should be identical to CalculateCorsFlag defined in
// //services/network/cors/cors_url_loader.cc. // //services/network/cors/cors_url_loader.cc.
// This function will be removed when out-of-renderer CORS is enabled.
PLATFORM_EXPORT bool CalculateCorsFlag( PLATFORM_EXPORT bool CalculateCorsFlag(
const KURL& url, const KURL& url,
const SecurityOrigin* initiator_origin, const SecurityOrigin* initiator_origin,
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink { namespace blink {
...@@ -101,87 +100,6 @@ TEST_F(CorsExposedHeadersTest, Asterisk) { ...@@ -101,87 +100,6 @@ TEST_F(CorsExposedHeadersTest, Asterisk) {
HTTPHeaderSet({"a", "b", "*"})); HTTPHeaderSet({"a", "b", "*"}));
} }
// Keep this in sync with the CalculateResponseTainting test in
// services/network/cors/cors_url_loader_unittest.cc.
TEST(CorsTest, CalculateResponseTainting) {
using network::mojom::FetchResponseType;
using network::mojom::RequestMode;
const KURL same_origin_url("https://example.com/");
const KURL cross_origin_url("https://example2.com/");
scoped_refptr<SecurityOrigin> origin_refptr =
SecurityOrigin::Create(same_origin_url);
const SecurityOrigin* origin = origin_refptr.get();
const SecurityOrigin* no_origin = nullptr;
// CORS flag is false, same-origin request
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kSameOrigin,
origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNoCors,
origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kCors,
origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(FetchResponseType::kBasic,
cors::CalculateResponseTainting(
same_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNavigate,
origin, nullptr, CorsFlag::Unset));
// CORS flag is false, cross-origin request
EXPECT_EQ(
FetchResponseType::kOpaque,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNoCors,
origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNavigate,
origin, nullptr, CorsFlag::Unset));
// CORS flag is true, same-origin request
EXPECT_EQ(FetchResponseType::kCors,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kCors,
origin, nullptr, CorsFlag::Set));
EXPECT_EQ(FetchResponseType::kCors,
cors::CalculateResponseTainting(
same_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
nullptr, CorsFlag::Set));
// CORS flag is true, cross-origin request
EXPECT_EQ(FetchResponseType::kCors, cors::CalculateResponseTainting(
cross_origin_url, RequestMode::kCors,
origin, nullptr, CorsFlag::Set));
EXPECT_EQ(FetchResponseType::kCors,
cors::CalculateResponseTainting(
cross_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
nullptr, CorsFlag::Set));
// Origin is not provided.
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNoCors,
no_origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNavigate,
no_origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNoCors,
no_origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNavigate,
no_origin, nullptr, CorsFlag::Unset));
}
} // namespace } // namespace
} // namespace blink } // namespace blink
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