chrome-devtools-frontend 1.0.975056 → 1.0.975442

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.
Files changed (29) hide show
  1. package/config/gni/devtools_grd_files.gni +4 -0
  2. package/config/gni/devtools_image_files.gni +1 -0
  3. package/front_end/Images/src/ic_layers_16x16.svg +11 -0
  4. package/front_end/core/host/UserMetrics.ts +2 -1
  5. package/front_end/core/i18n/locales/en-US.json +13 -1
  6. package/front_end/core/i18n/locales/en-XL.json +13 -1
  7. package/front_end/core/root/Runtime.ts +1 -0
  8. package/front_end/core/sdk/CSSLayer.ts +30 -0
  9. package/front_end/core/sdk/CSSModel.ts +5 -0
  10. package/front_end/core/sdk/CSSRule.ts +3 -0
  11. package/front_end/core/sdk/sdk.ts +2 -0
  12. package/front_end/entrypoints/main/MainImpl.ts +5 -0
  13. package/front_end/generated/protocol.ts +6 -0
  14. package/front_end/panels/elements/LayersWidget.ts +167 -0
  15. package/front_end/panels/elements/StylesSidebarPane.ts +71 -3
  16. package/front_end/panels/elements/elements-meta.ts +15 -2
  17. package/front_end/panels/elements/elements.ts +2 -0
  18. package/front_end/panels/elements/layersWidget.css +28 -0
  19. package/front_end/panels/elements/stylesSidebarPane.css +4 -0
  20. package/front_end/panels/lighthouse/LighthouseController.ts +3 -3
  21. package/package.json +1 -1
  22. package/scripts/build/assert_grd.py +1 -1
  23. package/scripts/build/assert_third_party_readmes.py +1 -1
  24. package/scripts/build/build_inspector_overlay.py +1 -1
  25. package/scripts/build/code_generator_frontend.py +1 -1
  26. package/scripts/build/efficiently_recompile.py +1 -1
  27. package/scripts/build/generate_aria.py +2 -0
  28. package/scripts/build/generate_devtools_grd.py +1 -5
  29. package/scripts/build/generate_supported_css.py +6 -5
