chrome-devtools-frontend 1.0.1622369 → 1.0.1624583

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 (101) hide show
  1. package/.agents/skills/foundation-test-migration/SKILL.md +1 -1
  2. package/front_end/Images/src/expand.svg +1 -0
  3. package/front_end/core/host/AidaClient.ts +6 -5
  4. package/front_end/core/host/AidaClientTypes.ts +3 -1
  5. package/front_end/core/host/DispatchHttpRequestClient.ts +6 -3
  6. package/front_end/core/platform/api/HostRuntime.ts +3 -0
  7. package/front_end/core/platform/browser/HostRuntime.ts +10 -0
  8. package/front_end/core/platform/node/HostRuntime.ts +10 -0
  9. package/front_end/core/root/Runtime.ts +6 -5
  10. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +72 -8
  11. package/front_end/entrypoints/greendev_floaty/floaty.html +1 -1
  12. package/front_end/generated/Deprecation.ts +7 -0
  13. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  14. package/front_end/generated/SupportedCSSProperties.js +6 -6
  15. package/front_end/generated/protocol.ts +1 -0
  16. package/front_end/models/ai_assistance/agents/GreenDevAgent.ts +373 -112
  17. package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +57 -0
  18. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +2 -1
  19. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +3 -10
  20. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +2 -3
  21. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +2 -3
  22. package/front_end/models/javascript_metadata/NativeFunctions.js +9 -4
  23. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +8 -4
  24. package/front_end/panels/ai_assistance/components/ChatMessage.ts +219 -8
  25. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -2
  26. package/front_end/panels/console/ConsoleView.ts +86 -7
  27. package/front_end/panels/console/ConsoleViewMessage.ts +23 -1
  28. package/front_end/panels/elements/StylePropertiesSection.ts +1 -2
  29. package/front_end/panels/elements/StylePropertyTreeElement.ts +3 -3
  30. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +11 -2
  31. package/front_end/panels/elements/StylesSidebarPane.ts +29 -5
  32. package/front_end/panels/elements/stylePropertiesTreeOutline.css +5 -1
  33. package/front_end/panels/emulation/DeviceModeToolbar.ts +37 -13
  34. package/front_end/panels/emulation/deviceModeView.css +25 -0
  35. package/front_end/panels/greendev/GreenDevPanel.ts +30 -3
  36. package/front_end/panels/media/EventDisplayTable.ts +1 -1
  37. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +48 -27
  38. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +67 -38
  39. package/front_end/panels/network/NetworkConfigView.ts +1 -1
  40. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -22
  41. package/front_end/third_party/chromium/README.chromium +1 -1
  42. package/front_end/third_party/lighthouse/README.chromium +2 -2
  43. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +5176 -5104
  44. package/front_end/third_party/lighthouse/locales/ar-XB.json +72 -36
  45. package/front_end/third_party/lighthouse/locales/ar.json +72 -36
  46. package/front_end/third_party/lighthouse/locales/bg.json +72 -36
  47. package/front_end/third_party/lighthouse/locales/ca.json +72 -36
  48. package/front_end/third_party/lighthouse/locales/cs.json +72 -36
  49. package/front_end/third_party/lighthouse/locales/da.json +74 -38
  50. package/front_end/third_party/lighthouse/locales/de.json +72 -36
  51. package/front_end/third_party/lighthouse/locales/el.json +73 -37
  52. package/front_end/third_party/lighthouse/locales/en-GB.json +74 -38
  53. package/front_end/third_party/lighthouse/locales/en-US.json +245 -17
  54. package/front_end/third_party/lighthouse/locales/en-XL.json +245 -17
  55. package/front_end/third_party/lighthouse/locales/es-419.json +72 -36
  56. package/front_end/third_party/lighthouse/locales/es.json +73 -37
  57. package/front_end/third_party/lighthouse/locales/fi.json +72 -36
  58. package/front_end/third_party/lighthouse/locales/fil.json +74 -38
  59. package/front_end/third_party/lighthouse/locales/fr.json +162 -126
  60. package/front_end/third_party/lighthouse/locales/he.json +74 -38
  61. package/front_end/third_party/lighthouse/locales/hi.json +73 -37
  62. package/front_end/third_party/lighthouse/locales/hr.json +72 -36
  63. package/front_end/third_party/lighthouse/locales/hu.json +73 -37
  64. package/front_end/third_party/lighthouse/locales/id.json +74 -38
  65. package/front_end/third_party/lighthouse/locales/it.json +72 -36
  66. package/front_end/third_party/lighthouse/locales/ja.json +72 -36
  67. package/front_end/third_party/lighthouse/locales/ko.json +72 -36
  68. package/front_end/third_party/lighthouse/locales/lt.json +72 -36
  69. package/front_end/third_party/lighthouse/locales/lv.json +72 -36
  70. package/front_end/third_party/lighthouse/locales/nl.json +73 -37
  71. package/front_end/third_party/lighthouse/locales/no.json +72 -36
  72. package/front_end/third_party/lighthouse/locales/pl.json +72 -36
  73. package/front_end/third_party/lighthouse/locales/pt-PT.json +72 -36
  74. package/front_end/third_party/lighthouse/locales/pt.json +74 -38
  75. package/front_end/third_party/lighthouse/locales/ro.json +72 -36
  76. package/front_end/third_party/lighthouse/locales/ru.json +72 -36
  77. package/front_end/third_party/lighthouse/locales/sk.json +72 -36
  78. package/front_end/third_party/lighthouse/locales/sl.json +72 -36
  79. package/front_end/third_party/lighthouse/locales/sr-Latn.json +73 -37
  80. package/front_end/third_party/lighthouse/locales/sr.json +73 -37
  81. package/front_end/third_party/lighthouse/locales/sv.json +75 -39
  82. package/front_end/third_party/lighthouse/locales/ta.json +73 -37
  83. package/front_end/third_party/lighthouse/locales/te.json +72 -36
  84. package/front_end/third_party/lighthouse/locales/th.json +73 -37
  85. package/front_end/third_party/lighthouse/locales/tr.json +72 -36
  86. package/front_end/third_party/lighthouse/locales/uk.json +72 -36
  87. package/front_end/third_party/lighthouse/locales/vi.json +74 -38
  88. package/front_end/third_party/lighthouse/locales/zh-HK.json +72 -36
  89. package/front_end/third_party/lighthouse/locales/zh-TW.json +74 -38
  90. package/front_end/third_party/lighthouse/locales/zh.json +75 -39
  91. package/front_end/third_party/lighthouse/report/bundle.js +2 -1
  92. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
  93. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +6 -2
  94. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +4 -1
  95. package/front_end/ui/legacy/SuggestBox.ts +1 -0
  96. package/front_end/ui/legacy/TextPrompt.ts +2 -1
  97. package/front_end/ui/legacy/UIUtils.ts +26 -4
  98. package/front_end/ui/visual_logging/KnownContextValues.ts +20 -0
  99. package/package.json +9 -8
  100. package/front_end/panels/emulation/components/DeviceSizeInputElement.ts +0 -134
  101. package/front_end/panels/emulation/components/components.ts +0 -9
