Skip to content
This repository was archived by the owner on Aug 25, 2026. It is now read-only.

Commit 585aeee

Browse files
amovar18mohdsayed
andcommitted
Feature: Protected audience analysis in PSAT (#811)
* Add PA analysis in service worker. Improve attach CDP function. * Add storage.interestGroupAccessed method to service worker. * Add bid value to the auction events. * Split syncCookieStore into dataStore, CookieStore and PAStore. Change its references. * Export interface from dataStore. * Change some more references. * Add protected audience provider to the devtools. * Convert bid to null. * Add last mile connection to the devtools * Add method to incorporate multiple auction ID. * Handle multiSeller auctions. Console.log data in app.tsx. * Descructure details in the extension. * Refactor service worker. Move service worker PA methods to PAStore. * Fix errors in the refactor. * Fix lint errors * Fix tests. * Move PA types to common package. * Update devtools protocol package to latest version * Move InterestGroup and auctionEvents to common package * Add support to hear globalEvents. * Add comment to explain auctionEvents structure. Refactor PA store to fix some bug when it was made to accomodate global events. * Use globalEvents instead of interestGroupEvents. * compute received Bids and noBids. * Fix noBids in the protected audience provider. * Fix nobids value. Add object diff in state update. Remove console.log. Add adUnit code to the data being provided in the bids and noBids. * Add ads and Bidders in protectedAudience API provider. * Add adUnitCode optional chaining. Fix set spread of bidders. * Fix data being displayed on the panel. * Fix data refresh on tab reload. * Reduce state updates. Refactor code move udeCallback to separate functions. * Fix error of not updating. * Fix undefined error. * Remove logic to reset interest group data on page load or navigation. * Fix failing tests. * Fix merge conflicts. * Fix failing build. * Fix failing tests * Fix initial sync override. * Fix failing tests. * Fix tab reload data refresh. --------- Co-authored-by: sayedtaqui <sayedwp@gmail.com>
1 parent 8df1a0d commit 585aeee

42 files changed

Lines changed: 2047 additions & 664 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎package-lock.json‎

Lines changed: 10 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎packages/cli/src/e2e-tests/index.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ describe('CLI E2E Test', () => {
2020

2121
it('Should run site analysis', () => {
2222
return coffee
23-
.fork(cli, ['-u https://bbc.com', '-w 1000'])
24-
.includes('stdout', '/out/bbc-com/report_')
23+
.fork(cli, ['-u https://domain-aaa.com/', '-w 1000'])
24+
.includes('stdout', '/out/domain-aaa-com/report_')
2525
.end();
2626
}, 60000);
2727
});

‎packages/common/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@
4242
"tldts": "^6.0.14"
4343
},
4444
"devDependencies": {
45-
"devtools-protocol": "^0.0.1333880"
45+
"devtools-protocol": "^0.0.1345247"
4646
}
4747
}

‎packages/common/src/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,4 @@ export * from './worker/enums';
5252
export * from './utils/generateReports';
5353
export * from './cookies.types';
5454
export * from './libraryDetection.types';
55+
export * from './protectedAudience.types';
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
/**
17+
* External dependencies
18+
*/
19+
import type { Protocol } from 'devtools-protocol';
20+
21+
export interface singleAuctionEvent {
22+
bidCurrency?: string;
23+
uniqueAuctionId?: Protocol.Storage.InterestGroupAuctionId;
24+
bid?: number;
25+
name?: string;
26+
ownerOrigin?: string;
27+
type: string;
28+
formattedTime: string | Date;
29+
componentSellerOrigin?: string;
30+
time: number;
31+
auctionConfig?: object;
32+
interestGroupConfig?: Protocol.Storage.InterestGroupAccessedEvent;
33+
parentAuctionId?: Protocol.Storage.InterestGroupAuctionId;
34+
eventType:
35+
| 'interestGroupAuctionEventOccurred'
36+
| 'interestGroupAuctionNetworkRequestCompleted'
37+
| 'interestGroupAuctionNetworkRequestCreated'
38+
| 'interestGroupAccessed';
39+
}
40+
41+
export interface auctionData {
42+
[uniqueAuctionId: Protocol.Storage.InterestGroupAuctionId]: {
43+
auctionTime: Protocol.Network.TimeSinceEpoch;
44+
auctionConfig?: any;
45+
parentAuctionId?: Protocol.Storage.InterestGroupAuctionId;
46+
};
47+
}
48+
49+
export type InterestGroups = singleAuctionEvent & {
50+
details: any;
51+
};
52+
53+
export type MultiSellerAuction = {
54+
[parentAuctionId: string]: {
55+
[uniqueAuctionId: string]: singleAuctionEvent[];
56+
};
57+
};
58+
59+
export type SingleSellerAuction = {
60+
[parentAuctionId: string]: singleAuctionEvent[];
61+
};
62+
63+
export type NoBidsType = {
64+
[auctionId: string]: {
65+
ownerOrigin: string;
66+
name: string;
67+
uniqueAuctionId: string;
68+
adUnitCode?: string;
69+
mediaContainerSize?: number[][];
70+
};
71+
};
72+
73+
export type AdsAndBiddersType = {
74+
[adUnitCode: string]: {
75+
adUnitCode: string;
76+
bidders: string[];
77+
mediaContainerSize: number[][];
78+
};
79+
};
80+
81+
export type ReceivedBids = singleAuctionEvent & {
82+
adUnitCode?: string;
83+
mediaContainerSize?: number[];
84+
};
85+
86+
export type AuctionEventsType = SingleSellerAuction | MultiSellerAuction | null;

