chrome-devtools-frontend 1.0.1534251 → 1.0.1535712

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 (44) hide show
  1. package/docs/contributing/infrastructure.md +32 -0
  2. package/docs/contributing/issues.md +15 -37
  3. package/eslint.config.mjs +1 -0
  4. package/front_end/core/host/InspectorFrontendHost.ts +2 -0
  5. package/front_end/core/host/InspectorFrontendHostAPI.ts +1 -0
  6. package/front_end/core/host/UserMetrics.ts +29 -1
  7. package/front_end/core/protocol_client/CDPConnection.ts +53 -5
  8. package/front_end/core/protocol_client/InspectorBackend.ts +0 -89
  9. package/front_end/core/protocol_client/protocol_client.ts +2 -0
  10. package/front_end/core/root/Runtime.ts +1 -0
  11. package/front_end/core/sdk/RehydratingConnection.ts +1 -1
  12. package/front_end/devtools_compatibility.js +230 -32
  13. package/front_end/generated/SupportedCSSProperties.js +38 -0
  14. package/front_end/models/ai_assistance/BuiltInAi.ts +141 -39
  15. package/front_end/panels/ai_assistance/PatchWidget.ts +39 -40
  16. package/front_end/panels/ai_assistance/components/ExploreWidget.ts +0 -2
  17. package/front_end/panels/autofill/AutofillView.ts +2 -3
  18. package/front_end/panels/changes/CombinedDiffView.ts +13 -14
  19. package/front_end/panels/common/BadgeNotification.ts +1 -3
  20. package/front_end/panels/console/ConsoleInsightTeaser.ts +8 -1
  21. package/front_end/panels/console/ConsoleView.ts +1 -0
  22. package/front_end/panels/console/consoleView.css +0 -1
  23. package/front_end/panels/elements/ElementsTreeOutline.ts +1 -1
  24. package/front_end/panels/network/components/DirectSocketConnectionView.ts +4 -6
  25. package/front_end/panels/network/components/ResponseHeaderSection.ts +1 -2
  26. package/front_end/panels/security/CookieControlsView.ts +72 -66
  27. package/front_end/panels/security/CookieReportView.ts +15 -14
  28. package/front_end/panels/security/IPProtectionView.ts +1 -2
  29. package/front_end/panels/security/SecurityPanel.ts +19 -19
  30. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +36 -36
  31. package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +1 -2
  32. package/front_end/third_party/chromium/README.chromium +1 -1
  33. package/front_end/ui/components/dialogs/Dialog.ts +7 -17
  34. package/front_end/ui/components/text_editor/TextEditor.ts +2 -3
  35. package/front_end/ui/components/text_editor/config.ts +1 -3
  36. package/front_end/ui/legacy/UIUtils.ts +5 -0
  37. package/front_end/ui/legacy/components/inline_editor/CSSAngle.ts +1 -1
  38. package/front_end/ui/legacy/components/perf_ui/BrickBreaker.ts +2 -2
  39. package/front_end/ui/legacy/components/perf_ui/Font.ts +1 -14
  40. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  41. package/inspector_overlay/testing/InspectorOverlayHelpers.ts +2 -10
  42. package/package.json +1 -1
  43. package/front_end/services/window_bounds/WindowBoundsService.ts +0 -27
  44. package/front_end/services/window_bounds/window_bounds.ts +0 -9
@@ -1,7 +1,6 @@
1
1
  // Copyright 2024 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
5
4
 
6
5
  import '../../ui/components/switch/switch.js';
7
6
  import '../../ui/components/cards/cards.js';
@@ -14,15 +13,14 @@ import type * as Platform from '../../core/platform/platform.js';
14
13
  import * as Root from '../../core/root/root.js';
15
14
  import * as SDK from '../../core/sdk/sdk.js';
16
15
  import * as Buttons from '../../ui/components/buttons/buttons.js';
17
- import * as ChromeLink from '../../ui/components/chrome_link/chrome_link.js';
18
16
  import * as Input from '../../ui/components/input/input.js';
19
17
  import * as UI from '../../ui/legacy/legacy.js';
