From 2a6c6edb4fcb12a0b4fbcfc2a8765e200ae6955f Mon Sep 17 00:00:00 2001 From: Kudaligi Amoghavarsha Date: Fri, 2 Aug 2024 20:53:37 +0530 Subject: [PATCH 1/6] Fix: QA issues on v0.10 (#795) * Fix tabFrames calculation in the report. * Remove unwanted `. * Add unknown to the analytics. * Change httpOnly to httponly. * Fix http only filter sorting. * Fix types that break the build. * Remove animation which used to delay thecolor updation. * Add darkmode for report. * Add darkmode for extension report. * Fix white color. * Fix empty circle color. * Center align section, add text for zero blocked cookies, update header dark color * Fix failing test. * Fix failing test. * Add httonly to js cookies in cli. * Move generateTableCSV to common folder and reuse it. * Fix file naming and import. * Fix build breaking. * Make samesite lowercase default. Use samesite instead of sameSite. * Use lax bydefault. * Fix failing tests. * Fix failing text. * Fix command in the workflow doc. * Fix command in the workflow doc. * Fix sameSite attribute. * Use i18n for samesite in CSV and update key in hook * Update comparator * Update comparator * Fix the csv sanitisation. * Fix failing tests. * Fix sanitisation of records and fix failing tests * Add edgecase data to cli-dashboard. --------- Co-authored-by: Mayank Rana --- docs/development-workflows.md | 2 +- .../src/browserManagement/index.ts | 13 +- packages/analysis-utils/src/types.ts | 2 +- packages/cli-dashboard/src/app.tsx | 6 +- .../cli-dashboard/src/dummyData/PSAT_DATA.js | 145 ++++++++++++++++++ packages/common/src/cookies.types.ts | 4 +- .../common/src/utils/findAnalyticsMatch.ts | 2 +- .../generateReports/generateAllCookiesCSV.ts | 65 ++------ .../generateCLICookieTableCSV.ts | 22 ++- .../generateCookiesWithIssuesCSV.ts | 4 +- .../generateExtensionCookietableCSV.ts} | 21 ++- .../common/src/utils/generateReports/index.ts | 2 + .../utils/parseRequestWillBeSentExtraInfo.ts | 2 +- .../utils/parseResponseReceivedExtraInfo.ts | 2 +- .../common/src/utils/sanitizeCsvRecord.ts | 4 +- .../src/utils/tests/sanitizeCsvRecords.ts | 2 +- .../circlePieChart/emptyCirclePieChart.tsx | 2 +- .../src/components/circlePieChart/index.tsx | 1 - .../cookieTable/utils/exportCookies.ts | 6 +- .../cookiesLanding/landingHeader/index.tsx | 4 +- .../src/components/table/utils/index.ts | 3 - ...rameStatsComponentForExtensionDashboard.ts | 37 ++++- packages/extension/src/contentScript/types.ts | 12 ++ .../src/serviceWorker/createCookieObject.ts | 2 +- .../parseResponseCookieHeader.ts | 7 + .../tests/parseRequestCookieHeader.ts | 8 +- .../src/store/synchnorousCookieStore.ts | 5 + .../src/utils/createCookieFromAuditsIssue.ts | 2 + .../src/utils/parseNetworkCookies.ts | 2 +- .../utils/processAndStoreDocumentCookies.ts | 15 +- .../extension/src/utils/tests/parseHeaders.ts | 14 +- .../cookieLanding/blockedCookiesSection.tsx | 2 + .../cookiesListing/useCookieListing/index.tsx | 2 +- .../tests/useCookieListing.tsx | 9 ++ .../src/view/report/dashboardApp.tsx | 4 + .../i18n/_locales/messages/en/messages.json | 2 +- .../src/dashboard/components/header/index.tsx | 2 +- .../components/siteMapReport/layout.tsx | 2 +- .../siteReport/components/layout.tsx | 2 +- .../cookieLanding/blockedCookiesSection.tsx | 6 + .../cookieLanding/framesSection.tsx | 11 +- .../cookieLanding/landing.tsx | 4 + .../cookies/cookiesLandingContainer/index.tsx | 1 - .../components/utils/tests/data.mock.ts | 12 +- .../components/utils/tests/extractCookies.ts | 8 +- .../utils/tests/extractReportData.ts | 4 +- .../components/utils/tests/reshapeCookies.ts | 8 +- .../hooks/useCookieListing/index.tsx | 6 +- 48 files changed, 365 insertions(+), 138 deletions(-) rename packages/{design-system/src/components/table/utils => common/src/utils/generateReports}/generateCLICookieTableCSV.ts (82%) rename packages/{design-system/src/components/table/utils/generatExtensionCookietableCSV.ts => common/src/utils/generateReports/generateExtensionCookietableCSV.ts} (84%) diff --git a/docs/development-workflows.md b/docs/development-workflows.md index 6e78761d8..95ff168ea 100644 --- a/docs/development-workflows.md +++ b/docs/development-workflows.md @@ -41,7 +41,7 @@ npm run dev:cli After making changes in the `cli`, `cli-dashboard`, or any CLI-related packages, use: ```bash -npm run build:cli +npm run build:cli:dashboard ``` ## Build Workflows diff --git a/packages/analysis-utils/src/browserManagement/index.ts b/packages/analysis-utils/src/browserManagement/index.ts index e0b12366d..e24d30aac 100644 --- a/packages/analysis-utils/src/browserManagement/index.ts +++ b/packages/analysis-utils/src/browserManagement/index.ts @@ -334,7 +334,7 @@ export class BrowserManagement { domain: parsedCookie.domain, path: parsedCookie.path || '/', value: parsedCookie.value, - samesite: parsedCookie.samesite || 'Lax', + samesite: parsedCookie.samesite?.toLowerCase() || 'lax', expires: parsedCookie.expires || 'Session', httponly: parsedCookie.httponly || false, secure: parsedCookie.secure || false, @@ -407,9 +407,9 @@ export class BrowserManagement { domain: associatedCookie.cookie.domain, path: associatedCookie.cookie.path || '/', value: associatedCookie.cookie.value, - sameSite: associatedCookie.cookie.sameSite || 'Lax', + samesite: associatedCookie.cookie.sameSite?.toLowerCase() || 'lax', expires: associatedCookie.cookie.expires || 'Session', - httpOnly: associatedCookie.cookie.httpOnly || false, + httponly: associatedCookie.cookie.httpOnly || false, secure: associatedCookie.cookie.secure || false, partitionKey: '', }, @@ -562,7 +562,12 @@ export class BrowserManagement { } const key = cookie.name + ':' + cookie.domain + ':' + cookie.path; frameCookies[key] = { - parsedCookie: { ...cookie, partitionKey: '' }, + parsedCookie: { + ...cookie, + partitionKey: '', + httponly: false, + samesite: cookie.sameSite?.toLowerCase() || 'lax', + }, }; }); diff --git a/packages/analysis-utils/src/types.ts b/packages/analysis-utils/src/types.ts index be4d567e2..1ab5025aa 100644 --- a/packages/analysis-utils/src/types.ts +++ b/packages/analysis-utils/src/types.ts @@ -56,7 +56,7 @@ export interface CookieLogDetails category: string; description: string; isFirstParty: 'Yes' | 'No'; - sameSite: string; + samesite: string; partitionKey?: Protocol.Network.CookiePartitionKey; pageUrl: string; requestUrls: { [key: string]: string }; diff --git a/packages/cli-dashboard/src/app.tsx b/packages/cli-dashboard/src/app.tsx index 99148307b..c0cb12fd5 100644 --- a/packages/cli-dashboard/src/app.tsx +++ b/packages/cli-dashboard/src/app.tsx @@ -60,6 +60,10 @@ const App = () => { return; } + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + bodyTag.classList.add('dark'); + } + bodyTag.style.fontSize = '75%'; }, []); @@ -130,7 +134,7 @@ const App = () => { } return ( -
+
{ }; export const emptyAnalytics = { - platform: '', + platform: 'Unknown', category: 'Uncategorized', name: '', domain: '', diff --git a/packages/common/src/utils/generateReports/generateAllCookiesCSV.ts b/packages/common/src/utils/generateReports/generateAllCookiesCSV.ts index 117d3b382..718406a1b 100644 --- a/packages/common/src/utils/generateReports/generateAllCookiesCSV.ts +++ b/packages/common/src/utils/generateReports/generateAllCookiesCSV.ts @@ -17,16 +17,17 @@ /** * External dependencies */ -import sanitizeCsvRecord from '../sanitizeCsvRecord'; import { I18n } from '@google-psat/i18n'; /** * Internal dependencies */ import { + CookieTableData, type CompleteJson, type CookieJsonDataType, } from '../../cookies.types'; -import calculateEffectiveExpiryDate from '../calculateEffectiveExpiryDate'; +import generateExtensionCookieTableCSV from './generateExtensionCookietableCSV'; +import generateCLICookieTableCSV from './generateCLICookieTableCSV'; export const COOKIES_DATA_HEADER = [ () => I18n.getMessage('name'), @@ -59,61 +60,19 @@ const generateAllCookiesCSV = (siteAnalysisData: CompleteJson): string => { }); }); - if (isExtension) { - COOKIES_DATA_HEADER.push( - () => I18n.getMessage('priority'), - () => I18n.getMessage('size') - ); - } - - let cookieRecords = ''; + const cookieRecords: CookieTableData[] = []; for (const cookie of cookieMap.values()) { - //This should be in the same order as cookieDataHeader - const expires = calculateEffectiveExpiryDate(cookie.parsedCookie.expires); - - const recordsArray = [ - cookie.parsedCookie.name, - cookie.isFirstParty - ? I18n.getMessage('firstParty') - : I18n.getMessage('thirdParty'), - cookie.parsedCookie.domain || ' ', - cookie.parsedCookie.partitionKey || ' ', - cookie.parsedCookie.sameSite, - I18n.getMessage( - cookie.analytics?.category?.toLowerCase() || 'uncategorized' - ), - cookie.analytics.platform, - cookie.parsedCookie.httpOnly - ? I18n.getMessage('yes') - : I18n.getMessage('no'), - cookie.parsedCookie.secure - ? I18n.getMessage('yes') - : I18n.getMessage('no'), - cookie.parsedCookie.value, - cookie.parsedCookie.path, - expires === 'Session' ? I18n.getMessage('session') : expires, - cookie.isBlocked ? I18n.getMessage('yes') : I18n.getMessage('no'), - cookie.analytics.GDPR || 'NA', - ]; - - if (isExtension) { - recordsArray.push( - I18n.getMessage((cookie.parsedCookie?.priority || ' ').toLowerCase()), - cookie.parsedCookie?.size?.toString() ?? ' ' - ); - } - - recordsArray.map(sanitizeCsvRecord); - - cookieRecords += recordsArray.join(',') + '\r\n'; + //@ts-ignore + cookieRecords.push(cookie); + } + if (isExtension) { + return generateExtensionCookieTableCSV(cookieRecords, true) as string; + } else { + return generateCLICookieTableCSV(cookieRecords, true) as string; } - return ( - COOKIES_DATA_HEADER.map((header) => header()).join(',') + - '\r\n' + - cookieRecords - ); + return ''; }; export default generateAllCookiesCSV; diff --git a/packages/design-system/src/components/table/utils/generateCLICookieTableCSV.ts b/packages/common/src/utils/generateReports/generateCLICookieTableCSV.ts similarity index 82% rename from packages/design-system/src/components/table/utils/generateCLICookieTableCSV.ts rename to packages/common/src/utils/generateReports/generateCLICookieTableCSV.ts index f8b386167..ebdfce65a 100644 --- a/packages/design-system/src/components/table/utils/generateCLICookieTableCSV.ts +++ b/packages/common/src/utils/generateReports/generateCLICookieTableCSV.ts @@ -16,8 +16,12 @@ /** * External dependencies. */ -import { type CookieTableData, sanitizeCsvRecord } from '@google-psat/common'; import { I18n } from '@google-psat/i18n'; +/** + * Internal dependencies. + */ +import sanitizeCsvRecord from '../sanitizeCsvRecord'; +import { type CookieTableData } from '../../cookies.types'; const COOKIES_TABLE_DATA_HEADER_CLI = [ () => I18n.getMessage('name'), @@ -36,7 +40,10 @@ const COOKIES_TABLE_DATA_HEADER_CLI = [ () => I18n.getMessage('gdpr'), ]; -const generateCLICookieTableCSV = (cookies: CookieTableData[]): Blob => { +const generateCLICookieTableCSV = ( + cookies: CookieTableData[], + returnString = false +): Blob | string => { let cookieRecords = ''; for (const cookie of cookies) { @@ -48,8 +55,7 @@ const generateCLICookieTableCSV = (cookies: CookieTableData[]): Blob => { : I18n.getMessage('thirdParty'), cookie.parsedCookie.domain || ' ', cookie.parsedCookie.partitionKey || ' ', - //@ts-ignore - cookie.parsedCookie?.sameSite ?? cookie.parsedCookie?.samesite, + I18n.getMessage((cookie.parsedCookie?.samesite ?? 'lax').toLowerCase()), I18n.getMessage( cookie.analytics?.category?.toLowerCase() || 'uncategorized' ), @@ -70,6 +76,14 @@ const generateCLICookieTableCSV = (cookies: CookieTableData[]): Blob => { cookieRecords += recordsArray.join(',') + '\r\n'; } + if (returnString) { + return ( + COOKIES_TABLE_DATA_HEADER_CLI.map((header) => header()).join(',') + + '\r\n' + + cookieRecords + ); + } + return new Blob([ COOKIES_TABLE_DATA_HEADER_CLI.map((header) => header()).join(',') + '\r\n' + diff --git a/packages/common/src/utils/generateReports/generateCookiesWithIssuesCSV.ts b/packages/common/src/utils/generateReports/generateCookiesWithIssuesCSV.ts index fa5c5ef30..dddab4556 100644 --- a/packages/common/src/utils/generateReports/generateCookiesWithIssuesCSV.ts +++ b/packages/common/src/utils/generateReports/generateCookiesWithIssuesCSV.ts @@ -78,12 +78,12 @@ const generateCookiesWithIssuesCSV = ( : I18n.getMessage('thirdParty'), cookie.parsedCookie.domain || ' ', cookie.parsedCookie.partitionKey || ' ', - cookie.parsedCookie.sameSite, + I18n.getMessage((cookie.parsedCookie.samesite ?? 'lax').toLowerCase()), I18n.getMessage( cookie.analytics?.category?.toLowerCase() || 'uncategorized' ), cookie.analytics.platform, - cookie.parsedCookie.httpOnly + cookie.parsedCookie.httponly ? I18n.getMessage('yes') : I18n.getMessage('no'), cookie.parsedCookie.secure diff --git a/packages/design-system/src/components/table/utils/generatExtensionCookietableCSV.ts b/packages/common/src/utils/generateReports/generateExtensionCookietableCSV.ts similarity index 84% rename from packages/design-system/src/components/table/utils/generatExtensionCookietableCSV.ts rename to packages/common/src/utils/generateReports/generateExtensionCookietableCSV.ts index 945379372..9b6683e10 100644 --- a/packages/design-system/src/components/table/utils/generatExtensionCookietableCSV.ts +++ b/packages/common/src/utils/generateReports/generateExtensionCookietableCSV.ts @@ -16,8 +16,12 @@ /** * External dependencies. */ -import { type CookieTableData, sanitizeCsvRecord } from '@google-psat/common'; import { I18n } from '@google-psat/i18n'; +/** + * Internal dependencies. + */ +import sanitizeCsvRecord from '../sanitizeCsvRecord'; +import { type CookieTableData } from '../../cookies.types'; const COOKIES_TABLE_DATA_HEADER_EXTENSION = [ () => I18n.getMessage('name'), @@ -38,7 +42,10 @@ const COOKIES_TABLE_DATA_HEADER_EXTENSION = [ () => I18n.getMessage('size'), ]; -const generateExtensionCookieTableCSV = (cookies: CookieTableData[]): Blob => { +const generateExtensionCookieTableCSV = ( + cookies: CookieTableData[], + returnString = false +): Blob | string => { let cookieRecords = ''; for (const cookie of cookies) { @@ -50,7 +57,7 @@ const generateExtensionCookieTableCSV = (cookies: CookieTableData[]): Blob => { : I18n.getMessage('thirdParty'), cookie.parsedCookie.domain || ' ', cookie.parsedCookie.partitionKey || ' ', - cookie.parsedCookie.samesite, + I18n.getMessage((cookie.parsedCookie.samesite ?? 'lax').toLowerCase()), I18n.getMessage( cookie.analytics?.category?.toLowerCase() || 'uncategorized' ), @@ -75,6 +82,14 @@ const generateExtensionCookieTableCSV = (cookies: CookieTableData[]): Blob => { cookieRecords += recordsArray.join(',') + '\r\n'; } + if (returnString) { + return ( + COOKIES_TABLE_DATA_HEADER_EXTENSION.map((header) => header()).join(',') + + '\r\n' + + cookieRecords + ); + } + return new Blob([ COOKIES_TABLE_DATA_HEADER_EXTENSION.map((header) => header()).join(',') + '\r\n' + diff --git a/packages/common/src/utils/generateReports/index.ts b/packages/common/src/utils/generateReports/index.ts index 75a64d39b..d4c377694 100644 --- a/packages/common/src/utils/generateReports/index.ts +++ b/packages/common/src/utils/generateReports/index.ts @@ -18,3 +18,5 @@ export { default as generateCookiesWithIssuesCSV } from './generateCookiesWithIs export { default as generateAllCookiesCSV } from './generateAllCookiesCSV'; export { default as generateSummaryDataCSV } from './generateSummaryDataCSV'; export { default as generateTechnologyCSV } from './generateTechnologyCSV'; +export { default as generateCLICookieTableCSV } from './generateCLICookieTableCSV'; +export { default as generateExtensionCookieTableCSV } from './generateExtensionCookietableCSV'; diff --git a/packages/common/src/utils/parseRequestWillBeSentExtraInfo.ts b/packages/common/src/utils/parseRequestWillBeSentExtraInfo.ts index 072d04d3a..c74ea54ef 100644 --- a/packages/common/src/utils/parseRequestWillBeSentExtraInfo.ts +++ b/packages/common/src/utils/parseRequestWillBeSentExtraInfo.ts @@ -71,7 +71,7 @@ export default function parseRequestWillBeSentExtraInfo( ...cookieWithoutPartitionKey, httponly: cookieWithoutPartitionKey?.httpOnly ?? false, expires: effectiveExpirationDate, - samesite: cookie.sameSite?.toLowerCase() ?? '', + samesite: cookie.sameSite?.toLowerCase() ?? 'lax', domain, partitionKey: '', }, diff --git a/packages/common/src/utils/parseResponseReceivedExtraInfo.ts b/packages/common/src/utils/parseResponseReceivedExtraInfo.ts index a04442f1a..b538199d1 100644 --- a/packages/common/src/utils/parseResponseReceivedExtraInfo.ts +++ b/packages/common/src/utils/parseResponseReceivedExtraInfo.ts @@ -96,7 +96,7 @@ export default function parseResponseReceivedExtraInfo( ...parsedCookie, httponly: parsedCookie?.httponly ?? false, expires: effectiveExpirationDate, - samesite: parsedCookie.samesite ?? '', + samesite: parsedCookie.samesite?.toLowerCase() ?? 'lax', domain, partitionKey: '', }, diff --git a/packages/common/src/utils/sanitizeCsvRecord.ts b/packages/common/src/utils/sanitizeCsvRecord.ts index 9e07add3b..c6e676d39 100644 --- a/packages/common/src/utils/sanitizeCsvRecord.ts +++ b/packages/common/src/utils/sanitizeCsvRecord.ts @@ -31,7 +31,9 @@ const sanitizeCsvRecord = (record: unknown): string => { } recordCopy = recordCopy.replace(/"/g, '""'); - return recordCopy.includes(',') ? '"' + recordCopy + '"' : recordCopy; + return recordCopy.includes(',') || recordCopy.includes('"') + ? '"' + recordCopy + '"' + : recordCopy; }; export default sanitizeCsvRecord; diff --git a/packages/common/src/utils/tests/sanitizeCsvRecords.ts b/packages/common/src/utils/tests/sanitizeCsvRecords.ts index cbd85fe5f..7e0dc2d08 100644 --- a/packages/common/src/utils/tests/sanitizeCsvRecords.ts +++ b/packages/common/src/utils/tests/sanitizeCsvRecords.ts @@ -33,7 +33,7 @@ describe('sanitizeCsvRecord : ', () => { it('should add double quotes before any double quotes in the string', () => { const invalidString = 'a value with "quotes"'; - const validString = 'a value with ""quotes""'; + const validString = '"a value with ""quotes"""'; expect(sanitizeCsvRecord(invalidString)).toBe(validString); }); diff --git a/packages/design-system/src/components/circlePieChart/emptyCirclePieChart.tsx b/packages/design-system/src/components/circlePieChart/emptyCirclePieChart.tsx index efc8faa66..48919547d 100644 --- a/packages/design-system/src/components/circlePieChart/emptyCirclePieChart.tsx +++ b/packages/design-system/src/components/circlePieChart/emptyCirclePieChart.tsx @@ -32,7 +32,7 @@ const EmptyCirclePieChart = () => { colorScale={[COLOR_MAP.brightGray.color]} data={[{ x: '', y: 100 }]} /> -

+

0

diff --git a/packages/design-system/src/components/circlePieChart/index.tsx b/packages/design-system/src/components/circlePieChart/index.tsx index 403617cf2..b9600c89a 100644 --- a/packages/design-system/src/components/circlePieChart/index.tsx +++ b/packages/design-system/src/components/circlePieChart/index.tsx @@ -56,7 +56,6 @@ const CirclePieChart = ({ ({ x: '', y: count }))} labels={() => ''} colorScale={data.map(({ color }) => color)} diff --git a/packages/design-system/src/components/cookieTable/utils/exportCookies.ts b/packages/design-system/src/components/cookieTable/utils/exportCookies.ts index 137d18b02..4bd3ed48f 100644 --- a/packages/design-system/src/components/cookieTable/utils/exportCookies.ts +++ b/packages/design-system/src/components/cookieTable/utils/exportCookies.ts @@ -20,6 +20,8 @@ import { type CookieTableData, getCurrentDateAndTime, + generateCLICookieTableCSV, + generateExtensionCookieTableCSV, } from '@google-psat/common'; import { saveAs } from 'file-saver'; @@ -27,10 +29,6 @@ import { saveAs } from 'file-saver'; * Internal dependencies */ import { TableRow } from '../../table'; -import { - generateCLICookieTableCSV, - generateExtensionCookieTableCSV, -} from '../../table/utils'; const exportCookies = (isCLI = false, rows: TableRow[], hostname: string) => { const _cookies = rows.map(({ originalData }) => originalData); diff --git a/packages/design-system/src/components/cookiesLanding/landingHeader/index.tsx b/packages/design-system/src/components/cookiesLanding/landingHeader/index.tsx index b4cc5510b..a5317152a 100644 --- a/packages/design-system/src/components/cookiesLanding/landingHeader/index.tsx +++ b/packages/design-system/src/components/cookiesLanding/landingHeader/index.tsx @@ -43,10 +43,10 @@ const LandingHeader = ({ )} data-testid="cookies-landing-header" > -
+
{dataMapping.map((circleData, index) => { return ( -
+