chrome-devtools-frontend 1.0.948359 → 1.0.950001

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 (58) hide show
  1. package/config/gni/all_devtools_files.gni +5 -0
  2. package/config/gni/devtools_grd_files.gni +5 -6
  3. package/front_end/core/host/UserMetrics.ts +0 -1
  4. package/front_end/core/i18n/locales/en-US.json +45 -30
  5. package/front_end/core/i18n/locales/en-XL.json +49 -34
  6. package/front_end/core/root/Runtime.ts +1 -0
  7. package/front_end/core/sdk/AccessibilityModel.ts +7 -7
  8. package/front_end/core/sdk/RemoteObject.ts +15 -1
  9. package/front_end/entrypoints/devtools_app/devtools_app.ts +0 -1
  10. package/front_end/entrypoints/visibility.gni +3 -1
  11. package/front_end/entrypoints/worker_app/worker_app.ts +0 -1
  12. package/front_end/generated/InspectorBackendCommands.js +8 -1
  13. package/front_end/generated/protocol-mapping.d.ts +4 -0
  14. package/front_end/generated/protocol-proxy-api.d.ts +6 -0
  15. package/front_end/generated/protocol.d.ts +9 -0
  16. package/front_end/models/issues_manager/AttributionReportingIssue.ts +42 -2
  17. package/front_end/models/issues_manager/CorsIssue.ts +1 -4
  18. package/front_end/models/issues_manager/descriptions/arInvalidAttributionSourceExpiry.md +4 -0
  19. package/front_end/models/issues_manager/descriptions/arInvalidAttributionSourcePriority.md +4 -0
  20. package/front_end/models/issues_manager/descriptions/arInvalidEventSourceTriggerData.md +9 -0
  21. package/front_end/models/issues_manager/descriptions/arInvalidTriggerDedupKey.md +5 -0
  22. package/front_end/models/issues_manager/descriptions/arInvalidTriggerPriority.md +5 -0
  23. package/front_end/models/issues_manager/descriptions/corsPreflightResponseInvalid.md +2 -2
  24. package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +45 -3
  25. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +2 -4
  26. package/front_end/panels/accessibility/axBreadcrumbs.css +4 -0
  27. package/front_end/panels/application/components/FrameDetailsView.ts +29 -15
  28. package/front_end/panels/console/ConsolePrompt.ts +0 -4
  29. package/front_end/panels/elements/AccessibilityTreeUtils.ts +1 -7
  30. package/front_end/panels/elements/AccessibilityTreeView.ts +4 -6
  31. package/front_end/panels/elements/PropertiesWidget.ts +109 -4
  32. package/front_end/panels/elements/propertiesWidget.css +34 -0
  33. package/front_end/panels/emulation/DeviceModeToolbar.ts +5 -1
  34. package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +44 -0
  35. package/front_end/panels/issues/CorsIssueDetailsView.ts +6 -2
  36. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +1 -0
  37. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  38. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +8 -6
  39. package/front_end/third_party/codemirror.next/package.json +3 -3
  40. package/package.json +1 -1
  41. package/scripts/eslint_rules/lib/ban_a_tags_in_lit_html.js +2 -11
  42. package/scripts/eslint_rules/lib/ban_literal_devtools_component_tag_names.js +2 -11
  43. package/scripts/eslint_rules/lib/ban_self_closing_custom_element_tagnames.js +2 -11
  44. package/scripts/eslint_rules/lib/ban_style_tags_in_lit_html.js +2 -11
  45. package/scripts/eslint_rules/lib/lit_html_data_as_type.js +2 -11
  46. package/scripts/eslint_rules/lib/lit_html_no_attribute_quotes.js +1 -13
  47. package/scripts/eslint_rules/lib/lit_no_style_interpolation.js +2 -11
  48. package/scripts/eslint_rules/lib/static_tag_must_be_static_property.js +2 -11
  49. package/scripts/eslint_rules/lib/utils.js +29 -0
  50. package/scripts/eslint_rules/tests/.eslintrc.js +4 -0
  51. package/scripts/eslint_rules/tests/utils_test.js +40 -0
  52. package/front_end/panels/help/HelpImpl.ts +0 -141
  53. package/front_end/panels/help/ReleaseNoteText.ts +0 -1496
  54. package/front_end/panels/help/ReleaseNoteView.ts +0 -107
  55. package/front_end/panels/help/help-meta.ts +0 -145
  56. package/front_end/panels/help/help.ts +0 -13
  57. package/front_end/panels/help/releaseNote.css +0 -115
  58. package/scripts/build/rjsmin.py +0 -484
@@ -0,0 +1,5 @@
1
+ # Ensure the "priority" query parameter for an attribution redirect is a valid number
2
+
3
+ The priority associated with an attribution was defaulted to `0`.
4
+ This happens if the `priority` query parameter provided in the `.well-known` redirect is not a
5
+ valid 64-bit signed integer.
@@ -1,5 +1,5 @@
1
1
  # Ensure preflight responses are valid
2
2
 