20
- import * as Lit from '../../ui/lit/lit.js';
18
+ import {Directives, html, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
21
19
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
22
20
 
23
21
  import cookieControlsViewStyles from './cookieControlsView.css.js';
24
22
 
25
- const {render, html} = Lit;
23
+ const {ref} = Directives;
26
24
 
27
25
  const UIStrings = {
28
26
  /**
@@ -118,52 +116,50 @@ export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
118
116
  export const i18nFormatString = i18n.i18n.getFormatLocalizedString.bind(undefined, str_);
119
117
 
120
118
  export interface ViewInput {
119
+ thirdPartyControlsDict: Root.Runtime.HostConfig['thirdPartyCookieControls'];
120
+ isGracePeriodActive: boolean;
121
121
  inputChanged: (newValue: boolean, setting: Common.Settings.Setting<boolean>) => void;
122
122
  openChromeCookieSettings: () => void;
123
123
  }
124
124
 
125
125
  export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
126
126
 
127
- export function showInfobar(): void {
128
- UI.InspectorView.InspectorView.instance().displayDebuggedTabReloadRequiredWarning(
129
- i18nString(UIStrings.siteReloadMessage));
127
+ function getChromeFlagsLink(flag: string): TemplateResult {
128
+ return html`
129
+ <devtools-chrome-link href="chrome://flags/#${flag}" tabindex="0">
130
+ ${flag}
131
+ </devtools-chrome-link>`;
130
132
  }
133
+ const DEFAULT_VIEW: View = (input: ViewInput, _output: object, target: HTMLElement): void => {
134
+ // createSetting() allows us to initialize the settings with the UI binding values the first
135
+ // time that the browser starts, and use the existing setting value for all subsequent uses.
136
+ const enterpriseEnabledSetting = Common.Settings.Settings.instance().createSetting(
137
+ 'enterprise-enabled',
138
+ input.thirdPartyControlsDict && input.thirdPartyControlsDict.managedBlockThirdPartyCookies &&
139
+ typeof input.thirdPartyControlsDict.managedBlockThirdPartyCookies === 'boolean' ?
140
+ input.thirdPartyControlsDict.managedBlockThirdPartyCookies :
141
+ false,
142
+ Common.Settings.SettingStorageType.GLOBAL);
143
+ const toggleEnabledSetting = Common.Settings.Settings.instance().createSetting(
144
+ 'cookie-control-override-enabled',
145
+ input.thirdPartyControlsDict?.thirdPartyCookieRestrictionEnabled ?
146
+ input.thirdPartyControlsDict.thirdPartyCookieRestrictionEnabled :
147
+ false,
148
+ Common.Settings.SettingStorageType.GLOBAL);
149
+ const gracePeriodDisabledSetting = Common.Settings.Settings.instance().createSetting(
150
+ 'grace-period-mitigation-disabled',
151
+ input.thirdPartyControlsDict?.thirdPartyCookieMetadataEnabled ?
152
+ input.thirdPartyControlsDict.thirdPartyCookieMetadataEnabled :
153
+ true,
154
+ Common.Settings.SettingStorageType.GLOBAL);
155
+ const heuristicsDisabledSetting = Common.Settings.Settings.instance().createSetting(
156
+ 'heuristic-mitigation-disabled',
157
+ input.thirdPartyControlsDict?.thirdPartyCookieHeuristicsEnabled ?
158
+ input.thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled :
159
+ true,
160
+ Common.Settings.SettingStorageType.GLOBAL);
131
161
 
132
- export class CookieControlsView extends UI.Widget.VBox {
133
- #view: View;
134
- #isGracePeriodActive: boolean;
135
- #thirdPartyControlsDict: Root.Runtime.HostConfig['thirdPartyCookieControls'];
136
-
137
- constructor(element?: HTMLElement, view: View = (input, _, target) => {
138
- // createSetting() allows us to initialize the settings with the UI binding values the first
139
- // time that the browser starts, and use the existing setting value for all subsequent uses.
140
- const enterpriseEnabledSetting = Common.Settings.Settings.instance().createSetting(
141
- 'enterprise-enabled',
142
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.managedBlockThirdPartyCookies &&
143
- typeof this.#thirdPartyControlsDict.managedBlockThirdPartyCookies === 'boolean' ?
144
- this.#thirdPartyControlsDict.managedBlockThirdPartyCookies :
145
- false,
146
- Common.Settings.SettingStorageType.GLOBAL);
147
- const toggleEnabledSetting = Common.Settings.Settings.instance().createSetting(
148
- 'cookie-control-override-enabled',
149
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.thirdPartyCookieRestrictionEnabled ?
150
- this.#thirdPartyControlsDict.thirdPartyCookieRestrictionEnabled :
151
- false,
152
- Common.Settings.SettingStorageType.GLOBAL);
153
- const gracePeriodDisabledSetting = Common.Settings.Settings.instance().createSetting(
154
- 'grace-period-mitigation-disabled',
155
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.thirdPartyCookieMetadataEnabled ?
156
- this.#thirdPartyControlsDict.thirdPartyCookieMetadataEnabled :
157
- true,
158
- Common.Settings.SettingStorageType.GLOBAL);
159
- const heuristicsDisabledSetting = Common.Settings.Settings.instance().createSetting(
160
- 'heuristic-mitigation-disabled',
161
- this.#thirdPartyControlsDict && this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled ?
162
- this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled :
163
- true,
164
- Common.Settings.SettingStorageType.GLOBAL);
165
-
166
- // clang-format off
162
+ // clang-format off
167
163
  const cardHeader = html `
168
164
  <div class="card-header">
169
165
  <div class="lhs">
@@ -175,11 +171,11 @@ export class CookieControlsView extends UI.Widget.VBox {
175
171
  <devtools-icon
176
172
  tabindex="0"
177
173
  name="domain"
178
- ${Lit.Directives.ref((el: Element|undefined) => {
174
+ ${ref((el: Element|undefined) => {
179
175
  UI.Tooltip.Tooltip.install(el as HTMLElement, i18nString(UIStrings.enterpriseTooltip));
180
176
  (el as HTMLElement).role = 'img';
181
177
  })}>
182
- </devtools-icon>` : Lit.nothing
178
+ </devtools-icon>` : nothing
183
179
  }
184
180
  </div>
185
181
  <div>
@@ -197,8 +193,8 @@ export class CookieControlsView extends UI.Widget.VBox {
197
193
  `;
198
194
 
199
195
  const gracePeriodControlDisabled =
200
- (this.#thirdPartyControlsDict ? (!this.#thirdPartyControlsDict.thirdPartyCookieMetadataEnabled) : false) ||
201
- enterpriseEnabledSetting.get() || !toggleEnabledSetting.get() || !this.#isGracePeriodActive;
196
+ (input.thirdPartyControlsDict ? (!input.thirdPartyControlsDict.thirdPartyCookieMetadataEnabled) : false) ||
197
+ enterpriseEnabledSetting.get() || !toggleEnabledSetting.get() || !input.isGracePeriodActive;
202
198
  const gracePeriodControl = html`
203
199
  <div class="card-row">
204
200
  <label class='checkbox-label'>
@@ -215,11 +211,11 @@ export class CookieControlsView extends UI.Widget.VBox {
215
211
  i18nFormatString(UIStrings.gracePeriodExplanation, {
216
212
  PH1: i18nString(UIStrings.gracePeriod),
217
213
  }) :
218
- (this.#thirdPartyControlsDict ? !this.#thirdPartyControlsDict?.thirdPartyCookieMetadataEnabled: false) ?
214
+ (input.thirdPartyControlsDict ? !input.thirdPartyControlsDict?.thirdPartyCookieMetadataEnabled: false) ?
219
215
  i18nFormatString(UIStrings.enableFlag, {
220
- PH1: this.getChromeFlagsLink(UIStrings.tpcdMetadataGrants),
216
+ PH1: getChromeFlagsLink(UIStrings.tpcdMetadataGrants),
221
217
  }) :
222
- i18nFormatString(this.#isGracePeriodActive ? UIStrings.gracePeriodExplanation : UIStrings.enrollGracePeriod, {
218
+ i18nFormatString(input.isGracePeriodActive ? UIStrings.gracePeriodExplanation : UIStrings.enrollGracePeriod, {
223
219
  PH1: UI.Fragment.html`<x-link class="devtools-link" href="https://developers.google.com/privacy-sandbox/cookies/temporary-exceptions/grace-period" jslog=${VisualLogging.link('grace-period-link').track({click: true})}>${i18nString(UIStrings.gracePeriod)}</x-link>`,
224
220
  })
225
221
  }
@@ -230,7 +226,7 @@ export class CookieControlsView extends UI.Widget.VBox {
230
226
  `;
231
227
 
232
228
  const heuristicsControlDisabled =
233
- (this.#thirdPartyControlsDict ? (!this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled) : false) ||
229
+ (input.thirdPartyControlsDict ? (!input.thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled) : false) ||
234
230
  enterpriseEnabledSetting.get() || !toggleEnabledSetting.get();
235
231
  const heuristicControl = html`
236
232
  <div class="card-row">
@@ -248,9 +244,9 @@ export class CookieControlsView extends UI.Widget.VBox {
248
244
  i18nFormatString(UIStrings.heuristicExplanation, {
249
245
  PH1: i18nString(UIStrings.scenarios),
250
246
  }) :
251
- (this.#thirdPartyControlsDict ? !this.#thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled: false) ?
247
+ (input.thirdPartyControlsDict ? !input.thirdPartyControlsDict.thirdPartyCookieHeuristicsEnabled: false) ?
252
248
  i18nFormatString(UIStrings.enableFlag, {
253
- PH1: this.getChromeFlagsLink(UIStrings.tpcdHeuristicsGrants),
249
+ PH1: getChromeFlagsLink(UIStrings.tpcdHeuristicsGrants),
254
250
  }) :
255
251
  i18nFormatString(UIStrings.heuristicExplanation, {
256
252
  PH1: UI.Fragment.html`<x-link class="devtools-link" href="https://developers.google.com/privacy-sandbox/cookies/temporary-exceptions/heuristics-based-exceptions" jslog=${VisualLogging.link('heuristic-link').track({click: true})}>${i18nString(UIStrings.scenarios)}</x-link>`,
@@ -300,12 +296,24 @@ export class CookieControlsView extends UI.Widget.VBox {
300
296
  </div>
301
297
  </div>
302
298
  </devtools-card>
303
- ${Boolean(enterpriseEnabledSetting.get()) ? enterpriseDisclaimer : Lit.nothing}
299
+ ${Boolean(enterpriseEnabledSetting.get()) ? enterpriseDisclaimer : nothing}
304
300
  </div>
305
301
  </div>
306
- `, target, {host: this});
307
- // clang-format on
308
- }) {
302
+ `, target);
303
+ // clang-format on
304
+ };
305
+
306
+ export function showInfobar(): void {
307
+ UI.InspectorView.InspectorView.instance().displayDebuggedTabReloadRequiredWarning(
308
+ i18nString(UIStrings.siteReloadMessage));
309
+ }
310
+
311
+ export class CookieControlsView extends UI.Widget.VBox {
312
+ #view: View;
313
+ #isGracePeriodActive: boolean;
314
+ #thirdPartyControlsDict: Root.Runtime.HostConfig['thirdPartyCookieControls'];
315
+
316
+ constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
309
317
  super(element, {useShadowDom: true});
310
318
  this.#view = view;
311
319
  this.#isGracePeriodActive = false;
@@ -327,7 +335,14 @@ export class CookieControlsView extends UI.Widget.VBox {
327
335
  }
328
336
 
329
337
  override performUpdate(): void {
330
- this.#view(this, this, this.contentElement);
338
+ this.#view(
339
+ {
340
+ thirdPartyControlsDict: this.#thirdPartyControlsDict,
341
+ isGracePeriodActive: this.#isGracePeriodActive,
342
+ inputChanged: this.inputChanged.bind(this),
343
+ openChromeCookieSettings: this.openChromeCookieSettings.bind(this),
344
+ },
345
+ this, this.contentElement);
331
346
  }
332
347
 
333
348
  inputChanged(newValue: boolean, setting: Common.Settings.Setting<boolean>): void {
@@ -390,13 +405,4 @@ export class CookieControlsView extends UI.Widget.VBox {
390
405
  this.requestUpdate();
391
406
  }
392
407
  }
393
-
394
- getChromeFlagsLink(flag: string): Element {
395
- const link = new ChromeLink.ChromeLink.ChromeLink();
396
- link.textContent = flag;
397
- link.href = ('chrome://flags/' + flag) as Platform.DevToolsPath.UrlString;
398
- link.setAttribute('tabindex', '0');
399
-
400
- return link;
401
- }
402
408
  }
@@ -196,17 +196,8 @@ export interface CookieReportNodeData {
196
196
  }
197
197
 
198
198
  export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
199
-
200
- export class CookieReportView extends UI.Widget.VBox {
201
- #issuesManager?: IssuesManager.IssuesManager.IssuesManager;
202
- namedBitSetFilterUI?: UI.FilterBar.NamedBitSetFilterUI;
203
- #cookieRows = new Map<string, IssuesManager.CookieIssue.CookieReportInfo>();
204
- #view: View;
205
- filterItems: UI.FilterBar.Item[] = [];
206
- searchText: string;
207
-
208
- constructor(element?: HTMLElement, view: View = (input, output, target) => {
209
- // clang-format off
199
+ const DEFAULT_VIEW: View = (input, output, target) => {
200
+ // clang-format off
210
201
  render(html `
211
202
  <div class="report overflow-auto">
212
203
  <div class="header">
@@ -283,9 +274,19 @@ export class CookieReportView extends UI.Widget.VBox {
283
274
  }
284
275
 
285
276
  </div>
286
- `, target, {host: this});
287
- // clang-format on
288
- }) {
277
+ `, target);
278
+ // clang-format on
279
+ };
280
+
281
+ export class CookieReportView extends UI.Widget.VBox {
282
+ #issuesManager?: IssuesManager.IssuesManager.IssuesManager;
283
+ namedBitSetFilterUI?: UI.FilterBar.NamedBitSetFilterUI;
284
+ #cookieRows = new Map<string, IssuesManager.CookieIssue.CookieReportInfo>();
285
+ #view: View;
286
+ filterItems: UI.FilterBar.Item[] = [];
287
+ searchText: string;
288
+
289
+ constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
289
290
  super(element, {useShadowDom: true});
290
291
  this.#view = view;
291
292
  this.registerRequiredCSS(cookieReportViewStyles);
@@ -1,7 +1,6 @@
1
1
  // Copyright 2025 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
5
4
 
6
5
  import '../../ui/components/switch/switch.js';
7
6
  import '../../ui/components/cards/cards.js';
@@ -136,7 +135,7 @@ export interface ViewInput {
136
135
  }
137
136
  export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
138
137
 
139
- export const DEFAULT_VIEW: View = (input, _, target) => {
138
+ export const DEFAULT_VIEW: View = (input, _output, target) => {
140
139
  const {status} = input;
141
140
  const statusText = status ? i18nString(UIStrings[status]) : i18nString(UIStrings.statusUnknown);
142
141
 
@@ -2,7 +2,6 @@
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
  /* eslint-disable @devtools/no-imperative-dom-api */
5
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
6
5
 
7
6
  import * as Common from '../../core/common/common.js';
8
7
  import * as Host from '../../core/host/host.js';
@@ -549,6 +548,24 @@ export interface ViewOutput {
549
548
 
550
549
  export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
551
550
 
551
+ const DEFAULT_VIEW: View = (input: ViewInput, output: ViewOutput, target: HTMLElement): void => {
552
+ // clang-format off
553
+ render(html`
554
+ <devtools-split-view direction="column" name="security"
555
+ ${UI.Widget.widgetRef(UI.SplitWidget.SplitWidget, e => {output.splitWidget = e;})}>
556
+ <devtools-widget
557
+ slot="sidebar"
558
+ .widgetConfig=${widgetConfig(SecurityPanelSidebar)}
559
+ @showIPProtection=${() => output.setVisibleView(new IPProtectionView())}
560
+ @showCookieReport=${()=>output.setVisibleView(new CookieReportView())}
561
+ @showFlagControls=${() => output.setVisibleView(new CookieControlsView())}
562
+ ${UI.Widget.widgetRef(SecurityPanelSidebar, e => {output.sidebar = e;})}>
563
+ </devtools-widget>
564
+ </devtools-split-view>`,
565
+ target);
566
+ // clang-format on
567
+ };
568
+
552
569
  export class SecurityPanel extends UI.Panel.Panel implements SDK.TargetManager.SDKModelObserver<SecurityModel> {
553
570
  readonly mainView: SecurityMainView;
554
571
  readonly sidebar!: SecurityPanelSidebar;
@@ -560,24 +577,7 @@ export class SecurityPanel extends UI.Panel.Panel implements SDK.TargetManager.S
560
577
  private securityModel: SecurityModel|null;
561
578
  readonly splitWidget!: UI.SplitWidget.SplitWidget;
562
579
 
563
- constructor(private view: View = (_input, output, target) => {
564
- // clang-format off
565
- render(
566
- html`
567
- <devtools-split-view direction="column" name="security"
568
- ${UI.Widget.widgetRef(UI.SplitWidget.SplitWidget, e => {output.splitWidget = e;})}>
569
- <devtools-widget
570
- slot="sidebar"
571
- .widgetConfig=${widgetConfig(SecurityPanelSidebar)}
572
- @showIPProtection=${() => output.setVisibleView(new IPProtectionView())}
573
- @showCookieReport=${()=>output.setVisibleView(new CookieReportView())}
574
- @showFlagControls=${() => output.setVisibleView(new CookieControlsView())}
575
- ${UI.Widget.widgetRef(SecurityPanelSidebar, e => {output.sidebar = e;})}>
576
- </devtools-widget>
577
- </devtools-split-view>`,
578
- target, {host: this});
579
- // clang-format on
580
- }) {
580
+ constructor(private view: View = DEFAULT_VIEW) {
581
581
  super('security');
582
582
 
583
583
  this.update();
@@ -2,8 +2,6 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
6
-
7
5
  import '../../ui/components/linkifier/linkifier.js';
8
6
  import '../../ui/legacy/components/data_grid/data_grid.js';
9
7
 
@@ -125,24 +123,9 @@ interface ViewInput {
125
123
  }
126
124
  type View = (input: ViewInput, output: object, target: HTMLElement) => void;
127
125
 
128
- export class TimelineSelectorStatsView extends UI.Widget.VBox {
129
- #selectorLocations: Map<string, Protocol.CSS.SourceRange[]>;
130
- #parsedTrace: Trace.TraceModel.ParsedTrace|null = null;
131
- /**
132
- * We store the last event (or array of events) that we renderered. We do
133
- * this because as the user zooms around the panel this view is updated,
134
- * however if the set of events that are populating the view is the same as it
135
- * was the last time, we can bail without doing any re-rendering work.
136
- * If the user views a single event, this will be set to that single event, but if they are viewing a range of events, this will be set to an array.
137
- * If it's null, that means we have not rendered yet.
138
- */
139
- #lastStatsSourceEventOrEvents: Trace.Types.Events.RecalcStyle|Trace.Types.Events.RecalcStyle[]|null = null;
140
- #view: View;
141
- #timings: SelectorTiming[] = [];
142
-
143
- constructor(parsedTrace: Trace.TraceModel.ParsedTrace|null, view: View = (input, _, target) => {
144
- render(
145
- html`
126
+ const DEFAULT_VIEW: View = (input, _output, target) => {
127
+ render(
128
+ html`
146
129
  <devtools-data-grid striped name=${i18nString(UIStrings.selectorStats)}
147
130
  @contextmenu=${input.onContextMenu.bind(input)}>
148
131
  <table>
@@ -153,7 +136,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox {
153
136
  </th>
154
137
  <th id=${SelectorTimingsKey.InvalidationCount} weight="1.5" sortable hideable>
155
138
  <span title=${i18nString(UIStrings.invalidationCountExplanation)}>${
156
- i18nString(UIStrings.invalidationCount)}</span>
139
+ i18nString(UIStrings.invalidationCount)}</span>
157
140
  </th>
158
141
  <th id=${SelectorTimingsKey.MatchAttempts} weight="1" sortable hideable align="right">
159
142
  <span title=${i18nString(UIStrings.matchAttemptsExplanation)}>
@@ -165,7 +148,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox {
165
148
  </th>
166
149
  <th id=${SelectorTimingsKey.RejectPercentage} weight="1" sortable hideable align="right">
167
150
  <span title=${i18nString(UIStrings.slowPathNonMatchesExplanation)}>${
168
- i18nString(UIStrings.slowPathNonMatches)}</span>
151
+ i18nString(UIStrings.slowPathNonMatches)}</span>
169
152
  </th>
170
153
  <th id=${SelectorTimingsKey.Selector} weight="3" sortable hideable>
171
154
  <span title=${i18nString(UIStrings.selectorExplanation)}>
@@ -177,15 +160,15 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox {
177
160
  </th>
178
161
  </tr>
179
162
  ${input.timings.map(timing => {
180
- const nonMatches = timing[SelectorTimingsKey.MatchAttempts] - timing[SelectorTimingsKey.MatchCount];
181
- const slowPathNonMatches =
182
- (nonMatches ? 1.0 - timing[SelectorTimingsKey.FastRejectCount] / nonMatches : 0) * 100;
183
- const styleSheetId = timing[SelectorTimingsKey.StyleSheetId];
184
- const locations = timing.locations;
185
- const locationMessage = locations ? null :
186
- locations === null ? '' :
187
- i18nString(UIStrings.unableToLinkViaStyleSheetId, {PH1: styleSheetId});
188
- return html`<tr>
163
+ const nonMatches = timing[SelectorTimingsKey.MatchAttempts] - timing[SelectorTimingsKey.MatchCount];
164
+ const slowPathNonMatches =
165
+ (nonMatches ? 1.0 - timing[SelectorTimingsKey.FastRejectCount] / nonMatches : 0) * 100;
166
+ const styleSheetId = timing[SelectorTimingsKey.StyleSheetId];
167
+ const locations = timing.locations;
168
+ const locationMessage = locations ? null :
169
+ locations === null ? '' :
170
+ i18nString(UIStrings.unableToLinkViaStyleSheetId, {PH1: styleSheetId});
171
+ return html`<tr>
189
172
  <td data-value=${timing[SelectorTimingsKey.Elapsed]}>
190
173
  ${(timing[SelectorTimingsKey.Elapsed] / 1000.0).toFixed(3)}
191
174
  </td>
@@ -201,17 +184,34 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox {
201
184
  ${timing[SelectorTimingsKey.Selector]}
202
185
  </td>
203
186
  <td data-value=${styleSheetId}>${
204
- locations ? html`${locations.map((location, itemIndex) => html`
187
+ locations ? html`${locations.map((location, itemIndex) => html`
205
188
  <devtools-linkifier .data=${location}></devtools-linkifier
206
189
  >${itemIndex !== locations.length - 1 ? ',' : ''}`)}` :
207
- locationMessage}
190
+ locationMessage}
208
191
  </td>
209
192
  </tr>`;
210
- })}
193
+ })}
211
194
  </table>
212
195
  </devtools-data-grid>`,
213
- target, {host: this});
214
- }) {
196
+ target);
197
+ };
198
+
199
+ export class TimelineSelectorStatsView extends UI.Widget.VBox {
200
+ #selectorLocations: Map<string, Protocol.CSS.SourceRange[]>;
201
+ #parsedTrace: Trace.TraceModel.ParsedTrace|null = null;
202
+ /**
203
+ * We store the last event (or array of events) that we renderered. We do
204
+ * this because as the user zooms around the panel this view is updated,
205
+ * however if the set of events that are populating the view is the same as it
206
+ * was the last time, we can bail without doing any re-rendering work.
207
+ * If the user views a single event, this will be set to that single event, but if they are viewing a range of events, this will be set to an array.
208
+ * If it's null, that means we have not rendered yet.
209
+ */
210
+ #lastStatsSourceEventOrEvents: Trace.Types.Events.RecalcStyle|Trace.Types.Events.RecalcStyle[]|null = null;
211
+ #view: View;
212
+ #timings: SelectorTiming[] = [];
213
+
214
+ constructor(parsedTrace: Trace.TraceModel.ParsedTrace|null, view: View = DEFAULT_VIEW) {
215
215
  super({jslog: `${VisualLogging.pane('selector-stats').track({resize: true})}`});
216
216
  this.registerRequiredCSS(timelineSelectorStatsViewStyles);
217
217
 
@@ -1,7 +1,6 @@
1
1
  // Copyright 2024 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
5
4
 
6
5
  import * as Common from '../../../core/common/common.js';
7
6
  import * as i18n from '../../../core/i18n/i18n.js';
@@ -448,5 +447,5 @@ export const DEFAULT_VIEW: (input: SidebarAnnotationsTabViewInput, output: objec
448
447
  </setting-checkbox>`
449
448
  }
450
449
  </span>`,
451
- target, {host: target});
450
+ target);
452
451
  };
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: https://source.chromium.org/chromium/chromium/src/+/main:components/variations/proto/devtools/
3
3
  Version: N/A
4
- Revision: 2a28b0737c1e845353e9a2082e30ecd5043c0afe
4
+ Revision: c7f689c4ea24e98a4a1e06c78b10633db5a9f78f
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE
@@ -5,11 +5,11 @@
5
5
 
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
7
  import * as Platform from '../../../core/platform/platform.js';
8
- import * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';
9
8
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
10
9
  import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
11
10
  import * as Lit from '../../../ui/lit/lit.js';
12
11
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
12
+ import * as UI from '../../legacy/legacy.js';
13
13
  import * as Buttons from '../buttons/buttons.js';
14
14
 
15
15
  import dialogStyles from './dialog.css.js';
@@ -77,10 +77,6 @@ interface DialogData {
77
77
  */
78
78
  dialogShownCallback: (() => unknown)|null;
79
79
 
80
- /**
81
- * Optional. Service that provides the window dimensions used for positioning the Dialog.
82
- */
83
- windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsService;
84
80
  /**
85
81
  * Whether the dialog is closed when the 'Escape' key is pressed. When true, the event is
86
82
  * propagation is stopped.
@@ -132,7 +128,6 @@ export class Dialog extends HTMLElement {
132
128
  horizontalAlignment: DialogHorizontalAlignment.CENTER,
133
129
  getConnectorCustomXPosition: null,
134
130
  dialogShownCallback: null,
135
- windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsServiceImpl.instance(),
136
131
  closeOnESC: true,
137
132
  closeOnScroll: true,
138
133
  closeButton: false,
@@ -161,7 +156,7 @@ export class Dialog extends HTMLElement {
161
156
  this.#forceDialogCloseInDevToolsBound();
162
157
  });
163
158
  readonly #dialogResizeObserver = new ResizeObserver(this.#updateDialogBounds.bind(this));
164
- #devToolsBoundingElement = this.windowBoundsService.getDevToolsBoundingElement();
159
+ #devToolsBoundingElement = UI.UIUtils.getDevToolsBoundingElement();
165
160
 
166
161
  // We bind here because we have to listen to keydowns on the entire window,
167
162
  // not on the Dialog element itself. This is because if the user has the
@@ -204,16 +199,6 @@ export class Dialog extends HTMLElement {
204
199
  this.#onStateChange();
205
200
  }
206
201
 
207
- get windowBoundsService(): WindowBoundsService.WindowBoundsService.WindowBoundsService {
208
- return this.#props.windowBoundsService;
209
- }
210
-
211
- set windowBoundsService(windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsService) {
212
- this.#props.windowBoundsService = windowBoundsService;
213
- this.#devToolsBoundingElement = this.windowBoundsService.getDevToolsBoundingElement();
214
- this.#onStateChange();
215
- }
216
-
217
202
  get bestVerticalPosition(): DialogVerticalPosition|null {
218
203
  return this.#bestVerticalPosition;
219
204
  }
@@ -733,6 +718,11 @@ export class Dialog extends HTMLElement {
733
718
  VisualLogging.setMappedParent(this.#getDialog(), this.parentElementOrShadowHost() as HTMLElement);
734
719
  // clang-format on
735
720
  }
721
+
722
+ setBoundingElementForTesting(element: HTMLElement): void {
723
+ this.#devToolsBoundingElement = element;
724
+ this.#onStateChange();
725
+ }
736
726
  }
737
727
 
738
728
  customElements.define('devtools-dialog', Dialog);
@@ -3,8 +3,8 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../../core/common/common.js';
6
- import * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';
7
6
  import * as CodeMirror from '../../../third_party/codemirror.next/codemirror.next.js';
7
+ import * as UI from '../../legacy/legacy.js';
8
8
  import * as ThemeSupport from '../../legacy/theme_support/theme_support.js';
9
9
  import * as CodeHighlighter from '../code_highlighter/code_highlighter.js';
10
10
 
@@ -166,8 +166,7 @@ export class TextEditor extends HTMLElement {
166
166
  }
167
167
 
168
168
  #startObservingResize(): void {
169
- const devtoolsElement =
170
- WindowBoundsService.WindowBoundsService.WindowBoundsServiceImpl.instance().getDevToolsBoundingElement();
169
+ const devtoolsElement = UI.UIUtils.getDevToolsBoundingElement();
171
170
  if (devtoolsElement) {
172
171
  this.#devtoolsResizeObserver.observe(devtoolsElement);
173
172
  }
@@ -7,7 +7,6 @@ import * as Common from '../../../core/common/common.js';
7
7
  import type * as Host from '../../../core/host/host.js';
8
8
  import * as i18n from '../../../core/i18n/i18n.js';
9
9
  import * as TextUtils from '../../../models/text_utils/text_utils.js';
10
- import * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';
11
10
  import * as CM from '../../../third_party/codemirror.next/codemirror.next.js';
12
11
  import * as UI from '../../legacy/legacy.js';
13
12
  import * as VisualLogging from '../../visual_logging/visual_logging.js';
@@ -343,8 +342,7 @@ let sideBarElement: HTMLElement|null = null;
343
342
 
344
343
  function getTooltipSpace(): DOMRect {
345
344
  if (!sideBarElement) {
346
- sideBarElement =
347
- WindowBoundsService.WindowBoundsService.WindowBoundsServiceImpl.instance().getDevToolsBoundingElement();
345
+ sideBarElement = UI.UIUtils.getDevToolsBoundingElement();
348
346
  }
349
347
  return sideBarElement.getBoundingClientRect();
350
348
  }
@@ -56,6 +56,7 @@ import confirmDialogStyles from './confirmDialog.css.js';
56
56
  import {Dialog} from './Dialog.js';
57
57
  import {GlassPane, PointerEventsBehavior, SizeBehavior} from './GlassPane.js';
58
58
  import inspectorCommonStyles from './inspectorCommon.css.js';
59
+ import {InspectorView} from './InspectorView.js';
59
60
  import {KeyboardShortcut, Keys} from './KeyboardShortcut.js';
60
61
  import smallBubbleStyles from './smallBubble.css.js';
61
62
  import {Tooltip} from './Tooltip.js';
@@ -2348,3 +2349,7 @@ export function copyTextToClipboard(text: string, alert?: string): void {
2348
2349
  ARIAUtils.LiveAnnouncer.alert(alert);
2349
2350
  }
2350
2351
  }
2352
+
2353
+ export function getDevToolsBoundingElement(): HTMLElement {
2354
+ return InspectorView.maybeGetInspectorViewInstance()?.element || document.body;
2355
+ }
@@ -99,7 +99,7 @@ export class CSSAngle extends HTMLElement {
99
99
  this.angleElement = this.querySelector<HTMLElement>('.css-angle');
100
100
  }
101
101
  if (!this.swatchElement) {
102
- this.swatchElement = this.querySelector<HTMLElement>('devtools-css-angle-swatch');
102
+ this.swatchElement = this.querySelector('devtools-css-angle-swatch');
103
103
  }
104
104
  if (!this.angleElement || !this.swatchElement) {
105
105
  return;
@@ -4,7 +4,7 @@
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
6
  import * as i18n from '../../../../core/i18n/i18n.js';
7
- import * as WindowBounds from '../../../../services/window_bounds/window_bounds.js';
7
+ import * as UI from '../../legacy.js';
8
8
  import * as ThemeSupport from '../../theme_support/theme_support.js';
9
9
 
10
10
  import type {FlameChart} from './FlameChart.js';
@@ -124,7 +124,7 @@ export class BrickBreaker extends HTMLElement {
124
124
  #keyPressHandlerBound = this.#keyPressHandler.bind(this);
125
125
  #closeGameBound = this.#closeGame.bind(this);
126
126
  #mouseMoveHandlerBound = this.#mouseMoveHandler.bind(this);
127
- #boundingElement = WindowBounds.WindowBoundsService.WindowBoundsServiceImpl.instance().getDevToolsBoundingElement();
127
+ #boundingElement = UI.UIUtils.getDevToolsBoundingElement();
128
128
  // Value by which we moved the game up relative to the viewport
129
129
  #gameViewportOffset = 0;
130
130
  #running = false;