chrome-devtools-frontend 1.0.1029692 → 1.0.1029795
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/devtools_grd_files.gni +1 -0
- package/front_end/models/issues_manager/AttributionReportingIssue.ts +11 -0
- package/front_end/models/issues_manager/descriptions/arInvalidEligibleHeader.md +19 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +3 -23
- package/front_end/panels/elements/StylesSidebarPane.ts +31 -1
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +2 -0
- package/front_end/panels/network/components/RequestHeadersView.ts +28 -6
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +41 -3
- package/front_end/ui/legacy/TextPrompt.ts +1 -1
- package/package.json +1 -1
@@ -280,6 +280,7 @@ grd_files_release_sources = [
|
|
280
280
|
"front_end/models/issues_manager/descriptions/TwaHttpError.md",
|
281
281
|
"front_end/models/issues_manager/descriptions/TwaPageUnavailableOffline.md",
|
282
282
|
"front_end/models/issues_manager/descriptions/arInsecureContext.md",
|
283
|
+
"front_end/models/issues_manager/descriptions/arInvalidEligibleHeader.md",
|
283
284
|
"front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md",
|
284
285
|
"front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md",
|
285
286
|
"front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md",
|
@@ -14,6 +14,7 @@ export const enum IssueCode {
|
|
14
14
|
InsecureContext = 'AttributionReportingIssue::InsecureContext',
|
15
15
|
InvalidRegisterSourceHeader = 'AttributionReportingIssue::InvalidRegisterSourceHeader',
|
16
16
|
InvalidRegisterTriggerHeader = 'AttributionReportingIssue::InvalidRegisterTriggerHeader',
|
17
|
+
InvalidEligibleHeader = 'AttributionReportingIssue::InvalidEligibleHeader',
|
17
18
|
// TODO(apaseltiner): Remove this once old issue types are removed from
|
18
19
|
// protocol.
|
19
20
|
Unknown = 'AttributionReportingIssue::Unknown',
|
@@ -31,6 +32,8 @@ function getIssueCode(details: Protocol.Audits.AttributionReportingIssueDetails)
|
|
31
32
|
return IssueCode.InvalidRegisterSourceHeader;
|
32
33
|
case Protocol.Audits.AttributionReportingIssueType.InvalidRegisterTriggerHeader:
|
33
34
|
return IssueCode.InvalidRegisterTriggerHeader;
|
35
|
+
case Protocol.Audits.AttributionReportingIssueType.InvalidEligibleHeader:
|
36
|
+
return IssueCode.InvalidEligibleHeader;
|
34
37
|
default:
|
35
38
|
return IssueCode.Unknown;
|
36
39
|
}
|
@@ -76,6 +79,14 @@ export class AttributionReportingIssue extends Issue<IssueCode> {
|
|
76
79
|
file: 'arInvalidRegisterTriggerHeader.md',
|
77
80
|
links: [],
|
78
81
|
};
|
82
|
+
case IssueCode.InvalidEligibleHeader:
|
83
|
+
return {
|
84
|
+
file: 'arInvalidEligibleHeader.md',
|
85
|
+
links: [{
|
86
|
+
link: 'https://tools.ietf.org/id/draft-ietf-httpbis-header-structure-15.html#rfc.section.4.2.2',
|
87
|
+
linkTitle: 'Structured Headers RFC',
|
88
|
+
}],
|
89
|
+
};
|
79
90
|
case IssueCode.Unknown:
|
80
91
|
return null;
|
81
92
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Ensure that the `Attribution-Reporting-Eligible` header is valid
|
2
|
+
|
3
|
+
This page sent a request containing an `Attribution-Reporting-Eligible` header,
|
4
|
+
but the header value was not a valid structured dictionary, causing any source
|
5
|
+
or trigger registration in the response to be ignored.
|
6
|
+
|
7
|
+
The header should contain a structured dictionary as follows:
|
8
|
+
|
9
|
+
To allow the response to register an event source:
|
10
|
+
`Attribution-Reporting-Eligible: event-source`
|
11
|
+
|
12
|
+
To allow the response to register a trigger:
|
13
|
+
`Attribution-Reporting-Eligible: trigger`
|
14
|
+
|
15
|
+
To allow the response to register an event source or a trigger:
|
16
|
+
`Attribution-Reporting-Eligible: event-source, trigger`
|
17
|
+
|
18
|
+
To prevent the response from registering anything:
|
19
|
+
`Attribution-Reporting-Eligible: `
|
@@ -26,6 +26,8 @@ import {cssRuleValidatorsMap, type AuthoringHint} from './CSSRuleValidator.js';
|
|
26
26
|
const FlexboxEditor = ElementsComponents.StylePropertyEditor.FlexboxEditor;
|
27
27
|
const GridEditor = ElementsComponents.StylePropertyEditor.GridEditor;
|
28
28
|
|
29
|
+
export const activeHints = new WeakMap<Element, AuthoringHint>();
|
30
|
+
|
29
31
|
const UIStrings = {
|
30
32
|
/**
|
31
33
|
*@description Text in Color Swatch Popover Icon of the Elements panel
|
@@ -719,11 +721,7 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
719
721
|
const showAuthoringHint = authoringHint !== null && this.property.parsedOk;
|
720
722
|
if (showAuthoringHint) {
|
721
723
|
const hintIcon = UI.Icon.Icon.create('mediumicon-info', 'hint');
|
722
|
-
|
723
|
-
new UI.PopoverHelper.PopoverHelper(hintIcon, event => this.handleHintPopoverRequest(authoringHint, event));
|
724
|
-
hintPopover.setHasPadding(true);
|
725
|
-
hintPopover.setTimeout(0, 100);
|
726
|
-
|
724
|
+
activeHints.set(hintIcon, authoringHint);
|
727
725
|
this.listItemElement.append(hintIcon);
|
728
726
|
}
|
729
727
|
|
@@ -836,24 +834,6 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
|
|
836
834
|
return null;
|
837
835
|
}
|
838
836
|
|
839
|
-
private handleHintPopoverRequest(authoringHint: AuthoringHint, event: Event): UI.PopoverHelper.PopoverRequest|null {
|
840
|
-
const link = event.composedPath()[0];
|
841
|
-
Platform.DCHECK(() => link instanceof Element, 'Link is not an instance of Element');
|
842
|
-
|
843
|
-
return {
|
844
|
-
box: (link as Element).boxInWindow(),
|
845
|
-
show: async(popover: UI.GlassPane.GlassPane): Promise<boolean> => {
|
846
|
-
const node = this.node();
|
847
|
-
if (!node) {
|
848
|
-
return false;
|
849
|
-
}
|
850
|
-
const popupElement = new ElementsComponents.CSSHintDetailsView.CSSHintDetailsView(authoringHint);
|
851
|
-
popover.contentElement.insertAdjacentElement('beforeend', popupElement);
|
852
|
-
return true;
|
853
|
-
},
|
854
|
-
};
|
855
|
-
}
|
856
|
-
|
857
837
|
private mouseUp(event: MouseEvent): void {
|
858
838
|
const activeTreeElement = parentMap.get(this.parentPaneInternal);
|
859
839
|
parentMap.delete(this.parentPaneInternal);
|
@@ -60,7 +60,7 @@ import {StyleEditorWidget} from './StyleEditorWidget.js';
|
|
60
60
|
import {StylePropertyHighlighter} from './StylePropertyHighlighter.js';
|
61
61
|
import stylesSidebarPaneStyles from './stylesSidebarPane.css.js';
|
62
62
|
|
63
|
-
import {type StylePropertyTreeElement} from './StylePropertyTreeElement.js';
|
63
|
+
import {activeHints, type StylePropertyTreeElement} from './StylePropertyTreeElement.js';
|
64
64
|
import {
|
65
65
|
StylePropertiesSection,
|
66
66
|
BlankStylePropertiesSection,
|
@@ -213,6 +213,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
213
213
|
private needsForceUpdate: boolean;
|
214
214
|
private readonly resizeThrottler: Common.Throttler.Throttler;
|
215
215
|
private readonly imagePreviewPopover: ImagePreviewPopover;
|
216
|
+
#hintPopoverHelper: UI.PopoverHelper.PopoverHelper;
|
216
217
|
activeCSSAngle: InlineEditor.CSSAngle.CSSAngle|null;
|
217
218
|
#urlToChangeTracker: Map<Platform.DevToolsPath.UrlString, ChangeTracker> = new Map();
|
218
219
|
#copyChangesButton?: UI.Toolbar.ToolbarButton;
|
@@ -282,6 +283,35 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
|
|
282
283
|
}, () => this.node());
|
283
284
|
|
284
285
|
this.activeCSSAngle = null;
|
286
|
+
|
287
|
+
this.#hintPopoverHelper = new UI.PopoverHelper.PopoverHelper(this.contentElement, event => {
|
288
|
+
const icon = event.composedPath()[0] as Element;
|
289
|
+
|
290
|
+
if (!icon) {
|
291
|
+
return null;
|
292
|
+
}
|
293
|
+
|
294
|
+
if (!icon.matches('.hint')) {
|
295
|
+
return null;
|
296
|
+
}
|
297
|
+
|
298
|
+
const hint = activeHints.get(icon);
|
299
|
+
|
300
|
+
if (!hint) {
|
301
|
+
return null;
|
302
|
+
}
|
303
|
+
|
304
|
+
return {
|
305
|
+
box: icon.boxInWindow(),
|
306
|
+
show: async(popover: UI.GlassPane.GlassPane): Promise<boolean> => {
|
307
|
+
const popupElement = new ElementsComponents.CSSHintDetailsView.CSSHintDetailsView(hint);
|
308
|
+
popover.contentElement.appendChild(popupElement);
|
309
|
+
return true;
|
310
|
+
},
|
311
|
+
};
|
312
|
+
});
|
313
|
+
this.#hintPopoverHelper.setTimeout(200);
|
314
|
+
this.#hintPopoverHelper.setHasPadding(true);
|
285
315
|
}
|
286
316
|
|
287
317
|
swatchPopoverHelper(): InlineEditor.SwatchPopoverHelper.SwatchPopoverHelper {
|
@@ -57,6 +57,7 @@ export class AttributionReportingIssueDetailsView extends AffectedResourcesView
|
|
57
57
|
switch (issueCode) {
|
58
58
|
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidRegisterSourceHeader:
|
59
59
|
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidRegisterTriggerHeader:
|
60
|
+
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidEligibleHeader:
|
60
61
|
this.appendColumnTitle(header, i18nString(UIStrings.request));
|
61
62
|
this.appendColumnTitle(header, i18nString(UIStrings.invalidHeaderValue));
|
62
63
|
break;
|
@@ -92,6 +93,7 @@ export class AttributionReportingIssueDetailsView extends AffectedResourcesView
|
|
92
93
|
switch (issueCode) {
|
93
94
|
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidRegisterSourceHeader:
|
94
95
|
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidRegisterTriggerHeader:
|
96
|
+
case IssuesManager.AttributionReportingIssue.IssueCode.InvalidEligibleHeader:
|
95
97
|
this.#appendRequestOrEmptyCell(element, details.request);
|
96
98
|
this.appendIssueDetailCell(element, details.invalidParameter || '');
|
97
99
|
break;
|
@@ -173,12 +173,16 @@ export class RequestHeadersView extends UI.Widget.VBox {
|
|
173
173
|
wasShown(): void {
|
174
174
|
this.#request.addEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this.#refreshHeadersView, this);
|
175
175
|
this.#request.addEventListener(SDK.NetworkRequest.Events.FinishedLoading, this.#refreshHeadersView, this);
|
176
|
+
this.#request.addEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this.#refreshHeadersView, this);
|
177
|
+
this.#request.addEventListener(SDK.NetworkRequest.Events.ResponseHeadersChanged, this.#refreshHeadersView, this);
|
176
178
|
this.#refreshHeadersView();
|
177
179
|
}
|
178
180
|
|
179
181
|
willHide(): void {
|
180
182
|
this.#request.removeEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this.#refreshHeadersView, this);
|
181
183
|
this.#request.removeEventListener(SDK.NetworkRequest.Events.FinishedLoading, this.#refreshHeadersView, this);
|
184
|
+
this.#request.removeEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this.#refreshHeadersView, this);
|
185
|
+
this.#request.removeEventListener(SDK.NetworkRequest.Events.ResponseHeadersChanged, this.#refreshHeadersView, this);
|
182
186
|
}
|
183
187
|
|
184
188
|
#refreshHeadersView(): void {
|
@@ -385,7 +389,10 @@ export class RequestHeadersComponent extends HTMLElement {
|
|
385
389
|
LitHtml.nothing
|
386
390
|
}${header.name}:
|
387
391
|
</div>
|
388
|
-
<div
|
392
|
+
<div
|
393
|
+
class="header-value ${header.headerValueIncorrect ? 'header-warning' : ''}"
|
394
|
+
@copy=${():void => Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue)}
|
395
|
+
>
|
389
396
|
${header.value?.toString() || ''}
|
390
397
|
${this.#maybeRenderHeaderValueSuffix(header)}
|
391
398
|
</div>
|
@@ -582,28 +589,43 @@ export class RequestHeadersComponent extends HTMLElement {
|
|
582
589
|
>
|
583
590
|
<div class="row">
|
584
591
|
<div class="header-name">${i18nString(UIStrings.requestUrl)}:</div>
|
585
|
-
<div
|
592
|
+
<div
|
593
|
+
class="header-value"
|
594
|
+
@copy=${():void => Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue)}
|
595
|
+
>${this.#request.url()}</div>
|
586
596
|
</div>
|
587
597
|
${this.#request.statusCode? html`
|
588
598
|
<div class="row">
|
589
599
|
<div class="header-name">${i18nString(UIStrings.requestMethod)}:</div>
|
590
|
-
<div
|
600
|
+
<div
|
601
|
+
class="header-value"
|
602
|
+
@copy=${():void => Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue)}
|
603
|
+
>${this.#request.requestMethod}</div>
|
591
604
|
</div>
|
592
605
|
<div class="row">
|
593
606
|
<div class="header-name">${i18nString(UIStrings.statusCode)}:</div>
|
594
|
-
<div
|
607
|
+
<div
|
608
|
+
class="header-value ${coloredCircleClassName} ${statusTextHasComment ? 'status-with-comment' : ''}"
|
609
|
+
@copy=${():void => Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue)}
|
610
|
+
>${statusText}</div>
|
595
611
|
</div>
|
596
612
|
` : ''}
|
597
613
|
${this.#request.remoteAddress()? html`
|
598
614
|
<div class="row">
|
599
615
|
<div class="header-name">${i18nString(UIStrings.remoteAddress)}:</div>
|
600
|
-
<div
|
616
|
+
<div
|
617
|
+
class="header-value"
|
618
|
+
@copy=${():void => Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue)}
|
619
|
+
>${this.#request.remoteAddress()}</div>
|
601
620
|
</div>
|
602
621
|
` : ''}
|
603
622
|
${this.#request.referrerPolicy()? html`
|
604
623
|
<div class="row">
|
605
624
|
<div class="header-name">${i18nString(UIStrings.referrerPolicy)}:</div>
|
606
|
-
<div
|
625
|
+
<div
|
626
|
+
class="header-value"
|
627
|
+
@copy=${():void => Host.userMetrics.actionTaken(Host.UserMetrics.Action.NetworkPanelCopyValue)}
|
628
|
+
>${this.#request.referrerPolicy()}</div>
|
607
629
|
</div>
|
608
630
|
` : ''}
|
609
631
|
</${Category.litTagName}>
|
@@ -125,6 +125,8 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
|
|
125
125
|
private messages: LogMessage[] = [];
|
126
126
|
private isRecording: boolean = false;
|
127
127
|
|
128
|
+
#historyAutocompleteDataProvider = new HistoryAutocompleteDataProvider();
|
129
|
+
|
128
130
|
constructor() {
|
129
131
|
super(true);
|
130
132
|
this.started = false;
|
@@ -303,21 +305,24 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
|
|
303
305
|
const shrinkFactor = 0.2;
|
304
306
|
const tooltip = i18nString(UIStrings.sendRawCDPCommandExplanation);
|
305
307
|
const input = new UI.Toolbar.ToolbarInput(
|
306
|
-
placeholder, accessiblePlaceholder, growFactor, shrinkFactor, tooltip,
|
308
|
+
placeholder, accessiblePlaceholder, growFactor, shrinkFactor, tooltip,
|
309
|
+
this.#historyAutocompleteDataProvider.buildTextPromptCompletions, false);
|
307
310
|
input.addEventListener(UI.Toolbar.ToolbarInput.Event.EnterPressed, () => this.#onCommandSend(input));
|
308
311
|
return input;
|
309
312
|
}
|
310
313
|
|
311
314
|
#onCommandSend(input: UI.Toolbar.ToolbarInput): void {
|
312
|
-
const
|
315
|
+
const value = input.value();
|
316
|
+
const {command, parameters} = parseCommandInput(value);
|
313
317
|
const test = ProtocolClient.InspectorBackend.test;
|
314
318
|
// TODO: TS thinks that properties are read-only because
|
315
319
|
// in TS test is defined as a namespace.
|
316
320
|
// @ts-ignore
|
317
321
|
test.sendRawMessage(command, parameters, () => {});
|
322
|
+
this.#historyAutocompleteDataProvider.addEntry(value);
|
318
323
|
}
|
319
324
|
|
320
|
-
static instance(opts = {forceNew: null}): ProtocolMonitorImpl {
|
325
|
+
static instance(opts: {forceNew: null|boolean} = {forceNew: null}): ProtocolMonitorImpl {
|
321
326
|
const {forceNew} = opts;
|
322
327
|
if (!protocolMonitorImplInstance || forceNew) {
|
323
328
|
protocolMonitorImplInstance = new ProtocolMonitorImpl();
|
@@ -487,6 +492,39 @@ export class ProtocolMonitorImpl extends UI.Widget.VBox {
|
|
487
492
|
}
|
488
493
|
}
|
489
494
|
|
495
|
+
export class HistoryAutocompleteDataProvider {
|
496
|
+
#maxHistorySize = 200;
|
497
|
+
#commandHistory = new Set<string>();
|
498
|
+
|
499
|
+
constructor(maxHistorySize?: number) {
|
500
|
+
if (maxHistorySize !== undefined) {
|
501
|
+
this.#maxHistorySize = maxHistorySize;
|
502
|
+
}
|
503
|
+
}
|
504
|
+
|
505
|
+
buildTextPromptCompletions =
|
506
|
+
async(expression: string, prefix: string, force?: boolean): Promise<UI.SuggestBox.Suggestions> => {
|
507
|
+
if (!prefix && !force && expression) {
|
508
|
+
return [];
|
509
|
+
}
|
510
|
+
const newestToOldest = [...this.#commandHistory].reverse();
|
511
|
+
return newestToOldest.filter(cmd => cmd.startsWith(prefix)).map(text => ({
|
512
|
+
text,
|
513
|
+
}));
|
514
|
+
};
|
515
|
+
|
516
|
+
addEntry(value: string): void {
|
517
|
+
if (this.#commandHistory.has(value)) {
|
518
|
+
this.#commandHistory.delete(value);
|
519
|
+
}
|
520
|
+
this.#commandHistory.add(value);
|
521
|
+
if (this.#commandHistory.size > this.#maxHistorySize) {
|
522
|
+
const earliestEntry = this.#commandHistory.values().next().value;
|
523
|
+
this.#commandHistory.delete(earliestEntry);
|
524
|
+
}
|
525
|
+
}
|
526
|
+
}
|
527
|
+
|
490
528
|
export class InfoWidget extends UI.Widget.VBox {
|
491
529
|
private readonly tabbedPane: UI.TabbedPane.TabbedPane;
|
492
530
|
constructor() {
|
@@ -89,7 +89,7 @@ export class TextPrompt extends Common.ObjectWrapper.ObjectWrapper<EventTypes> i
|
|
89
89
|
}
|
90
90
|
|
91
91
|
initialize(
|
92
|
-
completions: (this: null,
|
92
|
+
completions: (this: null, expression: string, filter: string, force?: boolean|undefined) => Promise<Suggestion[]>,
|
93
93
|
stopCharacters?: string, usesSuggestionBuilder?: boolean): void {
|
94
94
|
this.loadCompletions = completions;
|
95
95
|
this.completionStopCharacters = stopCharacters || ' =:[({;,!+-*/&|^<>.';
|
package/package.json
CHANGED