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
@@ -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
|
+
}
|
@@ -0,0 +1,34 @@
|
|
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
|
+
.reporting-container {
|
14
|
+
height: 100%;
|
15
|
+
display: flex;
|
16
|
+
flex-direction: column;
|
17
|
+
width: 100%;
|
18
|
+
}
|
19
|
+
|
20
|
+
.reporting-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
|
+
|
31
|
+
.inline-icon {
|
32
|
+
vertical-align: text-bottom;
|
33
|
+
}
|
34
|
+
}
|
@@ -183,29 +183,23 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
183
183
|
'source-code': true,
|
184
184
|
'breakpoint-hit': input.highlightedItem === breakpoint,
|
185
185
|
});
|
186
|
-
const
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
if (expanded) {
|
204
|
-
output.userExpandedCategories.add(category);
|
205
|
-
} else {
|
206
|
-
output.userExpandedCategories.delete(category);
|
207
|
-
}
|
208
|
-
};
|
186
|
+
const onExpand =
|
187
|
+
(category: SDK.CategorizedBreakpoint.Category, {detail: {expanded}}: UI.TreeOutline.TreeViewElement.ExpandEvent):
|
188
|
+
void => {
|
189
|
+
const breakpoints = category && input.categories.get(category);
|
190
|
+
if (!breakpoints) {
|
191
|
+
return;
|
192
|
+
}
|
193
|
+
if (shouldExpandCategory(breakpoints)) {
|
194
|
+
// Basically ignore expand/collapse when the category is expanded by default.
|
195
|
+
return;
|
196
|
+
}
|
197
|
+
if (expanded) {
|
198
|
+
output.userExpandedCategories.add(category);
|
199
|
+
} else {
|
200
|
+
output.userExpandedCategories.delete(category);
|
201
|
+
}
|
202
|
+
};
|
209
203
|
|
210
204
|
render(
|
211
205
|
// clang-format off
|
@@ -219,17 +213,15 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
219
213
|
</devtools-toolbar>
|
220
214
|
<devtools-tree
|
221
215
|
${ref(e => { output.defaultFocus = e; })}
|
222
|
-
@expand=${onExpand}
|
223
216
|
.template=${html`
|
224
217
|
<ul role="tree">
|
225
218
|
${filteredCategories.map(([category, breakpoints]) => html`
|
226
|
-
<li
|
219
|
+
<li @expand=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) => onExpand(category, e)}
|
227
220
|
role="treeitem"
|
228
221
|
jslog-context=${category}
|
229
222
|
aria-checked=${breakpoints.some(breakpoint => breakpoint.enabled())
|
230
223
|
? breakpoints.some(breakpoint => !breakpoint.enabled()) ? 'mixed' : true
|
231
|
-
: false}
|
232
|
-
${trackCategoryConfigElement(category)}>
|
224
|
+
: false}>
|
233
225
|
<style>${categorizedBreakpointsSidebarPaneStyles}</style>
|
234
226
|
<devtools-checkbox
|
235
227
|
class="small"
|
@@ -192,7 +192,14 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
192
192
|
}
|
193
193
|
|
194
194
|
async #presentStarterBadge(badge: Badges.Badge): Promise<void> {
|
195
|
-
const
|
195
|
+
const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
|
196
|
+
// The `getProfile` call failed and returned a `null`.
|
197
|
+
// For that case, we don't show anything.
|
198
|
+
if (!getProfileResponse) {
|
199
|
+
return;
|
200
|
+
}
|
201
|
+
|
202
|
+
const hasGdpProfile = Boolean(getProfileResponse.profile);
|
196
203
|
const receiveBadgesSettingEnabled = Badges.UserBadges.instance().isReceiveBadgesSettingEnabled();
|
197
204
|
const googleDeveloperProgramLink = UI.XLink.XLink.create(
|
198
205
|
'https://developers.google.com/program', lockedString('Google Developer Program'), 'badge-link', undefined,
|
@@ -200,14 +207,14 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
200
207
|
|
201
208
|
// If the user already has a GDP profile and the receive badges setting enabled,
|
202
209
|
// starter badge behaves as if it's an activity based badge.
|
203
|
-
if (
|
210
|
+
if (hasGdpProfile && receiveBadgesSettingEnabled) {
|
204
211
|
this.#presentActivityBasedBadge(badge);
|
205
212
|
return;
|
206
213
|
}
|
207
214
|
|
208
215
|
// If the user already has a GDP profile and the receive badges setting disabled,
|
209
216
|
// starter badge behaves as a nudge for opting into receiving badges.
|
210
|
-
if (
|
217
|
+
if (hasGdpProfile && !receiveBadgesSettingEnabled) {
|
211
218
|
this.#show({
|
212
219
|
message: i18nFormatString(
|
213
220
|
UIStrings.starterBadgeAwardMessageSettingDisabled, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
|
@@ -1050,7 +1050,7 @@ let searchNetworkViewInstance: SearchNetworkView;
|
|
1050
1050
|
|
1051
1051
|
export class SearchNetworkView extends Search.SearchView.SearchView {
|
1052
1052
|
private constructor() {
|
1053
|
-
super('network'
|
1053
|
+
super('network');
|
1054
1054
|
}
|
1055
1055
|
|
1056
1056
|
static instance(opts: {
|
@@ -173,17 +173,17 @@ export interface ViewInput {
|
|
173
173
|
filterKeys: string[];
|
174
174
|
filter: string;
|
175
175
|
parseFilter: (filter: string) => TextUtils.TextUtils.ParsedFilter[];
|
176
|
-
onRecord: (
|
176
|
+
onRecord: (record: boolean) => void;
|
177
177
|
onClear: () => void;
|
178
178
|
onSave: () => void;
|
179
|
-
onSplitChange: (
|
179
|
+
onSplitChange: (onlyMain: boolean) => void;
|
180
180
|
onSelect: (e: CustomEvent<HTMLElement|null>) => void;
|
181
181
|
onContextMenu: (e: CustomEvent<{menu: UI.ContextMenu.ContextMenu, element: HTMLElement}>) => void;
|
182
|
-
onFilterChanged: (
|
183
|
-
onCommandChange: (
|
184
|
-
onCommandSubmitted: (
|
185
|
-
onTargetChange: (
|
186
|
-
onToggleSidebar: (
|
182
|
+
onFilterChanged: (filter: string) => void;
|
183
|
+
onCommandChange: (command: string) => void;
|
184
|
+
onCommandSubmitted: (input: string) => void;
|
185
|
+
onTargetChange: (targetId: string) => void;
|
186
|
+
onToggleSidebar: () => void;
|
187
187
|
targets: SDK.Target.Target[];
|
188
188
|
selectedTargetId: string;
|
189
189
|
}
|
@@ -203,7 +203,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
203
203
|
direction="column"
|
204
204
|
sidebar-initial-size="400"
|
205
205
|
sidebar-visibility=${input.sidebarVisible ? 'visible' : 'hidden'}
|
206
|
-
@change=${input.onSplitChange}>
|
206
|
+
@change=${(e: CustomEvent<string>) => input.onSplitChange(e.detail === 'OnlyMain')}>
|
207
207
|
<div slot="main" class="vbox protocol-monitor-main">
|
208
208
|
<devtools-toolbar class="protocol-monitor-toolbar"
|
209
209
|
jslog=${VisualLogging.toolbar('top')}>
|
@@ -214,22 +214,23 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
214
214
|
.variant=${Buttons.Button.Variant.ICON_TOGGLE}
|
215
215
|
.toggleType=${Buttons.Button.ToggleType.RED}
|
216
216
|
.toggled=${true}
|
217
|
-
@click=${input.onRecord}
|
217
|
+
@click=${(e: Event) => input.onRecord((e.target as Buttons.Button.Button).toggled)}>
|
218
|
+
</devtools-button>
|
218
219
|
<devtools-button title=${i18nString(UIStrings.clearAll)}
|
219
220
|
.iconName=${'clear'}
|
220
221
|
.variant=${Buttons.Button.Variant.TOOLBAR}
|
221
222
|
.jslogContext=${'protocol-monitor.clear-all'}
|
222
|
-
@click=${input.onClear}></devtools-button>
|
223
|
+
@click=${() => input.onClear()}></devtools-button>
|
223
224
|
<devtools-button title=${i18nString(UIStrings.save)}
|
224
225
|
.iconName=${'download'}
|
225
226
|
.variant=${Buttons.Button.Variant.TOOLBAR}
|
226
227
|
.jslogContext=${'protocol-monitor.save'}
|
227
|
-
@click=${input.onSave}></devtools-button>
|
228
|
+
@click=${() => input.onSave()}></devtools-button>
|
228
229
|
<devtools-toolbar-input type="filter"
|
229
230
|
list="filter-suggestions"
|
230
231
|
style="flex-grow: 1"
|
231
232
|
value=${input.filter}
|
232
|
-
@change=${input.onFilterChanged}>
|
233
|
+
@change=${(e: Event) => input.onFilterChanged((e.target as HTMLInputElement).value)}>
|
233
234
|
<datalist id="filter-suggestions">
|
234
235
|
${input.filterKeys.map(key => html`
|
235
236
|
<option value=${key + ':'}></option>
|
@@ -320,7 +321,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
320
321
|
.iconName=${input.sidebarVisible ? 'left-panel-close' : 'left-panel-open'}
|
321
322
|
.variant=${Buttons.Button.Variant.TOOLBAR}
|
322
323
|
.jslogContext=${'protocol-monitor.toggle-command-editor'}
|
323
|
-
@click=${input.onToggleSidebar}></devtools-button>
|
324
|
+
@click=${() => input.onToggleSidebar()}></devtools-button>
|
324
325
|
</devtools-button>
|
325
326
|
<devtools-toolbar-input id="command-input"
|
326
327
|
style=${styleMap({
|
@@ -330,8 +331,8 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
330
331
|
list="command-input-suggestions"
|
331
332
|
placeholder=${i18nString(UIStrings.sendRawCDPCommand)}
|
332
333
|
title=${i18nString(UIStrings.sendRawCDPCommandExplanation)}
|
333
|
-
@change=${input.onCommandChange}
|
334
|
-
@submit=${input.onCommandSubmitted}>
|
334
|
+
@change=${(e: Event) => input.onCommandChange((e.target as HTMLInputElement).value)}
|
335
|
+
@submit=${(e: Event) => input.onCommandSubmitted((e.target as HTMLInputElement).value)}>
|
335
336
|
<datalist id="command-input-suggestions">
|
336
337
|
${input.commandSuggestions.map(c => html`<option value=${c}></option>`)}
|
337
338
|
</datalist>
|
@@ -340,7 +341,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
340
341
|
title=${i18nString(UIStrings.selectTarget)}
|
341
342
|
style=${styleMap({display: input.sidebarVisible ? 'none' : 'flex'})}
|
342
343
|
jslog=${VisualLogging.dropDown('target-selector').track({change: true})}
|
343
|
-
@change=${input.onTargetChange}>
|
344
|
+
@change=${(e: Event) => input.onTargetChange((e.target as HTMLSelectElement).value)}>
|
344
345
|
${input.targets.map(target => html`
|
345
346
|
<option jslog=${VisualLogging.item('target').track({click: true})}
|
346
347
|
value=${target.id()} ?selected=${target.id() === input.selectedTargetId}>
|
@@ -416,8 +417,8 @@ export class ProtocolMonitorImpl extends UI.Panel.Panel {
|
|
416
417
|
filterKeys: this.#filterKeys,
|
417
418
|
filter: this.#filter,
|
418
419
|
parseFilter: this.filterParser.parse.bind(this.filterParser),
|
419
|
-
onSplitChange: (
|
420
|
-
if (
|
420
|
+
onSplitChange: (onlyMain: boolean) => {
|
421
|
+
if (onlyMain) {
|
421
422
|
this.#populateToolbarInput();
|
422
423
|
this.#sidebarVisible = false;
|
423
424
|
} else {
|
@@ -427,8 +428,8 @@ export class ProtocolMonitorImpl extends UI.Panel.Panel {
|
|
427
428
|
}
|
428
429
|
this.requestUpdate();
|
429
430
|
},
|
430
|
-
onRecord: (
|
431
|
-
this.setRecording(
|
431
|
+
onRecord: (recording: boolean) => {
|
432
|
+
this.setRecording(recording);
|
432
433
|
},
|
433
434
|
onClear: () => {
|
434
435
|
this.#messages = [];
|
@@ -449,24 +450,22 @@ export class ProtocolMonitorImpl extends UI.Panel.Panel {
|
|
449
450
|
this.#populateContextMenu(e.detail.menu, message);
|
450
451
|
}
|
451
452
|
},
|
452
|
-
onCommandChange: (
|
453
|
-
this.#command =
|
453
|
+
onCommandChange: (command: string) => {
|
454
|
+
this.#command = command;
|
454
455
|
},
|
455
|
-
onCommandSubmitted: (
|
456
|
-
this.#commandAutocompleteSuggestionProvider.addEntry(
|
457
|
-
const {command, parameters} = parseCommandInput(
|
456
|
+
onCommandSubmitted: (input: string) => {
|
457
|
+
this.#commandAutocompleteSuggestionProvider.addEntry(input);
|
458
|
+
const {command, parameters} = parseCommandInput(input);
|
458
459
|
this.onCommandSend(command, parameters, this.#selectedTargetId);
|
459
460
|
},
|
460
|
-
onFilterChanged: (
|
461
|
-
this.#filter =
|
461
|
+
onFilterChanged: (filter: string) => {
|
462
|
+
this.#filter = filter;
|
462
463
|
this.requestUpdate();
|
463
464
|
},
|
464
|
-
onTargetChange: (
|
465
|
-
|
466
|
-
this.#selectedTargetId = e.target.value;
|
467
|
-
}
|
465
|
+
onTargetChange: (targetId: string) => {
|
466
|
+
this.#selectedTargetId = targetId;
|
468
467
|
},
|
469
|
-
onToggleSidebar: (
|
468
|
+
onToggleSidebar: () => {
|
470
469
|
this.#sidebarVisible = !this.#sidebarVisible;
|
471
470
|
this.requestUpdate();
|
472
471
|
},
|