0

Use SimpleUrlPatternMatcher for dictionary matching

The spec of Compression Dictionary Transport has been changed by [1] to
use URLPattern [2] for the matching algorithm of dictionaries. Also [3]
changed the Use-As-Dictionary header’s "match" value to be parsed as a
constructor string of URLPattern.

This CL changes the behavior of Chromium to follow those spec changes
when V2 backend is enabled.

[1]: https://github.com/httpwg/http-extensions/pull/2646
[2]: https://urlpattern.spec.whatwg.org/
[3]: https://github.com/httpwg/http-extensions/pull/2689

Fuchsia-Binary-Size: Size increase is unavoidable.
Bug: 1413922
Change-Id: I6ffba1c8c016145822643a18bc4f18bb7f0ac35f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5232339
Reviewed-by: Patrick Meenan <pmeenan@chromium.org>
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1256029}
This commit is contained in:
Tsuyoshi Horo
2024-02-05 01:35:01 +00:00
committed by Chromium LUCI CQ
parent a6665cf098
commit cdb7dfa61e
9 changed files with 238 additions and 48 deletions

@@ -201,7 +201,7 @@ construction to catch up the following spec changes:
- Change Content-Encoding name "br-d" "zstd-d" - Change Content-Encoding name "br-d" "zstd-d"
- Stauts: Implemented by https://crrev.com/c/5185977. - Stauts: Implemented by https://crrev.com/c/5185977.
- Changed match to use URLPattern - Changed match to use URLPattern
- Stauts: Not yet implemented. - Stauts: Implemented by https://crrev.com/c/5232339.
- Added support for a server-provided dictionary id - Added support for a server-provided dictionary id
- Stauts: Not yet implemented. - Stauts: Not yet implemented.
- Stop using "expires" value of "Use-As-Dictionary" header, and use the cache - Stop using "expires" value of "Use-As-Dictionary" header, and use the cache

