feat: Add shared dictionary management APIs (#44950)
* Add bare-bones GetSharedDictionaryUsageInfo * Add GetSharedDictionaryInfo() * Improve API, use isolation keys * Add documentation * Update docs/api/session.md * Update shell/browser/api/electron_api_session.cc * Add tests * Implement feedback <3 * Improve tests * chore: lint * docs: add note about clearing cache in ses.clearData --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Felix Rieseberg <fr@makenotion.com>
This commit is contained in:
parent
c54f1f98fe
commit
9a7848ced1
9 changed files with 384 additions and 0 deletions
|
@ -54,6 +54,7 @@
|
|||
#include "net/http/http_util.h"
|
||||
#include "services/network/network_service.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "services/network/public/cpp/request_destination.h"
|
||||
#include "services/network/public/mojom/clear_data_filter.mojom.h"
|
||||
#include "shell/browser/api/electron_api_app.h"
|
||||
#include "shell/browser/api/electron_api_cookies.h"
|
||||
|
@ -79,6 +80,7 @@
|
|||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/media_converter.h"
|
||||
#include "shell/common/gin_converters/net_converter.h"
|
||||
#include "shell/common/gin_converters/time_converter.h"
|
||||
#include "shell/common/gin_converters/usb_protected_classes_converter.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
|
@ -1074,6 +1076,178 @@ std::vector<base::FilePath> Session::GetPreloads() const {
|
|||
return prefs->preloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the network service's ClearSharedDictionaryCacheForIsolationKey
|
||||
* method, allowing clearing the Shared Dictionary cache for a given isolation
|
||||
* key. Details about the feature available at
|
||||
* https://developer.chrome.com/blog/shared-dictionary-compression
|
||||
*/
|
||||
v8::Local<v8::Promise> Session::ClearSharedDictionaryCacheForIsolationKey(
|
||||
const gin_helper::Dictionary& options) {
|
||||
gin_helper::Promise<void> promise(isolate_);
|
||||
auto handle = promise.GetHandle();
|
||||
|
||||
GURL frame_origin_url, top_frame_site_url;
|
||||
if (!options.Get("frameOrigin", &frame_origin_url) ||
|
||||
!options.Get("topFrameSite", &top_frame_site_url)) {
|
||||
promise.RejectWithErrorMessage(
|
||||
"Must provide frameOrigin and topFrameSite strings to "
|
||||
"`clearSharedDictionaryCacheForIsolationKey`");
|
||||
return handle;
|
||||
}
|
||||
|
||||
if (!frame_origin_url.is_valid() || !top_frame_site_url.is_valid()) {
|
||||
promise.RejectWithErrorMessage(
|
||||
"Invalid URLs provided for frameOrigin or topFrameSite");
|
||||
return handle;
|
||||
}
|
||||
|
||||
url::Origin frame_origin = url::Origin::Create(frame_origin_url);
|
||||
net::SchemefulSite top_frame_site(top_frame_site_url);
|
||||
net::SharedDictionaryIsolationKey isolation_key(frame_origin, top_frame_site);
|
||||
|
||||
browser_context_->GetDefaultStoragePartition()
|
||||
->GetNetworkContext()
|
||||
->ClearSharedDictionaryCacheForIsolationKey(
|
||||
isolation_key,
|
||||
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
||||
std::move(promise)));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the network service's ClearSharedDictionaryCache
|
||||
* method, allowing clearing the Shared Dictionary cache.
|
||||
* https://developer.chrome.com/blog/shared-dictionary-compression
|
||||
*/
|
||||
v8::Local<v8::Promise> Session::ClearSharedDictionaryCache() {
|
||||
gin_helper::Promise<void> promise(isolate_);
|
||||
auto handle = promise.GetHandle();
|
||||
|
||||
browser_context_->GetDefaultStoragePartition()
|
||||
->GetNetworkContext()
|
||||
->ClearSharedDictionaryCache(
|
||||
base::Time(), base::Time::Max(),
|
||||
nullptr /*mojom::ClearDataFilterPtr*/,
|
||||
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
||||
std::move(promise)));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the network service's GetSharedDictionaryInfo method, allowing
|
||||
* inspection of Shared Dictionary information. Details about the feature
|
||||
* available at https://developer.chrome.com/blog/shared-dictionary-compression
|
||||
*/
|
||||
v8::Local<v8::Promise> Session::GetSharedDictionaryInfo(
|
||||
const gin_helper::Dictionary& options) {
|
||||
gin_helper::Promise<std::vector<gin_helper::Dictionary>> promise(isolate_);
|
||||
auto handle = promise.GetHandle();
|
||||
|
||||
GURL frame_origin_url, top_frame_site_url;
|
||||
if (!options.Get("frameOrigin", &frame_origin_url) ||
|
||||
!options.Get("topFrameSite", &top_frame_site_url)) {
|
||||
promise.RejectWithErrorMessage(
|
||||
"Must provide frameOrigin and topFrameSite strings");
|
||||
return handle;
|
||||
}
|
||||
|
||||
if (!frame_origin_url.is_valid() || !top_frame_site_url.is_valid()) {
|
||||
promise.RejectWithErrorMessage(
|
||||
"Invalid URLs provided for frameOrigin or topFrameSite");
|
||||
return handle;
|
||||
}
|
||||
|
||||
url::Origin frame_origin = url::Origin::Create(frame_origin_url);
|
||||
net::SchemefulSite top_frame_site(top_frame_site_url);
|
||||
net::SharedDictionaryIsolationKey isolation_key(frame_origin, top_frame_site);
|
||||
|
||||
browser_context_->GetDefaultStoragePartition()
|
||||
->GetNetworkContext()
|
||||
->GetSharedDictionaryInfo(
|
||||
isolation_key,
|
||||
base::BindOnce(
|
||||
[](gin_helper::Promise<std::vector<gin_helper::Dictionary>>
|
||||
promise,
|
||||
std::vector<network::mojom::SharedDictionaryInfoPtr> info) {
|
||||
v8::Isolate* isolate = promise.isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
std::vector<gin_helper::Dictionary> result;
|
||||
result.reserve(info.size());
|
||||
|
||||
for (const auto& item : info) {
|
||||
gin_helper::Dictionary dict =
|
||||
gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("match", item->match);
|
||||
|
||||
// Convert RequestDestination enum values to strings
|
||||
std::vector<std::string> destinations;
|
||||
for (const auto& dest : item->match_dest) {
|
||||
destinations.push_back(
|
||||
network::RequestDestinationToString(dest));
|
||||
}
|
||||
dict.Set("matchDestinations", destinations);
|
||||
dict.Set("id", item->id);
|
||||
dict.Set("dictionaryUrl", item->dictionary_url.spec());
|
||||
dict.Set("lastFetchTime", item->last_fetch_time);
|
||||
dict.Set("responseTime", item->response_time);
|
||||
dict.Set("expirationDuration",
|
||||
item->expiration.InMillisecondsF());
|
||||
dict.Set("lastUsedTime", item->last_used_time);
|
||||
dict.Set("size", item->size);
|
||||
dict.Set("hash", net::HashValue(item->hash).ToString());
|
||||
|
||||
result.push_back(dict);
|
||||
}
|
||||
|
||||
promise.Resolve(result);
|
||||
},
|
||||
std::move(promise)));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the network service's GetSharedDictionaryUsageInfo method, allowing
|
||||
* inspection of Shared Dictionary information. Details about the feature
|
||||
* available at https://developer.chrome.com/blog/shared-dictionary-compression
|
||||
*/
|
||||
v8::Local<v8::Promise> Session::GetSharedDictionaryUsageInfo() {
|
||||
gin_helper::Promise<std::vector<gin_helper::Dictionary>> promise(isolate_);
|
||||
auto handle = promise.GetHandle();
|
||||
|
||||
browser_context_->GetDefaultStoragePartition()
|
||||
->GetNetworkContext()
|
||||
->GetSharedDictionaryUsageInfo(base::BindOnce(
|
||||
[](gin_helper::Promise<std::vector<gin_helper::Dictionary>> promise,
|
||||
const std::vector<net::SharedDictionaryUsageInfo>& info) {
|
||||
v8::Isolate* isolate = promise.isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
std::vector<gin_helper::Dictionary> result;
|
||||
result.reserve(info.size());
|
||||
|
||||
for (const auto& item : info) {
|
||||
gin_helper::Dictionary dict =
|
||||
gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("frameOrigin",
|
||||
item.isolation_key.frame_origin().Serialize());
|
||||
dict.Set("topFrameSite",
|
||||
item.isolation_key.top_frame_site().Serialize());
|
||||
dict.Set("totalSizeBytes", item.total_size_bytes);
|
||||
result.push_back(dict);
|
||||
}
|
||||
|
||||
promise.Resolve(result);
|
||||
},
|
||||
std::move(promise)));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
v8::Local<v8::Promise> Session::LoadExtension(
|
||||
const base::FilePath& extension_path,
|
||||
|
@ -1627,6 +1801,13 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
|
|||
&Session::CreateInterruptedDownload)
|
||||
.SetMethod("setPreloads", &Session::SetPreloads)
|
||||
.SetMethod("getPreloads", &Session::GetPreloads)
|
||||
.SetMethod("getSharedDictionaryUsageInfo",
|
||||
&Session::GetSharedDictionaryUsageInfo)
|
||||
.SetMethod("getSharedDictionaryInfo", &Session::GetSharedDictionaryInfo)
|
||||
.SetMethod("clearSharedDictionaryCache",
|
||||
&Session::ClearSharedDictionaryCache)
|
||||
.SetMethod("clearSharedDictionaryCacheForIsolationKey",
|
||||
&Session::ClearSharedDictionaryCacheForIsolationKey)
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
.SetMethod("loadExtension", &Session::LoadExtension)
|
||||
.SetMethod("removeExtension", &Session::RemoveExtension)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue