feat: Add shared dictionary management APIs (#44750)

* Add bare-bones GetSharedDictionaryUsageInfo

* Add GetSharedDictionaryInfo()

* Improve API, use isolation keys

* Add documentation

* Update docs/api/session.md

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

* Update shell/browser/api/electron_api_session.cc

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* Add tests

* Implement feedback <3

* Improve tests

* chore: lint

* docs: add note about clearing cache in ses.clearData

---------

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: alice <alice@makenotion.com>
This commit is contained in:
Felix Rieseberg 2024-12-04 14:25:11 -03:00 committed by GitHub
parent 158a87d494
commit 687a59b43b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 384 additions and 0 deletions

View file

@ -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 () => {