chrome-devtools-frontend 1.0.1583146 → 1.0.1585538

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 (112) hide show
  1. package/front_end/core/host/InspectorFrontendHostAPI.ts +1 -0
  2. package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
  3. package/front_end/core/root/Runtime.ts +12 -6
  4. package/front_end/core/sdk/CSSMatchedStyles.ts +3 -0
  5. package/front_end/core/sdk/CSSMetadata.ts +3 -0
  6. package/front_end/entrypoints/main/MainImpl.ts +1 -0
  7. package/front_end/generated/Deprecation.ts +21 -0
  8. package/front_end/generated/InspectorBackendCommands.ts +5 -3
  9. package/front_end/generated/SupportedCSSProperties.js +6 -2
  10. package/front_end/generated/protocol-mapping.d.ts +2 -1
  11. package/front_end/generated/protocol-proxy-api.d.ts +2 -1
  12. package/front_end/generated/protocol.ts +14 -0
  13. package/front_end/models/ai_assistance/AiConversation.ts +34 -2
  14. package/front_end/models/ai_assistance/BuiltInAi.ts +1 -2
  15. package/front_end/models/ai_assistance/agents/AiAgent.ts +3 -10
  16. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +1 -1
  17. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +17 -9
  18. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -24
  19. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +5 -0
  20. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +16 -8
  21. package/front_end/models/computed_style/ComputedStyleModel.ts +20 -15
  22. package/front_end/models/greendev/Prototypes.ts +1 -5
  23. package/front_end/models/issues_manager/CorsIssue.ts +2 -9
  24. package/front_end/models/issues_manager/descriptions/corsLocalNetworkAccessPermissionDenied.md +2 -2
  25. package/front_end/models/javascript_metadata/NativeFunctions.js +20 -0
  26. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +13 -36
  27. package/front_end/panels/ai_assistance/components/ChatInput.ts +73 -95
  28. package/front_end/panels/ai_assistance/components/ChatView.ts +0 -2
  29. package/front_end/panels/common/AiCodeGenerationTeaser.ts +10 -0
  30. package/front_end/panels/console/ConsoleView.ts +1 -2
  31. package/front_end/panels/console/ConsoleViewMessage.ts +18 -11
  32. package/front_end/panels/elements/ComputedStyleWidget.ts +41 -21
  33. package/front_end/panels/elements/ElementsPanel.ts +18 -5
  34. package/front_end/panels/elements/ElementsTreeElement.ts +27 -64
  35. package/front_end/panels/elements/NodeStackTraceWidget.ts +1 -3
  36. package/front_end/panels/elements/computedStyleWidget.css +1 -6
  37. package/front_end/panels/issues/AffectedResourcesView.ts +1 -2
  38. package/front_end/panels/network/NetworkDataGridNode.ts +0 -8
  39. package/front_end/panels/network/RequestConditionsDrawer.ts +138 -112
  40. package/front_end/panels/settings/SettingsScreen.ts +12 -4
  41. package/front_end/panels/snippets/SnippetsQuickOpen.ts +6 -9
  42. package/front_end/panels/sources/CallStackSidebarPane.ts +4 -6
  43. package/front_end/panels/sources/DebuggerPlugin.ts +2 -1
  44. package/front_end/panels/sources/GoToLineQuickOpen.ts +0 -4
  45. package/front_end/panels/sources/OpenFileQuickOpen.ts +0 -4
  46. package/front_end/panels/sources/OutlineQuickOpen.ts +0 -4
  47. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +3 -1
  48. package/front_end/panels/sources/sources-meta.ts +9 -6
  49. package/front_end/panels/timeline/TimelineFlameChartView.ts +0 -12
  50. package/front_end/panels/timeline/TimelinePanel.ts +35 -15
  51. package/front_end/panels/timeline/components/Sidebar.ts +21 -0
  52. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +1 -20
  53. package/front_end/panels/timeline/components/insights/InsightRenderer.ts +0 -1
  54. package/front_end/third_party/chromium/README.chromium +1 -1
  55. package/front_end/third_party/puppeteer/README.chromium +2 -2
  56. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts +1 -1
  57. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  58. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +1 -1
  59. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  61. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +2 -3
  62. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
  63. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  64. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  65. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/encoding.d.ts.map +1 -1
  66. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/encoding.js +5 -3
  67. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/encoding.js.map +1 -1
  68. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  70. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +8 -6
  71. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts +1 -1
  72. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  73. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +1 -1
  74. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  76. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +2 -3
  77. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
  78. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  79. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  80. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/encoding.d.ts.map +1 -1
  81. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/encoding.js +5 -3
  82. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/encoding.js.map +1 -1
  83. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  84. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  85. package/front_end/third_party/puppeteer/package/package.json +4 -4
  86. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +1 -1
  87. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +2 -2
  88. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +4 -3
  89. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  90. package/front_end/third_party/puppeteer/package/src/util/encoding.ts +5 -3
  91. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  92. package/front_end/ui/components/linkifier/LinkifierImpl.ts +3 -0
  93. package/front_end/ui/components/linkifier/LinkifierUtils.ts +3 -0
  94. package/front_end/ui/components/text_editor/AiCodeGenerationParser.ts +29 -7
  95. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +34 -18
  96. package/front_end/ui/legacy/InspectorView.ts +41 -15
  97. package/front_end/ui/legacy/UIUtils.ts +30 -6
  98. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +4 -3
  99. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +2 -1
  100. package/front_end/ui/legacy/components/quick_open/HelpQuickOpen.ts +8 -2
  101. package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +8 -8
  102. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +12 -9
  103. package/front_end/ui/legacy/components/utils/Linkifier.ts +116 -87
  104. package/front_end/ui/legacy/legacy.ts +0 -2
  105. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  106. package/mcp/HostBindings.ts +3 -0
  107. package/package.json +1 -1
  108. package/front_end/models/issues_manager/descriptions/corsInsecurePrivateNetwork.md +0 -10
  109. package/front_end/models/issues_manager/descriptions/corsPreflightAllowPrivateNetworkError.md +0 -10
  110. package/front_end/models/issues_manager/descriptions/corsPrivateNetworkPermissionDenied.md +0 -10
  111. package/front_end/ui/legacy/Floaty.ts +0 -438
  112. package/front_end/ui/legacy/floaty.css +0 -77