3
- A cross-origin resource sharing (CORS) request was blocked because the response to the associated [preflight request](issueCorsPreflightRequest) had an unsuccessful HTTP status code and/or was a redirect.
3
+ A cross-origin resource sharing (CORS) request was blocked because the response to the associated [preflight request](issueCorsPreflightRequest) failed, had an unsuccessful HTTP status code, and/or was a redirect.
4
4
 
5
- To fix this issue, ensure all CORS preflight `OPTION` requests are answered with a successful HTTP status code (2xx) and do not redirect.
5
+ To fix this issue, ensure all CORS preflight `OPTIONS` requests are answered with a successful HTTP status code (2xx) and do not redirect.
@@ -3,8 +3,11 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
+ import * as Host from '../../core/host/host.js';
6
7
  import * as i18n from '../../core/i18n/i18n.js';
8
+ import * as Root from '../../core/root/root.js';
7
9
  import * as SDK from '../../core/sdk/sdk.js';
10
+ import * as Feedback from '../../ui/components/panel_feedback/panel_feedback.js';
8
11
  import * as UI from '../../ui/legacy/legacy.js';
9
12
 
10
13
  import axBreadcrumbsStyles from './axBreadcrumbs.css.js';
@@ -27,6 +30,18 @@ const UIStrings = {
27
30
  *@description Ignored node element text content in AXBreadcrumbs Pane of the Accessibility panel
28
31
  */
29
32
  ignored: 'Ignored',
33
+ /**
34
+ *@description Name for experimental tree toggle.
35
+ */
36
+ fullTreeExperimentName: 'Enable full-page accessibility tree',
37
+ /**
38
+ *@description Description text for experimental tree toggle.
39
+ */
40
+ fullTreeExperimentDescription: 'The accessibility tree moved to the top right corner of the DOM tree.',
41
+ /**
42
+ *@description Message saying that DevTools must be restarted before the experiment is enabled.
43
+ */
44
+ reloadRequired: 'Reload required before the change takes effect.',
30
45
  };
31
46
  const str_ = i18n.i18n.registerUIStrings('panels/accessibility/AXBreadcrumbsPane.ts', UIStrings);
