chrome-devtools-frontend 1.0.1001419 → 1.0.1002867
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/config/gni/devtools_grd_files.gni +5 -6
- package/front_end/core/common/ParsedURL.ts +3 -3
- package/front_end/core/host/InspectorFrontendHost.ts +30 -1
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/i18n/locales/en-US.json +155 -11
- package/front_end/core/i18n/locales/en-XL.json +155 -11
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/Runtime.ts +7 -3
- package/front_end/core/sdk/ServiceWorkerManager.ts +6 -5
- package/front_end/entrypoints/formatter_worker/FormatterActions.ts +14 -0
- package/front_end/entrypoints/formatter_worker/ScopeParser.ts +491 -0
- package/front_end/entrypoints/formatter_worker/Substitute.ts +4 -440
- package/front_end/entrypoints/formatter_worker/formatter_worker.ts +2 -0
- package/front_end/entrypoints/main/MainImpl.ts +1 -0
- package/front_end/generated/InspectorBackendCommands.js +42 -12
- package/front_end/generated/SupportedCSSProperties.js +3 -5
- package/front_end/generated/protocol-mapping.d.ts +5 -1
- package/front_end/generated/protocol-proxy-api.d.ts +4 -1
- package/front_end/generated/protocol.ts +68 -14
- package/front_end/models/bindings/BreakpointManager.ts +12 -11
- package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
- package/front_end/models/issues_manager/AttributionReportingIssue.ts +6 -34
- package/front_end/models/issues_manager/DeprecationIssue.ts +313 -399
- package/front_end/models/issues_manager/Issue.ts +8 -4
- package/front_end/models/issues_manager/descriptions/arInvalidHeader.md +3 -0
- package/front_end/models/persistence/PersistenceImpl.ts +2 -2
- package/front_end/models/timeline_model/TimelineModel.ts +0 -48
- package/front_end/panels/application/AppManifestView.ts +3 -3
- package/front_end/panels/application/ApplicationPanelCacheSection.ts +3 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +11 -6
- package/front_end/panels/application/ApplicationPanelTreeElement.ts +2 -2
- package/front_end/panels/application/BackgroundServiceView.ts +5 -4
- package/front_end/panels/application/ResourcesPanel.ts +1 -1
- package/front_end/panels/console/ConsoleViewMessage.ts +6 -3
- package/front_end/panels/css_overview/components/CSSOverviewStartView.ts +3 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +19 -13
- package/front_end/panels/elements/StylesSidebarPane.ts +53 -0
- package/front_end/panels/elements/stylesSidebarPane.css +3 -0
- package/front_end/panels/issues/AffectedResourcesView.ts +4 -3
- package/front_end/panels/issues/AffectedSourcesView.ts +2 -1
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +9 -38
- package/front_end/panels/issues/IssueView.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseController.ts +6 -3
- package/front_end/panels/lighthouse/LighthouseReporterTypes.ts +2 -1
- package/front_end/panels/lighthouse/lighthousePanel.css +4 -0
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +2 -2
- package/front_end/panels/profiler/HeapSnapshotView.ts +2 -1
- package/front_end/panels/profiler/ProfileDataGrid.ts +1 -1
- package/front_end/panels/security/SecurityPanel.ts +6 -5
- package/front_end/panels/settings/SettingsScreen.ts +2 -3
- package/front_end/panels/sources/DebuggerPlugin.ts +10 -9
- package/front_end/panels/sources/JavaScriptBreakpointsSidebarPane.ts +3 -3
- package/front_end/panels/timeline/PerformanceModel.ts +2 -6
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +1 -14
- package/front_end/panels/timeline/TimelineUIUtils.ts +14 -12
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1036 -1088
- package/front_end/third_party/lighthouse/locales/en-US.json +244 -4
- package/front_end/third_party/lighthouse/locales/en-XL.json +244 -4
- package/front_end/third_party/lighthouse/report/bundle.d.ts +4 -22
- package/front_end/third_party/lighthouse/report/bundle.js +23 -366
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
- package/front_end/ui/components/docs/linkifier/simple-url.ts +2 -1
- package/front_end/ui/components/docs/panel_feedback/basic.ts +3 -2
- package/front_end/ui/components/docs/panel_feedback/button.ts +2 -1
- package/front_end/ui/components/linkifier/LinkifierImpl.ts +4 -3
- package/front_end/ui/components/linkifier/LinkifierUtils.ts +2 -3
- package/front_end/ui/components/panel_feedback/FeedbackButton.ts +4 -6
- package/front_end/ui/components/panel_feedback/PanelFeedback.ts +5 -4
- package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +3 -3
- package/front_end/ui/components/text_editor/javascript.ts +2 -2
- package/front_end/ui/legacy/EmptyWidget.ts +2 -1
- package/front_end/ui/legacy/UIUtils.ts +4 -4
- package/front_end/ui/legacy/XLink.ts +12 -13
- package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +2 -4
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +0 -2
- package/front_end/ui/legacy/components/utils/ImagePreview.ts +3 -7
- package/front_end/ui/legacy/components/utils/Linkifier.ts +23 -23
- package/front_end/ui/legacy/toolbar.css +1 -1
- package/package.json +1 -1
- package/scripts/whitespaces.txt +1 -0
- package/front_end/models/issues_manager/descriptions/arInvalidAttributionSourceEventId.md +0 -3
- package/front_end/models/issues_manager/descriptions/arInvalidAttributionSourceExpiry.md +0 -4
- package/front_end/models/issues_manager/descriptions/arInvalidAttributionSourcePriority.md +0 -4
@@ -5,6 +5,7 @@
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
6
6
|
import * as Host from '../../core/host/host.js';
|
7
7
|
import * as i18n from '../../core/i18n/i18n.js';
|
8
|
+
import type * as Platform from '../../core/platform/platform.js';
|
8
9
|
import type * as SDK from '../../core/sdk/sdk.js';
|
9
10
|
import type * as Protocol from '../../generated/protocol.js';
|
10
11
|
|
@@ -204,14 +205,17 @@ export abstract class Issue<IssueCode extends string = string> {
|
|
204
205
|
}
|
205
206
|
}
|
206
207
|
|
207
|
-
export function toZeroBasedLocation(location: Protocol.Audits.SourceCodeLocation|undefined):
|
208
|
-
|
209
|
-
|
208
|
+
export function toZeroBasedLocation(location: Protocol.Audits.SourceCodeLocation|undefined): {
|
209
|
+
url: Platform.DevToolsPath.UrlString,
|
210
|
+
scriptId: Protocol.Runtime.ScriptId|undefined,
|
211
|
+
lineNumber: number,
|
212
|
+
columnNumber: number|undefined,
|
213
|
+
}|undefined {
|
210
214
|
if (!location) {
|
211
215
|
return undefined;
|
212
216
|
}
|
213
217
|
return {
|
214
|
-
url: location.url,
|
218
|
+
url: location.url as Platform.DevToolsPath.UrlString,
|
215
219
|
scriptId: location.scriptId,
|
216
220
|
lineNumber: location.lineNumber,
|
217
221
|
columnNumber: location.columnNumber === 0 ? undefined : location.columnNumber - 1,
|
@@ -256,8 +256,8 @@ export class PersistenceImpl extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
256
256
|
Promise<void> {
|
257
257
|
const breakpoints = this.breakpointManager.breakpointLocationsForUISourceCode(from).map(
|
258
258
|
breakpointLocation => breakpointLocation.breakpoint);
|
259
|
-
await Promise.all(breakpoints.map(breakpoint => {
|
260
|
-
breakpoint.remove(false /* keepInStorage */);
|
259
|
+
await Promise.all(breakpoints.map(async breakpoint => {
|
260
|
+
await breakpoint.remove(false /* keepInStorage */);
|
261
261
|
return this.breakpointManager.setBreakpoint(
|
262
262
|
to, breakpoint.lineNumber(), breakpoint.columnNumber(), breakpoint.condition(), breakpoint.enabled());
|
263
263
|
}));
|
@@ -98,7 +98,6 @@ export class TimelineModelImpl {
|
|
98
98
|
private lastRecalculateStylesEvent!: SDK.TracingModel.Event|null;
|
99
99
|
private currentScriptEvent!: SDK.TracingModel.Event|null;
|
100
100
|
private eventStack!: SDK.TracingModel.Event[];
|
101
|
-
private knownInputEvents!: Set<string>;
|
102
101
|
private browserFrameTracking!: boolean;
|
103
102
|
private persistentIds!: boolean;
|
104
103
|
private legacyCurrentPage!: any;
|
@@ -573,7 +572,6 @@ export class TimelineModelImpl {
|
|
573
572
|
this.lastRecalculateStylesEvent = null;
|
574
573
|
this.currentScriptEvent = null;
|
575
574
|
this.eventStack = [];
|
576
|
-
this.knownInputEvents = new Set();
|
577
575
|
this.browserFrameTracking = false;
|
578
576
|
this.persistentIds = false;
|
579
577
|
this.legacyCurrentPage = null;
|
@@ -833,44 +831,6 @@ export class TimelineModelImpl {
|
|
833
831
|
group(TrackType.Animation).push(asyncEvent);
|
834
832
|
continue;
|
835
833
|
}
|
836
|
-
|
837
|
-
if (asyncEvent.hasCategory(TimelineModelImpl.Category.LatencyInfo) ||
|
838
|
-
asyncEvent.name === RecordType.ImplSideFling) {
|
839
|
-
const lastStep = asyncEvent.steps[asyncEvent.steps.length - 1];
|
840
|
-
if (!lastStep) {
|
841
|
-
throw new Error('AsyncEvent.steps access is out of bounds.');
|
842
|
-
}
|
843
|
-
if (lastStep.phase !== SDK.TracingModel.Phase.NestableAsyncEnd) {
|
844
|
-
continue;
|
845
|
-
}
|
846
|
-
const chromeLatencyInfo = asyncEvent.args['chrome_latency_info'];
|
847
|
-
|
848
|
-
const data = chromeLatencyInfo?.['component_info'];
|
849
|
-
asyncEvent.causedFrame =
|
850
|
-
Boolean(data?.some((c: any) => c['component_type'] === 'COMPONENT_INPUT_EVENT_LATENCY_RENDERER_SWAP'));
|
851
|
-
if (asyncEvent.hasCategory(TimelineModelImpl.Category.LatencyInfo)) {
|
852
|
-
if (lastStep.id && !this.knownInputEvents.has(chromeLatencyInfo.trace_id)) {
|
853
|
-
continue;
|
854
|
-
}
|
855
|
-
if (asyncEvent.name === RecordType.InputLatencyMouseMove && !asyncEvent.causedFrame) {
|
856
|
-
continue;
|
857
|
-
}
|
858
|
-
// Coalesced events are not really been processed, no need to track them.
|
859
|
-
if (!data || data['is_coalesced']) {
|
860
|
-
continue;
|
861
|
-
}
|
862
|
-
|
863
|
-
const rendererMain =
|
864
|
-
data?.find((c: any) => c['component_type'] === 'COMPONENT_INPUT_EVENT_LATENCY_RENDERER_MAIN');
|
865
|
-
if (rendererMain) {
|
866
|
-
const time = rendererMain['time_us'] / 1000;
|
867
|
-
TimelineData.forEvent(asyncEvent.steps[0]).timeWaitingForMainThread =
|
868
|
-
time - asyncEvent.steps[0].startTime;
|
869
|
-
}
|
870
|
-
}
|
871
|
-
group(TrackType.Input).push(asyncEvent);
|
872
|
-
continue;
|
873
|
-
}
|
874
834
|
}
|
875
835
|
}
|
876
836
|
|
@@ -1210,13 +1170,6 @@ export class TimelineModelImpl {
|
|
1210
1170
|
}
|
1211
1171
|
|
1212
1172
|
private processBrowserEvent(event: SDK.TracingModel.Event): void {
|
1213
|
-
if (event.name === RecordType.LatencyInfoFlow) {
|
1214
|
-
if (event.args.chrome_latency_info?.trace_id) {
|
1215
|
-
this.knownInputEvents.add(event.args.chrome_latency_info.trace_id);
|
1216
|
-
}
|
1217
|
-
return;
|
1218
|
-
}
|
1219
|
-
|
1220
1173
|
if (event.name === RecordType.ResourceWillSendRequest) {
|
1221
1174
|
const requestId = event.args?.data?.requestId;
|
1222
1175
|
if (typeof requestId === 'string') {
|
@@ -1715,7 +1668,6 @@ export class Track {
|
|
1715
1668
|
export enum TrackType {
|
1716
1669
|
MainThread = 'MainThread',
|
1717
1670
|
Worker = 'Worker',
|
1718
|
-
Input = 'Input',
|
1719
1671
|
Animation = 'Animation',
|
1720
1672
|
Timings = 'Timings',
|
1721
1673
|
Console = 'Console',
|
@@ -433,7 +433,7 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
433
433
|
.addChangeListener(this.updateManifest.bind(this, true));
|
434
434
|
|
435
435
|
this.emptyView = new UI.EmptyWidget.EmptyWidget(i18nString(UIStrings.noManifestDetected));
|
436
|
-
this.emptyView.appendLink('https://web.dev/add-manifest/');
|
436
|
+
this.emptyView.appendLink('https://web.dev/add-manifest/' as Platform.DevToolsPath.UrlString);
|
437
437
|
|
438
438
|
this.emptyView.show(this.contentElement);
|
439
439
|
this.emptyView.hideWidget();
|
@@ -693,7 +693,7 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
693
693
|
this.newNoteUrlField.parentElement?.classList.toggle('hidden', !hasNewNoteUrl);
|
694
694
|
this.newNoteUrlField.removeChildren();
|
695
695
|
if (hasNewNoteUrl) {
|
696
|
-
const completeURL = (Common.ParsedURL.ParsedURL.completeURL(url, newNoteUrl) as
|
696
|
+
const completeURL = (Common.ParsedURL.ParsedURL.completeURL(url, newNoteUrl) as Platform.DevToolsPath.UrlString);
|
697
697
|
const link = Components.Linkifier.Linkifier.linkifyURL(
|
698
698
|
completeURL, ({text: newNoteUrl} as Components.Linkifier.LinkifyURLOptions));
|
699
699
|
link.tabIndex = 0;
|
@@ -763,7 +763,7 @@ export class AppManifestView extends UI.Widget.VBox implements SDK.TargetManager
|
|
763
763
|
shortcutSection.appendFlexedField('Description', shortcut.description);
|
764
764
|
}
|
765
765
|
const urlField = shortcutSection.appendFlexedField('URL');
|
766
|
-
const shortcutUrl =
|
766
|
+
const shortcutUrl = Common.ParsedURL.ParsedURL.completeURL(url, shortcut.url) as Platform.DevToolsPath.UrlString;
|
767
767
|
const link = Components.Linkifier.Linkifier.linkifyURL(
|
768
768
|
shortcutUrl, ({text: shortcut.url} as Components.Linkifier.LinkifyURLOptions));
|
769
769
|
link.tabIndex = 0;
|
@@ -41,7 +41,9 @@ export class ServiceWorkerCacheTreeElement extends ExpandableApplicationPanelTre
|
|
41
41
|
constructor(resourcesPanel: ResourcesPanel) {
|
42
42
|
super(resourcesPanel, i18nString(UIStrings.cacheStorage), 'CacheStorage');
|
43
43
|
const icon = UI.Icon.Icon.create('mediumicon-database', 'resource-tree-item');
|
44
|
-
this.setLink(
|
44
|
+
this.setLink(
|
45
|
+
'https://developer.chrome.com/docs/devtools/storage/cache/?utm_source=devtools' as
|
46
|
+
Platform.DevToolsPath.UrlString);
|
45
47
|
this.setLeadingIcons([icon]);
|
46
48
|
this.swCacheModel = null;
|
47
49
|
this.swCacheTreeElements = new Set();
|
@@ -243,7 +243,8 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
243
243
|
this.localStorageListTreeElement =
|
244
244
|
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.localStorage), 'LocalStorage');
|
245
245
|
this.localStorageListTreeElement.setLink(
|
246
|
-
'https://developer.chrome.com/docs/devtools/storage/localstorage/?utm_source=devtools'
|
246
|
+
'https://developer.chrome.com/docs/devtools/storage/localstorage/?utm_source=devtools' as
|
247
|
+
Platform.DevToolsPath.UrlString);
|
247
248
|
const localStorageIcon = UI.Icon.Icon.create('mediumicon-table', 'resource-tree-item');
|
248
249
|
this.localStorageListTreeElement.setLeadingIcons([localStorageIcon]);
|
249
250
|
|
@@ -251,19 +252,22 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
251
252
|
this.sessionStorageListTreeElement =
|
252
253
|
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.sessionStorage), 'SessionStorage');
|
253
254
|
this.sessionStorageListTreeElement.setLink(
|
254
|
-
'https://developer.chrome.com/docs/devtools/storage/sessionstorage/?utm_source=devtools'
|
255
|
+
'https://developer.chrome.com/docs/devtools/storage/sessionstorage/?utm_source=devtools' as
|
256
|
+
Platform.DevToolsPath.UrlString);
|
255
257
|
const sessionStorageIcon = UI.Icon.Icon.create('mediumicon-table', 'resource-tree-item');
|
256
258
|
this.sessionStorageListTreeElement.setLeadingIcons([sessionStorageIcon]);
|
257
259
|
|
258
260
|
storageTreeElement.appendChild(this.sessionStorageListTreeElement);
|
259
261
|
this.indexedDBListTreeElement = new IndexedDBTreeElement(panel);
|
260
262
|
this.indexedDBListTreeElement.setLink(
|
261
|
-
'https://developer.chrome.com/docs/devtools/storage/indexeddb/?utm_source=devtools'
|
263
|
+
'https://developer.chrome.com/docs/devtools/storage/indexeddb/?utm_source=devtools' as
|
264
|
+
Platform.DevToolsPath.UrlString);
|
262
265
|
storageTreeElement.appendChild(this.indexedDBListTreeElement);
|
263
266
|
this.databasesListTreeElement =
|
264
267
|
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.webSql), 'Databases');
|
265
268
|
this.databasesListTreeElement.setLink(
|
266
|
-
'https://developer.chrome.com/docs/devtools/storage/websql/?utm_source=devtools'
|
269
|
+
'https://developer.chrome.com/docs/devtools/storage/websql/?utm_source=devtools' as
|
270
|
+
Platform.DevToolsPath.UrlString);
|
267
271
|
const databaseIcon = UI.Icon.Icon.create('mediumicon-database', 'resource-tree-item');
|
268
272
|
this.databasesListTreeElement.setLeadingIcons([databaseIcon]);
|
269
273
|
|
@@ -271,7 +275,8 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
|
|
271
275
|
this.cookieListTreeElement =
|
272
276
|
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.cookies), 'Cookies');
|
273
277
|
this.cookieListTreeElement.setLink(
|
274
|
-
'https://developer.chrome.com/docs/devtools/storage/cookies/?utm_source=devtools'
|
278
|
+
'https://developer.chrome.com/docs/devtools/storage/cookies/?utm_source=devtools' as
|
279
|
+
Platform.DevToolsPath.UrlString);
|
275
280
|
const cookieIcon = UI.Icon.Icon.create('mediumicon-cookie', 'resource-tree-item');
|
276
281
|
this.cookieListTreeElement.setLeadingIcons([cookieIcon]);
|
277
282
|
storageTreeElement.appendChild(this.cookieListTreeElement);
|
@@ -1505,7 +1510,7 @@ export class StorageCategoryView extends UI.Widget.VBox {
|
|
1505
1510
|
this.emptyWidget.text = text;
|
1506
1511
|
}
|
1507
1512
|
|
1508
|
-
setLink(link:
|
1513
|
+
setLink(link: Platform.DevToolsPath.UrlString|null): void {
|
1509
1514
|
if (link && !this.linkElement) {
|
1510
1515
|
this.linkElement = this.emptyWidget.appendLink(link);
|
1511
1516
|
}
|
@@ -47,7 +47,7 @@ export class ApplicationPanelTreeElement extends UI.TreeOutline.TreeElement {
|
|
47
47
|
export class ExpandableApplicationPanelTreeElement extends ApplicationPanelTreeElement {
|
48
48
|
protected readonly expandedSetting: Common.Settings.Setting<boolean>;
|
49
49
|
protected readonly categoryName: string;
|
50
|
-
protected categoryLink:
|
50
|
+
protected categoryLink: Platform.DevToolsPath.UrlString|null;
|
51
51
|
|
52
52
|
constructor(resourcesPanel: ResourcesPanel, categoryName: string, settingsKey: string, settingsDefault = false) {
|
53
53
|
super(resourcesPanel, categoryName, false);
|
@@ -61,7 +61,7 @@ export class ExpandableApplicationPanelTreeElement extends ApplicationPanelTreeE
|
|
61
61
|
return 'category://' + this.categoryName as Platform.DevToolsPath.UrlString;
|
62
62
|
}
|
63
63
|
|
64
|
-
setLink(link:
|
64
|
+
setLink(link: Platform.DevToolsPath.UrlString): void {
|
65
65
|
this.categoryLink = link;
|
66
66
|
}
|
67
67
|
|
@@ -2,17 +2,18 @@
|
|
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
4
|
|
5
|
-
// eslint-disable-next-line rulesdir/es_modules_import
|
6
|
-
import emptyWidgetStyles from '../../ui/legacy/emptyWidget.css.js';
|
7
|
-
import backgroundServiceViewStyles from './backgroundServiceView.css.js';
|
8
5
|
import type * as Common from '../../core/common/common.js';
|
9
6
|
import * as i18n from '../../core/i18n/i18n.js';
|
10
7
|
import * as Platform from '../../core/platform/platform.js';
|
11
8
|
import * as SDK from '../../core/sdk/sdk.js';
|
9
|
+
import * as Protocol from '../../generated/protocol.js';
|
12
10
|
import * as Bindings from '../../models/bindings/bindings.js';
|
13
11
|
import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';
|
12
|
+
// eslint-disable-next-line rulesdir/es_modules_import
|
13
|
+
import emptyWidgetStyles from '../../ui/legacy/emptyWidget.css.js';
|
14
14
|
import * as UI from '../../ui/legacy/legacy.js';
|
15
|
-
|
15
|
+
|
16
|
+
import backgroundServiceViewStyles from './backgroundServiceView.css.js';
|
16
17
|
|
17
18
|
import type {BackgroundServiceModel} from './BackgroundServiceModel.js';
|
18
19
|
import {Events} from './BackgroundServiceModel.js';
|
@@ -140,7 +140,7 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
|
|
140
140
|
return view;
|
141
141
|
}
|
142
142
|
|
143
|
-
showCategoryView(categoryName: string, categoryLink:
|
143
|
+
showCategoryView(categoryName: string, categoryLink: Platform.DevToolsPath.UrlString|null): void {
|
144
144
|
if (!this.categoryView) {
|
145
145
|
this.categoryView = new StorageCategoryView();
|
146
146
|
}
|
@@ -1439,7 +1439,8 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
|
|
1439
1439
|
}
|
1440
1440
|
|
1441
1441
|
// SyntaxErrors might not populate the URL field. Try to resolve it via scriptId.
|
1442
|
-
const url =
|
1442
|
+
const url =
|
1443
|
+
exceptionDetails.url as Platform.DevToolsPath.UrlString || debuggerModel.scriptForId(scriptId)?.sourceURL;
|
1443
1444
|
if (!url) {
|
1444
1445
|
return;
|
1445
1446
|
}
|
@@ -1531,7 +1532,9 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
|
|
1531
1532
|
}
|
1532
1533
|
|
1533
1534
|
private linkifyWithCustomLinkifier(
|
1534
|
-
string: string,
|
1535
|
+
string: string,
|
1536
|
+
linkifier: (arg0: string, arg1: Platform.DevToolsPath.UrlString, arg2?: number, arg3?: number) => Node):
|
1537
|
+
DocumentFragment {
|
1535
1538
|
if (string.length > getMaxTokenizableStringLength()) {
|
1536
1539
|
const propertyValue = new ObjectUI.ObjectPropertiesSection.ExpandableTextPropertyValue(
|
1537
1540
|
document.createElement('span'), string, getLongStringVisibleLength());
|
@@ -1563,7 +1566,7 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
|
|
1563
1566
|
if (splitResult) {
|
1564
1567
|
linkNode = linkifier(token.text, sourceURL, splitResult.lineNumber, splitResult.columnNumber);
|
1565
1568
|
} else {
|
1566
|
-
linkNode = linkifier(token.text,
|
1569
|
+
linkNode = linkifier(token.text, Platform.DevToolsPath.EmptyUrlString);
|
1567
1570
|
}
|
1568
1571
|
container.appendChild(linkNode);
|
1569
1572
|
break;
|
@@ -3,6 +3,7 @@
|
|
3
3
|
// found in the LICENSE file.
|
4
4
|
|
5
5
|
import * as i18n from '../../../core/i18n/i18n.js';
|
6
|
+
import type * as Platform from '../../../core/platform/platform.js';
|
6
7
|
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
7
8
|
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
8
9
|
import * as PanelFeedback from '../../../ui/components/panel_feedback/panel_feedback.js';
|
@@ -43,8 +44,8 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
43
44
|
|
44
45
|
const {render, html} = LitHtml;
|
45
46
|
|
46
|
-
const FEEDBACK_LINK = 'https://g.co/devtools/css-overview-feedback';
|
47
|
-
const DOC_LINK = 'https://developer.chrome.com/docs/devtools/css-overview';
|
47
|
+
const FEEDBACK_LINK = 'https://g.co/devtools/css-overview-feedback' as Platform.DevToolsPath.UrlString;
|
48
|
+
const DOC_LINK = 'https://developer.chrome.com/docs/devtools/css-overview' as Platform.DevToolsPath.UrlString;
|
48
49
|
export class OverviewStartRequestedEvent extends Event {
|
49
50
|
static readonly eventName = 'overviewstartrequested';
|
50
51
|
|
@@ -848,45 +848,46 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
848
848
|
return;
|
849
849
|
}
|
850
850
|
|
851
|
+
const contextMenu = this.createCopyContextMenu(event);
|
852
|
+
void contextMenu.show();
|
853
|
+
}
|
854
|
+
|
855
|
+
createCopyContextMenu(event: Event): UI.ContextMenu.ContextMenu {
|
851
856
|
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
852
|
-
contextMenu.
|
857
|
+
contextMenu.headerSection().appendItem(i18nString(UIStrings.copyDeclaration), () => {
|
853
858
|
const propertyText = `${this.property.name}: ${this.property.value};`;
|
854
859
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(propertyText);
|
855
860
|
Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.DeclarationViaContextMenu);
|
856
861
|
});
|
857
862
|
|
858
|
-
contextMenu.
|
863
|
+
contextMenu.headerSection().appendItem(i18nString(UIStrings.copyProperty), () => {
|
859
864
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.property.name);
|
860
865
|
Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.PropertyViaContextMenu);
|
861
866
|
});
|
862
867
|
|
863
|
-
contextMenu.
|
868
|
+
contextMenu.headerSection().appendItem(i18nString(UIStrings.copyValue), () => {
|
864
869
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.property.value);
|
865
870
|
Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.ValueViaContextMenu);
|
866
871
|
});
|
867
872
|
|
868
|
-
contextMenu.
|
873
|
+
contextMenu.headerSection().appendItem(i18nString(UIStrings.copyRule), () => {
|
869
874
|
const section = (this.section() as StylePropertiesSection);
|
870
875
|
const ruleText = StylesSidebarPane.formatLeadingProperties(section).ruleText;
|
871
876
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(ruleText);
|
872
877
|
Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.RuleViaContextMenu);
|
873
878
|
});
|
874
879
|
|
875
|
-
contextMenu.
|
880
|
+
contextMenu.headerSection().appendItem(
|
881
|
+
i18nString(UIStrings.copyCssDeclarationAsJs), this.copyCssDeclarationAsJs.bind(this));
|
882
|
+
|
883
|
+
contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copyAllDeclarations), () => {
|
876
884
|
const section = (this.section() as StylePropertiesSection);
|
877
885
|
const allDeclarationText = StylesSidebarPane.formatLeadingProperties(section).allDeclarationText;
|
878
886
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(allDeclarationText);
|
879
887
|
Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.AllDeclarationsViaContextMenu);
|
880
888
|
});
|
881
889
|
|
882
|
-
contextMenu.defaultSection().appendItem(i18nString(UIStrings.viewComputedValue), () => {
|
883
|
-
void this.viewComputedValue();
|
884
|
-
});
|
885
|
-
|
886
890
|
contextMenu.clipboardSection().appendItem(
|
887
|
-
i18nString(UIStrings.copyCssDeclarationAsJs), this.copyCssDeclarationAsJs.bind(this));
|
888
|
-
|
889
|
-
contextMenu.defaultSection().appendItem(
|
890
891
|
i18nString(UIStrings.copyAllCssDeclarationsAsJs), this.copyAllCssDeclarationAsJs.bind(this));
|
891
892
|
|
892
893
|
// TODO(changhaohan): conditionally add this item only when there are changes to copy
|
@@ -896,7 +897,11 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
896
897
|
Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.AllChangesViaStylesPane);
|
897
898
|
});
|
898
899
|
|
899
|
-
|
900
|
+
contextMenu.footerSection().appendItem(i18nString(UIStrings.viewComputedValue), () => {
|
901
|
+
void this.viewComputedValue();
|
902
|
+
});
|
903
|
+
|
904
|
+
return contextMenu;
|
900
905
|
}
|
901
906
|
|
902
907
|
private async viewComputedValue(): Promise<void> {
|
@@ -1513,6 +1518,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
1513
1518
|
}
|
1514
1519
|
if (updatedProperty) {
|
1515
1520
|
this.listItemElement.classList.toggle('changed', this.isPropertyChanged(updatedProperty));
|
1521
|
+
this.parentPane().updateChangeStatus();
|
1516
1522
|
}
|
1517
1523
|
|
1518
1524
|
this.matchedStylesInternal.resetActiveProperties();
|
@@ -147,6 +147,14 @@ const UIStrings = {
|
|
147
147
|
*/
|
148
148
|
automaticDarkMode: 'Automatic dark mode',
|
149
149
|
/**
|
150
|
+
*@description Tooltip text that appears when hovering over the css changes button in the Styles Sidebar Pane of the Elements panel
|
151
|
+
*/
|
152
|
+
copyAllCSSChanges: 'Copy all the CSS changes',
|
153
|
+
/**
|
154
|
+
*@description Tooltip text that appears after clicking on the copy CSS changes button
|
155
|
+
*/
|
156
|
+
copiedToClipboard: 'Copied to clipboard',
|
157
|
+
/**
|
150
158
|
*@description Text displayed on layer separators in the styles sidebar pane.
|
151
159
|
*/
|
152
160
|
layer: 'Layer',
|
@@ -207,6 +215,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
207
215
|
private readonly imagePreviewPopover: ImagePreviewPopover;
|
208
216
|
activeCSSAngle: InlineEditor.CSSAngle.CSSAngle|null;
|
209
217
|
#urlToChangeTracker: Map<Platform.DevToolsPath.UrlString, ChangeTracker> = new Map();
|
218
|
+
#copyChangesButton?: UI.Toolbar.ToolbarButton;
|
210
219
|
|
211
220
|
static instance(): StylesSidebarPane {
|
212
221
|
if (!stylesSidebarPaneInstance) {
|
@@ -579,6 +588,11 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
579
588
|
if (!this.initialUpdateCompleted) {
|
580
589
|
this.initialUpdateCompleted = true;
|
581
590
|
this.appendToolbarItem(this.createRenderingShortcuts());
|
591
|
+
if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES)) {
|
592
|
+
this.#copyChangesButton = this.createCopyAllChangesButton();
|
593
|
+
this.appendToolbarItem(this.#copyChangesButton);
|
594
|
+
this.#copyChangesButton.element.classList.add('hidden');
|
595
|
+
}
|
582
596
|
this.dispatchEventToListeners(Events.InitialUpdateCompleted);
|
583
597
|
}
|
584
598
|
|
@@ -1109,6 +1123,22 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
1109
1123
|
return changedLines.has(formattedLineNumber + 1);
|
1110
1124
|
}
|
1111
1125
|
|
1126
|
+
updateChangeStatus(): void {
|
1127
|
+
if (!this.#copyChangesButton) {
|
1128
|
+
return;
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
let hasChangedStyles = false;
|
1132
|
+
for (const changeTracker of this.#urlToChangeTracker.values()) {
|
1133
|
+
if (changeTracker.changedLines.size > 0) {
|
1134
|
+
hasChangedStyles = true;
|
1135
|
+
break;
|
1136
|
+
}
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
this.#copyChangesButton.element.classList.toggle('hidden', !hasChangedStyles);
|
1140
|
+
}
|
1141
|
+
|
1112
1142
|
private async refreshChangedLines(uiSourceCode: Workspace.UISourceCode.UISourceCode): Promise<void> {
|
1113
1143
|
const changeTracker = this.#urlToChangeTracker.get(uiSourceCode.url());
|
1114
1144
|
if (!changeTracker) {
|
@@ -1290,6 +1320,29 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
1290
1320
|
|
1291
1321
|
return button;
|
1292
1322
|
}
|
1323
|
+
|
1324
|
+
private createCopyAllChangesButton(): UI.Toolbar.ToolbarButton {
|
1325
|
+
const copyAllChangesButton =
|
1326
|
+
new UI.Toolbar.ToolbarButton(i18nString(UIStrings.copyAllCSSChanges), 'largeicon-copy');
|
1327
|
+
// TODO(1296947): implement a dedicated component to share between all copy buttons
|
1328
|
+
copyAllChangesButton.element.setAttribute('data-content', i18nString(UIStrings.copiedToClipboard));
|
1329
|
+
let timeout: number|undefined;
|
1330
|
+
copyAllChangesButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, async () => {
|
1331
|
+
const allChanges = await this.getFormattedChanges();
|
1332
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(allChanges);
|
1333
|
+
Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.AllChangesViaStylesPane);
|
1334
|
+
if (timeout) {
|
1335
|
+
clearTimeout(timeout);
|
1336
|
+
timeout = undefined;
|
1337
|
+
}
|
1338
|
+
copyAllChangesButton.element.classList.add('copied-to-clipboard');
|
1339
|
+
timeout = window.setTimeout(() => {
|
1340
|
+
copyAllChangesButton.element.classList.remove('copied-to-clipboard');
|
1341
|
+
timeout = undefined;
|
1342
|
+
}, 2000);
|
1343
|
+
});
|
1344
|
+
return copyAllChangesButton;
|
1345
|
+
}
|
1293
1346
|
}
|
1294
1347
|
|
1295
1348
|
export const enum Events {
|
@@ -232,6 +232,9 @@
|
|
232
232
|
|
233
233
|
.sidebar-pane-section-toolbar.new-rule-toolbar {
|
234
234
|
visibility: hidden;
|
235
|
+
margin-bottom: 5px;
|
236
|
+
|
237
|
+
--toolbar-height: 16px;
|
235
238
|
}
|
236
239
|
|
237
240
|
.styles-pane:not(.is-editing-style) .styles-section.matched-styles:not(.read-only):hover .sidebar-pane-section-toolbar.new-rule-toolbar {
|
@@ -5,6 +5,7 @@
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
6
6
|
import * as Host from '../../core/host/host.js';
|
7
7
|
import * as i18n from '../../core/i18n/i18n.js';
|
8
|
+
import type * as Platform from '../../core/platform/platform.js';
|
8
9
|
import * as SDK from '../../core/sdk/sdk.js';
|
9
10
|
import type * as IssuesManager from '../../models/issues_manager/issues_manager.js';
|
10
11
|
import * as Logs from '../../models/logs/logs.js';
|
@@ -44,7 +45,7 @@ export const enum AffectedItem {
|
|
44
45
|
Source = 'Source',
|
45
46
|
}
|
46
47
|
|
47
|
-
export const extractShortPath = (path:
|
48
|
+
export const extractShortPath = (path: Platform.DevToolsPath.UrlString): string => {
|
48
49
|
// 1st regex matches everything after last '/'
|
49
50
|
// if path ends with '/', 2nd regex returns everything between the last two '/'
|
50
51
|
return (/[^/]+$/.exec(path) || /[^/]+\/$/.exec(path) || [''])[0];
|
@@ -255,8 +256,8 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
|
|
255
256
|
// TODO(crbug.com/1108503): Add some mechanism to be able to add telemetry to this element.
|
256
257
|
const linkifier = new Components.Linkifier.Linkifier(maxLengthForDisplayedURLs);
|
257
258
|
const sourceAnchor = linkifier.linkifyScriptLocation(
|
258
|
-
target || null, sourceLocation.scriptId || null, sourceLocation.url
|
259
|
-
{columnNumber: sourceLocation.columnNumber, inlineFrameIndex: 0});
|
259
|
+
target || null, sourceLocation.scriptId || null, sourceLocation.url as Platform.DevToolsPath.UrlString,
|
260
|
+
sourceLocation.lineNumber, {columnNumber: sourceLocation.columnNumber, inlineFrameIndex: 0});
|
260
261
|
sourceCodeLocation.appendChild(sourceAnchor);
|
261
262
|
}
|
262
263
|
element.appendChild(sourceCodeLocation);
|
@@ -42,7 +42,8 @@ export class AffectedSourcesView extends AffectedResourcesView {
|
|
42
42
|
// Also, this element has a context menu, so we should be able to
|
43
43
|
// track when the user use the context menu too.
|
44
44
|
// TODO(crbug.com/1108503): Add some mechanism to be able to add telemetry to this element.
|
45
|
-
const anchorElement =
|
45
|
+
const anchorElement =
|
46
|
+
Components.Linkifier.Linkifier.linkifyURL(url as Platform.DevToolsPath.UrlString, linkifierURLOptions);
|
46
47
|
cellElement.appendChild(anchorElement);
|
47
48
|
const rowElement = document.createElement('tr');
|
48
49
|
rowElement.classList.add('affected-resource-source');
|
@@ -24,24 +24,13 @@ const UIStrings = {
|
|
24
24
|
*/
|
25
25
|
element: 'Element',
|
26
26
|
/**
|
27
|
-
* @description Noun, label for the column showing the
|
28
|
-
*/
|
29
|
-
request: 'Request',
|
30
|
-
/**
|
31
|
-
* @description Label for the column showing the invalid value used as the 'attributionsourceeventid' attribute
|
32
|
-
* on an anchor HTML element ("a link").
|
33
|
-
*/
|
34
|
-
invalidSourceEventId: 'Invalid `attributionsourceeventid`',
|
35
|
-
/**
|
36
|
-
* @description Label for the column showing the invalid value used as the 'attributionexpiry' attribute
|
37
|
-
* on an anchor HTML element ("a link").
|
27
|
+
* @description Noun, label for the column showing the invalid header value in the issue details table.
|
38
28
|
*/
|
39
|
-
|
29
|
+
invalidHeaderValue: 'Invalid Header Value',
|
40
30
|
/**
|
41
|
-
* @description
|
42
|
-
* on an anchor HTML element ("a link").
|
31
|
+
* @description Noun, label for the column showing the associated network request in the issue details table.
|
43
32
|
*/
|
44
|
-
|
33
|
+
request: 'Request',
|
45
34
|
/**
|
46
35
|
* @description Label for the column showing the invalid URL used in an HTML anchor element ("a link").
|
47
36
|
* A origin is (roughly said) the front part of a URL.
|
@@ -89,20 +78,10 @@ export class AttributionReportingIssueDetailsView extends AffectedResourcesView
|
|
89
78
|
this.appendColumnTitle(header, i18nString(UIStrings.element));
|
90
79
|
this.appendColumnTitle(header, i18nString(UIStrings.untrustworthyOrigin));
|
91
80
|
break;
|
92
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.
|
93
|
-
this.appendColumnTitle(header, i18nString(UIStrings.frame));
|
94
|
-
this.appendColumnTitle(header, i18nString(UIStrings.element));
|
95
|
-
this.appendColumnTitle(header, i18nString(UIStrings.invalidSourceEventId));
|
96
|
-
break;
|
97
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourceExpiry:
|
98
|
-
this.appendColumnTitle(header, i18nString(UIStrings.frame));
|
99
|
-
this.appendColumnTitle(header, i18nString(UIStrings.element));
|
100
|
-
this.appendColumnTitle(header, i18nString(UIStrings.invalidSourceExpiry));
|
101
|
-
break;
|
102
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourcePriority:
|
81
|
+
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidHeader:
|
103
82
|
this.appendColumnTitle(header, i18nString(UIStrings.frame));
|
104
|
-
this.appendColumnTitle(header, i18nString(UIStrings.
|
105
|
-
this.appendColumnTitle(header, i18nString(UIStrings.
|
83
|
+
this.appendColumnTitle(header, i18nString(UIStrings.request));
|
84
|
+
this.appendColumnTitle(header, i18nString(UIStrings.invalidHeaderValue));
|
106
85
|
break;
|
107
86
|
case IssuesManager.AttributionReportingIssue.IssueCode.PermissionPolicyDisabled:
|
108
87
|
this.appendColumnTitle(header, i18nString(UIStrings.frame));
|
@@ -129,11 +108,6 @@ export class AttributionReportingIssueDetailsView extends AffectedResourcesView
|
|
129
108
|
const details = issue.issueDetails;
|
130
109
|
|
131
110
|
switch (issueCode) {
|
132
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.AttributionUntrustworthyFrameOrigin:
|
133
|
-
this.#appendFrameOrEmptyCell(element, issue);
|
134
|
-
this.#appendRequestOrEmptyCell(element, details.request);
|
135
|
-
this.appendIssueDetailCell(element, details.invalidParameter || '');
|
136
|
-
break;
|
137
111
|
case IssuesManager.AttributionReportingIssue.IssueCode.AttributionSourceUntrustworthyOrigin:
|
138
112
|
await this.#appendElementOrEmptyCell(element, issue);
|
139
113
|
this.appendIssueDetailCell(element, details.invalidParameter || '');
|
@@ -142,12 +116,9 @@ export class AttributionReportingIssueDetailsView extends AffectedResourcesView
|
|
142
116
|
this.#appendRequestOrEmptyCell(element, details.request);
|
143
117
|
this.appendIssueDetailCell(element, details.invalidParameter || '');
|
144
118
|
break;
|
145
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.
|
146
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourceEventId:
|
147
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourceExpiry:
|
148
|
-
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourcePriority:
|
119
|
+
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidHeader:
|
149
120
|
this.#appendFrameOrEmptyCell(element, issue);
|
150
|
-
|
121
|
+
this.#appendRequestOrEmptyCell(element, details.request);
|
151
122
|
this.appendIssueDetailCell(element, details.invalidParameter || '');
|
152
123
|
break;
|
153
124
|
case IssuesManager.AttributionReportingIssue.IssueCode.PermissionPolicyDisabled:
|
@@ -181,7 +181,7 @@ class AffectedMixedContentView extends AffectedResourcesView {
|
|
181
181
|
},
|
182
182
|
}));
|
183
183
|
} else {
|
184
|
-
const filename = extractShortPath(mixedContent.insecureURL);
|
184
|
+
const filename = extractShortPath(mixedContent.insecureURL as Platform.DevToolsPath.UrlString);
|
185
185
|
const cell = this.appendIssueDetailCell(element, filename, 'affected-resource-mixed-content-info');
|
186
186
|
cell.title = mixedContent.insecureURL;
|
187
187
|
}
|