@@ -73,6 +73,7 @@ import {ImagePreviewPopover} from './ImagePreviewPopover.js';
73
73
  import {getRegisteredDecorators, type MarkerDecorator, type MarkerDecoratorRegistration} from './MarkerDecorator.js';
74
74
 
75
75
  const {html, nothing, render, Directives: {ref}} = Lit;
76
+ const {animateOn} = UI.UIUtils;
76
77
 
77
78
  const UIStrings = {
78
79
  /**
@@ -465,6 +466,8 @@ export interface Decoration {
465
466
  color: string;
466
467
  }
467
468
 
469
+ const DOM_UPDATE_ANIMATION_CLASS_NAME = 'dom-update-highlight';
470
+
468
471
  function handleAdornerKeydown(cb: (event: Event) => void): (event: KeyboardEvent) => void {
469
472
  return (event: KeyboardEvent) => {
470
473
  if (event.code === 'Enter' || event.code === 'Space') {
@@ -525,14 +528,6 @@ function renderTitle(
525
528
  const result = convertUnicodeCharsToHTMLEntities(firstChild.nodeValue());
526
529
  const textContent = Platform.StringUtilities.collapseWhitespace(result.text);
527
530
 
528
- const highlightAnimation = (updateRecord?.hasChangedChildren() || updateRecord?.isCharDataModified()) ?
529
- ref(el => {
530
- if (el) {
531
- UI.UIUtils.runCSSAnimationOnce(el, 'dom-update-highlight');
532
- }
533
- }) :
534
- nothing;
535
-
536
531
  const renderTextNode = ref(el => {
537
532
  if (el) {
538
533
  el.textContent = textContent;
@@ -541,8 +536,11 @@ function renderTitle(
541
536
  });
542
537
 
543
538
  return html`${openingTag}<span class="webkit-html-text-node" jslog=${
544
- VisualLogging.value('text-node').track({change: true, dblclick: true})} ${highlightAnimation} ${
545
- renderTextNode}></span>\u200B${renderTag(node, tagName, true, expanded, false, updateRecord)}`;
539
+ VisualLogging.value('text-node').track({change: true, dblclick: true})} ${
540
+ animateOn(
541
+ Boolean((updateRecord?.hasChangedChildren() || updateRecord?.isCharDataModified())),
542
+ DOM_UPDATE_ANIMATION_CLASS_NAME)} ${renderTextNode}></span>\u200B${
543
+ renderTag(node, tagName, true, expanded, false, updateRecord)}`;
546
544
  }
547
545
 
548
546
  if (isXMLMimeType || !ForbiddenClosingTagElements.has(tagName)) {
@@ -577,12 +575,6 @@ function renderTitle(
577
575
 
578
576
  const result = convertUnicodeCharsToHTMLEntities(node.nodeValue());
579
577
  const textContent = Platform.StringUtilities.collapseWhitespace(result.text);
580
- const highlightAnimation = updateRecord?.isCharDataModified() ? ref(el => {
581
- if (el) {
582
- UI.UIUtils.runCSSAnimationOnce(el, 'dom-update-highlight');
583
- }
584
- }) :
585
- nothing;
586
578
  const renderTextNode = ref(el => {
587
579
  if (el) {
588
580
  el.textContent = textContent;
@@ -592,7 +584,8 @@ function renderTitle(
592
584
  return html`"<span class="webkit-html-text-node" jslog=${VisualLogging.value('text-node').track({
593
585
  change: true,
594
586
  dblclick: true
595
- })} ${highlightAnimation} ${renderTextNode}></span>"`;
587
+ })} ${animateOn(Boolean(updateRecord?.isCharDataModified()), DOM_UPDATE_ANIMATION_CLASS_NAME)} ${
588
+ renderTextNode}></span>"`;
596
589
  }
597
590
 
598
591
  case Node.COMMENT_NODE: {
@@ -622,18 +615,12 @@ function renderTitle(
622
615
 
623
616
  case Node.DOCUMENT_NODE: {
624
617
  const text = (node as SDK.DOMModel.DOMDocument).documentURL;
625
- const linkify = ref(el => {
626
- if (el) {
627
- el.removeChildren();
628
- el.appendChild(Components.Linkifier.Linkifier.linkifyURL(text, {
629
- text,
630
- preventClick: true,
631
- showColumnNumber: false,
632
- inlineFrameIndex: 0,
633
- }));
634
- }
635
- });
636
- return html`<span>#document (<span ${linkify}></span>)</span>`;
618
+ return html`<span>#document (<span>${Components.Linkifier.Linkifier.renderLinkifiedUrl(text, {
619
+ text,
620
+ preventClick: true,
621
+ showColumnNumber: false,
622
+ inlineFrameIndex: 0,
623
+ })}</span>)</span>`;
637
624
  }
638
625
 
639
626
  case Node.DOCUMENT_FRAGMENT_NODE: {
@@ -684,20 +671,6 @@ function renderAttribute(
684
671
  dblclick: true,
685
672
  });
686
673
 
687
- const highlightNameAnimation = updateRecord?.isAttributeModified(name) && !hasText ? ref(el => {
688
- if (el) {
689
- UI.UIUtils.runCSSAnimationOnce(el, 'dom-update-highlight');
690
- }
691
- }) :
692
- nothing;
693
-
694
- const highlightValueAnimation = updateRecord?.isAttributeModified(name) && hasText ? ref(el => {
695
- if (el) {
696
- UI.UIUtils.runCSSAnimationOnce(el, 'dom-update-highlight');
697
- }
698
- }) :
699
- nothing;
700
-
701
674
  function linkifyValue(value: string): Element {
702
675
  const rewrittenHref = node ? node.resolveURL(value) : null;
703
676
  if (rewrittenHref === null) {
@@ -831,10 +804,13 @@ function renderAttribute(
831
804
  }
832
805
  }
833
806
 
834
- return html`<span class="webkit-html-attribute" jslog=${jslog}><span class="webkit-html-attribute-name" ${
835
- highlightNameAnimation} ${relationRefDirective}>${name}</span>${
836
- hasText ? html`=\u200B"<span class="webkit-html-attribute-value" ${highlightValueAnimation} ${setAttrValue} ${
837
- valueRelationRefDirective}></span>"` :
807
+ return html`<span class="webkit-html-attribute" jslog=${jslog}><span class="webkit-html-attribute-name"
808
+ ${animateOn(Boolean(updateRecord?.isAttributeModified(name) && !hasText), DOM_UPDATE_ANIMATION_CLASS_NAME)} ${
809
+ relationRefDirective}>${name}</span>${
810
+ hasText ? html`=\u200B"<span class="webkit-html-attribute-value" ${
811
+ animateOn(
812
+ Boolean(updateRecord?.isAttributeModified(name) && hasText),
813
+ DOM_UPDATE_ANIMATION_CLASS_NAME)} ${setAttrValue} ${valueRelationRefDirective}></span>"` :
838
814
  nothing}</span>`;
839
815
  }
840
816
 
@@ -855,13 +831,6 @@ function renderTag(
855
831
  hasUpdates = hasUpdates || (!expanded && updateRecord.hasChangedChildren());
856
832
  }
857
833
 
858
- const highlightAnimation = hasUpdates ? ref(el => {
859
- if (el) {
860
- UI.UIUtils.runCSSAnimationOnce(el, 'dom-update-highlight');
861
- }
862
- }) :
863
- nothing;
864
-
865
834
  // We are taking full text content of the tag, including attributes and children, to set the aria label.
866
835
  // FIXME: we should compute the aria label ourselves if it is event needed.
867
836
  const setAriaLabel = ref(el => {
@@ -876,7 +845,8 @@ function renderTag(
876
845
 
877
846
  return html`<span
878
847
  class=${Lit.Directives.classMap(classMap)} ${setAriaLabel}
879
- >&lt;<span class=${tagNameClass} jslog=${jslog || nothing} ${highlightAnimation}>${tagString}</span>${
848
+ >&lt;<span class=${tagNameClass} jslog=${jslog || nothing} ${
849
+ animateOn(hasUpdates, DOM_UPDATE_ANIMATION_CLASS_NAME)}>${tagString}</span>${
880
850
  attributes.map(attr => html` ${renderAttribute(attr, updateRecord, false, node)}`)}&gt;</span>\u200B`;
881
851
  }
882
852
 
@@ -1189,7 +1159,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1189
1159
 
1190
1160
  static animateOnDOMUpdate(treeElement: ElementsTreeElement): void {
1191
1161
  const tagName = treeElement.listItemElement.querySelector('.webkit-html-tag-name');
1192
- UI.UIUtils.runCSSAnimationOnce(tagName || treeElement.listItemElement, 'dom-update-highlight');
1162
+ UI.UIUtils.runCSSAnimationOnce(tagName || treeElement.listItemElement, DOM_UPDATE_ANIMATION_CLASS_NAME);
1193
1163
  }
1194
1164
 
1195
1165
  static visibleShadowRoots(node: SDK.DOMModel.DOMNode): SDK.DOMModel.DOMNode[] {
@@ -1420,7 +1390,7 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1420
1390
  }
1421
1391
  }
1422
1392
  }
1423
- UI.UIUtils.runCSSAnimationOnce(animationElement, 'dom-update-highlight');
1393
+ UI.UIUtils.runCSSAnimationOnce(animationElement, DOM_UPDATE_ANIMATION_CLASS_NAME);
1424
1394
  }
1425
1395
 
1426
1396
  isClosingTag(): boolean {
@@ -1726,13 +1696,6 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1726
1696
  if (this.editing) {
1727
1697
  return false;
1728
1698
  }
1729
- const handledByFloaty = UI.Floaty.onFloatyClick({
1730
- type: UI.Floaty.FloatyContextTypes.ELEMENT_NODE_ID,
1731
- data: {nodeId: this.nodeInternal.id},
1732
- });
1733
- if (handledByFloaty) {
1734
- return false;
1735
- }
1736
1699
  return super.select(omitFocus, selectedByUser);
1737
1700
  }
1738
1701
 
@@ -45,7 +45,7 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
45
45
  };
46
46
 
47
47
  export class NodeStackTraceWidget extends UI.Widget.VBox {
48
- readonly #linkifier = new Components.Linkifier.Linkifier(MaxLengthForLinks);
48
+ readonly #linkifier = new Components.Linkifier.Linkifier(UI.UIUtils.MaxLengthForDisplayedURLsInConsole);
49
49
  readonly #view: View;
50
50
 
51
51
  constructor(view = DEFAULT_VIEW) {
@@ -81,5 +81,3 @@ export class NodeStackTraceWidget extends UI.Widget.VBox {
81
81
  this.#view(input, {}, this.contentElement);
82
82
  }
83
83
  }
84
-
85
- export const MaxLengthForLinks = 40;
@@ -14,12 +14,7 @@
14
14
  width: 100%;
15
15
  }
16
16
 
17
- .styles-sidebar-computed-style-widget {
18
- min-height: auto;
19
- }
20
-
21
- .computed-style-tree-outline-container {
22
- flex-grow: 1;
17
+ devtools-tree-outline {
23
18
  flex-shrink: 0;
24
19
  }
25
20
 
@@ -253,8 +253,7 @@ export abstract class AffectedResourcesView extends UI.TreeOutline.TreeElement {
253
253
  const sourceCodeLocation = document.createElement('td');
254
254
  sourceCodeLocation.classList.add('affected-source-location');
255
255
  if (sourceLocation) {
256
- const maxLengthForDisplayedURLs = 40; // Same as console messages.
257
- const linkifier = new Components.Linkifier.Linkifier(maxLengthForDisplayedURLs);
256
+ const linkifier = new Components.Linkifier.Linkifier(UI.UIUtils.MaxLengthForDisplayedURLsInConsole);
258
257
  const sourceAnchor = linkifier.linkifyScriptLocation(
259
258
  target || null, sourceLocation.scriptId || null, sourceLocation.url as Platform.DevToolsPath.UrlString,
260
259
  sourceLocation.lineNumber, {columnNumber: sourceLocation.columnNumber, inlineFrameIndex: 0});
@@ -1185,14 +1185,6 @@ export class NetworkRequestNode extends NetworkNode {
1185
1185
  }
1186
1186
 
1187
1187
  override select(suppressSelectedEvent?: boolean): void {
1188
- const id = this.request()?.requestId();
1189
- if (id) {
1190
- const floatyHandled =
1191
- UI.Floaty.onFloatyClick({type: UI.Floaty.FloatyContextTypes.NETWORK_REQUEST, data: {requestId: id}});
1192
- if (floatyHandled) {
1193
- return;
1194
- }
1195
- }
1196
1188
  super.select(suppressSelectedEvent);
1197
1189
  this.parentView().dispatchEventToListeners(Events.RequestSelected, this.requestInternal);
1198
1190
  }
@@ -183,6 +183,109 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
183
183
  target);
184
184
  };
185
185
 
186
+ function renderItem(
187
+ condition: SDK.NetworkManager.RequestCondition, editable: boolean, index: number,
188
+ onToggle: (condition: SDK.NetworkManager.RequestCondition) => void,
189
+ onConditionsChanged: (
190
+ condition: SDK.NetworkManager.RequestCondition, conditions: SDK.NetworkManager.ThrottlingConditions) => void,
191
+ onIncreasePriority: (condition: SDK.NetworkManager.RequestCondition) => void,
192
+ onDecreasePriority: (condition: SDK.NetworkManager.RequestCondition) => void,
193
+ lookUpRequestCount: (condition: SDK.NetworkManager.RequestCondition) => number): LitTemplate {
194
+ const {enabled, originalOrUpgradedURLPattern, constructorStringOrWildcardURL, wildcardURL} = condition;
195
+ const toggle = (e: Event): void => {
196
+ e.consume(true);
197
+ onToggle(condition);
198
+ };
199
+
200
+ const moveUp = (e: Event): void => {
201
+ e.consume(true);
202
+ onIncreasePriority(condition);
203
+ };
204
+
205
+ const moveDown = (e: Event): void => {
206
+ e.consume(true);
207
+ onDecreasePriority(condition);
208
+ };
209
+
210
+ // clang-format off
211
+ return html`
212
+ <input class=blocked-url-checkbox
213
+ @change=${toggle}
214
+ type=checkbox
215
+ title=${i18nString(UIStrings.enableThrottlingToggleLabel, {PH1: constructorStringOrWildcardURL})}
216
+ .checked=${live(enabled)}
217
+ .disabled=${!editable || !originalOrUpgradedURLPattern}
218
+ jslog=${VisualLogging.toggle().track({ change: true })}>
219
+ <devtools-button
220
+ .iconName=${'arrow-up'}
221
+ .variant=${Buttons.Button.Variant.ICON}
222
+ .title=${i18nString(UIStrings.increasePriority, {PH1: constructorStringOrWildcardURL})}
223
+ .jslogContext=${'decrease-priority'}
224
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
225
+ @click=${moveUp}>
226
+ </devtools-button>
227
+ <devtools-button
228
+ .iconName=${'arrow-down'}
229
+ .variant=${Buttons.Button.Variant.ICON}
230
+ .title=${i18nString(UIStrings.decreasePriority, {PH1: constructorStringOrWildcardURL})}
231
+ .jslogContext=${'increase-priority'}
232
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
233
+ @click=${moveDown}></devtools-button>
234
+ ${originalOrUpgradedURLPattern ? html`
235
+ <devtools-tooltip variant=rich jslogcontext=url-pattern id=url-pattern-${index}>
236
+ <div>hash: ${originalOrUpgradedURLPattern.hash}</div>
237
+ <div>hostname: ${originalOrUpgradedURLPattern.hostname}</div>
238
+ <div>password: ${originalOrUpgradedURLPattern.password}</div>
239
+ <div>pathname: ${originalOrUpgradedURLPattern.pathname}</div>
240
+ <div>port: ${originalOrUpgradedURLPattern.port}</div>
241
+ <div>protocol: ${originalOrUpgradedURLPattern.protocol}</div>
242
+ <div>search: ${originalOrUpgradedURLPattern.search}</div>
243
+ <div>username: ${originalOrUpgradedURLPattern.username}</div>
244
+ <hr />
245
+ ${learnMore()}
246
+ </devtools-tooltip>` : nothing}
247
+ ${wildcardURL ? html`
248
+ <devtools-icon name=warning-filled class="small warning" aria-details=url-pattern-warning-${index}>
249
+ </devtools-icon>
250
+ <devtools-tooltip variant=rich jslogcontext=url-pattern-warning id=url-pattern-warning-${index}>
251
+ ${i18nString(UIStrings.patternWasUpgraded, {PH1: wildcardURL})}
252
+ </devtools-tooltip>
253
+ `: nothing}
254
+ ${!originalOrUpgradedURLPattern ? html`
255
+ <devtools-icon name=cross-circle-filled class=small aria-details=url-pattern-error-${index}>
256
+ </devtools-icon>
257
+ <devtools-tooltip variant=rich jslogcontext=url-pattern-warning id=url-pattern-error-${index}>
258
+ ${SDK.NetworkManager.RequestURLPattern.isValidPattern(constructorStringOrWildcardURL) ===
259
+ SDK.NetworkManager.RequestURLPatternValidity.HAS_REGEXP_GROUPS
260
+ ? i18nString(UIStrings.patternFailedWithRegExpGroups)
261
+ : i18nString(UIStrings.patternFailedToParse)}
262
+ ${learnMore()}
263
+ </devtools-tooltip>`: nothing}
264
+ <div
265
+ @click=${toggle}
266
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
267
+ class=blocked-url-label
268
+ aria-details=url-pattern-${index}>
269
+ ${constructorStringOrWildcardURL}
270
+ </div>
271
+ <devtools-widget
272
+ class=conditions-selector
273
+ title=${i18nString(UIStrings.requestConditionsLabel)}
274
+ .widgetConfig=${UI.Widget.widgetConfig(
275
+ MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelectorWidget, {
276
+ variant:
277
+ MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect.Variant.INDIVIDUAL_REQUEST_CONDITIONS,
278
+ jslogContext: 'request-conditions',
279
+ disabled: !editable,
280
+ onConditionsChanged: conditions => onConditionsChanged(condition, conditions),
281
+ currentConditions: condition.conditions,
282
+ })}></devtools-widget>
283
+ <devtools-widget
284
+ ?disabled=${!editable || !originalOrUpgradedURLPattern}
285
+ .widgetConfig=${widgetConfig(AffectedCountWidget, {condition, lookUpRequestCount})}></devtools-widget>`;
286
+ // clang-format on
287
+ }
288
+
186
289
  interface AffectedCountViewInput {
187
290
  count: number;
188
291
  }
@@ -198,39 +301,36 @@ function matchesUrl(conditions: SDK.NetworkManager.RequestCondition, url: string
198
301
  export class AffectedCountWidget extends UI.Widget.Widget {
199
302
  readonly #view: AffectedCountView;
200
303
  #condition?: SDK.NetworkManager.RequestCondition;
201
- #drawer?: RequestConditionsDrawer;
304
+ #lookUpRequestCount?: (condition: SDK.NetworkManager.RequestCondition) => number;
305
+
202
306
  constructor(target?: HTMLElement, view = AFFECTED_COUNT_DEFAULT_VIEW) {
203
307
  super(target, {classes: ['blocked-url-count']});
204
308
  this.#view = view;
205
309
  }
206
310
 
207
- get condition(): SDK.NetworkManager.RequestCondition|undefined {
208
- return this.#condition;
311
+ get lookUpRequestCount(): ((condition: SDK.NetworkManager.RequestCondition) => number)|undefined {
312
+ return this.#lookUpRequestCount;
209
313
  }
210
314
 
211
- set condition(conditions: SDK.NetworkManager.RequestCondition) {
212
- this.#condition = conditions;
213
- this.requestUpdate();
315
+ set lookUpRequestCount(val: (condition: SDK.NetworkManager.RequestCondition) => number) {
316
+ this.#lookUpRequestCount = val;
214
317
  }
215
318
 
216
- get drawer(): RequestConditionsDrawer|undefined {
217
- return this.#drawer;
319
+ get condition(): SDK.NetworkManager.RequestCondition|undefined {
320
+ return this.#condition;
218
321
  }
219
322
 
220
- set drawer(drawer: RequestConditionsDrawer) {
221
- this.#drawer = drawer;
323
+ set condition(conditions: SDK.NetworkManager.RequestCondition) {
324
+ this.#condition = conditions;
222
325
  this.requestUpdate();
223
326
  }
224
327
 
225
328
  override performUpdate(): void {
226
- if (!this.#condition || !this.#drawer) {
329
+ if (!this.#condition || !this.#lookUpRequestCount) {
227
330
  return;
228
331
  }
229
332
 
230
- const count = this.#condition.isBlocking ? this.#drawer.blockedRequestsCount(this.#condition) :
231
- this.#drawer.throttledRequestsCount(this.#condition);
232
-
233
- this.#view({count}, {}, this.element);
333
+ this.#view({count: this.#lookUpRequestCount(this.#condition)}, {}, this.element);
234
334
  }
235
335
 
236
336
  override wasShown(): void {
@@ -342,112 +442,38 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
342
442
 
343
443
  updateItem(element: HTMLElement, condition: SDK.NetworkManager.RequestCondition, editable: boolean, index: number):
344
444
  void {
345
- const toggle = (e: Event): void => {
445
+ const onToggle = (condition: {enabled: boolean}): void => {
346
446
  if (editable) {
347
- e.consume(true);
348
447
  condition.enabled = !condition.enabled;
349
448
  }
350
449
  };
351
- const onConditionsChanged = (conditions: SDK.NetworkManager.ThrottlingConditions): void => {
352
- if (editable) {
353
- condition.conditions = conditions;
354
- }
355
- };
356
450
 
357
- const {enabled, originalOrUpgradedURLPattern, constructorStringOrWildcardURL, wildcardURL} = condition;
451
+ const onConditionsChanged =
452
+ (condition: {conditions: SDK.NetworkManager.ThrottlingConditions},
453
+ conditions: SDK.NetworkManager.ThrottlingConditions): void => {
454
+ if (editable) {
455
+ condition.conditions = conditions;
456
+ }
457
+ };
358
458
 
359
- const moveUp = (e: Event): void => {
459
+ const onIncreasePriority = (condition: SDK.NetworkManager.RequestCondition): void => {
360
460
  if (this.manager.requestConditions.conditionsEnabled) {
361
461
  UI.ARIAUtils.LiveAnnouncer.status(i18nString(UIStrings.patternMovedUp));
362
- e.consume(true);
363
462
  this.manager.requestConditions.increasePriority(condition);
364
463
  }
365
464
  };
366
- const moveDown = (e: Event): void => {
465
+
466
+ const onDecreasePriority = (condition: SDK.NetworkManager.RequestCondition): void => {
367
467
  if (this.manager.requestConditions.conditionsEnabled) {
368
468
  UI.ARIAUtils.LiveAnnouncer.status(i18nString(UIStrings.patternMovedDown));
369
- e.consume(true);
370
469
  this.manager.requestConditions.decreasePriority(condition);
371
470
  }
372
471
  };
472
+
373
473
  render(
374
- // clang-format off
375
- html`
376
- <input class=blocked-url-checkbox
377
- @change=${toggle}
378
- type=checkbox
379
- title=${i18nString(UIStrings.enableThrottlingToggleLabel, {PH1: constructorStringOrWildcardURL})}
380
- .checked=${live(enabled)}
381
- .disabled=${!editable || !originalOrUpgradedURLPattern}
382
- jslog=${VisualLogging.toggle().track({ change: true })}>
383
- <devtools-button
384
- .iconName=${'arrow-up'}
385
- .variant=${Buttons.Button.Variant.ICON}
386
- .title=${i18nString(UIStrings.increasePriority, {PH1: constructorStringOrWildcardURL})}
387
- .jslogContext=${'decrease-priority'}
388
- ?disabled=${!editable || !originalOrUpgradedURLPattern}
389
- @click=${moveUp}>
390
- </devtools-button>
391
- <devtools-button
392
- .iconName=${'arrow-down'}
393
- .variant=${Buttons.Button.Variant.ICON}
394
- .title=${i18nString(UIStrings.decreasePriority, {PH1: constructorStringOrWildcardURL})}
395
- .jslogContext=${'increase-priority'}
396
- ?disabled=${!editable || !originalOrUpgradedURLPattern}
397
- @click=${moveDown}></devtools-button>
398
- ${originalOrUpgradedURLPattern ? html`
399
- <devtools-tooltip variant=rich jslogcontext=url-pattern id=url-pattern-${index}>
400
- <div>hash: ${originalOrUpgradedURLPattern.hash}</div>
401
- <div>hostname: ${originalOrUpgradedURLPattern.hostname}</div>
402
- <div>password: ${originalOrUpgradedURLPattern.password}</div>
403
- <div>pathname: ${originalOrUpgradedURLPattern.pathname}</div>
404
- <div>port: ${originalOrUpgradedURLPattern.port}</div>
405
- <div>protocol: ${originalOrUpgradedURLPattern.protocol}</div>
406
- <div>search: ${originalOrUpgradedURLPattern.search}</div>
407
- <div>username: ${originalOrUpgradedURLPattern.username}</div>
408
- <hr />
409
- ${learnMore()}
410
- </devtools-tooltip>` : nothing}
411
- ${wildcardURL ? html`
412
- <devtools-icon name=warning-filled class="small warning" aria-details=url-pattern-warning-${index}>
413
- </devtools-icon>
414
- <devtools-tooltip variant=rich jslogcontext=url-pattern-warning id=url-pattern-warning-${index}>
415
- ${i18nString(UIStrings.patternWasUpgraded, {PH1: wildcardURL})}
416
- </devtools-tooltip>
417
- `: nothing}
418
- ${!originalOrUpgradedURLPattern ? html`
419
- <devtools-icon name=cross-circle-filled class=small aria-details=url-pattern-error-${index}>
420
- </devtools-icon>
421
- <devtools-tooltip variant=rich jslogcontext=url-pattern-warning id=url-pattern-error-${index}>
422
- ${SDK.NetworkManager.RequestURLPattern.isValidPattern(constructorStringOrWildcardURL) ===
423
- SDK.NetworkManager.RequestURLPatternValidity.HAS_REGEXP_GROUPS
424
- ? i18nString(UIStrings.patternFailedWithRegExpGroups)
425
- : i18nString(UIStrings.patternFailedToParse)}
426
- ${learnMore()}
427
- </devtools-tooltip>`: nothing}
428
- <div
429
- @click=${toggle}
430
- ?disabled=${!editable || !originalOrUpgradedURLPattern}
431
- class=blocked-url-label
432
- aria-details=url-pattern-${index}>
433
- ${constructorStringOrWildcardURL}
434
- </div>
435
- <devtools-widget
436
- class=conditions-selector
437
- title=${i18nString(UIStrings.requestConditionsLabel)}
438
- .widgetConfig=${UI.Widget.widgetConfig(
439
- MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelectorWidget, {
440
- variant:
441
- MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect.Variant.INDIVIDUAL_REQUEST_CONDITIONS,
442
- jslogContext: 'request-conditions',
443
- disabled: !editable,
444
- onConditionsChanged,
445
- currentConditions: condition.conditions,
446
- })}></devtools-widget>
447
- <devtools-widget
448
- ?disabled=${!editable || !originalOrUpgradedURLPattern}
449
- .widgetConfig=${widgetConfig(AffectedCountWidget, {condition, drawer: this})}></devtools-widget>`,
450
- // clang-format on
474
+ renderItem(
475
+ condition, editable, index, onToggle, onConditionsChanged, onIncreasePriority, onDecreasePriority,
476
+ this.#getRequestCount.bind(this)),
451
477
  element);
452
478
  }
453
479
 
@@ -546,17 +572,17 @@ export class RequestConditionsDrawer extends UI.Widget.VBox implements
546
572
  this.requestUpdate();
547
573
  }
548
574
 
549
- blockedRequestsCount(condition: SDK.NetworkManager.RequestCondition): number {
550
- let result = 0;
551
- for (const blockedUrl of this.blockedCountForUrl.keys()) {
552
- if (matchesUrl(condition, blockedUrl)) {
553
- result += (this.blockedCountForUrl.get(blockedUrl) as number);
575
+ #getRequestCount(condition: SDK.NetworkManager.RequestCondition): number {
576
+ if (condition.isBlocking) {
577
+ let result = 0;
578
+ for (const blockedUrl of this.blockedCountForUrl.keys()) {
579
+ if (matchesUrl(condition, blockedUrl)) {
580
+ result += (this.blockedCountForUrl.get(blockedUrl) as number);
581
+ }
554
582
  }
583
+ return result;
555
584
  }
556
- return result;
557
- }
558
585
 
559
- throttledRequestsCount(condition: SDK.NetworkManager.RequestCondition): number {
560
586
  let result = 0;
561
587
  for (const ruleId of condition.ruleIds) {
562
588
  result += this.#throttledCount.get(ruleId) ?? 0;
@@ -60,6 +60,10 @@ const UIStrings = {
60
60
  * @description Message to display if a setting change requires a reload of DevTools
61
61
  */
62
62
  settingsChangedReloadDevTools: 'Settings changed. To apply, reload DevTools.',
63
+ /**
64
+ * @description Message to display if a setting change requires a reload of DevTools
65
+ */
66
+ settingsChangedRestartChrome: 'Settings changed. To apply, restart Chrome.',
63
67
  /**
64
68
  * @description Warning text shown when the user has entered text to filter the
65
69
  * list of experiments, but no experiments match the filter.
@@ -464,8 +468,13 @@ export class ExperimentsSettingsTab extends UI.Widget.VBox implements SettingsTa
464
468
  }
465
469
  experiment.setEnabled(checkbox.checked);
466
470
  Host.userMetrics.experimentChanged(experiment.name, experiment.isEnabled());
467
- UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(
468
- i18nString(UIStrings.settingsChangedReloadDevTools));
471
+ if (experiment instanceof Root.Runtime.HostExperiment && experiment.requiresChromeRestart) {
472
+ UI.InspectorView.InspectorView.instance().displayChromeRestartRequiredWarning(
473
+ i18nString(UIStrings.settingsChangedRestartChrome));
474
+ } else {
475
+ UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(
476
+ i18nString(UIStrings.settingsChangedReloadDevTools));
477
+ }
469
478
  }
470
479
  checkbox.addEventListener('click', listener, false);
471
480
 
@@ -628,7 +637,7 @@ const GREENDEV_VIEW: View = (input, _output, target) => {
628
637
  <span>${i18nString(UIStrings.greenDevUnstable)}</span>
629
638
  </div>
630
639
  <div class="settings-experiments-block">
631
- ${renderPrototypeCheckboxes(input.settings, ['aiAnnotations', 'inDevToolsFloaty', 'copyToGemini'])}
640
+ ${renderPrototypeCheckboxes(input.settings, ['aiAnnotations', 'copyToGemini'])}
632
641
  </div>
633
642
  </devtools-card>
634
643
  </div>
@@ -637,7 +646,6 @@ const GREENDEV_VIEW: View = (input, _output, target) => {
637
646
  };
638
647
 
639
648
  const GREENDEV_PROTOTYPE_NAMES: Record<keyof GreenDev.GreenDevSettings, string> = {
640
- inDevToolsFloaty: 'In DevTools context picker',
641
649
  aiAnnotations: 'AI auto-annotations',
642
650
  copyToGemini: 'Copy changes to AI Prompt'
643
651
  };
@@ -37,16 +37,12 @@ const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined
37
37
  let snippetsQuickOpenInstance: SnippetsQuickOpen;
38
38
 
39
39
  export class SnippetsQuickOpen extends QuickOpen.FilteredListWidget.Provider {
40
- private snippets: Workspace.UISourceCode.UISourceCode[];
41
- private constructor() {
42
- super('snippet');
43
- this.snippets = [];
44
- }
40
+ private snippets: Workspace.UISourceCode.UISourceCode[] = [];
45
41
 
46
- static instance(opts: {forceNew: boolean|null} = {forceNew: null}): SnippetsQuickOpen {
47
- const {forceNew} = opts;
42
+ static instance(opts: {forceNew: boolean|null, jslogContext: string}): SnippetsQuickOpen {
43
+ const {forceNew, jslogContext} = opts;
48
44
  if (!snippetsQuickOpenInstance || forceNew) {
49
- snippetsQuickOpenInstance = new SnippetsQuickOpen();
45
+ snippetsQuickOpenInstance = new SnippetsQuickOpen(jslogContext);
50
46
  }
51
47
 
52
48
  return snippetsQuickOpenInstance;
@@ -102,8 +98,9 @@ export class SnippetsQuickOpen extends QuickOpen.FilteredListWidget.Provider {
102
98
  QuickOpen.FilteredListWidget.registerProvider({
103
99
  prefix: '!',
104
100
  iconName: 'exclamation',
105
- provider: () => Promise.resolve(SnippetsQuickOpen.instance()),
101
+ provider: jslogContext => Promise.resolve(SnippetsQuickOpen.instance({forceNew: null, jslogContext})),
106
102
  helpTitle: i18nLazyString(UIStrings.runSnippet),
107
103
  titlePrefix: i18nLazyString(UIStrings.run),
108
104
  titleSuggestion: i18nLazyString(UIStrings.snippet),
105
+ jslogContext: 'snippet'
109
106
  });