chrome-devtools-frontend 1.0.1521880 → 1.0.1522585
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/docs/ui_engineering.md +76 -0
- package/front_end/core/host/GdpClient.ts +116 -66
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/core/sdk/EnhancedTracesParser.ts +13 -6
- 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/generated/Deprecation.ts +4 -4
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +10 -6
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +559 -0
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +42 -4
- package/front_end/models/badges/UserBadges.ts +14 -16
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/trace/LanternComputationData.ts +1 -0
- package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +10 -0
- package/front_end/models/trace/insights/DocumentLatency.ts +9 -10
- package/front_end/models/trace/types/TraceEvents.ts +6 -5
- 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/protocol_monitor/ProtocolMonitor.ts +31 -32
- 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/timeline/TimelineFlameChartView.ts +17 -0
- package/front_end/panels/timeline/TimelinePanel.ts +5 -0
- package/front_end/panels/timeline/TimelineUIUtils.ts +12 -3
- package/front_end/panels/timeline/components/ExportTraceOptions.ts +21 -9
- package/front_end/panels/timeline/timelineDetailsView.css +5 -0
- 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/chromium/README.chromium +1 -1
- package/front_end/third_party/diff/README.chromium +0 -1
- package/front_end/ui/components/tooltips/Tooltip.ts +13 -4
- 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
@@ -4,7 +4,6 @@
|
|
4
4
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
6
6
|
import * as Host from '../../core/host/host.js';
|
7
|
-
import * as Root from '../../core/root/root.js';
|
8
7
|
|
9
8
|
import {AiExplorerBadge} from './AiExplorerBadge.js';
|
10
9
|
import type {Badge, BadgeAction, BadgeActionEvents, BadgeContext, TriggerOptions} from './Badge.js';
|
@@ -50,8 +49,7 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
50
49
|
super();
|
51
50
|
|
52
51
|
this.#receiveBadgesSetting = Common.Settings.Settings.instance().moduleSetting('receive-gdp-badges');
|
53
|
-
if (Host.GdpClient.
|
54
|
-
Root.Runtime.GdpProfilesEnterprisePolicyValue.ENABLED_WITHOUT_BADGES) {
|
52
|
+
if (!Host.GdpClient.isBadgesEnabled()) {
|
55
53
|
this.#receiveBadgesSetting.set(false);
|
56
54
|
}
|
57
55
|
this.#receiveBadgesSetting.addChangeListener(this.#reconcileBadges, this);
|
@@ -106,10 +104,10 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
106
104
|
if (!badge.isStarterBadge) {
|
107
105
|
shouldAwardBadge = true;
|
108
106
|
} else {
|
109
|
-
const
|
107
|
+
const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
|
110
108
|
const receiveBadgesSettingEnabled = Boolean(this.#receiveBadgesSetting.get());
|
111
109
|
// If there is a GDP profile and the user has enabled receiving badges, we award the starter badge as well.
|
112
|
-
if (
|
110
|
+
if (getProfileResponse?.profile && receiveBadgesSettingEnabled && !this.#isStarterBadgeDismissed() &&
|
113
111
|
!this.#isStarterBadgeSnoozed()) {
|
114
112
|
shouldAwardBadge = true;
|
115
113
|
}
|
@@ -157,27 +155,28 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
157
155
|
return;
|
158
156
|
}
|
159
157
|
|
160
|
-
if (!Host.GdpClient.isGdpProfilesAvailable() ||
|
161
|
-
Host.GdpClient.getGdpProfilesEnterprisePolicy() !== Root.Runtime.GdpProfilesEnterprisePolicyValue.ENABLED) {
|
158
|
+
if (!Host.GdpClient.isGdpProfilesAvailable() || !Host.GdpClient.isBadgesEnabled()) {
|
162
159
|
this.#deactivateAllBadges();
|
163
160
|
return;
|
164
161
|
}
|
165
162
|
|
166
|
-
const
|
167
|
-
|
168
|
-
|
169
|
-
|
163
|
+
const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
|
164
|
+
if (!getProfileResponse) {
|
165
|
+
this.#deactivateAllBadges();
|
166
|
+
return;
|
170
167
|
}
|
171
168
|
|
169
|
+
const hasGdpProfile = Boolean(getProfileResponse.profile);
|
170
|
+
const isEligibleToCreateProfile = getProfileResponse.isEligible;
|
172
171
|
// User does not have a GDP profile & not eligible to create one.
|
173
172
|
// So, we don't activate any badges for them.
|
174
|
-
if (!
|
173
|
+
if (!hasGdpProfile && !isEligibleToCreateProfile) {
|
175
174
|
this.#deactivateAllBadges();
|
176
175
|
return;
|
177
176
|
}
|
178
177
|
|
179
178
|
let awardedBadgeNames: Set<string>|null = null;
|
180
|
-
if (
|
179
|
+
if (hasGdpProfile) {
|
181
180
|
awardedBadgeNames = await Host.GdpClient.GdpClient.instance().getAwardedBadgeNames(
|
182
181
|
{names: this.#allBadges.map(badge => badge.name)});
|
183
182
|
// This is a conservative approach. We bail out if `awardedBadgeNames` is null
|
@@ -202,9 +201,8 @@ export class UserBadges extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
202
201
|
}
|
203
202
|
|
204
203
|
const shouldActivateStarterBadge = badge.isStarterBadge && isEligibleToCreateProfile &&
|
205
|
-
!this.#isStarterBadgeDismissed() && !this.#isStarterBadgeSnoozed();
|
206
|
-
const shouldActivateActivityBasedBadge =
|
207
|
-
!badge.isStarterBadge && Boolean(gdpProfile) && receiveBadgesSettingEnabled;
|
204
|
+
Host.GdpClient.isStarterBadgeEnabled() && !this.#isStarterBadgeDismissed() && !this.#isStarterBadgeSnoozed();
|
205
|
+
const shouldActivateActivityBasedBadge = !badge.isStarterBadge && hasGdpProfile && receiveBadgesSettingEnabled;
|
208
206
|
if (shouldActivateStarterBadge || shouldActivateActivityBasedBadge) {
|
209
207
|
badge.activate();
|
210
208
|
} else {
|
@@ -192,6 +192,7 @@ function createLanternRequest(
|
|
192
192
|
priority: request.args.data.priority,
|
193
193
|
frameId: request.args.data.frame,
|
194
194
|
fromWorker,
|
195
|
+
serverResponseTime: request.args.data.lrServerResponseTime ?? undefined,
|
195
196
|
// Set later.
|
196
197
|
redirects: undefined,
|
197
198
|
redirectSource: undefined,
|
@@ -295,6 +295,7 @@ export async function finalize(): Promise<void> {
|
|
295
295
|
*
|
296
296
|
* See `_updateTimingsForLightrider` in Lighthouse for more detail.
|
297
297
|
*/
|
298
|
+
let lrServerResponseTime;
|
298
299
|
if (isLightrider && request.receiveResponse?.args.data.headers) {
|
299
300
|
timing = {
|
300
301
|
requestTime: Helpers.Timing.microToSeconds(request.sendRequests.at(0)?.ts ?? 0 as Types.Timing.Micro),
|
@@ -330,6 +331,14 @@ export async function finalize(): Promise<void> {
|
|
330
331
|
timing.connectEnd = TCPMs as Types.Timing.Milli;
|
331
332
|
timing.sslEnd = TCPMs as Types.Timing.Milli;
|
332
333
|
}
|
334
|
+
|
335
|
+
// Lightrider does not have any equivalent for `sendEnd` timing values. The
|
336
|
+
// closest we can get to the server response time is from a header that
|
337
|
+
// Lightrider sets.
|
338
|
+
const ResponseMsHeader = request.receiveResponse.args.data.headers.find(h => h.name === 'X-ResponseMs');
|
339
|
+
if (ResponseMsHeader) {
|
340
|
+
lrServerResponseTime = Math.max(0, parseInt(ResponseMsHeader.value, 10)) as Types.Timing.Milli;
|
341
|
+
}
|
333
342
|
}
|
334
343
|
|
335
344
|
// TODO: consider allowing chrome / about.
|
@@ -526,6 +535,7 @@ export async function finalize(): Promise<void> {
|
|
526
535
|
initiator: finalSendRequest.args.data.initiator,
|
527
536
|
stackTrace: finalSendRequest.args.data.stackTrace,
|
528
537
|
timing,
|
538
|
+
lrServerResponseTime,
|
529
539
|
url,
|
530
540
|
failed: request.resourceFinish?.args.data.didFail ?? false,
|
531
541
|
finished: Boolean(request.resourceFinish),
|
@@ -95,15 +95,14 @@ export type DocumentLatencyInsightModel = InsightModel<typeof UIStrings, {
|
|
95
95
|
},
|
96
96
|
}>;
|
97
97
|
|
98
|
-
function getServerResponseTime(
|
99
|
-
|
100
|
-
//
|
101
|
-
//
|
102
|
-
//
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
return lanternRequest.serverResponseTime as Types.Timing.Milli;
|
98
|
+
function getServerResponseTime(request: Types.Events.SyntheticNetworkRequest): Types.Timing.Milli|null {
|
99
|
+
// For technical reasons, Lightrider does not have `sendEnd` timing values. The
|
100
|
+
// closest we can get to the server response time is from a header that Lightrider
|
101
|
+
// sets.
|
102
|
+
// @ts-expect-error
|
103
|
+
const isLightrider = globalThis.isLightrider;
|
104
|
+
if (isLightrider) {
|
105
|
+
return request.args.data.lrServerResponseTime ?? null;
|
107
106
|
}
|
108
107
|
|
109
108
|
const timing = request.args.data.timing;
|
@@ -202,7 +201,7 @@ export function generateInsight(
|
|
202
201
|
return finalize({warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});
|
203
202
|
}
|
204
203
|
|
205
|
-
const serverResponseTime = getServerResponseTime(documentRequest
|
204
|
+
const serverResponseTime = getServerResponseTime(documentRequest);
|
206
205
|
if (serverResponseTime === null) {
|
207
206
|
throw new Error('missing document request timing');
|
208
207
|
}
|
@@ -124,10 +124,10 @@ export interface TraceFrame {
|
|
124
124
|
processId: ProcessID;
|
125
125
|
url: string;
|
126
126
|
parent?: string;
|
127
|
-
// Added to
|
127
|
+
// Added to Chrome in April 2024:
|
128
128
|
// crrev.com/c/5424783
|
129
129
|
isOutermostMainFrame?: boolean;
|
130
|
-
// Added to
|
130
|
+
// Added to Chrome in June 2024:
|
131
131
|
// crrev.com/c/5595033
|
132
132
|
isInPrimaryMainFrame?: boolean;
|
133
133
|
}
|
@@ -415,6 +415,8 @@ export interface SyntheticNetworkRequest extends Complete, SyntheticBased<Phase.
|
|
415
415
|
initiator?: Initiator,
|
416
416
|
requestMethod?: string,
|
417
417
|
timing?: ResourceReceiveResponseTimingData,
|
418
|
+
/** Server response time according to Lightrider. */
|
419
|
+
lrServerResponseTime?: Milli,
|
418
420
|
},
|
419
421
|
};
|
420
422
|
cat: 'loading';
|
@@ -549,7 +551,6 @@ export function isAuctionWorkletDoneWithProcess(event: Event): event is AuctionW
|
|
549
551
|
* consuming screenshot events from the ScreenshotHandler, you must make sure
|
550
552
|
* to have your code deal with the two different formats.
|
551
553
|
*/
|
552
|
-
// These are nullable because in January 2025 a CL in Chromium
|
553
554
|
export interface LegacyScreenshot extends Event {
|
554
555
|
/**
|
555
556
|
* @deprecated This value is incorrect. Use ScreenshotHandler.getPresentationTimestamp()
|
@@ -745,7 +746,7 @@ export interface LargestContentfulPaintCandidate extends Mark {
|
|
745
746
|
nodeId: Protocol.DOM.BackendNodeId,
|
746
747
|
loadingAttr: string,
|
747
748
|
type?: string,
|
748
|
-
// Landed in
|
749
|
+
// Landed in Chrome M140: crrev.com/c/6702010
|
749
750
|
nodeName?: string,
|
750
751
|
},
|
751
752
|
};
|
@@ -990,7 +991,7 @@ export interface SyntheticLayoutShift extends Omit<LayoutShift, 'name'>, Synthet
|
|
990
991
|
export const NO_NAVIGATION = 'NO_NAVIGATION';
|
991
992
|
|
992
993
|
/**
|
993
|
-
* This maybe be a navigation id string from
|
994
|
+
* This maybe be a navigation id string from Chrome, or `NO_NAVIGATION`, which represents the
|
994
995
|
* portion of the trace for which we don't have any navigation event for (as it happeneded prior
|
995
996
|
* to the trace start).
|
996
997
|
*/
|
@@ -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
|
}
|