Commit 0be148b8 authored by Maks Orlovich's avatar Maks Orlovich Committed by Commit Bot

Move Accept-CH parsing code into services/network/public/cpp

We need to handle it in the browser for navigation redirects;
which by upcoming security rules means that the network service
should parse it, which requires the code to be in services/network

The renderer also needs to parse it, so it needs to be in
services/network/public/cpp.

Also ParseAceptCH got split into ParseAcceptCH and FilterAcceptCH along the way,
since it feels like network service shouldn't know about browser
experiments on what hints to support.

Bug: 1050726
Change-Id: I4b10ce6ddf97efd852a44d4c8a4f85a9a6a0c404
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2124734
Commit-Queue: Maksim Orlovich <morlovich@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756826}
parent 30312696
...@@ -17,6 +17,8 @@ jumbo_component("cpp") { ...@@ -17,6 +17,8 @@ jumbo_component("cpp") {
output_name = "network_cpp" output_name = "network_cpp"
sources = [ sources = [
"client_hints.cc",
"client_hints.h",
"constants.cc", "constants.cc",
"constants.h", "constants.h",
"content_security_policy/content_security_policy.cc", "content_security_policy/content_security_policy.cc",
...@@ -229,6 +231,7 @@ source_set("tests") { ...@@ -229,6 +231,7 @@ source_set("tests") {
testonly = true testonly = true
sources = [ sources = [
"client_hints_unittest.cc",
"content_security_policy/content_security_policy_unittest.cc", "content_security_policy/content_security_policy_unittest.cc",
"content_security_policy/csp_context_unittest.cc", "content_security_policy/csp_context_unittest.cc",
"content_security_policy/csp_source_list_unittest.cc", "content_security_policy/csp_source_list_unittest.cc",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/public/cpp/client_hints.h"
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/no_destructor.h"
#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/http/structured_headers.h"
namespace network {
const char* const kClientHintsNameMapping[] = {"device-memory",
"dpr",
"width",
"viewport-width",
"rtt",
"downlink",
"ect",
"lang",
"ua",
"ua-arch",
"ua-platform",
"ua-model",
"ua-mobile",
"ua-full-version"};
const size_t kClientHintsMappingsCount = base::size(kClientHintsNameMapping);
static_assert(
base::size(kClientHintsNameMapping) ==
(static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) + 1),
"Client Hint name table size must match network::mojom::WebClientHintsType "
"range");
namespace {
struct ClientHintNameCompator {
bool operator()(const std::string& lhs, const std::string& rhs) const {
return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0;
}
};
using DecodeMap = base::flat_map<std::string,
network::mojom::WebClientHintsType,
ClientHintNameCompator>;
DecodeMap MakeDecodeMap() {
DecodeMap result;
for (size_t i = 0;
i < static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) + 1;
++i) {
result.insert(
std::make_pair(kClientHintsNameMapping[i],
static_cast<network::mojom::WebClientHintsType>(i)));
}
return result;
}
const DecodeMap& GetDecodeMap() {
static const base::NoDestructor<DecodeMap> decode_map(MakeDecodeMap());
return *decode_map;
}
} // namespace
base::Optional<std::vector<network::mojom::WebClientHintsType>> ParseAcceptCH(
const std::string& header) {
// Accept-CH is an sh-list of tokens; see:
// https://httpwg.org/http-extensions/client-hints.html#rfc.section.3.1
base::Optional<net::structured_headers::List> maybe_list =
net::structured_headers::ParseList(header);
if (!maybe_list.has_value())
return base::nullopt;
// Standard validation rules: we want a list of tokens, so this better
// only have tokens (but params are OK!)
for (const auto& list_item : maybe_list.value()) {
// Make sure not a nested list.
if (list_item.member.size() != 1u)
return base::nullopt;
if (!list_item.member[0].item.is_token())
return base::nullopt;
}
std::vector<network::mojom::WebClientHintsType> result;
// Now convert those to actual hint enums.
const DecodeMap& decode_map = GetDecodeMap();
for (const auto& list_item : maybe_list.value()) {
const std::string& token_value = list_item.member[0].item.GetString();
auto iter = decode_map.find(token_value);
if (iter != decode_map.end())
result.push_back(iter->second);
} // for list_item
return base::make_optional(std::move(result));
}
} // namespace network
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_PUBLIC_CPP_CLIENT_HINTS_H_
#define SERVICES_NETWORK_PUBLIC_CPP_CLIENT_HINTS_H_
#include <stddef.h>
#include <string>
#include "base/component_export.h"
#include "base/optional.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
namespace network {
// Mapping from WebClientHintsType to the hint's name in Accept-CH header.
// The ordering matches the ordering of enums in
// services/network/public/mojom/web_client_hints_types.mojom
COMPONENT_EXPORT(NETWORK_CPP)
extern const char* const kClientHintsNameMapping[];
COMPONENT_EXPORT(NETWORK_CPP) extern const size_t kClientHintsMappingsCount;
// Tries to parse an Accept-CH header. Returns base::nullopt if parsing
// failed and the header should be ignored; otherwise returns a (possibly
// empty) list of hints to accept.
base::Optional<std::vector<network::mojom::WebClientHintsType>>
COMPONENT_EXPORT(NETWORK_CPP) ParseAcceptCH(const std::string& header);
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_CLIENT_HINTS_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/public/cpp/client_hints.h"
#include <iostream>
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::UnorderedElementsAre;
namespace network {
TEST(ClientHintsTest, ParseAcceptCH) {
base::Optional<std::vector<network::mojom::WebClientHintsType>> result;
// Empty is OK.
result = ParseAcceptCH(" ");
ASSERT_TRUE(result.has_value());
EXPECT_TRUE(result.value().empty());
// Normal case.
result = ParseAcceptCH("device-memory, rtt, lang ");
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang));
// Must be a list of tokens, not other things.
result = ParseAcceptCH("\"device-memory\", \"rtt\", \"lang\"");
EXPECT_FALSE(result.has_value());
// Parameters to the tokens are ignored, as encourageed by structured headers
// spec.
result = ParseAcceptCH("device-memory;resolution=GIB, rtt, lang");
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang));
// Unknown tokens are fine, since this meant to be extensible.
result = ParseAcceptCH("device-memory, rtt, lang , nosuchtokenwhywhywhy");
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang));
}
TEST(ClientHintsTest, ParseAcceptCHCaseInsensitive) {
base::Optional<std::vector<network::mojom::WebClientHintsType>> result;
// Matching is case-insensitive.
result = ParseAcceptCH("Device-meMory, Rtt, lanG ");
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang));
}
} // namespace network
...@@ -7,31 +7,13 @@ ...@@ -7,31 +7,13 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/containers/flat_map.h"
#include "base/no_destructor.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/string_tokenizer.h" #include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "net/http/structured_headers.h"
namespace blink { namespace blink {
const char* const kClientHintsNameMapping[] = {"device-memory",
"dpr",
"width",
"viewport-width",
"rtt",
"downlink",
"ect",
"lang",
"ua",
"ua-arch",
"ua-platform",
"ua-model",
"ua-mobile",
"ua-full-version"};
const char* const kClientHintsHeaderMapping[] = { const char* const kClientHintsHeaderMapping[] = {
"device-memory", "device-memory",
"dpr", "dpr",
...@@ -49,15 +31,10 @@ const char* const kClientHintsHeaderMapping[] = { ...@@ -49,15 +31,10 @@ const char* const kClientHintsHeaderMapping[] = {
"sec-ch-ua-full-version", "sec-ch-ua-full-version",
}; };
const size_t kClientHintsMappingsCount = base::size(kClientHintsNameMapping); const size_t kClientHintsMappingsCount = base::size(kClientHintsHeaderMapping);
static_assert(base::size(kClientHintsNameMapping) ==
base::size(kClientHintsHeaderMapping),
"The Client Hint name and header mappings must contain the same "
"number of entries.");
static_assert( static_assert(
base::size(kClientHintsNameMapping) == base::size(kClientHintsHeaderMapping) ==
(static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) + 1), (static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) + 1),
"Client Hint name table size must match network::mojom::WebClientHintsType " "Client Hint name table size must match network::mojom::WebClientHintsType "
"range"); "range");
...@@ -70,37 +47,6 @@ const char* const kWebEffectiveConnectionTypeMapping[] = { ...@@ -70,37 +47,6 @@ const char* const kWebEffectiveConnectionTypeMapping[] = {
const size_t kWebEffectiveConnectionTypeMappingCount = const size_t kWebEffectiveConnectionTypeMappingCount =
base::size(kWebEffectiveConnectionTypeMapping); base::size(kWebEffectiveConnectionTypeMapping);
namespace {
struct ClientHintNameCompator {
bool operator()(const std::string& lhs, const std::string& rhs) const {
return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0;
}
};
using DecodeMap = base::flat_map<std::string,
network::mojom::WebClientHintsType,
ClientHintNameCompator>;
DecodeMap MakeDecodeMap() {
DecodeMap result;
for (size_t i = 0;
i < static_cast<int>(network::mojom::WebClientHintsType::kMaxValue) + 1;
++i) {
result.insert(
std::make_pair(kClientHintsNameMapping[i],
static_cast<network::mojom::WebClientHintsType>(i)));
}
return result;
}
const DecodeMap& GetDecodeMap() {
static const base::NoDestructor<DecodeMap> decode_map(MakeDecodeMap());
return *decode_map;
}
} // namespace
std::string SerializeLangClientHint(const std::string& raw_language_list) { std::string SerializeLangClientHint(const std::string& raw_language_list) {
base::StringTokenizer t(raw_language_list, ","); base::StringTokenizer t(raw_language_list, ",");
std::string result; std::string result;
...@@ -115,38 +61,15 @@ std::string SerializeLangClientHint(const std::string& raw_language_list) { ...@@ -115,38 +61,15 @@ std::string SerializeLangClientHint(const std::string& raw_language_list) {
return result; return result;
} }
base::Optional<std::vector<network::mojom::WebClientHintsType>> ParseAcceptCH( base::Optional<std::vector<network::mojom::WebClientHintsType>> FilterAcceptCH(
const std::string& header, base::Optional<std::vector<network::mojom::WebClientHintsType>> in,
bool permit_lang_hints, bool permit_lang_hints,
bool permit_ua_hints) { bool permit_ua_hints) {
// Accept-CH is an sh-list of tokens; see: if (!in.has_value())
// https://httpwg.org/http-extensions/client-hints.html#rfc.section.3.1
base::Optional<net::structured_headers::List> maybe_list =
net::structured_headers::ParseList(header);
if (!maybe_list.has_value())
return base::nullopt;
// Standard validation rules: we want a list of tokens, so this better
// only have tokens (but params are OK!)
for (const auto& list_item : maybe_list.value()) {
// Make sure not a nested list.
if (list_item.member.size() != 1u)
return base::nullopt; return base::nullopt;
if (!list_item.member[0].item.is_token())
return base::nullopt;
}
std::vector<network::mojom::WebClientHintsType> result; std::vector<network::mojom::WebClientHintsType> result;
for (network::mojom::WebClientHintsType hint : in.value()) {
// Now convert those to actual hint enums.
const DecodeMap& decode_map = GetDecodeMap();
for (const auto& list_item : maybe_list.value()) {
const std::string& token_value = list_item.member[0].item.GetString();
auto iter = decode_map.find(token_value);
if (iter != decode_map.end()) {
network::mojom::WebClientHintsType hint = iter->second;
// Some hints are supported only conditionally. // Some hints are supported only conditionally.
switch (hint) { switch (hint) {
case network::mojom::WebClientHintsType::kLang: case network::mojom::WebClientHintsType::kLang:
...@@ -164,9 +87,8 @@ base::Optional<std::vector<network::mojom::WebClientHintsType>> ParseAcceptCH( ...@@ -164,9 +87,8 @@ base::Optional<std::vector<network::mojom::WebClientHintsType>> ParseAcceptCH(
break; break;
default: default:
result.push_back(hint); result.push_back(hint);
} // switch (hint) }
} // if iter != end }
} // for list_item
return base::make_optional(std::move(result)); return base::make_optional(std::move(result));
} }
......
...@@ -14,15 +14,6 @@ using testing::UnorderedElementsAre; ...@@ -14,15 +14,6 @@ using testing::UnorderedElementsAre;
namespace blink { namespace blink {
namespace mojom {
void PrintTo(const network::mojom::WebClientHintsType& value,
std::ostream* os) {
*os << ::testing::PrintToString(static_cast<int>(value));
}
} // namespace mojom
TEST(ClientHintsTest, SerializeLangClientHint) { TEST(ClientHintsTest, SerializeLangClientHint) {
std::string header = SerializeLangClientHint(""); std::string header = SerializeLangClientHint("");
EXPECT_TRUE(header.empty()); EXPECT_TRUE(header.empty());
...@@ -38,77 +29,16 @@ TEST(ClientHintsTest, SerializeLangClientHint) { ...@@ -38,77 +29,16 @@ TEST(ClientHintsTest, SerializeLangClientHint) {
header); header);
} }
TEST(ClientHintsTest, ParseAcceptCH) { TEST(ClientHintsTest, FilterAcceptCH) {
base::Optional<std::vector<network::mojom::WebClientHintsType>> result; EXPECT_FALSE(FilterAcceptCH(base::nullopt, true, true).has_value());
// Empty is OK.
result = ParseAcceptCH(" ",
/* permit_lang_hints = */ true,
/* permit_ua_hints = */ true);
ASSERT_TRUE(result.has_value());
EXPECT_TRUE(result.value().empty());
// Normal case.
result = ParseAcceptCH("device-memory, rtt, lang ",
/* permit_lang_hints = */ true,
/* permit_ua_hints = */ true);
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang));
// Must be a list of tokens, not other things.
result = ParseAcceptCH("\"device-memory\", \"rtt\", \"lang\"",
/* permit_lang_hints = */ true,
/* permit_ua_hints = */ true);
EXPECT_FALSE(result.has_value());
// Parameters to the tokens are ignored, as encourageed by structured headers
// spec.
result = ParseAcceptCH("device-memory;resolution=GIB, rtt, lang",
/* permit_lang_hints = */ true,
/* permit_ua_hints = */ true);
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang));
// Unknown tokens are fine, since this meant to be extensible.
result = ParseAcceptCH("device-memory, rtt, lang , nosuchtokenwhywhywhy",
/* permit_lang_hints = */ true,
/* permit_ua_hints = */ true);
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang));
}
TEST(ClientHintsTest, ParseAcceptCHCaseInsensitive) {
base::Optional<std::vector<network::mojom::WebClientHintsType>> result; base::Optional<std::vector<network::mojom::WebClientHintsType>> result;
// Matching is case-insensitive. result =
result = ParseAcceptCH("Device-meMory, Rtt, lanG ", FilterAcceptCH(std::vector<network::mojom::WebClientHintsType>(
/* permit_lang_hints = */ true, {network::mojom::WebClientHintsType::kDeviceMemory,
/* permit_ua_hints = */ true);
ASSERT_TRUE(result.has_value());
EXPECT_THAT(
result.value(),
UnorderedElementsAre(network::mojom::WebClientHintsType::kDeviceMemory,
network::mojom::WebClientHintsType::kRtt, network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang)); network::mojom::WebClientHintsType::kUA}),
}
// Checks to make sure that language-controlled things are filtered.
TEST(ClientHintsTest, ParseAcceptCHFlag) {
base::Optional<std::vector<network::mojom::WebClientHintsType>> result;
result = ParseAcceptCH("device-memory, rtt, lang, ua",
/* permit_lang_hints = */ false, /* permit_lang_hints = */ false,
/* permit_ua_hints = */ true); /* permit_ua_hints = */ true);
ASSERT_TRUE(result.has_value()); ASSERT_TRUE(result.has_value());
...@@ -118,7 +48,17 @@ TEST(ClientHintsTest, ParseAcceptCHFlag) { ...@@ -118,7 +48,17 @@ TEST(ClientHintsTest, ParseAcceptCHFlag) {
network::mojom::WebClientHintsType::kRtt, network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kUA)); network::mojom::WebClientHintsType::kUA));
result = ParseAcceptCH("rtt, lang, ua, arch, platform, model, mobile", std::vector<network::mojom::WebClientHintsType> in{
network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang,
network::mojom::WebClientHintsType::kUA,
network::mojom::WebClientHintsType::kUAArch,
network::mojom::WebClientHintsType::kUAPlatform,
network::mojom::WebClientHintsType::kUAModel,
network::mojom::WebClientHintsType::kUAMobile,
network::mojom::WebClientHintsType::kUAFullVersion};
result = FilterAcceptCH(in,
/* permit_lang_hints = */ true, /* permit_lang_hints = */ true,
/* permit_ua_hints = */ false); /* permit_ua_hints = */ false);
ASSERT_TRUE(result.has_value()); ASSERT_TRUE(result.has_value());
...@@ -126,8 +66,7 @@ TEST(ClientHintsTest, ParseAcceptCHFlag) { ...@@ -126,8 +66,7 @@ TEST(ClientHintsTest, ParseAcceptCHFlag) {
UnorderedElementsAre(network::mojom::WebClientHintsType::kRtt, UnorderedElementsAre(network::mojom::WebClientHintsType::kRtt,
network::mojom::WebClientHintsType::kLang)); network::mojom::WebClientHintsType::kLang));
result = result = FilterAcceptCH(in,
ParseAcceptCH("rtt, lang, ua, ua-arch, ua-platform, ua-model, ua-mobile",
/* permit_lang_hints = */ true, /* permit_lang_hints = */ true,
/* permit_ua_hints = */ true); /* permit_ua_hints = */ true);
ASSERT_TRUE(result.has_value()); ASSERT_TRUE(result.has_value());
...@@ -139,9 +78,10 @@ TEST(ClientHintsTest, ParseAcceptCHFlag) { ...@@ -139,9 +78,10 @@ TEST(ClientHintsTest, ParseAcceptCHFlag) {
network::mojom::WebClientHintsType::kUAArch, network::mojom::WebClientHintsType::kUAArch,
network::mojom::WebClientHintsType::kUAPlatform, network::mojom::WebClientHintsType::kUAPlatform,
network::mojom::WebClientHintsType::kUAModel, network::mojom::WebClientHintsType::kUAModel,
network::mojom::WebClientHintsType::kUAMobile)); network::mojom::WebClientHintsType::kUAMobile,
network::mojom::WebClientHintsType::kUAFullVersion));
result = ParseAcceptCH("rtt, lang, ua, arch, platform, model, mobile", result = FilterAcceptCH(in,
/* permit_lang_hints = */ false, /* permit_lang_hints = */ false,
/* permit_ua_hints = */ false); /* permit_ua_hints = */ false);
ASSERT_TRUE(result.has_value()); ASSERT_TRUE(result.has_value());
......
...@@ -14,11 +14,9 @@ ...@@ -14,11 +14,9 @@
namespace blink { namespace blink {
// Mapping from WebClientHintsType to the hint's name in header values (e.g. // Mapping from WebClientHintsType to the hint's to the hint's outgoing header
// kLang => "lang"), and to the hint's outgoing header (e.g. kLang => // (e.g. kLang => "sec-ch-lang"). The ordering matches the ordering of enums in
// "sec-ch-lang"). The ordering matches the ordering of enums in // services/network/public/mojom/web_client_hints_types.mojom
// third_party/blink/public/platform/web_client_hints_type.h.
BLINK_COMMON_EXPORT extern const char* const kClientHintsNameMapping[];
BLINK_COMMON_EXPORT extern const char* const kClientHintsHeaderMapping[]; BLINK_COMMON_EXPORT extern const char* const kClientHintsHeaderMapping[];
BLINK_COMMON_EXPORT extern const size_t kClientHintsMappingsCount; BLINK_COMMON_EXPORT extern const size_t kClientHintsMappingsCount;
...@@ -39,14 +37,13 @@ BLINK_COMMON_EXPORT extern const size_t kWebEffectiveConnectionTypeMappingCount; ...@@ -39,14 +37,13 @@ BLINK_COMMON_EXPORT extern const size_t kWebEffectiveConnectionTypeMappingCount;
std::string BLINK_COMMON_EXPORT std::string BLINK_COMMON_EXPORT
SerializeLangClientHint(const std::string& raw_language_list); SerializeLangClientHint(const std::string& raw_language_list);
// Tries to parse an Accept-CH header. Returns base::nullopt if parsing // Filters a parsed accept-CH list to exclude clients hints support for which
// failed and the header should be ignored; otherwise returns a (possibly // is currently conditional on experiments:
// empty) list of hints to accept. // Language hints will only be kept if |permit_lang_hints| is true;
//
// Language hints will only be in the result if |permit_lang_hints| is true;
// UA-related ones if |permit_ua_hints| is. // UA-related ones if |permit_ua_hints| is.
base::Optional<std::vector<network::mojom::WebClientHintsType>> BLINK_COMMON_EXPORT
BLINK_COMMON_EXPORT ParseAcceptCH(const std::string& header, base::Optional<std::vector<network::mojom::WebClientHintsType>> FilterAcceptCH(
base::Optional<std::vector<network::mojom::WebClientHintsType>> in,
bool permit_lang_hints, bool permit_lang_hints,
bool permit_ua_hints); bool permit_ua_hints);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h" #include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
#include "base/macros.h" #include "base/macros.h"
#include "services/network/public/cpp/client_hints.h"
#include "third_party/blink/public/common/client_hints/client_hints.h" #include "third_party/blink/public/common/client_hints/client_hints.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/network/http_parsers.h" #include "third_party/blink/renderer/platform/network/http_parsers.h"
...@@ -51,7 +52,7 @@ void ClientHintsPreferences::UpdateFromAcceptClientHintsHeader( ...@@ -51,7 +52,7 @@ void ClientHintsPreferences::UpdateFromAcceptClientHintsHeader(
// Note: .Ascii() would convert tab to ?, which is undesirable. // Note: .Ascii() would convert tab to ?, which is undesirable.
base::Optional<std::vector<network::mojom::WebClientHintsType>> parsed_ch = base::Optional<std::vector<network::mojom::WebClientHintsType>> parsed_ch =
ParseAcceptCH(header_value.Latin1(), FilterAcceptCH(network::ParseAcceptCH(header_value.Latin1()),
RuntimeEnabledFeatures::LangClientHintHeaderEnabled(), RuntimeEnabledFeatures::LangClientHintHeaderEnabled(),
RuntimeEnabledFeatures::UserAgentClientHintEnabled()); RuntimeEnabledFeatures::UserAgentClientHintEnabled());
if (!parsed_ch.has_value()) if (!parsed_ch.has_value())
......
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