chrome-devtools-frontend 1.0.1545096 → 1.0.1547147

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 (124) hide show
  1. package/docs/styleguide/ux/styles.md +1 -1
  2. package/eslint.config.mjs +1 -1
  3. package/front_end/Images/src/arrow-down.svg +8 -1
  4. package/front_end/Images/src/arrow-up.svg +8 -1
  5. package/front_end/core/host/AidaClient.ts +1 -1
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  7. package/front_end/core/host/UserMetrics.ts +0 -5
  8. package/front_end/core/platform/HostRuntime.ts +18 -0
  9. package/front_end/core/platform/KeyboardUtilities.ts +2 -2
  10. package/front_end/core/platform/StringUtilities.ts +1 -1
  11. package/front_end/core/platform/api/HostRuntime.ts +20 -0
  12. package/front_end/core/platform/api/api.ts +7 -0
  13. package/front_end/core/platform/browser/HostRuntime.ts +14 -0
  14. package/front_end/core/platform/browser/browser.ts +7 -0
  15. package/front_end/core/platform/node/HostRuntime.ts +13 -0
  16. package/front_end/core/platform/node/node.ts +7 -0
  17. package/front_end/core/platform/platform.ts +2 -2
  18. package/front_end/core/sdk/SourceMapScopesInfo.ts +141 -23
  19. package/front_end/core/sdk/Target.ts +5 -14
  20. package/front_end/core/sdk/TargetManager.ts +26 -4
  21. package/front_end/core/sdk/sdk-meta.ts +62 -0
  22. package/front_end/devtools_compatibility.js +0 -1
  23. package/front_end/entrypoints/main/MainImpl.ts +2 -2
  24. package/front_end/foundation/Universe.ts +2 -2
  25. package/front_end/generated/Deprecation.ts +7 -0
  26. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  27. package/front_end/generated/SupportedCSSProperties.js +4 -2
  28. package/front_end/generated/protocol.ts +3 -2
  29. package/front_end/models/ai_assistance/AiConversation.ts +188 -0
  30. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -172
  31. package/front_end/models/ai_assistance/ConversationHandler.ts +5 -5
  32. package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -3
  33. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +6 -2
  34. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -1
  35. package/front_end/models/ai_assistance/agents/StylingAgent.ts +3 -9
  36. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  37. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +313 -313
  38. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +8 -6
  39. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +33 -33
  40. package/front_end/models/ai_assistance/performance/AICallTree.ts +9 -3
  41. package/front_end/models/bindings/CSSWorkspaceBinding.ts +5 -3
  42. package/front_end/models/bindings/SASSSourceMapping.ts +6 -4
  43. package/front_end/models/cpu_profile/CPUProfileDataModel.ts +10 -7
  44. package/front_end/models/crux-manager/CrUXManager.ts +7 -4
  45. package/front_end/models/issues_manager/GenericIssue.ts +12 -9
  46. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  47. package/front_end/models/trace/handlers/SamplesHandler.ts +3 -0
  48. package/front_end/models/trace/helpers/Trace.ts +13 -0
  49. package/front_end/models/trace/types/TraceEvents.ts +2 -1
  50. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +29 -0
  51. package/front_end/models/workspace/IgnoreListManager.ts +1 -2
  52. package/front_end/models/workspace/UISourceCode.ts +50 -0
  53. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +9 -9
  54. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +8 -0
  55. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -2
  56. package/front_end/panels/animation/AnimationTimeline.ts +0 -8
  57. package/front_end/panels/application/FrameDetailsView.ts +8 -8
  58. package/front_end/panels/application/components/StackTrace.ts +84 -85
  59. package/front_end/panels/common/AiCodeGenerationTeaser.ts +80 -0
  60. package/front_end/panels/common/common.ts +2 -1
  61. package/front_end/panels/console/ConsolePrompt.ts +3 -1
  62. package/front_end/panels/console/ConsoleViewport.ts +1 -2
  63. package/front_end/panels/elements/ElementIssueUtils.ts +2 -2
  64. package/front_end/panels/elements/StylePropertyTreeElement.ts +23 -19
  65. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  66. package/front_end/panels/elements/cssValueTraceView.css +1 -1
  67. package/front_end/panels/elements/elements-meta.ts +1 -0
  68. package/front_end/panels/explain/components/ConsoleInsight.ts +44 -57
  69. package/front_end/panels/explain/components/consoleInsight.css +46 -1
  70. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +1 -2
  71. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +19 -0
  72. package/front_end/panels/network/RequestConditionsDrawer.ts +54 -24
  73. package/front_end/panels/network/networkLogView.css +11 -0
  74. package/front_end/panels/network/networkTimingTable.css +8 -6
  75. package/front_end/panels/network/requestConditionsDrawer.css +10 -1
  76. package/front_end/panels/profiler/ProfilesPanel.ts +1 -2
  77. package/front_end/panels/settings/KeybindsSettingsTab.ts +20 -21
  78. package/front_end/panels/sources/CoveragePlugin.ts +5 -5
  79. package/front_end/panels/sources/Plugin.ts +1 -1
  80. package/front_end/panels/sources/ProfilePlugin.ts +22 -14
  81. package/front_end/panels/sources/UISourceCodeFrame.ts +2 -1
  82. package/front_end/panels/sources/sources-meta.ts +0 -62
  83. package/front_end/panels/timeline/README.md +1 -9
  84. package/front_end/panels/timeline/ThreadAppender.ts +0 -7
  85. package/front_end/panels/timeline/TimelinePanel.ts +1 -1
  86. package/front_end/panels/timeline/TimelineUIUtils.ts +2 -0
  87. package/front_end/panels/timeline/components/ExportTraceOptions.ts +15 -1
  88. package/front_end/panels/timeline/components/LiveMetricsView.ts +37 -1
  89. package/front_end/panels/timeline/components/exportTraceOptions.css +11 -2
  90. package/front_end/third_party/chromium/README.chromium +1 -1
  91. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +1 -0
  92. package/front_end/ui/legacy/ARIAUtils.ts +2 -2
  93. package/front_end/ui/legacy/ActionRegistration.ts +11 -0
  94. package/front_end/ui/legacy/SoftDropDown.ts +2 -2
  95. package/front_end/ui/legacy/TextPrompt.ts +3 -2
  96. package/front_end/ui/legacy/Treeoutline.ts +2 -1
  97. package/front_end/ui/legacy/UIUtils.ts +11 -10
  98. package/front_end/ui/legacy/Widget.ts +3 -2
  99. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +2 -2
  100. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +62 -39
  101. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +1 -1
  102. package/front_end/ui/legacy/components/perf_ui/TimelineGrid.ts +2 -2
  103. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -7
  104. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +1 -2
  105. package/front_end/ui/legacy/inspectorCommon.css +2 -2
  106. package/front_end/ui/legacy/legacy.ts +2 -0
  107. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  108. package/package.json +1 -1
  109. package/front_end/panels/explain/components/consoleInsightSourcesList.css +0 -51
  110. package/front_end/ui/components/docs/README.md +0 -6
  111. package/front_end/ui/components/docs/building-ui-documentation/ComponentEvents.md +0 -54
  112. package/front_end/ui/components/docs/building-ui-documentation/ComponentPerformance.md +0 -136
  113. package/front_end/ui/components/docs/building-ui-documentation/CreatingComponents.md +0 -242
  114. package/front_end/ui/components/docs/building-ui-documentation/README.md +0 -23
  115. package/front_end/ui/components/docs/building-ui-documentation/StylingComponents.md +0 -66
  116. package/front_end/ui/components/docs/building-ui-documentation/TestingComponents.md +0 -111
  117. package/front_end/ui/components/docs/component_docs.ts +0 -24
  118. package/front_end/ui/components/docs/component_docs_styles.css +0 -53
  119. package/front_end/ui/components/docs/create_breadcrumbs.ts +0 -44
  120. package/front_end/ui/components/docs/slider/basic.html +0 -20
  121. package/front_end/ui/components/docs/switch/basic.html +0 -20
  122. /package/front_end/models/issues_manager/descriptions/{genericFormAriaLabelledByToNonExistingId.md → genericFormAriaLabelledByToNonExistingIdError.md} +0 -0
  123. /package/front_end/models/issues_manager/descriptions/{genericFormLabelHasNeitherForNorNestedInput.md → genericFormLabelHasNeitherForNorNestedInputError.md} +0 -0
  124. /package/front_end/{core/platform → ui/legacy}/DOMUtilities.ts +0 -0