@@ -907,8 +907,7 @@ export class StylePropertiesSection {
907
907
  return;
908
908
  }
909
909
  const sourceTreeElement = this.closestPropertyForEditing(this.#activeAiSuggestion.cssProperty.index);
910
- if (!(sourceTreeElement instanceof StylePropertyTreeElement) ||
911
- sourceTreeElement.property !== this.#activeAiSuggestion.cssProperty) {
910
+ if (!(sourceTreeElement instanceof StylePropertyTreeElement)) {
912
911
  return;
913
912
  }
914
913
  return sourceTreeElement;
@@ -3515,7 +3515,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
3515
3515
  if (this.prompt) {
3516
3516
  this.prompt.detach();
3517
3517
  this.prompt = null;
3518
- this.#clearGhostTextInValue();
3518
+ this.section().activeAiSuggestion = undefined;
3519
3519
  }
3520
3520
  }
3521
3521
 
@@ -3637,12 +3637,12 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
3637
3637
  }
3638
3638
  const isEditingName = UI.UIUtils.isBeingEdited(this.nameElement);
3639
3639
  if (isEditingName) {
3640
- this.prompt.applySuggestion({text: activeAiSuggestion.name}, true);
3640
+ this.prompt.applySuggestion({text: activeAiSuggestion.name, disableAcceptSuggestionOnStopCharacters: true}, true);
3641
3641
  this.#showGhostTextInValue(activeAiSuggestion.value);
3642
3642
  } else {
3643
3643
  // Only has ghost text for one field - name part or value part
3644
3644
  const currentSuggestedText = isEditingName ? activeAiSuggestion.name : activeAiSuggestion.value;
3645
- this.prompt.applySuggestion({text: currentSuggestedText}, true);
3645
+ this.prompt.applySuggestion({text: currentSuggestedText, disableAcceptSuggestionOnStopCharacters: true}, true);
3646
3646
  }
3647
3647
  }
3648
3648
 
@@ -5,6 +5,7 @@
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as Host from '../../core/host/host.js';
7
7
  import * as i18n from '../../core/i18n/i18n.js';
8
+ import * as Root from '../../core/root/root.js';
8
9
  import type * as SDK from '../../core/sdk/sdk.js';
9
10
  import * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
10
11
  import * as TextUtils from '../../models/text_utils/text_utils.js';
@@ -55,9 +56,17 @@ export class StylesAiCodeCompletionProvider {
55
56
  // early return as this means that code completion was previously setup
56
57
  return;
57
58
  }
