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.
- package/config/gni/devtools_grd_files.gni +4 -0
- package/config/gni/devtools_image_files.gni +1 -0
- package/front_end/Images/src/ic_layers_16x16.svg +11 -0
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/i18n/locales/en-US.json +13 -1
- package/front_end/core/i18n/locales/en-XL.json +13 -1
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/core/sdk/CSSLayer.ts +30 -0
- package/front_end/core/sdk/CSSModel.ts +5 -0
- package/front_end/core/sdk/CSSRule.ts +3 -0
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/entrypoints/main/MainImpl.ts +5 -0
- package/front_end/generated/protocol.ts +6 -0
- package/front_end/panels/elements/LayersWidget.ts +167 -0
- package/front_end/panels/elements/StylesSidebarPane.ts +71 -3
- package/front_end/panels/elements/elements-meta.ts +15 -2
- package/front_end/panels/elements/elements.ts +2 -0
- package/front_end/panels/elements/layersWidget.css +28 -0
- package/front_end/panels/elements/stylesSidebarPane.css +4 -0
- package/front_end/panels/lighthouse/LighthouseController.ts +3 -3
- package/package.json +1 -1
- package/scripts/build/assert_grd.py +1 -1
- package/scripts/build/assert_third_party_readmes.py +1 -1
- package/scripts/build/build_inspector_overlay.py +1 -1
- package/scripts/build/code_generator_frontend.py +1 -1
- package/scripts/build/efficiently_recompile.py +1 -1
- package/scripts/build/generate_aria.py +2 -0
- package/scripts/build/generate_devtools_grd.py +1 -5
- 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",
|
@@ -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' =
|
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": "
|
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": "Â
|
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
|
-
|
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
|
-
|
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.
|
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.
|
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
|
+
}
|
@@ -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: '
|
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
@@ -1,4 +1,4 @@
|
|
1
|
-
#!/usr/bin/env
|
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
|
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 =
|
74
|
-
|
75
|
-
|
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"])
|