Skip to content

Commit 094b6c3

Browse files
jalonthomasDevtools-frontend LUCI CQ
authored andcommitted
Add filtering for name and domain in the Cookie Report table
Filter behavior: http://go/scrcast/NjAwMzk2NTE3ODE1MDkxMnwxM2RiODNiMi0wYQ Bug: 395067568 Change-Id: I9695a76744334dc114cc91f243b8004ca8fa4f9f Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6253558 Reviewed-by: Paul Irish <[email protected]> Reviewed-by: Danil Somsikov <[email protected]> Commit-Queue: Jalon Thomas <[email protected]>
1 parent 9ddeb25 commit 094b6c3

File tree

5 files changed

+111
-12
lines changed

5 files changed

+111
-12
lines changed

front_end/panels/security/CookieReportView.ts

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import '../../ui/legacy/components/data_grid/data_grid.js';
66

77
import * as Common from '../../core/common/common.js';
88
import * as i18n from '../../core/i18n/i18n.js';
9+
import * as Platform from '../../core/platform/platform.js';
910
import * as SDK from '../../core/sdk/sdk.js';
1011
import * as Protocol from '../../generated/protocol.js';
1112
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
13+
import type * as TextUtils from '../../models/text_utils/text_utils.js';
1214
import * as UI from '../../ui/legacy/legacy.js';
1315
import * as Lit from '../../ui/lit/lit.js';
1416
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
@@ -188,6 +190,9 @@ export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
188190
export interface ViewInput {
189191
cookieRows: IssuesManager.CookieIssue.CookieReportInfo[];
190192
filterItems: UI.FilterBar.Item[];
193+
filters: TextUtils.TextUtils.ParsedFilter[];
194+
searchText: string;
195+
onSearchFilterChanged: (e: CustomEvent<string>) => void;
191196
onFilterChanged: () => void;
192197
onSortingChanged: () => void;
193198
populateContextMenu: (event: CustomEvent<{menu: UI.ContextMenu.ContextMenu, element: HTMLElement}>) => void;
@@ -213,6 +218,7 @@ export class CookieReportView extends UI.Widget.VBox {
213218
#cookieRows = new Map<string, IssuesManager.CookieIssue.CookieReportInfo>();
214219
#view: View;
215220
filterItems: UI.FilterBar.Item[] = [];
221+
searchText: string;
216222

217223
constructor(element?: HTMLElement, view: View = (input, output, target) => {
218224
// clang-format off
@@ -224,21 +230,32 @@ export class CookieReportView extends UI.Widget.VBox {
224230
</div>
225231
${input.cookieRows.length > 0 ?
226232
html`
227-
<devtools-named-bit-set-filter
228-
class="filter"
229-
aria-label="Third-party cookie status filters"
230-
@filterChanged=${input.onFilterChanged}
231-
.options=${{items: input.filterItems}}
232-
${ref((el?: Element) => {
233-
if(el instanceof UI.FilterBar.NamedBitSetFilterUIElement){
234-
output.namedBitSetFilterUI = el.getOrCreateNamedBitSetFilterUI();
235-
}
236-
})}
237-
></devtools-named-bit-set-filter>
233+
<div class="filters-container">
234+
<devtools-toolbar>
235+
<devtools-toolbar-input
236+
type="filter"
237+
style="flex-grow: 0.4;"
238+
@change=${input.onSearchFilterChanged}
239+
value=${input.searchText}
240+
></devtools-toolbar-input>
241+
</devtools-toolbar>
242+
<devtools-named-bit-set-filter
243+
class="filter"
244+
aria-label="Third-party cookie status filters"
245+
@filterChanged=${input.onFilterChanged}
246+
.options=${{items: input.filterItems}}
247+
${ref((el?: Element) => {
248+
if(el instanceof UI.FilterBar.NamedBitSetFilterUIElement){
249+
output.namedBitSetFilterUI = el.getOrCreateNamedBitSetFilterUI();
250+
}
251+
})}
252+
></devtools-named-bit-set-filter>
253+
</div>
238254
<!-- @ts-ignore -->
239255
<devtools-data-grid
240256
name=${i18nString(UIStrings.report)}
241257
striped
258+
.filters=${input.filters}
242259
@sort=${input.onSortingChanged}
243260
@contextmenu=${input.populateContextMenu.bind(input)}
244261
>
@@ -287,6 +304,7 @@ export class CookieReportView extends UI.Widget.VBox {
287304
super(true, undefined, element);
288305
this.#view = view;
289306
this.registerRequiredCSS(cookieReportViewStyles);
307+
this.searchText = Common.Settings.Settings.instance().createSetting('cookie-report-search-query', '').get();
290308

291309
SDK.TargetManager.TargetManager.instance().addModelListener(
292310
SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,
@@ -313,7 +331,14 @@ export class CookieReportView extends UI.Widget.VBox {
313331
}
314332
return true;
315333
}),
334+
filters: [{
335+
key: 'name,domain',
336+
regex: RegExp(Platform.StringUtilities.escapeForRegExp(this.searchText), 'i'),
337+
negative: false,
338+
}],
339+
searchText: this.searchText,
316340
filterItems: this.filterItems,
341+
onSearchFilterChanged: (e: CustomEvent<string>) => this.onSearchFilterChanged(e),
317342
onFilterChanged: () => this.requestUpdate(),
318343
onSortingChanged: () => this.requestUpdate(),
319344
populateContextMenu: this.populateContextMenu.bind(this),
@@ -344,6 +369,12 @@ export class CookieReportView extends UI.Widget.VBox {
344369
}
345370
}
346371

372+
onSearchFilterChanged(e: CustomEvent<string>): void {
373+
this.searchText = e.detail ? e.detail : '';
374+
Common.Settings.Settings.instance().createSetting('cookie-report-search-query', '').set(this.searchText);
375+
this.requestUpdate();
376+
}
377+
347378
#buildFilterItems(): UI.FilterBar.Item[] {
348379
const filterItems: UI.FilterBar.Item[] = [];
349380

front_end/panels/security/cookieReportView.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,15 @@
4040
}
4141

4242
.filter {
43-
padding-left: var(--sys-size-5);
4443
padding-right: var(--sys-size-6);
4544
flex-shrink: 0;
4645
}
4746

47+
.filters-container {
48+
display: flex;
49+
padding-left: var(--sys-size-5);
50+
}
51+
4852
devtools-data-grid {
4953
flex: auto;
5054
margin-left: -1px;

front_end/ui/legacy/Toolbar.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,7 @@ class ToolbarInputElement extends HTMLElement {
864864

865865
item!: ToolbarInput;
866866
datalist: HTMLDataListElement|null = null;
867+
value: string|undefined = undefined;
867868

868869
connectedCallback(): void {
869870
if (this.item) {
@@ -889,6 +890,9 @@ class ToolbarInputElement extends HTMLElement {
889890
/* shrinkFactor=*/ undefined, tooltip, this.datalist ? this.#onAutocomplete.bind(this) : undefined,
890891
/* dynamicCompletions=*/ undefined, jslogContext, this);
891892
}
893+
if (this.value) {
894+
this.item.setValue(this.value);
895+
}
892896
this.item.addEventListener(ToolbarInput.Event.TEXT_CHANGED, event => {
893897
this.dispatchEvent(new CustomEvent('change', {detail: event.data}));
894898
});
@@ -910,6 +914,8 @@ class ToolbarInputElement extends HTMLElement {
910914
if (name === 'value') {
911915
if (this.item && this.item.value() !== newValue) {
912916
this.item.setValue(newValue, true);
917+
} else {
918+
this.value = newValue;
913919
}
914920
}
915921
}

front_end/ui/visual_logging/KnownContextValues.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ export const knownContextValues = new Set([
876876
'cookie-flag-controls',
877877
'cookie-preview',
878878
'cookie-report',
879+
'cookie-report-search-query',
879880
'cookie-view-show-decoded',
880881
'cookies',
881882
'cookies-data',

test/e2e/security/privacy_test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// Copyright 2020 The Chromium Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4+
import {assert} from 'chai';
45

56
import {expectError} from '../../conductor/events.js';
67
import {click, getBrowserAndPages, waitForAria} from '../../shared/helper.js';
78
import {reloadDevTools} from '../helpers/cross-tool-helper.js';
9+
import {getDataGridRows} from '../helpers/datagrid-helpers.js';
810
import {
911
navigateToSecurityTab,
1012
} from '../helpers/security-helpers.js';
@@ -50,4 +52,59 @@ describe('The Privacy and security panel', function() {
5052
// Infobar should be gone after clicking the close button
5153
infoBar.evaluate(el => assert.isNotNull(el));
5254
});
55+
56+
it('filters rows when the search filter is populated', async () => {
57+
await navigateToSecurityTab(/* privcayEnabled=*/ true);
58+
await click('[aria-label="Third-party cookies"]');
59+
60+
// Populate with test issues to be filtered
61+
const {frontend} = getBrowserAndPages();
62+
frontend.evaluate(() => {
63+
const issue1 = {
64+
code: 'CookieIssue',
65+
details: {
66+
cookieIssueDetails: {
67+
cookie: {
68+
name: 'a',
69+
path: '/',
70+
domain: 'a.test',
71+
},
72+
cookieExclusionReasons: ['ExcludeThirdPartyPhaseout'],
73+
cookieWarningReasons: [],
74+
operation: 'ReadCookie',
75+
cookieUrl: 'a.test',
76+
},
77+
},
78+
};
79+
// @ts-expect-error
80+
window.addIssueForTest(issue1);
81+
82+
const issue2 = {
83+
code: 'CookieIssue',
84+
details: {
85+
cookieIssueDetails: {
86+
cookie: {
87+
name: 'b',
88+
path: '/',
89+
domain: 'b.test',
90+
},
91+
cookieExclusionReasons: ['ExcludeThirdPartyPhaseout'],
92+
cookieWarningReasons: [],
93+
operation: 'ReadCookie',
94+
cookieUrl: 'b.test',
95+
},
96+
},
97+
};
98+
// @ts-expect-error
99+
window.addIssueForTest(issue2);
100+
});
101+
assert.lengthOf(await getDataGridRows(2, undefined, true), 2);
102+
103+
const searchFilter = await waitForAria('Filter');
104+
searchFilter.evaluate(el => assert.isNotNull(el));
105+
searchFilter.type('a.test');
106+
107+
// The second issue should be filtered out.
108+
assert.lengthOf(await getDataGridRows(1, undefined, true), 1);
109+
});
53110
});

0 commit comments

Comments
 (0)