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:

committed by
Chromium LUCI CQ

parent
a6665cf098
commit
cdb7dfa61e
docs/experiments
services/network/shared_dictionary
@@ -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_;
|
||||||
|
Reference in New Issue
Block a user