chrome-devtools-frontend 1.0.927127 → 1.0.928589

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 (144) hide show
  1. package/AUTHORS +1 -0
  2. package/config/gni/all_devtools_files.gni +0 -1
  3. package/config/gni/devtools_grd_files.gni +30 -4
  4. package/config/gni/devtools_image_files.gni +1 -0
  5. package/front_end/Images/src/ic_preview_feature.svg +3 -0
  6. package/front_end/Tests.js +2 -3
  7. package/front_end/core/common/Settings.ts +26 -45
  8. package/front_end/core/host/UserMetrics.ts +2 -2
  9. package/front_end/core/i18n/locales/en-US.json +60 -15
  10. package/front_end/core/i18n/locales/en-XL.json +60 -15
  11. package/front_end/core/platform/keyboard-utilities.ts +1 -0
  12. package/front_end/core/root/Runtime.ts +62 -61
  13. package/front_end/core/sdk/AccessibilityModel.ts +73 -73
  14. package/front_end/core/sdk/CPUProfileDataModel.ts +14 -14
  15. package/front_end/core/sdk/CPUProfilerModel.ts +33 -33
  16. package/front_end/core/sdk/CPUThrottlingManager.ts +8 -8
  17. package/front_end/core/sdk/CSSFontFace.ts +10 -10
  18. package/front_end/core/sdk/CSSMatchedStyles.ts +114 -114
  19. package/front_end/core/sdk/CSSMedia.ts +22 -22
  20. package/front_end/core/sdk/CSSMetadata.ts +53 -49
  21. package/front_end/core/sdk/CSSModel.ts +139 -135
  22. package/front_end/core/sdk/CSSProperty.ts +18 -18
  23. package/front_end/core/sdk/CSSRule.ts +15 -15
  24. package/front_end/core/sdk/CSSStyleDeclaration.ts +49 -47
  25. package/front_end/core/sdk/CSSStyleSheetHeader.ts +12 -12
  26. package/front_end/core/sdk/ChildTargetManager.ts +41 -40
  27. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +10 -10
  28. package/front_end/core/sdk/Connections.ts +81 -81
  29. package/front_end/core/sdk/ConsoleModel.ts +68 -68
  30. package/front_end/core/sdk/Cookie.ts +48 -48
  31. package/front_end/core/sdk/CookieModel.ts +13 -13
  32. package/front_end/core/sdk/CookieParser.ts +45 -45
  33. package/front_end/core/sdk/DOMDebuggerModel.ts +131 -131
  34. package/front_end/core/sdk/DOMModel.ts +264 -252
  35. package/front_end/core/sdk/DebuggerModel.ts +209 -205
  36. package/front_end/core/sdk/EmulationModel.ts +76 -76
  37. package/front_end/core/sdk/FilmStripModel.ts +29 -29
  38. package/front_end/core/sdk/FrameManager.ts +43 -42
  39. package/front_end/core/sdk/HeapProfilerModel.ts +36 -36
  40. package/front_end/core/sdk/IsolateManager.ts +82 -82
  41. package/front_end/core/sdk/IssuesModel.ts +6 -6
  42. package/front_end/core/sdk/LayerTreeBase.ts +37 -37
  43. package/front_end/core/sdk/LogModel.ts +5 -5
  44. package/front_end/core/sdk/NetworkManager.ts +229 -225
  45. package/front_end/core/sdk/NetworkRequest.ts +368 -360
  46. package/front_end/core/sdk/OverlayColorGenerator.ts +9 -9
  47. package/front_end/core/sdk/OverlayModel.ts +155 -153
  48. package/front_end/core/sdk/OverlayPersistentHighlighter.ts +100 -101
  49. package/front_end/core/sdk/PageResourceLoader.ts +30 -30
  50. package/front_end/core/sdk/PaintProfiler.ts +16 -16
  51. package/front_end/core/sdk/PerformanceMetricsModel.ts +12 -12
  52. package/front_end/core/sdk/ProfileTreeModel.ts +3 -3
  53. package/front_end/core/sdk/RemoteObject.ts +108 -104
  54. package/front_end/core/sdk/Resource.ts +85 -84
  55. package/front_end/core/sdk/ResourceTreeModel.ts +150 -145
  56. package/front_end/core/sdk/RuntimeModel.ts +38 -34
  57. package/front_end/core/sdk/SDKModel.ts +3 -3
  58. package/front_end/core/sdk/ScreenCaptureModel.ts +19 -19
  59. package/front_end/core/sdk/Script.ts +29 -29
  60. package/front_end/core/sdk/SecurityOriginManager.ts +19 -19
  61. package/front_end/core/sdk/ServerTiming.ts +2 -2
  62. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +43 -43
  63. package/front_end/core/sdk/ServiceWorkerManager.ts +72 -68
  64. package/front_end/core/sdk/SourceMap.ts +40 -36
  65. package/front_end/core/sdk/SourceMapManager.ts +57 -57
  66. package/front_end/core/sdk/Target.ts +64 -63
  67. package/front_end/core/sdk/TargetManager.ts +60 -56
  68. package/front_end/core/sdk/TracingManager.ts +39 -39
  69. package/front_end/core/sdk/TracingModel.ts +125 -125
  70. package/front_end/core/sdk/WebAuthnModel.ts +9 -9
  71. package/front_end/entrypoints/lighthouse_worker/{LighthouseService.js → LighthouseService.ts} +20 -45
  72. package/front_end/entrypoints/lighthouse_worker/{lighthouse_worker.js → lighthouse_worker.ts} +0 -0
  73. package/front_end/entrypoints/main/MainImpl.ts +7 -2
  74. package/front_end/legacy_test_runner/elements_test_runner/ElementsTestRunner.js +4 -4
  75. package/front_end/legacy_test_runner/sdk_test_runner/sdk_test_runner.js +1 -1
  76. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +0 -6
  77. package/front_end/models/issues_manager/GenericIssue.ts +86 -0
  78. package/front_end/models/issues_manager/Issue.ts +24 -0
  79. package/front_end/models/issues_manager/IssuesManager.ts +18 -6
  80. package/front_end/models/issues_manager/descriptions/genericCrossOriginPortalPostMessageError.md +3 -0
  81. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  82. package/front_end/models/javascript_metadata/NativeFunctions.js +5422 -1
  83. package/front_end/panels/console/ConsoleSidebar.ts +0 -3
  84. package/front_end/panels/elements/ElementsTreeElement.ts +53 -61
  85. package/front_end/panels/elements/ElementsTreeOutline.ts +0 -1
  86. package/front_end/panels/elements/components/LayoutPane.ts +5 -1
  87. package/front_end/panels/issues/GenericIssueDetailsView.ts +68 -0
  88. package/front_end/panels/issues/IssueAggregator.ts +16 -0
  89. package/front_end/panels/issues/IssueKindView.ts +95 -0
  90. package/front_end/panels/issues/IssueView.ts +6 -0
  91. package/front_end/panels/issues/IssuesPane.ts +81 -18
  92. package/front_end/panels/issues/issuesTree.css +8 -3
  93. package/front_end/panels/lighthouse/LighthouseController.ts +3 -1
  94. package/front_end/panels/network/NetworkItemView.ts +1 -1
  95. package/front_end/panels/network/networkLogView.css +5 -0
  96. package/front_end/panels/sensors/LocationsSettingsTab.ts +1 -1
  97. package/front_end/panels/settings/SettingsScreen.ts +1 -0
  98. package/front_end/panels/settings/settingsScreen.css +24 -0
  99. package/front_end/panels/snippets/SnippetsQuickOpen.ts +8 -3
  100. package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
  101. package/front_end/panels/sources/sources-meta.ts +22 -7
  102. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  103. package/front_end/third_party/codemirror.next/package.json +4 -4
  104. package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +137 -0
  105. package/front_end/ui/components/code_highlighter/codeHighlighter.css +51 -0
  106. package/front_end/ui/components/code_highlighter/code_highlighter.ts +11 -0
  107. package/front_end/ui/components/docs/text_editor/basic.html +28 -0
  108. package/front_end/ui/components/docs/text_editor/basic.ts +14 -0
  109. package/front_end/ui/components/docs/text_prompt/basic.html +35 -0
  110. package/front_end/ui/components/docs/text_prompt/basic.ts +19 -0
  111. package/front_end/ui/components/issue_counter/IssueLinkIcon.ts +1 -0
  112. package/front_end/ui/components/render_coordinator/RenderCoordinator.ts +17 -0
  113. package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +1 -0
  114. package/front_end/ui/components/text_editor/TextEditor.ts +161 -0
  115. package/front_end/ui/components/text_editor/config.ts +264 -0
  116. package/front_end/{panels/console/components/components.ts → ui/components/text_editor/text_editor.ts} +2 -5
  117. package/front_end/ui/components/text_editor/theme.ts +113 -0
  118. package/front_end/ui/components/text_prompt/TextPrompt.ts +144 -0
  119. package/front_end/ui/components/text_prompt/textPrompt.css +33 -0
  120. package/front_end/ui/components/text_prompt/text_prompt.ts +9 -0
  121. package/front_end/ui/legacy/ARIAUtils.ts +14 -11
  122. package/front_end/ui/legacy/TabbedPane.ts +32 -3
  123. package/front_end/ui/legacy/UIUtils.ts +3 -1
  124. package/front_end/ui/legacy/View.ts +6 -0
  125. package/front_end/ui/legacy/ViewManager.ts +5 -1
  126. package/front_end/ui/legacy/ViewRegistration.ts +5 -0
  127. package/front_end/ui/legacy/XLink.ts +1 -1
  128. package/front_end/ui/legacy/closeButton.css +6 -0
  129. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +8 -3
  130. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +38 -38
  131. package/front_end/ui/legacy/components/quick_open/HelpQuickOpen.ts +10 -4
  132. package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +23 -6
  133. package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +14 -16
  134. package/front_end/ui/legacy/filter.css +1 -0
  135. package/front_end/ui/legacy/tabbedPane.css +24 -0
  136. package/front_end/ui/legacy/toolbar.css +5 -0
  137. package/inspector_overlay/main.ts +2 -1
  138. package/inspector_overlay/tool_screenshot.ts +8 -1
  139. package/package.json +1 -1
  140. package/scripts/build/rollup.config.js +9 -0
  141. package/scripts/migration/class-fields/migrate.js +56 -0
  142. package/scripts/migration/class-fields/package.json +5 -0
  143. package/front_end/panels/console/components/SidebarDeprecation.ts +0 -58
  144. package/front_end/panels/console/components/sidebarDeprecation.css +0 -17
