[go: nahoru, domu]

blob: 063bdba66267475176a0e4f84c3344d4447a38d6 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const {assert} = chai;
import * as SDK from '../../../../../front_end/core/sdk/sdk.js';
import {assertNotNullOrUndefined} from '../../../../../front_end/core/platform/platform.js';
import * as Protocol from '../../../../../front_end/generated/protocol.js';
import * as Resources from '../../../../../front_end/panels/application/application.js';
import * as UI from '../../../../../front_end/ui/legacy/legacy.js';
import {createTarget} from '../../helpers/EnvironmentHelpers.js';
import {describeWithMockConnection, dispatchEvent} from '../../helpers/MockConnection.js';
import {assertElement, assertShadowRoot, dispatchFocusOutEvent} from '../../helpers/DOMHelpers.js';
import * as Coordinator from '../../../../../front_end/ui/components/render_coordinator/render_coordinator.js';
const coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();
describeWithMockConnection('StorageView', () => {
const tests = (targetFactory: () => SDK.Target.Target) => {
const testKey = 'test-storage-key';
const testOrigin = 'test-origin';
let target: SDK.Target.Target;
let domStorageModel: Resources.DOMStorageModel.DOMStorageModel|null;
let storageKeyManager: SDK.StorageKeyManager.StorageKeyManager|null;
beforeEach(() => {
target = targetFactory();
domStorageModel = target.model(Resources.DOMStorageModel.DOMStorageModel);
domStorageModel?.enable();
storageKeyManager = target.model(SDK.StorageKeyManager.StorageKeyManager);
});
it('emits correct events on clear', () => {
const testId = {storageKey: testKey, isLocalStorage: true} as Protocol.DOMStorage.StorageId;
assertNotNullOrUndefined(domStorageModel);
assert.isEmpty(domStorageModel.storages());
assertNotNullOrUndefined(storageKeyManager);
storageKeyManager.dispatchEventToListeners(SDK.StorageKeyManager.Events.StorageKeyAdded, testKey);
assertNotNullOrUndefined(domStorageModel.storageForId(testId));
const dispatcherSpy = sinon.spy(domStorageModel, 'dispatchEventToListeners');
const spyClearDataForStorageKey = sinon.stub(target.storageAgent(), 'invoke_clearDataForStorageKey');
Resources.StorageView.StorageView.clear(target, testKey, null, [Protocol.Storage.StorageType.All], false);
// must be called 4 times, twice with DOMStorageRemoved for local and non-local storage and twice with DOMStorageAdded
assert.isTrue(spyClearDataForStorageKey.calledOnce);
assert.strictEqual(dispatcherSpy.callCount, 4);
sinon.assert.calledWith(
dispatcherSpy, Resources.DOMStorageModel.Events.DOMStorageRemoved as unknown as sinon.SinonMatcher);
sinon.assert.calledWith(
dispatcherSpy, Resources.DOMStorageModel.Events.DOMStorageAdded as unknown as sinon.SinonMatcher);
});
it('changes subtitle on MainStorageKeyChanged event', () => {
assertNotNullOrUndefined(domStorageModel);
assertNotNullOrUndefined(storageKeyManager);
const view = new Resources.StorageView.StorageView();
storageKeyManager.dispatchEventToListeners(
SDK.StorageKeyManager.Events.MainStorageKeyChanged, {mainStorageKey: testKey});
const subtitle =
view.element.shadowRoot?.querySelector('div.flex-auto')?.shadowRoot?.querySelector('div.report-subtitle');
assert.strictEqual(subtitle?.textContent, testKey);
});
it('shows a warning message when entering a too big custom quota', async () => {
assertNotNullOrUndefined(domStorageModel);
assertNotNullOrUndefined(storageKeyManager);
const securityOriginManager = target.model(SDK.SecurityOriginManager.SecurityOriginManager);
assertNotNullOrUndefined(securityOriginManager);
sinon.stub(securityOriginManager, 'mainSecurityOrigin').returns(testOrigin);
const view = new Resources.StorageView.StorageView();
const container = view.element.shadowRoot?.querySelector('.clear-storage-header') || null;
assertElement(container, HTMLDivElement);
assertShadowRoot(container.shadowRoot);
const customQuotaCheckbox = container.shadowRoot.querySelector('.quota-override-row span')
?.shadowRoot?.querySelector('[title="Simulate custom storage quota"]') ||
null;
assertElement(customQuotaCheckbox, HTMLInputElement);
customQuotaCheckbox.checked = true;
const errorDiv = container.shadowRoot.querySelector('.quota-override-error');
assertElement(errorDiv, HTMLDivElement);
assert.strictEqual(errorDiv.textContent, '');
const editor = container.shadowRoot.querySelector('.quota-override-notification-editor');
assertElement(editor, HTMLInputElement);
editor.value = '9999999999999';
dispatchFocusOutEvent(editor);
await coordinator.done();
assert.strictEqual(errorDiv.textContent, 'Number must be smaller than 9,000,000,000,000');
});
it('also clears cookies on clear', () => {
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
const cookieModel = target.model(SDK.CookieModel.CookieModel)!;
const clearByOriginSpy = sinon.spy(target.storageAgent(), 'invoke_clearDataForOrigin');
const cookieClearSpy = sinon.spy(cookieModel, 'clear');
Resources.StorageView.StorageView.clear(target, testKey, testOrigin, [Protocol.Storage.StorageType.All], false);
assert.isTrue(clearByOriginSpy.calledOnceWithExactly({origin: testOrigin, storageTypes: 'cookies'}));
assert.isTrue(cookieClearSpy.calledOnceWithExactly(undefined, testOrigin));
});
it('also clears WebSQL on clear', async () => {
const databaseModel = target.model(Resources.DatabaseModel.DatabaseModel);
assertNotNullOrUndefined(databaseModel);
const databaseRemoved = new Promise(resolve => {
databaseModel.addEventListener(Resources.DatabaseModel.Events.DatabasesRemoved, resolve);
});
const testDatabase = new Resources.DatabaseModel.Database(
databaseModel, 'test-id' as Protocol.Database.DatabaseId, 'test-domain', 'test-name', '1');
databaseModel.enable();
databaseModel.addDatabase(testDatabase);
assert.deepEqual(databaseModel.databases()[0], testDatabase);
Resources.StorageView.StorageView.clear(target, testKey, '', [Protocol.Storage.StorageType.All], false);
await databaseRemoved;
assert.isEmpty(databaseModel.databases());
});
it('clears e.g. WebSQL on clear site data', async () => {
const FRAME = {
id: 'main',
loaderId: 'test',
url: 'http://example.com',
securityOrigin: 'http://example.com',
mimeType: 'text/html',
};
const databaseModel = target.model(Resources.DatabaseModel.DatabaseModel);
assertNotNullOrUndefined(databaseModel);
const databaseRemoved = databaseModel.once(Resources.DatabaseModel.Events.DatabasesRemoved);
const testDatabase = new Resources.DatabaseModel.Database(
databaseModel, 'test-id' as Protocol.Database.DatabaseId, 'test-domain', 'test-name', '1');
databaseModel.enable();
databaseModel.addDatabase(testDatabase);
assert.deepEqual(databaseModel.databases()[0], testDatabase);
sinon.stub(target.storageAgent(), 'invoke_getStorageKeyForFrame')
.resolves({storageKey: testKey, getError: () => undefined});
dispatchEvent(target, 'Page.frameNavigated', {frame: FRAME});
const actionDelegate = Resources.StorageView.ActionDelegate.instance();
actionDelegate.handleAction(
UI.ActionRegistration.ActionCategory.RESOURCES as unknown as UI.Context.Context, 'resources.clear');
await databaseRemoved;
assert.isEmpty(databaseModel.databases());
});
it('clears cache on clear', async () => {
const cacheStorageModel = target.model(SDK.ServiceWorkerCacheModel.ServiceWorkerCacheModel);
assertNotNullOrUndefined(cacheStorageModel);
const storageBucketModel = target.model(SDK.StorageBucketsModel.StorageBucketsModel);
assertNotNullOrUndefined(storageBucketModel);
const testStorageBucket = {
storageKey: testKey,
name: 'inbox',
};
const testStorageBucketInfo = {
bucket: testStorageBucket,
id: '0',
expiration: 0,
quota: 0,
persistent: false,
durability: Protocol.Storage.StorageBucketsDurability.Strict,
};
let caches = [
{
cacheId: 'id1' as Protocol.CacheStorage.CacheId,
securityOrigin: '',
storageKey: testStorageBucket.storageKey,
storageBucket: testStorageBucket,
cacheName: 'test-cache-1',
},
{
cacheId: 'id2' as Protocol.CacheStorage.CacheId,
securityOrigin: '',
storageKey: testStorageBucket.storageKey,
storageBucket: testStorageBucket,
cacheName: 'test-cache-2',
},
];
sinon.stub(target.cacheStorageAgent(), 'invoke_requestCacheNames').resolves({caches, getError: () => undefined});
cacheStorageModel.enable();
const cacheAddedPromise = new Promise<void>(resolve => {
cacheStorageModel.addEventListener(SDK.ServiceWorkerCacheModel.Events.CacheAdded, () => {
resolve();
});
});
storageBucketModel?.storageBucketCreatedOrUpdated({bucketInfo: testStorageBucketInfo});
await cacheAddedPromise;
caches = [];
Resources.StorageView.StorageView.clear(target, testKey, '', [Protocol.Storage.StorageType.Cache_storage], false);
assert.isEmpty(cacheStorageModel.caches());
});
};
describe('without tab target', () => tests(createTarget));
describe('with tab target', () => tests(() => {
const tabTarget = createTarget({type: SDK.Target.Type.Tab});
createTarget({parentTarget: tabTarget, subtype: 'prerender'});
return createTarget({parentTarget: tabTarget});
}));
});