Remove page-side consent overlay and preserve passive TCF capture boundary

Dieser Commit ist enthalten in:
2026-06-14 13:09:17 +02:00
Ursprung e19eef67b2
Commit 3a174128e0
2 geänderte Dateien mit 693 neuen und 41 gelöschten Zeilen
+637
Datei anzeigen
@@ -8,10 +8,12 @@ const EVIDENCE_RECORDING_SOURCE = "vendorget_background_mirror";
const GVL_AUTO_UPDATE_SOURCE = "extension_startup"; const GVL_AUTO_UPDATE_SOURCE = "extension_startup";
const AUTO_GVL_CHECK_THROTTLE_MS = 24 * 60 * 60 * 1000; const AUTO_GVL_CHECK_THROTTLE_MS = 24 * 60 * 60 * 1000;
const AUTO_GVL_CHECK_STORAGE_KEY = "vendorgetAutoGvlUpdateStatus"; const AUTO_GVL_CHECK_STORAGE_KEY = "vendorgetAutoGvlUpdateStatus";
const CONSENT_CAPTURE_SESSION_TIMEOUT_MS = 10 * 60 * 1000;
let isAutoGvlCheckRunning = false; let isAutoGvlCheckRunning = false;
let lastAutoGvlCheckStartedAt = null; let lastAutoGvlCheckStartedAt = null;
let latestGvlUpdateStatus = null; let latestGvlUpdateStatus = null;
const consentCaptureSessions = new Map();
browser.runtime.onMessage.addListener((message, sender) => browser.runtime.onMessage.addListener((message, sender) =>
handleVendorGetMessage(message, sender) handleVendorGetMessage(message, sender)
@@ -22,6 +24,24 @@ browser.webRequest.onBeforeRequest.addListener(
{ urls: ["<all_urls>"] } { urls: ["<all_urls>"] }
); );
browser.tabs.onRemoved.addListener((tabId) => {
cleanupConsentCaptureSessionsForTab(tabId, "tab_removed");
});
browser.tabs.onUpdated.addListener((tabId, changeInfo) => {
if (changeInfo.url) {
cleanupConsentCaptureSessionsForTab(tabId, "page_changed");
}
});
if (browser.runtime.onSuspend) {
browser.runtime.onSuspend.addListener(() => {
consentCaptureSessions.forEach((session) => {
cleanupIncompleteConsentCaptureSession(session, "browser_end");
});
});
}
console.info("GVL auto update disabled; use manual sync"); console.info("GVL auto update disabled; use manual sync");
async function handleVendorGetMessage(message, sender) { async function handleVendorGetMessage(message, sender) {
@@ -113,6 +133,10 @@ async function handleVendorGetMessage(message, sender) {
return handleGetLatestConsentStateMessage(); return handleGetLatestConsentStateMessage();
} }
if (message.type === "get_consent_evidence_chain") {
return handleGetConsentEvidenceChainMessage(message);
}
if (message.type === "list_recent_consent_states") { if (message.type === "list_recent_consent_states") {
return handleListRecentConsentStatesMessage(); return handleListRecentConsentStatesMessage();
} }
@@ -166,6 +190,11 @@ async function handleVendorGetMessage(message, sender) {
return; return;
} }
if (eventName === "tcf_pre_consent_event") {
await handlePreConsentTcfEvent(message.payload.payload, sender);
return;
}
if (eventName !== "consent_capture") { if (eventName !== "consent_capture") {
console.log("VG-Observe ignored event", message); console.log("VG-Observe ignored event", message);
return; return;
@@ -188,6 +217,8 @@ async function handleVendorGetMessage(message, sender) {
stableStringify(consentState.fingerprintSource) stableStringify(consentState.fingerprintSource)
); );
const captureSessionId = getActiveConsentCaptureSessionId(sender);
rememberLatestConsentState(consentState); rememberLatestConsentState(consentState);
const result = await persistConsentState( const result = await persistConsentState(
@@ -195,6 +226,17 @@ async function handleVendorGetMessage(message, sender) {
message.payload.payload?.rawTcData ?? null message.payload.payload?.rawTcData ?? null
); );
if (captureSessionId) {
await persistConsentExecutionEvent({
captureSessionId,
consentState,
rawCapture: message.payload.payload,
sender
});
}
completeConsentCaptureSession(sender);
console.log("VG-Observe consent state persisted", result); console.log("VG-Observe consent state persisted", result);
} }
@@ -961,6 +1003,79 @@ async function handleGetLatestConsentStateMessage() {
}; };
} }
async function handleGetConsentEvidenceChainMessage(message) {
const stateFingerprint = normalizeStateFingerprint(
message?.payload?.stateFingerprint
);
const db = await openVendorGetDb();
const consentState = stateFingerprint
? await getConsentStateByFingerprint(db, stateFingerprint)
: null;
if (!consentState) {
return {
success: false,
error: "consent_state_not_found",
stateFingerprint
};
}
const consentEvents = await listConsentEventsByStateFingerprint(
db,
stateFingerprint
);
const observedRequests =
await listObservedRequestsByCorrelationStateFingerprint(
db,
stateFingerprint
);
const gvlContext = await buildConsentEvidenceChainGvlContext(
db,
consentState
);
return {
success: true,
stateFingerprint,
chain: {
consentState: {
record: consentState,
source: {
role: "primary_observation",
store: VENDORGET_STORE_NAMES.consentStates,
keyPath: "stateFingerprint"
}
},
consentEvents: {
records: consentEvents,
source: {
role: "observation_events",
store: VENDORGET_STORE_NAMES.consentEvents,
index: "stateFingerprint"
}
},
observedRequests: {
records: observedRequests,
source: {
role: "correlated_primary_observations",
store: VENDORGET_STORE_NAMES.observedRequests,
index: "correlationStateFingerprint",
field: "correlation.stateFingerprint"
}
},
gvlContext,
assembly: {
role: "technical_assembly",
method: "indexeddb_readonly_existing_records",
writes: false,
newDataSources: false,
correlationRecalculated: false,
interpretation: "none"
}
}
};
}
async function handleListRecentConsentStatesMessage() { async function handleListRecentConsentStatesMessage() {
const db = await openVendorGetDb(); const db = await openVendorGetDb();
const consentStates = await listRecentConsentStates(db, 25); const consentStates = await listRecentConsentStates(db, 25);
@@ -981,6 +1096,175 @@ async function handleListRecentObservedRequestsMessage() {
}; };
} }
function normalizeStateFingerprint(value) {
if (typeof value !== "string") {
return null;
}
const trimmedValue = value.trim();
return trimmedValue ? trimmedValue : null;
}
function getConsentStateByFingerprint(db, stateFingerprint) {
return new Promise((resolve, reject) => {
const tx = db.transaction([VENDORGET_STORE_NAMES.consentStates], "readonly");
const statesStore = tx.objectStore(VENDORGET_STORE_NAMES.consentStates);
const getRequest = statesStore.get(stateFingerprint);
let consentStateOrNull = null;
getRequest.onerror = () => reject(getRequest.error);
getRequest.onsuccess = () => {
consentStateOrNull = getRequest.result ?? null;
};
tx.onerror = () => reject(tx.error);
tx.onabort = () => reject(tx.error);
tx.oncomplete = () => resolve(consentStateOrNull);
});
}
function listConsentEventsByStateFingerprint(db, stateFingerprint) {
return new Promise((resolve, reject) => {
const consentEvents = [];
const tx = db.transaction([VENDORGET_STORE_NAMES.consentEvents], "readonly");
const eventsStore = tx.objectStore(VENDORGET_STORE_NAMES.consentEvents);
const stateFingerprintIndex = eventsStore.index("stateFingerprint");
const cursorRequest = stateFingerprintIndex.openCursor(
IDBKeyRange.only(stateFingerprint)
);
cursorRequest.onerror = () => reject(cursorRequest.error);
cursorRequest.onsuccess = () => {
const cursor = cursorRequest.result;
if (!cursor) {
return;
}
consentEvents.push(cursor.value);
cursor.continue();
};
tx.onerror = () => reject(tx.error);
tx.onabort = () => reject(tx.error);
tx.oncomplete = () => {
resolve(consentEvents.sort(compareConsentEvidenceEventRecords));
};
});
}
function listObservedRequestsByCorrelationStateFingerprint(
db,
stateFingerprint
) {
return new Promise((resolve, reject) => {
const observedRequests = [];
const tx = db.transaction(
[VENDORGET_STORE_NAMES.observedRequests],
"readonly"
);
const requestsStore = tx.objectStore(VENDORGET_STORE_NAMES.observedRequests);
const stateFingerprintIndex = requestsStore.index(
"correlationStateFingerprint"
);
const cursorRequest = stateFingerprintIndex.openCursor(
IDBKeyRange.only(stateFingerprint)
);
cursorRequest.onerror = () => reject(cursorRequest.error);
cursorRequest.onsuccess = () => {
const cursor = cursorRequest.result;
if (!cursor) {
return;
}
observedRequests.push(cursor.value);
cursor.continue();
};
tx.onerror = () => reject(tx.error);
tx.onabort = () => reject(tx.error);
tx.oncomplete = () => {
resolve(observedRequests.sort(compareConsentEvidenceRequestRecords));
};
});
}
async function buildConsentEvidenceChainGvlContext(db, consentState) {
const vendorListVersion = consentState?.gvl?.vendorListVersion ?? null;
const snapshot =
vendorListVersion !== null && vendorListVersion !== undefined
? await getGvlSnapshotByVendorListVersion(db, vendorListVersion)
: null;
const normalizedCounts = await countGvlNormalizedRecordsForVersion(
db,
vendorListVersion
);
const provenance = snapshot ? getGvlEvidenceProvenanceState(snapshot) : null;
return {
vendorListVersion,
snapshot,
normalizedCounts,
provenance,
source: {
role: "reference_context",
snapshotStore: VENDORGET_STORE_NAMES.gvlSnapshots,
snapshotIndex: "vendorListVersion",
normalizedStores: [
VENDORGET_STORE_NAMES.gvlVendors,
VENDORGET_STORE_NAMES.gvlPurposes,
VENDORGET_STORE_NAMES.gvlSpecialPurposes,
VENDORGET_STORE_NAMES.gvlFeatures,
VENDORGET_STORE_NAMES.gvlSpecialFeatures,
VENDORGET_STORE_NAMES.gvlDataCategories,
VENDORGET_STORE_NAMES.gvlVendorRelationships
],
normalizedIndex: "vendorListVersion"
}
};
}
function compareConsentEvidenceEventRecords(left, right) {
return (
compareNullableIsoDate(left?.capturedAt, right?.capturedAt) ||
compareNullableIsoDate(left?.recordedAt, right?.recordedAt) ||
toConsentEvidenceComparableNumber(left?.id) -
toConsentEvidenceComparableNumber(right?.id)
);
}
function compareConsentEvidenceRequestRecords(left, right) {
return (
compareNullableIsoDate(left?.firstSeenAt, right?.firstSeenAt) ||
compareNullableIsoDate(left?.lastSeenAt, right?.lastSeenAt) ||
String(left?.requestFingerprint ?? "").localeCompare(
String(right?.requestFingerprint ?? "")
)
);
}
function compareNullableIsoDate(left, right) {
return (
toConsentEvidenceComparableTime(left) -
toConsentEvidenceComparableTime(right)
);
}
function toConsentEvidenceComparableTime(value) {
const timestamp = Date.parse(value ?? "");
return Number.isNaN(timestamp) ? 0 : timestamp;
}
function toConsentEvidenceComparableNumber(value) {
const numberValue = Number(value);
return Number.isFinite(numberValue) ? numberValue : 0;
}
function getLatestConsentState(db) { function getLatestConsentState(db) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const tx = db.transaction(["consent_states"], "readonly"); const tx = db.transaction(["consent_states"], "readonly");
@@ -1814,6 +2098,225 @@ function getNextAllowedAutoGvlCheckAt(lastAutoGvlCheckAt) {
return new Date(lastCheckTime + AUTO_GVL_CHECK_THROTTLE_MS).toISOString(); return new Date(lastCheckTime + AUTO_GVL_CHECK_THROTTLE_MS).toISOString();
} }
function getConsentCaptureSessionKey(sender) {
const tabId = sender?.tab?.id;
const frameId = sender?.frameId ?? 0;
if (tabId === null || tabId === undefined) {
return null;
}
return `${tabId}:${frameId}`;
}
function createCaptureSessionId() {
if (crypto?.randomUUID) {
return crypto.randomUUID();
}
return [
"consent-capture",
Date.now().toString(36),
Math.random().toString(36).slice(2)
].join("-");
}
function buildConsentEventPageContext(rawCapture, sender) {
return {
url: rawCapture?.url ?? sender?.tab?.url ?? sender?.url ?? null,
origin: rawCapture?.origin ?? sender?.origin ?? null,
tabId: sender?.tab?.id ?? null,
frameId: sender?.frameId ?? null,
incognito: sender?.tab?.incognito ?? null,
cookieStoreId: sender?.tab?.cookieStoreId ?? null
};
}
function buildConsentEventDiagnostics(rawCapture, extraDiagnostics) {
return {
bridgeTimestampUtc: rawCapture?.timestampUtc ?? null,
rawTopLevelKeys: Object.keys(rawCapture?.rawTcData ?? rawCapture ?? {}),
...(extraDiagnostics ?? {})
};
}
function startConsentCaptureSessionTimeout(session) {
session.timeoutId = setTimeout(() => {
cleanupIncompleteConsentCaptureSession(session, "timeout");
}, CONSENT_CAPTURE_SESSION_TIMEOUT_MS);
}
async function handlePreConsentTcfEvent(rawCapture, sender) {
if (isEvidenceWriteSuspended()) {
console.info("VG-Observe pre-consent capture skipped: maintenance mode");
return;
}
const eventStatus = rawCapture?.eventStatus ?? null;
if (eventStatus !== "cmpuishown" && eventStatus !== "tcloaded") {
return;
}
const sessionKey = getConsentCaptureSessionKey(sender);
if (!sessionKey) {
return;
}
let session = consentCaptureSessions.get(sessionKey);
if (session?.status === "declined" || session?.status === "completed") {
return;
}
if (session?.status === "active") {
await persistProviderAnnouncementEvent({
captureSessionId: session.captureSessionId,
rawCapture,
sender
});
return;
}
if (!session) {
session = {
key: sessionKey,
tabId: sender?.tab?.id ?? null,
frameId: sender?.frameId ?? null,
status: "prompting",
captureSessionId: null,
bufferedPreConsentEvents: [],
timeoutId: null
};
consentCaptureSessions.set(sessionKey, session);
startConsentCaptureSessionTimeout(session);
}
session.bufferedPreConsentEvents.push({
rawCapture,
sender
});
if (session.promptInProgress) {
return;
}
session.promptInProgress = true;
const accepted = await askUserForConsentCapture(sender);
if (!consentCaptureSessions.has(sessionKey)) {
return;
}
session.promptInProgress = false;
if (!accepted) {
session.status = "declined";
session.bufferedPreConsentEvents = [];
return;
}
session.status = "active";
session.captureSessionId = createCaptureSessionId();
const bufferedEvents = session.bufferedPreConsentEvents;
session.bufferedPreConsentEvents = [];
for (const bufferedEvent of bufferedEvents) {
await persistProviderAnnouncementEvent({
captureSessionId: session.captureSessionId,
rawCapture: bufferedEvent.rawCapture,
sender: bufferedEvent.sender
});
}
}
async function askUserForConsentCapture(sender) {
console.info(
"VG-Observe pre-consent provider announcement capture inactive: extension-owned consent prompt is not implemented",
{
tabId: sender?.tab?.id ?? null,
frameId: sender?.frameId ?? null
}
);
return false;
}
function getActiveConsentCaptureSessionId(sender) {
const sessionKey = getConsentCaptureSessionKey(sender);
const session = sessionKey ? consentCaptureSessions.get(sessionKey) : null;
if (!session || session.status !== "active") {
return null;
}
return session.captureSessionId ?? null;
}
function completeConsentCaptureSession(sender) {
const sessionKey = getConsentCaptureSessionKey(sender);
let session = sessionKey ? consentCaptureSessions.get(sessionKey) : null;
if (!sessionKey) {
return;
}
if (!session) {
session = {
key: sessionKey,
tabId: sender?.tab?.id ?? null,
frameId: sender?.frameId ?? null,
status: "completed",
captureSessionId: null,
bufferedPreConsentEvents: [],
timeoutId: null
};
consentCaptureSessions.set(sessionKey, session);
}
session.status = "completed";
session.completedAt = new Date().toISOString();
session.bufferedPreConsentEvents = [];
session.promptInProgress = false;
if (session.timeoutId) {
clearTimeout(session.timeoutId);
session.timeoutId = null;
}
}
function cleanupConsentCaptureSessionsForTab(tabId, reason) {
consentCaptureSessions.forEach((session) => {
if (session.tabId === tabId) {
cleanupIncompleteConsentCaptureSession(session, reason);
}
});
}
function cleanupIncompleteConsentCaptureSession(session, reason) {
if (session.timeoutId) {
clearTimeout(session.timeoutId);
}
consentCaptureSessions.delete(session.key);
if (!session.captureSessionId || session.status === "completed") {
return;
}
deleteProviderAnnouncementEventsForSession(
session.captureSessionId,
reason
).catch((error) => {
console.warn("VG-Observe provider announcement cleanup failed", error);
});
}
function getLatestGvlSnapshotByVendorListVersion(db) { function getLatestGvlSnapshotByVendorListVersion(db) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const tx = db.transaction([VENDORGET_STORE_NAMES.gvlSnapshots], "readonly"); const tx = db.transaction([VENDORGET_STORE_NAMES.gvlSnapshots], "readonly");
@@ -2018,6 +2521,9 @@ function buildConsentStateV1(rawCapture, sender, latestPingData) {
addtlConsent: rawCapture?.addtlConsent ?? null addtlConsent: rawCapture?.addtlConsent ?? null
}, },
rawTcString: rawCapture?.rawTcString ?? null,
rawTcData: rawCapture?.rawTcData ?? null,
purposes: { purposes: {
consents: rawCapture?.purpose?.consents ?? {}, consents: rawCapture?.purpose?.consents ?? {},
legitimateInterests: rawCapture?.purpose?.legitimateInterests ?? {} legitimateInterests: rawCapture?.purpose?.legitimateInterests ?? {}
@@ -2093,6 +2599,10 @@ async function persistConsentState(consentState, rawTcData) {
existingState.lastSeenAt = now; existingState.lastSeenAt = now;
existingState.seenCount = (existingState.seenCount ?? 1) + 1; existingState.seenCount = (existingState.seenCount ?? 1) + 1;
existingState.updatedAt = now; existingState.updatedAt = now;
existingState.rawTcString =
existingState.rawTcString ?? consentState.rawTcString ?? null;
existingState.rawTcData =
existingState.rawTcData ?? consentState.rawTcData ?? null;
statesStore.put(existingState); statesStore.put(existingState);
@@ -2104,6 +2614,7 @@ async function persistConsentState(consentState, rawTcData) {
stateFingerprint: consentState.stateFingerprint, stateFingerprint: consentState.stateFingerprint,
page: consentState.page, page: consentState.page,
rawEventName: "consent_capture", rawEventName: "consent_capture",
rawTcString: consentState.rawTcString ?? null,
rawTcData: rawTcData, rawTcData: rawTcData,
diagnostics: consentState.diagnostics diagnostics: consentState.diagnostics
}); });
@@ -2138,6 +2649,7 @@ async function persistConsentState(consentState, rawTcData) {
stateFingerprint: consentState.stateFingerprint, stateFingerprint: consentState.stateFingerprint,
page: consentState.page, page: consentState.page,
rawEventName: "consent_capture", rawEventName: "consent_capture",
rawTcString: consentState.rawTcString ?? null,
rawTcData: rawTcData, rawTcData: rawTcData,
diagnostics: consentState.diagnostics diagnostics: consentState.diagnostics
}); });
@@ -2153,6 +2665,131 @@ async function persistConsentState(consentState, rawTcData) {
}); });
} }
async function persistProviderAnnouncementEvent({
captureSessionId,
rawCapture,
sender
}) {
const db = await openVendorGetDb();
const now = new Date().toISOString();
const capturedAt = rawCapture?.timestampUtc ?? now;
return addConsentEventRecord(db, {
eventType: "provider_announcement",
capturedAt,
recordedAt: now,
recordingSource: EVIDENCE_RECORDING_SOURCE,
captureSessionId,
stateFingerprint: null,
page: buildConsentEventPageContext(rawCapture, sender),
rawEventName: rawCapture?.eventStatus ?? null,
eventStatus: rawCapture?.eventStatus ?? null,
cmpStatus: rawCapture?.cmpStatus ?? null,
tcString: rawCapture?.tcString ?? null,
addtlConsent: rawCapture?.addtlConsent ?? null,
vendorListVersion: rawCapture?.vendorListVersion ?? null,
rawTcString: rawCapture?.rawTcString ?? null,
rawTcData: rawCapture?.rawTcData ?? null,
diagnostics: buildConsentEventDiagnostics(rawCapture, {
consentEvidenceRole: "providerAnnouncement"
})
});
}
async function persistConsentExecutionEvent({
captureSessionId,
consentState,
rawCapture,
sender
}) {
const db = await openVendorGetDb();
const now = new Date().toISOString();
const capturedAt = consentState?.capturedAt ?? rawCapture?.timestampUtc ?? now;
return addConsentEventRecord(db, {
eventType: "consent_execution",
capturedAt,
recordedAt: now,
recordingSource: EVIDENCE_RECORDING_SOURCE,
captureSessionId,
stateFingerprint: consentState?.stateFingerprint ?? null,
page: buildConsentEventPageContext(rawCapture, sender),
rawEventName: "useractioncomplete",
eventStatus: rawCapture?.eventStatus ?? null,
cmpStatus: rawCapture?.cmpStatus ?? null,
tcString: rawCapture?.tcString ?? null,
addtlConsent: rawCapture?.addtlConsent ?? null,
vendorListVersion: rawCapture?.vendorListVersion ?? null,
rawTcString: rawCapture?.rawTcString ?? null,
rawTcData: rawCapture?.rawTcData ?? null,
diagnostics: buildConsentEventDiagnostics(rawCapture, {
consentEvidenceRole: "consentExecution"
})
});
}
function addConsentEventRecord(db, record) {
return new Promise((resolve, reject) => {
const tx = db.transaction(["consent_events"], "readwrite");
const eventsStore = tx.objectStore("consent_events");
const request = eventsStore.add(record);
request.onerror = () => reject(request.error);
tx.onerror = () => reject(tx.error);
tx.onabort = () => reject(tx.error);
tx.oncomplete = () => resolve(record);
});
}
async function deleteProviderAnnouncementEventsForSession(
captureSessionId,
reason
) {
const db = await openVendorGetDb();
return new Promise((resolve, reject) => {
const tx = db.transaction(["consent_events"], "readwrite");
const eventsStore = tx.objectStore("consent_events");
const eventTypeIndex = eventsStore.index("eventType");
const request = eventTypeIndex.openCursor(
IDBKeyRange.only("provider_announcement")
);
let deletedCount = 0;
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const cursor = request.result;
if (!cursor) {
return;
}
if (cursor.value?.captureSessionId === captureSessionId) {
cursor.delete();
deletedCount += 1;
}
cursor.continue();
};
tx.onerror = () => reject(tx.error);
tx.onabort = () => reject(tx.error);
tx.oncomplete = () => {
console.info("VG-Observe provider announcement cleanup complete", {
captureSessionId,
reason,
deletedCount
});
resolve({
captureSessionId,
reason,
deletedCount
});
};
});
}
async function persistObservedRequest(observedRequest) { async function persistObservedRequest(observedRequest) {
const db = await openVendorGetDb(); const db = await openVendorGetDb();
+45 -30
Datei anzeigen
@@ -20,7 +20,7 @@
function cloneSerializable(value, seen) { function cloneSerializable(value, seen) {
if (value === undefined) { if (value === undefined) {
return null; return undefined;
} }
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") { if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
@@ -50,10 +50,6 @@
}); });
} }
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
return undefined;
}
const result = {}; const result = {};
Object.keys(value).forEach(function (key) { Object.keys(value).forEach(function (key) {
@@ -75,31 +71,8 @@
return result; return result;
} }
window.__tcfapi("ping", 2, function (pingData, pingSuccess) { function buildTcfEventCapture(tcData) {
return {
console.log("VendorGet __tcfapi ping:", {
success: pingSuccess,
data: pingData
});
emitToContentScript("tcf_ping", {
success: pingSuccess,
data: pingData
});
});
window.__tcfapi("addEventListener", 2, function (tcData, success) {
if (!success || !tcData) {
return;
}
console.log("VendorGet raw event:", tcData);
if (tcData.eventStatus === "useractioncomplete") {
const capture = {
url: window.location.href, url: window.location.href,
origin: window.location.origin, origin: window.location.origin,
@@ -133,8 +106,50 @@
addtlConsent: tcData.addtlConsent, addtlConsent: tcData.addtlConsent,
rawTcString: {
tcString: tcData.tcString,
addtlConsent: tcData.addtlConsent
},
rawTcData: cloneSerializable(tcData) rawTcData: cloneSerializable(tcData)
}; };
}
window.__tcfapi("ping", 2, function (pingData, pingSuccess) {
console.log("VendorGet __tcfapi ping:", {
success: pingSuccess,
data: pingData
});
emitToContentScript("tcf_ping", {
success: pingSuccess,
data: pingData
});
});
window.__tcfapi("addEventListener", 2, function (tcData, success) {
if (!success || !tcData) {
return;
}
console.log("VendorGet raw event:", tcData);
if (
tcData.eventStatus === "cmpuishown" ||
tcData.eventStatus === "tcloaded"
) {
emitToContentScript(
"tcf_pre_consent_event",
buildTcfEventCapture(tcData)
);
}
if (tcData.eventStatus === "useractioncomplete") {
const capture = buildTcfEventCapture(tcData);
console.log("VendorGet CONSENT CAPTURE:", capture); console.log("VendorGet CONSENT CAPTURE:", capture);