diff --git a/manifest.firefox.json b/manifest.firefox.json index 917c622..74406c3 100644 --- a/manifest.firefox.json +++ b/manifest.firefox.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "2.0.11", + "version": "2.0.12", "description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.", "browser_specific_settings": { "gecko": { diff --git a/manifest.json b/manifest.json index 608598c..6e8f86c 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "2.0.11", + "version": "2.0.12", "description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.", "permissions": [ "storage", diff --git a/package.json b/package.json index b78dfe4..321b0b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "silent-send", - "version": "2.0.11", + "version": "2.0.12", "private": true, "license": "BSL-1.1", "description": "Browser extension that substitutes personal data before sending to AI services", diff --git a/src/content/content.js b/src/content/content.js index f8d578a..c7e5031 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -905,11 +905,8 @@ // ============================================================ // Fetch Interception — scans ALL POST requests with a body. // Service-agnostic: doesn't depend on URL patterns. - // Uses __ssOriginalFetch from the early hook (injected synchronously - // before any page JS) to ensure we have the real fetch, even if - // frameworks like Next.js (ChatGPT) store a reference early. // ============================================================ - const originalFetch = window.__ssOriginalFetch || window.fetch; + const originalFetch = window.fetch; // URLs to never touch (static assets, analytics, etc.) const SKIP_URL_PATTERNS = [ @@ -1029,9 +1026,7 @@ return originalFetch.call(this, url, options); }; - // Register our fetch interceptor so the early hook proxy can use it - window.__ssInterceptFetch = window.fetch; - window.__ssReady = true; + // ============================================================ // Document Upload Processing @@ -1397,8 +1392,8 @@ // ============================================================ // XMLHttpRequest Interception — same aggressive approach // ============================================================ - const origOpen = window.__ssOriginalXHROpen || XMLHttpRequest.prototype.open; - const origSend = window.__ssOriginalXHRSend || XMLHttpRequest.prototype.send; + const origOpen = XMLHttpRequest.prototype.open; + const origSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function (method, url, ...rest) { this._ssUrl = url; diff --git a/src/content/injector.js b/src/content/injector.js index c802986..7bf78c4 100644 --- a/src/content/injector.js +++ b/src/content/injector.js @@ -15,24 +15,6 @@ if (window.__silentSendInjected) return; window.__silentSendInjected = true; - // Cross-browser API - const api = - typeof browser !== 'undefined' && browser.runtime - ? browser - : typeof chrome !== 'undefined' - ? chrome - : null; - - // IMMEDIATELY inject the early fetch hook into the page world as an - // EXTERNAL file. Must be external (not inline) because sites like - // claude.ai have strict CSP that blocks inline scripts. Firefox - // enforces this strictly; Chrome is more permissive but external - // works everywhere. - const earlyHook = document.createElement('script'); - earlyHook.src = api.runtime.getURL('src/content/early-hook.js'); - (document.head || document.documentElement).appendChild(earlyHook); - earlyHook.onload = () => earlyHook.remove(); - // Merge active profiles into flat identity object function mergeProfiles(data) { const profiles = data?.profiles || []; @@ -65,6 +47,14 @@ return merged; } + // Cross-browser API + const api = + typeof browser !== 'undefined' && browser.runtime + ? browser + : typeof chrome !== 'undefined' + ? chrome + : null; + // Load mappings and settings, then inject into page async function init() { const result = await api.storage.local.get(['ss_mappings', 'ss_identity', 'ss_settings']); @@ -80,8 +70,7 @@ // Merge active profiles into a flat identity object for the content script const identity = mergeProfiles(identityData); - // Load the full content.js which will use __ssOriginalFetch - // (captured by the early hook above) and set __ssReady = true + // 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 })); script.src = api.runtime.getURL('src/content/content.js'); diff --git a/src/options/options.html b/src/options/options.html index 185c7cf..3ea99c4 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -591,7 +591,7 @@