Commit a738266c authored by arthursonzogni's avatar arthursonzogni Committed by Commit Bot

[ParsedHeaders](1/n) Move SW CSP parsing to http_parser.

On 2019-09-27, lfg@ added support for parsing CSP for navigation
response provided by the ServiceWorker.
See https://chromium-review.googlesource.com/c/chromium/src/+/1819631

This patch is an alternative version of:
https://chromium-review.googlesource.com/c/chromium/src/+/2126933

What is not kept:

0) Automatically convert blink/non-blink typed using mojo.
   As a result all the ConvertToBlink functions remained.

What is kept:

1) Move the part from the ServiceWorker about parsing CSP toward the
   blink http_parser.

2) Use the HttpResponseHeader instead of the HTTP field values.
   This will help with ParsedHeader in the following patch:
   https://chromium-review.googlesource.com/c/chromium/src/+/2122647/11

Bug: 1063832
Change-Id: I7721e846f0fd14b6a8517d25b4e9cd39d0c77061
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2134246
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarLucas Gadani <lfg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757002}
parent 03c26aeb
......@@ -104,6 +104,23 @@ bool FetchHeaderList::Get(const String& name, String& result) const {
return found;
}
String FetchHeaderList::GetAsRawString(int status_code,
String status_message) const {
StringBuilder builder;
builder.Append("HTTP/1.1 ");
builder.AppendNumber(status_code);
builder.Append(" ");
builder.Append(status_message);
builder.Append("\r\n");
for (auto& it : header_list_) {
builder.Append(it.first);
builder.Append(":");
builder.Append(it.second);
builder.Append("\r\n");
}
return builder.ToString();
}
bool FetchHeaderList::Has(const String& name) const {
// https://fetch.spec.whatwg.org/#header-list-contains
// "A header list (|list|) contains a name (|name|) if |list| contains a
......
......@@ -37,6 +37,7 @@ class CORE_EXPORT FetchHeaderList final
size_t size() const;
void Remove(const String&);
bool Get(const String&, String&) const;
String GetAsRawString(int status_code, String status_message) const;
bool Has(const String&) const;
void ClearList();
......
......@@ -4,9 +4,6 @@
#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
#include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
......@@ -15,76 +12,13 @@
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "url/gurl.h"
using Type = network::mojom::FetchResponseType;
using ResponseSource = network::mojom::FetchResponseSource;
// TODO(lfg): Stop converting from/to blink type. Instead use mojo to
// automagically convert this.
namespace network {
namespace mojom {
blink::CSPSourcePtr ConvertToBlink(CSPSourcePtr source) {
return blink::CSPSource::New(
String::FromUTF8(source->scheme), String::FromUTF8(source->host),
source->port, String::FromUTF8(source->path), source->is_host_wildcard,
source->is_port_wildcard);
}
blink::CSPSourceListPtr ConvertToBlink(CSPSourceListPtr source_list) {
WTF::Vector<blink::CSPSourcePtr> sources;
for (auto& it : source_list->sources)
sources.push_back(ConvertToBlink(std::move(it)));
return blink::CSPSourceList::New(std::move(sources), source_list->allow_self,
source_list->allow_star,
source_list->allow_response_redirects);
}
blink::CSPDirectiveName ConvertToBlink(CSPDirectiveName name) {
return static_cast<blink::CSPDirectiveName>(name);
}
blink::ContentSecurityPolicyHeaderPtr ConvertToBlink(
ContentSecurityPolicyHeaderPtr header) {
return blink::ContentSecurityPolicyHeader::New(
String::FromUTF8(header->header_value), header->type, header->source);
}
blink::ContentSecurityPolicyPtr ConvertToBlink(
ContentSecurityPolicyPtr policy_in) {
auto policy = blink::ContentSecurityPolicy::New();
policy->header = ConvertToBlink(std::move(policy_in->header));
policy->use_reporting_api = policy_in->use_reporting_api;
for (auto& directive : policy_in->directives) {
policy->directives.insert(ConvertToBlink(directive.first),
ConvertToBlink(std::move(directive.second)));
}
for (auto& endpoint : policy_in->report_endpoints)
policy->report_endpoints.push_back(String::FromUTF8(endpoint));
return policy;
}
WTF::Vector<blink::ContentSecurityPolicyPtr> ConvertToBlink(
std::vector<ContentSecurityPolicyPtr> policies) {
WTF::Vector<blink::ContentSecurityPolicyPtr> blink_policies;
for (auto& policy : policies)
blink_policies.push_back(ConvertToBlink(std::move(policy)));
return blink_policies;
}
} // namespace mojom
} // namespace network
namespace blink {
namespace {
......@@ -331,30 +265,8 @@ mojom::blink::FetchAPIResponsePtr FetchResponseData::PopulateFetchAPIResponse(
response->loaded_with_credentials = loaded_with_credentials_;
for (const auto& header : HeaderList()->List())
response->headers.insert(header.first, header.second);
// Check if there's a Content-Security-Policy header and parse it if
// necessary.
// TODO(lfg). What about report only header?
if (base::FeatureList::IsEnabled(
network::features::kOutOfBlinkFrameAncestors)) {
String content_security_policy_header;
std::vector<network::mojom::ContentSecurityPolicyPtr> policies;
if (HeaderList()->Get("content-security-policy",
content_security_policy_header)) {
network::AddContentSecurityPolicyFromHeaders(
StringUTF8Adaptor(content_security_policy_header).AsStringPiece(),
network::mojom::ContentSecurityPolicyType::kEnforce, request_url,
&policies);
}
if (HeaderList()->Get("content-security-policy-report-only",
content_security_policy_header)) {
network::AddContentSecurityPolicyFromHeaders(
StringUTF8Adaptor(content_security_policy_header).AsStringPiece(),
network::mojom::ContentSecurityPolicyType::kReport, request_url,
&policies);
}
response->content_security_policy = ConvertToBlink(std::move(policies));
}
response->content_security_policy = ParseContentSecurityPolicy(
HeaderList()->GetAsRawString(status_, status_message_), request_url);
return response;
}
......
......@@ -18,7 +18,6 @@
#include "third_party/blink/renderer/platform/network/http_header_set.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
......
......@@ -36,6 +36,9 @@
#include "net/http/http_content_disposition.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/header_field_tokenizer.h"
......@@ -50,6 +53,69 @@
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
// We would like finding a way to convert from/to blink type automatically.
// The following attempt has been withdrawn:
// https://chromium-review.googlesource.com/c/chromium/src/+/2126933/7
namespace network {
namespace mojom {
blink::CSPSourcePtr ConvertToBlink(CSPSourcePtr source) {
return blink::CSPSource::New(
String::FromUTF8(source->scheme), String::FromUTF8(source->host),
source->port, String::FromUTF8(source->path), source->is_host_wildcard,
source->is_port_wildcard);
}
blink::CSPSourceListPtr ConvertToBlink(CSPSourceListPtr source_list) {
WTF::Vector<blink::CSPSourcePtr> sources;
for (auto& it : source_list->sources)
sources.push_back(ConvertToBlink(std::move(it)));
return blink::CSPSourceList::New(std::move(sources), source_list->allow_self,
source_list->allow_star,
source_list->allow_response_redirects);
}
blink::CSPDirectiveName ConvertToBlink(CSPDirectiveName name) {
return static_cast<blink::CSPDirectiveName>(name);
}
blink::ContentSecurityPolicyHeaderPtr ConvertToBlink(
ContentSecurityPolicyHeaderPtr header) {
return blink::ContentSecurityPolicyHeader::New(
String::FromUTF8(header->header_value), header->type, header->source);
}
blink::ContentSecurityPolicyPtr ConvertToBlink(
ContentSecurityPolicyPtr policy_in) {
auto policy = blink::ContentSecurityPolicy::New();
policy->header = ConvertToBlink(std::move(policy_in->header));
policy->use_reporting_api = policy_in->use_reporting_api;
for (auto& directive : policy_in->directives) {
policy->directives.insert(ConvertToBlink(directive.first),
ConvertToBlink(std::move(directive.second)));
}
for (auto& endpoint : policy_in->report_endpoints)
policy->report_endpoints.push_back(String::FromUTF8(endpoint));
return policy;
}
WTF::Vector<blink::ContentSecurityPolicyPtr> ConvertToBlink(
std::vector<ContentSecurityPolicyPtr> policies) {
WTF::Vector<blink::ContentSecurityPolicyPtr> blink_policies;
for (auto& policy : policies)
blink_policies.push_back(ConvertToBlink(std::move(policy)));
return blink_policies;
}
} // namespace mojom
} // namespace network
namespace blink {
namespace {
......@@ -600,4 +666,21 @@ std::unique_ptr<ServerTimingHeaderVector> ParseServerTimingHeader(
return headers;
}
// This function is simply calling network::AddContentSecurityPolicyFromHeaders
// and convert from/to blink types. It is used for navigation requests served by
// a ServiceWorker. It is tested by FetchResponseDataTest.ContentSecurityPolicy.
WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr>
ParseContentSecurityPolicy(const String& raw_headers, const KURL& url) {
if (!base::FeatureList::IsEnabled(
network::features::kOutOfBlinkFrameAncestors)) {
return {};
}
auto headers = base::MakeRefCounted<net::HttpResponseHeaders>(
net::HttpUtil::AssembleRawHeaders(raw_headers.Latin1()));
std::vector<network::mojom::ContentSecurityPolicyPtr> policies;
network::AddContentSecurityPolicyFromHeaders(*headers, url, &policies);
return network::mojom::ConvertToBlink(std::move(policies));
}
} // namespace blink
......@@ -33,6 +33,7 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "services/network/public/mojom/content_security_policy.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
#include "third_party/blink/renderer/platform/network/server_timing_header.h"
#include "third_party/blink/renderer/platform/platform_export.h"
......@@ -49,6 +50,7 @@ namespace blink {
class HTTPHeaderMap;
class ResourceResponse;
class KURL;
enum ContentTypeOptionsDisposition {
kContentTypeOptionsNone,
......@@ -141,6 +143,13 @@ PLATFORM_EXPORT bool ParseContentRangeHeaderFor206(const String& content_range,
PLATFORM_EXPORT std::unique_ptr<ServerTimingHeaderVector>
ParseServerTimingHeader(const String&);
// Parse CSP ContentSecurityPolicy from raw headers.
// This is the same as network::AddContentSecurityPolicyFromHeaders(), but using
// blink types.
PLATFORM_EXPORT WTF::Vector<network::mojom::blink::ContentSecurityPolicyPtr>
ParseContentSecurityPolicy(const String& raw_headers, const KURL& url);
} // namespace blink
#endif
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