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
|
@ -1360,6 +1360,36 @@ specified when registering the protocol.
|
|||
|
||||
Returns `Promise<void>` - resolves when the code cache clear operation is complete.
|
||||
|
||||
#### `ses.getSharedDictionaryUsageInfo()`
|
||||
|
||||
Returns `Promise<SharedDictionaryUsageInfo[]>` - an array of shared dictionary information entries in Chromium's networking service's storage.
|
||||
|
||||
Shared dictionaries are used to power advanced compression of data sent over the wire, specifically with Brotli and ZStandard. You don't need to call any of the shared dictionary APIs in Electron to make use of this advanced web feature, but if you do, they allow deeper control and inspection of the shared dictionaries used during decompression.
|
||||
|
||||
To get detailed information about a specific shared dictionary entry, call `getSharedDictionaryInfo(options)`.
|
||||
|
||||
#### `ses.getSharedDictionaryInfo(options)`
|
||||
|
||||
* `options` Object
|
||||
* `frameOrigin` string - The origin of the frame where the request originates. It’s specific to the individual frame making the request and is defined by its scheme, host, and port. In practice, will look like a URL.
|
||||
* `topFrameSite` string - The site of the top-level browsing context (the main frame or tab that contains the request). It’s less granular than `frameOrigin` and focuses on the broader "site" scope. In practice, will look like a URL.
|
||||
|
||||
Returns `Promise<SharedDictionaryInfo[]>` - an array of shared dictionary information entries in Chromium's networking service's storage.
|
||||
|
||||
To get information about all present shared dictionaries, call `getSharedDictionaryUsageInfo()`.
|
||||
|
||||
#### `ses.clearSharedDictionaryCache()`
|
||||
|
||||
Returns `Promise<void>` - resolves when the dictionary cache has been cleared, both in memory and on disk.
|
||||
|
||||
#### `ses.clearSharedDictionaryCacheForIsolationKey(options)`
|
||||
|
||||
* `options` Object
|
||||
* `frameOrigin` string - The origin of the frame where the request originates. It’s specific to the individual frame making the request and is defined by its scheme, host, and port. In practice, will look like a URL.
|
||||
* `topFrameSite` string - The site of the top-level browsing context (the main frame or tab that contains the request). It’s less granular than `frameOrigin` and focuses on the broader "site" scope. In practice, will look like a URL.
|
||||
|
||||
Returns `Promise<void>` - resolves when the dictionary cache has been cleared for the specified isolation key, both in memory and on disk.
|
||||
|
||||
#### `ses.setSpellCheckerEnabled(enable)`
|
||||
|
||||
* `enable` boolean
|
||||
|
@ -1537,6 +1567,8 @@ This method clears more types of data and is more thorough than the
|
|||
|
||||
**Note:** Cookies are stored at a broader scope than origins. When removing cookies and filtering by `origins` (or `excludeOrigins`), the cookies will be removed at the [registrable domain](https://url.spec.whatwg.org/#host-registrable-domain) level. For example, clearing cookies for the origin `https://really.specific.origin.example.com/` will end up clearing all cookies for `example.com`. Clearing cookies for the origin `https://my.website.example.co.uk/` will end up clearing all cookies for `example.co.uk`.
|
||||
|
||||
**Note:** Clearing cache data will also clear the shared dictionary cache. This means that any dictionaries used for compression may be reloaded after clearing the cache. If you wish to clear the shared dictionary cache but leave other cached data intact, you may want to use the `clearSharedDictionaryCache` method.
|
||||
|
||||
For more information, refer to Chromium's [`BrowsingDataRemover` interface][browsing-data-remover].
|
||||
|
||||
### Instance Properties
|
||||
|
|
12
docs/api/structures/shared-dictionary-info.md
Normal file
12
docs/api/structures/shared-dictionary-info.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
# SharedDictionaryInfo Object
|
||||
|
||||
* `match` string - The matching path pattern for the dictionary which was declared in 'use-as-dictionary' response header's `match` option.
|
||||
* `matchDestinations` string[] - An array of matching destinations for the dictionary which was declared in 'use-as-dictionary' response header's `match-dest` option.
|
||||
* `id` string - The Id for the dictionary which was declared in 'use-as-dictionary' response header's `id` option.
|
||||
* `dictionaryUrl` string - URL of the dictionary.
|
||||
* `lastFetchTime` Date - The time of when the dictionary was received from the network layer.
|
||||
* `responseTime` Date - The time of when the dictionary was received from the server. For cached responses, this time could be "far" in the past.
|
||||
* `expirationDuration` number - The expiration time for the dictionary which was declared in 'use-as-dictionary' response header's `expires` option in seconds.
|
||||
* `lastUsedTime` Date - The time when the dictionary was last used.
|
||||
* `size` number - The amount of bytes stored for this shared dictionary information object in Chromium's internal storage (usually Sqlite).
|
||||
* `hash` string - The sha256 hash of the dictionary binary.
|
5
docs/api/structures/shared-dictionary-usage-info.md
Normal file
5
docs/api/structures/shared-dictionary-usage-info.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SharedDictionaryUsageInfo Object
|
||||
|
||||
* `frameOrigin` string - The origin of the frame where the request originates. It’s specific to the individual frame making the request and is defined by its scheme, host, and port. In practice, will look like a URL.
|
||||
* `topFrameSite` string - The site of the top-level browsing context (the main frame or tab that contains the request). It’s less granular than `frameOrigin` and focuses on the broader "site" scope. In practice, will look like a URL.
|
||||
* `totalSizeBytes` number - The amount of bytes stored for this shared dictionary information object in Chromium's internal storage (usually Sqlite).
|
|
@ -133,6 +133,8 @@ auto_filenames = {
|
|||
"docs/api/structures/segmented-control-segment.md",
|
||||
"docs/api/structures/serial-port.md",
|
||||
"docs/api/structures/service-worker-info.md",
|
||||
"docs/api/structures/shared-dictionary-info.md",
|
||||
"docs/api/structures/shared-dictionary-usage-info.md",
|
||||
"docs/api/structures/shared-worker-info.md",
|
||||
"docs/api/structures/sharing-item.md",
|
||||
"docs/api/structures/shortcut-details.md",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -140,6 +140,12 @@ class Session final : public gin::Wrappable<Session>,
|
|||
void CreateInterruptedDownload(const gin_helper::Dictionary& options);
|
||||
void SetPreloads(const std::vector<base::FilePath>& preloads);
|
||||
std::vector<base::FilePath> GetPreloads() const;
|
||||
v8::Local<v8::Promise> GetSharedDictionaryInfo(
|
||||
const gin_helper::Dictionary& options);
|
||||
v8::Local<v8::Promise> GetSharedDictionaryUsageInfo();
|
||||
v8::Local<v8::Promise> ClearSharedDictionaryCache();
|
||||
v8::Local<v8::Promise> ClearSharedDictionaryCacheForIsolationKey(
|
||||
const gin_helper::Dictionary& options);
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> ServiceWorkerContext(v8::Isolate* isolate);
|
||||
|
|
|
@ -277,6 +277,106 @@ describe('session module', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('shared dictionary APIs', () => {
|
||||
// Shared dictionaries can only be created from real https websites, which we
|
||||
// lack the APIs to fake in CI. If you're working on this code, you can run
|
||||
// the real-internet tests below by uncommenting the `skip` below.
|
||||
// In CI, we'll run simple tests here that ensure that the code in question doesn't
|
||||
// crash, even if we expect it to not return any real dictionaries.
|
||||
it('can get shared dictionary usage info', async () => {
|
||||
expect(await session.defaultSession.getSharedDictionaryUsageInfo()).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('can get shared dictionary info', async () => {
|
||||
expect(await session.defaultSession.getSharedDictionaryInfo({
|
||||
frameOrigin: 'https://compression-dictionary-transport-threejs-demo.glitch.me',
|
||||
topFrameSite: 'https://compression-dictionary-transport-threejs-demo.glitch.me'
|
||||
})).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('can clear shared dictionary cache', async () => {
|
||||
await session.defaultSession.clearSharedDictionaryCache();
|
||||
});
|
||||
|
||||
it('can clear shared dictionary cache for isolation key', async () => {
|
||||
await session.defaultSession.clearSharedDictionaryCacheForIsolationKey({
|
||||
frameOrigin: 'https://compression-dictionary-transport-threejs-demo.glitch.me',
|
||||
topFrameSite: 'https://compression-dictionary-transport-threejs-demo.glitch.me'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('shared dictionary APIs (using a real website with real dictionaries)', () => {
|
||||
const appPath = path.join(fixtures, 'api', 'shared-dictionary');
|
||||
const runApp = (command: 'getSharedDictionaryInfo' | 'getSharedDictionaryUsageInfo' | 'clearSharedDictionaryCache' | 'clearSharedDictionaryCacheForIsolationKey') => {
|
||||
return new Promise((resolve) => {
|
||||
let output = '';
|
||||
|
||||
const appProcess = ChildProcess.spawn(
|
||||
process.execPath,
|
||||
[appPath, command]
|
||||
);
|
||||
|
||||
appProcess.stdout.on('data', data => { output += data; });
|
||||
appProcess.on('exit', () => {
|
||||
const trimmedOutput = output.replaceAll(/(\r\n|\n|\r)/gm, '');
|
||||
|
||||
try {
|
||||
resolve(JSON.parse(trimmedOutput));
|
||||
} catch (e) {
|
||||
console.error(`Error trying to deserialize ${trimmedOutput}`);
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
fs.rmSync(path.join(fixtures, 'api', 'shared-dictionary', 'user-data-dir'), { recursive: true });
|
||||
});
|
||||
|
||||
it('can get shared dictionary usage info', async () => {
|
||||
// In our fixture, this calls session.defaultSession.getSharedDictionaryUsageInfo()
|
||||
expect(await runApp('getSharedDictionaryUsageInfo')).to.deep.equal([{
|
||||
frameOrigin: 'https://compression-dictionary-transport-threejs-demo.glitch.me',
|
||||
topFrameSite: 'https://compression-dictionary-transport-threejs-demo.glitch.me',
|
||||
totalSizeBytes: 1198641
|
||||
}]);
|
||||
});
|
||||
|
||||
it('can get shared dictionary info', async () => {
|
||||
// In our fixture, this calls session.defaultSession.getSharedDictionaryInfo({
|
||||
// frameOrigin: 'https://compression-dictionary-transport-threejs-demo.glitch.me',
|
||||
// topFrameSite: 'https://compression-dictionary-transport-threejs-demo.glitch.me'
|
||||
// })
|
||||
const sharedDictionaryInfo = await runApp('getSharedDictionaryInfo') as Electron.SharedDictionaryInfo[];
|
||||
|
||||
expect(sharedDictionaryInfo).to.have.lengthOf(1);
|
||||
expect(sharedDictionaryInfo[0].match).to.not.be.undefined();
|
||||
expect(sharedDictionaryInfo[0].hash).to.not.be.undefined();
|
||||
expect(sharedDictionaryInfo[0].lastFetchTime).to.not.be.undefined();
|
||||
expect(sharedDictionaryInfo[0].responseTime).to.not.be.undefined();
|
||||
expect(sharedDictionaryInfo[0].expirationDuration).to.not.be.undefined();
|
||||
expect(sharedDictionaryInfo[0].lastUsedTime).to.not.be.undefined();
|
||||
expect(sharedDictionaryInfo[0].size).to.not.be.undefined();
|
||||
});
|
||||
|
||||
it('can clear shared dictionary cache', async () => {
|
||||
// In our fixture, this calls session.defaultSession.clearSharedDictionaryCache()
|
||||
// followed by session.defaultSession.getSharedDictionaryUsageInfo()
|
||||
expect(await runApp('clearSharedDictionaryCache')).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('can clear shared dictionary cache for isolation key', async () => {
|
||||
// In our fixture, this calls session.defaultSession.clearSharedDictionaryCacheForIsolationKey({
|
||||
// frameOrigin: 'https://compression-dictionary-transport-threejs-demo.glitch.me',
|
||||
// topFrameSite: 'https://compression-dictionary-transport-threejs-demo.glitch.me'
|
||||
// })
|
||||
// followed by session.defaultSession.getSharedDictionaryUsageInfo()
|
||||
expect(await runApp('clearSharedDictionaryCacheForIsolationKey')).to.deep.equal([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('will-download event', () => {
|
||||
afterEach(closeAllWindows);
|
||||
it('can cancel default download behavior', async () => {
|
||||
|
|
42
spec/fixtures/api/shared-dictionary/main.js
vendored
Normal file
42
spec/fixtures/api/shared-dictionary/main.js
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
const { app, BrowserWindow, session } = require('electron');
|
||||
|
||||
const path = require('node:path');
|
||||
|
||||
app.setPath('userData', path.join(__dirname, 'user-data-dir'));
|
||||
|
||||
// Grab the command to run from process.argv
|
||||
const command = process.argv[2];
|
||||
app.whenReady().then(async () => {
|
||||
const bw = new BrowserWindow({ show: true });
|
||||
await bw.loadURL('https://compression-dictionary-transport-threejs-demo.glitch.me/demo.html?r=151');
|
||||
|
||||
// Wait a second for glitch to load, it sometimes takes a while
|
||||
// if the glitch app is booting up (did-finish-load will fire too soon)
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
try {
|
||||
let result;
|
||||
const isolationKey = {
|
||||
frameOrigin: 'https://compression-dictionary-transport-threejs-demo.glitch.me',
|
||||
topFrameSite: 'https://compression-dictionary-transport-threejs-demo.glitch.me'
|
||||
};
|
||||
|
||||
if (command === 'getSharedDictionaryInfo') {
|
||||
result = await session.defaultSession.getSharedDictionaryInfo(isolationKey);
|
||||
} else if (command === 'getSharedDictionaryUsageInfo') {
|
||||
result = await session.defaultSession.getSharedDictionaryUsageInfo();
|
||||
} else if (command === 'clearSharedDictionaryCache') {
|
||||
await session.defaultSession.clearSharedDictionaryCache();
|
||||
result = await session.defaultSession.getSharedDictionaryUsageInfo();
|
||||
} else if (command === 'clearSharedDictionaryCacheForIsolationKey') {
|
||||
await session.defaultSession.clearSharedDictionaryCacheForIsolationKey(isolationKey);
|
||||
result = await session.defaultSession.getSharedDictionaryUsageInfo();
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(result));
|
||||
} catch (e) {
|
||||
console.log('error', e);
|
||||
} finally {
|
||||
app.quit();
|
||||
}
|
||||
});
|
4
spec/fixtures/api/shared-dictionary/package.json
vendored
Normal file
4
spec/fixtures/api/shared-dictionary/package.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "electron-test-shared-dictionary-app",
|
||||
"main": "main.js"
|
||||
}
|
Loading…
Reference in a new issue