32
47
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -37,24 +52,48 @@ export class AXBreadcrumbsPane extends AccessibilitySubPane {
37
52
  private collapsingBreadcrumbId: number;
38
53
  private hoveredBreadcrumb: AXBreadcrumb|null;
39
54
  private readonly rootElement: HTMLElement;
55
+ #legacyTreeDisabled = false;
40
56
 
41
57
  constructor(axSidebarView: AccessibilitySidebarView) {
42
58
  super(i18nString(UIStrings.accessibilityTree));
43
59
 
44
60
  this.element.classList.add('ax-subpane');
45
- UI.ARIAUtils.markAsTree(this.element);
46
61
  this.element.tabIndex = -1;
47
62
 
48
63
  this.axSidebarView = axSidebarView;
49
-
50
64
  this.preselectedBreadcrumb = null;
51
65
  this.inspectedNodeBreadcrumb = null;
52
66
 
53
67
  this.collapsingBreadcrumbId = -1;
54
68
 
55
- this.hoveredBreadcrumb = null;
56
69
  this.rootElement = this.element.createChild('div', 'ax-breadcrumbs');
57
70
 
71
+ this.hoveredBreadcrumb = null;
72
+ const previewToggle = new Feedback.PreviewToggle.PreviewToggle();
73
+ const name = i18nString(UIStrings.fullTreeExperimentName);
74
+ const experiment = Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE;
75
+ const onChangeCallback: (checked: boolean) => void = checked => {
76
+ Host.userMetrics.experimentChanged(experiment, checked);
77
+ UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(i18nString(UIStrings.reloadRequired));
78
+ };
79
+ if (Root.Runtime.experiments.isEnabled(experiment)) {
80
+ this.#legacyTreeDisabled = true;
81
+ const feedbackURL = 'https://goo.gle/devtools-a11y-tree-feedback';
82
+ previewToggle.data = {
83
+ name,
84
+ helperText: i18nString(UIStrings.fullTreeExperimentDescription),
85
+ feedbackURL,
86
+ experiment,
87
+ onChangeCallback,
88
+ };
89
+ this.element.appendChild(previewToggle);
90
+ return;
91
+ }
92
+ previewToggle.data = {name, helperText: null, feedbackURL: null, experiment, onChangeCallback};
93
+ this.element.prepend(previewToggle);
94
+
95
+ UI.ARIAUtils.markAsTree(this.rootElement);
96
+
58
97
  this.rootElement.addEventListener('keydown', this.onKeyDown.bind(this), true);
59
98
  this.rootElement.addEventListener('mousemove', this.onMouseMove.bind(this), false);
60
99
  this.rootElement.addEventListener('mouseleave', this.onMouseLeave.bind(this), false);
@@ -72,6 +111,9 @@ export class AXBreadcrumbsPane extends AccessibilitySubPane {
72
111
  }
73
112
 
74
113
  setAXNode(axNode: SDK.AccessibilityModel.AccessibilityNode|null): void {
114
+ if (this.#legacyTreeDisabled) {
115
+ return;
116
+ }
75
117
  const hadFocus = this.element.hasFocus();
76
118
  super.setAXNode(axNode);
77
119
 
@@ -31,10 +31,8 @@ export class AccessibilitySidebarView extends UI.ThrottledWidget.ThrottledWidget
31
31
  this.axNodeInternal = null;
32
32
  this.skipNextPullNode = false;
33
33
  this.sidebarPaneStack = UI.ViewManager.ViewManager.instance().createStackLocation();
34
- if (!Root.Runtime.experiments.isEnabled('fullAccessibilityTree')) {
35
- this.breadcrumbsSubPane = new AXBreadcrumbsPane(this);
36
- this.sidebarPaneStack.showView(this.breadcrumbsSubPane);
37
- }
34
+ this.breadcrumbsSubPane = new AXBreadcrumbsPane(this);
35
+ this.sidebarPaneStack.showView(this.breadcrumbsSubPane);
38
36
  this.ariaSubPane = new ARIAAttributesPane();
39
37
  this.sidebarPaneStack.showView(this.ariaSubPane);
40
38
  this.axNodeSubPane = new AXNodeSubPane();
@@ -99,6 +99,10 @@
99
99
  background-color: var(--color-background-elevation-0);
100
100
  }
101
101
 
102
+ .ax-breadcrumbs .ax-node:not(.inspected):focus {
103
+ background-color: var(--color-background-elevation-1);
104
+ }
105
+
102
106
  .ax-breadcrumbs .ax-node.inspected:focus * {
103
107
  color: inherit;
104
108
  }
@@ -47,6 +47,11 @@ const UIStrings = {
47
47
  */
48
48
  document: 'Document',
49
49
  /**
50
+ *@description A web URL (for a lot of languages this does not need to be translated, please translate only where necessary)
51
+ */
52
+ url: 'URL',
53
+ /**
54
+ /**
50
55
  *@description Title for a link to the Sources panel
51
56
  */
52
57
  clickToRevealInSourcesPanel: 'Click to reveal in Sources panel',
@@ -63,6 +68,12 @@ const UIStrings = {
63
68
  */
64
69
  clickToRevealInNetworkPanelMight: 'Click to reveal in Network panel (might require page reload)',
65
70
  /**
71
+ *@description The origin of a URL (https://web.dev/same-site-same-origin/#origin)
72
+ *(for a lot of languages this does not need to be translated, please translate only where necessary)
73
+ */
74
+ origin: 'Origin',
75
+ /**
76
+ /**
66
77
  *@description Related node label in Timeline UIUtils of the Performance panel
67
78
  */
68
79
  ownerElement: 'Owner Element',
@@ -107,9 +118,11 @@ const UIStrings = {
107
118
  */
108
119
  no: 'No',
109
120
  /**
110
- *@description Row title for in the Frame Details view
121
+ *@description Label for whether a frame is cross-origin isolated
122
+ *(https://developer.chrome.com/docs/extensions/mv3/cross-origin-isolation/)
123
+ *(for a lot of languages this does not need to be translated, please translate only where necessary)
111
124
  */
112
- crossoriginIsolated: '`Cross-Origin` Isolated',
125
+ crossoriginIsolated: 'Cross-Origin Isolated',
113
126
  /**
114
127
  *@description Explanatory text in the Frame Details view
115
128
  */
@@ -132,10 +145,11 @@ const UIStrings = {
132
145
  */
133
146
  apiAvailability: 'API availability',
134
147
  /**
135
- *@description Explanatory text in the Frame Details view for the API availability section
148
+ *@description Explanation of why cross-origin isolation is important
149
+ *(https://web.dev/why-coop-coep/)
150
+ *(for a lot of languages 'cross-origin isolation' does not need to be translated, please translate only where necessary)
136
151
  */
137
- availabilityOfCertainApisDepends:
138
- 'Availability of certain APIs depends on the document being `cross-origin` isolated.',
152
+ availabilityOfCertainApisDepends: 'Availability of certain APIs depends on the document being cross-origin isolated.',
139
153
  /**
140
154
  *@description Description of the SharedArrayBuffer status
141
155
  */
@@ -159,13 +173,17 @@ const UIStrings = {
159
173
  sharedarraybufferConstructorIsAvailable:
160
174
  '`SharedArrayBuffer` constructor is available but `SABs` cannot be transferred via `postMessage`',
161
175
  /**
162
- *@description Explanation for the SharedArrayBuffer availability status
176
+ *@description Explanation why SharedArrayBuffer will not be available in the future
177
+ *(https://developer.chrome.com/docs/extensions/mv3/cross-origin-isolation/)
178
+ *(for a lot of languages 'cross-origin isolation' does not need to be translated, please translate only where necessary)
163
179
  */
164
- willRequireCrossoriginIsolated: '⚠️ will require `cross-origin` isolated context in the future',
180
+ willRequireCrossoriginIsolated: '⚠️ will require cross-origin isolated context in the future',
165
181
  /**
166
- *@description Explanation for the SharedArrayBuffer availability status
182
+ *@description Explanation why SharedArrayBuffer is not available
183
+ *(https://developer.chrome.com/docs/extensions/mv3/cross-origin-isolation/)
184
+ *(for a lot of languages 'cross-origin isolation' does not need to be translated, please translate only where necessary).
167
185
  */
168
- requiresCrossoriginIsolated: 'requires `cross-origin` isolated context',
186
+ requiresCrossoriginIsolated: 'requires cross-origin isolated context',
169
187
  /**
170
188
  *@description Explanation for the SharedArrayBuffer availability status in case the transfer of a SAB requires the
171
189
  * permission policy `cross-origin-isolated` to be enabled (e.g. because the message refers to the situation in an iframe).
@@ -218,10 +236,6 @@ const UIStrings = {
218
236
  */
219
237
  createdByAdScriptExplanation:
220
238
  'There was an ad script in the `(async) stack` when this frame was created. Examining the creation `stack trace` of this frame might provide more insight.',
221
- /**
222
- *@description Label for a list of origin trials that associated with at least one token.
223
- */
224
- // originTrials: 'Origin Trials',
225
239
  };
226
240
  const str_ = i18n.i18n.registerUIStrings('panels/application/components/FrameDetailsView.ts', UIStrings);
227
241
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -343,7 +357,7 @@ export class FrameDetailsReportView extends HTMLElement {
343
357
  return LitHtml.html`
344
358
  <${ReportView.ReportView.ReportSectionHeader.litTagName}>${i18nString(UIStrings.document)}</${
345
359
  ReportView.ReportView.ReportSectionHeader.litTagName}>
346
- <${ReportView.ReportView.ReportKey.litTagName}>${i18n.i18n.lockedString('URL')}</${
360
+ <${ReportView.ReportView.ReportKey.litTagName}>${i18nString(UIStrings.url)}</${
347
361
  ReportView.ReportView.ReportKey.litTagName}>
348
362
  <${ReportView.ReportView.ReportValue.litTagName}>
349
363
  <div class="inline-items">
@@ -449,7 +463,7 @@ export class FrameDetailsReportView extends HTMLElement {
449
463
  private maybeRenderOrigin(): LitHtml.TemplateResult|{} {
450
464
  if (this.frame && this.frame.securityOrigin && this.frame.securityOrigin !== '://') {
451
465
  return LitHtml.html`
452
- <${ReportView.ReportView.ReportKey.litTagName}>${i18n.i18n.lockedString('Origin')}</${
466
+ <${ReportView.ReportView.ReportKey.litTagName}>${i18nString(UIStrings.origin)}</${
453
467
  ReportView.ReportView.ReportKey.litTagName}>
454
468
  <${ReportView.ReportView.ReportValue.litTagName}>
455
469
  <div class="text-ellipsis" title=${this.frame.securityOrigin}>${this.frame.securityOrigin}</div>
@@ -259,7 +259,6 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
259
259
  } else {
260
260
  this.editor.dispatch({scrollIntoView: true});
261
261
  }
262
- this.enterProcessedForTest();
263
262
  return true;
264
263
  }
265
264
 
@@ -283,9 +282,6 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
283
282
  }
284
283
  }
285
284
 
286
- private enterProcessedForTest(): void {
287
- }
288
-
289
285
  private editorUpdate(update: CodeMirror.ViewUpdate): void {
290
286
  if (update.docChanged ||
291
287
  CodeMirror.selectedCompletion(update.state) !== CodeMirror.selectedCompletion(update.startState)) {
@@ -86,13 +86,7 @@ async function getChildren(node: SDK.AccessibilityModel.AccessibilityNode):
86
86
  const localRoot = await getRootNode(frameId);
87
87
  return [localRoot];
88
88
  }
89
- if (node.hasUnloadedChildren()) {
90
- await node.accessibilityModel().requestAXChildren(node.id(), node.getFrameId() || undefined);
91
- if (node.numChildren() !== node.children().length) {
92
- throw new Error('Once loaded, number of children and length of children must match.');
93
- }
94
- }
95
- return node.children();
89
+ return node.accessibilityModel().requestAXChildren(node.id(), node.getFrameId() || undefined);
96
90
  }
97
91
 
98
92
  export async function sdkNodeToAXTreeNodes(sdkNode: SDK.AccessibilityModel.AccessibilityNode): Promise<AXTreeNode[]> {
@@ -120,16 +120,14 @@ export class AccessibilityTreeView extends UI.Widget.VBox implements
120
120
 
121
121
  // Selected node in the DOM tree has changed.
122
122
  async selectedNodeChanged(inspectedNode: SDK.DOMModel.DOMNode): Promise<void> {
123
- if (this.isShowing()) {
123
+ if (this.isShowing() || (inspectedNode === this.inspectedDOMNode)) {
124
124
  return;
125
125
  }
126
126
  if (inspectedNode.ownerDocument && (inspectedNode.nodeName() === 'HTML' || inspectedNode.nodeName() === 'BODY')) {
127
- inspectedNode = inspectedNode.ownerDocument;
127
+ this.inspectedDOMNode = inspectedNode.ownerDocument;
128
+ } else {
129
+ this.inspectedDOMNode = inspectedNode;
128
130
  }
129
- if (inspectedNode === this.inspectedDOMNode) {
130
- return;
131
- }
132
- this.inspectedDOMNode = inspectedNode;
133
131
  }
134
132
 
135
133
  treeUpdated({data}: Common.EventTarget
@@ -31,25 +31,67 @@
31
31
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
  */
33
33
 
34
- import propertiesWidgetStyles from './propertiesWidget.css.js';
35
- import type * as Common from '../../core/common/common.js';
34
+ import * as Common from '../../core/common/common.js';
36
35
  import * as Host from '../../core/host/host.js';
36
+ import * as i18n from '../../core/i18n/i18n.js';
37
37
  import * as SDK from '../../core/sdk/sdk.js';
38
+ import * as Protocol from '../../generated/protocol.js';
38
39
  import * as ObjectUI from '../../ui/legacy/components/object_ui/object_ui.js';
39
40
  import * as UI from '../../ui/legacy/legacy.js';
40
41
 
42
+ import propertiesWidgetStyles from './propertiesWidget.css.js';
43
+ import {StylesSidebarPane} from './StylesSidebarPane.js';
44
+
41
45
  const OBJECT_GROUP_NAME = 'properties-sidebar-pane';
42
46
 
47
+ const UIStrings = {
48
+ /**
49
+ * @description Placeholder text for a text input used to filter which DOM element properties show up in
50
+ * the Properties tab of the Elements panel.
51
+ */
52
+ filter: 'Filter',
53
+ /**
54
+ * @description ARIA accessible name for the text input used to filter which DOM element properties show up
55
+ * in the Properties tab of the Elements panel.
56
+ */
57
+ filterProperties: 'Filter Properties',
58
+ /**
59
+ * @description Text on the checkbox in the Properties tab of the Elements panel, which controls whether
60
+ * all properties of the currently selected DOM element are shown, or only meaningful properties (i.e.
61
+ * excluding properties whose values aren't set for example).
62
+ */
63
+ showAll: 'Show all',
64
+ /**
65
+ * @description Tooltip on the checkbox in the Properties tab of the Elements panel, which controls whether
66
+ * all properties of the currently selected DOM element are shown, or only meaningful properties (i.e.
67
+ * excluding properties whose values aren't set for example).
68
+ */
69
+ showAllTooltip: 'When unchecked, only properties whose values are neither null nor undefined will be shown',
70
+ /**
71
+ * @description Text shown to the user when a filter is applied in the Properties tab of the Elements panel, but
72
+ * no properties matched the filter and thus no results were returned.
73
+ */
74
+ noMatchingProperty: 'No matching property',
75
+ };
76
+ const str_ = i18n.i18n.registerUIStrings('panels/elements/PropertiesWidget.ts', UIStrings);
77
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
78
+
43
79
  let propertiesWidgetInstance: PropertiesWidget;
44
80
 
45
81
  export class PropertiesWidget extends UI.ThrottledWidget.ThrottledWidget {
46
82
  private node: SDK.DOMModel.DOMNode|null;
83
+ private readonly showAllPropertiesSetting: Common.Settings.Setting<boolean>;
84
+ private filterRegex: RegExp|null = null;
85
+ private readonly noMatchesElement: HTMLElement;
47
86
  private readonly treeOutline: ObjectUI.ObjectPropertiesSection.ObjectPropertiesSectionsTreeOutline;
48
87
  private readonly expandController: ObjectUI.ObjectPropertiesSection.ObjectPropertiesSectionsTreeExpandController;
49
88
  private lastRequestedNode?: SDK.DOMModel.DOMNode;
50
89
  constructor() {
51
90
  super(true /* isWebComponent */);
52
91
 
92
+ this.showAllPropertiesSetting = Common.Settings.Settings.instance().createSetting('showAllProperties', false);
93
+ this.showAllPropertiesSetting.addChangeListener(this.filterList.bind(this));
94
+
53
95
  SDK.TargetManager.TargetManager.instance().addModelListener(
54
96
  SDK.DOMModel.DOMModel, SDK.DOMModel.Events.AttrModified, this.onNodeChange, this);
55
97
  SDK.TargetManager.TargetManager.instance().addModelListener(
@@ -61,6 +103,20 @@ export class PropertiesWidget extends UI.ThrottledWidget.ThrottledWidget {
61
103
  UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, this.setNode, this);
62
104
  this.node = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);
63
105
 
106
+ const hbox = this.contentElement.createChild('div', 'hbox properties-widget-toolbar');
107
+ const filterContainerElement = hbox.createChild('div', 'properties-widget-filter-box');
108
+ const filterInput = StylesSidebarPane.createPropertyFilterElement(
109
+ i18nString(UIStrings.filter), hbox, this.filterProperties.bind(this));
110
+ UI.ARIAUtils.setAccessibleName(filterInput, i18nString(UIStrings.filterProperties));
111
+ filterContainerElement.appendChild(filterInput);
112
+
113
+ const toolbar = new UI.Toolbar.Toolbar('styles-pane-toolbar', hbox);
114
+ toolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(
115
+ this.showAllPropertiesSetting, i18nString(UIStrings.showAllTooltip), i18nString(UIStrings.showAll)));
116
+
117
+ this.noMatchesElement = this.contentElement.createChild('div', 'gray-info-message hidden');
118
+ this.noMatchesElement.textContent = i18nString(UIStrings.noMatchingProperty);
119
+
64
120
  this.treeOutline = new ObjectUI.ObjectPropertiesSection.ObjectPropertiesSectionsTreeOutline({readOnly: true});
65
121
  this.treeOutline.setShowSelectionOnKeyboardFocus(/* show */ true, /* preventTabOrder */ false);
66
122
  this.expandController =
@@ -73,6 +129,7 @@ export class PropertiesWidget extends UI.ThrottledWidget.ThrottledWidget {
73
129
 
74
130
  this.update();
75
131
  }
132
+
76
133
  static instance(opts: {
77
134
  forceNew: boolean|null,
78
135
  }|undefined = {forceNew: null}): PropertiesWidget {
@@ -84,6 +141,46 @@ export class PropertiesWidget extends UI.ThrottledWidget.ThrottledWidget {
84
141
  return propertiesWidgetInstance;
85
142
  }
86
143
 
144
+ private filterProperties(this: PropertiesWidget, regex: RegExp|null): void {
145
+ this.filterRegex = regex;
146
+ this.filterList();
147
+ }
148
+
149
+ private filterList(): void {
150
+ const isHidden = (property: SDK.RemoteObject.RemoteObjectProperty): boolean => {
151
+ if (!this.showAllPropertiesSetting.get()) {
152
+ if (SDK.RemoteObject.RemoteObject.isNullOrUndefined(property.value)) {
153
+ return true;
154
+ }
155
+ if (property.value?.type === Protocol.Runtime.RemoteObjectType.Undefined ||
156
+ (property.value?.type === Protocol.Runtime.RemoteObjectType.Object &&
157
+ property.value.subtype === Protocol.Runtime.RemoteObjectSubtype.Null)) {
158
+ return true;
159
+ }
160
+ }
161
+ if (this.filterRegex !== null) {
162
+ if (this.filterRegex.test(property.name)) {
163
+ return false;
164
+ }
165
+ if (this.filterRegex.test(property.value?.description ?? '')) {
166
+ return false;
167
+ }
168
+ return true;
169
+ }
170
+ return false;
171
+ };
172
+ let noMatches = true;
173
+ for (const element of this.treeOutline.rootElement().children()) {
174
+ const {property} = element as ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement;
175
+ const hidden = isHidden(property);
176
+ if (!hidden) {
177
+ noMatches = false;
178
+ }
179
+ element.hidden = hidden;
180
+ }
181
+ this.noMatchesElement.classList.toggle('hidden', !noMatches);
182
+ }
183
+
87
184
  private setNode(event: Common.EventTarget.EventTargetEvent<SDK.DOMModel.DOMNode|null>): void {
88
185
  this.node = event.data;
89
186
  this.update();
@@ -106,8 +203,15 @@ export class PropertiesWidget extends UI.ThrottledWidget.ThrottledWidget {
106
203
  return;
107
204
  }
108
205
 
109
- await ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement.populate(
110
- this.treeOutline.rootElement(), object, true, true, undefined, undefined);
206
+ const treeElement = this.treeOutline.rootElement();
207
+ let {properties} = await SDK.RemoteObject.RemoteObject.loadFromObjectPerProto(object, true /* generatePreview */);
208
+ treeElement.removeChildren();
209
+ if (properties === null) {
210
+ properties = [];
211
+ }
212
+ ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement.populateWithProperties(
213
+ treeElement, properties, null, true /* skipProto */, true /* skipGettersAndSetters */, object);
214
+ this.filterList();
111
215
  }
112
216
 
113
217
  private onNodeChange(event: Common.EventTarget
@@ -122,6 +226,7 @@ export class PropertiesWidget extends UI.ThrottledWidget.ThrottledWidget {
122
226
  }
123
227
  this.update();
124
228
  }
229
+
125
230
  wasShown(): void {
126
231
  super.wasShown();
127
232
  this.registerCSSFiles([propertiesWidgetStyles]);
@@ -8,3 +8,37 @@
8
8
  padding: 2px 0 2px 5px;
9
9
  flex: none;
10
10
  }
11
+
12
+ .properties-widget-toolbar {
13
+ border-bottom: 1px solid var(--color-details-hairline-light);
14
+ flex-shrink: 0;
15
+ }
16
+
17
+ .properties-widget-filter-box {
18
+ flex: auto;
19
+ display: flex;
20
+ }
21
+
22
+ .properties-widget-filter-box > input {
23
+ outline: none !important; /* stylelint-disable-line declaration-no-important */
24
+ border: none;
25
+ width: 100%;
26
+ background: var(--color-background);
27
+ padding-left: 4px;
28
+ margin: 3px;
29
+ }
30
+
31
+ .properties-widget-filter-box > input:focus,
32
+ .properties-widget-filter-box > input:not(:placeholder-shown) {
33
+ box-shadow: var(--legacy-focus-ring-active-shadow);
34
+ }
35
+
36
+ .properties-widget-filter-box > input::placeholder {
37
+ color: var(--color-text-disabled);
38
+ }
39
+
40
+ @media (forced-colors: active) {
41
+ .properties-widget-filter-box > input {
42
+ border: 1px solid ButtonText;
43
+ }
44
+ }
@@ -402,7 +402,7 @@ export class DeviceModeToolbar {
402
402
  private appendScaleMenuItems(contextMenu: UI.ContextMenu.ContextMenu): void {
403
403
  if (this.model.type() === EmulationModel.DeviceModeModel.Type.Device) {
404
404
  contextMenu.footerSection().appendItem(
405
- i18nString(UIStrings.fitToWindowF, {PH1: this.getPrettyZoomPercentage()}),
405
+ i18nString(UIStrings.fitToWindowF, {PH1: this.getPrettyFitZoomPercentage()}),
406
406
  this.onScaleMenuChanged.bind(this, this.model.fitScale()), false);
407
407
  }
408
408
  contextMenu.footerSection().appendCheckboxItem(
@@ -693,6 +693,10 @@ export class DeviceModeToolbar {
693
693
  }
694
694
  }
695
695
 
696
+ private getPrettyFitZoomPercentage(): string {
697
+ return `${(this.model.fitScale() * 100).toFixed(0)}`;
698
+ }
699
+
696
700
  private getPrettyZoomPercentage(): string {
697
701
  return `${(this.model.scale() * 100).toFixed(0)}`;
698
702
  }
@@ -32,6 +32,16 @@ const UIStrings = {
32
32
  * on an anchor HTML element ("a link").
33
33
  */
34
34
  invalidSourceEventId: 'Invalid `attributionsourceeventid`',
35
+ /**
36
+ * @description Label for the column showing the invalid value used as the 'attributionexpiry' attribute
37
+ * on an anchor HTML element ("a link").
38
+ */
39
+ invalidSourceExpiry: 'Invalid `attributionexpiry`',
40
+ /**
41
+ * @description Label for the column showing the invalid value used as the 'attributionpriority' attribute
42
+ * on an anchor HTML element ("a link").
43
+ */
44
+ invalidSourcePriority: 'Invalid `attributionsourcepriority`',
35
45
  /**
36
46
  * @description Label for the column showing the invalid URL used in an HTML anchor element ("a link").
37
47
  * A origin is (roughly said) the front part of a URL.
@@ -47,6 +57,16 @@ const UIStrings = {
47
57
  * 'event-source-trigger-data' query parameter.
48
58
  */
49
59
  invalidEventSourceTriggerData: 'Invalid `event-source-trigger-data`',
60
+ /**
61
+ * @description Label for the column showing the invalid value used for the
62
+ * 'priority' query parameter.
63
+ */
64
+ invalidTriggerPriority: 'Invalid `priority`',
65
+ /**
66
+ * @description Label for the column showing the invalid value used for the
67
+ * 'dedup-key' query parameter.
68
+ */
69
+ invalidTriggerDedupKey: 'Invalid `dedup-key`',
50
70
  };
51
71
  const str_ = i18n.i18n.registerUIStrings('panels/issues/AttributionReportingIssueDetailsView.ts', UIStrings);
52
72
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -94,15 +114,34 @@ export class AttributionReportingIssueDetailsView extends AffectedResourcesView
94
114
  this.appendColumnTitle(header, i18nString(UIStrings.request));
95
115
  this.appendColumnTitle(header, i18nString(UIStrings.invalidTriggerData));
96
116
  break;
117
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidEventSourceTriggerData:
97
118
  case IssuesManager.AttributionReportingIssue.IssueCode.AttributionEventSourceTriggerDataTooLarge:
98
119
  this.appendColumnTitle(header, i18nString(UIStrings.request));
99
120
  this.appendColumnTitle(header, i18nString(UIStrings.invalidEventSourceTriggerData));
100
121
  break;
122
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidTriggerPriority:
123
+ this.appendColumnTitle(header, i18nString(UIStrings.request));
124
+ this.appendColumnTitle(header, i18nString(UIStrings.invalidTriggerPriority));
125
+ break;
126
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidTriggerDedupKey:
127
+ this.appendColumnTitle(header, i18nString(UIStrings.request));
128
+ this.appendColumnTitle(header, i18nString(UIStrings.invalidTriggerDedupKey));
129
+ break;
101
130
  case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourceEventId:
102
131
  this.appendColumnTitle(header, i18nString(UIStrings.frame));
103
132
  this.appendColumnTitle(header, i18nString(UIStrings.element));
104
133
  this.appendColumnTitle(header, i18nString(UIStrings.invalidSourceEventId));
105
134
  break;
135
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourceExpiry:
136
+ this.appendColumnTitle(header, i18nString(UIStrings.frame));
137
+ this.appendColumnTitle(header, i18nString(UIStrings.element));
138
+ this.appendColumnTitle(header, i18nString(UIStrings.invalidSourceExpiry));
139
+ break;
140
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourcePriority:
141
+ this.appendColumnTitle(header, i18nString(UIStrings.frame));
142
+ this.appendColumnTitle(header, i18nString(UIStrings.element));
143
+ this.appendColumnTitle(header, i18nString(UIStrings.invalidSourcePriority));
144
+ break;
106
145
  case IssuesManager.AttributionReportingIssue.IssueCode.MissingAttributionData:
107
146
  this.appendColumnTitle(header, i18nString(UIStrings.request));
108
147
  break;
@@ -144,11 +183,16 @@ export class AttributionReportingIssueDetailsView extends AffectedResourcesView
144
183
  case IssuesManager.AttributionReportingIssue.IssueCode.AttributionEventSourceTriggerDataTooLarge:
145
184
  case IssuesManager.AttributionReportingIssue.IssueCode.AttributionUntrustworthyOrigin:
146
185
  case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionData:
186
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidEventSourceTriggerData:
187
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidTriggerPriority:
188
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidTriggerDedupKey:
147
189
  this.appendRequestOrEmptyCell(element, details.request);
148
190
  this.appendIssueDetailCell(element, details.invalidParameter || '');
149
191
  break;
150
192
  case IssuesManager.AttributionReportingIssue.IssueCode.AttributionSourceUntrustworthyFrameOrigin:
151
193
  case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourceEventId:
194
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourceExpiry:
195
+ case IssuesManager.AttributionReportingIssue.IssueCode.InvalidAttributionSourcePriority:
152
196
  this.appendFrameOrEmptyCell(element, issue);
153
197
  await this.appendElementOrEmptyCell(element, issue);
154
198
  this.appendIssueDetailCell(element, details.invalidParameter || '');
@@ -119,6 +119,10 @@ const UIStrings = {
119
119
  *@description Header for the column with the URL scheme that is not supported by fetch
120
120
  */
121
121
  unsupportedScheme: 'Unsupported Scheme',
122
+ /**
123
+ *@description A failed network request.
124
+ */
125
+ failedRequest: 'Failed Request',
122
126
  };
123
127
  const str_ = i18n.i18n.registerUIStrings('panels/issues/CorsIssueDetailsView.ts', UIStrings);
124
128
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -210,7 +214,6 @@ export class CorsIssueDetailsView extends AffectedResourcesView {
210
214
  default:
211
215
  Platform.assertUnhandled<IssuesManager.CorsIssue.IssueCode.PreflightMissingAllowExternal|
212
216
  IssuesManager.CorsIssue.IssueCode.PreflightInvalidAllowExternal|
213
- IssuesManager.CorsIssue.IssueCode.InvalidResponse|
214
217
  IssuesManager.CorsIssue.IssueCode.InvalidPrivateNetworkAccess|
215
218
  IssuesManager.CorsIssue.IssueCode.UnexpectedPrivateNetworkAccess>(issueCode);
216
219
  }
@@ -283,6 +286,8 @@ export class CorsIssueDetailsView extends AffectedResourcesView {
283
286
  return i18nString(UIStrings.preflightInvalidStatus);
284
287
  case Protocol.Network.CorsError.PreflightDisallowedRedirect:
285
288
  return i18nString(UIStrings.preflightDisallowedRedirect);
289
+ case Protocol.Network.CorsError.InvalidResponse:
290
+ return i18nString(UIStrings.failedRequest);
286
291
  }
287
292
  throw new Error('Invalid Argument');
288
293
  }
@@ -447,7 +452,6 @@ export class CorsIssueDetailsView extends AffectedResourcesView {
447
452
  this.appendStatus(element, details.isWarning);
448
453
  Platform.assertUnhandled<IssuesManager.CorsIssue.IssueCode.PreflightMissingAllowExternal|
449
454
  IssuesManager.CorsIssue.IssueCode.PreflightInvalidAllowExternal|
450
- IssuesManager.CorsIssue.IssueCode.InvalidResponse|
451
455
  IssuesManager.CorsIssue.IssueCode.InvalidPrivateNetworkAccess|
452
456
  IssuesManager.CorsIssue.IssueCode.UnexpectedPrivateNetworkAccess>(issueCode);
453
457
  break;
@@ -554,6 +554,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
554
554
  aria-controls="form-container"
555
555
  @disabled=${this.isFormDisabled}
556
556
  aria-disabled=${this.isFormDisabled}
557
+ aria-label=${i18nString(UIStrings.title)}
557
558
  >
558
559
  <${IconButton.Icon.Icon.litTagName}
559
560
  class=${this.isFormOpened ? '' : 'rotate-icon'}