@@ -8,7 +8,6 @@ import * as SDK from '../../core/sdk/sdk.js';
8
8
  import * as Protocol from '../../generated/protocol.js';
9
9
  import type * as TextUtils from '../../models/text_utils/text_utils.js';
10
10
  import * as UI from '../../ui/legacy/legacy.js';
11
- import * as ConsoleComponents from './components/components.js';
12
11
 
13
12
  import type {LevelsMask} from './ConsoleFilter.js';
14
13
  import {ConsoleFilter, FilterType} from './ConsoleFilter.js';
@@ -63,8 +62,6 @@ export class ConsoleSidebar extends Common.ObjectWrapper.eventMixin<EventTypes,
63
62
  this.tree = new UI.TreeOutline.TreeOutlineInShadow();
64
63
  this.tree.addEventListener(UI.TreeOutline.Events.ElementSelected, this.selectionChanged.bind(this));
65
64
 
66
- const deprecationWarning = new ConsoleComponents.SidebarDeprecation.SidebarDeprecation();
67
- this.contentElement.appendChild(deprecationWarning);
68
65
  this.contentElement.appendChild(this.tree.element);
69
66
  this.selectedTreeElement = null;
70
67
  this.treeElements = [];
@@ -39,13 +39,16 @@ import * as Platform from '../../core/platform/platform.js';
39
39
  import * as SDK from '../../core/sdk/sdk.js';