59
+ // Adding '}' as a stop sequence so that suggestion is limited to properties for a given style section
60
+ const stopSequences = ['}'];
61
+ if (this.#aiCodeCompletionConfig.completionContext.stopSequences) {
62
+ stopSequences.push(...this.#aiCodeCompletionConfig.completionContext.stopSequences);
63
+ }
58
64
  this.#aiCodeCompletion = new AiCodeCompletion.AiCodeCompletion.AiCodeCompletion(
59
- {aidaClient: this.#aidaClient}, this.#aiCodeCompletionConfig.panel, undefined,
60
- this.#aiCodeCompletionConfig.completionContext.stopSequences);
65
+ {
66
+ aidaClient: this.#aidaClient,
67
+ serverSideLoggingEnabled: !Root.Runtime.hostConfig.aidaAvailability?.disallowLogging
68
+ },
69
+ this.#aiCodeCompletionConfig.panel, undefined, stopSequences);
61
70
  this.#aiCodeCompletionConfig.onFeatureEnabled();
62
71
  }
63
72
 
@@ -135,10 +135,16 @@ const UIStrings = {
135
135
  * @description Tooltip text for the link in the sidebar pane layer separators that reveals the layer in the layer tree view.
136
136
  */
137
137
  clickToRevealLayer: 'Click to reveal layer in layer tree',
138
+ /**
139
+ * @description Text to announce that the AI suggestion was accepted.
140
+ * @example {color: blue;} PH1
141
+ */
142
+ aiSuggestionAccepted: '{PH1} Suggestion accepted.',
138
143
  } as const;
139
144
 
140
145
  const str_ = i18n.i18n.registerUIStrings('panels/elements/StylesSidebarPane.ts', UIStrings);
141
146
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
147
+ const lockedString = i18n.i18n.lockedString;
142
148
 
143
149
  // Number of ms elapsed with no keypresses to determine is the input is finished, to announce results
144
150
  const FILTER_IDLE_PERIOD = 500;
@@ -1918,14 +1924,18 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
1918
1924
  return;
1919
1925
  }
1920
1926
  break;
1921
- case 'Enter':
1927
+ case 'Enter': {
1922
1928
  if (keyboardEvent.shiftKey) {
1923
1929
  return;
1924
1930
  }
1925
1931
  // Accept any available autocompletions and advance to the next field.
1926
- this.tabKeyPressed();
1932
+ const handled = this.tabKeyPressed();
1933
+ if (this.aiCodeCompletionProvider && handled) {
1934
+ event.consume(true);
1935
+ }
1927
1936
  keyboardEvent.preventDefault();
1928
1937
  return;
1938
+ }
1929
1939
  case 'Escape':
1930
1940
  if (this.#handleEscape(keyboardEvent)) {
1931
1941
  return;
@@ -2264,9 +2274,18 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
2264
2274
  if (!this.queryRange) {
2265
2275
  this.queryRange = new TextUtils.TextRange.TextRange(0, 0, 0, this.text().length);
2266
2276
  }
2277
+
2278
+ const properties = this.#getAiSuggestedProperties(args.text);
2279
+ if (properties.length === 0) {
2280
+ this.treeElement.section().activeAiSuggestion = undefined;
2281
+ this.activeAiSuggestionInfo = undefined;
2282
+ return;
2283
+ }
2284
+
2285
+ const styleText = properties.map(p => `${p.name}: ${p.value};`).join(' ');
2267
2286
  this.treeElement.section().activeAiSuggestion = {
2268
- text: args.text,
2269
- properties: this.#getAiSuggestedProperties(args.text),
2287
+ text: styleText,
2288
+ properties,
2270
2289
  cursorPosition: args.from,
2271
2290
  clearCachedRequest: args.clearCachedRequest,
2272
2291
  cssProperty: this.treeElement.property,
@@ -2276,6 +2295,7 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
2276
2295
  if (args.rpcGlobalId) {
2277
2296
  args.onImpression(args.rpcGlobalId, latency, args.sampleId);
2278
2297
  }
2298
+ UI.ARIAUtils.LiveAnnouncer.status(lockedString(styleText));
2279
2299
  }
2280
2300
 
2281
2301
  #getAiSuggestedProperties(suggestionText: string): ActiveAiSuggestionProperty[] {
@@ -2356,7 +2376,7 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
2356
2376
  // Explicitly set the query range as it is cleared during `acceptAutoComplete`
2357
2377
  this.queryRange = new TextUtils.TextRange.TextRange(0, 0, 0, textAfterAccept.length);
2358
2378
  // Re-apply the ghost text for the remainder
2359
- this.applySuggestion({text: suggestionForCurrentPrompt}, true);
2379
+ this.applySuggestion({text: suggestionForCurrentPrompt, disableAcceptSuggestionOnStopCharacters: true}, true);
2360
2380
  }
2361
2381
  return true;
2362
2382
  }
@@ -2371,12 +2391,16 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
2371
2391
  }
2372
2392
 
2373
2393
  async commitAiSuggestion(): Promise<void> {
2394
+ const suggestionText = this.treeElement.section().activeAiSuggestion?.text;
2374
2395
  await this.treeElement.section().commitActiveAiSuggestion();
2375
2396
  if (this.activeAiSuggestionInfo) {
2376
2397
  this.aiCodeCompletionProvider?.onSuggestionAccepted(
2377
2398
  this.activeAiSuggestionInfo.citations, this.activeAiSuggestionInfo.rpcGlobalId,
2378
2399
  this.activeAiSuggestionInfo.sampleId);
2379
2400
  }
2401
+ if (suggestionText) {
2402
+ UI.ARIAUtils.LiveAnnouncer.status(i18nString(UIStrings.aiSuggestionAccepted, {PH1: suggestionText}));
2403
+ }
2380
2404
  // Clear state and return
2381
2405
  this.setAiAutoCompletion(null);
2382
2406
  }
@@ -89,7 +89,11 @@
89
89
  }
90
90
 
91
91
  &.ghost-row, .ghost-value-prediction {
92
- opacity: 50%;
92
+ .webkit-css-property {
93
+ opacity: 50%;
94
+ }
95
+
96
+ color: var(--sys-color-token-subtle);
93
97
  font-style: italic;
94
98
  pointer-events: none;
95
99
  }
