chrome-devtools-frontend 1.0.1602543 → 1.0.1603822

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 (47) hide show
  1. package/.agents/skills/version-control/SKILL.md +17 -2
  2. package/front_end/core/sdk/OverlayModel.ts +13 -13
  3. package/front_end/core/sdk/OverlayPersistentHighlighter.ts +13 -10
  4. package/front_end/core/sdk/RuntimeModel.ts +5 -5
  5. package/front_end/core/sdk/ServiceWorkerManager.ts +4 -2
  6. package/front_end/core/sdk/TargetManager.ts +5 -0
  7. package/front_end/core/sdk/WebMCPModel.ts +6 -0
  8. package/front_end/generated/InspectorBackendCommands.ts +3 -0
  9. package/front_end/generated/protocol-mapping.d.ts +8 -0
  10. package/front_end/generated/protocol-proxy-api.d.ts +10 -0
  11. package/front_end/generated/protocol.ts +57 -0
  12. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +16 -5
  13. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.snapshot.txt +60 -9
  14. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.ts +71 -15
  15. package/front_end/models/javascript_metadata/NativeFunctions.js +6 -2
  16. package/front_end/models/lighthouse/LighthouseReporterTypes.ts +10 -8
  17. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +4 -3
  18. package/front_end/panels/ai_assistance/components/ChatMessage.ts +83 -19
  19. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +30 -10
  20. package/front_end/panels/ai_assistance/components/chatMessage.css +33 -7
  21. package/front_end/panels/ai_assistance/components/walkthroughView.css +35 -5
  22. package/front_end/panels/common/ThrottlingUtils.ts +46 -0
  23. package/front_end/panels/common/common.ts +1 -0
  24. package/front_end/panels/elements/ComputedStyleWidget.ts +11 -1
  25. package/front_end/panels/elements/StandaloneStylesContainer.ts +0 -3
  26. package/front_end/panels/elements/StylePropertiesSection.ts +0 -49
  27. package/front_end/panels/elements/StylesContainer.ts +0 -1
  28. package/front_end/panels/elements/StylesSidebarPane.ts +32 -7
  29. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +14 -0
  30. package/front_end/panels/profiler/ProfileView.ts +0 -9
  31. package/front_end/panels/settings/keybindsSettingsTab.css +25 -31
  32. package/front_end/panels/timeline/ThirdPartyTreeView.ts +8 -0
  33. package/front_end/panels/timeline/TimelinePanel.ts +14 -2
  34. package/front_end/panels/timeline/components/FieldSettingsDialog.ts +5 -9
  35. package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -2
  36. package/front_end/panels/timeline/components/OriginMap.ts +176 -159
  37. package/front_end/panels/timeline/components/originMap.css +4 -51
  38. package/front_end/panels/timeline/thirdPartyTreeView.css +6 -0
  39. package/front_end/panels/timeline/timeline-meta.ts +11 -0
  40. package/front_end/panels/timeline/utils/Helpers.ts +5 -25
  41. package/front_end/third_party/acorn/README.chromium +1 -0
  42. package/front_end/third_party/chromium/README.chromium +1 -1
  43. package/front_end/ui/components/{list → lists}/List.ts +1 -1
  44. package/front_end/ui/components/{list → lists}/list.css +0 -1
  45. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +3 -3
  46. package/package.json +1 -1
  47. /package/front_end/ui/components/{list → lists}/lists.ts +0 -0