40
40
  import * as TextUtils from '../../models/text_utils/text_utils.js';
41
41
  import * as Adorners from '../../ui/components/adorners/adorners.js';
42
- import * as TextEditor from '../../ui/legacy/components/text_editor/text_editor.js';
42
+ import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
43
+ import * as TextEditorLegacy from '../../ui/legacy/components/text_editor/text_editor.js';
43
44
  import * as Components from '../../ui/legacy/components/utils/utils.js';
44
45
  import * as UI from '../../ui/legacy/legacy.js';
45
46
  import * as Emulation from '../emulation/emulation.js';
47
+
46
48
  import * as ElementsComponents from './components/components.js';
47
49
  import {canGetJSPath, cssPath, jsPath, xPath} from './DOMPath.js';
48
50
  import {ElementsPanel} from './ElementsPanel.js';
51
+
49
52
  import type {ElementsTreeOutline, UpdateRecord} from './ElementsTreeOutline.js';
50
53
  import {MappedCharToEntity} from './ElementsTreeOutline.js';
51
54
  import {ImagePreviewPopover} from './ImagePreviewPopover.js';
@@ -986,9 +989,9 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
986
989
  }
987
990
  }
988
991
 
989
- private startEditingAsHTML(
992
+ private async startEditingAsHTML(
990
993
  commitCallback: (arg0: string, arg1: string) => void, disposeCallback: () => void,
991
- maybeInitialValue: string|null): void {
994
+ maybeInitialValue: string|null): Promise<void> {
992
995
  if (maybeInitialValue === null) {
993
996
  return;
994
997
  }
@@ -1013,56 +1016,62 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1013
1016
  // Append editor.
1014
1017
  this.listItemElement.appendChild(this.htmlEditElement);
1015
1018
 
1016
- const factory = TextEditor.CodeMirrorTextEditor.CodeMirrorTextEditorFactory.instance();
1017
- const editor = factory.createEditor({
1018
- lineNumbers: false,
1019
- lineWrapping: Common.Settings.Settings.instance().moduleSetting('domWordWrap').get(),
1020
- mimeType: 'text/html',
1021
- autoHeight: false,
1022
- padBottom: false,
1023
- bracketMatchingSetting: undefined,
1024
- devtoolsAccessibleName: undefined,
1025
- maxHighlightLength: undefined,
1026
- placeholder: undefined,
1027
- lineWiseCopyCut: undefined,
1028
- inputStyle: undefined,
1029
- });
1019
+ const TextEditor = await import('../../ui/components/text_editor/text_editor.js');
1020
+ const CodeMirror = await import('../../third_party/codemirror.next/codemirror.next.js');
1021
+ const {html} = await CodeMirror.html();
1022
+ const editor = new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({
1023
+ doc: initialValue,
1024
+ extensions: [
1025
+ CodeMirror.keymap.of([
1026
+ {
1027
+ key: 'Mod-Enter',
1028
+ run: (): boolean => {
1029
+ this.editing?.commit();
1030
+ return true;
1031
+ },
1032
+ },
1033
+ {
1034
+ key: 'Escape',
1035
+ run: (): boolean => {
1036
+ this.editing?.cancel();
1037
+ return true;
1038
+ },
1039
+ },
1040
+ ]),
1041
+ TextEditor.Config.baseConfiguration(initialValue),
1042
+ html(),
1043
+ TextEditor.Config.domWordWrap,
1044
+ CodeMirror.EditorView.theme({
1045
+ '.cm-editor': {maxHeight: '300px'},
1046
+ '.cm-scroller': {overflowY: 'auto'},
1047
+ }),
1048
+ CodeMirror.EditorView.domEventHandlers({
1049
+ focusout: event => {
1050
+ // The relatedTarget is null when no element gains focus, e.g. switching windows.
1051
+ const relatedTarget = (event.relatedTarget as Node | null);
1052
+ if (relatedTarget && !relatedTarget.isSelfOrDescendant(editor)) {
1053
+ this.editing && this.editing.commit();
1054
+ }
1055
+ },
1056
+ }),
1057
+ ],
1058
+ }));
1030
1059
  this.editing = {commit: commit.bind(this), cancel: dispose.bind(this), editor, resize: resize.bind(this)};
1031
1060
  resize.call(this);
1032
- editor.widget().show((this.htmlEditElement as HTMLElement));
1033
- editor.setText(initialValue);
1034
- editor.widget().focus();
1035
- editor.widget().element.addEventListener('focusout', event => {
1036
- // The relatedTarget is null when no element gains focus, e.g. switching windows.
1037
- const relatedTarget = (event.relatedTarget as Node | null);
1038
- if (relatedTarget && !relatedTarget.isSelfOrDescendant(editor.widget().element)) {
1039
- this.editing && this.editing.commit();
1040
- }
1041
- }, false);
1042
- editor.widget().element.addEventListener('keydown', keydown.bind(this), true);
1061
+ this.htmlEditElement.appendChild(editor);
1062
+ editor.editor.focus();
1043
1063
 
1044
- this.treeOutline && this.treeOutline.setMultilineEditing((this.editing as {
1045
- commit: () => void,
1046
- cancel: () => void,
1047
- editor: UI.TextEditor.TextEditor,
1048
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
1049
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1050
- resize: () => any,
1051
- }));
1064
+ this.treeOutline && this.treeOutline.setMultilineEditing(this.editing);
1052
1065
 
1053
1066
  function resize(this: ElementsTreeElement): void {
1054
1067
  if (this.treeOutline && this.htmlEditElement) {
1055
1068
  this.htmlEditElement.style.width = this.treeOutline.visibleWidth() - this.computeLeftIndent() - 30 + 'px';
1056
1069
  }
1057
-
1058
- if (this.editing && this.editing.editor) {
1059
- (this.editing.editor as TextEditor.CodeMirrorTextEditor.CodeMirrorTextEditor).onResize();
1060
- }
1061
1070
  }
1062
1071
 
1063
1072
  function commit(this: ElementsTreeElement): void {
1064
1073
  if (this.editing && this.editing.editor) {
1065
- commitCallback(initialValue, this.editing.editor.text());
1074
+ commitCallback(initialValue, this.editing.editor.state.doc.toString());
1066
1075
  }
1067
1076
  dispose.call(this);
1068
1077
  }
@@ -1071,8 +1080,6 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1071
1080
  if (!this.editing || !this.editing.editor) {
1072
1081
  return;
1073
1082
  }
1074
- this.editing.editor.widget().element.removeEventListener('blur', this.editing.commit, true);
1075
- this.editing.editor.widget().detach();
1076
1083
  this.editing = null;
1077
1084
 
1078
1085
  // Remove editor.
@@ -1098,21 +1105,6 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1098
1105
 
1099
1106
  disposeCallback();
1100
1107
  }