@@ -16,7 +16,6 @@ import * as UI from '../../ui/legacy/legacy.js';
16
16
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
17
17
  import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
18
18
 
19
- import * as EmulationComponents from './components/components.js';
20
19
  const UIStrings = {
21
20
  /**
22
21
  * @description Title of the device dimensions selection item in the Device Mode Toolbar.
@@ -219,8 +218,8 @@ export class DeviceModeToolbar {
219
218
  private spanButton!: Buttons.Button.Button;
220
219
  private postureItem!: HTMLSelectElement;
221
220
  private modeButton!: Buttons.Button.Button;
222
- private widthInput: EmulationComponents.DeviceSizeInputElement.SizeInputElement;
223
- private heightInput: EmulationComponents.DeviceSizeInputElement.SizeInputElement;
221
+ private widthInput: HTMLInputElement;
222
+ private heightInput: HTMLInputElement;
224
223
  private deviceScaleItem!: HTMLSelectElement;
225
224
  private deviceScaleItems: HTMLElement[] = [];
226
225
  private deviceSelectItem!: HTMLSelectElement;
@@ -255,10 +254,9 @@ export class DeviceModeToolbar {
255
254
  Common.Settings.Settings.instance().createSetting('emulation.auto-adjust-scale', true);
256
255
 
257
256
  this.lastMode = new Map();
258
- this.widthInput = new EmulationComponents.DeviceSizeInputElement.SizeInputElement(
259
- i18nString(UIStrings.width), {jslogContext: 'width'});
260
- this.heightInput = new EmulationComponents.DeviceSizeInputElement.SizeInputElement(
261
- i18nString(UIStrings.heightLeaveEmptyForFull), {jslogContext: 'height'});
257
+
258
+ this.widthInput = this.createSizeInput(i18nString(UIStrings.width), 'width');
259
+ this.heightInput = this.createSizeInput(i18nString(UIStrings.heightLeaveEmptyForFull), 'height');
262
260
 
263
261
  this.#element = document.createElement('div');
264
262
  this.#element.classList.add('device-mode-toolbar');
@@ -306,6 +304,30 @@ export class DeviceModeToolbar {
306
304
  return element;
307
305
  }
308
306
 
307
+ private createSizeInput(title: string, jslogContext: string): HTMLInputElement {
308
+ const input = document.createElement('input');
309
+ input.type = 'number';
310
+ input.max = String(EmulationModel.DeviceModeModel.MaxDeviceSize);
311
+ input.min = String(EmulationModel.DeviceModeModel.MinDeviceSize);
312
+ input.title = title;
313
+ input.classList.add('device-mode-size-input');
314
+ input.setAttribute('jslog', `${VisualLogging.textField().track({change: true}).context(jslogContext)}`);
315
+
316
+ input.addEventListener('keydown', (event: Event) => {
317
+ let modifiedValue = UI.UIUtils.modifiedFloatNumber(Number(input.value), event);
318
+ if (modifiedValue === null) {
319
+ return;
320
+ }
321
+ modifiedValue = Math.min(modifiedValue, EmulationModel.DeviceModeModel.MaxDeviceSize);
322
+ modifiedValue = Math.max(modifiedValue, EmulationModel.DeviceModeModel.MinDeviceSize);
323
+
324
+ event.preventDefault();
325
+ input.value = String(modifiedValue);
326
+ input.dispatchEvent(new Event('change'));
327
+ });
328
+ return input;
329
+ }
330
+
309
331
  private createMainToolbar(): UI.Toolbar.Toolbar {
310
332
  const mainToolbar = this.#element.createChild('devtools-toolbar', 'main-toolbar');
311
333
 
@@ -320,14 +342,16 @@ export class DeviceModeToolbar {
320
342
  mainToolbar.append(...dimensionsSpan.childNodes);
321
343
  mainToolbar.append(this.deviceSelectItem);
322
344
 
323
- this.widthInput.addEventListener('sizechanged', ({size: width}) => {
345
+ this.widthInput.addEventListener('change', () => {
346
+ const width = Number(this.widthInput.value);
324
347
  if (this.autoAdjustScaleSetting.get()) {
325
348
  this.model.setWidthAndScaleToFit(width);
326
349
  } else {
327
350
  this.model.setWidth(width);
328
351
  }
329
352
  });
330
- this.heightInput.addEventListener('sizechanged', ({size: height}) => {
353
+ this.heightInput.addEventListener('change', () => {
354
+ const height = Number(this.heightInput.value);
331
355
  if (this.autoAdjustScaleSetting.get()) {
332
356
  this.model.setHeightAndScaleToFit(height);
333
357
  } else {
@@ -389,8 +413,8 @@ export class DeviceModeToolbar {
389
413
  MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect.createForGlobalConditions(
390
414
  mainToolbar, i18nString(UIStrings.throttling));
391
415
  const saveDataItem = MobileThrottling.ThrottlingManager.throttlingManager().createSaveDataOverrideSelector();
392
- saveDataItem.turnShrinkable();
393
- mainToolbar.appendToolbarItem(saveDataItem);
416
+ saveDataItem.classList.add('dark-text', 'toolbar-has-dropdown-shrinkable');
417
+ mainToolbar.append(saveDataItem);
394
418
 
395
419
  mainToolbar.append(this.createEmptyToolbarElement());
396
420
  this.modeButton = new Buttons.Button.Button();
@@ -947,8 +971,8 @@ export class DeviceModeToolbar {
947
971
  }
948
972
 
949
973
  const size = this.model.appliedDeviceSize();
950
- this.widthInput.size = String(size.width);
951
- this.heightInput.size =
974
+ this.widthInput.value = String(size.width);
975
+ this.heightInput.value =
952
976
  this.model.type() === EmulationModel.DeviceModeModel.Type.Responsive && this.model.isFullHeight() ?
953
977
  '' :
954
978
  String(size.height);
@@ -25,6 +25,31 @@
25
25
  font-size: 16px;
26
26
  }
27
27
 
28
+ .device-mode-size-input {
29
+ /*
30
+ * 4 characters for the maximum size of the value,
31
+ * 2 characters for the width of the step-buttons,
32
+ * 2 pixels padding between the characters and the
33
+ * step-buttons.
34
+ */
35
+ width: calc(4ch + 2ch + 2px);
36
+ max-height: 18px;
37
+ border: var(--sys-color-neutral-outline);
38
+ border-radius: 4px;
39
+ margin: 0 2px;
40
+ text-align: center;
41
+ font-size: inherit;
42
+ font-family: inherit;
43
+ }
44
+
45
+ .device-mode-size-input:disabled {
46
+ user-select: none;
47
+ }
48
+
49
+ .device-mode-size-input:focus::-webkit-input-placeholder {
50
+ color: transparent;
51
+ }
52
+
28
53
  .device-mode-empty-toolbar-element {
29
54
  width: 0;
30
55
  }
