428 Zeilen
13 KiB
JavaScript
428 Zeilen
13 KiB
JavaScript
"use strict";
|
|
|
|
const requestMonitoringToggle = document.getElementById(
|
|
"request-monitoring-toggle"
|
|
);
|
|
const requestMonitoringStatus = document.getElementById(
|
|
"request-monitoring-status"
|
|
);
|
|
const consentCaptureToggle = document.getElementById("consent-capture-toggle");
|
|
const consentCaptureStatus = document.getElementById("consent-capture-status");
|
|
const preConsentCapture = document.getElementById("pre-consent-capture");
|
|
const preConsentCaptureSummary = document.getElementById(
|
|
"pre-consent-capture-summary"
|
|
);
|
|
const preConsentCaptureStart = document.getElementById(
|
|
"pre-consent-capture-start"
|
|
);
|
|
const preConsentCaptureDecline = document.getElementById(
|
|
"pre-consent-capture-decline"
|
|
);
|
|
const preConsentCaptureStatus = document.getElementById(
|
|
"pre-consent-capture-status"
|
|
);
|
|
const maintenanceWarning = document.getElementById("maintenance-warning");
|
|
const evidenceLockedCount = document.getElementById("evidence-locked-count");
|
|
const evidenceDashboardButton = document.getElementById(
|
|
"evidence-dashboard-button"
|
|
);
|
|
const evidenceExportJsonButton = document.getElementById(
|
|
"evidence-export-json-button"
|
|
);
|
|
const evidencePurgeUnlockedButton = document.getElementById(
|
|
"evidence-purge-unlocked-button"
|
|
);
|
|
const evidencePurgeConfirmModal = document.getElementById(
|
|
"evidence-purge-confirm-modal"
|
|
);
|
|
const evidencePurgeCancelButton = document.getElementById(
|
|
"evidence-purge-cancel-button"
|
|
);
|
|
const evidencePurgeConfirmButton = document.getElementById(
|
|
"evidence-purge-confirm-button"
|
|
);
|
|
const evidenceExportJsonStatus = document.getElementById(
|
|
"evidence-export-json-status"
|
|
);
|
|
const evidenceRetentionStatus = document.getElementById(
|
|
"evidence-retention-status"
|
|
);
|
|
|
|
const evidenceStoreCountCells = {
|
|
consent_states: document.getElementById("evidence-consent-states-count"),
|
|
consent_events: document.getElementById("evidence-consent-events-count"),
|
|
observed_requests: document.getElementById("evidence-observed-requests-count"),
|
|
gvl_snapshots: document.getElementById("evidence-gvl-snapshots-count"),
|
|
gvl_snapshot_events: document.getElementById(
|
|
"evidence-gvl-snapshot-events-count"
|
|
)
|
|
};
|
|
|
|
document.addEventListener("DOMContentLoaded", async () => {
|
|
await renderSettings();
|
|
await renderPreConsentCaptureStatus();
|
|
await renderEvidenceMaintenanceStatus();
|
|
await renderEvidenceRetentionStatus();
|
|
|
|
consentCaptureToggle.addEventListener("change", async () => {
|
|
consentCaptureToggle.disabled = true;
|
|
|
|
await setVendorGetSetting(
|
|
"consentCaptureEnabled",
|
|
consentCaptureToggle.checked
|
|
);
|
|
|
|
if (consentCaptureToggle.checked) {
|
|
await probePreConsentCaptureForActiveTab();
|
|
}
|
|
|
|
await renderSettings();
|
|
await renderPreConsentCaptureStatus();
|
|
|
|
consentCaptureToggle.disabled = false;
|
|
});
|
|
|
|
requestMonitoringToggle.addEventListener("change", async () => {
|
|
requestMonitoringToggle.disabled = true;
|
|
|
|
await setVendorGetSetting(
|
|
"requestMonitoringEnabled",
|
|
requestMonitoringToggle.checked
|
|
);
|
|
await renderSettings();
|
|
|
|
requestMonitoringToggle.disabled = false;
|
|
});
|
|
|
|
evidenceDashboardButton.addEventListener("click", async () => {
|
|
await browser.tabs.create({
|
|
url: browser.runtime.getURL("src/dashboard/dashboard.html")
|
|
});
|
|
});
|
|
|
|
evidenceExportJsonButton.addEventListener("click", exportEvidenceJsonFile);
|
|
evidencePurgeUnlockedButton.addEventListener("click", openPurgeConfirmModal);
|
|
evidencePurgeCancelButton.addEventListener("click", closePurgeConfirmModal);
|
|
evidencePurgeConfirmButton.addEventListener("click", purgeUnlockedEvidence);
|
|
preConsentCaptureStart.addEventListener("click", startPreConsentCapture);
|
|
preConsentCaptureDecline.addEventListener("click", declinePreConsentCapture);
|
|
});
|
|
|
|
async function renderSettings() {
|
|
const settings = await getVendorGetSettings();
|
|
const consentCaptureEnabled = settings.consentCaptureEnabled;
|
|
const requestMonitoringEnabled = settings.requestMonitoringEnabled;
|
|
|
|
consentCaptureToggle.checked = consentCaptureEnabled;
|
|
consentCaptureStatus.textContent = consentCaptureEnabled ? "aktiv" : "aus";
|
|
|
|
requestMonitoringToggle.checked = requestMonitoringEnabled;
|
|
requestMonitoringStatus.textContent = requestMonitoringEnabled
|
|
? "aktiv"
|
|
: "aus";
|
|
}
|
|
|
|
async function renderEvidenceRetentionStatus() {
|
|
try {
|
|
const status = await getEvidenceRetentionStatus();
|
|
|
|
renderEvidenceStoreCounts(status.storeCounts ?? {});
|
|
evidenceLockedCount.textContent = formatStatusValue(status.lockedCount);
|
|
renderEvidenceRetentionMessage("Bereit");
|
|
} catch (error) {
|
|
renderEvidenceStoreCounts({});
|
|
evidenceLockedCount.textContent = "-";
|
|
renderEvidenceRetentionMessage("Status konnte nicht geladen werden");
|
|
console.warn("VendorGet-IV evidence retention status failed", error);
|
|
}
|
|
}
|
|
|
|
async function renderEvidenceMaintenanceStatus() {
|
|
try {
|
|
const status = await browser.runtime.sendMessage({
|
|
type: "get_evidence_maintenance_status"
|
|
});
|
|
|
|
if (!status?.success) {
|
|
throw new Error(status?.error ?? "get_evidence_maintenance_status_failed");
|
|
}
|
|
|
|
maintenanceWarning.hidden = !status.evidenceWriteSuspended;
|
|
} catch (error) {
|
|
maintenanceWarning.hidden = true;
|
|
console.warn("VendorGet-IV maintenance status failed", error);
|
|
}
|
|
}
|
|
|
|
async function getEvidenceRetentionStatus() {
|
|
const status = await browser.runtime.sendMessage({
|
|
type: "get_evidence_retention_status"
|
|
});
|
|
|
|
if (!status?.success) {
|
|
throw new Error(status?.error ?? "get_evidence_retention_status_failed");
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
function renderEvidenceStoreCounts(storeCounts) {
|
|
for (const [storeName, cell] of Object.entries(evidenceStoreCountCells)) {
|
|
cell.textContent = formatStatusValue(storeCounts[storeName]);
|
|
}
|
|
}
|
|
|
|
function formatStatusValue(value) {
|
|
return Number.isFinite(value) ? String(value) : "-";
|
|
}
|
|
|
|
function renderEvidenceRetentionMessage(message) {
|
|
evidenceRetentionStatus.textContent = message;
|
|
}
|
|
|
|
async function renderPreConsentCaptureStatus() {
|
|
try {
|
|
const activeTab = await getActiveTab();
|
|
|
|
if (!activeTab?.id) {
|
|
renderNoPreConsentCapture();
|
|
return;
|
|
}
|
|
|
|
const result = await browser.runtime.sendMessage({
|
|
type: "get_pre_consent_capture_status",
|
|
payload: {
|
|
tabId: activeTab.id
|
|
}
|
|
});
|
|
|
|
if (!result?.success) {
|
|
throw new Error(result?.error ?? "get_pre_consent_capture_status_failed");
|
|
}
|
|
|
|
renderPreConsentCapture(result.capture);
|
|
} catch (error) {
|
|
renderNoPreConsentCapture();
|
|
console.warn("VendorGet-IV pre-consent status failed", error);
|
|
}
|
|
}
|
|
|
|
async function probePreConsentCaptureForActiveTab() {
|
|
try {
|
|
const activeTab = await getActiveTab();
|
|
|
|
if (!activeTab?.id) {
|
|
return;
|
|
}
|
|
|
|
await browser.runtime.sendMessage({
|
|
type: "probe_pre_consent_capture_for_tab",
|
|
payload: {
|
|
tabId: activeTab.id
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.warn("VendorGet-IV pre-consent probe failed", error);
|
|
}
|
|
}
|
|
|
|
function renderPreConsentCapture(capture) {
|
|
if (!capture) {
|
|
renderNoPreConsentCapture();
|
|
return;
|
|
}
|
|
|
|
preConsentCapture.hidden = false;
|
|
preConsentCaptureStart.hidden = capture.status !== "attention";
|
|
preConsentCaptureDecline.hidden = capture.status !== "attention";
|
|
|
|
if (capture.status === "recording") {
|
|
preConsentCaptureSummary.textContent = "Pre-Consent-Erfassung läuft.";
|
|
preConsentCaptureStatus.textContent =
|
|
"Provider-Announcement wurde gesichert; warte auf useractioncomplete.";
|
|
return;
|
|
}
|
|
|
|
preConsentCaptureSummary.textContent = buildPreConsentCaptureSummary(capture);
|
|
preConsentCaptureStatus.textContent = "";
|
|
}
|
|
|
|
function renderNoPreConsentCapture() {
|
|
preConsentCapture.hidden = true;
|
|
preConsentCaptureSummary.textContent = "";
|
|
preConsentCaptureStatus.textContent = "";
|
|
preConsentCaptureStart.disabled = false;
|
|
preConsentCaptureDecline.disabled = false;
|
|
}
|
|
|
|
function buildPreConsentCaptureSummary(capture) {
|
|
const eventLabel = capture.firstEventStatus ?? "TCF-Event";
|
|
const eventCount = Number(capture.eventCount ?? 0);
|
|
|
|
return `${eventLabel} erkannt, ${eventCount} Pre-Consent-Event(s) gepuffert.`;
|
|
}
|
|
|
|
async function startPreConsentCapture() {
|
|
await answerPreConsentCapture("start_pre_consent_capture");
|
|
}
|
|
|
|
async function declinePreConsentCapture() {
|
|
await answerPreConsentCapture("decline_pre_consent_capture");
|
|
}
|
|
|
|
async function answerPreConsentCapture(messageType) {
|
|
preConsentCaptureStart.disabled = true;
|
|
preConsentCaptureDecline.disabled = true;
|
|
|
|
try {
|
|
const activeTab = await getActiveTab();
|
|
|
|
if (!activeTab?.id) {
|
|
throw new Error("active_tab_unavailable");
|
|
}
|
|
|
|
const result = await browser.runtime.sendMessage({
|
|
type: messageType,
|
|
payload: {
|
|
tabId: activeTab.id
|
|
}
|
|
});
|
|
|
|
if (!result?.success) {
|
|
throw new Error(result?.error ?? messageType);
|
|
}
|
|
|
|
renderPreConsentCapture(result.capture);
|
|
} catch (error) {
|
|
preConsentCaptureStatus.textContent = "Aktion konnte nicht ausgeführt werden";
|
|
console.warn("VendorGet-IV pre-consent action failed", error);
|
|
} finally {
|
|
preConsentCaptureStart.disabled = false;
|
|
preConsentCaptureDecline.disabled = false;
|
|
}
|
|
}
|
|
|
|
async function getActiveTab() {
|
|
const tabs = await browser.tabs.query({
|
|
active: true,
|
|
currentWindow: true
|
|
});
|
|
|
|
return tabs[0] ?? null;
|
|
}
|
|
|
|
function openPurgeConfirmModal() {
|
|
evidencePurgeConfirmModal.hidden = false;
|
|
evidencePurgeCancelButton.focus();
|
|
}
|
|
|
|
function closePurgeConfirmModal() {
|
|
evidencePurgeConfirmModal.hidden = true;
|
|
evidencePurgeUnlockedButton.focus();
|
|
}
|
|
|
|
async function purgeUnlockedEvidence() {
|
|
closePurgeConfirmModal();
|
|
evidencePurgeUnlockedButton.disabled = true;
|
|
renderEvidenceRetentionMessage("Ungesperrte Evidence-Daten werden gelöscht...");
|
|
|
|
try {
|
|
const result = await browser.runtime.sendMessage({
|
|
type: "purge_unlocked_evidence_records"
|
|
});
|
|
|
|
if (!result?.success) {
|
|
throw new Error(result?.error ?? "purge_unlocked_evidence_records_failed");
|
|
}
|
|
|
|
await renderEvidenceRetentionStatus();
|
|
renderEvidenceRetentionMessage(buildPurgeUnlockedSuccessMessage(result));
|
|
} catch (error) {
|
|
renderEvidenceRetentionMessage("Löschen fehlgeschlagen");
|
|
console.warn("VendorGet-IV unlocked evidence purge failed", error);
|
|
} finally {
|
|
evidencePurgeUnlockedButton.disabled = false;
|
|
}
|
|
}
|
|
|
|
function buildPurgeUnlockedSuccessMessage(result) {
|
|
if (Number.isFinite(result.deletedCount)) {
|
|
const message = `Ungesperrte Evidence-Daten gelöscht: ${result.deletedCount} Records`;
|
|
|
|
if (Number(result.keptGvlWorkspaceProtectedCount ?? 0) > 0) {
|
|
return `${message}. Diese GVL-Evidence wurde noch nicht in den Vault exportiert.`;
|
|
}
|
|
|
|
return message;
|
|
}
|
|
|
|
return "Ungesperrte Evidence-Daten gelöscht";
|
|
}
|
|
|
|
async function exportEvidenceJsonFile() {
|
|
evidenceExportJsonButton.disabled = true;
|
|
renderEvidenceExportJsonMessage("Export läuft…");
|
|
|
|
try {
|
|
const result = await browser.runtime.sendMessage({
|
|
type: "export_evidence_json"
|
|
});
|
|
|
|
if (!result?.success || !result.export) {
|
|
throw new Error(result?.error ?? "export_evidence_json_failed");
|
|
}
|
|
|
|
downloadJsonExport(result.export);
|
|
renderEvidenceExportJsonMessage(buildExportSuccessMessage(result.export));
|
|
} catch (error) {
|
|
renderEvidenceExportJsonMessage("Export fehlgeschlagen");
|
|
console.warn("VendorGet-IV evidence JSON export failed", error);
|
|
} finally {
|
|
evidenceExportJsonButton.disabled = false;
|
|
}
|
|
}
|
|
|
|
function downloadJsonExport(exportContainer) {
|
|
const json = JSON.stringify(exportContainer, null, 2);
|
|
const blob = new Blob([json], { type: "application/json" });
|
|
const url = URL.createObjectURL(blob);
|
|
const downloadLink = document.createElement("a");
|
|
|
|
downloadLink.href = url;
|
|
downloadLink.download = `vendorget-evidence-export-${formatExportTimestamp(
|
|
new Date()
|
|
)}.json`;
|
|
document.body.append(downloadLink);
|
|
downloadLink.click();
|
|
downloadLink.remove();
|
|
|
|
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
}
|
|
|
|
function buildExportSuccessMessage(exportContainer) {
|
|
const storeCount = exportContainer?.metadata?.stores?.length ?? 0;
|
|
const totalRecordCount =
|
|
exportContainer?.metadata?.summary?.totalRecordCount ?? 0;
|
|
|
|
return `Export gespeichert: ${storeCount} Stores, ${totalRecordCount} Records`;
|
|
}
|
|
|
|
function formatExportTimestamp(date) {
|
|
const year = date.getFullYear();
|
|
const month = padDatePart(date.getMonth() + 1);
|
|
const day = padDatePart(date.getDate());
|
|
const hours = padDatePart(date.getHours());
|
|
const minutes = padDatePart(date.getMinutes());
|
|
const seconds = padDatePart(date.getSeconds());
|
|
|
|
return `${year}${month}${day}-${hours}${minutes}${seconds}`;
|
|
}
|
|
|
|
function padDatePart(value) {
|
|
return String(value).padStart(2, "0");
|
|
}
|
|
|
|
function renderEvidenceExportJsonMessage(message) {
|
|
evidenceExportJsonStatus.textContent = message;
|
|
}
|