@@ -83,6 +83,7 @@ grd_files_release_sources = [
83
83
  "front_end/Images/ic_folder_local.svg",
84
84
  "front_end/Images/ic_folder_network.svg",
85
85
  "front_end/Images/ic_info_black_18dp.svg",
86
+ "front_end/Images/ic_layers_16x16.svg",
86
87
  "front_end/Images/ic_memory_16x16.svg",
87
88
  "front_end/Images/ic_page_next_16x16_icon.svg",
88
89
  "front_end/Images/ic_page_prev_16x16_icon.svg",
@@ -592,6 +593,7 @@ grd_files_debug_sources = [
592
593
  "front_end/core/sdk/CPUThrottlingManager.js",
593
594
  "front_end/core/sdk/CSSContainerQuery.js",
594
595
  "front_end/core/sdk/CSSFontFace.js",
596
+ "front_end/core/sdk/CSSLayer.js",
595
597
  "front_end/core/sdk/CSSMatchedStyles.js",
596
598
  "front_end/core/sdk/CSSMedia.js",
597
599
  "front_end/core/sdk/CSSMetadata.js",
@@ -934,6 +936,7 @@ grd_files_debug_sources = [
934
936
  "front_end/panels/elements/EventListenersWidget.js",
935
937
  "front_end/panels/elements/ImagePreviewPopover.js",
936
938
  "front_end/panels/elements/InspectElementModeController.js",
939
+ "front_end/panels/elements/LayersWidget.js",
937
940
  "front_end/panels/elements/LayoutSidebarPane.js",
938
941
  "front_end/panels/elements/MarkerDecorator.js",
939
942
  "front_end/panels/elements/MetricsSidebarPane.js",
@@ -979,6 +982,7 @@ grd_files_debug_sources = [
979
982
  "front_end/panels/elements/elementStatePaneWidget.css.js",
980
983
  "front_end/panels/elements/elementsPanel.css.js",
981
984
  "front_end/panels/elements/elementsTreeOutline.css.js",
985
+ "front_end/panels/elements/layersWidget.css.js",
982
986
  "front_end/panels/elements/layoutPane.css.js",
983
987
  "front_end/panels/elements/metricsSidebarPane.css.js",
984
988
  "front_end/panels/elements/nodeStackTraceWidget.css.js",
@@ -93,6 +93,7 @@ devtools_svg_sources = [
93
93
  "ic_folder_local.svg",
94
94
  "ic_folder_network.svg",
95
95
  "ic_info_black_18dp.svg",
96
+ "ic_layers_16x16.svg",
96
97
  "ic_memory_16x16.svg",
97
98
  "ic_page_next_16x16_icon.svg",
98
99
  "ic_page_prev_16x16_icon.svg",
@@ -0,0 +1,11 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_101_638)">
3
+ <path d="M5.34247 8.54807L2.42415 9.82267C1.94959 10.0299 1.94959 10.859 2.42415 11.0663L7.822 13.4239C7.93714 13.4742 8.06277 13.4742 8.17792 13.4239L13.576 11.0663C14.0506 10.859 14.0506 10.0299 13.576 9.82266L10.6576 8.54803L9.05598 9.24755L11.7964 10.4445L7.99996 12.1026L4.20373 10.4445L6.9441 9.24761L5.34247 8.54807Z" fill="black"/>
4
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M4.20374 5.15001L7.99997 6.80809L11.7964 5.14999L8.0001 3.49191L4.20374 5.15001ZM2.42415 4.5282C1.94959 4.73547 1.94959 5.56454 2.42415 5.77181L7.822 8.12942C7.93715 8.17972 8.06277 8.17972 8.17792 8.12943L13.576 5.7718C14.0506 5.56453 14.0506 4.73546 13.576 4.52819L8.17806 2.17057C8.06291 2.12028 7.93729 2.12028 7.82214 2.17058L2.42415 4.5282Z" fill="black"/>
5
+ </g>
6
+ <defs>
7
+ <clipPath id="clip0_101_638">
8
+ <rect width="16" height="16" rx="2" fill="white"/>
9
+ </clipPath>
10
+ </defs>
11
+ </svg>
@@ -588,8 +588,9 @@ export enum DevtoolsExperiments {
588
588
  'headerOverrides' = 56,
589
589
  'lighthousePanelFR' = 57,
590
590
  'evaluateExpressionsWithSourceMaps' = 58,
591
+ 'cssLayers' = 59,
591
592
  // Increment this when new experiments are added.
592
- 'MaxValue' = 59,
593
+ 'MaxValue' = 60,
593
594
  }
594
595
  /* eslint-enable @typescript-eslint/naming-convention */
595
596
 
@@ -4751,6 +4751,12 @@
4751
4751
  "panels/elements/EventListenersWidget.ts | showListenersOnTheAncestors": {
4752
4752
  "message": "Show listeners on the ancestors"
4753
4753
  },
4754
+ "panels/elements/LayersWidget.ts | cssLayersTitle": {
4755
+ "message": "CSS layers"
4756
+ },
4757
+ "panels/elements/LayersWidget.ts | toggleCSSLayers": {
4758
+ "message": "Toggle CSS Layers view"
4759
+ },
4754
4760
  "panels/elements/MarkerDecorator.ts | domBreakpoint": {
4755
4761
  "message": "DOM Breakpoint"
4756
4762
  },
@@ -4832,6 +4838,9 @@
4832
4838
  "panels/elements/StylePropertyTreeElement.ts | viewComputedValue": {
4833
4839
  "message": "View computed value"
4834
4840
  },
4841
+ "panels/elements/StylesSidebarPane.ts | clickToRevealLayer": {
4842
+ "message": "Click to reveal layer in layer tree"
4843
+ },
4835
4844
  "panels/elements/StylesSidebarPane.ts | constructedStylesheet": {
4836
4845
  "message": "constructed stylesheet"
4837
4846
  },
@@ -4886,6 +4895,9 @@
4886
4895
  "panels/elements/StylesSidebarPane.ts | invalidString": {
4887
4896
  "message": "{PH1}, property name: {PH2}, property value: {PH3}"
4888
4897
  },
4898
+ "panels/elements/StylesSidebarPane.ts | layer": {
4899
+ "message": "Layer"
4900
+ },
4889
4901
  "panels/elements/StylesSidebarPane.ts | newStyleRule": {
4890
4902
  "message": "New Style Rule"
4891
4903
  },
@@ -5823,7 +5835,7 @@
5823
5835
  "message": "Timespan"
5824
5836
  },
5825
5837
  "panels/lighthouse/LighthouseController.ts | useLegacyNavigation": {
5826
- "message": "Audit the page using classic Lighthouse when in navigation mode."
5838
+ "message": "Analyze the page using classic Lighthouse when in navigation mode."
5827
5839
  },
5828
5840
  "panels/lighthouse/LighthouseController.ts | webSql": {
5829
5841
  "message": "Web SQL"
@@ -4751,6 +4751,12 @@
4751
4751
  "panels/elements/EventListenersWidget.ts | showListenersOnTheAncestors": {
4752
4752
  "message": "Ŝh́ôẃ l̂íŝt́êńêŕŝ ón̂ t́ĥé âńĉéŝt́ôŕŝ"
4753
4753
  },
4754
+ "panels/elements/LayersWidget.ts | cssLayersTitle": {
4755
+ "message": "ĈŚŜ ĺâýêŕŝ"
4756
+ },
4757
+ "panels/elements/LayersWidget.ts | toggleCSSLayers": {
4758
+ "message": "T̂óĝǵl̂é ĈŚŜ Ĺâýêŕŝ v́îéŵ"
4759
+ },
4754
4760
  "panels/elements/MarkerDecorator.ts | domBreakpoint": {
4755
4761
  "message": "D̂ÓM̂ B́r̂éâḱp̂óîńt̂"
4756
4762
  },
@@ -4832,6 +4838,9 @@
4832
4838
  "panels/elements/StylePropertyTreeElement.ts | viewComputedValue": {
4833
4839
  "message": "V̂íêẃ ĉóm̂ṕût́êd́ v̂ál̂úê"
4834
4840
  },
4841
+ "panels/elements/StylesSidebarPane.ts | clickToRevealLayer": {
4842
+ "message": "Ĉĺîćk̂ t́ô ŕêv́êál̂ ĺâýêŕ îń l̂áŷér̂ t́r̂éê"
4843
+ },
4835
4844
  "panels/elements/StylesSidebarPane.ts | constructedStylesheet": {
4836
4845
  "message": "ĉón̂śt̂ŕûćt̂éd̂ śt̂ýl̂éŝh́êét̂"
4837
4846
  },
@@ -4886,6 +4895,9 @@
4886
4895
  "panels/elements/StylesSidebarPane.ts | invalidString": {
4887
4896
  "message": "{PH1}, p̂ŕôṕêŕt̂ý n̂ám̂é: {PH2}, p̂ŕôṕêŕt̂ý v̂ál̂úê: {PH3}"
4888
4897
  },
4898
+ "panels/elements/StylesSidebarPane.ts | layer": {
4899
+ "message": "L̂áŷér̂"
4900
+ },
4889
4901
  "panels/elements/StylesSidebarPane.ts | newStyleRule": {
4890
4902
  "message": "N̂éŵ Śt̂ýl̂é R̂úl̂é"
4891
4903
  },
@@ -5823,7 +5835,7 @@
5823
5835
  "message": "T̂ím̂éŝṕâń"
5824
5836
  },
5825
5837
  "panels/lighthouse/LighthouseController.ts | useLegacyNavigation": {
5826
- "message": "Âúd̂ít̂ t́ĥé p̂áĝé ûśîńĝ ćl̂áŝśîć L̂íĝh́t̂h́ôúŝé ŵh́êń îń n̂áv̂íĝát̂íôń m̂ód̂é."
5838
+ "message": "Âńâĺŷźê t́ĥé p̂áĝé ûśîńĝ ćl̂áŝśîć L̂íĝh́t̂h́ôúŝé ŵh́êń îń n̂áv̂íĝát̂íôń m̂ód̂é."
5827
5839
  },
5828
5840
  "panels/lighthouse/LighthouseController.ts | webSql": {
5829
5841
  "message": "Ŵéb̂ ŚQ̂Ĺ"
@@ -275,6 +275,7 @@ export enum ExperimentName {
275
275
  PRECISE_CHANGES = 'preciseChanges',
276
276
  STYLES_PANE_CSS_CHANGES = 'stylesPaneCSSChanges',
277
277
  HEADER_OVERRIDES = 'headerOverrides',
278
+ CSS_LAYERS = 'cssLayers',
278
279
  }
279
280
 
280
281
  // TODO(crbug.com/1167717): Make this a const enum again
@@ -0,0 +1,30 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as TextUtils from '../../models/text_utils/text_utils.js';
6
+ import type * as Protocol from '../../generated/protocol.js';
7
+
8
+ import type {CSSModel} from './CSSModel.js';
9
+ import {CSSQuery} from './CSSQuery.js';
10
+
11
+ export class CSSLayer extends CSSQuery {
12
+ static parseLayerPayload(cssModel: CSSModel, payload: Protocol.CSS.CSSLayer[]): CSSLayer[] {
13
+ return payload.map(supports => new CSSLayer(cssModel, supports));
14
+ }
15
+
16
+ constructor(cssModel: CSSModel, payload: Protocol.CSS.CSSLayer) {
17
+ super(cssModel);
18
+ this.reinitialize(payload);
19
+ }
20
+
21
+ reinitialize(payload: Protocol.CSS.CSSLayer): void {
22
+ this.text = payload.text;
23
+ this.range = payload.range ? TextUtils.TextRange.TextRange.fromObject(payload.range) : null;
24
+ this.styleSheetId = payload.styleSheetId;
25
+ }
26
+
27
+ active(): boolean {
28
+ return true;
29
+ }
30
+ }
@@ -266,6 +266,11 @@ export class CSSModel extends SDKModel<EventTypes> {
266
266
  return medias ? CSSMedia.parseMediaArrayPayload(this, medias) : [];
267
267
  }
268
268
 
269
+ async rootLayerPromise(nodeId: Protocol.DOM.NodeId): Promise<Protocol.CSS.CSSLayerData> {
270
+ const {rootLayer} = await this.agent.invoke_getLayersForNode({nodeId});
271
+ return rootLayer;
272
+ }
273
+
269
274
  isEnabled(): boolean {
270
275
  return this.#isEnabled;
271
276
  }
@@ -6,6 +6,7 @@ import * as Protocol from '../../generated/protocol.js';
6
6
  import * as TextUtils from '../../models/text_utils/text_utils.js';
7
7
 
8
8
  import {CSSContainerQuery} from './CSSContainerQuery.js';
9
+ import {CSSLayer} from './CSSLayer.js';
9
10
  import {CSSMedia} from './CSSMedia.js';
10
11
  import {CSSSupports} from './CSSSupports.js';
11
12
 
@@ -101,6 +102,7 @@ export class CSSStyleRule extends CSSRule {
101
102
  media: CSSMedia[];
102
103
  containerQueries: CSSContainerQuery[];
103
104
  supports: CSSSupports[];
105
+ layers: CSSLayer[];
104
106
  wasUsed: boolean;
105
107
  constructor(cssModel: CSSModel, payload: Protocol.CSS.CSSRule, wasUsed?: boolean) {
106
108
  // TODO(crbug.com/1011811): Replace with spread operator or better types once Closure is gone.
@@ -111,6 +113,7 @@ export class CSSStyleRule extends CSSRule {
111
113
  CSSContainerQuery.parseContainerQueriesPayload(cssModel, payload.containerQueries) :
112
114
  [];
113
115
  this.supports = payload.supports ? CSSSupports.parseSupportsPayload(cssModel, payload.supports) : [];
116
+ this.layers = payload.layers ? CSSLayer.parseLayerPayload(cssModel, payload.layers) : [];
114
117
  this.wasUsed = wasUsed || false;
115
118
  }
116
119
 
@@ -24,6 +24,7 @@ import * as CPUProfilerModel from './CPUProfilerModel.js';
24
24
  import * as CPUThrottlingManager from './CPUThrottlingManager.js';
25
25
  import * as CSSContainerQuery from './CSSContainerQuery.js';
26
26
  import * as CSSFontFace from './CSSFontFace.js';
27
+ import * as CSSLayer from './CSSLayer.js';
27
28
  import * as CSSMatchedStyles from './CSSMatchedStyles.js';
28
29
  import * as CSSMedia from './CSSMedia.js';
29
30
  import * as CSSMetadata from './CSSMetadata.js';
@@ -92,6 +93,7 @@ export {
92
93
  CPUThrottlingManager,
93
94
  CSSContainerQuery,
94
95
  CSSFontFace,
96
+ CSSLayer,
95
97
  CSSMatchedStyles,
96
98
  CSSMedia,
97
99
  CSSMetadata,
@@ -384,6 +384,10 @@ export class MainImpl {
384
384
  // New Lighthouse panel with timespan and snapshot mode
385
385
  Root.Runtime.experiments.register('lighthousePanelFR', 'Use Lighthouse panel with timespan and snapshot modes');
386
386
 
387
+ // Tooling for CSS layers in Styles sidebar pane.
388
+ Root.Runtime.experiments.register(
389
+ Root.Runtime.ExperimentName.CSS_LAYERS, 'Tooling for CSS layers in the Styles pane');
390
+
387
391
  Root.Runtime.experiments.enableExperimentsByDefault([
388
392
  'sourceOrderViewer',
389
393
  'hideIssuesFeature',
@@ -391,6 +395,7 @@ export class MainImpl {
391
395
  Root.Runtime.ExperimentName.PRECISE_CHANGES,
392
396
  'reportingApiDebugging',
393
397
  Root.Runtime.ExperimentName.SYNC_SETTINGS,
398
+ Root.Runtime.ExperimentName.CSS_LAYERS,
394
399
  ]);
395
400
 
396
401
  Root.Runtime.experiments.cleanUpStaleExperiments();
@@ -10869,6 +10869,12 @@ export namespace Page {
10869
10869
  * Not restored reason
10870
10870
  */
10871
10871
  reason: BackForwardCacheNotRestoredReason;
10872
+ /**
10873
+ * Context associated with the reason. The meaning of this context is
10874
+ * dependent on the reason:
10875
+ * - EmbedderExtensionSentMessageToCachedFrame: the extension ID.
10876
+ */
10877
+ context?: string;
10872
10878
  }
10873
10879
 
10874
10880
  export interface BackForwardCacheNotRestoredExplanationTree {
@@ -0,0 +1,167 @@
1
+ // Copyright (c) 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as i18n from '../../core/i18n/i18n.js';
6
+ import * as SDK from '../../core/sdk/sdk.js';
7
+ import * as UI from '../../ui/legacy/legacy.js';
8
+ import type * as Protocol from '../../generated/protocol.js';
9
+ import * as TreeOutline from '../../ui/components/tree_outline/tree_outline.js';
10
+
11
+ import {ElementsPanel} from './ElementsPanel.js';
12
+ import layersWidgetStyles from './layersWidget.css.js';
13
+ import * as IconButton from '../../ui/components/icon_button/icon_button.js';
14
+
15
+ const UIStrings = {
16
+ /**
17
+ * @description Title of a section in the Element State Pane Widget of the Elements panel.
18
+ * The widget shows the layers present in the context of the currently selected node.
19
+ * */
20
+ cssLayersTitle: 'CSS layers',
21
+ /**
22
+ * @description Tooltip text in Element State Pane Widget of the Elements panel.
23
+ * For a button that opens a tool that shows the layers present in the current document.
24
+ */
25
+ toggleCSSLayers: 'Toggle CSS Layers view',
26
+ };
27
+ const str_ = i18n.i18n.registerUIStrings('panels/elements/LayersWidget.ts', UIStrings);
28
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
29
+
30
+ let layersWidgetInstance: LayersWidget;
31
+
32
+ export class LayersWidget extends UI.Widget.Widget {
33
+ private cssModel?: SDK.CSSModel.CSSModel|null;
34
+ private layerTreeComponent = new TreeOutline.TreeOutline.TreeOutline<string>();
35
+
36
+ constructor() {
37
+ super(true);
38
+
39
+ this.contentElement.className = 'styles-layers-pane';
40
+ UI.UIUtils.createTextChild(this.contentElement.createChild('div'), i18nString(UIStrings.cssLayersTitle));
41
+
42
+ this.contentElement.appendChild(this.layerTreeComponent);
43
+
44
+ UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.update, this);
45
+ }
46
+
47
+ private updateModel(cssModel: SDK.CSSModel.CSSModel|null): void {
48
+ if (this.cssModel === cssModel) {
49
+ return;
50
+ }
51
+ if (this.cssModel) {
52
+ this.cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetChanged, this.update, this);
53
+ }
54
+ this.cssModel = cssModel;
55
+ if (this.cssModel) {
56
+ this.cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetChanged, this.update, this);
57
+ }
58
+ }
59
+
60
+ async wasShown(): Promise<void> {
61
+ super.wasShown();
62
+ this.registerCSSFiles([layersWidgetStyles]);
63
+ return this.update();
64
+ }
65
+
66
+ private async update(): Promise<void> {
67
+ if (!this.isShowing()) {
68
+ return;
69
+ }
70
+
71
+ let node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
72
+ if (node) {
73
+ node = node.enclosingElementOrSelf();
74
+ }
75
+ if (!node) {
76
+ // do something meaningful?
77
+ return;
78
+ }
79
+
80
+ this.updateModel(node.domModel().cssModel());
81
+ if (!this.cssModel) {
82
+ return;
83
+ }
84
+ const makeTreeNode = (parentId: string) =>
85
+ (layer: Protocol.CSS.CSSLayerData): TreeOutline.TreeOutlineUtils.TreeNode<string> => {
86
+ const subLayers = layer.subLayers;
87
+ const treeNodeData = layer.order + ': ' + layer.name;
88
+ const id = parentId ? parentId + '.' + layer.name : layer.name;
89
+ if (!subLayers) {
90
+ return {treeNodeData, id};
91
+ }
92
+ return {
93
+ treeNodeData,
94
+ id,
95
+ children: (): Promise<TreeOutline.TreeOutlineUtils.TreeNode<string>[]> =>
96
+ Promise.resolve(subLayers.sort((layer1, layer2) => layer1.order - layer2.order).map(makeTreeNode(id))),
97
+ };
98
+ };
99
+ const rootLayer = await this.cssModel.rootLayerPromise(node.id);
100
+ this.layerTreeComponent.data = {
101
+ defaultRenderer: TreeOutline.TreeOutline.defaultRenderer,
102
+ tree: [makeTreeNode('')(rootLayer)],
103
+ };
104
+
105
+ // We only expand the first 5 user-defined layers to not make the
106
+ // view too overwhelming.
107
+ await this.layerTreeComponent.expandRecursively(5);
108
+ }
109
+
110
+ async revealLayer(layerName: string): Promise<void> {
111
+ if (!this.isShowing()) {
112
+ ElementsPanel.instance().showToolbarPane(this, ButtonProvider.instance().item());
113
+ }
114
+ await this.update();
115
+ return this.layerTreeComponent.expandToAndSelectTreeNodeId('implicit outer layer.' + layerName);
116
+ }
117
+
118
+ static instance(opts: {
119
+ forceNew: boolean|null,
120
+ }|undefined = {forceNew: null}): LayersWidget {
121
+ const {forceNew} = opts;
122
+ if (!layersWidgetInstance || forceNew) {
123
+ layersWidgetInstance = new LayersWidget();
124
+ }
125
+
126
+ return layersWidgetInstance;
127
+ }
128
+ }
129
+
130
+ let buttonProviderInstance: ButtonProvider;
131
+
132
+ export class ButtonProvider implements UI.Toolbar.Provider {
133
+ private readonly button: UI.Toolbar.ToolbarToggle;
134
+ private constructor() {
135
+ const layersIcon = new IconButton.Icon.Icon();
136
+ layersIcon.data = {
137
+ iconName: 'ic_layers_16x16',
138
+ color: 'var(--color-text-secondary)',
139
+ width: '13px',
140
+ height: '13px',
141
+ };
142
+ this.button = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.toggleCSSLayers), layersIcon);
143
+ this.button.setVisible(false);
144
+ this.button.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this.clicked, this);
145
+ this.button.element.classList.add('monospace');
146
+ }
147
+
148
+ static instance(opts: {
149
+ forceNew: boolean|null,
150
+ } = {forceNew: null}): ButtonProvider {
151
+ const {forceNew} = opts;
152
+ if (!buttonProviderInstance || forceNew) {
153
+ buttonProviderInstance = new ButtonProvider();
154
+ }
155
+
156
+ return buttonProviderInstance;
157
+ }
158
+
159
+ private clicked(): void {
160
+ const view = LayersWidget.instance();
161
+ ElementsPanel.instance().showToolbarPane(!view.isShowing() ? view : null, this.button);
162
+ }
163
+
164
+ item(): UI.Toolbar.ToolbarToggle {
165
+ return this.button;
166
+ }
167
+ }
@@ -65,6 +65,7 @@ import stylesSidebarPaneStyles from './stylesSidebarPane.css.js';
65
65
 
66
66
  import type {Context} from './StylePropertyTreeElement.js';
67
67
  import {StylePropertyTreeElement} from './StylePropertyTreeElement.js';
68
+ import * as LayersWidget from './LayersWidget.js';
68
69
 
69
70
  const UIStrings = {
70
71
  /**
@@ -187,6 +188,14 @@ const UIStrings = {
187
188
  *@description Tooltip text that appears after clicking on the copy CSS changes button
188
189
  */
189
190
  copiedToClipboard: 'Copied to clipboard',
191
+ /**
192
+ *@description Text displayed on layer separators in the styles sidebar pane.
193
+ */
194
+ layer: 'Layer',
195
+ /**
196
+ *@description Tooltip text for the link in the sidebar pane layer separators that reveals the layer in the layer tree view.
197
+ */
198
+ clickToRevealLayer: 'Click to reveal layer in layer tree',
190
199
  };
191
200
 
192
201
  const str_ = i18n.i18n.registerUIStrings('panels/elements/StylesSidebarPane.ts', UIStrings);
@@ -853,6 +862,31 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
853
862
  const blocks = [new SectionBlock(null)];
854
863
  let sectionIdx = 0;
855
864
  let lastParentNode: SDK.DOMModel.DOMNode|null = null;
865
+
866
+ let lastLayers: SDK.CSSLayer.CSSLayer[]|null = null;
867
+ let sawLayers: boolean = false;
868
+
869
+ const layersExperimentEnabled = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CSS_LAYERS);
870
+ const addLayerSeparator = (style: SDK.CSSStyleDeclaration.CSSStyleDeclaration): void => {
871
+ if (!layersExperimentEnabled) {
872
+ return;
873
+ }
874
+ const parentRule = style.parentRule;
875
+ if (parentRule instanceof SDK.CSSRule.CSSStyleRule) {
876
+ const layers = parentRule.layers;
877
+ if ((layers.length || lastLayers) && lastLayers !== layers) {
878
+ const block = SectionBlock.createLayerBlock(layers);
879
+ blocks.push(block);
880
+ sawLayers = true;
881
+ lastLayers = layers;
882
+ }
883
+ }
884
+ };
885
+
886
+ // We disable the layer widget initially. If we see a layer in
887
+ // the matched styles we reenable the button.
888
+ LayersWidget.ButtonProvider.instance().item().setVisible(false);
889
+
856
890
  const refreshedURLs = new Set<string>();
857
891
  for (const style of matchedStyles.nodeStyles()) {
858
892
  if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES) && style.parentRule) {
@@ -870,6 +904,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
870
904
  blocks.push(block);
871
905
  }
872
906
 
907
+ addLayerSeparator(style);
908
+
873
909
  const lastBlock = blocks[blocks.length - 1];
874
910
  if (lastBlock) {
875
911
  this.idleCallbackManager.schedule(() => {
@@ -887,15 +923,18 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
887
923
  }
888
924
  pseudoTypes = pseudoTypes.concat([...keys].sort());
889
925
  for (const pseudoType of pseudoTypes) {
890
- const block = SectionBlock.createPseudoTypeBlock(pseudoType);
926
+ blocks.push(SectionBlock.createPseudoTypeBlock(pseudoType));
927
+ lastLayers = null;
928
+
891
929
  for (const style of matchedStyles.pseudoStyles(pseudoType)) {
930
+ addLayerSeparator(style);
931
+ const lastBlock = blocks[blocks.length - 1];
892
932
  this.idleCallbackManager.schedule(() => {
893
933
  const section = new StylePropertiesSection(this, matchedStyles, style, sectionIdx);
894
934
  sectionIdx++;
895
- block.sections.push(section);
935
+ lastBlock.sections.push(section);
896
936
  });
897
937
  }
898
- blocks.push(block);
899
938
  }
900
939
 
901
940
  for (const keyframesRule of matchedStyles.keyframes()) {
@@ -909,6 +948,18 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
909
948
  blocks.push(block);
910
949
  }
911
950
 
951
+ if (layersExperimentEnabled) {
952
+ // If we have seen a layer in matched styles we enable
953
+ // the layer widget button.
954
+ if (sawLayers) {
955
+ LayersWidget.ButtonProvider.instance().item().setVisible(true);
956
+ } else if (LayersWidget.LayersWidget.instance().isShowing()) {
957
+ // Since the button for toggling the layers view is now hidden
958
+ // we ensure that the layers view is not currently toggled.
959
+ ElementsPanel.instance().showToolbarPane(null, LayersWidget.ButtonProvider.instance().item());
960
+ }
961
+ }
962
+
912
963
  await this.idleCallbackManager.awaitDone();
913
964
 
914
965
  return blocks;
@@ -1379,6 +1430,23 @@ export class SectionBlock {
1379
1430
  return new SectionBlock(separatorElement);
1380
1431
  }
1381
1432
 
1433
+ static createLayerBlock(layers: SDK.CSSLayer.CSSLayer[]): SectionBlock {
1434
+ const separatorElement = document.createElement('div');
1435
+ separatorElement.className = 'sidebar-separator layer-separator';
1436
+ UI.UIUtils.createTextChild(separatorElement.createChild('div'), i18nString(UIStrings.layer));
1437
+ if (!layers.length) {
1438
+ UI.UIUtils.createTextChild(separatorElement.createChild('div'), '\xa0user\xa0agent\xa0stylesheet');
1439
+ return new SectionBlock(separatorElement);
1440
+ }
1441
+ const layerLink = separatorElement.createChild('button') as HTMLButtonElement;
1442
+ layerLink.className = 'link';
1443
+ layerLink.title = i18nString(UIStrings.clickToRevealLayer);
1444
+ const name = layers.map(layer => layer.text || '<anonymous>').join('.');
1445
+ layerLink.textContent = name;
1446
+ layerLink.onclick = (): Promise<void> => LayersWidget.LayersWidget.instance().revealLayer(name);
1447
+ return new SectionBlock(separatorElement);
1448
+ }
1449
+
1382
1450
  updateFilter(): boolean {
1383
1451
  let hasAnyVisibleSection = false;
1384
1452
  for (const section of this.sections) {
@@ -513,7 +513,7 @@ Common.Revealer.registerRevealer({
513
513
  UI.Toolbar.registerToolbarItem({
514
514
  async loadItem() {
515
515
  const Elements = await loadElementsModule();
516
- return Elements.ElementStatePaneWidget.ButtonProvider.instance();
516
+ return Elements.LayersWidget.ButtonProvider.instance();
517
517
  },
518
518
  order: 1,
519
519
  location: UI.Toolbar.ToolbarItemLocation.STYLES_SIDEBARPANE_TOOLBAR,
@@ -526,7 +526,7 @@ UI.Toolbar.registerToolbarItem({
526
526
  UI.Toolbar.registerToolbarItem({
527
527
  async loadItem() {
528
528
  const Elements = await loadElementsModule();
529
- return Elements.ClassesPaneWidget.ButtonProvider.instance();
529
+ return Elements.ElementStatePaneWidget.ButtonProvider.instance();
530
530
  },
531
531
  order: 2,
532
532
  location: UI.Toolbar.ToolbarItemLocation.STYLES_SIDEBARPANE_TOOLBAR,
@@ -536,6 +536,19 @@ UI.Toolbar.registerToolbarItem({
536
536
  actionId: undefined,
537
537
  });
538
538
 
539
+ UI.Toolbar.registerToolbarItem({
540
+ async loadItem() {
541
+ const Elements = await loadElementsModule();
542
+ return Elements.ClassesPaneWidget.ButtonProvider.instance();
543
+ },
544
+ order: 3,
545
+ location: UI.Toolbar.ToolbarItemLocation.STYLES_SIDEBARPANE_TOOLBAR,
546
+ showLabel: undefined,
547
+ condition: undefined,
548
+ separator: undefined,
549
+ actionId: undefined,
550
+ });
551
+
539
552
  UI.Toolbar.registerToolbarItem({
540
553
  async loadItem() {
541
554
  const Elements = await loadElementsModule();
@@ -39,6 +39,7 @@ import * as ElementsTreeElementHighlighter from './ElementsTreeElementHighlighte
39
39
  import * as ElementsTreeOutline from './ElementsTreeOutline.js';
40
40
  import * as EventListenersWidget from './EventListenersWidget.js';
41
41
  import * as InspectElementModeController from './InspectElementModeController.js';
42
+ import * as LayersWidget from './LayersWidget.js';
42
43
  import * as LayoutSidebarPane from './LayoutSidebarPane.js';
43
44
  import * as MarkerDecorator from './MarkerDecorator.js';
44
45
  import * as MetricsSidebarPane from './MetricsSidebarPane.js';
@@ -66,6 +67,7 @@ export {
66
67
  ElementsTreeOutline,
67
68
  EventListenersWidget,
68
69
  InspectElementModeController,
70
+ LayersWidget,
69
71
  LayoutSidebarPane,
70
72
  MarkerDecorator,
71
73
  MetricsSidebarPane,
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright 2022 The Chromium Authors. All rights reserved.
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
+ .styles-layers-pane {
8
+ overflow: hidden;
9
+ padding-left: 2px;
10
+ background-color: var(--color-background-elevation-1);
11
+ border-bottom: 1px solid var(--color-details-hairline);
12
+ margin-top: 0;
13
+ padding-bottom: 2px;
14
+ }
15
+
16
+ .styles-layers-pane > div {
17
+ font-weight: bold;
18
+ margin: 8px 4px 6px;
19
+ }
20
+
21
+ .styles-layers-pane > table {
22
+ width: 100%;
23
+ border-spacing: 0;
24
+ }
25
+
26
+ .styles-layers-pane td {
27
+ padding: 0;
28
+ }
@@ -217,6 +217,10 @@
217
217
  margin-left: 2px;
218
218
  }
219
219
 
220
+ .sidebar-separator.layer-separator {
221
+ display: flex;
222
+ }
223
+
220
224
  .sidebar-pane-section-toolbar {
221
225
  position: absolute;
222
226
  right: 0;
@@ -109,7 +109,7 @@ const UIStrings = {
109
109
  */
110
110
  lighthouseMode: 'Lighthouse mode',
111
111
  /**
112
- * @description Tooltip text of a radio button to select the Lighthouse mode.
112
+ * @description Tooltip text of a radio button to select the Lighthouse mode. "Navigation" is a Lighthouse mode that audits a page navigation. "Timespan" is a Lighthouse mode that audits user interactions over a period of time. "Snapshot" is a Lighthouse mode that audits the current page state.
113
113
  */
114
114
  runLighthouseInMode: 'Run Lighthouse in navigation, timespan, or snapshot mode',
115
115
  /**
@@ -150,9 +150,9 @@ const UIStrings = {
150
150
  */
151
151
  legacyNavigation: 'Legacy navigation',
152
152
  /**
153
- * @description Tooltip text that appears when hovering over the 'Legacy navigation' checkbox in the settings pane opened by clicking the setting cog in the start view of the audits panel
153
+ * @description Tooltip text that appears when hovering over the 'Legacy navigation' checkbox in the settings pane opened by clicking the setting cog in the start view of the audits panel. "Navigation mode" is a Lighthouse mode that analyzes a page navigation.
154
154
  */
155
- useLegacyNavigation: 'Audit the page using classic Lighthouse when in navigation mode.',
155
+ useLegacyNavigation: 'Analyze the page using classic Lighthouse when in navigation mode.',
156
156
  /**
157
157
  * @description Tooltip text of checkbox to reset storage features prior to running audits in
158
158
  * Lighthouse. Resetting the storage clears/empties it to a neutral state.
package/package.json CHANGED
@@ -54,5 +54,5 @@
54
54
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
55
55
  "watch": "third_party/node/node.py --output scripts/watch_build.js"
56
56
  },
57
- "version": "1.0.975056"
57
+ "version": "1.0.975442"
58
58
  }
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env vpython
1
+ #!/usr/bin/env vpython3
2
2
  # -*- coding: UTF-8 -*-
3
3
  #
4
4
  # Copyright 2021 The Chromium Authors. All rights reserved.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env vpython
1
+ #!/usr/bin/env vpython3
2
2
  # -*- coding: UTF-8 -*-
3
3
  #
4
4
  # Copyright 2022 The Chromium Authors. All rights reserved.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env vpython
1
+ #!/usr/bin/env vpython3
2
2
  # -*- coding: utf-8 -*-
3
3
  #
4
4
  # Copyright 2020 The Chromium Authors. All rights reserved.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env vpython
1
+ #!/usr/bin/env vpython3
2
2
  # Copyright (c) 2011 Google Inc. All rights reserved.
3
3
  # Copyright (c) 2012 Intel Corporation. All rights reserved.
4
4
  #
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env vpython
1
+ #!/usr/bin/env vpython3
2
2
  #
3
3
  # Copyright 2019 The Chromium Authors. All rights reserved.
4
4
  # Use of this source code is governed by a BSD-style license that can be
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env vpython3
2
+ #
1
3
  # Copyright 2018 The Chromium Authors. All rights reserved.
2
4
  # Use of this source code is governed by a BSD-style license that can be
3
5
  # found in the LICENSE file.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env vpython
1
+ #!/usr/bin/env vpython3
2
2
  #
3
3
  # Copyright (C) 2011 Google Inc. All rights reserved.
4
4
  #
@@ -29,13 +29,9 @@
29
29
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
  """Creates a grd file for packaging the inspector files."""
31
31
 
32
- from __future__ import with_statement
33
- from os import path
34
32
 
35
- import errno
36
33
  import os
37
34
  import shlex
38
- import shutil
39
35
  import sys
40
36
  from xml.dom import minidom
41
37
 
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env vpython
1
+ #!/usr/bin/env vpython3
2
2
  # Copyright (c) 2014 Google Inc. All rights reserved.
3
3
  #
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,7 @@ READ_LOCATION = path.join(ROOT_DIRECTORY, 'third_party', 'blink', 'renderer', 'c
44
44
 
45
45
 
46
46
  def _keep_only_required_keys(entry):
47
- for key in entry.keys():
47
+ for key in list(entry.keys()):
48
48
  if key not in ("name", "longhands", "svg", "inherited", "keywords"):
49
49
  del entry[key]
50
50
  return entry
@@ -70,9 +70,10 @@ def properties_from_file(file_name):
70
70
  properties.append(_keep_only_required_keys(entry))
71
71
  property_names[entry["name"]] = entry
72
72
  if "keywords" in entry:
73
- keywords = list(
74
- filter(lambda keyword: not keyword.startswith("-internal-"),
75
- entry["keywords"]))
73
+ keywords = [
74
+ keyword for keyword in entry["keywords"]
75
+ if not keyword.startswith("-internal-")
76
+ ]
76
77
  property_values[entry["name"]] = {"values": keywords}
77
78
 
78
79
  properties.sort(key=lambda entry: entry["name"])