@@ -8,6 +8,8 @@ import * as Host from '../../core/host/host.js';
8
8
  import type * as Platform from '../../core/platform/platform.js';
9
9
  import * as SDK from '../../core/sdk/sdk.js';
10
10
  import type * as Protocol from '../../generated/protocol.js';
11
+ import * as Marked from '../../third_party/marked/marked.js';
12
+ import * as MarkdownView from '../../ui/components/markdown_view/markdown_view.js';
11
13
  import * as UI from '../../ui/legacy/legacy.js';
12
14
 
13
15
  import greenDevPanelStyles from './GreenDevPanel.css.js';
@@ -265,9 +267,11 @@ export class GreenDevPanel extends UI.Panel.Panel {
265
267
  if (data.type === 'new-message' && data.text) {
266
268
  this.#appendMessageToContainer(session.container, data.text, data.isUser ?? false);
267
269
  } else if (data.type === 'update-last-message') {
268
- const lastMsg = session.container.lastElementChild?.querySelector('.message-content');
270
+ const lastMsg = session.container.lastElementChild?.querySelector('.message-content devtools-markdown-view');
269
271
  if (lastMsg) {
270
- lastMsg.textContent = data.text ?? null;
272
+ (lastMsg as MarkdownView.MarkdownView.MarkdownView).data = {
273
+ tokens: Marked.Marked.lexer(data.text ?? ''),
274
+ };
271
275
  }
272
276
  } else if (data.type === 'full-state') {
273
277
  session.container.innerHTML = '';
@@ -306,7 +310,30 @@ export class GreenDevPanel extends UI.Panel.Panel {
306
310
 
307
311
  const content = document.createElement('div');
308
312
  content.className = 'message-content';
309
- content.textContent = text;
313
+ if (isUser) {
314
+ content.textContent = text;
315
+ } else {
316
+ const markdown = new MarkdownView.MarkdownView.MarkdownView();
317
+ markdown.data = {
318
+ tokens: Marked.Marked.lexer(text),
319
+ };
320
+ content.append(markdown);
321
+ const style = document.createElement('style');
322
+ style.textContent = `
323
+ .message { font-size: 1.0rem; }
324
+ .message code { font-size: 1.0rem; font-family: 'Roboto Mono', monospace; color: green; }
325
+ devtools-code-block {
326
+ white-space: pre-wrap;
327
+ }
328
+ `;
329
+ markdown.shadowRoot?.appendChild(style);
330
+
331
+ const codeBlocks = markdown.shadowRoot?.querySelectorAll('devtools-code-block');
332
+ for (const block of codeBlocks ?? []) {
333
+ // We need to rerender the component for the styles to be applied.
334
+ block.connectedCallback();
335
+ }
336
+ }
310
337
  content.style.flexGrow = '1';
311
338
  messageElement.appendChild(content);
312
339
 
@@ -42,7 +42,7 @@ export interface EventDisplayColumnConfig {
42
42
  }
43
43
 
44
44
  export const enum MediaEventColumnKeys {
45
- TIMESTAMP = 'display-timestamp',
45
+ TIMESTAMP = 'displayTimestamp',
46
46
  EVENT = 'event',
47
47
  VALUE = 'value',
48
48
  }
@@ -176,35 +176,11 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.eventMixin<Eve
176
176
  #disabled = false;
177
177
 
178
178
  static createForGlobalConditions(element: HTMLElement, title: string): NetworkThrottlingSelect {
179
- ThrottlingManager.instance(); // Instantiate the throttling manager to connect network manager with the setting
180
179
  const selectElement = element.createChild('select');
181
- const select = new NetworkThrottlingSelect(selectElement, {
182
- title,
183
- jslogContext: SDK.NetworkManager.activeNetworkThrottlingKeySetting().name,
184
- currentConditions: SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions()
185
- });
180
+ const select = new NetworkThrottlingSelect(selectElement, {title});
181
+ select.bindToGlobalConditions = true;
186
182
  select.show(element, undefined, /* suppressOrphanWidgetError= */ true);
187
- select.addEventListener(Events.CONDITIONS_CHANGED, event => {
188
- const conditions = event.data;
189
- if (!('block' in conditions)) {
190
- SDK.NetworkManager.MultitargetNetworkManager.instance().setNetworkConditions(conditions);
191
- }
192
- });
193
- SDK.NetworkManager.MultitargetNetworkManager.instance().addEventListener(
194
- SDK.NetworkManager.MultitargetNetworkManager.Events.CONDITIONS_CHANGED, () => {
195
- select.currentConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions();
196
- });
197
-
198
- // Subscribe to CrUX field data changes to show recommended throttling
199
- // presets based on real-user RTT data.
200
- const cruxManager = CrUXManager.CrUXManager.instance();
201
- const updateRecommendation = (): void => {
202
- const roundTripTimeMetricData = cruxManager.getSelectedFieldMetricData('round_trip_time');
203
- select.recommendedConditions =
204
- PanelsCommon.ThrottlingUtils.getRecommendedNetworkConditions(roundTripTimeMetricData);
205
- };
206
- cruxManager.addEventListener(CrUXManager.Events.FIELD_DATA_CHANGED, updateRecommendation);
207
- updateRecommendation();
183
+ select.performUpdate();
208
184
 
209
185
  return select;
210
186
  }
@@ -259,6 +235,51 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.eventMixin<Eve
259
235
  this.requestUpdate();
260
236
  }
261
237
 
238
+ #onConditionsChanged =
239
+ (event: Common.EventTarget.EventTargetEvent<SDK.NetworkManager.ThrottlingConditions>): void => {
240
+ const conditions = event.data;
241
+ if (!('block' in conditions)) {
242
+ SDK.NetworkManager.MultitargetNetworkManager.instance().setNetworkConditions(conditions);
243
+ }
244
+ };
245
+
246
+ #onGlobalConditionsChanged = (): void => {
247
+ this.currentConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions();
248
+ };
249
+
250
+ #updateRecommendation = (): void => {
251
+ const cruxManager = CrUXManager.CrUXManager.instance();
252
+ const roundTripTimeMetricData = cruxManager.getSelectedFieldMetricData('round_trip_time');
253
+ this.recommendedConditions = PanelsCommon.ThrottlingUtils.getRecommendedNetworkConditions(roundTripTimeMetricData);
254
+ };
255
+
256
+ set bindToGlobalConditions(bind: boolean) {
257
+ const cruxManager = CrUXManager.CrUXManager.instance();
258
+ const multitargetNetworkManager = SDK.NetworkManager.MultitargetNetworkManager.instance();
259
+
260
+ if (bind) {
261
+ this.#jslogContext = SDK.NetworkManager.activeNetworkThrottlingKeySetting().name;
262
+ ThrottlingManager.instance(); // Instantiate the throttling manager to connect network manager with the setting
263
+ this.#currentConditions = multitargetNetworkManager.networkConditions();
264
+
265
+ this.addEventListener(Events.CONDITIONS_CHANGED, this.#onConditionsChanged);
266
+ multitargetNetworkManager.addEventListener(
267
+ SDK.NetworkManager.MultitargetNetworkManager.Events.CONDITIONS_CHANGED, this.#onGlobalConditionsChanged);
268
+
269
+ // Subscribe to CrUX field data changes to show recommended throttling
270
+ // presets based on real-user RTT data.
271
+ cruxManager.addEventListener(CrUXManager.Events.FIELD_DATA_CHANGED, this.#updateRecommendation);
272
+ this.#updateRecommendation();
273
+ } else {
274
+ this.removeEventListener(Events.CONDITIONS_CHANGED, this.#onConditionsChanged);
275
+ multitargetNetworkManager.removeEventListener(
276
+ SDK.NetworkManager.MultitargetNetworkManager.Events.CONDITIONS_CHANGED, this.#onGlobalConditionsChanged);
277
+ cruxManager.removeEventListener(CrUXManager.Events.FIELD_DATA_CHANGED, this.#updateRecommendation);
278
+ }
279
+
280
+ this.requestUpdate();
281
+ }
282
+
262
283
  get variant(): NetworkThrottlingSelect.Variant {
263
284
  return this.#variant;
264
285
  }
@@ -9,6 +9,7 @@ import * as i18n from '../../core/i18n/i18n.js';
9
9
  import * as SDK from '../../core/sdk/sdk.js';
10
10
  import {Icon} from '../../ui/kit/kit.js';
11
11
  import * as UI from '../../ui/legacy/legacy.js';
12
+ import {html, render} from '../../ui/lit/lit.js';
12
13
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
13
14
 
14
15
  import {MobileThrottlingSelector} from './MobileThrottlingSelector.js';
@@ -330,45 +331,27 @@ export class ThrottlingManager extends Common.ObjectWrapper.ObjectWrapper<Thrott
330
331
  };
331
332
  }
332
333
 
333
- createSaveDataOverrideSelector(className?: string): UI.Toolbar.ToolbarComboBox {
334
- const reset = new Option(i18nString(UIStrings.noSaveDataOverride), undefined, true, true);
335
- const enable = new Option(i18nString(UIStrings.saveDataOn));
336
- const disable = new Option(i18nString(UIStrings.saveDataOff));
337
- const handler = (e: Event): void => {
338
- const select = e.target as HTMLSelectElement;
339
- switch (select.selectedOptions.item(0)) {
340
- case reset:
341
- for (const emulationModel of SDK.TargetManager.TargetManager.instance().models(
342
- SDK.EmulationModel.EmulationModel)) {
343
- void this.#emulationQueue.push(
344
- emulationModel.setDataSaverOverride(SDK.EmulationModel.DataSaverOverride.UNSET));
345
- }
346
- break;
347
- case enable:
348
- for (const emulationModel of SDK.TargetManager.TargetManager.instance().models(
349
- SDK.EmulationModel.EmulationModel)) {
350
- void this.#emulationQueue.push(
351
- emulationModel.setDataSaverOverride(SDK.EmulationModel.DataSaverOverride.ENABLED));
352
- }
353
- break;
354
- case disable:
355
- for (const emulationModel of SDK.TargetManager.TargetManager.instance().models(
356
- SDK.EmulationModel.EmulationModel)) {
357
- void this.#emulationQueue.push(
358
- emulationModel.setDataSaverOverride(SDK.EmulationModel.DataSaverOverride.DISABLED));
359
- }
360
- break;
361
- }
362
- this.dispatchEventToListeners(ThrottlingManager.Events.SAVE_DATA_OVERRIDE_CHANGED, select.selectedIndex);
363
- };
364
- const select = new UI.Toolbar.ToolbarComboBox(handler, i18nString(UIStrings.saveDataSettingTooltip), className);
365
- select.addOption(reset);
366
- select.addOption(enable);
367
- select.addOption(disable);
368
-
369
- this.addEventListener(
370
- ThrottlingManager.Events.SAVE_DATA_OVERRIDE_CHANGED, ({data}) => select.setSelectedIndex(data));
334
+ setSaveDataOverride(selectedIndex: number): void {
335
+ let override = SDK.EmulationModel.DataSaverOverride.UNSET;
336
+ if (selectedIndex === 1) {
337
+ override = SDK.EmulationModel.DataSaverOverride.ENABLED;
338
+ } else if (selectedIndex === 2) {
339
+ override = SDK.EmulationModel.DataSaverOverride.DISABLED;
340
+ }
341
+ for (const emulationModel of SDK.TargetManager.TargetManager.instance().models(SDK.EmulationModel.EmulationModel)) {
342
+ void this.#emulationQueue.push(emulationModel.setDataSaverOverride(override));
343
+ }
344
+ this.dispatchEventToListeners(ThrottlingManager.Events.SAVE_DATA_OVERRIDE_CHANGED, selectedIndex);
345
+ }
371
346
 
347
+ createSaveDataOverrideSelector(className?: string): HTMLSelectElement {
348
+ const select = document.createElement('select');
349
+ select.title = i18nString(UIStrings.saveDataSettingTooltip);
350
+ UI.ARIAUtils.setLabel(select, i18nString(UIStrings.saveDataSettingTooltip));
351
+ if (className) {
352
+ select.className = className;
353
+ }
354
+ UI.Widget.registerWidgetConfig(select, UI.Widget.widgetConfig(SaveDataOverrideSelect));
372
355
  return select;
373
356
  }
374
357
 
@@ -453,6 +436,52 @@ export class ThrottlingManager extends Common.ObjectWrapper.ObjectWrapper<Thrott
453
436
  }
454
437
  }
