mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-26 12:08:15 +00:00
fix(extension): stop storing room/settings in chrome.storage.sync
Room ID, password, and username were resurrected from synced storage on a fresh install (sync survives an uninstall in the user's Google account), which made the extension silently auto-connect to a dead room and appear permanently connected. getSettings() and all settings reads (popup, content, audio-options, applyAudioSettingsToTab) are now local-only, and legacy keys are actively purged from sync on install/update/startup. Only onboardingComplete and dismissedHints remain in sync. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -126,17 +126,13 @@ function setCustomParam(param, value) {
|
||||
}
|
||||
|
||||
async function init() {
|
||||
let audioData = (await chrome.storage.local.get(['audioSettings'])).audioSettings;
|
||||
const syncData = await chrome.storage.sync.get(['audioSettings', 'locale']);
|
||||
if (!audioData && syncData.audioSettings) {
|
||||
audioData = syncData.audioSettings;
|
||||
await chrome.storage.local.set({ audioSettings: audioData });
|
||||
}
|
||||
const lang = syncData.locale || getSystemLanguage();
|
||||
// Local-only: audioSettings/locale are never read from storage.sync.
|
||||
const { audioSettings, locale } = await chrome.storage.local.get(['audioSettings', 'locale']);
|
||||
const lang = locale || getSystemLanguage();
|
||||
await loadLocale(lang);
|
||||
translateDOM();
|
||||
|
||||
currentSettings = mergeAudioSettings(audioData);
|
||||
currentSettings = mergeAudioSettings(audioSettings);
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
+22
-28
@@ -43,11 +43,13 @@ async function initUninstallURL() {
|
||||
chrome.runtime.onInstalled.addListener((details) => {
|
||||
if (details.reason === 'install' || details.reason === 'update') {
|
||||
initUninstallURL();
|
||||
purgeLegacySyncKeys();
|
||||
}
|
||||
});
|
||||
|
||||
chrome.runtime.onStartup.addListener(() => {
|
||||
initUninstallURL();
|
||||
purgeLegacySyncKeys();
|
||||
});
|
||||
|
||||
// --- State Management ---
|
||||
@@ -286,29 +288,14 @@ async function getPeerId() {
|
||||
}
|
||||
|
||||
async function getSettings() {
|
||||
// Try local (per-device) first, fall back to sync for migration
|
||||
let data = await chrome.storage.local.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username']);
|
||||
let migrated = false;
|
||||
if (!data.username) {
|
||||
const syncData = await chrome.storage.sync.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username']);
|
||||
if (syncData.username || syncData.roomId) {
|
||||
data = syncData;
|
||||
migrated = true;
|
||||
}
|
||||
}
|
||||
// Local-only by design. Room credentials (roomId/password) and identity
|
||||
// (username) must NEVER come from storage.sync — syncing them across devices
|
||||
// both leaks them and resurrects dead rooms on reinstall (a fresh install
|
||||
// has empty local storage but sync survives in the user's Google account).
|
||||
const data = await chrome.storage.local.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username']);
|
||||
let username = data.username;
|
||||
if (!username) {
|
||||
username = generateUsername();
|
||||
}
|
||||
if (migrated) {
|
||||
await chrome.storage.local.set({
|
||||
serverUrl: data.serverUrl || '',
|
||||
useCustomServer: data.useCustomServer || false,
|
||||
roomId: data.roomId || '',
|
||||
password: data.password || '',
|
||||
username
|
||||
});
|
||||
} else if (!data.username) {
|
||||
await chrome.storage.local.set({ username });
|
||||
}
|
||||
return {
|
||||
@@ -320,6 +307,19 @@ async function getSettings() {
|
||||
};
|
||||
}
|
||||
|
||||
// Privacy + correctness: only onboardingComplete and dismissedHints belong in
|
||||
// storage.sync. Everything else is per-device local storage. This actively
|
||||
// removes legacy keys that older versions wrote to sync (and that would
|
||||
// otherwise be redistributed across devices and resurrected on reinstall).
|
||||
const LEGACY_SYNC_KEYS = [
|
||||
'serverUrl', 'useCustomServer', 'roomId', 'password', 'username',
|
||||
'filterNoise', 'autoSyncNextEpisode', 'forceSyncMode',
|
||||
'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings'
|
||||
];
|
||||
function purgeLegacySyncKeys() {
|
||||
chrome.storage.sync.remove(LEGACY_SYNC_KEYS).catch(() => {});
|
||||
}
|
||||
|
||||
function addLog(message, type = 'info') {
|
||||
const log = {
|
||||
timestamp: new Date().toISOString(),
|
||||
@@ -1494,14 +1494,8 @@ function resetAudioProcessingInTab(tabId) {
|
||||
|
||||
async function applyAudioSettingsToTab(tabId) {
|
||||
if (!tabId) return;
|
||||
let data = (await chrome.storage.local.get(['audioSettings']));
|
||||
if (!data.audioSettings) {
|
||||
const syncData = await chrome.storage.sync.get(['audioSettings']);
|
||||
if (syncData.audioSettings) {
|
||||
data = syncData;
|
||||
await chrome.storage.local.set({ audioSettings: syncData.audioSettings });
|
||||
}
|
||||
}
|
||||
// Local-only: audioSettings are never read from storage.sync.
|
||||
const data = await chrome.storage.local.get(['audioSettings']);
|
||||
chrome.tabs.sendMessage(tabId, {
|
||||
action: 'APPLY_AUDIO_SETTINGS',
|
||||
settings: data.audioSettings
|
||||
|
||||
+1
-18
@@ -89,25 +89,8 @@
|
||||
let _audioSettings = null;
|
||||
let _audioProcessingAllowed = true;
|
||||
|
||||
// Cache the autoSyncNextEpisode setting
|
||||
// Cache the autoSyncNextEpisode setting (local-only; never read from sync)
|
||||
chrome.storage.local.get(['autoSyncNextEpisode', 'audioSettings'], (data) => {
|
||||
if (data.autoSyncNextEpisode === undefined || data.audioSettings === undefined) {
|
||||
chrome.storage.sync.get(['autoSyncNextEpisode', 'audioSettings'], (syncData) => {
|
||||
const migrate = {};
|
||||
if (data.autoSyncNextEpisode === undefined && syncData.autoSyncNextEpisode !== undefined) {
|
||||
migrate.autoSyncNextEpisode = syncData.autoSyncNextEpisode;
|
||||
}
|
||||
if (data.audioSettings === undefined && syncData.audioSettings !== undefined) {
|
||||
migrate.audioSettings = syncData.audioSettings;
|
||||
}
|
||||
if (Object.keys(migrate).length) chrome.storage.local.set(migrate);
|
||||
_autoSyncEnabled = syncData.autoSyncNextEpisode !== false;
|
||||
_audioSettings = mergeAudioSettings(syncData.audioSettings);
|
||||
const v = findVideo();
|
||||
if (v && _audioProcessingAllowed) applyAudioSettings(v, _audioSettings);
|
||||
});
|
||||
return;
|
||||
}
|
||||
_autoSyncEnabled = data.autoSyncNextEpisode !== false;
|
||||
_audioSettings = mergeAudioSettings(data.audioSettings);
|
||||
const video = findVideo();
|
||||
|
||||
+2
-12
@@ -175,19 +175,9 @@ function setRoomRefreshCooldown() {
|
||||
|
||||
// --- Initialization ---
|
||||
async function init() {
|
||||
// Local-only by design — settings and room credentials never come from
|
||||
// storage.sync (only onboardingComplete + dismissedHints live there).
|
||||
const localData = await chrome.storage.local.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username', 'filterNoise', 'autoSyncNextEpisode', 'forceSyncMode', 'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings', 'activeTab']);
|
||||
// Migrate preferences from sync → local for existing users
|
||||
const oldSync = await chrome.storage.sync.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username', 'filterNoise', 'autoSyncNextEpisode', 'forceSyncMode', 'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings']);
|
||||
const toMigrate = {};
|
||||
for (const key of ['serverUrl', 'useCustomServer', 'roomId', 'password', 'username', 'filterNoise', 'autoSyncNextEpisode', 'forceSyncMode', 'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings']) {
|
||||
if (localData[key] === undefined && oldSync[key] !== undefined) {
|
||||
toMigrate[key] = oldSync[key];
|
||||
localData[key] = oldSync[key];
|
||||
}
|
||||
}
|
||||
if (Object.keys(toMigrate).length) {
|
||||
await chrome.storage.local.set(toMigrate);
|
||||
}
|
||||
|
||||
let activeLang = localData.locale;
|
||||
if (!activeLang) {
|
||||
|
||||
Reference in New Issue
Block a user