1101
-
1102
- function keydown(this: ElementsTreeElement, event: Event): void {
1103
- const keyboardEvent = (event as KeyboardEvent);
1104
- const isMetaOrCtrl = UI.KeyboardShortcut.KeyboardShortcut.eventHasCtrlEquivalentKey(keyboardEvent) &&
1105
- !keyboardEvent.altKey && !keyboardEvent.shiftKey;
1106
- if (keyboardEvent.key === 'Enter' && (isMetaOrCtrl || keyboardEvent.isMetaOrCtrlForTest)) {
1107
- keyboardEvent.consume(true);
1108
- this.editing && this.editing.commit();
1109
- } else if (
1110
- keyboardEvent.keyCode === UI.KeyboardShortcut.Keys.Esc.code ||
1111
- keyboardEvent.key === Platform.KeyboardUtilities.ESCAPE_KEY) {
1112
- keyboardEvent.consume(true);
1113
- this.editing && this.editing.cancel();
1114
- }
1115
- }
1116
1108
  }
1117
1109
 
1118
1110
  private attributeEditingCommitted(
@@ -1732,14 +1724,14 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1732
1724
  newNode.textContent = text.startsWith('\n') ? text.substring(1) : text;
1733
1725
 
1734
1726
  const javascriptSyntaxHighlighter =
1735
- new TextEditor.SyntaxHighlighter.SyntaxHighlighter('text/javascript', true);
1727
+ new TextEditorLegacy.SyntaxHighlighter.SyntaxHighlighter('text/javascript', true);
1736
1728
  javascriptSyntaxHighlighter.syntaxHighlightNode(newNode).then(updateSearchHighlight);
1737
1729
  } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === 'style') {
1738
1730
  const newNode = titleDOM.createChild('span', 'webkit-html-text-node webkit-html-css-node');
1739
1731
  const text = node.nodeValue();
1740
1732
  newNode.textContent = text.startsWith('\n') ? text.substring(1) : text;
1741
1733
 
1742
- const cssSyntaxHighlighter = new TextEditor.SyntaxHighlighter.SyntaxHighlighter('text/css', true);
1734
+ const cssSyntaxHighlighter = new TextEditorLegacy.SyntaxHighlighter.SyntaxHighlighter('text/css', true);
1743
1735
  cssSyntaxHighlighter.syntaxHighlightNode(newNode).then(updateSearchHighlight);
1744
1736
  } else {
1745
1737
  UI.UIUtils.createTextChild(titleDOM, '"');
@@ -2224,7 +2216,7 @@ export function adornerComparator(adornerA: Adorners.Adorner.Adorner, adornerB:
2224
2216
  export interface EditorHandles {
2225
2217
  commit: () => void;
2226
2218
  cancel: () => void;
2227
- editor?: UI.TextEditor.TextEditor|TextEditor.CodeMirrorTextEditor.CodeMirrorTextEditor;
2219
+ editor?: TextEditor.TextEditor.TextEditor;
2228
2220
  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
2229
2221
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2230
2222
  resize: () => any;
@@ -1631,7 +1631,6 @@ export interface MultilineEditorController {
1631
1631
  cancel: () => void;
1632
1632
  commit: () => void;
1633
1633
  resize: () => void;
1634
- editor: UI.TextEditor.TextEditor;
1635
1634
  }
1636
1635
 
1637
1636
  export interface ClipboardData {
@@ -17,6 +17,10 @@ import inspectorCommonStyles from '../../../ui/legacy/inspectorCommon.css.js';
17
17
 
18
18
  import * as i18n from '../../../core/i18n/i18n.js';
19
19
  const UIStrings = {
20
+ /**
21
+ *@description Title of the input to select the overlay color for an element using the color picker
22
+ */
23
+ chooseElementOverlayColor: 'Choose the overlay color for this element',
20
24
  /**
21
25
  *@description Title of the show element button in the Layout pane of the Elements panel
22
26
  */
@@ -257,7 +261,7 @@ export class LayoutPane extends HTMLElement {
257
261
  } as NodeTextData}></${NodeText.litTagName}>
258
262
  </span>
259
263
  </label>
260
- <label @keyup=${onColorLabelKeyUp} @keydown=${onColorLabelKeyDown} tabindex="0" class="color-picker-label" style="background: ${element.color};">
264
+ <label @keyup=${onColorLabelKeyUp} @keydown=${onColorLabelKeyDown} tabindex="0" title=${i18nString(UIStrings.chooseElementOverlayColor)} class="color-picker-label" style="background: ${element.color};">
261
265
  <input @change=${onColorChange} @input=${onColorChange} class="color-picker" type="color" value=${element.color} />
262
266
  </label>
263
267
  <button tabindex="0" @click=${onElementClick} title=${i18nString(UIStrings.showElementInTheElementsPanel)} class="show-element"></button>
@@ -0,0 +1,68 @@
1
+ // Copyright 2021 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as i18n from '../../core/i18n/i18n.js';
6
+ import type * as Platform from '../../core/platform/platform.js';
7
+ import type * as IssuesManager from '../../models/issues_manager/issues_manager.js';
8
+
9
+ import {AffectedResourcesView} from './AffectedResourcesView.js';
10
+
11
+ const UIStrings = {
12
+ /**
13
+ *@description Label for number of affected resources indication in issue view
14
+ */
15
+ nResources: '{n, plural, =1 {# resource} other {# resources}}',
16
+ /**
17
+ *@description Title for the 'Frame' column.
18
+ */
19
+ frameId: 'Frame',
20
+ };
21
+
22
+ const str_ = i18n.i18n.registerUIStrings('panels/issues/GenericIssueDetailsView.ts', UIStrings);
23
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
24
+
25
+ export class GenericIssueDetailsView extends AffectedResourcesView {
26
+ protected getResourceNameWithCount(count: number): Platform.UIString.LocalizedString {
27
+ return i18nString(UIStrings.nResources, {n: count});
28
+ }
29
+
30
+ private appendDetails(genericIssues: ReadonlySet<IssuesManager.GenericIssue.GenericIssue>): void {
31
+ const header = document.createElement('tr');
32
+
33
+ const sampleIssueDetails = genericIssues.values().next().value.details();
34
+ if (sampleIssueDetails.frameId) {
35
+ this.appendColumnTitle(header, i18nString(UIStrings.frameId));
36
+ }
37
+
38
+ this.affectedResources.appendChild(header);
39
+ let count = 0;
40
+ for (const genericIssue of genericIssues) {
41
+ count++;
42
+ this.appendDetail(genericIssue);
43
+ }
44
+ this.updateAffectedResourceCount(count);
45
+ }
46
+
47
+ private appendDetail(genericIssue: IssuesManager.GenericIssue.GenericIssue): void {
48
+ const element = document.createElement('tr');
49
+ element.classList.add('affected-resource-directive');
50
+
51
+ const details = genericIssue.details();
52
+ if (details.frameId) {
53
+ element.appendChild(this.createFrameCell(details.frameId, genericIssue.getCategory()));
54
+ }
55
+
56
+ this.affectedResources.appendChild(element);
57
+ }
58
+
59
+ update(): void {
60
+ this.clear();
61
+ const issues = this.issue.getGenericIssues();
62
+ if (issues.size > 0) {
63
+ this.appendDetails(issues);
64
+ } else {
65
+ this.updateAffectedResourceCount(0);
66
+ }
67
+ }
68
+ }
@@ -45,6 +45,7 @@ export class AggregatedIssue extends IssuesManager.Issue.Issue {
45
45
  private attributionReportingIssues = new Set<IssuesManager.AttributionReportingIssue.AttributionReportingIssue>();
46
46
  private wasmCrossOriginModuleSharingIssues =
47
47
  new Set<IssuesManager.WasmCrossOriginModuleSharingIssue.WasmCrossOriginModuleSharingIssue>();
48
+ private genericIssues = new Set<IssuesManager.GenericIssue.GenericIssue>();
48
49
  private representative?: IssuesManager.Issue.Issue;
49
50
  private aggregatedIssuesCount = 0;
50
51
  private key: AggregationKey;
@@ -130,6 +131,10 @@ export class AggregatedIssue extends IssuesManager.Issue.Issue {
130
131
  return this.wasmCrossOriginModuleSharingIssues;
131
132
  }
132
133
 
134
+ getGenericIssues(): ReadonlySet<IssuesManager.GenericIssue.GenericIssue> {
135
+ return this.genericIssues;
136
+ }
137
+
133
138
  getDescription(): IssuesManager.MarkdownIssueDescription.MarkdownIssueDescription|null {
134
139
  if (this.representative) {
135
140
  return this.representative.getDescription();
@@ -221,6 +226,9 @@ export class AggregatedIssue extends IssuesManager.Issue.Issue {
221
226
  if (issue instanceof IssuesManager.WasmCrossOriginModuleSharingIssue.WasmCrossOriginModuleSharingIssue) {
222
227
  this.wasmCrossOriginModuleSharingIssues.add(issue);
223
228
  }
229
+ if (issue instanceof IssuesManager.GenericIssue.GenericIssue) {
230
+ this.genericIssues.add(issue);
231
+ }
224
232
  }
225
233
 
226
234
  getKind(): IssuesManager.Issue.IssueKind {
@@ -301,6 +309,14 @@ export class IssueAggregator extends Common.ObjectWrapper.ObjectWrapper<EventTyp
301
309
  return result;
302
310
  }
303
311
 
312
+ aggregatedIssueKinds(): Set<IssuesManager.Issue.IssueKind> {
313
+ const result = new Set<IssuesManager.Issue.IssueKind>();
314
+ for (const issue of this.aggregatedIssuesByKey.values()) {
315
+ result.add(issue.getKind());
316
+ }
317
+ return result;
318
+ }
319
+
304
320
  numberOfAggregatedIssues(): number {
305
321
  return this.aggregatedIssuesByKey.size;
306
322
  }
@@ -0,0 +1,95 @@
1
+ // Copyright 2021 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Common from '../../core/common/common.js';
6
+ import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
7
+ import * as Adorners from '../../ui/components/adorners/adorners.js';
8
+ import * as IconButton from '../../ui/components/icon_button/icon_button.js';
9
+ import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
10
+ import * as UI from '../../ui/legacy/legacy.js';
11
+
12
+ export function getGroupIssuesByKindSetting(): Common.Settings.Setting<boolean> {
13
+ return Common.Settings.Settings.instance().createSetting('groupIssuesByKind', false);
14
+ }
15
+
16
+ export function issueKindViewSortPriority(a: IssueKindView, b: IssueKindView): number {
17
+ if (a.getKind() === b.getKind()) {
18
+ return 0;
19
+ }
20
+ if (a.getKind() === IssuesManager.Issue.IssueKind.PageError) {
21
+ return -1;
22
+ }
23
+ if (a.getKind() === IssuesManager.Issue.IssueKind.BreakingChange &&
24
+ b.getKind() === IssuesManager.Issue.IssueKind.Improvement) {
25
+ return -1;
26
+ }
27
+ return 1;
28
+ }
29
+
30
+ export function getClassNameFromKind(kind: IssuesManager.Issue.IssueKind): string {
31
+ switch (kind) {
32
+ case IssuesManager.Issue.IssueKind.BreakingChange:
33
+ return 'breaking-changes';
34
+ case IssuesManager.Issue.IssueKind.Improvement:
35
+ return 'improvements';
36
+ case IssuesManager.Issue.IssueKind.PageError:
37
+ return 'page-errors';
38
+ }
39
+ }
40
+
41
+ export class IssueKindView extends UI.TreeOutline.TreeElement {
42
+ private kind: IssuesManager.Issue.IssueKind;
43
+ private issueCount: HTMLElement;
44
+
45
+ constructor(kind: IssuesManager.Issue.IssueKind) {
46
+ super(undefined, true);
47
+ this.kind = kind;
48
+ this.issueCount = document.createElement('span');
49
+
50
+ this.toggleOnClick = true;
51
+ this.listItemElement.classList.add('issue-kind');
52
+ this.listItemElement.classList.add(getClassNameFromKind(kind));
53
+ this.childrenListElement.classList.add('issue-kind-body');
54
+ }
55
+
56
+ getKind(): IssuesManager.Issue.IssueKind {
57
+ return this.kind;
58
+ }
59
+
60
+ private appendHeader(): void {
61
+ const header = document.createElement('div');
62
+ header.classList.add('header');
63
+
64
+ const issueKindIcon = new IconButton.Icon.Icon();
65
+ issueKindIcon.data = IssueCounter.IssueCounter.getIssueKindIconData(this.kind);
66
+ issueKindIcon.classList.add('leading-issue-icon');
67
+
68
+ const countAdorner = new Adorners.Adorner.Adorner();
69
+ countAdorner.data = {
70
+ name: 'countWrapper',
71
+ content: this.issueCount,
72
+ };
73
+ countAdorner.classList.add('aggregated-issues-count');
74
+ this.issueCount.textContent = '0';
75
+
76
+ const title = document.createElement('div');
77
+ title.classList.add('title');
78
+ title.textContent = IssuesManager.Issue.getIssueKindName(this.kind);
79
+
80
+ header.appendChild(issueKindIcon);
81
+ header.appendChild(countAdorner);
82
+ header.appendChild(title);
83
+
84
+ this.listItemElement.appendChild(header);
85
+ }
86
+
87
+ onattach(): void {
88
+ this.appendHeader();
89
+ this.expand();
90
+ }
91
+
92
+ update(count: number): void {
93
+ this.issueCount.textContent = `${count}`;
94
+ }
95
+ }
@@ -29,6 +29,7 @@ import {AffectedSharedArrayBufferIssueDetailsView} from './AffectedSharedArrayBu
29
29
  import {AffectedSourcesView} from './AffectedSourcesView.js';
30
30
  import {AffectedTrustedWebActivityIssueDetailsView} from './AffectedTrustedWebActivityIssueDetailsView.js';
31
31
  import {CorsIssueDetailsView} from './CorsIssueDetailsView.js';
32
+ import {GenericIssueDetailsView} from './GenericIssueDetailsView.js';
32
33
  import {WasmCrossOriginModuleSharingAffectedResourcesView} from './WasmCrossOriginModuleSharingAffectedResourcesView.js';
33
34
  import {AttributionReportingIssueDetailsView} from './AttributionReportingIssueDetailsView.js';
34
35
 
@@ -241,6 +242,7 @@ export class IssueView extends UI.TreeOutline.TreeElement {
241
242
  new AffectedElementsWithLowContrastView(this, this.issue),
242
243
  new AffectedTrustedWebActivityIssueDetailsView(this, this.issue),
243
244
  new CorsIssueDetailsView(this, this.issue),
245
+ new GenericIssueDetailsView(this, this.issue),
244
246
  new AffectedDocumentsInQuirksModeView(this, this.issue),
245
247
  new AttributionReportingIssueDetailsView(this, this.issue),
246
248
  new WasmCrossOriginModuleSharingAffectedResourcesView(this, this.issue),
@@ -442,6 +444,10 @@ export class IssueView extends UI.TreeOutline.TreeElement {
442
444
  this.throttle.schedule(async () => this.doUpdate());
443
445
  }
444
446
 
447
+ getIssueKind(): IssuesManager.Issue.IssueKind {
448
+ return this.issue.getKind();
449
+ }
450
+
445
451
  isForHiddenIssue(): boolean {
446
452
  return this.issue.isHidden();
447
453
  }
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
+ import * as Root from '../../core/root/root.js';
7
8
  import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
8
9
  import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
9
10
  import * as UI from '../../ui/legacy/legacy.js';
@@ -15,6 +16,7 @@ import issuesTreeStyles from './issuesTree.css.js';
15
16
  import type {AggregatedIssue, AggregationKey} from './IssueAggregator.js';
16
17
  import {Events as IssueAggregatorEvents, IssueAggregator} from './IssueAggregator.js';
17
18
  import {IssueView} from './IssueView.js';
19
+ import {IssueKindView, getGroupIssuesByKindSetting, issueKindViewSortPriority} from './IssueKindView.js';
18
20
 
19
21
  const UIStrings = {
20
22
  /**
@@ -64,6 +66,14 @@ const UIStrings = {
64
66
  * @description Label for a checkbox which toggles grouping by category in the issues tab
65
67
  */
66
68
  groupByCategory: 'Group by category',
69
+ /**
70
+ * @description Title for a checkbox which toggles grouping by kind in the issues tab
71
+ */
72
+ groupDisplayedIssuesUnderKind: 'Group displayed issues as Page errors, Breaking changes and Improvements',
73
+ /**
74
+ * @description Label for a checkbox which toggles grouping by kind in the issues tab
75
+ */
76
+ groupByKind: 'Group by kind',
67
77
  /**
68
78
  * @description Title for a checkbox. Whether the issues tab should include third-party issues or not.
69
79
  */
@@ -91,6 +101,10 @@ const UIStrings = {
91
101
  * browser behaviors.
92
102
  */
93
103
  quirksMode: 'Quirks Mode',
104
+ /**
105
+ * @description Category title for the different 'Generic' issues.
106
+ */
107
+ generic: 'Generic',
94
108
  };
95
109
  const str_ = i18n.i18n.registerUIStrings('panels/issues/IssuesPane.ts', UIStrings);
96
110
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -131,6 +145,8 @@ class IssueCategoryView extends UI.TreeOutline.TreeElement {
131
145
  return i18nString(UIStrings.attributionReporting);
132
146
  case IssuesManager.Issue.IssueCategory.QuirksMode:
133
147
  return i18nString(UIStrings.quirksMode);
148
+ case IssuesManager.Issue.IssueCategory.Generic:
149
+ return i18nString(UIStrings.generic);
134
150
  case IssuesManager.Issue.IssueCategory.Other:
135
151
  return i18nString(UIStrings.other);
136
152
  }
@@ -162,6 +178,7 @@ let issuesPaneInstance: IssuesPane;
162
178
  export class IssuesPane extends UI.Widget.VBox {
163
179
  private categoryViews: Map<IssuesManager.Issue.IssueCategory, IssueCategoryView>;
164
180
  private issueViews: Map<AggregationKey, IssueView>;
181
+ private kindViews: Map<IssuesManager.Issue.IssueKind, IssueKindView>;
165
182
  private showThirdPartyCheckbox: UI.Toolbar.ToolbarSettingCheckbox|null;
166
183
  private issuesTree: UI.TreeOutline.TreeOutlineInShadow;
167
184
  private hiddenIssuesRow: HiddenIssuesRow;
@@ -176,6 +193,7 @@ export class IssuesPane extends UI.Widget.VBox {
176
193
  this.contentElement.classList.add('issues-pane');
177
194
 
178
195
  this.categoryViews = new Map();
196
+ this.kindViews = new Map();
179
197
  this.issueViews = new Map();
180
198
  this.showThirdPartyCheckbox = null;
181
199
 
@@ -231,6 +249,15 @@ export class IssuesPane extends UI.Widget.VBox {
231
249
  this.fullUpdate(true);
232
250
  });
233
251
 
252
+ const groupByKindSetting = getGroupIssuesByKindSetting();
253
+ const groupByKindSettingCheckbox = new UI.Toolbar.ToolbarSettingCheckbox(
254
+ groupByKindSetting, i18nString(UIStrings.groupDisplayedIssuesUnderKind), i18nString(UIStrings.groupByKind));
255
+ rightToolbar.appendToolbarItem(groupByKindSettingCheckbox);
256
+ groupByKindSetting.addChangeListener(() => {
257
+ this.fullUpdate(true);
258
+ });
259
+ groupByKindSettingCheckbox.setVisible(Root.Runtime.experiments.isEnabled('groupAndHideIssuesByKind'));
260
+
234
261
  const thirdPartySetting = IssuesManager.Issue.getShowThirdPartyIssuesSetting();
235
262
  this.showThirdPartyCheckbox = new UI.Toolbar.ToolbarSettingCheckbox(
236
263
  thirdPartySetting, i18nString(UIStrings.includeCookieIssuesCausedBy),
@@ -309,28 +336,45 @@ export class IssuesPane extends UI.Widget.VBox {
309
336
  }
310
337
 
311
338
  private getIssueViewParent(issue: AggregatedIssue): UI.TreeOutline.TreeOutline|UI.TreeOutline.TreeElement {
312
- if (!getGroupIssuesByCategorySetting().get()) {
313
- if (issue.isHidden()) {
314
- return this.hiddenIssuesRow;
315
- }
316
- return this.issuesTree;
339
+ const groupByKind = Root.Runtime.experiments.isEnabled('groupAndHideIssuesByKind');
340
+ if (issue.isHidden()) {
341
+ return this.hiddenIssuesRow;
317
342
  }
343
+ if (groupByKind && getGroupIssuesByKindSetting().get()) {
344
+ const kind = issue.getKind();
345
+ const view = this.kindViews.get(kind);
346
+ if (view) {
347
+ return view;
348
+ }
318
349
 
319
- const category = issue.getCategory();
320
- const view = this.categoryViews.get(category);
321
- if (view) {
322
- return view;
350
+ const newView = new IssueKindView(kind);
351
+ this.issuesTree.appendChild(newView, (a, b) => {
352
+ if (a instanceof IssueKindView && b instanceof IssueKindView) {
353
+ return issueKindViewSortPriority(a, b);
354
+ }
355
+ return 0;
356
+ });
357
+ this.kindViews.set(kind, newView);
358
+ return newView;
323
359
  }
324
-
325
- const newView = new IssueCategoryView(category);
326
- this.issuesTree.appendChild(newView, (a, b) => {
327
- if (a instanceof IssueCategoryView && b instanceof IssueCategoryView) {
328
- return a.getCategoryName().localeCompare(b.getCategoryName());
360
+ if (getGroupIssuesByCategorySetting().get()) {
361
+ const category = issue.getCategory();
362
+ const view = this.categoryViews.get(category);
363
+ if (view) {
364
+ return view;
329
365
  }
330
- return 0;
331
- });
332
- this.categoryViews.set(category, newView);
333
- return newView;
366
+
367
+ const newView = new IssueCategoryView(category);
368
+ this.issuesTree.appendChild(newView, (a, b) => {
369
+ if (a instanceof IssueCategoryView && b instanceof IssueCategoryView) {
370
+ return a.getCategoryName().localeCompare(b.getCategoryName());
371
+ }
372
+ return 0;
373
+ });
374
+ this.categoryViews.set(category, newView);
375
+ return newView;
376
+ }
377
+ return this.issuesTree;
334
378
  }
335
379
 
336
380
  private clearViews<T>(views: Map<T, UI.TreeOutline.TreeElement>, preservedSet?: Set<T>): void {
@@ -349,6 +393,7 @@ export class IssuesPane extends UI.Widget.VBox {
349
393
 
350
394
  private fullUpdate(force: boolean): void {
351
395
  this.clearViews(this.categoryViews, force ? undefined : this.aggregator.aggregatedIssueCategories());
396
+ this.clearViews(this.kindViews, force ? undefined : this.aggregator.aggregatedIssueKinds());
352
397
  this.clearViews(this.issueViews, force ? undefined : this.aggregator.aggregatedIssueCodes());
353
398
  if (this.aggregator) {
354
399
  for (const issue of this.aggregator.aggregatedIssues()) {
@@ -358,9 +403,21 @@ export class IssuesPane extends UI.Widget.VBox {
358
403
  this.updateCounts();
359
404
  }
360
405
 
406
+ private updateIssueKindViewsCount(): void {
407
+ for (const view of this.kindViews.values()) {
408
+ const count =
409
+ this.issuesManager.numberOfIssues(view.getKind()) - this.issuesManager.numberOfHiddenIssues(view.getKind());
410
+ view.update(count);
411
+ }
412
+ }
413
+
361
414
  private updateCounts(): void {
415
+ const groupByKind = Root.Runtime.experiments.isEnabled('groupAndHideIssuesByKind');
362
416
  this.showIssuesTreeOrNoIssuesDetectedMessage(
363
417
  this.issuesManager.numberOfIssues(), this.issuesManager.numberOfHiddenIssues());
418
+ if (groupByKind && getGroupIssuesByKindSetting().get()) {
419
+ this.updateIssueKindViewsCount();
420
+ }
364
421
  }
365
422
 
366
423
  private showIssuesTreeOrNoIssuesDetectedMessage(issuesCount: number, hiddenIssueCount: number): void {
@@ -391,11 +448,17 @@ export class IssuesPane extends UI.Widget.VBox {
391
448
  await this.issueViewUpdatePromise;
392
449
  const key = this.aggregator.keyForIssue(issue);
393
450
  const issueView = this.issueViews.get(key);
451
+ const groupByKind = Root.Runtime.experiments.isEnabled('groupAndHideIssuesByKind');
394
452
  if (issueView) {
395
453
  if (issueView.isForHiddenIssue()) {
396
454
  this.hiddenIssuesRow.expand();
397
455
  this.hiddenIssuesRow.reveal();
398
456
  }
457
+ if (groupByKind && getGroupIssuesByKindSetting().get() && !issueView.isForHiddenIssue()) {
458
+ const kindView = this.kindViews.get(issueView.getIssueKind());
459
+ kindView?.expand();
460
+ kindView?.reveal();
461
+ }
399
462
  issueView.expand();
400
463
  issueView.reveal();
401
464
  issueView.select(false, true);