Add GamepadAPI, WebGL readPixels noise, auto-prune, import/export, badge
New fingerprint vectors: - Gamepad API: getGamepads() returns empty (prevents controller fingerprinting) - WebGL readPixels: seeded pixel noise on framebuffer reads New features: - Auto-prune: configurable automatic removal of inactive containers - Import/export: backup and restore all settings from options page - Toolbar badge: shows active container count - CHANGELOG.md: version history Bumped to v0.5.0 with 20 spoofed fingerprint vectors.
This commit is contained in:
@@ -155,6 +155,7 @@ async function getOrCreateContainerForDomain(baseDomain) {
|
||||
await browser.storage.local.set({ containerSeeds: seeds });
|
||||
|
||||
await buildProfileAndRegister(cookieStoreId, seeds[cookieStoreId]);
|
||||
await updateBadge();
|
||||
|
||||
return cookieStoreId;
|
||||
}
|
||||
@@ -251,6 +252,14 @@ browser.tabs.onRemoved.addListener((tabId) => {
|
||||
delete pendingTabs[tabId];
|
||||
});
|
||||
|
||||
// --- Badge: show active container count ---
|
||||
|
||||
async function updateBadge() {
|
||||
const count = Object.keys(domainMap).length;
|
||||
browser.browserAction.setBadgeText({ text: count > 0 ? String(count) : "" });
|
||||
browser.browserAction.setBadgeBackgroundColor({ color: "#4a9eff" });
|
||||
}
|
||||
|
||||
// --- Message Handling (from popup and options page) ---
|
||||
|
||||
browser.runtime.onMessage.addListener((message, sender) => {
|
||||
@@ -265,6 +274,10 @@ browser.runtime.onMessage.addListener((message, sender) => {
|
||||
if (message.type === "setWhitelist") return handleSetWhitelist(message.whitelist);
|
||||
if (message.type === "getVectorSettings") return handleGetVectorSettings();
|
||||
if (message.type === "setVectorSettings") return handleSetVectorSettings(message.vectorSettings);
|
||||
if (message.type === "exportSettings") return handleExportSettings();
|
||||
if (message.type === "importSettings") return handleImportSettings(message.data);
|
||||
if (message.type === "getAutoPruneSettings") return handleGetAutoPruneSettings();
|
||||
if (message.type === "setAutoPruneSettings") return handleSetAutoPruneSettings(message.settings);
|
||||
});
|
||||
|
||||
async function handleGetContainerList() {
|
||||
@@ -362,6 +375,7 @@ async function handleResetAll() {
|
||||
managedContainerIds.clear();
|
||||
for (const key of Object.keys(containerProfiles)) delete containerProfiles[key];
|
||||
await browser.storage.local.clear();
|
||||
await updateBadge();
|
||||
|
||||
return { ok: true };
|
||||
}
|
||||
@@ -381,9 +395,9 @@ async function handlePruneContainers() {
|
||||
await browser.contextualIdentities.remove(c.cookieStoreId);
|
||||
pruned++;
|
||||
} catch(e) {}
|
||||
// onRemoved listener handles domainMap + managedContainerIds cleanup
|
||||
}
|
||||
}
|
||||
await updateBadge();
|
||||
return { pruned };
|
||||
}
|
||||
|
||||
@@ -422,6 +436,82 @@ async function handleSetVectorSettings(vectorSettings) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
// --- Import/Export ---
|
||||
|
||||
async function handleExportSettings() {
|
||||
const stored = await browser.storage.local.get(null); // get everything
|
||||
return {
|
||||
version: browser.runtime.getManifest().version,
|
||||
exportedAt: new Date().toISOString(),
|
||||
domainMap,
|
||||
containerSeeds: stored.containerSeeds || {},
|
||||
containerSettings: stored.containerSettings || {},
|
||||
vectorSettings: stored.vectorSettings || {},
|
||||
whitelist: stored.whitelist || [],
|
||||
autoPrune: stored.autoPrune || { enabled: false, days: 30 }
|
||||
};
|
||||
}
|
||||
|
||||
async function handleImportSettings(data) {
|
||||
if (!data || !data.containerSeeds) return { ok: false, error: "Invalid data" };
|
||||
await browser.storage.local.set({
|
||||
containerSeeds: data.containerSeeds,
|
||||
containerSettings: data.containerSettings || {},
|
||||
vectorSettings: data.vectorSettings || {},
|
||||
whitelist: data.whitelist || [],
|
||||
autoPrune: data.autoPrune || { enabled: false, days: 30 }
|
||||
});
|
||||
cachedWhitelist = data.whitelist || [];
|
||||
if (data.domainMap) {
|
||||
domainMap = data.domainMap;
|
||||
await saveDomainMap();
|
||||
}
|
||||
await registerAllKnownContainers();
|
||||
await updateBadge();
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
// --- Auto-Prune ---
|
||||
|
||||
async function handleGetAutoPruneSettings() {
|
||||
const stored = await browser.storage.local.get("autoPrune");
|
||||
return stored.autoPrune || { enabled: false, days: 30 };
|
||||
}
|
||||
|
||||
async function handleSetAutoPruneSettings(settings) {
|
||||
await browser.storage.local.set({ autoPrune: settings });
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
async function runAutoPrune() {
|
||||
const stored = await browser.storage.local.get("autoPrune");
|
||||
const settings = stored.autoPrune || { enabled: false, days: 30 };
|
||||
if (!settings.enabled) return;
|
||||
|
||||
const tabs = await browser.tabs.query({});
|
||||
const activeContainers = new Set(tabs.map(t => t.cookieStoreId));
|
||||
|
||||
// Track last activity per container
|
||||
const actStored = await browser.storage.local.get("containerActivity");
|
||||
const activity = actStored.containerActivity || {};
|
||||
const now = Date.now();
|
||||
const cutoff = now - (settings.days * 24 * 60 * 60 * 1000);
|
||||
|
||||
for (const cid of managedContainerIds) {
|
||||
if (activeContainers.has(cid)) {
|
||||
activity[cid] = now; // update last active
|
||||
} else if (!activity[cid]) {
|
||||
activity[cid] = now; // first seen, set to now
|
||||
} else if (activity[cid] < cutoff) {
|
||||
// Inactive beyond threshold — prune
|
||||
try {
|
||||
await browser.contextualIdentities.remove(cid);
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
await browser.storage.local.set({ containerActivity: activity });
|
||||
}
|
||||
|
||||
// --- Container Lifecycle ---
|
||||
|
||||
browser.contextualIdentities.onRemoved.addListener(async ({ contextualIdentity }) => {
|
||||
@@ -507,6 +597,11 @@ async function init() {
|
||||
}
|
||||
cachedWhitelist = stored.whitelist || [];
|
||||
await registerAllKnownContainers();
|
||||
await updateBadge();
|
||||
|
||||
// Run auto-prune on startup and every 6 hours
|
||||
await runAutoPrune();
|
||||
setInterval(runAutoPrune, 6 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
Reference in New Issue
Block a user