chrome-devtools-frontend 1.0.962581 → 1.0.964938
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +1 -0
- package/config/gni/devtools_grd_files.gni +6 -0
- package/docs/resource_management.md +119 -0
- package/docs/workflows.md +7 -0
- package/front_end/core/common/ParsedURL.ts +12 -10
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/i18n/locales/en-US.json +23 -2
- package/front_end/core/i18n/locales/en-XL.json +23 -2
- package/front_end/core/root/Runtime.ts +2 -0
- package/front_end/core/sdk/DOMModel.ts +2 -2
- package/front_end/core/sdk/DebuggerModel.ts +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +7 -2
- package/front_end/generated/InspectorBackendCommands.js +8 -4
- package/front_end/generated/protocol-mapping.d.ts +12 -1
- package/front_end/generated/protocol-proxy-api.d.ts +11 -1
- package/front_end/generated/protocol.ts +27 -12
- package/front_end/models/javascript_metadata/NativeFunctions.js +7480 -4147
- package/front_end/models/persistence/IsolatedFileSystem.ts +3 -2
- package/front_end/models/persistence/PersistenceActions.ts +2 -2
- package/front_end/models/workspace/UISourceCode.ts +4 -5
- package/front_end/panels/animation/AnimationUI.ts +2 -1
- package/front_end/panels/application/AppManifestView.ts +7 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +41 -1
- package/front_end/panels/application/InterestGroupStorageModel.ts +87 -0
- package/front_end/panels/application/InterestGroupStorageView.ts +112 -0
- package/front_end/panels/application/InterestGroupTreeElement.ts +61 -0
- package/front_end/panels/application/application.ts +4 -0
- package/front_end/panels/application/components/BackForwardCacheStrings.ts +1 -1
- package/front_end/panels/application/components/FrameDetailsView.ts +1 -0
- package/front_end/panels/application/components/InterestGroupAccessGrid.ts +149 -0
- package/front_end/panels/application/components/components.ts +2 -0
- package/front_end/panels/application/components/interestGroupAccessGrid.css +26 -0
- package/front_end/panels/application/interestGroupStorageView.css +13 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +13 -0
- package/front_end/panels/elements/StylesSidebarPane.ts +73 -4
- package/front_end/panels/elements/stylesSectionTree.css +28 -0
- package/front_end/panels/media/PlayerListView.ts +2 -0
- package/front_end/panels/media/playerListView.css +3 -0
- package/front_end/panels/sensors/sensors-meta.ts +2 -2
- package/front_end/panels/sources/NavigatorView.ts +1 -1
- package/front_end/panels/sources/UISourceCodeFrame.ts +7 -0
- package/front_end/ui/components/diff_view/DiffView.ts +2 -2
- package/front_end/ui/components/docs/icon_button/basic.ts +1 -1
- package/front_end/ui/components/icon_button/IconButton.ts +1 -1
- package/front_end/ui/legacy/GlassPane.ts +2 -0
- package/front_end/ui/legacy/components/inline_editor/cssLength.css +1 -0
- package/front_end/ui/legacy/softDropDownButton.css +2 -0
- package/front_end/ui/legacy/themeColors.css +3 -1
- package/front_end/ui/legacy/toolbar.css +6 -0
- package/package.json +1 -1
- package/scripts/build/devtools_plugin.js +103 -0
- package/scripts/build/ninja/{rollup.gni → bundle.gni} +2 -2
- package/scripts/build/ninja/devtools_entrypoint.gni +8 -8
- package/scripts/build/rollup.config.js +3 -93
- package/scripts/devtools_paths.js +3 -2
- package/scripts/javascript_natives/helpers.js +211 -0
- package/scripts/javascript_natives/index.js +57 -194
- package/scripts/javascript_natives/package.json +8 -3
- package/scripts/javascript_natives/test.d.ts +9 -0
- package/scripts/javascript_natives/tests.js +195 -0
- package/scripts/whitespaces.txt +1 -0
@@ -176,7 +176,7 @@ export class IsolatedFileSystem extends PlatformFileSystem {
|
|
176
176
|
this.initialGitFoldersInternal.add(parentFolder);
|
177
177
|
}
|
178
178
|
if (this.isFileExcluded(entry.fullPath + '/')) {
|
179
|
-
this.excludedEmbedderFolders.push(Common.ParsedURL.ParsedURL.
|
179
|
+
this.excludedEmbedderFolders.push(Common.ParsedURL.ParsedURL.urlToRawPathString(
|
180
180
|
this.path() + entry.fullPath as Platform.DevToolsPath.UrlString, Host.Platform.isWin()));
|
181
181
|
continue;
|
182
182
|
}
|
@@ -555,7 +555,8 @@ export class IsolatedFileSystem extends PlatformFileSystem {
|
|
555
555
|
|
556
556
|
tooltipForURL(url: string): string {
|
557
557
|
const path = Platform.StringUtilities.trimMiddle(
|
558
|
-
Common.ParsedURL.ParsedURL.
|
558
|
+
Common.ParsedURL.ParsedURL.urlToRawPathString(url as Platform.DevToolsPath.UrlString, Host.Platform.isWin()),
|
559
|
+
150);
|
559
560
|
return i18nString(UIStrings.linkedToS, {PH1: path});
|
560
561
|
}
|
561
562
|
|
@@ -94,8 +94,8 @@ export class ContextMenuProvider implements UI.ContextMenu.Provider {
|
|
94
94
|
const fileURL = binding ? binding.fileSystem.contentURL() : contentProvider.contentURL();
|
95
95
|
if (fileURL.startsWith('file://')) {
|
96
96
|
// TODO(crbug.com/1253323): Cast to UrlString will be removed when migration to branded types is complete.
|
97
|
-
const path =
|
98
|
-
|
97
|
+
const path = Common.ParsedURL.ParsedURL.urlToRawPathString(
|
98
|
+
fileURL as Platform.DevToolsPath.UrlString, Host.Platform.isWin());
|
99
99
|
contextMenu.revealSection().appendItem(
|
100
100
|
i18nString(UIStrings.openInContainingFolder),
|
101
101
|
() => Host.InspectorFrontendHost.InspectorFrontendHostInstance.showItemInFolder(path));
|
@@ -263,8 +263,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
263
263
|
return;
|
264
264
|
}
|
265
265
|
|
266
|
-
if (this.contentInternal
|
267
|
-
this.contentInternal.content === updatedContent.content) {
|
266
|
+
if (this.contentInternal?.content === updatedContent.content) {
|
268
267
|
this.lastAcceptedContent = null;
|
269
268
|
return;
|
270
269
|
}
|
@@ -331,7 +330,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
331
330
|
if (this.isDirty()) {
|
332
331
|
return this.workingCopyInternal as string;
|
333
332
|
}
|
334
|
-
return
|
333
|
+
return this.contentInternal?.content || '';
|
335
334
|
}
|
336
335
|
|
337
336
|
resetWorkingCopy(): void {
|
@@ -393,7 +392,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
393
392
|
}
|
394
393
|
|
395
394
|
content(): string {
|
396
|
-
return
|
395
|
+
return this.contentInternal?.content || '';
|
397
396
|
}
|
398
397
|
|
399
398
|
loadError(): string|null {
|
@@ -439,7 +438,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
439
438
|
}
|
440
439
|
|
441
440
|
removeMessage(message: Message): void {
|
442
|
-
if (this.messagesInternal
|
441
|
+
if (this.messagesInternal?.delete(message)) {
|
443
442
|
this.dispatchEventToListeners(Events.MessageRemoved, message);
|
444
443
|
}
|
445
444
|
}
|
@@ -279,7 +279,8 @@ export class AnimationUI {
|
|
279
279
|
const iterationWidth = this.duration() * this.#timeline.pixelMsRatio();
|
280
280
|
let iteration;
|
281
281
|
for (iteration = 1; iteration < this.#animationInternal.source().iterations() &&
|
282
|
-
iterationWidth * (iteration - 1) < this.#timeline.width()
|
282
|
+
iterationWidth * (iteration - 1) < this.#timeline.width() &&
|
283
|
+
(iterationWidth > 0 || this.#animationInternal.source().iterations() !== Infinity);
|
283
284
|
iteration++) {
|
284
285
|
this.renderIteration(this.#tailGroup, iteration);
|
285
286
|
}
|
@@ -617,7 +617,13 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
617
617
|
const copyButton = new IconButton.IconButton.IconButton();
|
618
618
|
copyButton.title = i18nString(UIStrings.copyToClipboard);
|
619
619
|
copyButton.data = {
|
620
|
-
groups: [{
|
620
|
+
groups: [{
|
621
|
+
iconName: 'copy_icon',
|
622
|
+
iconHeight: '12px',
|
623
|
+
iconWidth: '12px',
|
624
|
+
text: '',
|
625
|
+
iconColor: 'var(--color-text-primary)',
|
626
|
+
}],
|
621
627
|
clickHandler: (): void => {
|
622
628
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(recommendedId);
|
623
629
|
},
|
@@ -59,6 +59,8 @@ import {DOMStorageModel, Events as DOMStorageModelEvents} from './DOMStorageMode
|
|
59
59
|
import type {Database as IndexedDBModelDatabase, DatabaseId, Index, ObjectStore} from './IndexedDBModel.js';
|
60
60
|
import {Events as IndexedDBModelEvents, IndexedDBModel} from './IndexedDBModel.js';
|
61
61
|
import {IDBDatabaseView, IDBDataView} from './IndexedDBViews.js';
|
62
|
+
import {InterestGroupStorageModel, Events as InterestGroupModelEvents} from './InterestGroupStorageModel.js';
|
63
|
+
import {InterestGroupTreeElement} from './InterestGroupTreeElement.js';
|
62
64
|
import {OpenedWindowDetailsView, WorkerDetailsView} from './OpenedWindowDetailsView.js';
|
63
65
|
import type {ResourcesPanel} from './ResourcesPanel.js';
|
64
66
|
import {ServiceWorkersView} from './ServiceWorkersView.js';
|
@@ -186,6 +188,7 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
186
188
|
localStorageListTreeElement: ExpandableApplicationPanelTreeElement;
|
187
189
|
sessionStorageListTreeElement: ExpandableApplicationPanelTreeElement;
|
188
190
|
indexedDBListTreeElement: IndexedDBTreeElement;
|
191
|
+
interestGroupTreeElement: InterestGroupTreeElement;
|
189
192
|
databasesListTreeElement: ExpandableApplicationPanelTreeElement;
|
190
193
|
cookieListTreeElement: ExpandableApplicationPanelTreeElement;
|
191
194
|
trustTokensTreeElement: TrustTokensTreeElement;
|
@@ -276,6 +279,9 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
276
279
|
this.trustTokensTreeElement = new TrustTokensTreeElement(panel);
|
277
280
|
storageTreeElement.appendChild(this.trustTokensTreeElement);
|
278
281
|
|
282
|
+
this.interestGroupTreeElement = new InterestGroupTreeElement(panel);
|
283
|
+
storageTreeElement.appendChild(this.interestGroupTreeElement);
|
284
|
+
|
279
285
|
const cacheSectionTitle = i18nString(UIStrings.cache);
|
280
286
|
const cacheTreeElement = this.addSidebarSection(cacheSectionTitle);
|
281
287
|
this.cacheStorageListTreeElement = new ServiceWorkerCacheTreeElement(panel);
|
@@ -349,7 +355,10 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
349
355
|
modelAdded: (model: IndexedDBModel): void => model.enable(),
|
350
356
|
modelRemoved: (model: IndexedDBModel): void => this.indexedDBListTreeElement.removeIndexedDBForModel(model),
|
351
357
|
});
|
352
|
-
|
358
|
+
SDK.TargetManager.TargetManager.instance().observeModels(InterestGroupStorageModel, {
|
359
|
+
modelAdded: (model: InterestGroupStorageModel): void => this.interestGroupModelAdded(model),
|
360
|
+
modelRemoved: (model: InterestGroupStorageModel): void => this.interestGroupModelRemoved(model),
|
361
|
+
});
|
353
362
|
// Work-around for crbug.com/1152713: Something is wrong with custom scrollbars and size containment.
|
354
363
|
// @ts-ignore
|
355
364
|
this.contentElement.style.contain = 'layout style';
|
@@ -376,6 +385,11 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
376
385
|
this.databaseModel.addEventListener(DatabaseModelEvents.DatabasesRemoved, this.resetWebSQL, this);
|
377
386
|
}
|
378
387
|
|
388
|
+
const interestGroupModel = target.model(InterestGroupStorageModel);
|
389
|
+
if (interestGroupModel) {
|
390
|
+
interestGroupModel.addEventListener(InterestGroupModelEvents.InterestGroupAccess, this.interestGroupAccess, this);
|
391
|
+
}
|
392
|
+
|
379
393
|
const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
|
380
394
|
if (!resourceTreeModel) {
|
381
395
|
return;
|
@@ -408,6 +422,12 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
408
422
|
this.databaseModel = null;
|
409
423
|
}
|
410
424
|
|
425
|
+
const interestGroupModel = target.model(InterestGroupStorageModel);
|
426
|
+
if (interestGroupModel) {
|
427
|
+
interestGroupModel.removeEventListener(
|
428
|
+
InterestGroupModelEvents.InterestGroupAccess, this.interestGroupAccess, this);
|
429
|
+
}
|
430
|
+
|
411
431
|
this.resetWithFrames();
|
412
432
|
}
|
413
433
|
|
@@ -422,6 +442,10 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
422
442
|
if (this.databaseModel) {
|
423
443
|
this.databaseModel.enable();
|
424
444
|
}
|
445
|
+
const interestGroupModel = this.target && this.target.model(InterestGroupStorageModel);
|
446
|
+
if (interestGroupModel) {
|
447
|
+
interestGroupModel.enable();
|
448
|
+
}
|
425
449
|
|
426
450
|
const cacheStorageModel = this.target && this.target.model(SDK.ServiceWorkerCacheModel.ServiceWorkerCacheModel);
|
427
451
|
if (cacheStorageModel) {
|
@@ -461,6 +485,16 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
461
485
|
model.removeEventListener(DOMStorageModelEvents.DOMStorageRemoved, this.domStorageRemoved, this);
|
462
486
|
}
|
463
487
|
|
488
|
+
private interestGroupModelAdded(model: InterestGroupStorageModel): void {
|
489
|
+
model.enable();
|
490
|
+
model.addEventListener(InterestGroupModelEvents.InterestGroupAccess, this.interestGroupAccess, this);
|
491
|
+
}
|
492
|
+
|
493
|
+
private interestGroupModelRemoved(model: InterestGroupStorageModel): void {
|
494
|
+
model.disable();
|
495
|
+
model.removeEventListener(InterestGroupModelEvents.InterestGroupAccess, this.interestGroupAccess, this);
|
496
|
+
}
|
497
|
+
|
464
498
|
private resetWithFrames(): void {
|
465
499
|
this.resourcesSection.reset();
|
466
500
|
this.reset();
|
@@ -516,6 +550,7 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
516
550
|
this.domains = {};
|
517
551
|
this.resetWebSQL();
|
518
552
|
this.cookieListTreeElement.removeChildren();
|
553
|
+
this.interestGroupTreeElement.clearEvents();
|
519
554
|
}
|
520
555
|
|
521
556
|
private frameNavigated(event: Common.EventTarget.EventTargetEvent<SDK.ResourceTreeModel.ResourceTreeFrame>): void {
|
@@ -533,6 +568,11 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
533
568
|
this.databasesListTreeElement.appendChild(databaseTreeElement);
|
534
569
|
}
|
535
570
|
|
571
|
+
private interestGroupAccess(event: Common.EventTarget.EventTargetEvent<Protocol.Storage.InterestGroupAccessedEvent>):
|
572
|
+
void {
|
573
|
+
this.interestGroupTreeElement.addEvent(event.data);
|
574
|
+
}
|
575
|
+
|
536
576
|
private addCookieDocument(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {
|
537
577
|
// In case the current frame was unreachable, show it's cookies
|
538
578
|
// instead of the error interstitials because they might help to
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2021 Google Inc. All rights reserved.
|
3
|
+
*
|
4
|
+
* Redistribution and use in source and binary forms, with or without
|
5
|
+
* modification, are permitted provided that the following conditions are
|
6
|
+
* met:
|
7
|
+
*
|
8
|
+
* * Redistributions of source code must retain the above copyright
|
9
|
+
* notice, this list of conditions and the following disclaimer.
|
10
|
+
* * Redistributions in binary form must reproduce the above
|
11
|
+
* copyright notice, this list of conditions and the following disclaimer
|
12
|
+
* in the documentation and/or other materials provided with the
|
13
|
+
* distribution.
|
14
|
+
* * Neither the name of Google Inc. nor the names of its
|
15
|
+
* contributors may be used to endorse or promote products derived from
|
16
|
+
* this software without specific prior written permission.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
19
|
+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
20
|
+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
21
|
+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
22
|
+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
24
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
26
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*/
|
30
|
+
|
31
|
+
import * as SDK from '../../core/sdk/sdk.js';
|
32
|
+
import type * as Protocol from '../../generated/protocol.js';
|
33
|
+
import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
|
34
|
+
|
35
|
+
export class InterestGroupStorageModel extends SDK.SDKModel.SDKModel<EventTypes> implements
|
36
|
+
ProtocolProxyApi.StorageDispatcher {
|
37
|
+
private readonly storageAgent: ProtocolProxyApi.StorageApi;
|
38
|
+
private enabled?: boolean;
|
39
|
+
|
40
|
+
constructor(target: SDK.Target.Target) {
|
41
|
+
super(target);
|
42
|
+
target.registerStorageDispatcher(this);
|
43
|
+
this.storageAgent = target.storageAgent();
|
44
|
+
this.enabled = false;
|
45
|
+
}
|
46
|
+
|
47
|
+
enable(): void {
|
48
|
+
if (this.enabled) {
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
void this.storageAgent.invoke_setInterestGroupTracking({enable: true});
|
52
|
+
}
|
53
|
+
|
54
|
+
disable(): void {
|
55
|
+
if (!this.enabled) {
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
void this.storageAgent.invoke_setInterestGroupTracking({enable: false});
|
59
|
+
}
|
60
|
+
|
61
|
+
interestGroupAccessed(event: Protocol.Storage.InterestGroupAccessedEvent): void {
|
62
|
+
this.dispatchEventToListeners(Events.InterestGroupAccess, event);
|
63
|
+
}
|
64
|
+
|
65
|
+
indexedDBListUpdated(_event: Protocol.Storage.IndexedDBListUpdatedEvent): void {
|
66
|
+
}
|
67
|
+
|
68
|
+
indexedDBContentUpdated(_event: Protocol.Storage.IndexedDBContentUpdatedEvent): void {
|
69
|
+
}
|
70
|
+
|
71
|
+
cacheStorageListUpdated(_event: Protocol.Storage.CacheStorageListUpdatedEvent): void {
|
72
|
+
}
|
73
|
+
|
74
|
+
cacheStorageContentUpdated(_event: Protocol.Storage.CacheStorageContentUpdatedEvent): void {
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
SDK.SDKModel.SDKModel.register(
|
79
|
+
InterestGroupStorageModel, {capabilities: SDK.Target.Capability.Storage, autostart: false});
|
80
|
+
|
81
|
+
export const enum Events {
|
82
|
+
InterestGroupAccess = 'InterestGroupAccess',
|
83
|
+
}
|
84
|
+
|
85
|
+
export type EventTypes = {
|
86
|
+
[Events.InterestGroupAccess]: Protocol.Storage.InterestGroupAccessedEvent,
|
87
|
+
};
|
@@ -0,0 +1,112 @@
|
|
1
|
+
// Copyright 2021 The Chromium Authors. All rights reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
3
|
+
// found in the LICENSE file.
|
4
|
+
|
5
|
+
import * as i18n from '../../core/i18n/i18n.js';
|
6
|
+
import * as UI from '../../ui/legacy/legacy.js';
|
7
|
+
import type * as DataGrid from '../../ui/components/data_grid/data_grid.js';
|
8
|
+
import type * as Protocol from '../../generated/protocol.js';
|
9
|
+
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
10
|
+
import * as ApplicationComponents from './components/components.js';
|
11
|
+
|
12
|
+
import interestGroupStorageViewStyles from './interestGroupStorageView.css.js';
|
13
|
+
|
14
|
+
const UIStrings = {
|
15
|
+
/**
|
16
|
+
*@description Placeholder text instructing the user how to display interest group
|
17
|
+
*details.
|
18
|
+
*/
|
19
|
+
clickToDisplayBody: 'Click on any interest group event to display the group\'s current state',
|
20
|
+
/**
|
21
|
+
interestGroupStorageItems: 'InterestGroup Storage Items',
|
22
|
+
*/
|
23
|
+
};
|
24
|
+
const str_ = i18n.i18n.registerUIStrings('panels/application/InterestGroupStorageView.ts', UIStrings);
|
25
|
+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
26
|
+
|
27
|
+
interface InterestGroupDetailsGetter {
|
28
|
+
getInterestGroupDetails: (owner: string, name: string) => Promise<Protocol.Storage.InterestGroupDetails|null>;
|
29
|
+
}
|
30
|
+
|
31
|
+
function eventEquals(
|
32
|
+
a: Protocol.Storage.InterestGroupAccessedEvent, b: Protocol.Storage.InterestGroupAccessedEvent): boolean {
|
33
|
+
return (a.accessTime === b.accessTime && a.type === b.type && a.ownerOrigin === b.ownerOrigin && a.name === b.name);
|
34
|
+
}
|
35
|
+
|
36
|
+
export class InterestGroupStorageView extends UI.SplitWidget.SplitWidget {
|
37
|
+
private readonly interestGroupGrid = new ApplicationComponents.InterestGroupAccessGrid.InterestGroupAccessGrid();
|
38
|
+
private events: Protocol.Storage.InterestGroupAccessedEvent[] = [];
|
39
|
+
private detailsGetter: InterestGroupDetailsGetter;
|
40
|
+
|
41
|
+
constructor(detailsGetter: InterestGroupDetailsGetter) {
|
42
|
+
super(/* isVertical */ false, /* secondIsSidebar: */ true);
|
43
|
+
this.detailsGetter = detailsGetter;
|
44
|
+
|
45
|
+
const topPanel = new UI.Widget.VBox();
|
46
|
+
const bottomPanel = new UI.Widget.VBox();
|
47
|
+
topPanel.setMinimumSize(0, 80);
|
48
|
+
this.setMainWidget(topPanel);
|
49
|
+
bottomPanel.setMinimumSize(0, 40);
|
50
|
+
this.setSidebarWidget(bottomPanel);
|
51
|
+
|
52
|
+
topPanel.contentElement.appendChild(this.interestGroupGrid);
|
53
|
+
this.interestGroupGrid.addEventListener('cellfocused', this.onFocus.bind(this));
|
54
|
+
|
55
|
+
bottomPanel.contentElement.classList.add('placeholder');
|
56
|
+
const centered = bottomPanel.contentElement.createChild('div');
|
57
|
+
centered.textContent = i18nString(UIStrings.clickToDisplayBody);
|
58
|
+
}
|
59
|
+
|
60
|
+
wasShown(): void {
|
61
|
+
super.wasShown();
|
62
|
+
const sbw = this.sidebarWidget();
|
63
|
+
if (sbw) {
|
64
|
+
sbw.registerCSSFiles([interestGroupStorageViewStyles]);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
addEvent(event: Protocol.Storage.InterestGroupAccessedEvent): void {
|
69
|
+
// Only add if not already present.
|
70
|
+
const foundEvent = this.events.find(t => eventEquals(t, event));
|
71
|
+
if (!foundEvent) {
|
72
|
+
this.events.push(event);
|
73
|
+
this.interestGroupGrid.data = this.events;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
clearEvents(): void {
|
78
|
+
this.events = [];
|
79
|
+
this.interestGroupGrid.data = this.events;
|
80
|
+
}
|
81
|
+
|
82
|
+
private async onFocus(event: Event): Promise<void> {
|
83
|
+
const focusedEvent = event as DataGrid.DataGridEvents.BodyCellFocusedEvent;
|
84
|
+
const row = focusedEvent.data.row;
|
85
|
+
if (!row) {
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
const ownerOrigin = row.cells.find(cell => cell.columnId === 'event-group-owner')?.value as string;
|
90
|
+
const name = row.cells.find(cell => cell.columnId === 'event-group-name')?.value as string;
|
91
|
+
if (!ownerOrigin || !name) {
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
|
95
|
+
const details = await this.detailsGetter.getInterestGroupDetails(ownerOrigin, name);
|
96
|
+
if (details) {
|
97
|
+
const jsonView = await SourceFrame.JSONView.JSONView.createView(JSON.stringify(details));
|
98
|
+
jsonView?.setMinimumSize(0, 40);
|
99
|
+
if (jsonView) {
|
100
|
+
this.setSidebarWidget(jsonView);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
getEventsForTesting(): Array<Protocol.Storage.InterestGroupAccessedEvent> {
|
106
|
+
return this.events;
|
107
|
+
}
|
108
|
+
|
109
|
+
getInterestGroupGridForTesting(): ApplicationComponents.InterestGroupAccessGrid.InterestGroupAccessGrid {
|
110
|
+
return this.interestGroupGrid;
|
111
|
+
}
|
112
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
// Copyright 2022 The Chromium Authors. All rights reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
3
|
+
// found in the LICENSE file.
|
4
|
+
|
5
|
+
import * as i18n from '../../core/i18n/i18n.js';
|
6
|
+
import * as SDK from '../../core/sdk/sdk.js';
|
7
|
+
import * as UI from '../../ui/legacy/legacy.js';
|
8
|
+
|
9
|
+
import type * as Protocol from '../../generated/protocol.js';
|
10
|
+
|
11
|
+
import {ApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js';
|
12
|
+
import type {ResourcesPanel} from './ResourcesPanel.js';
|
13
|
+
import {InterestGroupStorageView} from './InterestGroupStorageView.js';
|
14
|
+
|
15
|
+
const UIStrings = {
|
16
|
+
/**
|
17
|
+
*@description Label for an item in the Application Panel Sidebar of the Application panel
|
18
|
+
*/
|
19
|
+
interestGroups: 'Interest Groups',
|
20
|
+
};
|
21
|
+
const str_ = i18n.i18n.registerUIStrings('panels/application/InterestGroupTreeElement.ts', UIStrings);
|
22
|
+
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
23
|
+
|
24
|
+
export class InterestGroupTreeElement extends ApplicationPanelTreeElement {
|
25
|
+
private view: InterestGroupStorageView;
|
26
|
+
|
27
|
+
constructor(storagePanel: ResourcesPanel) {
|
28
|
+
super(storagePanel, i18nString(UIStrings.interestGroups), false);
|
29
|
+
const interestGroupIcon = UI.Icon.Icon.create('mediumicon-database', 'resource-tree-item');
|
30
|
+
this.setLeadingIcons([interestGroupIcon]);
|
31
|
+
this.view = new InterestGroupStorageView(this);
|
32
|
+
}
|
33
|
+
|
34
|
+
get itemURL(): string {
|
35
|
+
return 'interest-groups://';
|
36
|
+
}
|
37
|
+
|
38
|
+
async getInterestGroupDetails(owner: string, name: string): Promise<Protocol.Storage.InterestGroupDetails|null> {
|
39
|
+
const mainTarget = SDK.TargetManager.TargetManager.instance().mainTarget();
|
40
|
+
if (!mainTarget) {
|
41
|
+
return null;
|
42
|
+
}
|
43
|
+
const response =
|
44
|
+
await mainTarget.storageAgent().invoke_getInterestGroupDetails({'ownerOrigin': owner, 'name': name});
|
45
|
+
return response.details;
|
46
|
+
}
|
47
|
+
|
48
|
+
onselect(selectedByUser?: boolean): boolean {
|
49
|
+
super.onselect(selectedByUser);
|
50
|
+
this.showView(this.view);
|
51
|
+
return false;
|
52
|
+
}
|
53
|
+
|
54
|
+
addEvent(event: Protocol.Storage.InterestGroupAccessedEvent): void {
|
55
|
+
this.view.addEvent(event);
|
56
|
+
}
|
57
|
+
|
58
|
+
clearEvents(): void {
|
59
|
+
this.view.clearEvents();
|
60
|
+
}
|
61
|
+
}
|
@@ -14,6 +14,8 @@ import * as DOMStorageItemsView from './DOMStorageItemsView.js';
|
|
14
14
|
import * as DOMStorageModel from './DOMStorageModel.js';
|
15
15
|
import * as IndexedDBModel from './IndexedDBModel.js';
|
16
16
|
import * as IndexedDBViews from './IndexedDBViews.js';
|
17
|
+
import * as InterestGroupStorageModel from './InterestGroupStorageModel.js';
|
18
|
+
import * as InterestGroupStorageView from './InterestGroupStorageView.js';
|
17
19
|
import * as OpenedWindowDetailsView from './OpenedWindowDetailsView.js';
|
18
20
|
import * as ReportingApiReportsView from './ReportingApiReportsView.js';
|
19
21
|
import * as ResourcesPanel from './ResourcesPanel.js';
|
@@ -36,6 +38,8 @@ export {
|
|
36
38
|
DOMStorageModel,
|
37
39
|
IndexedDBModel,
|
38
40
|
IndexedDBViews,
|
41
|
+
InterestGroupStorageModel,
|
42
|
+
InterestGroupStorageView,
|
39
43
|
OpenedWindowDetailsView,
|
40
44
|
ReportingApiReportsView,
|
41
45
|
ResourcesPanel,
|
@@ -508,7 +508,7 @@ const str_ = i18n.i18n.registerUIStrings('panels/application/components/BackForw
|
|
508
508
|
const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
|
509
509
|
|
510
510
|
export const NotRestoredReasonDescription = {
|
511
|
-
'
|
511
|
+
'NotPrimaryMainFrame': {name: i18nLazyString(UIStrings.notMainFrame)},
|
512
512
|
'BackForwardCacheDisabled': {name: i18nLazyString(UIStrings.backForwardCacheDisabled)},
|
513
513
|
'RelatedActiveContentsExist': {name: i18nLazyString(UIStrings.relatedActiveContentsExist)},
|
514
514
|
'HTTPStatusNotOK': {name: i18nLazyString(UIStrings.HTTPStatusNotOK)},
|
@@ -342,6 +342,7 @@ export class FrameDetailsReportView extends HTMLElement {
|
|
342
342
|
{
|
343
343
|
iconName: 'refresh_12x12_icon',
|
344
344
|
text: i18nString(UIStrings.refresh),
|
345
|
+
iconColor: 'var(--color-text-primary)',
|
345
346
|
} as IconButton.IconButton.IconWithTextData,
|
346
347
|
],
|
347
348
|
} as IconButton.IconButton.IconButtonData}>
|
@@ -0,0 +1,149 @@
|
|
1
|
+
// Copyright 2022 The Chromium Authors. All rights reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
3
|
+
// found in the LICENSE file.
|
4
|
+
|
5
|
+
import * as i18n from '../../../core/i18n/i18n.js';
|
6
|
+
import * as DataGrid from '../../../ui/components/data_grid/data_grid.js';
|
7
|
+
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
8
|
+
import * as IconButton from '../../../ui/components/icon_button/icon_button.js';
|
9
|
+
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
10
|
+
import type * as Protocol from '../../../generated/protocol.js';
|
11
|
+
|
12
|
+
import interestGroupAccessGridStyles from './interestGroupAccessGrid.css.js';
|
13
|
+
|
14
|
+
const UIStrings = {
|
15
|
+
/**
|
16
|
+
*@description Hover text for an info icon in the Interest Group Event panel
|
17
|
+
*/
|
18
|
+
allInterestGroupStorageEvents: 'All interest group storage events.',
|
19
|
+
/**
|
20
|
+
*@description Text in InterestGroupStorage Items View of the Application panel
|
21
|
+
*/
|
22
|
+
eventTime: 'Event Time',
|
23
|
+
/**
|
24
|
+
*@description Text in InterestGroupStorage Items View of the Application panel
|
25
|
+
*/
|
26
|
+
eventType: 'Access Type',
|
27
|
+
/**
|
28
|
+
*@description Text in InterestGroupStorage Items View of the Application panel
|
29
|
+
*/
|
30
|
+
groupOwner: 'Owner',
|
31
|
+
/**
|
32
|
+
*@description Text in InterestGroupStorage Items View of the Application panel
|
33
|
+
*/
|
34
|
+
groupName: 'Name',
|
35
|
+
};
|
36
|
+
const str_ = i18n.i18n.registerUIStrings('panels/application/components/InterestGroupAccessGrid.ts', UIStrings);
|
37
|
+
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
38
|
+
|
39
|
+
export class InterestGroupAccessGrid extends HTMLElement {
|
40
|
+
static readonly litTagName = LitHtml.literal`devtools-interest-group-access-grid`;
|
41
|
+
readonly #shadow = this.attachShadow({mode: 'open'});
|
42
|
+
#datastores: Array<Protocol.Storage.InterestGroupAccessedEvent> = [];
|
43
|
+
|
44
|
+
connectedCallback(): void {
|
45
|
+
this.#shadow.adoptedStyleSheets = [interestGroupAccessGridStyles];
|
46
|
+
this.#render();
|
47
|
+
}
|
48
|
+
|
49
|
+
set data(data: Array<Protocol.Storage.InterestGroupAccessedEvent>) {
|
50
|
+
this.#datastores = data;
|
51
|
+
this.#render();
|
52
|
+
}
|
53
|
+
|
54
|
+
#render(): void {
|
55
|
+
// clang-format off
|
56
|
+
LitHtml.render(LitHtml.html`
|
57
|
+
<div>
|
58
|
+
<span class="heading">Interest Groups</span>
|
59
|
+
<${IconButton.Icon.Icon.litTagName} class="info-icon" title=${
|
60
|
+
i18nString(UIStrings.allInterestGroupStorageEvents)}
|
61
|
+
.data=${
|
62
|
+
{iconName: 'ic_info_black_18dp', color: 'var(--color-link)', width: '14px'} as
|
63
|
+
IconButton.Icon.IconWithName}>
|
64
|
+
</${IconButton.Icon.Icon.litTagName}>
|
65
|
+
${this.#renderGrid()}
|
66
|
+
</div>
|
67
|
+
`, this.#shadow, {host: this});
|
68
|
+
// clang-format on
|
69
|
+
}
|
70
|
+
|
71
|
+
#renderGrid(): LitHtml.TemplateResult {
|
72
|
+
const gridData: DataGrid.DataGridController.DataGridControllerData = {
|
73
|
+
columns: [
|
74
|
+
{
|
75
|
+
id: 'event-time',
|
76
|
+
title: i18nString(UIStrings.eventTime),
|
77
|
+
widthWeighting: 10,
|
78
|
+
hideable: false,
|
79
|
+
visible: true,
|
80
|
+
sortable: true,
|
81
|
+
},
|
82
|
+
{
|
83
|
+
id: 'event-type',
|
84
|
+
title: i18nString(UIStrings.eventType),
|
85
|
+
widthWeighting: 5,
|
86
|
+
hideable: false,
|
87
|
+
visible: true,
|
88
|
+
sortable: true,
|
89
|
+
},
|
90
|
+
{
|
91
|
+
id: 'event-group-owner',
|
92
|
+
title: i18nString(UIStrings.groupOwner),
|
93
|
+
widthWeighting: 10,
|
94
|
+
hideable: false,
|
95
|
+
visible: true,
|
96
|
+
sortable: true,
|
97
|
+
},
|
98
|
+
{
|
99
|
+
id: 'event-group-name',
|
100
|
+
title: i18nString(UIStrings.groupName),
|
101
|
+
widthWeighting: 10,
|
102
|
+
hideable: false,
|
103
|
+
visible: true,
|
104
|
+
sortable: true,
|
105
|
+
},
|
106
|
+
],
|
107
|
+
rows: this.#buildRows(),
|
108
|
+
initialSort: {
|
109
|
+
columnId: 'event-time',
|
110
|
+
direction: DataGrid.DataGridUtils.SortDirection.ASC,
|
111
|
+
},
|
112
|
+
};
|
113
|
+
|
114
|
+
return LitHtml.html`
|
115
|
+
<${DataGrid.DataGridController.DataGridController.litTagName} .data=${
|
116
|
+
gridData as DataGrid.DataGridController.DataGridControllerData}></${
|
117
|
+
DataGrid.DataGridController.DataGridController.litTagName}>
|
118
|
+
`;
|
119
|
+
}
|
120
|
+
|
121
|
+
#buildRows(): DataGrid.DataGridUtils.Row[] {
|
122
|
+
return this.#datastores.map(event => ({
|
123
|
+
cells: [
|
124
|
+
{
|
125
|
+
columnId: 'event-time',
|
126
|
+
value: event.accessTime,
|
127
|
+
renderer: this.#renderDateForDataGridCell.bind(this),
|
128
|
+
},
|
129
|
+
{columnId: 'event-type', value: event.type},
|
130
|
+
{columnId: 'event-group-owner', value: event.ownerOrigin},
|
131
|
+
{columnId: 'event-group-name', value: event.name},
|
132
|
+
],
|
133
|
+
}));
|
134
|
+
}
|
135
|
+
|
136
|
+
#renderDateForDataGridCell(value: DataGrid.DataGridUtils.CellValue): LitHtml.TemplateResult {
|
137
|
+
const date = new Date(1e3 * (value as number));
|
138
|
+
return LitHtml.html`${date.toLocaleString()}`;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
ComponentHelpers.CustomElements.defineComponent('devtools-interest-group-access-grid', InterestGroupAccessGrid);
|
143
|
+
|
144
|
+
declare global {
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
146
|
+
interface HTMLElementTagNameMap {
|
147
|
+
'devtools-interest-group-access-grid': InterestGroupAccessGrid;
|
148
|
+
}
|
149
|
+
}
|
@@ -5,6 +5,7 @@
|
|
5
5
|
import * as BackForwardCacheView from './BackForwardCacheView.js';
|
6
6
|
import * as EndpointsGrid from './EndpointsGrid.js';
|
7
7
|
import * as FrameDetailsView from './FrameDetailsView.js';
|
8
|
+
import * as InterestGroupAccessGrid from './InterestGroupAccessGrid.js';
|
8
9
|
import * as OriginTrialTreeView from './OriginTrialTreeView.js';
|
9
10
|
import * as ReportsGrid from './ReportsGrid.js';
|
10
11
|
import * as StackTrace from './StackTrace.js';
|
@@ -14,6 +15,7 @@ export {
|
|
14
15
|
BackForwardCacheView,
|
15
16
|
EndpointsGrid,
|
16
17
|
FrameDetailsView,
|
18
|
+
InterestGroupAccessGrid,
|
17
19
|
OriginTrialTreeView,
|
18
20
|
ReportsGrid,
|
19
21
|
StackTrace,
|