@@ -20,7 +20,6 @@ import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
20
20
  import * as Console from '../../console/console.js';
21
21
 
22
22
  import styles from './consoleInsight.css.js';
23
- import listStyles from './consoleInsightSourcesList.css.js';
24
23
 
25
24
  // Note: privacy and legal notices are not localized so far.
26
25
  const UIStrings = {
@@ -189,12 +188,14 @@ const SIGN_IN_URL = 'https://accounts.google.com' as Platform.DevToolsPath.UrlSt
189
188
 
190
189
  interface ViewInput {
191
190
  state: StateData;
191
+ closing: boolean;
192
192
  disableAnimations: boolean;
193
193
  renderer: MarkdownView.MarkdownView.MarkdownInsightRenderer;
194
194
  selectedRating?: boolean;
195
195
  noLogging: boolean;
196
196
  callbacks: {
197
197
  onClose: () => void,
198
+ onAnimationEnd: () => void,
198
199
  onSearch: () => void,
199
200
  onRating: (isPositive: boolean) => void,
200
201
  onReport: () => void,
@@ -363,6 +364,26 @@ function renderLoading(): Lit.TemplateResult {
363
364
  // clang-format on
364
365
  }
365
366
 
367
+ function renderInsightSourcesList(
368
+ sources: Console.PromptBuilder.Source[], isPageReloadRecommended: boolean): Lit.TemplateResult {
369
+ // clang-format off
370
+ return html`
371
+ <div class="insight-sources">style>
372
+ <ul>
373
+ ${Directives.repeat(sources, item => item.value, item => {
374
+ return html`<li><x-link class="link" title="${localizeType(item.type)} ${i18nString(UIStrings.opensInNewTab)}" href="data:text/plain;charset=utf-8,${encodeURIComponent(item.value)}" jslog=${VisualLogging.link('source-' + item.type).track({click: true})}>
375
+ <devtools-icon name="open-externally"></devtools-icon>
376
+ ${localizeType(item.type)}
377
+ </x-link></li>`;
378
+ })}
379
+ ${isPageReloadRecommended ? html`<li class="source-disclaimer">
380
+ <devtools-icon name="warning"></devtools-icon>
381
+ ${i18nString(UIStrings.reloadRecommendation)}</li>` : Lit.nothing}
382
+ </ul>
383
+ </div>`;
384
+ // clang-format on
385
+ }
386
+
366
387
  function renderInsight(
367
388
  insight: Extract<StateData, {type: State.INSIGHT}>, renderer: ViewInput['renderer'],
368
389
  disableAnimations: ViewInput['disableAnimations'], callbacks: ViewInput['callbacks'],
@@ -384,8 +405,7 @@ function renderInsight(
384
405
  ` : Lit.nothing}
385
406
  <details jslog=${VisualLogging.expand('sources').track({click: true})}>
386
407
  <summary>${i18nString(UIStrings.inputData)}</summary>
387
- <devtools-console-insight-sources-list .sources=${insight.sources} .isPageReloadRecommended=${insight.isPageReloadRecommended}>
388
- </devtools-console-insight-sources-list>
408
+ ${renderInsightSourcesList(insight.sources, insight.isPageReloadRecommended)}
389
409
  </details>
390
410
  <div class="buttons">
391
411
  ${renderSearchButton(callbacks.onSearch)}
@@ -652,6 +672,8 @@ export class ConsoleInsight extends HTMLElement {
652
672
  #headerRef = Directives.createRef<HTMLHeadingElement>();
653
673
  #citationLinks: HTMLElement[] = [];
654
674
  #areReferenceDetailsOpen = false;
675
+ #stateChanging = false;
676
+ #closing = false;
655
677
 
656
678
  // Rating sub-form state.
657
679
  #selectedRating?: boolean;
@@ -818,12 +840,9 @@ export class ConsoleInsight extends HTMLElement {
818
840
  }
819
841
 
820
842
  #transitionTo(newState: StateData): void {
821
- const previousState = this.#state;
843
+ this.#stateChanging = this.#state.type !== newState.type;
822
844
  this.#state = newState;
823
845
  this.#render();
824
- if (newState.type !== previousState.type) {
825
- this.#focusHeader();
826
- }
827
846
  }
828
847
 
829
848
  async #generateInsightIfNeeded(): Promise<void> {
@@ -855,10 +874,18 @@ export class ConsoleInsight extends HTMLElement {
855
874
  if (this.#state.type === State.CONSENT_REMINDER) {
856
875
  Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserCanceled);
857
876
  }
858
- this.shadowRoot?.addEventListener('animationend', () => {
877
+ this.#closing = true;
878
+ this.#render();
879
+ }
880
+
881
+ #onAnimationEnd(): void {
882
+ if (this.#closing) {
859
883
  this.dispatchEvent(new CloseEvent());
860
- }, {once: true});
861
- this.classList.add('closing');
884
+ return;
885
+ }
886
+ if (this.#stateChanging) {
887
+ this.#headerRef.value?.focus();
888
+ }
862
889
  }
863
890
 
864
891
  #onRating(isPositive: boolean): void {
@@ -1074,12 +1101,6 @@ export class ConsoleInsight extends HTMLElement {
1074
1101
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(SIGN_IN_URL);
1075
1102
  }
1076
1103
 
1077
- #focusHeader(): void {
1078
- this.addEventListener('animationend', () => {
1079
- this.#headerRef.value?.focus();
1080
- }, {once: true});
1081
- }
1082
-
1083
1104
  #onToggleReferenceDetails(): void {
1084
1105
  if (this.#referenceDetailsRef.value) {
1085
1106
  this.#areReferenceDetailsOpen = this.#referenceDetailsRef.value.open;
@@ -1103,6 +1124,7 @@ export class ConsoleInsight extends HTMLElement {
1103
1124
  #render(): void {
1104
1125
  const input: ViewInput = {
1105
1126
  state: this.#state,
1127
+ closing: this.#closing,
1106
1128
  disableAnimations: this.disableAnimations,
1107
1129
  renderer: this.#renderer,
1108
1130
  selectedRating: this.#selectedRating,
@@ -1110,6 +1132,7 @@ export class ConsoleInsight extends HTMLElement {
1110
1132
  Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING,
1111
1133
  callbacks: {
1112
1134
  onClose: this.#onClose.bind(this),
1135
+ onAnimationEnd: this.#onAnimationEnd.bind(this),
1113
1136
  onSearch: this.#onSearch.bind(this),
1114
1137
  onRating: this.#onRating.bind(this),
1115
1138
  onReport: this.#onReport.bind(this),
@@ -1181,7 +1204,11 @@ export class ConsoleInsight extends HTMLElement {
1181
1204
  render(html`
1182
1205
  <style>${styles}</style>
1183
1206
  <style>${Input.checkboxStyles}</style>
1184
- <div class="wrapper" jslog=${VisualLogging.pane('console-insights').track({resize: true})}>
1207
+ <div
1208
+ class=${Directives.classMap({wrapper: true, closing: input.closing})}
1209
+ jslog=${VisualLogging.pane('console-insights').track({resize: true})}
1210
+ @animationend=${callbacks.onAnimationEnd}
1211
+ >
1185
1212
  <div class="animation-wrapper">
1186
1213
  ${header}
1187
1214
  <main jslog=${jslog} class=${Directives.classMap(mainClasses)}>
@@ -1205,50 +1232,10 @@ export class ConsoleInsight extends HTMLElement {
1205
1232
  }
1206
1233
  }
1207
1234
 
1208
- class ConsoleInsightSourcesList extends HTMLElement {
1209
- readonly #shadow = this.attachShadow({mode: 'open'});
1210
- #sources: Console.PromptBuilder.Source[] = [];
1211
- #isPageReloadRecommended = false;
1212
-
1213
- #render(): void {
1214
- // clang-format off
1215
- render(html`
1216
- <style>${listStyles}</style>
1217
- <style>${Input.checkboxStyles}</style>
1218
- <ul>
1219
- ${Directives.repeat(this.#sources, item => item.value, item => {
1220
- return html`<li><x-link class="link" title="${localizeType(item.type)} ${i18nString(UIStrings.opensInNewTab)}" href="data:text/plain;charset=utf-8,${encodeURIComponent(item.value)}" jslog=${VisualLogging.link('source-' + item.type).track({click: true})}>
1221
- <devtools-icon name="open-externally"></devtools-icon>
1222
- ${localizeType(item.type)}
1223
- </x-link></li>`;
1224
- })}
1225
- ${this.#isPageReloadRecommended ? html`<li class="source-disclaimer">
1226
- <devtools-icon name="warning"></devtools-icon>
1227
- ${i18nString(UIStrings.reloadRecommendation)}</li>` : Lit.nothing}
1228
- </ul>
1229
- `, this.#shadow, {
1230
- host: this,
1231
- });
1232
- // clang-format on
1233
- }
1234
-
1235
- set sources(values: Console.PromptBuilder.Source[]) {
1236
- this.#sources = values;
1237
- this.#render();
1238
- }
1239
-
1240
- set isPageReloadRecommended(isPageReloadRecommended: boolean) {
1241
- this.#isPageReloadRecommended = isPageReloadRecommended;
1242
- this.#render();
1243
- }
1244
- }
1245
-
1246
1235
  customElements.define('devtools-console-insight', ConsoleInsight);
1247
- customElements.define('devtools-console-insight-sources-list', ConsoleInsightSourcesList);
1248
1236
 
1249
1237
  declare global {
1250
1238
  interface HTMLElementTagNameMap {
1251
1239
  'devtools-console-insight': ConsoleInsight;
1252
- 'devtools-console-insight-sources-list': ConsoleInsightSourcesList;
1253
1240
  }
1254
1241
  }
@@ -24,7 +24,7 @@
24
24
  animation: expand var(--sys-motion-duration-medium2) var(--sys-motion-easing-emphasized) forwards;
25
25
  }
26
26
 
27
- :host-context(.closing) .wrapper {
27
+ .wrapper.closing {
28
28
  animation: collapse var(--sys-motion-duration-medium2) var(--sys-motion-easing-emphasized) forwards;
29
29
  }
30
30
 
@@ -393,3 +393,48 @@ details h3 {
393
393
  .error-message {
394
394
  font: var(--sys-typescale-body4-bold);
395
395
  }
396
+
397
+ @scope (.insight-sources) {
398
+ :root {
399
+ padding: 0;
400
+ margin: 0;
401
+ box-sizing: border-box;
402
+ display: block;
403
+ }
404
+
405
+ ul {
406
+ color: var(--sys-color-primary);
407
+ font-size: 12px;
408
+ font-style: normal;
409
+ font-weight: 400;
410
+ line-height: 18px;
411
+ margin-top: 8px;
412
+ padding-left: var(--sys-size-6);
413
+ }
414
+
415
+ li {
416
+ list-style-type: none;
417
+ }
418
+
419
+ ul .link {
420
+ color: var(--sys-color-primary);
421
+ display: inline-flex !important; /* stylelint-disable-line declaration-no-important */
422
+ align-items: center;
423
+ gap: 4px;
424
+ text-decoration-line: underline;
425
+ }
426
+
427
+ devtools-icon {
428
+ height: 16px;
429
+ width: 16px;
430
+ margin-right: var(--sys-size-1);
431
+ }
432
+
433
+ devtools-icon[name="open-externally"] {
434
+ color: var(--icon-link);
435
+ }
436
+
437
+ .source-disclaimer {
438
+ color: var(--sys-color-on-surface-subtle);
439
+ }
440
+ }
@@ -6,7 +6,6 @@
6
6
 
7
7
  import * as Common from '../../core/common/common.js';
8
8
  import * as i18n from '../../core/i18n/i18n.js';
9
- import * as Platform from '../../core/platform/platform.js';
10
9
  import type * as SDK from '../../core/sdk/sdk.js';
11
10
  import * as UI from '../../ui/legacy/legacy.js';
12
11
 
@@ -80,7 +79,7 @@ export class LayerTreeOutline extends Common.ObjectWrapper.eventMixin<EventTypes
80
79
  wrapperElement.appendChild(this.treeOutline.element);
81
80
  wrapperElement.appendChild(summaryElement);
82
81
  this.element = wrapperElement;
83
- Platform.DOMUtilities.appendStyle(this.element, layerTreeOutlineStyles);
82
+ UI.DOMUtilities.appendStyle(this.element, layerTreeOutlineStyles);
84
83
 
85
84
  this.layerViewHost.showInternalLayersSetting().addChangeListener(this.update, this);
86
85
  }
@@ -64,6 +64,7 @@ interface ViewInput {
64
64
  customConditionsGroup: NetworkThrottlingConditionsGroup;
65
65
  jslogContext: string|undefined;
66
66
  title: string|undefined;
67
+ disabled: boolean;
67
68
  onSelect: (conditions: SDK.NetworkManager.ThrottlingConditions) => void;
68
69
  onAddCustomConditions: () => void;
69
70
  }
@@ -108,6 +109,7 @@ export const DEFAULT_VIEW: ViewFunction = (input, output, target) => {
108
109
  render(
109
110
  // clang-format off
110
111
  html`<select
112
+ ?disabled=${input.disabled}
111
113
  aria-label=${input.title ?? nothing}
112
114
  jslog=${VisualLogging.dropDown().track({change: true}).context(input.jslogContext)}
113
115
  @change=${onSelect}>
@@ -166,6 +168,7 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
166
168
  readonly #title?: string;
167
169
  readonly #view: ViewFunction;
168
170
  #variant: NetworkThrottlingSelect.Variant = NetworkThrottlingSelect.Variant.GLOBAL_CONDITIONS;
171
+ #disabled = false;
169
172
 
170
173
  static createForGlobalConditions(element: HTMLElement, title: string): NetworkThrottlingSelect {
171
174
  ThrottlingManager.instance(); // Instantiate the throttling manager to connect network manager with the setting
@@ -204,6 +207,14 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
204
207
  this.#performUpdate();
205
208
  }
206
209
 
210
+ get disabled(): boolean {
211
+ return this.#disabled;
212
+ }
213
+ set disabled(disabled: boolean) {
214
+ this.#disabled = disabled;
215
+ this.#performUpdate();
216
+ }
217
+
207
218
  get recommendedConditions(): SDK.NetworkManager.Conditions|null {
208
219
  return this.#recommendedConditions;
209
220
  }
@@ -284,6 +295,7 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
284
295
  selectedConditions: this.#currentConditions,
285
296
  jslogContext: this.#jslogContext,
286
297
  title: this.#title,
298
+ disabled: this.#disabled,
287
299
  onSelect,
288
300
  onAddCustomConditions,
289
301
  throttlingGroups,
@@ -308,6 +320,13 @@ export class NetworkThrottlingSelectorWidget extends UI.Widget.VBox {
308
320
  this.#select.addEventListener(Events.CONDITIONS_CHANGED, ({data}) => this.#conditionsChangedHandler?.(data));
309
321
  }
310
322
 
323
+ get disabled(): boolean {
324
+ return this.#select.disabled;
325
+ }
326
+ set disabled(disabled: boolean) {
327
+ this.#select.disabled = disabled;
328
+ }
329
+
311
330
  set variant(variant: NetworkThrottlingSelect.Variant) {
312
331
  this.#select.variant = variant;
313
332
  }
@@ -14,6 +14,7 @@ import * as Root from '../../core/root/root.js';
14
14
  import * as SDK from '../../core/sdk/sdk.js';
15
15
  import * as Logs from '../../models/logs/logs.js';
16
16
  import * as Buttons from '../../ui/components/buttons/buttons.js';
17
+ import * as uiI18n from '../../ui/i18n/i18n.js';
17
18
  import * as UI from '../../ui/legacy/legacy.js';
18
19
  import {Directives, html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
19
20
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
@@ -38,6 +39,10 @@ const UIStrings = {
38
39
  * @description Tooltip text that appears when hovering over the plus button in the Blocked URLs Pane of the Network panel
39
40
  */
40
41
  addPattern: 'Add pattern',
42
+ /**
43
+ * @description Tooltip text that appears when hovering over the plus button in the Blocked URLs Pane of the Network panel
44
+ */
45
+ addRule: 'Add rule',
41
46
  /**
42
47
  * @description Accessible label for the button to add request blocking patterns in the network request blocking tool
43
48
  */
@@ -53,7 +58,13 @@ const UIStrings = {
53
58
  /**
54
59
  * @description Text that shows in the network request blocking panel if no pattern has yet been added.
55
60
  */
56
- noPattern: 'No request throttling or blocking patterns',
61
+ noPattern: 'Nothing throttled or blocked',
62
+ /**
63
+ * @description Text that shows in the network request blocking panel if no pattern has yet been added.
64
+ * @example {Learn more} PH1
65
+ */
66
+ noThrottlingOrBlockingPattern:
67
+ `To throttle or block a network request, add a rule here manually or via the network panel's context menu. {PH1}`,
57
68
  /**
58
69
  * @description Text that shows in the network request blocking panel if no pattern has yet been added.
59
70
  * @example {Add pattern} PH1
@@ -75,8 +86,9 @@ const UIStrings = {
75
86
  textPatternToBlockMatching: 'Text pattern to block matching requests; use * for wildcard',
76
87
  /**
77
88
  * @description Text in Blocked URLs Pane of the Network panel
89
+ * @example {Learn more} PH1
78
90
  */
79
- textEditPattern: 'Text pattern to block or throttle matching requests; use URLPattern syntax.',
91
+ textEditPattern: 'Text pattern to block or throttle matching requests; use URL Pattern syntax. {PH1}',
80
92
  /**
81
93
  * @description Error text for empty list widget input in Request Blocking tool
82
94
  */
@@ -106,6 +118,10 @@ const UIStrings = {
106
118
  * @description Message to be announced for a when list item is removed from list widget
107
119
  */
108
120
  learnMore: 'Learn more',
121
+ /**
122
+ * @description Accessibility label on a `Learn more` link
123
+ */
124
+ learnMoreLabel: 'Learn more about URL pattern syntax',
109
125
  /**
110
126
  * @description Aria label on a button moving an entry up
111
127
  */
@@ -114,6 +130,15 @@ const UIStrings = {
114
130
  * @description Aria label on a button moving an entry down
115
131
  */
116
132
  decreasePriority: 'Move down (higher patterns are checked first)',
133
+ /**
134
+ * @description Tooltip on a checkbox togging the effects for a pattern
135
+ * @example {*://example.com} PH1
136
+ */
137
+ enableThrottlingToggleLabel: 'Throttle or block {PH1}',
138
+ /**
139
+ * @description Aria label on a combobox selecting the request conditions
140
+ */
141
+ requestConditionsLabel: 'Request conditions',
117
142
  } as const;
118
143
  const str_ = i18n.i18n.registerUIStrings('panels/network/RequestConditionsDrawer.ts', UIStrings);
119
144
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -155,23 +180,19 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
155
180
  ? i18nString(UIStrings.noPattern)
156
181
  : i18nString(UIStrings.noNetworkRequestsBlocked)}</span>
157
182
  <div class=empty-state-description>
158
- <span>${i18nString(UIStrings.addPatternToBlock, {PH1: i18nString(UIStrings.addPattern)})}</span>
159
- <x-link
160
- href=${NETWORK_REQUEST_BLOCKING_EXPLANATION_URL}
161
- tabindex=0
162
- class=devtools-link
163
- jslog=${VisualLogging.link().track({click: true, keydown:'Enter|Space'}).context('learn-more')}>
164
- ${i18nString(UIStrings.learnMore)}
165
- </x-link>
183
+ ${individualThrottlingEnabled
184
+ ? uiI18n.getFormatLocalizedStringTemplate(str_, UIStrings.noThrottlingOrBlockingPattern, {PH1: learnMore()})
185
+ : html`<span>${i18nString(UIStrings.addPatternToBlock,
186
+ {PH1: i18nString(UIStrings.addPattern)})}</span>${learnMore()}`}
166
187
  </div>
167
188
  <devtools-button
168
189
  @click=${input.addPattern}
169
190
  class=add-button
170
191
  .jslogContext=${'network.add-network-request-blocking-pattern'}
171
- aria-label=${individualThrottlingEnabled ? i18nString(UIStrings.addPatternLabel)
192
+ title=${individualThrottlingEnabled ? i18nString(UIStrings.addPatternLabel)
172
193
  : i18nString(UIStrings.addNetworkRequestBlockingPattern)}
173
194
  .variant=${Buttons.Button.Variant.TONAL}>
174
- ${i18nString(UIStrings.addPattern)}
195
+ ${individualThrottlingEnabled ? i18nString(UIStrings.addRule) : i18nString(UIStrings.addPattern)}
175
196
  </devtools-button>
176
197
  </div>
177
198
  <devtools-widget .widgetConfig=${UI.Widget.widgetConfig(UI.Widget.VBox)}>${input.list.element}</devtools-widget>
@@ -391,22 +412,25 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
391
412
  <input class=blocked-url-checkbox
392
413
  @click=${toggle}
393
414
  type=checkbox
415
+ title=${i18nString(UIStrings.enableThrottlingToggleLabel, {PH1: constructorStringOrWildcardURL})}
394
416
  ?checked=${enabled}
395
417
  ?disabled=${!editable || !originalOrUpgradedURLPattern}
396
418
  .jslog=${VisualLogging.toggle().track({ change: true })}>
397
- <devtools-button
398
- .iconName=${'arrow-down'}
399
- .variant=${Buttons.Button.Variant.ICON}
400
- .title=${i18nString(UIStrings.increasePriority)}
401
- .jslogContext=${'increase-priority'}
402
- @click=${moveDown}></devtools-button>
403
419
  <devtools-button
404
420
  .iconName=${'arrow-up'}
405
421
  .variant=${Buttons.Button.Variant.ICON}
406
422
  .title=${i18nString(UIStrings.decreasePriority)}
407
423
  .jslogContext=${'decrease-priority'}
424
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
408
425
  @click=${moveUp}>
409
426
  </devtools-button>
427
+ <devtools-button
428
+ .iconName=${'arrow-down'}
429
+ .variant=${Buttons.Button.Variant.ICON}
430
+ .title=${i18nString(UIStrings.increasePriority)}
431
+ .jslogContext=${'increase-priority'}
432
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
433
+ @click=${moveDown}></devtools-button>
410
434
  ${originalOrUpgradedURLPattern ? html`
411
435
  <devtools-tooltip variant=rich jslogcontext=url-pattern id=url-pattern-${index}>
412
436
  <div>hash: ${originalOrUpgradedURLPattern.hash}</div>
@@ -439,22 +463,26 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
439
463
  </devtools-tooltip>`: nothing}
440
464
  <div
441
465
  @click=${toggle}
466
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
442
467
  class=blocked-url-label
443
468
  aria-details=url-pattern-${index}>
444
469
  ${constructorStringOrWildcardURL}
445
470
  </div>
446
471
  <devtools-widget
447
472
  class=conditions-selector
448
- ?disabled=${!editable}
473
+ title=${i18nString(UIStrings.requestConditionsLabel)}
449
474
  .widgetConfig=${UI.Widget.widgetConfig(
450
475
  MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelectorWidget, {
451
476
  variant:
452
477
  MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect.Variant.INDIVIDUAL_REQUEST_CONDITIONS,
453
478
  jslogContext: 'request-conditions',
479
+ disabled: !editable,
454
480
  onConditionsChanged,
455
481
  currentConditions: condition.conditions,
456
482
  })}></devtools-widget>
457
- <devtools-widget .widgetConfig=${widgetConfig(AffectedCountWidget, {condition, drawer: this})}></devtools-widget>`,
483
+ <devtools-widget
484
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
485
+ .widgetConfig=${widgetConfig(AffectedCountWidget, {condition, drawer: this})}></devtools-widget>`,
458
486
  // clang-format on
459
487
  element);
460
488
  } else {
@@ -517,11 +545,12 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
517
545
  const editor = new UI.ListWidget.Editor<SDK.NetworkManager.RequestCondition>();
518
546
  const content = editor.contentElement();
519
547
  const titles = content.createChild('div', 'blocked-url-edit-row');
520
- const label = titles.createChild('div');
548
+ const label = titles.createChild('label');
521
549
  if (Root.Runtime.hostConfig.devToolsIndividualRequestThrottling?.enabled) {
522
- label.textContent = i18nString(UIStrings.textEditPattern);
523
- label.append(UI.XLink.XLink.create(
524
- PATTERN_API_DOCS_URL, i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more'));
550
+ const learnMore = UI.XLink.XLink.create(
551
+ PATTERN_API_DOCS_URL, i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more');
552
+ learnMore.title = i18nString(UIStrings.learnMoreLabel);
553
+ label.append(uiI18n.getFormatLocalizedString(str_, UIStrings.textEditPattern, {PH1: learnMore}));
525
554
  } else {
526
555
  label.textContent = i18nString(UIStrings.textPatternToBlockMatching);
527
556
  }
@@ -549,6 +578,7 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
549
578
  return {valid: true, errorMessage: undefined};
550
579
  };
551
580
  const urlInput = editor.createInput('url', 'text', '', validator);
581
+ label.htmlFor = urlInput.id = 'editor-url-input';
552
582
  fields.createChild('div', 'blocked-url-edit-value').appendChild(urlInput);
553
583
  return editor;
554
584
  }
@@ -175,6 +175,13 @@
175
175
  color: var(--sys-color-on-tonal-container);
176
176
  }
177
177
 
178
+ .network-log-grid.data-grid tr.selected.network-throttled-row,
179
+ .network-log-grid.data-grid tr.selected.network-throttled-row .devtools-link,
180
+ .network-log-grid.data-grid tr.selected.network-throttled-row .network-cell-subtitle,
181
+ .network-log-grid.data-grid tr.selected.network-throttled-row .network-dim-cell {
182
+ color: var(--sys-color-yellow);
183
+ }
184
+
178
185
  .network-header-subtitle {
179
186
  color: var(--sys-color-token-subtle);
180
187
  }
@@ -250,6 +257,10 @@
250
257
  }
251
258
  }
252
259
 
260
+ td.time-column {
261
+ vertical-align: middle;
262
+ }
263
+
253
264
  .data-grid-data-grid-node devtools-icon[name="arrow-up-down-circle"],
254
265
  .network-log-grid.data-grid.small .icon {
255
266
  width: 16px;
@@ -191,14 +191,16 @@ tr:has([aria-checked].network-fetch-timing-bar-clickable) ~ .network-fetch-timin
191
191
  background-color: var(--network-overview-waiting); /* stylelint-disable-line plugin/use_theme_colors */
192
192
  }
193
193
 
194
- .throttled devtools-icon {
195
- vertical-align: middle;
196
- margin-right: var(--sys-size-3);
197
- color: var(--sys-color-yellow);
198
- }
199
-
200
194
  td.throttled {
195
+ display: flex;
196
+ align-items: center;
197
+ justify-content: flex-end;
198
+ gap: var(--sys-size-3);
201
199
  color: var(--sys-color-yellow);
200
+
201
+ devtools-icon {
202
+ color: var(--sys-color-yellow);
203
+ }
202
204
  }
203
205
 
204
206
  .network-timing-bar.receiving,
@@ -32,6 +32,10 @@
32
32
  flex-direction: row;
33
33
  align-items: center;
34
34
  flex: auto;
35
+
36
+ devtools-button {
37
+ flex: none;
38
+ }
35
39
  }
36
40
 
37
41
  .blocked-url-count {
@@ -76,6 +80,11 @@
76
80
  }
77
81
 
78
82
  .conditions-selector {
79
- max-width: 120px;
83
+ width: max-content;
84
+ flex: none;
80
85
  margin: var(--sys-size-3);
81
86
  }
87
+
88
+ [disabled] {
89
+ opacity: 50%;
90
+ }
@@ -32,7 +32,6 @@ import '../../ui/legacy/legacy.js';
32
32
 
33
33
  import * as Common from '../../core/common/common.js';
34
34
  import * as i18n from '../../core/i18n/i18n.js';
35
- import * as Platform from '../../core/platform/platform.js';
36
35
  import * as SDK from '../../core/sdk/sdk.js';
37
36
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
38
37
  // eslint-disable-next-line @devtools/es-modules-import
@@ -241,7 +240,7 @@ export class ProfilesPanel extends UI.Panel.PanelWithSidebar implements DataDisp
241
240
  if (!this.toggleRecordAction.enabled()) {
242
241
  return true;
243
242
  }
244
- const toggleButton = Platform.DOMUtilities.deepActiveElement(this.element.ownerDocument);
243
+ const toggleButton = UI.DOMUtilities.deepActiveElement(this.element.ownerDocument);
245
244
  const type = this.selectedProfileType;
246
245
  if (!type) {
247
246
  return true;
@@ -271,30 +271,29 @@ export class KeybindsSettingsTab extends UI.Widget.VBox implements UI.ListContro
271
271
  }
272
272
 
273
273
  private createListItems(): KeybindsItem[] {
274
- const actions = UI.ActionRegistry.ActionRegistry.instance().actions().sort((actionA, actionB) => {
275
- if (actionA.category() < actionB.category()) {
276
- return -1;
277
- }
278
- if (actionA.category() > actionB.category()) {
279
- return 1;
280
- }
281
- if (actionA.id() < actionB.id()) {
282
- return -1;
283
- }
284
- if (actionA.id() > actionB.id()) {
285
- return 1;
286
- }
287
- return 0;
288
- });
274
+ const actions = UI.ActionRegistry.ActionRegistry.instance()
275
+ .actions()
276
+ .filter(action => action.configurableBindings())
277
+ .sort((actionA, actionB) => {
278
+ if (actionA.category() < actionB.category()) {
279
+ return -1;
280
+ }
281
+ if (actionA.category() > actionB.category()) {
282
+ return 1;
283
+ }
284
+ if (actionA.id() < actionB.id()) {
285
+ return -1;
286
+ }
287
+ if (actionA.id() > actionB.id()) {
288
+ return 1;
289
+ }
290
+ return 0;
291
+ });
289
292
 
290
293
  const items: KeybindsItem[] = [];
291
294
 
292
295
  let currentCategory: UI.ActionRegistration.ActionCategory;
293
296
  actions.forEach(action => {
294
- if (action.id() === 'elements.toggle-element-search') {
295
- return;
296
- }
297
-
298
297
  if (currentCategory !== action.category()) {
299
298
  items.push(action.category());
300
299
  }
@@ -305,7 +304,7 @@ export class KeybindsSettingsTab extends UI.Widget.VBox implements UI.ListContro
305
304
  }
306
305
 
307
306
  onEscapeKeyPressed(event: Event): void {
308
- const deepActiveElement = Platform.DOMUtilities.deepActiveElement(document);
307
+ const deepActiveElement = UI.DOMUtilities.deepActiveElement(document);
309
308
  if (this.editingRow && deepActiveElement && deepActiveElement.nodeName === 'INPUT') {
310
309
  this.editingRow.onEscapeKeyPressed(event);
311
310
  }
@@ -595,7 +594,7 @@ export class ShortcutListItem {
595
594
  }
596
595
 
597
596
  onEscapeKeyPressed(event: Event): void {
598
- const activeElement = Platform.DOMUtilities.deepActiveElement(document);
597
+ const activeElement = UI.DOMUtilities.deepActiveElement(document);
599
598
  for (const [shortcut, shortcutInput] of this.shortcutInputs.entries()) {
600
599
  if (activeElement === shortcutInput) {
601
600
  this.onShortcutInputKeyDown(shortcut, shortcutInput as HTMLInputElement, event);