455
438
 
439
+ export interface SaveDataOverrideViewInput {
440
+ selectedIndex: number;
441
+ onSelect: (index: number) => void;
442
+ }
443
+
444
+ export type SaveDataOverrideViewFunction =
445
+ (input: SaveDataOverrideViewInput, output: undefined, target: HTMLSelectElement) => void;
446
+
447
+ export const DEFAULT_SAVE_DATA_VIEW: SaveDataOverrideViewFunction = (input, _output, target) => {
448
+ // clang-format off
449
+ render(html`
450
+ <option value="unset" ?selected=${input.selectedIndex === 0}>${i18nString(UIStrings.noSaveDataOverride)}</option>
451
+ <option value="enabled" ?selected=${input.selectedIndex === 1}>${i18nString(UIStrings.saveDataOn)}</option>
452
+ <option value="disabled" ?selected=${input.selectedIndex === 2}>${i18nString(UIStrings.saveDataOff)}</option>
453
+ `, target, {container: {listeners: {change: (e: Event) => input.onSelect((e.target as HTMLSelectElement).selectedIndex)}}});
454
+ // clang-format on
455
+ };
456
+
457
+ export class SaveDataOverrideSelect extends
458
+ Common.ObjectWrapper.eventMixin<ThrottlingManager.EventTypes, typeof UI.Widget.Widget<HTMLSelectElement>>(
459
+ UI.Widget.Widget) {
460
+ #selectedIndex = 0;
461
+ readonly #view: SaveDataOverrideViewFunction;
462
+
463
+ constructor(element: HTMLElement, view = DEFAULT_SAVE_DATA_VIEW) {
464
+ super(element);
465
+ this.#view = view;
466
+ ThrottlingManager.instance().addEventListener(ThrottlingManager.Events.SAVE_DATA_OVERRIDE_CHANGED, ({data}) => {
467
+ this.#selectedIndex = data;
468
+ this.requestUpdate();
469
+ });
470
+ this.performUpdate();
471
+ }
472
+
473
+ override performUpdate(): void {
474
+ this.#view(
475
+ {
476
+ selectedIndex: this.#selectedIndex,
477
+ onSelect: index => {
478
+ ThrottlingManager.instance().setSaveDataOverride(index);
479
+ },
480
+ },
481
+ undefined, this.contentElement);
482
+ }
483
+ }
484
+
456
485
  export namespace ThrottlingManager {
457
486
  export const enum Events {
458
487
  SAVE_DATA_OVERRIDE_CHANGED = 'SaveDataOverrideChanged',
@@ -218,7 +218,7 @@ export class NetworkConfigView extends UI.Widget.VBox {
218
218
  const section = this.createSection(title, 'network-config-throttling');
219
219
  MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect.createForGlobalConditions(section, title);
220
220
  const saveDataSelect =
221
- MobileThrottling.ThrottlingManager.throttlingManager().createSaveDataOverrideSelector('chrome-select').element;
221
+ MobileThrottling.ThrottlingManager.throttlingManager().createSaveDataOverrideSelector('chrome-select');
222
222
  section.appendChild(saveDataSelect);
223
223
  }
224
224
 
@@ -182,12 +182,6 @@ const UIStrings = {
182
182
  * @description Text in Heap Snapshot View of a profiler tool
183
183
  */
184
184
  heapSnapshotProfilesShowMemory: 'See the memory distribution of JavaScript objects and related DOM nodes',
185
- /**
186
- * @description Label for a checkbox in the heap snapshot view of the profiler tool. The "heap snapshot" contains the
187
- * current state of JavaScript memory. With this checkbox enabled, the snapshot also includes internal data that is
188
- * specific to Chrome (hence implementation-specific).
189
- */
190
- exposeInternals: 'Internals with implementation details',
191
185
  /**
192
186
  * @description Progress update that the profiler is capturing a snapshot of the heap
193
187
  */
@@ -1282,7 +1276,6 @@ export class StatisticsPerspective extends Perspective {
1282
1276
  export class HeapSnapshotProfileType extends
1283
1277
  Common.ObjectWrapper.eventMixin<HeapSnapshotProfileTypeEventTypes, typeof ProfileType>(ProfileType)
1284
1278
  implements SDK.TargetManager.SDKModelObserver<SDK.HeapProfilerModel.HeapProfilerModel> {
1285
- readonly exposeInternals: Common.Settings.Setting<boolean>;
1286
1279
  customContentInternal: UI.UIUtils.CheckboxLabel|null;
1287
1280
  constructor(id?: string, title?: string) {
1288
1281
  super(id || HeapSnapshotProfileType.TypeId, title || i18nString(UIStrings.heapSnapshot));
@@ -1295,7 +1288,6 @@ export class HeapSnapshotProfileType extends
1295
1288
  SDK.TargetManager.TargetManager.instance().addModelListener(
1296
1289
  SDK.HeapProfilerModel.HeapProfilerModel, SDK.HeapProfilerModel.Events.REPORT_HEAP_SNAPSHOT_PROGRESS,
1297
1290
  this.reportHeapSnapshotProgress, this);
1298
- this.exposeInternals = Common.Settings.Settings.instance().createSetting('expose-internals', false);
1299
1291
  this.customContentInternal = null;
1300
1292
  }
1301
1293
 
@@ -1336,19 +1328,6 @@ export class HeapSnapshotProfileType extends
1336
1328
  return i18nString(UIStrings.heapSnapshotProfilesShowMemory);
1337
1329
  }
1338
1330
 
1339
- override customContent(): Element|null {
1340
- const exposeInternalsInHeapSnapshotCheckbox =
1341
- SettingsUI.SettingsUI.createSettingCheckbox(i18nString(UIStrings.exposeInternals), this.exposeInternals);
1342
- this.customContentInternal = exposeInternalsInHeapSnapshotCheckbox;
1343
- return exposeInternalsInHeapSnapshotCheckbox;
1344
- }
1345
-
1346
- override setCustomContentEnabled(enable: boolean): void {
1347
- if (this.customContentInternal) {
1348
- this.customContentInternal.disabled = !enable;
1349
- }
1350
- }
1351
-
1352
1331
  override createProfileLoadedFromFile(title: string): ProfileHeader {
1353
1332
  return new HeapProfileHeader(null, this, title);
1354
1333
  }
@@ -1370,7 +1349,7 @@ export class HeapSnapshotProfileType extends
1370
1349
  await heapProfilerModel.takeHeapSnapshot({
1371
1350
  reportProgress: true,
1372
1351
  captureNumericValue: true,
1373
- exposeInternals: this.exposeInternals.get(),
1352
+ exposeInternals: true,
1374
1353
  });
1375
1354
  profile = this.profileBeingRecorded() as HeapProfileHeader;
1376
1355
  if (!profile) {
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: Internal
3
3
  Version: N/A
4
- Revision: 1f344c5922432c73b3db8100c1f15163fdf8b530
4
+ Revision: e388465394450fcfccc5529cf634c8561999f3b8
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE