[issues] Link raw cookie lines to network panel
This CL adds a new network filter that allows users to search for
requests where the response includes a specified value in the
`Set-Cookie` header.
The issues panel uses the new filter to link issues with raw
cookie lines back to the network panel (should the issue be
associated with a network request).
Screenshots: https://imgur.com/a/zVZNrK1
[email protected]
Bug: 1179186
Change-Id: I9e275d31676a67a1b197c9aa195b65a144caeebf
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3068920
Commit-Queue: Simon Zünd <[email protected]>
Reviewed-by: Sigurd Schneider <[email protected]>
diff --git a/front_end/core/i18n/locales/en-US.json b/front_end/core/i18n/locales/en-US.json
index 658fb54..5433815 100644
--- a/front_end/core/i18n/locales/en-US.json
+++ b/front_end/core/i18n/locales/en-US.json
@@ -4742,6 +4742,9 @@
"panels/issues/AffectedCookiesView.ts | domain": {
"message": "Domain"
},
+ "panels/issues/AffectedCookiesView.ts | filterSetCookieTitle": {
+ "message": "Show network requests that include this Set-Cookie header in the network panel"
+ },
"panels/issues/AffectedCookiesView.ts | name": {
"message": "Name"
},
diff --git a/front_end/core/i18n/locales/en-XL.json b/front_end/core/i18n/locales/en-XL.json
index 26a94df..f64dbe7 100644
--- a/front_end/core/i18n/locales/en-XL.json
+++ b/front_end/core/i18n/locales/en-XL.json
@@ -4742,6 +4742,9 @@
"panels/issues/AffectedCookiesView.ts | domain": {
"message": "D̂óm̂áîń"
},
+ "panels/issues/AffectedCookiesView.ts | filterSetCookieTitle": {
+ "message": "Ŝh́ôẃ n̂ét̂ẃôŕk̂ ŕêq́ûéŝt́ŝ t́ĥát̂ ín̂ćl̂úd̂é t̂h́îś Set-Cookie ĥéâd́êŕ îń t̂h́ê ńêt́ŵór̂ḱ p̂án̂él̂"
+ },
"panels/issues/AffectedCookiesView.ts | name": {
"message": "N̂ám̂é"
},
diff --git a/front_end/panels/issues/AffectedCookiesView.ts b/front_end/panels/issues/AffectedCookiesView.ts
index 029a851..1f401c7 100644
--- a/front_end/panels/issues/AffectedCookiesView.ts
+++ b/front_end/panels/issues/AffectedCookiesView.ts
@@ -34,6 +34,10 @@
*@description Label for the the number of affected `Set-Cookie` lines associated with a DevTools issue. `Set-Cookie` is a specific header line in an HTTP network request and consists of a single line of text.
*/
nRawCookieLines: '{n, plural, =1 {1 Raw `Set-Cookie` header} other {# Raw `Set-Cookie` headers}}',
+ /**
+ *@description Title for text button in the Issues panel. Clicking the button navigates the user to the Network Panel. `Set-Cookie` is a specific header line in an HTTP network request and consists of a single line of text.
+ */
+ filterSetCookieTitle: 'Show network requests that include this `Set-Cookie` header in the network panel',
};
const str_ = i18n.i18n.registerUIStrings('panels/issues/AffectedCookiesView.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -117,13 +121,31 @@
override update(): void {
this.clear();
- const rawCookieLines = this.issue.getRawCookieLines();
- for (const rawCookieLine of rawCookieLines) {
+ const cookieLinesWithRequestIndicator = this.issue.getRawCookieLines();
+ let count = 0;
+
+ for (const cookie of cookieLinesWithRequestIndicator) {
const row = document.createElement('tr');
row.classList.add('affected-resource-directive');
- this.appendIssueDetailCell(row, rawCookieLine);
+ if (cookie.hasRequest) {
+ const cookieLine = document.createElement('td');
+ const textButton = UI.UIUtils.createTextButton(cookie.rawCookieLine, () => {
+ Common.Revealer.reveal(NetworkForward.UIFilter.UIRequestFilter.filters([
+ {
+ filterType: NetworkForward.UIFilter.FilterType.ResponseHeaderValueSetCookie,
+ filterValue: cookie.rawCookieLine,
+ },
+ ]));
+ }, 'link-style devtools-link');
+ textButton.title = i18nString(UIStrings.filterSetCookieTitle);
+ cookieLine.appendChild(textButton);
+ row.appendChild(cookieLine);
+ } else {
+ this.appendIssueDetailCell(row, cookie.rawCookieLine);
+ }
this.affectedResources.appendChild(row);
+ count++;
}
- this.updateAffectedResourceCount(rawCookieLines.size);
+ this.updateAffectedResourceCount(count);
}
}
diff --git a/front_end/panels/issues/IssueAggregator.ts b/front_end/panels/issues/IssueAggregator.ts
index 885a22d..762332d 100644
--- a/front_end/panels/issues/IssueAggregator.ts
+++ b/front_end/panels/issues/IssueAggregator.ts
@@ -16,7 +16,7 @@
cookie: Protocol.Audits.AffectedCookie,
hasRequest: boolean,
}>();
- private affectedRawCookieLines = new Set<string>();
+ private affectedRawCookieLines = new Map<string, {rawCookieLine: string, hasRequest: boolean}>();
private affectedRequests = new Map<string, Protocol.Audits.AffectedRequest>();
private affectedLocations = new Map<string, Protocol.Audits.SourceCodeLocation>();
private heavyAdIssues = new Set<IssuesManager.HeavyAdIssue.HeavyAdIssue>();
@@ -47,8 +47,8 @@
return Array.from(this.affectedCookies.values()).map(x => x.cookie);
}
- getRawCookieLines(): ReadonlySet<string> {
- return this.affectedRawCookieLines;
+ getRawCookieLines(): Iterable<{rawCookieLine: string, hasRequest: boolean}> {
+ return this.affectedRawCookieLines.values();
}
sources(): Iterable<Protocol.Audits.SourceCodeLocation> {
@@ -154,7 +154,9 @@
}
}
for (const rawCookieLine of issue.rawCookieLines()) {
- this.affectedRawCookieLines.add(rawCookieLine);
+ if (!this.affectedRawCookieLines.has(rawCookieLine)) {
+ this.affectedRawCookieLines.set(rawCookieLine, {rawCookieLine, hasRequest});
+ }
}
for (const location of issue.sources()) {
const key = JSON.stringify(location);
diff --git a/front_end/panels/network/NetworkLogView.ts b/front_end/panels/network/NetworkLogView.ts
index 2ba36dc..5e14fb8 100644
--- a/front_end/panels/network/NetworkLogView.ts
+++ b/front_end/panels/network/NetworkLogView.ts
@@ -620,6 +620,12 @@
return request.responseHeaderValue(value) !== undefined;
}
+ static _requestResponseHeaderSetCookieFilter(value: string, request: SDK.NetworkRequest.NetworkRequest): boolean {
+ // Multiple Set-Cookie headers in the request are concatenated via space. Only
+ // filter via `includes` instead of strict equality.
+ return Boolean(request.responseHeaderValue('Set-Cookie')?.includes(value));
+ }
+
static _requestMethodFilter(value: string, request: SDK.NetworkRequest.NetworkRequest): boolean {
return request.requestMethod === value;
}
@@ -1431,8 +1437,11 @@
}
const responseHeaders = request.responseHeaders;
- for (let i = 0, l = responseHeaders.length; i < l; ++i) {
- this._suggestionBuilder.addItem(NetworkForward.UIFilter.FilterType.HasResponseHeader, responseHeaders[i].name);
+ for (const responseHeader of responseHeaders) {
+ this._suggestionBuilder.addItem(NetworkForward.UIFilter.FilterType.HasResponseHeader, responseHeader.name);
+ if (responseHeader.name === 'Set-Cookie') {
+ this._suggestionBuilder.addItem(NetworkForward.UIFilter.FilterType.ResponseHeaderValueSetCookie);
+ }
}
for (const cookie of request.responseCookies) {
@@ -1734,6 +1743,9 @@
case NetworkForward.UIFilter.FilterType.HasResponseHeader:
return NetworkLogView._requestResponseHeaderFilter.bind(null, value);
+ case NetworkForward.UIFilter.FilterType.ResponseHeaderValueSetCookie:
+ return NetworkLogView._requestResponseHeaderSetCookieFilter.bind(null, value);
+
case NetworkForward.UIFilter.FilterType.Is:
if (value.toLowerCase() === NetworkForward.UIFilter.IsFilterType.Running) {
return NetworkLogView._runningRequestFilter;
diff --git a/front_end/panels/network/forward/UIFilter.ts b/front_end/panels/network/forward/UIFilter.ts
index d3c4a9b..db9a497 100644
--- a/front_end/panels/network/forward/UIFilter.ts
+++ b/front_end/panels/network/forward/UIFilter.ts
@@ -7,6 +7,7 @@
export enum FilterType {
Domain = 'domain',
HasResponseHeader = 'has-response-header',
+ ResponseHeaderValueSetCookie = 'response-header-set-cookie',
Is = 'is',
LargerThan = 'larger-than',
Method = 'method',