From 684413f5fe1e5504bee921f42c3d2687544ee792 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Mar 2026 04:08:02 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20username/hostname=20not=20substituting?= =?UTF-8?q?=20=E2=80=94=20injector=20wasn't=20merging=20profiles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the multi-profile migration, ss_identity changed from a flat object { names, emails, ... } to { profiles: [...] }. The injector was passing the raw profiles wrapper to the content script, which expected the flat format. Now the injector merges active profiles into a flat identity object before injecting into the page world, and also merges on storage change events. Also handles legacy format (pre-profile data) for backward compatibility. https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw --- src/content/injector.js | 50 ++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/src/content/injector.js b/src/content/injector.js index f42a1c1..048e93f 100644 --- a/src/content/injector.js +++ b/src/content/injector.js @@ -15,6 +15,38 @@ if (window.__silentSendInjected) return; window.__silentSendInjected = true; + // Merge active profiles into flat identity object + function mergeProfiles(data) { + const profiles = data?.profiles || []; + const active = profiles.filter(p => p.active); + + if (active.length === 0) { + // Legacy format: data IS the flat identity (pre-profile migration) + if (data && (data.names || data.emails || data.usernames)) return data; + return { emails: [], names: [], usernames: [], hostnames: [], phones: [], + catchAllEmail: '', emailDomains: [], + enabled: { emails: true, names: true, usernames: true, phones: true, paths: true } }; + } + + const merged = { + emails: [], names: [], usernames: [], hostnames: [], phones: [], + catchAllEmail: '', emailDomains: [], + enabled: { emails: true, names: true, usernames: true, phones: true, paths: true }, + }; + + for (const p of active) { + merged.emails.push(...(p.emails || [])); + merged.names.push(...(p.names || [])); + merged.usernames.push(...(p.usernames || [])); + merged.hostnames.push(...(p.hostnames || [])); + merged.phones.push(...(p.phones || [])); + if (p.catchAllEmail && !merged.catchAllEmail) merged.catchAllEmail = p.catchAllEmail; + merged.emailDomains.push(...(p.emailDomains || [])); + } + + return merged; + } + // Cross-browser API const api = typeof browser !== 'undefined' && browser.runtime @@ -27,9 +59,12 @@ async function init() { const result = await api.storage.local.get(['ss_mappings', 'ss_identity', 'ss_settings']); const mappings = result.ss_mappings || []; - const identity = result.ss_identity || {}; const settings = result.ss_settings || { enabled: true }; + // Merge active profiles into a flat identity object for the content script + const identityData = result.ss_identity || {}; + const identity = mergeProfiles(identityData); + // Inject the main interception script into the page's world const script = document.createElement('script'); script.setAttribute('data-ss-config', JSON.stringify({ mappings, identity, settings })); @@ -71,15 +106,14 @@ } }); - // Forward storage changes to the page script + // Forward storage changes to the page script (merge profiles before sending) api.storage.onChanged.addListener((changes) => { if (changes.ss_mappings || changes.ss_identity || changes.ss_settings) { - window.postMessage({ - type: 'ss:config-updated', - mappings: changes.ss_mappings?.newValue, - identity: changes.ss_identity?.newValue, - settings: changes.ss_settings?.newValue, - }, '*'); + const msg = { type: 'ss:config-updated' }; + if (changes.ss_mappings) msg.mappings = changes.ss_mappings.newValue; + if (changes.ss_identity) msg.identity = mergeProfiles(changes.ss_identity.newValue); + if (changes.ss_settings) msg.settings = changes.ss_settings.newValue; + window.postMessage(msg, '*'); } });