chrome-devtools-frontend 1.0.1571007 → 1.0.1571573
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/agents/prompts/README.md +18 -0
- package/agents/prompts/devtools-imports.md +47 -0
- package/agents/prompts/verification.md +27 -0
- package/front_end/core/host/UserMetrics.ts +1 -1
- package/front_end/core/root/Runtime.ts +48 -34
- package/front_end/core/sdk/CSSProperty.ts +1 -1
- package/front_end/core/sdk/CookieModel.ts +1 -1
- package/front_end/core/sdk/DOMModel.ts +1 -1
- package/front_end/core/sdk/OverlayModel.ts +3 -2
- package/front_end/entrypoints/main/MainImpl.ts +29 -18
- package/front_end/generated/SupportedCSSProperties.js +2 -6
- package/front_end/models/issues_manager/ContrastCheckTrigger.ts +2 -2
- package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
- package/front_end/models/trace/ModelImpl.ts +0 -4
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +1 -1
- package/front_end/panels/ai_assistance/PatchWidget.ts +10 -15
- package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +5 -4
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +3 -2
- package/front_end/panels/application/FrameDetailsView.ts +2 -1
- package/front_end/panels/application/components/ReportsGrid.ts +2 -1
- package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +3 -5
- package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -5
- package/front_end/panels/console/ConsoleInsightTeaser.ts +10 -11
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -2
- package/front_end/panels/css_overview/CSSOverviewModel.ts +1 -1
- package/front_end/panels/elements/ComputedStyleModel.ts +11 -13
- package/front_end/panels/elements/ComputedStyleWidget.ts +3 -3
- package/front_end/panels/elements/ElementsPanel.ts +5 -2
- package/front_end/panels/elements/ElementsSidebarPane.ts +1 -1
- package/front_end/panels/elements/PlatformFontsWidget.ts +1 -1
- package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/emulation/DeviceModeWrapper.ts +101 -62
- package/front_end/panels/explain/components/ConsoleInsight.ts +27 -23
- package/front_end/panels/explain/components/consoleInsight.css +1 -1
- package/front_end/panels/network/RequestTimingView.ts +4 -3
- package/front_end/panels/network/components/RequestHeadersView.css +2 -2
- package/front_end/panels/network/components/RequestHeadersView.ts +7 -6
- package/front_end/panels/profiler/HeapProfileView.ts +3 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +2 -2
- package/front_end/panels/recorder/RecorderController.ts +6 -7
- package/front_end/panels/recorder/recorderController.css +1 -1
- package/front_end/panels/security/CookieControlsView.ts +2 -2
- package/front_end/panels/security/CookieReportView.ts +7 -7
- package/front_end/panels/settings/AISettingsTab.ts +5 -5
- package/front_end/panels/settings/components/SyncSection.ts +4 -3
- package/front_end/panels/sources/CallStackSidebarPane.ts +4 -1
- package/front_end/panels/sources/NavigatorView.ts +1 -1
- package/front_end/panels/sources/SourcesPanel.ts +3 -1
- package/front_end/panels/timeline/CompatibilityTracksAppender.ts +1 -1
- package/front_end/panels/timeline/ThreadAppender.ts +1 -1
- package/front_end/panels/timeline/TimelineController.ts +4 -3
- package/front_end/panels/timeline/TimelinePanel.ts +4 -3
- package/front_end/panels/whats_new/ReleaseNoteView.ts +4 -3
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/CodeBlock.ts +3 -6
- package/front_end/ui/components/markdown_view/MarkdownLink.ts +3 -4
- package/front_end/ui/components/panel_feedback/PanelFeedback.ts +3 -4
- package/front_end/ui/components/panel_feedback/PreviewToggle.ts +9 -6
- package/front_end/ui/components/panel_feedback/panelFeedback.css +2 -2
- package/front_end/ui/kit/link/Link.ts +1 -14
- package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +1 -1
- package/front_end/ui/legacy/components/color_picker/ContrastOverlay.ts +5 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -1
- package/package.json +1 -1
|
@@ -856,7 +856,8 @@ export class FrameDetailsReportView extends UI.Widget.Widget {
|
|
|
856
856
|
|
|
857
857
|
constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
|
|
858
858
|
super(element, {useShadowDom: true});
|
|
859
|
-
this.#protocolMonitorExperimentEnabled =
|
|
859
|
+
this.#protocolMonitorExperimentEnabled =
|
|
860
|
+
Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.PROTOCOL_MONITOR);
|
|
860
861
|
this.#view = view;
|
|
861
862
|
}
|
|
862
863
|
|
|
@@ -134,7 +134,8 @@ export class ReportsGrid extends UI.Widget.Widget {
|
|
|
134
134
|
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
135
135
|
super(element);
|
|
136
136
|
this.#view = view;
|
|
137
|
-
this.#protocolMonitorExperimentEnabled =
|
|
137
|
+
this.#protocolMonitorExperimentEnabled =
|
|
138
|
+
Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.PROTOCOL_MONITOR);
|
|
138
139
|
this.requestUpdate();
|
|
139
140
|
}
|
|
140
141
|
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import '../../ui/components/spinners/spinners.js';
|
|
6
6
|
import '../../ui/components/tooltips/tooltips.js';
|
|
7
|
+
import '../../ui/kit/kit.js';
|
|
7
8
|
|
|
8
9
|
import * as Host from '../../core/host/host.js';
|
|
9
10
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
10
11
|
import type * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
|
|
11
12
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
12
13
|
import {Directives, html, nothing, render} from '../../ui/lit/lit.js';
|
|
13
|
-
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
14
14
|
|
|
15
15
|
import {AiCodeCompletionDisclaimer} from './AiCodeCompletionDisclaimer.js';
|
|
16
16
|
import styles from './aiCodeCompletionSummaryToolbar.css.js';
|
|
@@ -86,12 +86,10 @@ export const DEFAULT_SUMMARY_TOOLBAR_VIEW: View = (input, _output, target) => {
|
|
|
86
86
|
variant="rich"
|
|
87
87
|
jslogContext="ai-code-completion-citations"
|
|
88
88
|
><div class="citations-tooltip-container">
|
|
89
|
-
${Directives.repeat(input.citations, citation => html`<
|
|
89
|
+
${Directives.repeat(input.citations, citation => html`<devtools-link
|
|
90
90
|
tabIndex="0"
|
|
91
91
|
href=${citation}
|
|
92
|
-
|
|
93
|
-
click: true
|
|
94
|
-
})}>${citation}</x-link>`)}</div></devtools-tooltip>
|
|
92
|
+
.jslogContext=${'ai-code-completion-citations.citation-link'}>${citation}</devtools-link>`)}</div></devtools-tooltip>
|
|
95
93
|
</div>` : nothing;
|
|
96
94
|
|
|
97
95
|
render(
|
|
@@ -2,6 +2,8 @@
|
|
|
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
|
+
import '../../ui/kit/kit.js';
|
|
6
|
+
|
|
5
7
|
import * as Common from '../../core/common/common.js';
|
|
6
8
|
import * as Host from '../../core/host/host.js';
|
|
7
9
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
@@ -244,13 +246,11 @@ export class AiCodeCompletionTeaser extends UI.Widget.Widget {
|
|
|
244
246
|
{
|
|
245
247
|
iconName: 'warning',
|
|
246
248
|
// clang-format off
|
|
247
|
-
content: html`<
|
|
249
|
+
content: html`<devtools-link
|
|
248
250
|
href=${CODE_SNIPPET_WARNING_URL}
|
|
249
251
|
class="link devtools-link"
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
})}
|
|
253
|
-
>${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</x-link>`,
|
|
252
|
+
.jslogContext=${'code-snippets-explainer.ai-code-completion-teaser'}
|
|
253
|
+
>${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</devtools-link>`,
|
|
254
254
|
// clang-format on
|
|
255
255
|
});
|
|
256
256
|
return reminderItems;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import '../../ui/components/tooltips/tooltips.js';
|
|
6
|
+
import '../../ui/kit/kit.js';
|
|
6
7
|
|
|
7
8
|
import * as Common from '../../core/common/common.js';
|
|
8
9
|
import * as Host from '../../core/host/host.js';
|
|
@@ -167,13 +168,13 @@ function renderNoModel(input: ViewInput): Lit.TemplateResult {
|
|
|
167
168
|
lockedString(UIStringsNotTranslate.getHelpForWarning) :
|
|
168
169
|
lockedString(UIStringsNotTranslate.getHelpForError)}
|
|
169
170
|
</h2>
|
|
170
|
-
<div>You can get quick answers from <
|
|
171
|
-
.
|
|
171
|
+
<div>You can get quick answers from <devtools-link
|
|
172
|
+
.jslogContext=${'insights-teaser-built-in-ai-documentation'}
|
|
172
173
|
class="link"
|
|
173
174
|
href=${BUILT_IN_AI_DOCUMENTATION}
|
|
174
175
|
>
|
|
175
176
|
Chrome’s Built-in AI
|
|
176
|
-
</
|
|
177
|
+
</devtools-link>
|
|
177
178
|
, without any data leaving your device.
|
|
178
179
|
</div>
|
|
179
180
|
<div>${lockedString(UIStringsNotTranslate.toUseDownload)}</div>
|
|
@@ -324,12 +325,12 @@ function renderFooter(input: ViewInput): Lit.TemplateResult {
|
|
|
324
325
|
>
|
|
325
326
|
<div class="info-tooltip-text">${lockedString(UIStringsNotTranslate.infoTooltipText)}</div>
|
|
326
327
|
<div class="learn-more">
|
|
327
|
-
<
|
|
328
|
+
<devtools-link
|
|
328
329
|
class="devtools-link"
|
|
329
330
|
title=${lockedString(UIStringsNotTranslate.learnMoreAboutAiSummaries)}
|
|
330
331
|
href=${DATA_USAGE_URL}
|
|
331
|
-
|
|
332
|
-
>${lockedString(UIStringsNotTranslate.learnMoreAboutAiSummaries)}</
|
|
332
|
+
.jslogContext=${'explain.teaser.learn-more'}
|
|
333
|
+
>${lockedString(UIStringsNotTranslate.learnMoreAboutAiSummaries)}</devtools-link>
|
|
333
334
|
</div>
|
|
334
335
|
</devtools-tooltip>
|
|
335
336
|
${renderDontShowCheckbox(input)}
|
|
@@ -509,13 +510,11 @@ export class ConsoleInsightTeaser extends UI.Widget.Widget {
|
|
|
509
510
|
{
|
|
510
511
|
iconName: 'warning',
|
|
511
512
|
// clang-format off
|
|
512
|
-
content: html`<
|
|
513
|
+
content: html`<devtools-link
|
|
513
514
|
href=${CODE_SNIPPET_WARNING_URL}
|
|
514
515
|
class="link devtools-link"
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
})}
|
|
518
|
-
>${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</x-link>`,
|
|
516
|
+
.jslogContext=${'explain.teaser.code-snippets-explainer'}
|
|
517
|
+
>${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</devtools-link>`,
|
|
519
518
|
// clang-format on
|
|
520
519
|
}
|
|
521
520
|
],
|
|
@@ -483,7 +483,7 @@ function renderContrastIssue(key: string, issues: ContrastIssue[]): TemplateResu
|
|
|
483
483
|
const color = (minContrastIssue.textColor.asString(Common.Color.Format.HEXA));
|
|
484
484
|
const backgroundColor = (minContrastIssue.backgroundColor.asString(Common.Color.Format.HEXA));
|
|
485
485
|
|
|
486
|
-
const showAPCA = Root.Runtime.experiments.isEnabled(
|
|
486
|
+
const showAPCA = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.APCA);
|
|
487
487
|
|
|
488
488
|
const title = i18nString(UIStrings.textColorSOverSBackgroundResults, {
|
|
489
489
|
PH1: color,
|
|
@@ -1041,7 +1041,7 @@ function renderContrastRatio(data: PopulateNodesEventNodeTypes): TemplateResult
|
|
|
1041
1041
|
if (!('contrastRatio' in data)) {
|
|
1042
1042
|
throw new Error('Contrast ratio entry is missing a contrast ratio.');
|
|
1043
1043
|
}
|
|
1044
|
-
const showAPCA = Root.Runtime.experiments.isEnabled(
|
|
1044
|
+
const showAPCA = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.APCA);
|
|
1045
1045
|
const contrastRatio = Platform.NumberUtilities.floor(data.contrastRatio, 2);
|
|
1046
1046
|
const contrastRatioString = showAPCA ? contrastRatio + '%' : contrastRatio;
|
|
1047
1047
|
const border = getBorderString(data.backgroundColor);
|
|
@@ -267,7 +267,7 @@ export class CSSOverviewModel extends SDK.SDKModel.SDKModel<void> {
|
|
|
267
267
|
const formattedTextColor = formatColor(blendedTextColor);
|
|
268
268
|
const formattedBackgroundColor = formatColor(blendedBackgroundColor.asLegacyColor());
|
|
269
269
|
const key = `${formattedTextColor}_${formattedBackgroundColor}`;
|
|
270
|
-
if (Root.Runtime.experiments.isEnabled(
|
|
270
|
+
if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.APCA)) {
|
|
271
271
|
const contrastRatio = contrastInfo.contrastRatioAPCA();
|
|
272
272
|
const threshold = contrastInfo.contrastRatioAPCAThreshold();
|
|
273
273
|
const passes = contrastRatio && threshold ? Math.abs(contrastRatio) >= threshold : false;
|
|
@@ -18,13 +18,12 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
|
|
|
18
18
|
private computedStylePromise?: Promise<ComputedStyle|null>;
|
|
19
19
|
private currentTrackedNodeId?: number;
|
|
20
20
|
|
|
21
|
-
constructor() {
|
|
21
|
+
constructor(node?: SDK.DOMModel.DOMNode|null) {
|
|
22
22
|
super();
|
|
23
23
|
this.#cssModel = null;
|
|
24
24
|
this.eventListeners = [];
|
|
25
|
-
this.#node =
|
|
25
|
+
this.#node = node ?? null;
|
|
26
26
|
|
|
27
|
-
UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.onNodeChanged, this);
|
|
28
27
|
UI.Context.Context.instance().addFlavorChangeListener(
|
|
29
28
|
StylesSidebarPane, this.evaluateTrackingComputedStyleUpdatesForNode, this);
|
|
30
29
|
UI.Context.Context.instance().addFlavorChangeListener(
|
|
@@ -32,17 +31,23 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
dispose(): void {
|
|
35
|
-
UI.Context.Context.instance().removeFlavorChangeListener(SDK.DOMModel.DOMNode, this.onNodeChanged, this);
|
|
36
34
|
UI.Context.Context.instance().removeFlavorChangeListener(
|
|
37
35
|
StylesSidebarPane, this.evaluateTrackingComputedStyleUpdatesForNode, this);
|
|
38
36
|
UI.Context.Context.instance().removeFlavorChangeListener(
|
|
39
37
|
ComputedStyleWidget, this.evaluateTrackingComputedStyleUpdatesForNode, this);
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
node(): SDK.DOMModel.DOMNode|null {
|
|
40
|
+
get node(): SDK.DOMModel.DOMNode|null {
|
|
43
41
|
return this.#node;
|
|
44
42
|
}
|
|
45
43
|
|
|
44
|
+
set node(node: SDK.DOMModel.DOMNode|null) {
|
|
45
|
+
this.#node = node;
|
|
46
|
+
this.updateModel(this.#node ? this.#node.domModel().cssModel() : null);
|
|
47
|
+
this.onCSSModelChanged(null);
|
|
48
|
+
this.evaluateTrackingComputedStyleUpdatesForNode();
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
cssModel(): SDK.CSSModel.CSSModel|null {
|
|
47
52
|
return this.#cssModel?.isEnabled() ? this.#cssModel : null;
|
|
48
53
|
}
|
|
@@ -82,13 +87,6 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
|
|
|
82
87
|
}
|
|
83
88
|
}, 100);
|
|
84
89
|
|
|
85
|
-
private onNodeChanged(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode|null>): void {
|
|
86
|
-
this.#node = event.data;
|
|
87
|
-
this.updateModel(this.#node ? this.#node.domModel().cssModel() : null);
|
|
88
|
-
this.onCSSModelChanged(null);
|
|
89
|
-
this.evaluateTrackingComputedStyleUpdatesForNode();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
90
|
private updateModel(cssModel: SDK.CSSModel.CSSModel|null): void {
|
|
93
91
|
if (this.#cssModel === cssModel) {
|
|
94
92
|
return;
|
|
@@ -155,7 +153,7 @@ export class ComputedStyleModel extends Common.ObjectWrapper.ObjectWrapper<Event
|
|
|
155
153
|
}
|
|
156
154
|
|
|
157
155
|
private elementNode(): SDK.DOMModel.DOMNode|null {
|
|
158
|
-
const node = this.node
|
|
156
|
+
const node = this.node;
|
|
159
157
|
if (!node) {
|
|
160
158
|
return null;
|
|
161
159
|
}
|
|
@@ -319,7 +319,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
|
|
|
319
319
|
return link;
|
|
320
320
|
}
|
|
321
321
|
return null;
|
|
322
|
-
}, () => this.computedStyleModel.node
|
|
322
|
+
}, () => this.computedStyleModel.node);
|
|
323
323
|
|
|
324
324
|
const fontsWidget = new PlatformFontsWidget(this.computedStyleModel);
|
|
325
325
|
fontsWidget.show(this.contentElement);
|
|
@@ -356,7 +356,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
|
|
|
356
356
|
}
|
|
357
357
|
|
|
358
358
|
private async fetchMatchedCascade(): Promise<SDK.CSSMatchedStyles.CSSMatchedStyles|null> {
|
|
359
|
-
const node = this.computedStyleModel.node
|
|
359
|
+
const node = this.computedStyleModel.node;
|
|
360
360
|
if (!node || !this.computedStyleModel.cssModel()) {
|
|
361
361
|
return null;
|
|
362
362
|
}
|
|
@@ -370,7 +370,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
|
|
|
370
370
|
|
|
371
371
|
function validateStyles(this: ComputedStyleWidget, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null):
|
|
372
372
|
SDK.CSSMatchedStyles.CSSMatchedStyles|null {
|
|
373
|
-
return matchedStyles && matchedStyles.node() === this.computedStyleModel.node
|
|
373
|
+
return matchedStyles && matchedStyles.node() === this.computedStyleModel.node ? matchedStyles : null;
|
|
374
374
|
}
|
|
375
375
|
}
|
|
376
376
|
|
|
@@ -263,7 +263,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
|
|
|
263
263
|
this.mainContainer = document.createElement('div');
|
|
264
264
|
this.domTreeContainer = document.createElement('div');
|
|
265
265
|
const crumbsContainer = document.createElement('div');
|
|
266
|
-
if (Root.Runtime.experiments.isEnabled(
|
|
266
|
+
if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE)) {
|
|
267
267
|
this.initializeFullAccessibilityTreeView();
|
|
268
268
|
}
|
|
269
269
|
this.mainContainer.appendChild(this.domTreeContainer);
|
|
@@ -299,7 +299,10 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
|
|
|
299
299
|
|
|
300
300
|
crumbsContainer.appendChild(this.breadcrumbs);
|
|
301
301
|
|
|
302
|
-
const computedStyleModel = new ComputedStyleModel();
|
|
302
|
+
const computedStyleModel = new ComputedStyleModel(UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode));
|
|
303
|
+
UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, event => {
|
|
304
|
+
computedStyleModel.node = event.data;
|
|
305
|
+
});
|
|
303
306
|
this.stylesWidget = new StylesSidebarPane(computedStyleModel);
|
|
304
307
|
this.computedStyleWidget = new ComputedStyleWidget(computedStyleModel);
|
|
305
308
|
this.metricsWidget = new MetricsSidebarPane(computedStyleModel);
|
|
@@ -93,7 +93,7 @@ export class PlatformFontsWidget extends UI.Widget.VBox {
|
|
|
93
93
|
|
|
94
94
|
override async performUpdate(): Promise<void> {
|
|
95
95
|
const cssModel = this.sharedModel.cssModel();
|
|
96
|
-
const node = this.sharedModel.node
|
|
96
|
+
const node = this.sharedModel.node;
|
|
97
97
|
if (!node || !cssModel) {
|
|
98
98
|
this.#view({platformFonts: null}, {}, this.contentElement);
|
|
99
99
|
return;
|
|
@@ -257,7 +257,7 @@ export class StylePropertiesSection {
|
|
|
257
257
|
UI.ARIAUtils.setHidden(this.newStyleRuleToolbar, true);
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
if (Root.Runtime.experiments.isEnabled(
|
|
260
|
+
if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FONT_EDITOR) && this.editable) {
|
|
261
261
|
this.fontEditorToolbar = this.#styleRuleElement.createChild('devtools-toolbar', 'sidebar-pane-section-toolbar');
|
|
262
262
|
this.fontEditorSectionManager = new FontEditorSectionManager(this.parentPane.swatchPopoverHelper(), this);
|
|
263
263
|
this.fontEditorButton =
|
|
@@ -2348,7 +2348,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
|
2348
2348
|
this.name, this.style, this.#parentPane, this.#matchedStyles, this, this.getComputedStyles() ?? new Map()) :
|
|
2349
2349
|
[];
|
|
2350
2350
|
|
|
2351
|
-
if (Root.Runtime.experiments.isEnabled(
|
|
2351
|
+
if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.FONT_EDITOR) && this.property.parsedOk) {
|
|
2352
2352
|
renderers.push(new FontRenderer(this));
|
|
2353
2353
|
}
|
|
2354
2354
|
this.listItemElement.removeChildren();
|
|
@@ -123,73 +123,47 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
|
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
// Resolve to a remote object to ensure the node is alive in the context.
|
|
126
127
|
const object = await node.resolveToObject();
|
|
127
128
|
if (!object) {
|
|
128
129
|
return;
|
|
129
130
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const paddingLeft = parseFloat(styles.paddingLeft);
|
|
146
|
-
|
|
147
|
-
// The position of the frame in it's parent.
|
|
148
|
-
const rect = frame.getBoundingClientRect();
|
|
149
|
-
|
|
150
|
-
// The offset of the parent frame's content relative to the
|
|
151
|
-
// document. If there is no parent frame, the offset is 0.
|
|
152
|
-
// In case of OOPiF, there is no access to the parent frame's
|
|
153
|
-
// offset.
|
|
154
|
-
const parentFrameOffset = getFrameOffset(frame.ownerDocument.defaultView?.frameElement ?? null);
|
|
155
|
-
|
|
156
|
-
// The scroll position of the frame.
|
|
157
|
-
const scrollX = frame.ownerDocument.defaultView?.scrollX ?? 0;
|
|
158
|
-
const scrollY = frame.ownerDocument.defaultView?.scrollY ?? 0;
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
x: parentFrameOffset.x + rect.left + borderLeft + paddingLeft + scrollX,
|
|
162
|
-
y: parentFrameOffset.y + rect.top + borderTop + paddingTop + scrollY,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// The bounding client rect of the node relative to the viewport.
|
|
167
|
-
const rect = this.getBoundingClientRect();
|
|
168
|
-
const frameOffset = getFrameOffset(this.ownerDocument.defaultView?.frameElement ?? null);
|
|
169
|
-
|
|
170
|
-
// The scroll position of the frame.
|
|
171
|
-
const scrollX = this.ownerDocument.defaultView?.scrollX ?? 0;
|
|
172
|
-
const scrollY = this.ownerDocument.defaultView?.scrollY ?? 0;
|
|
173
|
-
|
|
174
|
-
// The offset of the node's content relative to the top-level
|
|
175
|
-
// document is the sum of the element offset relative to the
|
|
176
|
-
// document's viewport, the document's scroll position, and the
|
|
177
|
-
// parent's offset relative to the top-level document.
|
|
178
|
-
return JSON.stringify({
|
|
179
|
-
x: rect.left + frameOffset.x + scrollX,
|
|
180
|
-
y: rect.top + frameOffset.y + scrollY,
|
|
181
|
-
width: rect.width,
|
|
182
|
-
height: rect.height,
|
|
183
|
-
scale: 1,
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
if (!result.object) {
|
|
187
|
-
throw new Error('Clipping error: could not get object data.');
|
|
131
|
+
|
|
132
|
+
// Get the Box Model via CDP.
|
|
133
|
+
// This returns the quads relative to the target's viewport.
|
|
134
|
+
// We use the 'border' quad to include the border and padding in the screenshot,
|
|
135
|
+
// matching the 'width' and 'height' properties which are also Border Box dimensions.
|
|
136
|
+
const nodeBoxModel = await node.boxModel();
|
|
137
|
+
if (!nodeBoxModel) {
|
|
138
|
+
throw new Error(`Unable to get box model of the node: ${new Error().stack}`);
|
|
139
|
+
}
|
|
140
|
+
const nodeBorderQuad = nodeBoxModel.border;
|
|
141
|
+
|
|
142
|
+
// Get Layout Metrics to account for the Visual Viewport scroll and zoom.
|
|
143
|
+
const metrics = await node.domModel().target().pageAgent().invoke_getLayoutMetrics();
|
|
144
|
+
if (metrics.getError()) {
|
|
145
|
+
throw new Error(`Unable to get metrics: ${new Error().stack}`);
|
|
188
146
|
}
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
const
|
|
192
|
-
|
|
147
|
+
|
|
148
|
+
const scrollX = metrics.cssVisualViewport.pageX;
|
|
149
|
+
const scrollY = metrics.cssVisualViewport.pageY;
|
|
150
|
+
|
|
151
|
+
// Calculate the global offset for OOPiFs (Out-of-Process iframes).
|
|
152
|
+
// This accounts for the position of the target's frame within the main page.
|
|
153
|
+
const {x: oopifOffsetX, y: oopifOffsetY} = await getOopifOffset(node.domModel().target());
|
|
154
|
+
|
|
155
|
+
// Assemble the final Clip.
|
|
156
|
+
// The absolute coordinates are: Global (OOPiF) + Viewport Scroll + Local Node Position (Border Box).
|
|
157
|
+
const clip = {
|
|
158
|
+
x: oopifOffsetX + scrollX + nodeBorderQuad[0],
|
|
159
|
+
y: oopifOffsetY + scrollY + nodeBorderQuad[1],
|
|
160
|
+
width: nodeBoxModel.width,
|
|
161
|
+
height: nodeBoxModel.height,
|
|
162
|
+
scale: 1,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Apply Zoom factor.
|
|
166
|
+
const zoom = metrics.cssVisualViewport.zoom ?? 1;
|
|
193
167
|
clip.x *= zoom;
|
|
194
168
|
clip.y *= zoom;
|
|
195
169
|
clip.width *= zoom;
|
|
@@ -210,3 +184,68 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
|
|
|
210
184
|
return false;
|
|
211
185
|
}
|
|
212
186
|
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Calculate the offset of the "Local Root" frame relative to the "Global Root" (the main frame).
|
|
190
|
+
* This involves traversing the CDP Targets for OOPiFs.
|
|
191
|
+
*/
|
|
192
|
+
async function getOopifOffset(target: SDK.Target.Target|null): Promise<{x: number, y: number}> {
|
|
193
|
+
if (!target) {
|
|
194
|
+
return {x: 0, y: 0};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Get the parent target. If there's no parent (we are at root) or it's not a frame, we are done.
|
|
198
|
+
const parentTarget = target.parentTarget();
|
|
199
|
+
if (!parentTarget || parentTarget.type() !== SDK.Target.Type.FRAME) {
|
|
200
|
+
return {x: 0, y: 0};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Identify the current frame's ID to find its owner in the parent.
|
|
204
|
+
const frameId = target.model(SDK.ResourceTreeModel.ResourceTreeModel)?.mainFrame?.id;
|
|
205
|
+
if (!frameId) {
|
|
206
|
+
return {x: 0, y: 0};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Get the DOMModel of the parent to query the frame owner element.
|
|
210
|
+
const parentDOMModel = parentTarget.model(SDK.DOMModel.DOMModel);
|
|
211
|
+
if (!parentDOMModel) {
|
|
212
|
+
return {x: 0, y: 0};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Retrieve the frame owner node (e.g. the <iframe> element) in the parent's document.
|
|
216
|
+
const frameOwnerDeferred = await parentDOMModel.getOwnerNodeForFrame(frameId);
|
|
217
|
+
const frameOwner = await frameOwnerDeferred?.resolvePromise();
|
|
218
|
+
if (!frameOwner) {
|
|
219
|
+
return {x: 0, y: 0};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Get the content box of the iframe element.
|
|
223
|
+
// This is relative to the parent target's viewport.
|
|
224
|
+
const boxModel = await frameOwner.boxModel();
|
|
225
|
+
if (!boxModel) {
|
|
226
|
+
return {x: 0, y: 0};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// content is a Quad [x1, y1, x2, y2, x3, y3, x4, y4]
|
|
230
|
+
const contentQuad = boxModel.content;
|
|
231
|
+
const iframeContentX = contentQuad[0];
|
|
232
|
+
const iframeContentY = contentQuad[1];
|
|
233
|
+
|
|
234
|
+
// Get the scroll position of the parent target to convert viewport-relative coordinates
|
|
235
|
+
// to document-relative coordinates.
|
|
236
|
+
const parentMetrics = await parentTarget.pageAgent().invoke_getLayoutMetrics();
|
|
237
|
+
if (parentMetrics.getError()) {
|
|
238
|
+
return {x: 0, y: 0};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const scrollX = parentMetrics.cssVisualViewport.pageX;
|
|
242
|
+
const scrollY = parentMetrics.cssVisualViewport.pageY;
|
|
243
|
+
|
|
244
|
+
// Recursively add the offset of the parent target itself (if it is also an OOPiF).
|
|
245
|
+
const parentOffset = await getOopifOffset(parentTarget);
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
x: iframeContentX + scrollX + parentOffset.x,
|
|
249
|
+
y: iframeContentY + scrollY + parentOffset.y,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import '../../../ui/components/spinners/spinners.js';
|
|
6
|
+
import '../../../ui/kit/kit.js';
|
|
6
7
|
|
|
7
8
|
import * as Common from '../../../core/common/common.js';
|
|
8
9
|
import * as Host from '../../../core/host/host.js';
|
|
@@ -299,9 +300,9 @@ function renderSearchButton(onSearch: ViewInput['callbacks']['onSearch']): Lit.T
|
|
|
299
300
|
|
|
300
301
|
function renderLearnMoreAboutInsights(): Lit.TemplateResult {
|
|
301
302
|
// clang-format off
|
|
302
|
-
return html`<
|
|
303
|
+
return html`<devtools-link href=${LEARN_MORE_URL} class="link" .jslogContext=${'learn-more'}>
|
|
303
304
|
${i18nString(UIStrings.learnMore)}
|
|
304
|
-
</
|
|
305
|
+
</devtools-link>`;
|
|
305
306
|
// clang-format on
|
|
306
307
|
}
|
|
307
308
|
|
|
@@ -317,15 +318,15 @@ function maybeRenderSources(
|
|
|
317
318
|
<ol class="sources-list">
|
|
318
319
|
${directCitationUrls.map((url, index) => html`
|
|
319
320
|
<li>
|
|
320
|
-
<
|
|
321
|
+
<devtools-link
|
|
321
322
|
href=${url}
|
|
322
323
|
class=${Directives.classMap({link: true, highlighted: index === highlightedCitationIndex})}
|
|
323
|
-
|
|
324
|
+
.jslogContext=${'references.console-insights'}
|
|
324
325
|
${Directives.ref(e => { output.citationLinks[index] = e as HTMLElement; })}
|
|
325
326
|
@animationend=${onCitationAnimationEnd}
|
|
326
327
|
>
|
|
327
328
|
${url}
|
|
328
|
-
</
|
|
329
|
+
</devtools-link>
|
|
329
330
|
</li>
|
|
330
331
|
`)}
|
|
331
332
|
</ol>
|
|
@@ -343,13 +344,13 @@ function maybeRenderRelatedContent(relatedUrls: string[], directCitationUrls: st
|
|
|
343
344
|
<ul class="references-list">
|
|
344
345
|
${relatedUrls.map(relatedUrl => html`
|
|
345
346
|
<li>
|
|
346
|
-
<
|
|
347
|
+
<devtools-link
|
|
347
348
|
href=${relatedUrl}
|
|
348
349
|
class="link"
|
|
349
|
-
|
|
350
|
+
.jslogContext=${'references.console-insights'}
|
|
350
351
|
>
|
|
351
352
|
${relatedUrl}
|
|
352
|
-
</
|
|
353
|
+
</devtools-link>
|
|
353
354
|
</li>
|
|
354
355
|
`)}
|
|
355
356
|
</ul>
|
|
@@ -379,10 +380,10 @@ function renderInsightSourcesList(
|
|
|
379
380
|
<div class="insight-sources">
|
|
380
381
|
<ul>
|
|
381
382
|
${Directives.repeat(sources, item => item.value, item => {
|
|
382
|
-
return html`<li><
|
|
383
|
+
return html`<li><devtools-link class="link" title="${localizeType(item.type)} ${i18nString(UIStrings.opensInNewTab)}" href="data:text/plain;charset=utf-8,${encodeURIComponent(item.value)}" .jslogContext=${'source-' + item.type}>
|
|
383
384
|
<devtools-icon name="open-externally"></devtools-icon>
|
|
384
385
|
${localizeType(item.type)}
|
|
385
|
-
</
|
|
386
|
+
</devtools-link></li>`;
|
|
386
387
|
})}
|
|
387
388
|
${isPageReloadRecommended ? html`<li class="source-disclaimer">
|
|
388
389
|
<devtools-icon name="warning"></devtools-icon>
|
|
@@ -450,28 +451,28 @@ function renderConsentReminder(noLogging: boolean): Lit.TemplateResult {
|
|
|
450
451
|
<devtools-icon name="policy" class="medium">
|
|
451
452
|
</devtools-icon>
|
|
452
453
|
</div>
|
|
453
|
-
<div>Use of this feature is subject to the <
|
|
454
|
+
<div>Use of this feature is subject to the <devtools-link
|
|
454
455
|
href=${TERMS_OF_SERVICE_URL}
|
|
455
456
|
class="link"
|
|
456
|
-
|
|
457
|
+
.jslogContext=${'terms-of-service.console-insights'}>
|
|
457
458
|
Google Terms of Service
|
|
458
|
-
</
|
|
459
|
+
</devtools-link> and <devtools-link
|
|
459
460
|
href=${PRIVACY_POLICY_URL}
|
|
460
461
|
class="link"
|
|
461
|
-
|
|
462
|
+
.jslogContext=${'privacy-policy.console-insights'}>
|
|
462
463
|
Google Privacy Policy
|
|
463
|
-
</
|
|
464
|
+
</devtools-link>
|
|
464
465
|
</div>
|
|
465
466
|
<div>
|
|
466
467
|
<devtools-icon name="warning" class="medium">
|
|
467
468
|
</devtools-icon>
|
|
468
469
|
</div>
|
|
469
470
|
<div>
|
|
470
|
-
<
|
|
471
|
+
<devtools-link
|
|
471
472
|
href=${CODE_SNIPPET_WARNING_URL}
|
|
472
473
|
class="link"
|
|
473
|
-
|
|
474
|
-
>Use generated code snippets with caution</
|
|
474
|
+
.jslogContext=${'code-snippets-explainer.console-insights'}
|
|
475
|
+
>Use generated code snippets with caution</devtools-link>
|
|
475
476
|
</div>
|
|
476
477
|
</div>`;
|
|
477
478
|
// clang-format on
|
|
@@ -513,10 +514,10 @@ function renderDisclaimer(noLogging: boolean, onDisclaimerSettingsLink: () => vo
|
|
|
513
514
|
} <button class="link" role="link" @click=${onDisclaimerSettingsLink}
|
|
514
515
|
jslog=${VisualLogging.action('open-ai-settings').track({click: true})}>
|
|
515
516
|
Open settings
|
|
516
|
-
</button> or <
|
|
517
|
-
class="link"
|
|
517
|
+
</button> or <devtools-link href=${LEARN_MORE_URL}
|
|
518
|
+
class="link" .jslogContext=${'learn-more'}>
|
|
518
519
|
learn more
|
|
519
|
-
</
|
|
520
|
+
</devtools-link>
|
|
520
521
|
</span>`;
|
|
521
522
|
// clang-format on
|
|
522
523
|
}
|
|
@@ -549,7 +550,8 @@ function renderSignInFooter(onGoToSignIn: () => void): Lit.LitTemplate {
|
|
|
549
550
|
// clang-format on
|
|
550
551
|
}
|
|
551
552
|
|
|
552
|
-
function renderConsentReminderFooter(
|
|
553
|
+
function renderConsentReminderFooter(
|
|
554
|
+
onReminderSettingsLink: () => void, onConsentReminderConfirmed: () => void): Lit.LitTemplate {
|
|
553
555
|
// clang-format off
|
|
554
556
|
return html`
|
|
555
557
|
<div class="filler"></div>
|
|
@@ -575,7 +577,9 @@ function renderConsentReminderFooter(onReminderSettingsLink: () => void, onConse
|
|
|
575
577
|
// clang-format on
|
|
576
578
|
}
|
|
577
579
|
|
|
578
|
-
function renderInsightFooter(
|
|
580
|
+
function renderInsightFooter(
|
|
581
|
+
noLogging: ViewInput['noLogging'], selectedRating: ViewInput['selectedRating'],
|
|
582
|
+
callbacks: ViewInput['callbacks']): Lit.LitTemplate {
|
|
579
583
|
// clang-format off
|
|
580
584
|
return html`
|
|
581
585
|
<div class="disclaimer">
|