@@ -160,18 +160,6 @@ void WriteDiskCacheEntry(SharedDictionaryManager* manager,
write_callback.callback(), /*truncate=*/false))); write_callback.callback(), /*truncate=*/false)));
} }
base::UnguessableToken GetDiskCacheKeyTokenOfFirstDictionary(
const std::map<url::SchemeHostPort,
std::map<std::string, net::SharedDictionaryInfo>>&
dictionary_map,
const std::string& scheme_host_port_str) {
auto it =
dictionary_map.find(url::SchemeHostPort(GURL(scheme_host_port_str)));
CHECK(it != dictionary_map.end()) << scheme_host_port_str;
CHECK(!it->second.empty());
return it->second.begin()->second.disk_cache_key_token();
}
} // namespace } // namespace
class SharedDictionaryManagerOnDiskTest class SharedDictionaryManagerOnDiskTest
@@ -207,6 +195,21 @@ class SharedDictionaryManagerOnDiskTest
features::CompressionDictionaryTransportBackendVersion GetVersion() const { features::CompressionDictionaryTransportBackendVersion GetVersion() const {
return GetParam(); return GetParam();
} }
static base::UnguessableToken GetDiskCacheKeyTokenOfFirstDictionary(
const std::map<
url::SchemeHostPort,
std::map<std::string,
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher>>&
dictionary_map,
const std::string& scheme_host_port_str) {
auto it =
dictionary_map.find(url::SchemeHostPort(GURL(scheme_host_port_str)));
CHECK(it != dictionary_map.end()) << scheme_host_port_str;
CHECK(!it->second.empty());
return it->second.begin()->second.disk_cache_key_token();
}
std::unique_ptr<SharedDictionaryManager> CreateSharedDictionaryManager( std::unique_ptr<SharedDictionaryManager> CreateSharedDictionaryManager(
uint64_t cache_max_size = 0, uint64_t cache_max_size = 0,
uint64_t cache_max_count = uint64_t cache_max_count =
@@ -218,8 +221,10 @@ class SharedDictionaryManagerOnDiskTest
#endif // BUILDFLAG(IS_ANDROID) #endif // BUILDFLAG(IS_ANDROID)
/*file_operations_factory=*/nullptr); /*file_operations_factory=*/nullptr);
} }
const std::map<url::SchemeHostPort, const std::map<
std::map<std::string, net::SharedDictionaryInfo>>& url::SchemeHostPort,
std::map<std::string,
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher>>&
GetOnDiskDictionaryMap(SharedDictionaryStorage* storage) { GetOnDiskDictionaryMap(SharedDictionaryStorage* storage) {
return static_cast<SharedDictionaryStorageOnDisk*>(storage) return static_cast<SharedDictionaryStorageOnDisk*>(storage)
->GetDictionaryMapForTesting(); ->GetDictionaryMapForTesting();

@@ -229,8 +229,10 @@ class SharedDictionaryManagerTest
return static_cast<SharedDictionaryStorageInMemory*>(storage) return static_cast<SharedDictionaryStorageInMemory*>(storage)
->GetDictionaryMap(); ->GetDictionaryMap();
} }
const std::map<url::SchemeHostPort, const std::map<
std::map<std::string, net::SharedDictionaryInfo>>& url::SchemeHostPort,
std::map<std::string,
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher>>&
GetOnDiskDictionaryMap(SharedDictionaryStorage* storage) { GetOnDiskDictionaryMap(SharedDictionaryStorage* storage) {
return static_cast<SharedDictionaryStorageOnDisk*>(storage) return static_cast<SharedDictionaryStorageOnDisk*>(storage)
->GetDictionaryMapForTesting(); ->GetDictionaryMapForTesting();
@@ -716,6 +718,52 @@ TEST_P(SharedDictionaryManagerTest, DictionaryLifetimeFromCacheControlHeader) {
} }
} }
TEST_P(SharedDictionaryManagerTest, InvalidMatch) {
std::unique_ptr<SharedDictionaryManager> manager =
CreateSharedDictionaryManager();
net::SharedDictionaryIsolationKey isolation_key(url::Origin::Create(kUrl1),
kSite1);
scoped_refptr<SharedDictionaryStorage> storage =
manager->GetStorage(isolation_key);
ASSERT_TRUE(storage);
struct {
std::string header_string;
bool expect_success_v1;
bool expect_success_v2;
} kTestCases[] = {
// Invalid as a constructor string of URLPattern.
{"{", true, false},
// Unsupported regexp group.
{"(a|b)", true, false},
};
for (const auto& testcase : kTestCases) {
SCOPED_TRACE(
base::StringPrintf("match: %s", testcase.header_string.c_str()));
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate(base::StrCat(
{"HTTP/1.1 200 OK\n", shared_dictionary::kUseAsDictionaryHeaderName,
": match=\"", testcase.header_string, "\"\n",
"cache-control:max-age=100\n\n"}));
ASSERT_TRUE(headers);
scoped_refptr<SharedDictionaryWriter> writer = storage->MaybeCreateWriter(
GURL("https://origin1.test/testfile.txt"),
/*request_time=*/base::Time::Now(), /*response_time=*/base::Time::Now(),
*headers,
/*was_fetched_via_cache=*/false,
/*access_allowed_check_callback=*/base::BindOnce([]() {
return true;
}));
switch (GetVersion()) {
case features::CompressionDictionaryTransportBackendVersion::kV1:
EXPECT_EQ(testcase.expect_success_v1, !!writer);
break;
case features::CompressionDictionaryTransportBackendVersion::kV2:
EXPECT_EQ(testcase.expect_success_v2, !!writer);
break;
}
}
}
TEST_P(SharedDictionaryManagerTest, AccessAllowedCheckReturnTrue) { TEST_P(SharedDictionaryManagerTest, AccessAllowedCheckReturnTrue) {
std::unique_ptr<SharedDictionaryManager> manager = std::unique_ptr<SharedDictionaryManager> manager =
CreateSharedDictionaryManager(); CreateSharedDictionaryManager();
@@ -987,6 +1035,54 @@ TEST_P(SharedDictionaryManagerTest, WriteAndReadDictionary) {
} }
} }
} }
TEST_P(SharedDictionaryManagerTest, LongestMatchDictionaryWin) {
std::unique_ptr<SharedDictionaryManager> manager =
CreateSharedDictionaryManager();
net::SharedDictionaryIsolationKey isolation_key(url::Origin::Create(kUrl1),
kSite1);
scoped_refptr<SharedDictionaryStorage> storage =
manager->GetStorage(isolation_key);
ASSERT_TRUE(storage);
WriteDictionary(storage.get(), GURL("https://origin1.test/dict"), "*estfile*",
{"Longer match"});
WriteDictionary(storage.get(), GURL("https://origin1.test/dict"), "test*",
{"Shorter match"});
if (GetManagerType() == TestManagerType::kOnDisk) {
FlushCacheTasks();
}
auto dict = storage->GetDictionarySync(GURL("https://origin1.test/testfile"));
ASSERT_TRUE(dict);
net::TestCompletionCallback read_callback;
EXPECT_EQ(net::OK,
read_callback.GetResult(dict->ReadAll(read_callback.callback())));
EXPECT_EQ("Longer match", std::string(dict->data()->data(), dict->size()));
}
TEST_P(SharedDictionaryManagerTest, LatestDictionaryWin) {
std::unique_ptr<SharedDictionaryManager> manager =
CreateSharedDictionaryManager();
net::SharedDictionaryIsolationKey isolation_key(url::Origin::Create(kUrl1),
kSite1);
scoped_refptr<SharedDictionaryStorage> storage =
manager->GetStorage(isolation_key);
ASSERT_TRUE(storage);
WriteDictionary(storage.get(), GURL("https://origin1.test/dict"), "test*",
{"Old match"});
task_environment_.FastForwardBy(base::Seconds(1));
WriteDictionary(storage.get(), GURL("https://origin1.test/dict"), "*est*",
{"New match"});
if (GetManagerType() == TestManagerType::kOnDisk) {
FlushCacheTasks();
}
auto dict = storage->GetDictionarySync(GURL("https://origin1.test/testfile"));
ASSERT_TRUE(dict);
net::TestCompletionCallback read_callback;
EXPECT_EQ(net::OK,
read_callback.GetResult(dict->ReadAll(read_callback.callback())));
EXPECT_EQ("New match", std::string(dict->data()->data(), dict->size()));
}
TEST_P(SharedDictionaryManagerTest, OverrideDictionary) { TEST_P(SharedDictionaryManagerTest, OverrideDictionary) {
std::unique_ptr<SharedDictionaryManager> manager = std::unique_ptr<SharedDictionaryManager> manager =
CreateSharedDictionaryManager(); CreateSharedDictionaryManager();

@@ -120,6 +120,12 @@ std::optional<DictionaryHeaderInfo> ParseDictionaryHeaderInfo(
} // namespace } // namespace
// static
bool SharedDictionaryStorage::NeedToUseUrlPatternMatcher() {
return features::kCompressionDictionaryTransportBackendVersion.Get() !=
features::CompressionDictionaryTransportBackendVersion::kV1;
}
SharedDictionaryStorage::SharedDictionaryStorage() = default; SharedDictionaryStorage::SharedDictionaryStorage() = default;
SharedDictionaryStorage::~SharedDictionaryStorage() = default; SharedDictionaryStorage::~SharedDictionaryStorage() = default;

@@ -63,6 +63,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) SharedDictionaryStorage
protected: protected:
friend class base::RefCounted<SharedDictionaryStorage>; friend class base::RefCounted<SharedDictionaryStorage>;
// Returns true when V2 backend is used.
// TODO(crbug.com/1413922): Remove this when we remove V1 backend support.
static bool NeedToUseUrlPatternMatcher();
SharedDictionaryStorage(); SharedDictionaryStorage();
virtual ~SharedDictionaryStorage(); virtual ~SharedDictionaryStorage();
@@ -93,23 +97,29 @@ DictionaryInfoType* GetMatchingDictionaryFromDictionaryInfoMap(
if (it == dictionary_info_map.end()) { if (it == dictionary_info_map.end()) {
return nullptr; return nullptr;
} }
DictionaryInfoType* info = nullptr; DictionaryInfoType* matched_info = nullptr;
size_t mached_path_size = 0;
// TODO(crbug.com/1413922): If there are multiple matching dictionaries, this
// method currently returns the dictionary with the longest path pattern. But
// we should have a detailed description about `best-matching` in the spec.
for (auto& item : it->second) { for (auto& item : it->second) {
// TODO(crbug.com/1413922): base::MatchPattern() is treating '?' in the DictionaryInfoType& info = item.second;
// pattern as an wildcard. We need to introduce a new flag in CHECK_EQ(info.match(), item.first);
// base::MatchPattern() to treat '?' as a normal character. if (matched_info &&
// TODO(crbug.com/1413922): Need support path expansion for relative paths. ((matched_info->match().size() > info.match().size()) ||
if ((item.first.size() > mached_path_size) && (matched_info->match().size() == info.match().size() &&
base::MatchPattern(url.path(), item.first)) { matched_info->response_time() > info.response_time()))) {
mached_path_size = item.first.size(); continue;
info = &item.second; }
if (!info.matcher()) {
// This is for V1 backend.
// TODO(crbug.com/1413922): Remove this after V1 backend is removed.
if (base::MatchPattern(url.path(), info.match())) {
matched_info = &info;
}
} else {
if (info.matcher()->Match(url)) {
matched_info = &info;
}
} }
} }
return info; return matched_info;
} }
// Returns true if the same dictionary is already registered in // Returns true if the same dictionary is already registered in

