SpeculationRules: Dedup and sort tags passed to SpeculationRulesTags
This CL dedups and sorts given speculation rules tags by using std::set. Also, this CL adds unit tests for the class. Bug: 381687257 Change-Id: Ibbe4f4b5232ba2674bf46b362662f62b333869a7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6399977 Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org> Reviewed-by: Huanpo Lin <robertlin@chromium.org> Reviewed-by: Taiyo Mizuhashi <taiyo@chromium.org> Cr-Commit-Position: refs/heads/main@{#1439351}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
c033d20c2d
commit
105595025a
content
browser
preloading
test
@ -11,8 +11,11 @@ namespace content {
|
||||
|
||||
SpeculationRulesTags::SpeculationRulesTags() = default;
|
||||
SpeculationRulesTags::SpeculationRulesTags(
|
||||
std::vector<std::optional<std::string>> tags)
|
||||
: tags_(std::move(tags)) {}
|
||||
std::vector<std::optional<std::string>> tags) {
|
||||
for (auto& tag : tags) {
|
||||
tags_.insert(std::move(tag));
|
||||
}
|
||||
}
|
||||
|
||||
SpeculationRulesTags::~SpeculationRulesTags() = default;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef CONTENT_BROWSER_PRELOADING_SPECULATION_RULES_SPECULATION_RULES_TAGS_H_
|
||||
#define CONTENT_BROWSER_PRELOADING_SPECULATION_RULES_SPECULATION_RULES_TAGS_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -19,6 +20,7 @@ namespace content {
|
||||
class CONTENT_EXPORT SpeculationRulesTags {
|
||||
public:
|
||||
SpeculationRulesTags();
|
||||
// TODO(crbug.com/381687257): Use std::set instead of std::vector.
|
||||
explicit SpeculationRulesTags(std::vector<std::optional<std::string>> tags);
|
||||
~SpeculationRulesTags();
|
||||
|
||||
@ -33,7 +35,7 @@ class CONTENT_EXPORT SpeculationRulesTags {
|
||||
private:
|
||||
net::structured_headers::List ConvertStringToStructuredHeader();
|
||||
|
||||
std::vector<std::optional<std::string>> tags_;
|
||||
std::set<std::optional<std::string>> tags_;
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
@ -0,0 +1,64 @@
|
||||
// Copyright 2025 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "content/browser/preloading/speculation_rules/speculation_rules_tags.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace content {
|
||||
namespace {
|
||||
|
||||
using Tags = std::vector<std::optional<std::string>>;
|
||||
|
||||
void TestTags(const Tags& tags, const std::string& expected) {
|
||||
EXPECT_EQ(expected, SpeculationRulesTags(tags).ConvertStringToHeaderString());
|
||||
}
|
||||
|
||||
// Each string tag should be wrapped with double quotes during parsing.
|
||||
// https://www.rfc-editor.org/rfc/rfc8941.html#name-serializing-a-string
|
||||
TEST(SpeculationRulesTagsTest, Basic) {
|
||||
TestTags({R"(my-rules)"}, R"("my-rules")");
|
||||
TestTags({R"(my-rules1)", R"(my-rules2)"}, R"("my-rules1", "my-rules2")");
|
||||
}
|
||||
|
||||
// No tags should be parsed as null token.
|
||||
// https://www.rfc-editor.org/rfc/rfc8941.html#section-4.1.7
|
||||
TEST(SpeculationRulesTagsTest, NoTags) {
|
||||
TestTags({std::nullopt}, R"(null)");
|
||||
TestTags({std::nullopt, R"(my-rules)"}, R"(null, "my-rules")");
|
||||
TestTags({std::nullopt, R"(my-rules)", R"(null)"},
|
||||
R"(null, "my-rules", "null")");
|
||||
}
|
||||
|
||||
// A double quote (DQUOTE) should be converted to \" during parsing:
|
||||
// https://www.rfc-editor.org/rfc/rfc8941.html#name-serializing-a-string
|
||||
TEST(SpeculationRulesTagsTest, DoubleQuote) {
|
||||
TestTags({R"(")"}, R"("\"")");
|
||||
TestTags({R"("")"}, R"("\"\"")");
|
||||
TestTags({R"(my"rules)"}, R"("my\"rules")");
|
||||
TestTags({R"(my-rules)", R"(")"}, R"("\"", "my-rules")");
|
||||
}
|
||||
|
||||
// A backslash should be converted to \\ during parsing:
|
||||
// https://www.rfc-editor.org/rfc/rfc8941.html#name-serializing-a-string
|
||||
TEST(SpeculationRulesTagsTest, BackSlash) {
|
||||
TestTags({R"(\)"}, R"("\\")");
|
||||
TestTags({R"(\\)"}, R"("\\\\")");
|
||||
TestTags({R"(my\rules)"}, R"("my\\rules")");
|
||||
TestTags({R"(my-rules)", R"(\)"}, R"("\\", "my-rules")");
|
||||
}
|
||||
|
||||
TEST(SpeculationRulesTagsTest, Duplicate) {
|
||||
TestTags({std::nullopt, R"(my-rules)", R"(my-rules)"}, R"(null, "my-rules")");
|
||||
TestTags({std::nullopt, std::nullopt, R"(my-rules)"}, R"(null, "my-rules")");
|
||||
}
|
||||
|
||||
TEST(SpeculationRulesTagsTest, Sort) {
|
||||
TestTags({R"(def)", R"(jkl)", R"(def)", R"(null)", std::nullopt, R"(abc)",
|
||||
std::nullopt, R"(ghi)"},
|
||||
R"(null, "abc", "def", "ghi", "jkl", "null")");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace content
|
@ -2698,6 +2698,7 @@ test("content_unittests") {
|
||||
"../browser/preloading/prerender/prerender_metrics_unittest.cc",
|
||||
"../browser/preloading/prerenderer_impl_unittest.cc",
|
||||
"../browser/preloading/speculation_rules/speculation_host_impl_unittest.cc",
|
||||
"../browser/preloading/speculation_rules/speculation_rules_tags_unittest.cc",
|
||||
"../browser/presentation/presentation_service_impl_unittest.cc",
|
||||
"../browser/private_aggregation/private_aggregation_budget_key_unittest.cc",
|
||||
"../browser/private_aggregation/private_aggregation_budget_storage_unittest.cc",
|
||||
|
Reference in New Issue
Block a user