83 lines
3.8 KiB
JavaScript
83 lines
3.8 KiB
JavaScript
/* =============================================
|
||
HELLION NEWTAB — background.js
|
||
Quick-Save Background fuer Chrome (Service-Worker)
|
||
UND Firefox (Event-Page). Kein DOM/window. Listener
|
||
synchron auf Top-Level. Geteilte Logik via importScripts.
|
||
============================================= */
|
||
|
||
// Geteiltes DOM-freies Helfer-Modul aus Phase 1: ensureInbox(boards), uid(), normalizeBookmark(...).
|
||
// Chrome-Service-Worker laedt es via importScripts. Firefox-Event-Page hat KEIN importScripts —
|
||
// dort kommt das Modul ueber background.scripts (manifest.firefox.json) in den Scope, ensureInbox
|
||
// ist dann schon definiert. Der Guard verhindert den ReferenceError in der Event-Page.
|
||
if (typeof importScripts === 'function' && typeof ensureInbox === 'undefined') {
|
||
importScripts('quicksave-core.js');
|
||
}
|
||
|
||
// chrome.storage.local-Lese-/Schreib-Helfer als Promises (kein Store-Modul im Worker,
|
||
// das ist DOM/Seiten-gebunden). Identisches Verhalten: get -> Wert oder null.
|
||
function bgGet(key) {
|
||
return new Promise(resolve => {
|
||
chrome.storage.local.get([key], r => resolve(r[key] ?? null));
|
||
});
|
||
}
|
||
|
||
function bgSet(key, value) {
|
||
return new Promise((resolve, reject) => {
|
||
chrome.storage.local.set({ [key]: value }, () => {
|
||
if (chrome.runtime.lastError) {
|
||
reject(new Error(chrome.runtime.lastError.message));
|
||
return;
|
||
}
|
||
resolve();
|
||
});
|
||
});
|
||
}
|
||
|
||
// Kurze Badge-Bestaetigung, dann automatisch wieder leeren. color optional (Default gruen).
|
||
function flashBadge(text, color) {
|
||
chrome.action.setBadgeText({ text });
|
||
// Hintergrundfarbe optional, ohne extra Permission moeglich.
|
||
if (chrome.action.setBadgeBackgroundColor) {
|
||
chrome.action.setBadgeBackgroundColor({ color: color || '#1f9d55' });
|
||
}
|
||
setTimeout(() => chrome.action.setBadgeText({ text: '' }), 2000);
|
||
}
|
||
|
||
// Interne/nicht speicherbare Seiten (Browser-UI, Extension-Seiten) — kein sinnvolles Bookmark.
|
||
const UNSAVEABLE_URL = /^(chrome|chrome-extension|about|edge|opera|moz-extension|brave|vivaldi|view-source|devtools):/i;
|
||
|
||
// Quick-Save: aktiven Tab in die Pending-Queue haengen — NICHT boards schreiben.
|
||
// Datensicherheit (Phase-4-Review 2b): boards schreibt ausschliesslich die NewTab-Seite. Der Worker
|
||
// haengt nur an 'quicksave_pending' an; die Seite drained die Queue in die Inbox. So koennen Worker
|
||
// und Seite sich nicht im boards-Array gegenseitig ueberschreiben (kein Lost-Update bestehender Daten).
|
||
async function quickSaveActiveTab() {
|
||
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
|
||
const tab = tabs && tabs[0];
|
||
if (!tab || !tab.url || UNSAVEABLE_URL.test(tab.url)) {
|
||
// Kein speicherbarer Tab: kurzer roter Marker (langer Text wird im Badge abgeschnitten).
|
||
flashBadge('×', '#c0392b');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// read-modify-write nur auf der EIGENEN Queue (bgGet/bgSet sind via quickSaveChain serialisiert).
|
||
const pending = (await bgGet('quicksave_pending')) ?? [];
|
||
pending.push({ id: uid(), title: tab.title || tab.url, url: tab.url });
|
||
await bgSet('quicksave_pending', pending);
|
||
flashBadge(chrome.i18n.getMessage('quickSaveBadge'));
|
||
} catch (e) {
|
||
// Quota o.ae.: Badge zeigt nichts Gruenes, Fehler in die Worker-Konsole.
|
||
console.error('Quick-Save fehlgeschlagen:', e.message);
|
||
}
|
||
}
|
||
|
||
// Quick-Saves serialisieren: zwei schnelle Tastendruecke (Key-Repeat) wuerden sonst parallel
|
||
// read-modify-write machen und sich gegenseitig ueberschreiben (lost update). Promise-Kette
|
||
// sorgt fuer sequentielle Ausfuehrung. Listener bleibt SYNCHRON auf Top-Level registriert.
|
||
let quickSaveChain = Promise.resolve();
|
||
chrome.commands.onCommand.addListener(command => {
|
||
if (command === 'quick-save') {
|
||
quickSaveChain = quickSaveChain.then(() => quickSaveActiveTab()).catch(e => console.error('Quick-Save:', e && e.message));
|
||
}
|
||
});
|