@@ -14,6 +14,7 @@
#include "services/network/shared_dictionary/shared_dictionary_in_memory.h" #include "services/network/shared_dictionary/shared_dictionary_in_memory.h"
#include "services/network/shared_dictionary/shared_dictionary_manager_in_memory.h" #include "services/network/shared_dictionary/shared_dictionary_manager_in_memory.h"
#include "services/network/shared_dictionary/shared_dictionary_writer_in_memory.h" #include "services/network/shared_dictionary/shared_dictionary_writer_in_memory.h"
#include "services/network/shared_dictionary/simple_url_pattern_matcher.h"
#include "url/scheme_host_port.h" #include "url/scheme_host_port.h"
namespace network { namespace network {
@@ -105,9 +106,18 @@ SharedDictionaryStorageInMemory::CreateWriter(const GURL& url,
base::Time response_time, base::Time response_time,
base::TimeDelta expiration, base::TimeDelta expiration,
const std::string& match) { const std::string& match) {
return base::MakeRefCounted<SharedDictionaryWriterInMemory>(base::BindOnce( std::unique_ptr<SimpleUrlPatternMatcher> matcher;
&SharedDictionaryStorageInMemory::OnDictionaryWritten, if (NeedToUseUrlPatternMatcher()) {
weak_factory_.GetWeakPtr(), url, response_time, expiration, match)); auto matcher_create_result = SimpleUrlPatternMatcher::Create(match, url);
if (!matcher_create_result.has_value()) {
return nullptr;
}
matcher = std::move(matcher_create_result.value());
}
return base::MakeRefCounted<SharedDictionaryWriterInMemory>(
base::BindOnce(&SharedDictionaryStorageInMemory::OnDictionaryWritten,
weak_factory_.GetWeakPtr(), url, response_time, expiration,
match, std::move(matcher)));
} }
bool SharedDictionaryStorageInMemory::IsAlreadyRegistered( bool SharedDictionaryStorageInMemory::IsAlreadyRegistered(
@@ -124,6 +134,7 @@ void SharedDictionaryStorageInMemory::OnDictionaryWritten(
base::Time response_time, base::Time response_time,
base::TimeDelta expiration, base::TimeDelta expiration,
const std::string& match, const std::string& match,
std::unique_ptr<SimpleUrlPatternMatcher> matcher,
SharedDictionaryWriterInMemory::Result result, SharedDictionaryWriterInMemory::Result result,
scoped_refptr<net::IOBuffer> data, scoped_refptr<net::IOBuffer> data,
size_t size, size_t size,
@@ -132,9 +143,9 @@ void SharedDictionaryStorageInMemory::OnDictionaryWritten(
return; return;
} }
dictionary_info_map_[url::SchemeHostPort(url)].insert_or_assign( dictionary_info_map_[url::SchemeHostPort(url)].insert_or_assign(
match, match, DictionaryInfo(url, response_time, expiration, match,
DictionaryInfo(url, response_time, expiration, match, /*last_used_time=*/base::Time::Now(), data, size,
/*last_used_time=*/base::Time::Now(), data, size, hash)); hash, std::move(matcher)));
if (manager_) { if (manager_) {
manager_->MaybeRunCacheEvictionPerSite(isolation_key_.top_frame_site()); manager_->MaybeRunCacheEvictionPerSite(isolation_key_.top_frame_site());
manager_->MaybeRunCacheEviction(); manager_->MaybeRunCacheEviction();
@@ -149,7 +160,8 @@ SharedDictionaryStorageInMemory::DictionaryInfo::DictionaryInfo(
base::Time last_used_time, base::Time last_used_time,
scoped_refptr<net::IOBuffer> data, scoped_refptr<net::IOBuffer> data,
size_t size, size_t size,
const net::SHA256HashValue& hash) const net::SHA256HashValue& hash,
std::unique_ptr<SimpleUrlPatternMatcher> matcher)
: url_(url), : url_(url),
response_time_(response_time), response_time_(response_time),
expiration_(expiration), expiration_(expiration),
@@ -157,7 +169,8 @@ SharedDictionaryStorageInMemory::DictionaryInfo::DictionaryInfo(
last_used_time_(last_used_time), last_used_time_(last_used_time),
data_(std::move(data)), data_(std::move(data)),
size_(size), size_(size),
hash_(hash) {} hash_(hash),
matcher_(std::move(matcher)) {}
SharedDictionaryStorageInMemory::DictionaryInfo::DictionaryInfo( SharedDictionaryStorageInMemory::DictionaryInfo::DictionaryInfo(
DictionaryInfo&& other) = default; DictionaryInfo&& other) = default;

@@ -30,6 +30,7 @@ class CorsURLLoaderSharedDictionaryTest;
} // namespace cors } // namespace cors
class SharedDictionaryManagerInMemory; class SharedDictionaryManagerInMemory;
class SimpleUrlPatternMatcher;
// A SharedDictionaryStorage which is managed by // A SharedDictionaryStorage which is managed by
// SharedDictionaryManagerInMemory. // SharedDictionaryManagerInMemory.
@@ -45,7 +46,8 @@ class SharedDictionaryStorageInMemory : public SharedDictionaryStorage {
base::Time last_used_time, base::Time last_used_time,
scoped_refptr<net::IOBuffer> data, scoped_refptr<net::IOBuffer> data,
size_t size, size_t size,
const net::SHA256HashValue& hash); const net::SHA256HashValue& hash,
std::unique_ptr<SimpleUrlPatternMatcher> matcher);
DictionaryInfo(const DictionaryInfo&) = delete; DictionaryInfo(const DictionaryInfo&) = delete;
DictionaryInfo& operator=(const DictionaryInfo&) = delete; DictionaryInfo& operator=(const DictionaryInfo&) = delete;
@@ -63,6 +65,7 @@ class SharedDictionaryStorageInMemory : public SharedDictionaryStorage {
const scoped_refptr<net::IOBuffer>& data() const { return data_; } const scoped_refptr<net::IOBuffer>& data() const { return data_; }
size_t size() const { return size_; } size_t size() const { return size_; }
const net::SHA256HashValue& hash() const { return hash_; } const net::SHA256HashValue& hash() const { return hash_; }
const SimpleUrlPatternMatcher* matcher() const { return matcher_.get(); }
void set_last_used_time(base::Time last_used_time) { void set_last_used_time(base::Time last_used_time) {
last_used_time_ = last_used_time; last_used_time_ = last_used_time;
@@ -77,6 +80,7 @@ class SharedDictionaryStorageInMemory : public SharedDictionaryStorage {
scoped_refptr<net::IOBuffer> data_; scoped_refptr<net::IOBuffer> data_;
size_t size_; size_t size_;
net::SHA256HashValue hash_; net::SHA256HashValue hash_;
std::unique_ptr<SimpleUrlPatternMatcher> matcher_;
}; };
SharedDictionaryStorageInMemory( SharedDictionaryStorageInMemory(
@@ -127,6 +131,7 @@ class SharedDictionaryStorageInMemory : public SharedDictionaryStorage {
base::Time response_time, base::Time response_time,
base::TimeDelta expiration, base::TimeDelta expiration,
const std::string& match, const std::string& match,
std::unique_ptr<SimpleUrlPatternMatcher> matcher,
SharedDictionaryWriterInMemory::Result result, SharedDictionaryWriterInMemory::Result result,
scoped_refptr<net::IOBuffer> data, scoped_refptr<net::IOBuffer> data,
size_t size, size_t size,

@@ -19,6 +19,7 @@
#include "services/network/shared_dictionary/shared_dictionary_manager_on_disk.h" #include "services/network/shared_dictionary/shared_dictionary_manager_on_disk.h"
#include "services/network/shared_dictionary/shared_dictionary_on_disk.h" #include "services/network/shared_dictionary/shared_dictionary_on_disk.h"
#include "services/network/shared_dictionary/shared_dictionary_writer_on_disk.h" #include "services/network/shared_dictionary/shared_dictionary_writer_on_disk.h"
#include "services/network/shared_dictionary/simple_url_pattern_matcher.h"
#include "url/scheme_host_port.h" #include "url/scheme_host_port.h"
namespace network { namespace network {
@@ -104,6 +105,19 @@ class SharedDictionaryStorageOnDisk::WrappedSharedDictionary
scoped_refptr<RefCountedSharedDictionary> ref_counted_shared_dictionary_; scoped_refptr<RefCountedSharedDictionary> ref_counted_shared_dictionary_;
}; };
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher::
DictionaryInfoWithMatcher(net::SharedDictionaryInfo info,
std::unique_ptr<SimpleUrlPatternMatcher> matcher)
: net::SharedDictionaryInfo(std::move(info)),
matcher_(std::move(matcher)) {}
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher::
~DictionaryInfoWithMatcher() = default;
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher::
DictionaryInfoWithMatcher(DictionaryInfoWithMatcher&&) = default;
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher&
SharedDictionaryStorageOnDisk::DictionaryInfoWithMatcher::operator=(
DictionaryInfoWithMatcher&&) = default;
SharedDictionaryStorageOnDisk::SharedDictionaryStorageOnDisk( SharedDictionaryStorageOnDisk::SharedDictionaryStorageOnDisk(
base::WeakPtr<SharedDictionaryManagerOnDisk> manager, base::WeakPtr<SharedDictionaryManagerOnDisk> manager,
const net::SharedDictionaryIsolationKey& isolation_key, const net::SharedDictionaryIsolationKey& isolation_key,
@@ -197,10 +211,19 @@ SharedDictionaryStorageOnDisk::CreateWriter(const GURL& url,
if (!manager_) { if (!manager_) {
return nullptr; return nullptr;
} }
std::unique_ptr<SimpleUrlPatternMatcher> matcher;
if (NeedToUseUrlPatternMatcher()) {
auto matcher_create_result = SimpleUrlPatternMatcher::Create(match, url);
if (!matcher_create_result.has_value()) {
return nullptr;
}
matcher = std::move(matcher_create_result.value());
}
return manager_->CreateWriter( return manager_->CreateWriter(
isolation_key_, url, response_time, expiration, match, isolation_key_, url, response_time, expiration, match,
base::BindOnce(&SharedDictionaryStorageOnDisk::OnDictionaryWritten, base::BindOnce(&SharedDictionaryStorageOnDisk::OnDictionaryWritten,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr(), std::move(matcher)));
} }
bool SharedDictionaryStorageOnDisk::IsAlreadyRegistered( bool SharedDictionaryStorageOnDisk::IsAlreadyRegistered(
@@ -220,13 +243,24 @@ void SharedDictionaryStorageOnDisk::OnDatabaseRead(
if (!result.has_value()) { if (!result.has_value()) {
return; return;
} }
std::set<base::UnguessableToken> deleted_cache_tokens;
const bool need_matcher = NeedToUseUrlPatternMatcher();
for (auto& info : result.value()) { for (auto& info : result.value()) {
const url::SchemeHostPort scheme_host_port = const url::SchemeHostPort scheme_host_port =
url::SchemeHostPort(info.url()); url::SchemeHostPort(info.url());
const std::string match = info.match(); const std::string match = info.match();
(dictionary_info_map_[scheme_host_port]) std::unique_ptr<SimpleUrlPatternMatcher> matcher;
.insert(std::make_pair(match, std::move(info))); if (need_matcher) {
auto matcher_create_result =
SimpleUrlPatternMatcher::Create(match, info.url());
if (!matcher_create_result.has_value()) {
continue;
}
matcher = std::move(matcher_create_result.value());
}
dictionary_info_map_[scheme_host_port].insert(std::make_pair(
match, DictionaryInfoWithMatcher(std::move(info), std::move(matcher))));
} }
auto callbacks = std::move(pending_get_dictionary_tasks_); auto callbacks = std::move(pending_get_dictionary_tasks_);
@@ -236,11 +270,13 @@ void SharedDictionaryStorageOnDisk::OnDatabaseRead(
} }
void SharedDictionaryStorageOnDisk::OnDictionaryWritten( void SharedDictionaryStorageOnDisk::OnDictionaryWritten(
std::unique_ptr<SimpleUrlPatternMatcher> matcher,
net::SharedDictionaryInfo info) { net::SharedDictionaryInfo info) {
const url::SchemeHostPort scheme_host_port = url::SchemeHostPort(info.url()); const url::SchemeHostPort scheme_host_port = url::SchemeHostPort(info.url());
const std::string match = info.match(); const std::string match = info.match();
(dictionary_info_map_[scheme_host_port]) (dictionary_info_map_[scheme_host_port])
.insert_or_assign(match, std::move(info)); .insert_or_assign(match, DictionaryInfoWithMatcher(std::move(info),
std::move(matcher)));
} }
void SharedDictionaryStorageOnDisk::OnRefCountedSharedDictionaryDeleted( void SharedDictionaryStorageOnDisk::OnRefCountedSharedDictionaryDeleted(

@@ -28,6 +28,7 @@
namespace network { namespace network {
class SharedDictionaryManagerOnDisk; class SharedDictionaryManagerOnDisk;
class SimpleUrlPatternMatcher;
// A SharedDictionaryStorage which is managed by SharedDictionaryManagerOnDisk. // A SharedDictionaryStorage which is managed by SharedDictionaryManagerOnDisk.
class SharedDictionaryStorageOnDisk : public SharedDictionaryStorage { class SharedDictionaryStorageOnDisk : public SharedDictionaryStorage {
@@ -71,14 +72,32 @@ class SharedDictionaryStorageOnDisk : public SharedDictionaryStorage {
class RefCountedSharedDictionary; class RefCountedSharedDictionary;
class WrappedSharedDictionary; class WrappedSharedDictionary;
class DictionaryInfoWithMatcher : public net::SharedDictionaryInfo {
public:
DictionaryInfoWithMatcher(net::SharedDictionaryInfo info,
std::unique_ptr<SimpleUrlPatternMatcher> matcher);
~DictionaryInfoWithMatcher();
DictionaryInfoWithMatcher(const DictionaryInfoWithMatcher&) = delete;
DictionaryInfoWithMatcher& operator=(const DictionaryInfoWithMatcher&) =
delete;
DictionaryInfoWithMatcher(DictionaryInfoWithMatcher&&);
DictionaryInfoWithMatcher& operator=(DictionaryInfoWithMatcher&&);
const SimpleUrlPatternMatcher* matcher() const { return matcher_.get(); }
private:
std::unique_ptr<SimpleUrlPatternMatcher> matcher_;
};
void OnDatabaseRead( void OnDatabaseRead(
net::SQLitePersistentSharedDictionaryStore::DictionaryListOrError result); net::SQLitePersistentSharedDictionaryStore::DictionaryListOrError result);
void OnDictionaryWritten(net::SharedDictionaryInfo info); void OnDictionaryWritten(std::unique_ptr<SimpleUrlPatternMatcher> matcher,
net::SharedDictionaryInfo info);
void OnRefCountedSharedDictionaryDeleted( void OnRefCountedSharedDictionaryDeleted(
const base::UnguessableToken& disk_cache_key_token); const base::UnguessableToken& disk_cache_key_token);
const std::map<url::SchemeHostPort, const std::map<url::SchemeHostPort,
std::map<std::string, net::SharedDictionaryInfo>>& std::map<std::string, DictionaryInfoWithMatcher>>&
GetDictionaryMapForTesting() { GetDictionaryMapForTesting() {
return dictionary_info_map_; return dictionary_info_map_;
} }
@@ -87,7 +106,7 @@ class SharedDictionaryStorageOnDisk : public SharedDictionaryStorage {
const net::SharedDictionaryIsolationKey isolation_key_; const net::SharedDictionaryIsolationKey isolation_key_;
base::ScopedClosureRunner on_deleted_closure_runner_; base::ScopedClosureRunner on_deleted_closure_runner_;
std::map<url::SchemeHostPort, std::map<url::SchemeHostPort,
std::map<std::string, net::SharedDictionaryInfo>> std::map<std::string, DictionaryInfoWithMatcher>>
dictionary_info_map_; dictionary_info_map_;
std::map<base::UnguessableToken, raw_ptr<RefCountedSharedDictionary>> std::map<base::UnguessableToken, raw_ptr<RefCountedSharedDictionary>>
dictionaries_; dictionaries_;