@@ -0,0 +1,46 @@
1
+ // Copyright 2026 The Chromium Authors
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 SDK from '../../core/sdk/sdk.js';
6
+ import * as CrUXManager from '../../models/crux-manager/crux-manager.js';
7
+
8
+ export interface ThrottlingRecommendations {
9
+ cpuOption: SDK.CPUThrottlingManager.CPUThrottlingOption|null;
10
+ networkConditions: SDK.NetworkManager.Conditions|null;
11
+ }
12
+
13
+ /**
14
+ * Computes the recommended CPU and network throttling presets based on CrUX
15
+ * field metric data.
16
+ */
17
+ export function getThrottlingRecommendations(): ThrottlingRecommendations {
18
+ const cruxManager = CrUXManager.CrUXManager.instance();
19
+ const roundTripTimeMetricData = cruxManager.getSelectedFieldMetricData('round_trip_time');
20
+
21
+ let cpuOption: SDK.CPUThrottlingManager.CPUThrottlingOption =
22
+ SDK.CPUThrottlingManager.CalibratedMidTierMobileThrottlingOption;
23
+ if (cpuOption.rate() === 0) {
24
+ cpuOption = SDK.CPUThrottlingManager.MidTierThrottlingOption;
25
+ }
26
+
27
+ const networkConditions = getRecommendedNetworkConditions(roundTripTimeMetricData);
28
+
29
+ return {
30
+ cpuOption,
31
+ networkConditions,
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Computes the recommended network throttling preset based on CrUX RTT field
37
+ * metric data. Returns null if no RTT data is available or no preset matches.
38
+ */
39
+ export function getRecommendedNetworkConditions(roundTripTimeMetricData?: CrUXManager.MetricResponse):
40
+ SDK.NetworkManager.Conditions|null {
41
+ if (roundTripTimeMetricData?.percentiles) {
42
+ const rtt = Number(roundTripTimeMetricData.percentiles.p75);
43
+ return SDK.NetworkManager.getRecommendedNetworkPreset(rtt);
44
+ }
45
+ return null;
46
+ }
@@ -109,5 +109,6 @@ export * as ExtensionServer from './ExtensionServer.js';
109
109
  export * as ExtensionView from './ExtensionView.js';
110
110
  export * as PersistenceUtils from './PersistenceUtils.js';
111
111
  export * as DOMLinkifier from './DOMLinkifier.js';
112
+ export * as ThrottlingUtils from './ThrottlingUtils.js';
112
113
  export * as ExtensionIframe from './ExtensionView.js';
113
114
  export {CopyChangesToPrompt} from './CopyChangesToPrompt.js';
@@ -331,6 +331,7 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
331
331
 
332
332
  #computedStylesTree = new TreeOutline.TreeOutline.TreeOutline<ComputedStyleData>();
333
333
  #treeData?: TreeOutline.TreeOutline.TreeOutlineData<ComputedStyleData>;
334
+ #enableNarrowViewResizing = true;
334
335
  readonly #view: View;
335
336
 
336
337
  /**
@@ -378,10 +379,19 @@ export class ComputedStyleWidget extends UI.Widget.VBox {
378
379
  }
379
380
 
380
381
  override onResize(): void {
381
- const isNarrow = this.contentElement.offsetWidth < 260;
382
+ const isNarrow = this.#enableNarrowViewResizing && this.contentElement.offsetWidth < 260;
382
383
  this.#computedStylesTree.classList.toggle('computed-narrow', isNarrow);
383
384
  }
384
385
 
386
+ get enableNarrowViewResizing(): boolean {
387
+ return this.#enableNarrowViewResizing;
388
+ }
389
+
390
+ set enableNarrowViewResizing(enable: boolean) {
391
+ this.#enableNarrowViewResizing = enable;
392
+ this.onResize();
393
+ }
394
+
385
395
  get filterText(): RegExp|string {
386
396
  if (this.#filterIsRegex) {
387
397
  return new RegExp(this.#filterText);
@@ -115,9 +115,6 @@ export class StandaloneStylesContainer extends Common.ObjectWrapper.eventMixin<E
115
115
  }
116
116
 
117
117
  async #updateSections(signal?: AbortSignal): Promise<void> {
118
- for (const section of this.#sections) {
119
- section.dispose();
120
- }
121
118
  const node = this.node();
122
119
  if (!node) {
123
120
  this.#sections = [];
@@ -44,7 +44,6 @@ import * as SDK from '../../core/sdk/sdk.js';
44
44
  import * as Protocol from '../../generated/protocol.js';
45
45
  import * as Badges from '../../models/badges/badges.js';
46
46
  import * as Bindings from '../../models/bindings/bindings.js';
47
- import * as ComputedStyle from '../../models/computed_style/computed_style.js';
48
47
  import * as TextUtils from '../../models/text_utils/text_utils.js';
49
48
  import * as Buttons from '../../ui/components/buttons/buttons.js';
50
49
  import * as Tooltips from '../../ui/components/tooltips/tooltips.js';
@@ -375,55 +374,12 @@ export class StylePropertiesSection {
375
374
  this.markSelectorMatches();
376
375
  this.onpopulate();
377
376
  this.#updateCollapsedState();
378
-
379
- this.stylesContainer.computedStyleModel().addEventListener(
380
- ComputedStyle.ComputedStyleModel.Events.CSS_MODEL_CHANGED, this.#onCSSModelChanged, this);
381
377
  }
382
378
 
383
379
  setComputedStyles(computedStyles: Map<string, string>|null): void {
384
380
  this.computedStyles = computedStyles;
385
381
  }
386
382
 
387
- #onCSSModelChanged(event: Common.EventTarget.EventTargetEvent<ComputedStyle.ComputedStyleModel.CSSModelChangedEvent>):
388
- void {
389
- const edit = event?.data && 'edit' in event.data ? event.data.edit : null;
390
- if (edit) {
391
- this.styleSheetEdited(edit);
392
- void this.refreshComputedValues();
393
- return;
394
- }
395
-
396
- if (this.stylesContainer.isEditingStyle || this.stylesContainer.userOperation) {
397
- void this.refreshComputedValues();
398
- }
399
- }
400
-
401
- async refreshComputedValues(): Promise<void> {
402
- const node = this.stylesContainer.node();
403
- if (!node) {
404
- return;
405
- }
406
-
407
- const cssModel = node.domModel().cssModel();
408
- const computedStyleModel = this.stylesContainer.computedStyleModel();
409
-
410
- const matchedStyles = await cssModel.cachedMatchedCascadeForNode(node);
411
- const parentNodeId = matchedStyles?.getParentLayoutNodeId();
412
-
413
- const [computedStyles, parentsComputedStyles] = await Promise.all([
414
- computedStyleModel.fetchComputedStyle(),
415
- parentNodeId ? cssModel.getComputedStyle(parentNodeId) : null,
416
- ]);
417
-
418
- if (computedStyles) {
419
- this.setComputedStyles(computedStyles.computedStyle);
420
- }
421
- if (parentsComputedStyles) {
422
- this.setParentsComputedStyles(parentsComputedStyles);
423
- }
424
- this.updateAuthoringHint();
425
- }
426
-
427
383
  setParentsComputedStyles(parentsComputedStyles: Map<string, string>|null): void {
428
384
  this.parentsComputedStyles = parentsComputedStyles;
429
385
  }
@@ -444,11 +400,6 @@ export class StylePropertiesSection {
444
400
  }
445
401
  }
446
402
 
447
- dispose(): void {
448
- this.stylesContainer.computedStyleModel().removeEventListener(
449
- ComputedStyle.ComputedStyleModel.Events.CSS_MODEL_CHANGED, this.#onCSSModelChanged, this);
450
- }
451
-
452
403
  setSectionIdx(sectionIdx: number): void {
453
404
  this.sectionIdx = sectionIdx;
454
405
  this.onpopulate();
@@ -17,7 +17,6 @@ export interface StylesContainer {
17
17
  activeCSSAngle: InlineEditor.CSSAngle.CSSAngle|null;
18
18
  readonly webCustomData: WebCustomData|undefined;
19
19
  isEditingStyle: boolean;
20
- userOperation: boolean;
21
20
  readonly sectionByElement: WeakMap<Node, StylePropertiesSection>;
22
21
  readonly element: HTMLElement;
23
22
  readonly linkifier: Components.Linkifier.Linkifier;
@@ -189,7 +189,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
189
189
  private readonly decorator: StylePropertyHighlighter;
190
190
 
191
191
  private lastRevealedProperty: SDK.CSSProperty.CSSProperty|null = null;
192
- userOperation = false;
192
+ private userOperation = false;
193
193
  isEditingStyle = false;
194
194
  #filterRegex: RegExp|null = null;
195
195
  #isRegex = false;
@@ -211,6 +211,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
211
211
  #webCustomData?: WebCustomData;
212
212
 
213
213
  activeCSSAngle: InlineEditor.CSSAngle.CSSAngle|null = null;
214
+ #updateAbortController?: AbortController;
215
+ #updateComputedStylesAbortController?: AbortController;
214
216
 
215
217
  constructor(computedStyleModel: ComputedStyle.ComputedStyleModel.ComputedStyleModel) {
216
218
  super(computedStyleModel, {delegatesFocus: true});
@@ -688,9 +690,12 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
688
690
 
689
691
  override onCSSModelChanged(
690
692
  event: Common.EventTarget.EventTargetEvent<ComputedStyle.ComputedStyleModel.CSSModelChangedEvent>): void {
691
- // We only recreate sections if this update is more than an "edit" operation.
692
- // Sections will pull their own updates in the case of an "edit".
693
- if (event?.data && 'edit' in event.data && event.data.edit) {
693
+ const edit = event?.data && 'edit' in event.data ? event.data.edit : null;
694
+ if (edit) {
695
+ for (const section of this.allSections()) {
696
+ section.styleSheetEdited(edit);
697
+ }
698
+ void this.#refreshComputedStyles();
694
699
  return;
695
700
  }
696
701
 
@@ -713,6 +718,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
713
718
 
714
719
  #resetUpdateIfNotEditing(): void {
715
720
  if (this.userOperation || this.isEditingStyle) {
721
+ void this.#refreshComputedStyles();
716
722
  return;
717
723
  }
718
724
 
@@ -861,6 +867,28 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
861
867
  }
862
868
  }
863
869
 
870
+ async #refreshComputedStyles(): Promise<void> {
871
+ this.#updateComputedStylesAbortController?.abort();
872
+ this.#updateAbortController = new AbortController();
873
+ const signal = this.#updateAbortController.signal;
874
+ const matchedStyles = await this.fetchMatchedCascade();
875
+ const nodeId = this.node()?.id;
876
+ const parentNodeId = matchedStyles?.getParentLayoutNodeId();
877
+
878
+ const [computedStyles, parentsComputedStyles] =
879
+ await Promise.all([this.fetchComputedStylesFor(nodeId), this.fetchComputedStylesFor(parentNodeId)]);
880
+
881
+ if (signal.aborted) {
882
+ return;
883
+ }
884
+
885
+ for (const section of this.allSections()) {
886
+ section.setComputedStyles(computedStyles);
887
+ section.setParentsComputedStyles(parentsComputedStyles);
888
+ section.updateAuthoringHint();
889
+ }
890
+ }
891
+
864
892
  focusedSectionIndex(): number {
865
893
  let index = 0;
866
894
  for (const block of this.sectionBlocks) {
@@ -903,9 +931,6 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
903
931
 
904
932
  this.linkifier.reset();
905
933
  const prevSections = this.sectionBlocks.map(block => block.sections).flat();
906
- for (const section of prevSections) {
907
- section.dispose();
908
- }
909
934
  this.sectionBlocks = [];
910
935
 
911
936
  const node = this.node();
@@ -6,9 +6,11 @@ import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import * as Platform from '../../core/platform/platform.js';
8
8
  import * as SDK from '../../core/sdk/sdk.js';
9
+ import * as CrUXManager from '../../models/crux-manager/crux-manager.js';
9
10
  import * as UI from '../../ui/legacy/legacy.js';
10
11
  import * as Lit from '../../ui/lit/lit.js';
11
12
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
13
+ import * as PanelsCommon from '../common/common.js';
12
14
 
13
15
  import {ThrottlingManager} from './ThrottlingManager.js';
14
16
  import type {NetworkThrottlingConditionsGroup} from './ThrottlingPresets.js';
@@ -185,6 +187,18 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
185
187
  SDK.NetworkManager.MultitargetNetworkManager.Events.CONDITIONS_CHANGED, () => {
186
188
  select.currentConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions();
187
189
  });
190
+
191
+ // Subscribe to CrUX field data changes to show recommended throttling
192
+ // presets based on real-user RTT data.
193
+ const cruxManager = CrUXManager.CrUXManager.instance();
194
+ const updateRecommendation = (): void => {
195
+ const roundTripTimeMetricData = cruxManager.getSelectedFieldMetricData('round_trip_time');
196
+ select.recommendedConditions =
197
+ PanelsCommon.ThrottlingUtils.getRecommendedNetworkConditions(roundTripTimeMetricData);
198
+ };
199
+ cruxManager.addEventListener(CrUXManager.Events.FIELD_DATA_CHANGED, updateRecommendation);
200
+ updateRecommendation();
201
+
188
202
  return select;
189
203
  }
190
204
 
@@ -298,9 +298,6 @@ export class ProfileView extends UI.View.SimpleView implements UI.SearchableView
298
298
  if (!this.profileDataGridTree) {
299
299
  return;
300
300
  }
301
- const selectedProfileNode =
302
- this.dataGrid.selectedNode ? (this.dataGrid.selectedNode as ProfileDataGridNode).profileNode : null;
303
-
304
301
  this.dataGrid.rootNode().removeChildren();
305
302
 
306
303
  const children = this.profileDataGridTree.children;
@@ -309,12 +306,6 @@ export class ProfileView extends UI.View.SimpleView implements UI.SearchableView
309
306
  for (let index = 0; index < count; ++index) {
310
307
  this.dataGrid.rootNode().appendChild(children[index]);
311
308
  }
312
-
313
- if (selectedProfileNode) {
314
- // TODO(crbug.com/1011811): Cleanup the added `selected` property to this SDK class.
315
- // @ts-expect-error
316
- selectedProfileNode.selected = true;
317
- }
318
309
  }
319
310
 
320
311
  refreshVisibleData(): void {
@@ -35,7 +35,7 @@
35
35
  background-color: var(--sys-color-tonal-container);
36
36
  }
37
37
 
38
- .keybinds-list-item.keybinds-editing {
38
+ .keybinds-list-item-wrapper:has(.keybinds-list-item.keybinds-editing) {
39
39
  background-color: var(--sys-color-neutral-container);
40
40
  }
41
41
 
@@ -168,31 +168,30 @@ button.text-button {
168
168
  }
169
169
 
170
170
  @media (forced-colors: active) {
171
- /* Keyboard focus on wrapper element (shortcut items) */
171
+ .keybinds-list-item.keybinds-editing .keybinds-shortcut {
172
+ & devtools-button {
173
+ --sys-color-primary: buttonFace;
174
+ }
175
+ }
176
+
177
+ .keybinds-list-text input {
178
+ color: buttonText;
179
+ }
180
+
181
+ /* Keyboard focus / hover on wrapper element (shortcut items) */
172
182
  .keybinds-list-item-wrapper {
183
+ &:has(.keybinds-list-item:hover),
184
+ &:has(.keybinds-list-item:not(.keybinds-editing)):focus-within,
173
185
  &:focus,
174
186
  &:focus-visible {
175
- background-color: Highlight !important; /* stylelint-disable-line declaration-no-important */
187
+ background-color: Highlight;
176
188
  forced-color-adjust: none;
177
189
 
190
+ --icon-default: HighlightText;
191
+
178
192
  & .keybinds-list-text,
179
193
  & .keybinds-action-name {
180
- color: HighlightText !important; /* stylelint-disable-line declaration-no-important */
181
- }
182
-
183
- & .keybinds-key {
184
- background: HighlightText;
185
- color: Highlight;
186
- }
187
- }
188
-
189
- /* Hover state (shortcut items) */
190
- &:has(.keybinds-list-item:hover) {
191
- background-color: Highlight !important; /* stylelint-disable-line declaration-no-important */
192
- forced-color-adjust: none;
193
-
194
- & .keybinds-list-text {
195
- color: HighlightText !important; /* stylelint-disable-line declaration-no-important */
194
+ color: HighlightText;
196
195
  }
197
196
 
198
197
  & .keybinds-key {
@@ -203,23 +202,18 @@ button.text-button {
203
202
  }
204
203
 
205
204
  /* Editing state */
206
- .keybinds-list-item.keybinds-editing {
207
- background-color: Highlight !important; /* stylelint-disable-line declaration-no-important */
205
+ .keybinds-list-item-wrapper:has(.keybinds-list-item.keybinds-editing) {
206
+ background-color: Highlight;
208
207
  forced-color-adjust: none;
209
208
 
209
+ --icon-default: HighlightText;
210
+
210
211
  & .keybinds-list-text {
211
- color: HighlightText !important; /* stylelint-disable-line declaration-no-important */
212
+ color: HighlightText;
212
213
  }
213
- }
214
214
 
215
- /* Category headers (e.g., "Background Services", "Debugger") */
216
- .keybinds-category-header {
217
- &:hover,
218
- &:focus,
219
- &:focus-visible {
220
- background-color: Highlight !important; /* stylelint-disable-line declaration-no-important */
221
- color: HighlightText !important; /* stylelint-disable-line declaration-no-important */
222
- forced-color-adjust: none;
215
+ & .keybinds-error {
216
+ color: highlightText;
223
217
  }
224
218
  }
225
219
  }
@@ -257,6 +257,8 @@ export class ThirdPartyTreeViewWidget extends TimelineTreeView.TimelineTreeView
257
257
  export class ThirdPartyTreeElement extends UI.Widget.WidgetElement<UI.Widget.Widget> {
258
258
  #treeView?: ThirdPartyTreeViewWidget;
259
259
 
260
+ static readonly observedAttributes = ['max-rows'];
261
+
260
262
  set treeView(treeView: ThirdPartyTreeViewWidget) {
261
263
  this.#treeView = treeView;
262
264
  }
@@ -266,6 +268,12 @@ export class ThirdPartyTreeElement extends UI.Widget.WidgetElement<UI.Widget.Wid
266
268
  this.style.display = 'contents';
267
269
  }
268
270
 
271
+ attributeChangedCallback(name: string, _oldValue: string|null, newValue: string|null): void {
272
+ if (name === 'max-rows' && newValue) {
273
+ this.style.setProperty('--max-rows', newValue);
274
+ }
275
+ }
276
+
269
277
  override createWidget(): UI.Widget.Widget {
270
278
  const containerWidget = new UI.Widget.Widget(this);
271
279
  containerWidget.contentElement.style.display = 'contents';
@@ -62,6 +62,7 @@ import * as SettingsUI from '../../ui/legacy/components/settings_ui/settings_ui.
62
62
  import * as UI from '../../ui/legacy/legacy.js';
63
63
  import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
64
64
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
65
+ import * as PanelsCommon from '../common/common.js';
65
66
  import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
66
67
 
67
68
  import {ActiveFilters} from './ActiveFilters.js';
@@ -93,7 +94,7 @@ import {TimelineUIUtils} from './TimelineUIUtils.js';
93
94
  import {createHiddenTracksOverlay} from './TrackConfigBanner.js';
94
95
  import {UIDevtoolsController} from './UIDevtoolsController.js';
95
96
  import {UIDevtoolsUtils} from './UIDevtoolsUtils.js';
96
- import * as Utils from './utils/utils.js';
97
+ import type * as Utils from './utils/utils.js';
97
98
 
98
99
  const UIStrings = {
99
100
  /**
@@ -800,7 +801,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
800
801
  }
801
802
 
802
803
  #onFieldDataChanged(): void {
803
- const recs = Utils.Helpers.getThrottlingRecommendations();
804
+ const recs = PanelsCommon.ThrottlingUtils.getThrottlingRecommendations();
804
805
  this.cpuThrottlingSelect?.updateRecommendedOption(recs.cpuOption);
805
806
  if (this.networkThrottlingSelect) {
806
807
  this.networkThrottlingSelect.recommendedConditions = recs.networkConditions;
@@ -3281,6 +3282,17 @@ export class CoreVitalsRevealer implements Common.Revealer.Revealer<Utils.Helper
3281
3282
  }
3282
3283
  }
3283
3284
 
3285
+ export class TimeRangeRevealer implements Common.Revealer.Revealer<Utils.Helpers.RevealableTimeRange> {
3286
+ async reveal(revealable: Utils.Helpers.RevealableTimeRange): Promise<void> {
3287
+ await UI.ViewManager.ViewManager.instance().showView('timeline');
3288
+ const panel = TimelinePanel.instance();
3289
+ TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(
3290
+ revealable.bounds, {ignoreMiniMapBounds: true, shouldAnimate: true});
3291
+ panel.select(null);
3292
+ panel.getFlameChart().selectDetailsViewTab(Tab.Details, null);
3293
+ }
3294
+ }
3295
+
3284
3296
  export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
3285
3297
  handleAction(context: UI.Context.Context, actionId: string): boolean {
3286
3298
  const panel = context.flavor(TimelinePanel);
@@ -4,7 +4,6 @@
4
4
  /* eslint-disable @devtools/no-lit-render-outside-of-view */
5
5
 
6
6
  import '../../../ui/kit/kit.js';
7
- import './OriginMap.js';
8
7
 
9
8
  import * as i18n from '../../../core/i18n/i18n.js';
10
9
  import * as CrUXManager from '../../../models/crux-manager/crux-manager.js';
@@ -13,11 +12,12 @@ import * as Dialogs from '../../../ui/components/dialogs/dialogs.js';
13
12
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
14
13
  import * as Input from '../../../ui/components/input/input.js';
15
14
  import * as uiI18n from '../../../ui/i18n/i18n.js';
15
+ import * as UI from '../../../ui/legacy/legacy.js';
16
16
  import * as Lit from '../../../ui/lit/lit.js';
17
17
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
18
18
 
19
19
  import fieldSettingsDialogStyles from './fieldSettingsDialog.css.js';
20
- import type {OriginMap} from './OriginMap.js';
20
+ import {OriginMap} from './OriginMap.js';
21
21
 
22
22
  const UIStrings = {
23
23
  /**
@@ -95,6 +95,7 @@ const str_ = i18n.i18n.registerUIStrings('panels/timeline/components/FieldSettin
95
95
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
96
96
 
97
97
  const {html, nothing, Directives: {ifDefined}} = Lit;
98
+ const {widget, widgetRef} = UI.Widget;
98
99
 
99
100
  export class ShowDialog extends Event {
100
101
  static readonly eventName = 'showdialog';
@@ -309,13 +310,8 @@ export class FieldSettingsDialog extends HTMLElement {
309
310
  // clang-format off
310
311
  return html`
311
312
  <div class="origin-mapping-description">${i18nString(UIStrings.mapDevelopmentOrigins)}</div>
312
- <devtools-origin-map
313
- ${Lit.Directives.ref(el => {
314
- if (el instanceof HTMLElement) {
315
- this.#originMap = el as OriginMap;
316
- }
317
- })}
318
- ></devtools-origin-map>
313
+ <devtools-widget ${widget(OriginMap)} ${widgetRef(OriginMap, el => { this.#originMap = el; })}>
314
+ </devtools-widget>
319
315
  <div class="origin-mapping-button-section">
320
316
  <devtools-button
321
317
  @click=${() => this.#originMap?.startCreation()}
@@ -31,7 +31,6 @@ import * as UI from '../../../ui/legacy/legacy.js';
31
31
  import * as Lit from '../../../ui/lit/lit.js';
32
32
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
33
33
  import * as PanelsCommon from '../../common/common.js';
34
- import * as Utils from '../utils/utils.js';
35
34
 
36
35
  import {CPUThrottlingSelector} from './CPUThrottlingSelector.js';
37
36
  import {md} from './insights/Helpers.js';
@@ -636,7 +635,7 @@ export class LiveMetricsView extends LegacyWrapper.LegacyWrapper.WrappableCompon
636
635
  networkRecEl.classList.add('environment-rec');
637
636
  networkRecEl.textContent = this.#getNetworkRecTitle() || i18nString(UIStrings.notEnoughData);
638
637
 
639
- const recs = Utils.Helpers.getThrottlingRecommendations();
638
+ const recs = PanelsCommon.ThrottlingUtils.getThrottlingRecommendations();
640
639
 
641
640
  // clang-format off
642
641
  return html`