chrome-devtools-frontend 1.0.1521880 → 1.0.1522145
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/front_end/core/host/GdpClient.ts +116 -66
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +82 -32
- package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +7 -1
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +10 -6
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +42 -4
- package/front_end/models/badges/UserBadges.ts +14 -16
- package/front_end/panels/ai_assistance/components/UserActionRow.ts +1 -2
- package/front_end/panels/application/IndexedDBViews.ts +1 -0
- package/front_end/panels/application/ReportingApiTreeElement.ts +1 -2
- package/front_end/panels/application/ReportingApiView.ts +18 -20
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +3 -0
- package/front_end/panels/application/components/EndpointsGrid.ts +51 -59
- package/front_end/panels/application/components/ReportsGrid.ts +86 -107
- package/front_end/panels/application/components/StorageMetadataView.ts +30 -4
- package/front_end/panels/application/components/endpointsGrid.css +30 -0
- package/front_end/panels/application/components/reportsGrid.css +34 -0
- package/front_end/panels/application/components/storageMetadataView.css +9 -0
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +19 -27
- package/front_end/panels/common/BadgeNotification.ts +10 -3
- package/front_end/panels/network/NetworkPanel.ts +1 -1
- package/front_end/panels/search/SearchResultsPane.ts +14 -13
- package/front_end/panels/search/SearchView.ts +3 -20
- package/front_end/panels/settings/components/SyncSection.ts +8 -6
- package/front_end/panels/sources/SearchSourcesView.ts +1 -1
- package/front_end/panels/whats_new/ReleaseNoteText.ts +15 -11
- package/front_end/panels/whats_new/resources/WNDT.md +9 -6
- package/front_end/third_party/diff/README.chromium +0 -1
- package/front_end/ui/legacy/Treeoutline.ts +6 -9
- package/front_end/ui/legacy/UIUtils.ts +4 -17
- package/front_end/ui/legacy/Widget.ts +0 -5
- package/front_end/ui/legacy/XElement.ts +0 -33
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +3 -3
- package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +38 -21
- package/front_end/ui/legacy/components/perf_ui/filmStripView.css +29 -0
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +3 -2
- package/front_end/ui/legacy/legacy.ts +0 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
- package/front_end/panels/application/components/reportingApiGrid.css +0 -31
- package/front_end/ui/legacy/XWidget.ts +0 -133
@@ -1,7 +1,6 @@
|
|
1
1
|
// Copyright 2024 The Chromium Authors
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
|
-
/* eslint-disable rulesdir/no-lit-render-outside-of-view */
|
5
4
|
|
6
5
|
import * as Common from '../../../core/common/common.js';
|
7
6
|
import * as Host from '../../../core/host/host.js';
|
@@ -273,7 +272,7 @@ export const DEFAULT_VIEW = (input: UserActionRowViewInput, output: ViewOutput,
|
|
273
272
|
</div>
|
274
273
|
</form>
|
275
274
|
` : Lit.nothing}
|
276
|
-
`, target
|
275
|
+
`, target);
|
277
276
|
// clang-format on
|
278
277
|
};
|
279
278
|
|
@@ -8,7 +8,6 @@ import type * as Platform from '../../core/platform/platform.js';
|
|
8
8
|
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
|
9
9
|
|
10
10
|
import {ApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js';
|
11
|
-
import * as ApplicationComponents from './components/components.js';
|
12
11
|
import {ReportingApiView} from './ReportingApiView.js';
|
13
12
|
import type {ResourcesPanel} from './ResourcesPanel.js';
|
14
13
|
|
@@ -37,7 +36,7 @@ export class ReportingApiTreeElement extends ApplicationPanelTreeElement {
|
|
37
36
|
override onselect(selectedByUser?: boolean): boolean {
|
38
37
|
super.onselect(selectedByUser);
|
39
38
|
if (!this.view) {
|
40
|
-
this.view = new ReportingApiView(
|
39
|
+
this.view = new ReportingApiView();
|
41
40
|
}
|
42
41
|
this.showView(this.view);
|
43
42
|
Host.userMetrics.panelShown('reporting-api');
|
@@ -50,11 +50,10 @@ const REPORTING_API_EXPLANATION_URL =
|
|
50
50
|
interface ViewInput {
|
51
51
|
hasReports: boolean;
|
52
52
|
hasEndpoints: boolean;
|
53
|
-
|
54
|
-
|
55
|
-
// TODO (crbug.com/407940381): port ReportsGrid to a UI Widget and instantiate it in the view
|
56
|
-
reportsGrid: ApplicationComponents.ReportsGrid.ReportsGrid;
|
53
|
+
endpoints: Map<string, Protocol.Network.ReportingApiEndpoint[]>;
|
54
|
+
reports: Protocol.Network.ReportingApiReport[];
|
57
55
|
focusedReport?: Protocol.Network.ReportingApiReport;
|
56
|
+
onReportSelected: (id: string) => void;
|
58
57
|
}
|
59
58
|
|
60
59
|
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
@@ -68,7 +67,9 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
68
67
|
${input.hasReports ? html`
|
69
68
|
<devtools-split-view slot="main" sidebar-position="second" sidebar-initial-size="150">
|
70
69
|
<div slot="main">
|
71
|
-
|
70
|
+
<devtools-widget .widgetConfig=${widgetConfig(ApplicationComponents.ReportsGrid.ReportsGrid, {
|
71
|
+
reports: input.reports, onReportSelected: input.onReportSelected,
|
72
|
+
})}></devtools-widget>
|
72
73
|
</div>
|
73
74
|
<div slot="sidebar" class="vbox" jslog=${VisualLogging.pane('preview').track({resize: true})}>
|
74
75
|
${input.focusedReport ? html`
|
@@ -85,11 +86,15 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
85
86
|
</devtools-split-view>
|
86
87
|
` : html`
|
87
88
|
<div slot="main">
|
88
|
-
|
89
|
+
<devtools-widget .widgetConfig=${widgetConfig(ApplicationComponents.ReportsGrid.ReportsGrid, {
|
90
|
+
reports: input.reports, onReportSelected: input.onReportSelected,
|
91
|
+
})}></devtools-widget>
|
89
92
|
</div>
|
90
93
|
`}
|
91
94
|
<div slot="sidebar">
|
92
|
-
|
95
|
+
<devtools-widget .widgetConfig=${widgetConfig(ApplicationComponents.EndpointsGrid.EndpointsGrid, {
|
96
|
+
endpoints: input.endpoints,
|
97
|
+
})}></devtools-widget>
|
93
98
|
</div>
|
94
99
|
</devtools-split-view>
|
95
100
|
`, target);
|
@@ -109,20 +114,16 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
109
114
|
|
110
115
|
export class ReportingApiView extends UI.Widget.VBox implements
|
111
116
|
SDK.TargetManager.SDKModelObserver<SDK.NetworkManager.NetworkManager> {
|
112
|
-
readonly #endpointsGrid: ApplicationComponents.EndpointsGrid.EndpointsGrid;
|
113
117
|
#endpoints: Map<string, Protocol.Network.ReportingApiEndpoint[]>;
|
114
118
|
#view: View;
|
115
119
|
#networkManager?: SDK.NetworkManager.NetworkManager;
|
116
|
-
#reportsGrid = new ApplicationComponents.ReportsGrid.ReportsGrid();
|
117
120
|
#reports: Protocol.Network.ReportingApiReport[] = [];
|
118
121
|
#focusedReport?: Protocol.Network.ReportingApiReport;
|
119
122
|
|
120
|
-
constructor(
|
123
|
+
constructor(view = DEFAULT_VIEW) {
|
121
124
|
super();
|
122
125
|
this.#view = view;
|
123
|
-
this.#endpointsGrid = endpointsGrid;
|
124
126
|
this.#endpoints = new Map();
|
125
|
-
this.#reportsGrid.addEventListener('select', this.#onFocus.bind(this));
|
126
127
|
SDK.TargetManager.TargetManager.instance().observeModels(SDK.NetworkManager.NetworkManager, this);
|
127
128
|
this.requestUpdate();
|
128
129
|
}
|
@@ -158,35 +159,32 @@ export class ReportingApiView extends UI.Widget.VBox implements
|
|
158
159
|
const viewInput = {
|
159
160
|
hasReports: this.#reports.length > 0,
|
160
161
|
hasEndpoints: this.#endpoints.size > 0,
|
161
|
-
|
162
|
-
|
162
|
+
endpoints: this.#endpoints,
|
163
|
+
reports: this.#reports,
|
163
164
|
focusedReport: this.#focusedReport,
|
165
|
+
onReportSelected: this.#onReportSelected.bind(this),
|
164
166
|
};
|
165
167
|
this.#view(viewInput, {}, this.element);
|
166
168
|
}
|
167
169
|
|
168
170
|
#onEndpointsChangedForOrigin({data}: {data: Protocol.Network.ReportingApiEndpointsChangedForOriginEvent}): void {
|
169
171
|
this.#endpoints.set(data.origin, data.endpoints);
|
170
|
-
this.#endpointsGrid.data = {endpoints: this.#endpoints};
|
171
172
|
this.requestUpdate();
|
172
173
|
}
|
173
174
|
|
174
175
|
#onReportAdded({data: report}: {data: Protocol.Network.ReportingApiReport}): void {
|
175
176
|
this.#reports.push(report);
|
176
|
-
this.#reportsGrid.data = {reports: this.#reports};
|
177
177
|
this.requestUpdate();
|
178
178
|
}
|
179
179
|
|
180
180
|
#onReportUpdated({data: report}: {data: Protocol.Network.ReportingApiReport}): void {
|
181
181
|
const index = this.#reports.findIndex(oldReport => oldReport.id === report.id);
|
182
182
|
this.#reports[index] = report;
|
183
|
-
this.#reportsGrid.data = {reports: this.#reports};
|
184
183
|
this.requestUpdate();
|
185
184
|
}
|
186
185
|
|
187
|
-
|
188
|
-
const
|
189
|
-
const report = this.#reports.find(report => report.id === selectEvent.detail);
|
186
|
+
#onReportSelected(id: string): void {
|
187
|
+
const report = this.#reports.find(report => report.id === id);
|
190
188
|
if (report) {
|
191
189
|
this.#focusedReport = report;
|
192
190
|
this.requestUpdate();
|
@@ -134,6 +134,9 @@ export class ServiceWorkerCacheView extends UI.View.SimpleView {
|
|
134
134
|
const bucketInfo = this.model.target()
|
135
135
|
.model(SDK.StorageBucketsModel.StorageBucketsModel)
|
136
136
|
?.getBucketByName(cache.storageBucket.storageKey, cache.storageBucket.name);
|
137
|
+
|
138
|
+
this.metadataView.setShowOnlyBucket(false);
|
139
|
+
|
137
140
|
if (bucketInfo) {
|
138
141
|
this.metadataView.setStorageBucket(bucketInfo);
|
139
142
|
} else if (cache.storageKey) {
|
@@ -1,7 +1,6 @@
|
|
1
1
|
// Copyright 2021 The Chromium Authors
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
|
-
/* eslint-disable rulesdir/no-lit-render-outside-of-view */
|
5
4
|
|
6
5
|
import '../../../ui/legacy/components/data_grid/data_grid.js';
|
7
6
|
|
@@ -11,7 +10,7 @@ import * as UI from '../../../ui/legacy/legacy.js';
|
|
11
10
|
import * as Lit from '../../../ui/lit/lit.js';
|
12
11
|
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
13
12
|
|
14
|
-
import
|
13
|
+
import endpointsGridStyles from './endpointsGrid.css.js';
|
15
14
|
|
16
15
|
const UIStrings = {
|
17
16
|
/**
|
@@ -23,76 +22,69 @@ const UIStrings = {
|
|
23
22
|
* @description Placeholder text when there are no Reporting API endpoints.
|
24
23
|
*(https://developers.google.com/web/updates/2018/09/reportingapi#tldr)
|
25
24
|
*/
|
26
|
-
endpointsDescription: 'Here you will find the list of endpoints that receive the reports'
|
25
|
+
endpointsDescription: 'Here you will find the list of endpoints that receive the reports',
|
27
26
|
} as const;
|
28
27
|
const str_ = i18n.i18n.registerUIStrings('panels/application/components/EndpointsGrid.ts', UIStrings);
|
29
28
|
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
30
29
|
|
31
30
|
const {render, html} = Lit;
|
32
31
|
|
33
|
-
export interface
|
32
|
+
export interface ViewInput {
|
34
33
|
endpoints: Map<string, Protocol.Network.ReportingApiEndpoint[]>;
|
35
34
|
}
|
36
35
|
|
37
|
-
export
|
36
|
+
export const DEFAULT_VIEW = (input: ViewInput, output: undefined, target: HTMLElement): void => {
|
37
|
+
// clang-format off
|
38
|
+
render(html`
|
39
|
+
<style>${endpointsGridStyles}</style>
|
40
|
+
<style>${UI.inspectorCommonStyles}</style>
|
41
|
+
<div class="endpoints-container" jslog=${VisualLogging.section('endpoints')}>
|
42
|
+
<div class="endpoints-header">${i18n.i18n.lockedString('Endpoints')}</div>
|
43
|
+
${input.endpoints.size > 0 ? html`
|
44
|
+
<devtools-data-grid striped>
|
45
|
+
<table>
|
46
|
+
<tr>
|
47
|
+
<th id="origin" weight="30">${i18n.i18n.lockedString('Origin')}</th>
|
48
|
+
<th id="name" weight="20">${i18n.i18n.lockedString('Name')}</th>
|
49
|
+
<th id="url" weight="30">${i18n.i18n.lockedString('URL')}</th>
|
50
|
+
</tr>
|
51
|
+
${Array.from(input.endpoints).map(([origin, endpointArray]) =>
|
52
|
+
endpointArray.map(endpoint => html`<tr>
|
53
|
+
<td>${origin}</td>
|
54
|
+
<td>${endpoint.groupName}</td>
|
55
|
+
<td>${endpoint.url}</td>
|
56
|
+
</tr>`))
|
57
|
+
.flat()}
|
58
|
+
</table>
|
59
|
+
</devtools-data-grid>
|
60
|
+
` : html`
|
61
|
+
<div class="empty-state">
|
62
|
+
<span class="empty-state-header">${i18nString(UIStrings.noEndpointsToDisplay)}</span>
|
63
|
+
<span class="empty-state-description">${i18nString(UIStrings.endpointsDescription)}</span>
|
64
|
+
</div>
|
65
|
+
`}
|
66
|
+
</div>
|
67
|
+
`, target);
|
68
|
+
// clang-format on
|
69
|
+
};
|
38
70
|
|
39
|
-
|
40
|
-
#endpoints = new Map<string, Protocol.Network.ReportingApiEndpoint[]>();
|
71
|
+
type View = typeof DEFAULT_VIEW;
|
41
72
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
set data(data: EndpointsGridData) {
|
47
|
-
this.#endpoints = data.endpoints;
|
48
|
-
this.#render();
|
49
|
-
}
|
73
|
+
export class EndpointsGrid extends UI.Widget.Widget {
|
74
|
+
endpoints = new Map<string, Protocol.Network.ReportingApiEndpoint[]>();
|
75
|
+
#view: View;
|
50
76
|
|
51
|
-
|
52
|
-
|
77
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
78
|
+
super(element);
|
79
|
+
this.#view = view;
|
80
|
+
this.requestUpdate();
|
53
81
|
}
|
54
82
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
<div class="reporting-container" jslog=${VisualLogging.section('endpoints')}>
|
62
|
-
<div class="reporting-header">${i18n.i18n.lockedString('Endpoints')}</div>
|
63
|
-
${this.#endpoints.size > 0 ? html`
|
64
|
-
<devtools-data-grid striped>
|
65
|
-
<table>
|
66
|
-
<tr>
|
67
|
-
<th id="origin" weight="30">${i18n.i18n.lockedString('Origin')}</th>
|
68
|
-
<th id="name" weight="20">${i18n.i18n.lockedString('Name')}</th>
|
69
|
-
<th id="url" weight="30">${i18n.i18n.lockedString('URL')}</th>
|
70
|
-
</tr>
|
71
|
-
${Array.from(this.#endpoints).map(([origin, endpointArray]) =>
|
72
|
-
endpointArray.map(endpoint => html`<tr>
|
73
|
-
<td>${origin}</td>
|
74
|
-
<td>${endpoint.groupName}</td>
|
75
|
-
<td>${endpoint.url}</td>
|
76
|
-
</tr>`))
|
77
|
-
.flat()}
|
78
|
-
</table>
|
79
|
-
</devtools-data-grid>
|
80
|
-
` : html`
|
81
|
-
<div class="empty-state">
|
82
|
-
<span class="empty-state-header">${i18nString(UIStrings.noEndpointsToDisplay)}</span>
|
83
|
-
<span class="empty-state-description">${i18nString(UIStrings.endpointsDescription)}</span>
|
84
|
-
</div>
|
85
|
-
`}
|
86
|
-
</div>
|
87
|
-
`, this.#shadow, {host: this});
|
88
|
-
// clang-format on
|
89
|
-
}
|
90
|
-
}
|
91
|
-
|
92
|
-
customElements.define('devtools-resources-endpoints-grid', EndpointsGrid);
|
93
|
-
|
94
|
-
declare global {
|
95
|
-
interface HTMLElementTagNameMap {
|
96
|
-
'devtools-resources-endpoints-grid': EndpointsGrid;
|
83
|
+
override performUpdate(): void {
|
84
|
+
this.#view(
|
85
|
+
{
|
86
|
+
endpoints: this.endpoints,
|
87
|
+
},
|
88
|
+
undefined, this.contentElement);
|
97
89
|
}
|
98
90
|
}
|
@@ -1,23 +1,17 @@
|
|
1
1
|
// Copyright 2021 The Chromium Authors
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
|
-
/* eslint-disable rulesdir/no-lit-render-outside-of-view */
|
5
4
|
|
6
5
|
import '../../../ui/legacy/components/data_grid/data_grid.js';
|
7
|
-
import '../../../ui/components/icon_button/icon_button.js';
|
8
|
-
import '../../../ui/legacy/legacy.js';
|
9
6
|
|
10
7
|
import * as i18n from '../../../core/i18n/i18n.js';
|
11
8
|
import * as Root from '../../../core/root/root.js';
|
12
9
|
import type * as Protocol from '../../../generated/protocol.js';
|
13
|
-
// inspectorCommonStyles is imported for the empty state styling that is used for the start view
|
14
|
-
// eslint-disable-next-line rulesdir/es-modules-import
|
15
|
-
import inspectorCommonStyles from '../../../ui/legacy/inspectorCommon.css.js';
|
16
10
|
import * as UI from '../../../ui/legacy/legacy.js';
|
17
11
|
import * as Lit from '../../../ui/lit/lit.js';
|
18
12
|
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
19
13
|
|
20
|
-
import
|
14
|
+
import reportsGridStyles from './reportsGrid.css.js';
|
21
15
|
|
22
16
|
const UIStrings = {
|
23
17
|
/**
|
@@ -48,7 +42,7 @@ const UIStrings = {
|
|
48
42
|
* @description Column header for a table displaying Reporting API reports.
|
49
43
|
*The column contains the timestamp of when a report was generated.
|
50
44
|
*/
|
51
|
-
generatedAt: 'Generated at'
|
45
|
+
generatedAt: 'Generated at',
|
52
46
|
} as const;
|
53
47
|
const str_ = i18n.i18n.registerUIStrings('panels/application/components/ReportsGrid.ts', UIStrings);
|
54
48
|
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
@@ -57,115 +51,100 @@ const {render, html} = Lit;
|
|
57
51
|
|
58
52
|
const REPORTING_API_EXPLANATION_URL = 'https://developer.chrome.com/docs/capabilities/web-apis/reporting-api';
|
59
53
|
|
60
|
-
export class ReportsGridStatusHeader extends HTMLElement {
|
61
|
-
readonly #shadow = this.attachShadow({mode: 'open'});
|
62
|
-
|
63
|
-
connectedCallback(): void {
|
64
|
-
this.#render();
|
65
|
-
}
|
66
|
-
|
67
|
-
#render(): void {
|
68
|
-
// Disabled until https://crbug.com/1079231 is fixed.
|
69
|
-
// clang-format off
|
70
|
-
render(html`
|
71
|
-
<style>${reportingApiGridStyles}</style>
|
72
|
-
<span class="status-header">${i18nString(UIStrings.status)}</span>
|
73
|
-
<x-link href="https://web.dev/reporting-api/#report-status"
|
74
|
-
jslog=${VisualLogging.link('report-status').track({click: true})}>
|
75
|
-
<devtools-icon class="inline-icon medium" name="help" style="color: var(--icon-link);"></devtools-icon>
|
76
|
-
</x-link>
|
77
|
-
`, this.#shadow, {host: this});
|
78
|
-
// clang-format on
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
54
|
export interface ReportsGridData {
|
83
55
|
reports: Protocol.Network.ReportingApiReport[];
|
84
56
|
}
|
85
57
|
|
86
|
-
export
|
87
|
-
|
88
|
-
|
89
|
-
|
58
|
+
export interface ViewInput {
|
59
|
+
reports: Protocol.Network.ReportingApiReport[];
|
60
|
+
protocolMonitorExperimentEnabled: boolean;
|
61
|
+
onSelect: (e: CustomEvent<HTMLElement|null>) => void;
|
62
|
+
}
|
90
63
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
64
|
+
export const DEFAULT_VIEW = (input: ViewInput, output: undefined, target: HTMLElement): void => {
|
65
|
+
// clang-format off
|
66
|
+
render(html`
|
67
|
+
<style>${reportsGridStyles}</style>
|
68
|
+
<style>${UI.inspectorCommonStyles}</style>
|
69
|
+
<div class="reporting-container" jslog=${VisualLogging.section('reports')}>
|
70
|
+
<div class="reporting-header">${i18n.i18n.lockedString('Reports')}</div>
|
71
|
+
${input.reports.length > 0 ? html`
|
72
|
+
<devtools-data-grid striped @select=${input.onSelect}>
|
73
|
+
<table>
|
74
|
+
<tr>
|
75
|
+
${input.protocolMonitorExperimentEnabled ? html`
|
76
|
+
<th id="id" weight="30">${i18n.i18n.lockedString('ID')}</th>
|
77
|
+
` : ''}
|
78
|
+
<th id="url" weight="30">${i18n.i18n.lockedString('URL')}</th>
|
79
|
+
<th id="type" weight="20">${i18n.i18n.lockedString('Type')}</th>
|
80
|
+
<th id="status" weight="20">
|
81
|
+
<style>${reportsGridStyles}</style>
|
82
|
+
<span class="status-header">${i18nString(UIStrings.status)}</span>
|
83
|
+
<x-link href="https://web.dev/reporting-api/#report-status"
|
84
|
+
jslog=${VisualLogging.link('report-status').track({click: true})}>
|
85
|
+
<devtools-icon class="inline-icon medium" name="help" style="color: var(--icon-link);"
|
86
|
+
></devtools-icon>
|
87
|
+
</x-link>
|
88
|
+
</th>
|
89
|
+
<th id="destination" weight="20">${i18nString(UIStrings.destination)}</th>
|
90
|
+
<th id="timestamp" weight="20">${i18nString(UIStrings.generatedAt)}</th>
|
91
|
+
<th id="body" weight="20">${i18n.i18n.lockedString('Body')}</th>
|
92
|
+
</tr>
|
93
|
+
${input.reports.map(report => html`
|
94
|
+
<tr data-id=${report.id}>
|
95
|
+
${input.protocolMonitorExperimentEnabled ? html`<td>${report.id}</td>` : ''}
|
96
|
+
<td>${report.initiatorUrl}</td>
|
97
|
+
<td>${report.type}</td>
|
98
|
+
<td>${report.status}</td>
|
99
|
+
<td>${report.destination}</td>
|
100
|
+
<td>${new Date(report.timestamp * 1000).toLocaleString()}</td>
|
101
|
+
<td>${JSON.stringify(report.body)}</td>
|
102
|
+
</tr>
|
103
|
+
`)}
|
104
|
+
</table>
|
105
|
+
</devtools-data-grid>
|
106
|
+
` : html`
|
107
|
+
<div class="empty-state">
|
108
|
+
<span class="empty-state-header">${i18nString(UIStrings.noReportsToDisplay)}</span>
|
109
|
+
<div class="empty-state-description">
|
110
|
+
<span>${i18nString(UIStrings.reportingApiDescription)}</span>
|
111
|
+
${UI.XLink.XLink.create(REPORTING_API_EXPLANATION_URL, i18nString(UIStrings.learnMore), undefined,
|
112
|
+
undefined, 'learn-more')}
|
113
|
+
</div>
|
114
|
+
</div>
|
115
|
+
`}
|
116
|
+
</div>
|
117
|
+
`, target);
|
118
|
+
// clang-format on
|
119
|
+
};
|
95
120
|
|
96
|
-
|
97
|
-
this.#reports = data.reports;
|
98
|
-
this.#render();
|
99
|
-
}
|
121
|
+
type View = typeof DEFAULT_VIEW;
|
100
122
|
|
101
|
-
|
102
|
-
|
103
|
-
|
123
|
+
export class ReportsGrid extends UI.Widget.Widget {
|
124
|
+
reports: Protocol.Network.ReportingApiReport[] = [];
|
125
|
+
#protocolMonitorExperimentEnabled = false;
|
126
|
+
#view: View;
|
127
|
+
onReportSelected: (id: string) => void = () => {};
|
104
128
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
<style>${inspectorCommonStyles}</style>
|
111
|
-
<div class="reporting-container" jslog=${VisualLogging.section('reports')}>
|
112
|
-
<div class="reporting-header">${i18n.i18n.lockedString('Reports')}</div>
|
113
|
-
${this.#reports.length > 0 ? html`
|
114
|
-
<devtools-data-grid striped @select=${this.#onSelect}>
|
115
|
-
<table>
|
116
|
-
<tr>
|
117
|
-
${this.#protocolMonitorExperimentEnabled ? html`
|
118
|
-
<th id="id" weight="30">${i18n.i18n.lockedString('ID')}</th>
|
119
|
-
` : ''}
|
120
|
-
<th id="url" weight="30">${i18n.i18n.lockedString('URL')}</th>
|
121
|
-
<th id="type" weight="20">${i18n.i18n.lockedString('Type')}</th>
|
122
|
-
<th id="status" weight="20">
|
123
|
-
<devtools-resources-reports-grid-status-header></devtools-resources-reports-grid-status-header>
|
124
|
-
</th>
|
125
|
-
<th id="destination" weight="20">${i18nString(UIStrings.destination)}</th>
|
126
|
-
<th id="timestamp" weight="20">${i18nString(UIStrings.generatedAt)}</th>
|
127
|
-
<th id="body" weight="20">${i18n.i18n.lockedString('Body')}</th>
|
128
|
-
</tr>
|
129
|
-
${this.#reports.map(report => html`
|
130
|
-
<tr data-id=${report.id}>
|
131
|
-
${this.#protocolMonitorExperimentEnabled ? html`<td>${report.id}</td>` : ''}
|
132
|
-
<td>${report.initiatorUrl}</td>
|
133
|
-
<td>${report.type}</td>
|
134
|
-
<td>${report.status}</td>
|
135
|
-
<td>${report.destination}</td>
|
136
|
-
<td>${new Date(report.timestamp * 1000).toLocaleString()}</td>
|
137
|
-
<td>${JSON.stringify(report.body)}</td>
|
138
|
-
</tr>
|
139
|
-
`)}
|
140
|
-
</table>
|
141
|
-
</devtools-data-grid>
|
142
|
-
` : html`
|
143
|
-
<div class="empty-state">
|
144
|
-
<span class="empty-state-header">${i18nString(UIStrings.noReportsToDisplay)}</span>
|
145
|
-
<div class="empty-state-description">
|
146
|
-
<span>${i18nString(UIStrings.reportingApiDescription)}</span>
|
147
|
-
${UI.XLink.XLink.create(REPORTING_API_EXPLANATION_URL, i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more')}
|
148
|
-
</div>
|
149
|
-
</div>
|
150
|
-
`}
|
151
|
-
</div>
|
152
|
-
`, this.#shadow, {host: this});
|
153
|
-
// clang-format on
|
129
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
130
|
+
super(element);
|
131
|
+
this.#view = view;
|
132
|
+
this.#protocolMonitorExperimentEnabled = Root.Runtime.experiments.isEnabled('protocol-monitor');
|
133
|
+
this.requestUpdate();
|
154
134
|
}
|
155
135
|
|
156
|
-
#onSelect(e: CustomEvent<HTMLElement|null>): void {
|
157
|
-
if (e.detail) {
|
158
|
-
this.
|
136
|
+
#onSelect = (e: CustomEvent<HTMLElement|null>): void => {
|
137
|
+
if (e.detail?.dataset.id) {
|
138
|
+
this.onReportSelected(e.detail.dataset.id);
|
159
139
|
}
|
160
|
-
}
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
'devtools-resources-reports-grid': ReportsGrid;
|
140
|
+
};
|
141
|
+
|
142
|
+
override performUpdate(): void {
|
143
|
+
const viewInput = {
|
144
|
+
reports: this.reports,
|
145
|
+
protocolMonitorExperimentEnabled: this.#protocolMonitorExperimentEnabled,
|
146
|
+
onSelect: this.#onSelect,
|
147
|
+
};
|
148
|
+
this.#view(viewInput, undefined, this.contentElement);
|
170
149
|
}
|
171
150
|
}
|
@@ -14,6 +14,8 @@ import * as RenderCoordinator from '../../../ui/components/render_coordinator/re
|
|
14
14
|
import * as UI from '../../../ui/legacy/legacy.js';
|
15
15
|
import * as Lit from '../../../ui/lit/lit.js';
|
16
16
|
|
17
|
+
import storageMetadataViewStyle from './storageMetadataView.css.js';
|
18
|
+
|
17
19
|
const {html} = Lit;
|
18
20
|
|
19
21
|
const UIStrings = {
|
@@ -21,7 +23,7 @@ const UIStrings = {
|
|
21
23
|
* @description The origin of a URL (https://web.dev/same-site-same-origin/#origin).
|
22
24
|
*(for a lot of languages this does not need to be translated, please translate only where necessary)
|
23
25
|
*/
|
24
|
-
origin: '
|
26
|
+
origin: 'Frame origin',
|
25
27
|
/**
|
26
28
|
* @description Site (https://web.dev/same-site-same-origin/#site) for the URL the user sees in the omnibox.
|
27
29
|
*/
|
@@ -118,6 +120,7 @@ export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableCo
|
|
118
120
|
#storageBucketsModel?: SDK.StorageBucketsModel.StorageBucketsModel;
|
119
121
|
#storageKey: SDK.StorageKeyManager.StorageKey|null = null;
|
120
122
|
#storageBucket: Protocol.Storage.StorageBucketInfo|null = null;
|
123
|
+
#showOnlyBucket = true;
|
121
124
|
|
122
125
|
setStorageKey(storageKey: string): void {
|
123
126
|
this.#storageKey = SDK.StorageKeyManager.parseStorageKey(storageKey);
|
@@ -129,6 +132,10 @@ export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableCo
|
|
129
132
|
this.setStorageKey(storageBucket.bucket.storageKey);
|
130
133
|
}
|
131
134
|
|
135
|
+
setShowOnlyBucket(show: boolean): void {
|
136
|
+
this.#showOnlyBucket = show;
|
137
|
+
}
|
138
|
+
|
132
139
|
enableStorageBucketControls(model: SDK.StorageBucketsModel.StorageBucketsModel): void {
|
133
140
|
this.#storageBucketsModel = model;
|
134
141
|
if (this.#storageKey) {
|
@@ -141,6 +148,9 @@ export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableCo
|
|
141
148
|
// Disabled until https://crbug.com/1079231 is fixed.
|
142
149
|
// clang-format off
|
143
150
|
Lit.render(html`
|
151
|
+
<style>
|
152
|
+
${storageMetadataViewStyle}
|
153
|
+
</style>
|
144
154
|
<devtools-report .data=${{reportTitle: this.getTitle() ?? i18nString(UIStrings.loading)}}>
|
145
155
|
${await this.renderReportContent()}
|
146
156
|
</devtools-report>`, this.#shadow, {host: this});
|
@@ -181,11 +191,16 @@ export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableCo
|
|
181
191
|
topLevelSiteIsOpaque ? i18nString(UIStrings.yesBecauseTopLevelIsOpaque) :
|
182
192
|
(topLevelSite && origin !== topLevelSite) ? i18nString(UIStrings.yesBecauseOriginNotInTopLevelSite) :
|
183
193
|
null;
|
194
|
+
|
195
|
+
const isIframeOrEmbedded = topLevelSite && origin !== topLevelSite;
|
196
|
+
|
184
197
|
// Disabled until https://crbug.com/1079231 is fixed.
|
185
198
|
// clang-format off
|
186
199
|
return html`
|
187
|
-
${
|
188
|
-
|
200
|
+
${(isIframeOrEmbedded) ?
|
201
|
+
html`${this.key(i18nString(UIStrings.origin))}
|
202
|
+
${this.value(html`<div class="text-ellipsis" title=${origin}>${origin}</div>`)}`
|
203
|
+
: Lit.nothing}
|
189
204
|
${(topLevelSite || topLevelSiteIsOpaque) ? this.key(i18nString(UIStrings.topLevelSite)) : Lit.nothing}
|
190
205
|
${topLevelSite ? this.value(topLevelSite) : Lit.nothing}
|
191
206
|
${topLevelSiteIsOpaque ? this.value(i18nString(UIStrings.opaque)) : Lit.nothing}
|
@@ -205,11 +220,22 @@ export class StorageMetadataView extends LegacyWrapper.LegacyWrapper.WrappableCo
|
|
205
220
|
throw new Error('Should not call #renderStorageBucketInfo if #bucket is null.');
|
206
221
|
}
|
207
222
|
const {bucket: {name}, persistent, durability, quota} = this.#storageBucket;
|
223
|
+
const isDefault = !name;
|
208
224
|
|
225
|
+
if (!this.#showOnlyBucket) {
|
226
|
+
if (isDefault) {
|
227
|
+
return html`
|
228
|
+
${this.key(i18nString(UIStrings.bucketName))}
|
229
|
+
${this.value(html`<span class="default-bucket">default</span>`)}`;
|
230
|
+
}
|
231
|
+
return html`
|
232
|
+
${this.key(i18nString(UIStrings.bucketName))}
|
233
|
+
${this.value(name)}`;
|
234
|
+
}
|
209
235
|
// clang-format off
|
210
236
|
return html`
|
211
237
|
${this.key(i18nString(UIStrings.bucketName))}
|
212
|
-
${this.value(name ||
|
238
|
+
${this.value(name || html`<span class="default-bucket">default</span>`)}
|
213
239
|
${this.key(i18nString(UIStrings.persistent))}
|
214
240
|
${this.value(persistent ? i18nString(UIStrings.yes) : i18nString(UIStrings.no))}
|
215
241
|
${this.key(i18nString(UIStrings.durability))}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2025 The Chromium Authors
|
3
|
+
* Use of this source code is governed by a BSD-style license that can be
|
4
|
+
* found in the LICENSE file.
|
5
|
+
*/
|
6
|
+
|
7
|
+
@scope to (devtools-widget > *) {
|
8
|
+
:scope {
|
9
|
+
overflow: auto;
|
10
|
+
height: 100%;
|
11
|
+
}
|
12
|
+
|
13
|
+
.endpoints-container {
|
14
|
+
height: 100%;
|
15
|
+
display: flex;
|
16
|
+
flex-direction: column;
|
17
|
+
width: 100%;
|
18
|
+
}
|
19
|
+
|
20
|
+
.endpoints-header {
|
21
|
+
font-size: 15px;
|
22
|
+
background-color: var(--sys-color-surface2);
|
23
|
+
padding: 1px 4px;
|
24
|
+
flex-shrink: 0;
|
25
|
+
}
|
26
|
+
|
27
|
+
devtools-data-grid {
|
28
|
+
flex: auto;
|
29
|
+
}
|
30
|
+
}
|