‎packages/extension/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
},
5454
"devDependencies": {
5555
"@types/react-copy-to-clipboard": "^5.0.4",
56-
"devtools-protocol": "^0.0.1333880",
56+
"devtools-protocol": "^0.0.1345247",
5757
"html-inline-script-webpack-plugin": "^3.2.1"
5858
}
5959
}

‎packages/extension/src/serviceWorker/attachCDP.ts‎

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,41 @@
1717
* This function will attach the debugger to the given target.
1818
* @param {{ [key: string]: number | string }} target The target where debugger needs to be attached.
1919
*/
20-
export default async function attachCDP(target: {
21-
[key: string]: number | string;
22-
}) {
23-
try {
24-
await chrome.debugger.attach(target, '1.3');
25-
await chrome.debugger.sendCommand(target, 'Target.setAutoAttach', {
26-
// If this is set to true, debugger will be attached to every new target that is added to the current target.
27-
autoAttach: true,
28-
waitForDebuggerOnStart: false,
29-
//Enables "flat" access to the session via specifying sessionId attribute in the commands.
30-
// If this is set to true the debugger is also attached to the child targets of that the target it has been attached to.
31-
flatten: true,
32-
});
33-
await chrome.debugger.sendCommand(target, 'Network.enable');
34-
await chrome.debugger.sendCommand(target, 'Audits.enable');
35-
await chrome.debugger.sendCommand(target, 'Page.enable');
36-
} catch (error) {
37-
//Fail silently
38-
}
20+
export default function attachCDP(target: { [key: string]: number | string }) {
21+
chrome.debugger.attach(target, '1.3', async () => {
22+
if (chrome.runtime.lastError) {
23+
// eslint-disable-next-line no-console
24+
console.warn(chrome.runtime.lastError);
25+
}
26+
try {
27+
await chrome.debugger.sendCommand(target, 'Target.setAutoAttach', {
28+
autoAttach: true,
29+
flatten: false,
30+
waitForDebuggerOnStart: true,
31+
});
32+
33+
await chrome.debugger.sendCommand(
34+
target,
35+
'Storage.setInterestGroupAuctionTracking',
36+
{ enable: true }
37+
);
38+
39+
await chrome.debugger.sendCommand(target, 'Audits.enable');
40+
41+
await chrome.debugger.sendCommand(
42+
target,
43+
'Storage.setInterestGroupTracking',
44+
{
45+
enable: true,
46+
}
47+
);
48+
49+
await chrome.debugger.sendCommand(target, 'Page.enable');
50+
51+
await chrome.debugger.sendCommand(target, 'Network.enable');
52+
} catch (error) {
53+
// eslint-disable-next-line no-console
54+
console.warn(error);
55+
}
56+
});
3957
}

‎packages/extension/src/serviceWorker/chromeListeners/beforeSendHeadersListener.ts‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
* Internal dependencies
1818
*/
1919
import parseHeaders from '../../utils/parseHeaders';
20-
import synchnorousCookieStore from '../../store/synchnorousCookieStore';
20+
import dataStore from '../../store/dataStore';
21+
import cookieStore from '../../store/cookieStore';
2122
import { getTab } from '../../utils/getTab';
2223

2324
export const onBeforeSendHeadersListener = ({
@@ -27,26 +28,26 @@ export const onBeforeSendHeadersListener = ({
2728
frameId,
2829
requestId,
2930
}: chrome.webRequest.WebRequestHeadersDetails) => {
30-
if (synchnorousCookieStore.globalIsUsingCDP) {
31+
if (dataStore.globalIsUsingCDP) {
3132
return;
3233
}
3334

3435
(async () => {
3536
const tab = await getTab(tabId);
36-
let tabUrl = synchnorousCookieStore?.getTabUrl(tabId);
37+
let tabUrl = dataStore?.getTabUrl(tabId);
3738

3839
if (tab && tab.pendingUrl) {
3940
tabUrl = tab.pendingUrl;
4041
}
4142

4243
const cookies = await parseHeaders(
43-
synchnorousCookieStore.globalIsUsingCDP,
44+
dataStore.globalIsUsingCDP,
4445
'request',
45-
synchnorousCookieStore.tabToRead,
46-
synchnorousCookieStore.tabMode,
46+
dataStore.tabToRead,
47+
dataStore.tabMode,
4748
tabId,
4849
url,
49-
synchnorousCookieStore.cookieDB ?? {},
50+
dataStore.cookieDB ?? {},
5051
tabUrl,
5152
frameId.toString(),
5253
requestId,
@@ -58,6 +59,6 @@ export const onBeforeSendHeadersListener = ({
5859
}
5960

6061
// Adds the cookies from the request headers to the cookies object.
61-
synchnorousCookieStore?.update(tabId, cookies);
62+
cookieStore?.update(tabId, cookies);
6263
})();
6364
};

‎packages/extension/src/serviceWorker/chromeListeners/onCommittedNavigationListener.ts‎

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* Internal dependencies
1818
*/
1919
import { TABID_STORAGE } from '../../constants';
20-
import synchnorousCookieStore from '../../store/synchnorousCookieStore';
20+
import dataStore from '../../store/dataStore';
2121
import getQueryParams from '../../utils/getQueryParams';
2222
import attachCDP from '../attachCDP';
2323

@@ -36,7 +36,7 @@ export const onCommittedNavigationListener = async ({
3636
}
3737

3838
const targets = await chrome.debugger.getTargets();
39-
const mainFrameId = synchnorousCookieStore?.globalIsUsingCDP
39+
const mainFrameId = dataStore?.globalIsUsingCDP
4040
? targets.filter((target) => target.tabId && target.tabId === tabId)[0]
4141
?.id
4242
: 0;
@@ -50,19 +50,19 @@ export const onCommittedNavigationListener = async ({
5050
isUsingCDP: queryParams.psat_cdp === 'on',
5151
});
5252

53-
synchnorousCookieStore.globalIsUsingCDP = queryParams.psat_cdp === 'on';
54-
synchnorousCookieStore.tabMode =
53+
dataStore.globalIsUsingCDP = queryParams.psat_cdp === 'on';
54+
dataStore.tabMode =
5555
queryParams.psat_multitab === 'on' ? 'unlimited' : 'single';
5656
}
5757

58-
synchnorousCookieStore?.updateUrl(tabId, url);
58+
dataStore?.updateUrl(tabId, url);
5959

6060
if (url && !url.startsWith('chrome://')) {
61-
synchnorousCookieStore?.removeCookieData(tabId);
61+
dataStore?.removeCookieData(tabId);
6262

63-
if (synchnorousCookieStore.globalIsUsingCDP) {
64-
synchnorousCookieStore.deinitialiseVariablesForTab(tabId.toString());
65-
synchnorousCookieStore.initialiseVariablesForNewTab(tabId.toString());
63+
if (dataStore.globalIsUsingCDP) {
64+
dataStore.deinitialiseVariablesForTab(tabId.toString());
65+
dataStore.initialiseVariablesForNewTab(tabId.toString());
6666

6767
await attachCDP({ tabId });
6868

@@ -76,11 +76,7 @@ export const onCommittedNavigationListener = async ({
7676
}
7777
);
7878

79-
synchnorousCookieStore.updateParentChildFrameAssociation(
80-
tabId,
81-
targetId,
82-
'0'
83-
);
79+
dataStore.updateParentChildFrameAssociation(tabId, targetId, '0');
8480
}
8581
}
8682
await chrome.tabs.sendMessage(tabId, {

‎packages/extension/src/serviceWorker/chromeListeners/onEnabledListener.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/**
1717
* Internal dependencies
1818
*/
19-
import synchnorousCookieStore from '../../store/synchnorousCookieStore';
19+
import dataStore from '../../store/dataStore';
2020
import { updateGlobalVariableAndAttachCDP, setupIntervals } from './utils';
2121

2222
export const onEnabledListener = async (
@@ -26,7 +26,7 @@ export const onEnabledListener = async (
2626
return;
2727
}
2828

29-
synchnorousCookieStore?.clear();
29+
dataStore?.clear();
3030

3131
setupIntervals();
3232

0 commit comments

Comments
 (0)