chrome-devtools-frontend 1.0.948445 → 1.0.950484
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.
- package/config/gni/all_devtools_files.gni +5 -0
- package/config/gni/devtools_grd_files.gni +5 -6
- package/front_end/core/i18n/locales/en-US.json +45 -30
- package/front_end/core/i18n/locales/en-XL.json +49 -34
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/core/sdk/AccessibilityModel.ts +7 -7
- package/front_end/core/sdk/RemoteObject.ts +15 -1
- package/front_end/entrypoints/devtools_app/devtools_app.ts +0 -1
- package/front_end/entrypoints/visibility.gni +3 -1
- package/front_end/entrypoints/worker_app/worker_app.ts +0 -1
- package/front_end/generated/InspectorBackendCommands.js +8 -1
- package/front_end/generated/protocol-mapping.d.ts +4 -0
- package/front_end/generated/protocol-proxy-api.d.ts +6 -0
- package/front_end/generated/protocol.d.ts +9 -0
- package/front_end/models/issues_manager/AttributionReportingIssue.ts +75 -4
- package/front_end/models/issues_manager/CorsIssue.ts +1 -4
- package/front_end/models/issues_manager/descriptions/arInvalidAttributionSourceExpiry.md +4 -0
- package/front_end/models/issues_manager/descriptions/arInvalidAttributionSourcePriority.md +4 -0
- package/front_end/models/issues_manager/descriptions/arInvalidEventSourceTriggerData.md +9 -0
- package/front_end/models/issues_manager/descriptions/arInvalidTriggerDedupKey.md +5 -0
- package/front_end/models/issues_manager/descriptions/arInvalidTriggerPriority.md +5 -0
- package/front_end/models/issues_manager/descriptions/corsPreflightResponseInvalid.md +2 -2
- package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +45 -3
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +2 -4
- package/front_end/panels/accessibility/axBreadcrumbs.css +4 -0
- package/front_end/panels/animation/animationTimeline.css +2 -1
- package/front_end/panels/application/components/FrameDetailsView.ts +29 -15
- package/front_end/panels/console/ConsolePrompt.ts +14 -12
- package/front_end/panels/elements/AccessibilityTreeUtils.ts +1 -7
- package/front_end/panels/elements/AccessibilityTreeView.ts +4 -6
- package/front_end/panels/elements/PropertiesWidget.ts +109 -4
- package/front_end/panels/elements/propertiesWidget.css +34 -0
- package/front_end/panels/emulation/DeviceModeToolbar.ts +5 -1
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +44 -0
- package/front_end/panels/issues/CorsIssueDetailsView.ts +6 -2
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +1 -0
- package/front_end/panels/sources/BreakpointEditDialog.ts +8 -5
- package/front_end/panels/timeline/TimelinePanel.ts +5 -4
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/codemirror.next.d.ts +8 -6
- package/front_end/third_party/codemirror.next/package.json +3 -3
- package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +16 -0
- package/front_end/ui/components/text_editor/javascript.ts +16 -7
- package/package.json +1 -1
- package/scripts/eslint_rules/lib/ban_a_tags_in_lit_html.js +2 -11
- package/scripts/eslint_rules/lib/ban_literal_devtools_component_tag_names.js +2 -11
- package/scripts/eslint_rules/lib/ban_self_closing_custom_element_tagnames.js +2 -11
- package/scripts/eslint_rules/lib/ban_style_tags_in_lit_html.js +2 -11
- package/scripts/eslint_rules/lib/lit_html_data_as_type.js +2 -11
- package/scripts/eslint_rules/lib/lit_html_no_attribute_quotes.js +1 -13
- package/scripts/eslint_rules/lib/lit_no_style_interpolation.js +2 -11
- package/scripts/eslint_rules/lib/static_tag_must_be_static_property.js +2 -11
- package/scripts/eslint_rules/lib/utils.js +29 -0
- package/scripts/eslint_rules/tests/.eslintrc.js +4 -0
- package/scripts/eslint_rules/tests/utils_test.js +40 -0
- package/front_end/panels/help/HelpImpl.ts +0 -141
- package/front_end/panels/help/ReleaseNoteText.ts +0 -1496
- package/front_end/panels/help/ReleaseNoteView.ts +0 -107
- package/front_end/panels/help/help-meta.ts +0 -145
- package/front_end/panels/help/help.ts +0 -13
- package/front_end/panels/help/releaseNote.css +0 -115
- package/scripts/build/rjsmin.py +0 -484
|
@@ -40,7 +40,6 @@ export enum IssueCode {
|
|
|
40
40
|
PreflightMissingAllowExternal = 'CorsIssue::PreflightMissingAllowExternal',
|
|
41
41
|
// TODO(https://crbug.com/1263483): Remove this once it's removed from CDP.
|
|
42
42
|
PreflightInvalidAllowExternal = 'CorsIssue::PreflightInvalidAllowExternal',
|
|
43
|
-
InvalidResponse = 'CorsIssue::InvalidResponse',
|
|
44
43
|
NoCorsRedirectModeNotFollow = 'CorsIssue::NoCorsRedirectModeNotFollow',
|
|
45
44
|
InvalidPrivateNetworkAccess = 'CorsIssue::InvalidPrivateNetworkAccess',
|
|
46
45
|
UnexpectedPrivateNetworkAccess = 'CorsIssue::UnexpectedPrivateNetworkAccess',
|
|
@@ -63,6 +62,7 @@ function getIssueCode(details: Protocol.Audits.CorsIssueDetails): IssueCode {
|
|
|
63
62
|
return IssueCode.WildcardOriginNotAllowed;
|
|
64
63
|
case Protocol.Network.CorsError.PreflightInvalidStatus:
|
|
65
64
|
case Protocol.Network.CorsError.PreflightDisallowedRedirect:
|
|
65
|
+
case Protocol.Network.CorsError.InvalidResponse:
|
|
66
66
|
return IssueCode.PreflightResponseInvalid;
|
|
67
67
|
case Protocol.Network.CorsError.AllowOriginMismatch:
|
|
68
68
|
case Protocol.Network.CorsError.PreflightAllowOriginMismatch:
|
|
@@ -84,8 +84,6 @@ function getIssueCode(details: Protocol.Audits.CorsIssueDetails): IssueCode {
|
|
|
84
84
|
return IssueCode.PreflightMissingAllowExternal;
|
|
85
85
|
case Protocol.Network.CorsError.PreflightInvalidAllowExternal:
|
|
86
86
|
return IssueCode.PreflightInvalidAllowExternal;
|
|
87
|
-
case Protocol.Network.CorsError.InvalidResponse:
|
|
88
|
-
return IssueCode.InvalidResponse;
|
|
89
87
|
case Protocol.Network.CorsError.InsecurePrivateNetwork:
|
|
90
88
|
return IssueCode.InsecurePrivateNetwork;
|
|
91
89
|
case Protocol.Network.CorsError.NoCorsRedirectModeNotFollow:
|
|
@@ -226,7 +224,6 @@ export class CorsIssue extends Issue<IssueCode> {
|
|
|
226
224
|
};
|
|
227
225
|
case IssueCode.PreflightMissingAllowExternal:
|
|
228
226
|
case IssueCode.PreflightInvalidAllowExternal:
|
|
229
|
-
case IssueCode.InvalidResponse:
|
|
230
227
|
case IssueCode.InvalidPrivateNetworkAccess:
|
|
231
228
|
case IssueCode.UnexpectedPrivateNetworkAccess:
|
|
232
229
|
return null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Ensure the "event-source-trigger-data" query parameter for an attribution redirect is a valid number
|
|
2
|
+
|
|
3
|
+
The event-source trigger data associated with an attribution was defaulted to `0`.
|
|
4
|
+
This happens if the `event-source-trigger-data` query parameter provided in the `.well-known`
|
|
5
|
+
redirect is not a valid 64-bit unsigned integer.
|
|
6
|
+
|
|
7
|
+
Note that even if a valid integer is provided, only the lowest 1-bit of the
|
|
8
|
+
`event-source-trigger-data` query parameter is recorded, with a 5% chance of the 1 bit being
|
|
9
|
+
noised.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Ensure the "dedup-key" query parameter for an attribution redirect is a valid number
|
|
2
|
+
|
|
3
|
+
The dedup key associated with an attribution was defaulted to `null`.
|
|
4
|
+
This happens if the `dedup-key` query parameter provided in the `.well-known` redirect is not a
|
|
5
|
+
valid 64-bit signed integer.
|
|
@@ -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 `
|
|
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
|
-
|
|
35
|
-
|
|
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
|
|
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: '
|
|
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
|
|
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
|
|
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
|
|
180
|
+
willRequireCrossoriginIsolated: '⚠️ will require cross-origin isolated context in the future',
|
|
165
181
|
/**
|
|
166
|
-
*@description Explanation
|
|
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
|
|
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}>${
|
|
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}>${
|
|
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>
|
|
@@ -207,7 +207,14 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
|
207
207
|
{key: 'ArrowDown', run: (): boolean => this.moveHistory(1)},
|
|
208
208
|
{mac: 'Ctrl-p', run: (): boolean => this.moveHistory(-1, true)},
|
|
209
209
|
{mac: 'Ctrl-n', run: (): boolean => this.moveHistory(1, true)},
|
|
210
|
-
{
|
|
210
|
+
{
|
|
211
|
+
key: 'Enter',
|
|
212
|
+
run: (): boolean => {
|
|
213
|
+
this.handleEnter();
|
|
214
|
+
return true;
|
|
215
|
+
},
|
|
216
|
+
shift: CodeMirror.insertNewlineAndIndent,
|
|
217
|
+
},
|
|
211
218
|
];
|
|
212
219
|
}
|
|
213
220
|
|
|
@@ -242,30 +249,28 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
|
242
249
|
return true;
|
|
243
250
|
}
|
|
244
251
|
|
|
245
|
-
private enterWillEvaluate(): boolean {
|
|
252
|
+
private async enterWillEvaluate(): Promise<boolean> {
|
|
246
253
|
const {state} = this.editor;
|
|
247
|
-
return state.doc.length > 0 && TextEditor.JavaScript.isExpressionComplete(state);
|
|
254
|
+
return state.doc.length > 0 && await TextEditor.JavaScript.isExpressionComplete(state.doc.toString());
|
|
248
255
|
}
|
|
249
256
|
|
|
250
|
-
private
|
|
251
|
-
if (this.enterWillEvaluate()) {
|
|
257
|
+
private async handleEnter(): Promise<void> {
|
|
258
|
+
if (await this.enterWillEvaluate()) {
|
|
252
259
|
this.appendCommand(this.text(), true);
|
|
253
260
|
this.editor.dispatch({
|
|
254
261
|
changes: {from: 0, to: this.editor.state.doc.length},
|
|
255
262
|
scrollIntoView: true,
|
|
256
263
|
});
|
|
257
264
|
} else if (this.editor.state.doc.length) {
|
|
258
|
-
|
|
265
|
+
CodeMirror.insertNewlineAndIndent(this.editor.editor);
|
|
259
266
|
} else {
|
|
260
267
|
this.editor.dispatch({scrollIntoView: true});
|
|
261
268
|
}
|
|
262
|
-
this.enterProcessedForTest();
|
|
263
|
-
return true;
|
|
264
269
|
}
|
|
265
270
|
|
|
266
271
|
private updatePromptIcon(): void {
|
|
267
272
|
this.iconThrottler.schedule(async () => {
|
|
268
|
-
this.promptIcon.classList.toggle('console-prompt-incomplete', !this.enterWillEvaluate());
|
|
273
|
+
this.promptIcon.classList.toggle('console-prompt-incomplete', !(await this.enterWillEvaluate()));
|
|
269
274
|
});
|
|
270
275
|
}
|
|
271
276
|
|
|
@@ -283,9 +288,6 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
|
283
288
|
}
|
|
284
289
|
}
|
|
285
290
|
|
|
286
|
-
private enterProcessedForTest(): void {
|
|
287
|
-
}
|
|
288
|
-
|
|
289
291
|
private editorUpdate(update: CodeMirror.ViewUpdate): void {
|
|
290
292
|
if (update.docChanged ||
|
|
291
293
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
110
|
-
|
|
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.
|
|
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
|
}
|