Commit 4c33aada authored by Antonio Sartori's avatar Antonio Sartori Committed by Chromium LUCI CQ

CSP: Replace blink::SourceListDirective with mojo type

In the Blink Content Security Policy code, we switch from using the
internal blink type blink::SourceListDirective to using the mojo type
network::mojom::blink::CSPSourceList for handling lists of CSP source
expressions.

This is part of a project to harmonize the CSP code in Blink and in
services/network, and will make it easier to synchronize Content
Security Policies between the two.

Bug: 1021462,1149272
Change-Id: Ibb860148689399c9b169bb9e604bfed5d5df429f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2560100
Commit-Queue: Antonio Sartori <antoniosartori@chromium.org>
Reviewed-by: default avatarArthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: default avatarMike West <mkwst@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836104}
parent 2df425a5
...@@ -6,8 +6,10 @@ ...@@ -6,8 +6,10 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "base/base64url.h"
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/ranges/algorithm.h" #include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
...@@ -563,7 +565,18 @@ bool ParseHash(base::StringPiece expression, mojom::CSPHashSource* hash) { ...@@ -563,7 +565,18 @@ bool ParseHash(base::StringPiece expression, mojom::CSPHashSource* hash) {
return false; return false;
hash->algorithm = item.type; hash->algorithm = item.type;
hash->value = subexpression.as_string();
// We lazily accept both base64url and base64-encoded data.
std::string normalized_value;
base::ReplaceChars(subexpression, "+", "-", &normalized_value);
base::ReplaceChars(normalized_value, "/", "_", &normalized_value);
std::string out;
if (!base::Base64UrlDecode(normalized_value,
base::Base64UrlDecodePolicy::IGNORE_PADDING,
&out))
return false;
hash->value = std::vector<uint8_t>(out.begin(), out.end());
return true; return true;
} }
} }
......
...@@ -1273,25 +1273,16 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) { ...@@ -1273,25 +1273,16 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
"", "",
}, },
{ {
"'sha256-abc' 'sha256-ABC' 'sha256 'sha256-' 'sha384-abc' " "'sha256-YWJj' 'nonce-cde' 'sha256-QUJD'",
"'sha512-abc' 'sha-abc' 'sha256-*' 'sha-256-cde' 'sha-384-cde' "
"'sha-512-cde'",
base::Bind([] { base::Bind([] {
auto csp = mojom::CSPSourceList::New(); auto csp = mojom::CSPSourceList::New();
csp->hashes.push_back(mojom::CSPHashSource::New( csp->hashes.push_back(
mojom::CSPHashAlgorithm::SHA256, "abc")); mojom::CSPHashSource::New(mojom::CSPHashAlgorithm::SHA256,
csp->hashes.push_back(mojom::CSPHashSource::New( std::vector<uint8_t>{'a', 'b', 'c'}));
mojom::CSPHashAlgorithm::SHA256, "ABC")); csp->hashes.push_back(
csp->hashes.push_back(mojom::CSPHashSource::New( mojom::CSPHashSource::New(mojom::CSPHashAlgorithm::SHA256,
mojom::CSPHashAlgorithm::SHA384, "abc")); std::vector<uint8_t>{'A', 'B', 'C'}));
csp->hashes.push_back(mojom::CSPHashSource::New( csp->nonces.push_back("cde");
mojom::CSPHashAlgorithm::SHA512, "abc"));
csp->hashes.push_back(mojom::CSPHashSource::New(
mojom::CSPHashAlgorithm::SHA256, "cde"));
csp->hashes.push_back(mojom::CSPHashSource::New(
mojom::CSPHashAlgorithm::SHA384, "cde"));
csp->hashes.push_back(mojom::CSPHashSource::New(
mojom::CSPHashAlgorithm::SHA512, "cde"));
return csp; return csp;
}), }),
"", "",
...@@ -1426,6 +1417,58 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) { ...@@ -1426,6 +1417,58 @@ TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
} }
} }
TEST(ContentSecurityPolicy, ParseHash) {
using Algo = mojom::CSPHashAlgorithm;
struct TestCase {
std::string hash;
Algo expected_algorithm;
std::vector<uint8_t> expected_hash;
} cases[] = {
// For this test, we have the following base64 encoding:
// abc => YWJj ABC => QUJD cd => Y2Q= abcd => YWJjZA==
// We also test base64 without padding.
{"'sha256-YWJj'", Algo::SHA256, {'a', 'b', 'c'}},
{"'sha256-QUJD'", Algo::SHA256, {'A', 'B', 'C'}},
{"'sha256", Algo::None, {}},
{"'sha256-'", Algo::None, {}},
{"'sha384-YWJj'", Algo::SHA384, {'a', 'b', 'c'}},
{"'sha512-YWJjZA'", Algo::SHA512, {'a', 'b', 'c', 'd'}},
{"'sha-YWJj'", Algo::None, {}},
{"'sha256-*'", Algo::None, {}},
{"'sha-256-Y2Q'", Algo::SHA256, {'c', 'd'}},
{"'sha-384-Y2Q='", Algo::SHA384, {'c', 'd'}},
{"'sha-512-Y2Q='", Algo::SHA512, {'c', 'd'}},
// "ABCDE" is not valid base64 and should be ignored.
{"'sha256-ABCDE'", Algo::None, {}},
{"'sha256--__'", Algo::SHA256, {0xfb, 0xff}},
{"'sha256-++/'", Algo::SHA256, {0xfb, 0xef}},
// Other invalid hashes should be ignored.
{"'sha256-YWJj", Algo::None, {}},
{"'sha111-YWJj'", Algo::None, {}},
{"'sha256-ABC('", Algo::None, {}},
};
for (auto& test : cases) {
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
headers->SetHeader("Content-Security-Policy", "script-src " + test.hash);
std::vector<mojom::ContentSecurityPolicyPtr> policies;
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
const std::vector<mojom::CSPHashSourcePtr>& hashes =
policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]->hashes;
if (test.expected_algorithm != Algo::None) {
EXPECT_EQ(1u, hashes.size()) << test.hash << " should parse to one hash";
EXPECT_EQ(test.expected_algorithm, hashes[0]->algorithm)
<< test.hash << " should have algorithm " << test.expected_algorithm;
EXPECT_EQ(test.expected_hash, hashes[0]->value)
<< test.hash << " has not been base64decoded correctly";
} else {
EXPECT_TRUE(hashes.empty()) << test.hash << " should be an invalid hash";
}
}
}
TEST(ContentSecurityPolicy, IsValidRequiredCSPAttr) { TEST(ContentSecurityPolicy, IsValidRequiredCSPAttr) {
struct TestCase { struct TestCase {
const char* csp; const char* csp;
......
...@@ -64,14 +64,15 @@ struct CSPSource { ...@@ -64,14 +64,15 @@ struct CSPSource {
}; };
enum CSPHashAlgorithm { enum CSPHashAlgorithm {
SHA256, None = 0,
SHA384, SHA256 = 1,
SHA512, SHA384 = 2,
SHA512 = 4,
}; };
struct CSPHashSource { struct CSPHashSource {
CSPHashAlgorithm algorithm; CSPHashAlgorithm algorithm;
string value; array<uint8> value;
}; };
struct CSPSourceList { struct CSPSourceList {
......
...@@ -452,17 +452,17 @@ Vector<CSPHeaderAndType> ContentSecurityPolicy::Headers() const { ...@@ -452,17 +452,17 @@ Vector<CSPHeaderAndType> ContentSecurityPolicy::Headers() const {
void ContentSecurityPolicy::FillInCSPHashValues( void ContentSecurityPolicy::FillInCSPHashValues(
const String& source, const String& source,
uint8_t hash_algorithms_used, uint8_t hash_algorithms_used,
Vector<CSPHashValue>* csp_hash_values) { Vector<network::mojom::blink::CSPHashSourcePtr>& csp_hash_values) {
// Any additions or subtractions from this struct should also modify the // Any additions or subtractions from this struct should also modify the
// respective entries in the kSupportedPrefixes array in // respective entries in the kSupportedPrefixes array in
// SourceListDirective::parseHash(). // SourceListDirective::parseHash().
static const struct { static const struct {
ContentSecurityPolicyHashAlgorithm csp_hash_algorithm; network::mojom::blink::CSPHashAlgorithm csp_hash_algorithm;
HashAlgorithm algorithm; HashAlgorithm algorithm;
} kAlgorithmMap[] = { } kAlgorithmMap[] = {
{kContentSecurityPolicyHashAlgorithmSha256, kHashAlgorithmSha256}, {network::mojom::blink::CSPHashAlgorithm::SHA256, kHashAlgorithmSha256},
{kContentSecurityPolicyHashAlgorithmSha384, kHashAlgorithmSha384}, {network::mojom::blink::CSPHashAlgorithm::SHA384, kHashAlgorithmSha384},
{kContentSecurityPolicyHashAlgorithmSha512, kHashAlgorithmSha512}}; {network::mojom::blink::CSPHashAlgorithm::SHA512, kHashAlgorithmSha512}};
// Only bother normalizing the source/computing digests if there are any // Only bother normalizing the source/computing digests if there are any
// checks to be done. // checks to be done.
...@@ -474,13 +474,14 @@ void ContentSecurityPolicy::FillInCSPHashValues( ...@@ -474,13 +474,14 @@ void ContentSecurityPolicy::FillInCSPHashValues(
for (const auto& algorithm_map : kAlgorithmMap) { for (const auto& algorithm_map : kAlgorithmMap) {
DigestValue digest; DigestValue digest;
if (algorithm_map.csp_hash_algorithm & hash_algorithms_used) { if (static_cast<int32_t>(algorithm_map.csp_hash_algorithm) &
hash_algorithms_used) {
bool digest_success = bool digest_success =
ComputeDigest(algorithm_map.algorithm, utf8_source.data(), ComputeDigest(algorithm_map.algorithm, utf8_source.data(),
utf8_source.size(), digest); utf8_source.size(), digest);
if (digest_success) { if (digest_success) {
csp_hash_values->push_back( csp_hash_values.push_back(network::mojom::blink::CSPHashSource::New(
CSPHashValue(algorithm_map.csp_hash_algorithm, digest)); algorithm_map.csp_hash_algorithm, Vector<uint8_t>(digest)));
} }
} }
} }
...@@ -488,11 +489,11 @@ void ContentSecurityPolicy::FillInCSPHashValues( ...@@ -488,11 +489,11 @@ void ContentSecurityPolicy::FillInCSPHashValues(
// static // static
bool ContentSecurityPolicy::CheckHashAgainstPolicy( bool ContentSecurityPolicy::CheckHashAgainstPolicy(
Vector<CSPHashValue>& csp_hash_values, Vector<network::mojom::blink::CSPHashSourcePtr>& csp_hash_values,
const Member<CSPDirectiveList>& policy, const Member<CSPDirectiveList>& policy,
InlineType inline_type) { InlineType inline_type) {
for (const auto& csp_hash_value : csp_hash_values) { for (const auto& csp_hash_value : csp_hash_values) {
if (policy->AllowHash(csp_hash_value, inline_type)) if (policy->AllowHash(*csp_hash_value, inline_type))
return true; return true;
} }
return false; return false;
...@@ -515,11 +516,11 @@ bool ContentSecurityPolicy::AllowInline( ...@@ -515,11 +516,11 @@ bool ContentSecurityPolicy::AllowInline(
return true; return true;
} }
Vector<CSPHashValue> csp_hash_values; Vector<network::mojom::blink::CSPHashSourcePtr> csp_hash_values;
FillInCSPHashValues( FillInCSPHashValues(
content, content,
is_script ? script_hash_algorithms_used_ : style_hash_algorithms_used_, is_script ? script_hash_algorithms_used_ : style_hash_algorithms_used_,
&csp_hash_values); csp_hash_values);
// Step 2. Let result be "Allowed". [spec text] // Step 2. Let result be "Allowed". [spec text]
bool is_allowed = true; bool is_allowed = true;
......
...@@ -551,13 +551,15 @@ class CORE_EXPORT ContentSecurityPolicy final ...@@ -551,13 +551,15 @@ class CORE_EXPORT ContentSecurityPolicy final
const IntegrityMetadataSet& = IntegrityMetadataSet(), const IntegrityMetadataSet& = IntegrityMetadataSet(),
ParserDisposition = kParserInserted) const; ParserDisposition = kParserInserted) const;
static void FillInCSPHashValues(const String& source, static void FillInCSPHashValues(
const String& source,
uint8_t hash_algorithms_used, uint8_t hash_algorithms_used,
Vector<CSPHashValue>* csp_hash_values); Vector<network::mojom::blink::CSPHashSourcePtr>& csp_hash_values);
// checks a vector of csp hashes against policy, probably a good idea // checks a vector of csp hashes against policy, probably a good idea
// to use in tandem with FillInCSPHashValues. // to use in tandem with FillInCSPHashValues.
static bool CheckHashAgainstPolicy(Vector<CSPHashValue>&, static bool CheckHashAgainstPolicy(
Vector<network::mojom::blink::CSPHashSourcePtr>&,
const Member<CSPDirectiveList>&, const Member<CSPDirectiveList>&,
InlineType); InlineType);
......
...@@ -137,8 +137,8 @@ TEST_F(CSPDirectiveListTest, IsMatchingNoncePresent) { ...@@ -137,8 +137,8 @@ TEST_F(CSPDirectiveListTest, IsMatchingNoncePresent) {
// Report-only // Report-only
Member<CSPDirectiveList> directive_list = Member<CSPDirectiveList> directive_list =
CreateList(test.list, ContentSecurityPolicyType::kReport); CreateList(test.list, ContentSecurityPolicyType::kReport);
Member<SourceListDirective> directive = const network::mojom::blink::CSPSourceList* directive =
directive_list->OperativeDirective(test.type); directive_list->OperativeDirective(test.type).source_list;
EXPECT_EQ(test.expected, EXPECT_EQ(test.expected,
directive_list->IsMatchingNoncePresent(directive, test.nonce)); directive_list->IsMatchingNoncePresent(directive, test.nonce));
// Empty/null strings are always not present, regardless of the policy. // Empty/null strings are always not present, regardless of the policy.
...@@ -147,7 +147,7 @@ TEST_F(CSPDirectiveListTest, IsMatchingNoncePresent) { ...@@ -147,7 +147,7 @@ TEST_F(CSPDirectiveListTest, IsMatchingNoncePresent) {
// Enforce // Enforce
directive_list = CreateList(test.list, ContentSecurityPolicyType::kEnforce); directive_list = CreateList(test.list, ContentSecurityPolicyType::kEnforce);
directive = directive_list->OperativeDirective(test.type); directive = directive_list->OperativeDirective(test.type).source_list;
EXPECT_EQ(test.expected, EXPECT_EQ(test.expected,
directive_list->IsMatchingNoncePresent(directive, test.nonce)); directive_list->IsMatchingNoncePresent(directive, test.nonce));
// Empty/null strings are always not present, regardless of the policy. // Empty/null strings are always not present, regardless of the policy.
...@@ -599,7 +599,7 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) { ...@@ -599,7 +599,7 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
for (auto& test : cases) { for (auto& test : cases) {
// With an empty directive list the returned directive should always be // With an empty directive list the returned directive should always be
// null. // null.
EXPECT_FALSE(empty->OperativeDirective(test.directive)); EXPECT_FALSE(empty->OperativeDirective(test.directive).source_list);
// Add the directive itself as it should be the first one to be returned. // Add the directive itself as it should be the first one to be returned.
test.fallback_list.push_front(test.directive); test.fallback_list.push_front(test.directive);
...@@ -611,16 +611,14 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) { ...@@ -611,16 +611,14 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
directive_list = CreateList(directive_string.c_str(), directive_list = CreateList(directive_string.c_str(),
ContentSecurityPolicyType::kEnforce); ContentSecurityPolicyType::kEnforce);
CSPDirective* operative_directive = CSPOperativeDirective operative_directive =
directive_list->OperativeDirective(test.directive); directive_list->OperativeDirective(test.directive);
// We should have an actual directive returned here. // We should have an actual directive returned here.
EXPECT_TRUE(operative_directive); EXPECT_TRUE(operative_directive.source_list);
// The OperativeDirective should be first one in the fallback chain. // The OperativeDirective should be first one in the fallback chain.
EXPECT_EQ(test.fallback_list.front(), EXPECT_EQ(test.fallback_list.front(), operative_directive.type);
ContentSecurityPolicy::GetDirectiveType(
operative_directive->GetName()));
// Remove the first directive in the fallback chain from the directive // Remove the first directive in the fallback chain from the directive
// list and continue by testing that the next one is returned until we // list and continue by testing that the next one is returned until we
...@@ -643,7 +641,8 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) { ...@@ -643,7 +641,8 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
// the fallback chain that is returned. // the fallback chain that is returned.
directive_list = CreateList(directive_string.c_str(), directive_list = CreateList(directive_string.c_str(),
ContentSecurityPolicyType::kEnforce); ContentSecurityPolicyType::kEnforce);
EXPECT_FALSE(directive_list->OperativeDirective(test.directive)); EXPECT_FALSE(
directive_list->OperativeDirective(test.directive).source_list);
} }
} }
......
...@@ -7,121 +7,58 @@ ...@@ -7,121 +7,58 @@
#include "base/macros.h" #include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/csp/csp_directive.h"
#include "third_party/blink/renderer/core/frame/csp/csp_source.h" #include "third_party/blink/renderer/core/frame/csp/csp_source.h"
#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink { namespace blink {
class ContentSecurityPolicy;
class KURL; class KURL;
class CORE_EXPORT SourceListDirective final : public CSPDirective { CORE_EXPORT
public: network::mojom::blink::CSPSourceListPtr CSPSourceListParse(
SourceListDirective(const String& name, const String& name,
const String& value, const String& value,
ContentSecurityPolicy*); ContentSecurityPolicy* policy);
void Trace(Visitor*) const override;
void Parse(const UChar* begin, const UChar* end); CORE_EXPORT
bool CSPSourceListAllows(
bool Matches(const KURL&, const network::mojom::blink::CSPSourceList& source_list,
ResourceRequest::RedirectStatus = const network::mojom::blink::CSPSource& self_source,
ResourceRequest::RedirectStatus::kNoRedirect) const; const KURL&,
bool Allows(const KURL&,
ResourceRequest::RedirectStatus = ResourceRequest::RedirectStatus =
ResourceRequest::RedirectStatus::kNoRedirect) const; ResourceRequest::RedirectStatus::kNoRedirect);
bool AllowInline() const;
bool AllowEval() const; CORE_EXPORT
bool AllowWasmEval() const; bool CSPSourceListAllowNonce(
bool AllowDynamic() const; const network::mojom::blink::CSPSourceList& source_list,
bool AllowNonce(const String& nonce) const; const String& nonce);
bool AllowHash(const CSPHashValue&) const;
bool AllowUnsafeHashes() const; CORE_EXPORT
bool AllowReportSample() const; bool CSPSourceListAllowHash(
bool IsNone() const; const network::mojom::blink::CSPSourceList& source_list,
bool IsSelf() const; const network::mojom::blink::CSPHashSource& hash);
bool IsHashOrNoncePresent() const;
uint8_t HashAlgorithmsUsed() const; CORE_EXPORT
bool AllowAllInline() const; bool CSPSourceListIsNone(
bool AllowsURLBasedMatching() const; const network::mojom::blink::CSPSourceList& source_list);
// The algorithm is described more extensively here: CORE_EXPORT
// https://w3c.github.io/webappsec-csp/embedded/#subsume-source-list bool CSPSourceListIsSelf(
bool Subsumes(const HeapVector<Member<SourceListDirective>>&) const; const network::mojom::blink::CSPSourceList& source_list);
// Export a subset of the source list that affect navigation. CORE_EXPORT
// It contains every source-expressions, '*', 'none' and 'self'. bool CSPSourceListIsHashOrNoncePresent(
// It doesn't contain 'unsafe-inline' or 'unsafe-eval' for instance. const network::mojom::blink::CSPSourceList& source_list);
network::mojom::blink::CSPSourceListPtr ExposeForNavigationalChecks() const;
String DirectiveName() const { return directive_name_; } CORE_EXPORT
bool CSPSourceListAllowAllInline(
private: ContentSecurityPolicy::DirectiveType directive_type,
FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, ParseHost); const network::mojom::blink::CSPSourceList& source_list);
FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, OperativeDirectiveGivenType);
CORE_EXPORT
bool ParseSource(const UChar* begin, bool CSPSourceListAllowsURLBasedMatching(
const UChar* end, const network::mojom::blink::CSPSourceList& source_list);
String* scheme,
String* host,
int* port,
String* path,
bool* is_host_wildcard,
bool* is_port_wildcard);
bool ParseScheme(const UChar* begin, const UChar* end, String* scheme);
static bool ParseHost(const UChar* begin,
const UChar* end,
String* host,
bool* is_host_wildcard);
bool ParsePort(const UChar* begin,
const UChar* end,
int* port,
bool* is_port_wildcard);
bool ParsePath(const UChar* begin, const UChar* end, String* path);
bool ParseNonce(const UChar* begin, const UChar* end, String* nonce);
bool ParseHash(const UChar* begin,
const UChar* end,
DigestValue* hash,
ContentSecurityPolicyHashAlgorithm*);
void AddSourceSelf();
void AddSourceStar();
void AddSourceUnsafeAllowRedirects();
void AddSourceUnsafeInline();
void AddSourceUnsafeEval();
void AddSourceWasmEval();
void AddSourceStrictDynamic();
void AddSourceUnsafeHashes();
void AddReportSample();
void AddSourceNonce(const String& nonce);
void AddSourceHash(const ContentSecurityPolicyHashAlgorithm&,
const DigestValue& hash);
bool HasSourceMatchInList(const KURL&, ResourceRequest::RedirectStatus) const;
Member<ContentSecurityPolicy> policy_;
WTF::Vector<network::mojom::blink::CSPSourcePtr> list_;
String directive_name_;
bool allow_self_;
bool allow_star_;
bool allow_inline_;
bool allow_eval_;
bool allow_wasm_eval_;
bool allow_dynamic_;
bool allow_unsafe_hashes_;
bool allow_redirects_;
bool report_sample_;
HashSet<String> nonces_;
HashSet<CSPHashValue> hashes_;
uint8_t hash_algorithms_used_;
DISALLOW_COPY_AND_ASSIGN(SourceListDirective);
};
} // namespace blink } // namespace blink
......
...@@ -66,8 +66,11 @@ blink::CSPSourcePtr ConvertToBlink(CSPSourcePtr source) { ...@@ -66,8 +66,11 @@ blink::CSPSourcePtr ConvertToBlink(CSPSourcePtr source) {
} }
blink::CSPHashSourcePtr ConvertToBlink(CSPHashSourcePtr hash) { blink::CSPHashSourcePtr ConvertToBlink(CSPHashSourcePtr hash) {
return blink::CSPHashSource::New(hash->algorithm, WTF::Vector<uint8_t> hash_value;
String::FromUTF8(hash->value)); for (uint8_t el : hash->value)
hash_value.push_back(el);
return blink::CSPHashSource::New(hash->algorithm, hash_value);
} }
blink::CSPSourceListPtr ConvertToBlink(CSPSourceListPtr source_list) { blink::CSPSourceListPtr ConvertToBlink(CSPSourceListPtr source_list) {
......
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