"use strict"; const gvlSnapshotEmpty = document.getElementById("gvl-snapshot-empty"); const gvlSnapshotContent = document.getElementById("gvl-snapshot-content"); const gvlSnapshotList = document.getElementById("gvl-snapshot-list"); const gvlSnapshotSummary = document.getElementById("gvl-snapshot-summary"); const gvlTechnicalFields = document.getElementById("gvl-technical-fields"); const gvlDebugData = document.getElementById("gvl-debug-data"); const gvlFetchOfficialButton = document.getElementById( "gvl-fetch-official-button" ); const gvlFetchStatus = document.getElementById("gvl-fetch-status"); let gvlSnapshots = []; let selectedSnapshotSha256 = null; document.addEventListener("DOMContentLoaded", async () => { gvlFetchOfficialButton.addEventListener("click", async () => { await fetchOfficialGvl(); }); await renderGvlSnapshots(); }); async function fetchOfficialGvl() { gvlFetchOfficialButton.disabled = true; renderFetchStatus("Vendorliste wird abgerufen..."); try { const result = await browser.runtime.sendMessage({ type: "fetch_official_gvl" }); if (!result?.success) { throw new Error(result?.error ?? "official_gvl_fetch_failed"); } renderFetchStatus( result.alreadyKnown ? "Vendorliste bereits bekannt." : "Vendorliste abgerufen." ); await renderGvlSnapshots(); await renderSelectedGvlSnapshotSummary(); } catch (error) { renderFetchStatus("Vendorliste konnte nicht abgerufen werden."); console.warn("VG-Observe manual official GVL fetch failed", error); } finally { gvlFetchOfficialButton.disabled = false; } } function renderFetchStatus(message) { gvlFetchStatus.textContent = message; } async function renderGvlSnapshots() { try { const result = await browser.runtime.sendMessage({ type: "list_gvl_snapshots" }); if (!result?.success) { throw new Error(result?.error ?? "list_gvl_snapshots_failed"); } gvlSnapshots = result.gvlSnapshots ?? []; if (gvlSnapshots.length === 0) { renderNoGvlSnapshots(); return; } gvlSnapshotEmpty.hidden = true; gvlSnapshotContent.hidden = false; if (!findGvlSnapshot(selectedSnapshotSha256)) { selectedSnapshotSha256 = gvlSnapshots[0]?.sha256 ?? null; } renderGvlSnapshotList(); await renderSelectedGvlSnapshotSummary(); } catch (error) { gvlSnapshotEmpty.hidden = false; gvlSnapshotContent.hidden = true; gvlSnapshotEmpty.textContent = "Gespeicherte Vendorlisten konnten nicht geladen werden."; console.warn("VG-Observe GVL snapshot list failed", error); } } function renderNoGvlSnapshots() { gvlSnapshotList.textContent = ""; clearGvlSnapshotSummary(); gvlSnapshotEmpty.hidden = false; gvlSnapshotContent.hidden = true; gvlSnapshotEmpty.textContent = "Keine gespeicherten offiziellen Vendorlisten vorhanden."; } function renderGvlSnapshotList() { gvlSnapshotList.textContent = ""; for (const snapshot of gvlSnapshots) { const row = document.createElement("tr"); const isSelected = snapshot?.sha256 === selectedSnapshotSha256; row.className = isSelected ? "is-selected" : ""; row.tabIndex = 0; row.setAttribute("role", "button"); row.setAttribute("aria-pressed", isSelected ? "true" : "false"); row.addEventListener("click", async () => { await selectGvlSnapshot(snapshot?.sha256 ?? null); }); row.addEventListener("keydown", async (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); await selectGvlSnapshot(snapshot?.sha256 ?? null); } }); appendListCell(row, formatNullable(snapshot?.vendorListVersion), "numeric"); appendListCell(row, formatNullable(snapshot?.fetchedAt)); appendListCell(row, shortenSha256(snapshot?.sha256), "sha-cell"); appendListCell(row, formatNullable(snapshot?.sourceUrl), "url-cell"); gvlSnapshotList.append(row); } } function appendListCell(row, value, className) { const cell = document.createElement("td"); if (className) { cell.className = className; } cell.textContent = value; row.append(cell); } async function selectGvlSnapshot(sha256) { selectedSnapshotSha256 = sha256; renderGvlSnapshotList(); await renderSelectedGvlSnapshotSummary(); } async function renderSelectedGvlSnapshotSummary() { const snapshot = findGvlSnapshot(selectedSnapshotSha256); clearGvlSnapshotSummary(); if (!snapshot) { return; } try { const result = await browser.runtime.sendMessage({ type: "get_gvl_snapshot_summary", payload: { sha256: snapshot.sha256 } }); if (!result?.success) { throw new Error(result?.error ?? "get_gvl_snapshot_summary_failed"); } renderSummaryTable(result.summary ?? {}); } catch (error) { gvlSnapshotSummary.textContent = "Zusammenfassung dieser Vendorliste konnte nicht geladen werden."; console.warn("VG-Observe GVL snapshot summary failed", error); } } function renderSummaryTable(summary) { const table = document.createElement("table"); const body = document.createElement("tbody"); const rows = [ ["Vendorlisten-Version", formatNullable(summary.vendorListVersion)], ["Abrufzeitpunkt", formatNullable(summary.fetchedAt)], ["Quelle", formatNullable(summary.sourceUrl)], ["Anzahl Firmen/Vendoren", formatCount(summary.vendorCount)], ["Anzahl Zwecke/Purposes", formatCount(summary.purposeCount)], ["Anzahl Special Purposes", formatCount(summary.specialPurposeCount)], ["Anzahl Features", formatCount(summary.featureCount)], ["Anzahl Special Features", formatCount(summary.specialFeatureCount)], ["Anzahl Datenkategorien", formatCount(summary.dataCategoryCount)], [ "Anzahl Vendor-Beziehungen", formatCount(summary.vendorRelationshipCount) ] ]; table.className = "summary-table"; for (const [label, value] of rows) { const row = document.createElement("tr"); const labelCell = document.createElement("th"); const valueCell = document.createElement("td"); labelCell.scope = "row"; labelCell.textContent = label; valueCell.textContent = value; row.append(labelCell, valueCell); body.append(row); } table.append(body); gvlSnapshotSummary.append(table); gvlTechnicalFields.textContent = JSON.stringify( summary.technicalFields ?? {}, null, 2 ); gvlDebugData.textContent = JSON.stringify( { sha256: summary.sha256 ?? null, eventType: summary.eventType ?? null, eventCapturedAt: summary.eventCapturedAt ?? null, diagnostics: summary.diagnostics ?? null }, null, 2 ); } function clearGvlSnapshotSummary() { gvlSnapshotSummary.textContent = ""; gvlTechnicalFields.textContent = ""; gvlDebugData.textContent = ""; } function findGvlSnapshot(sha256) { if (!sha256) { return null; } return ( gvlSnapshots.find((snapshot) => { return snapshot?.sha256 === sha256; }) ?? null ); } function formatNullable(value) { if (value === null || value === undefined || value === "") { return "-"; } return String(value); } function formatCount(value) { if (value === null || value === undefined) { return "0"; } return String(value); } function shortenSha256(value) { if (!value) { return "-"; } return `${String(value).slice(0, 12)}...`; }