diff --git a/manifest.firefox.json b/manifest.firefox.json index f0c056e..f1e5987 100644 --- a/manifest.firefox.json +++ b/manifest.firefox.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "2.0.5", + "version": "2.0.6", "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 ad9d1fa..4890862 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "2.0.5", + "version": "2.0.6", "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 e33f7f7..454ba73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "silent-send", - "version": "2.0.5", + "version": "2.0.6", "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 b0020fe..24eef4d 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -908,14 +908,60 @@ return SKIP_URL_PATTERNS.some(p => p.test(url)); } - window.fetch = async function (url, options) { + window.fetch = async function (input, init) { if (!settings.enabled || !hasSubstitutions()) { - return originalFetch.call(this, url, options); + return originalFetch.call(this, input, init); + } + + // Handle both fetch(url, options) and fetch(Request) signatures + let url, options; + if (input instanceof Request) { + url = input.url; + // Clone the Request so we can read/modify the body + options = { + method: input.method, + headers: input.headers, + body: null, // will read below + mode: input.mode, + credentials: input.credentials, + cache: input.cache, + redirect: input.redirect, + referrer: input.referrer, + signal: input.signal, + }; + // Read the body from the Request object + try { + const ct = input.headers.get('content-type') || ''; + if (ct.includes('json') || ct.includes('text')) { + options.body = await input.text(); + } else { + // Non-text body — pass through unmodified + return originalFetch.call(this, input, init); + } + } catch { + return originalFetch.call(this, input, init); + } + } else { + url = input; + options = init ? { ...init } : {}; } const urlStr = typeof url === 'string' ? url : url?.url || ''; const method = (options?.method || 'GET').toUpperCase(); + // Convert non-string bodies to string where possible + if (options.body && typeof options.body !== 'string' && !(options.body instanceof FormData)) { + try { + if (options.body instanceof Blob) { + options.body = await options.body.text(); + } else if (options.body instanceof ArrayBuffer || ArrayBuffer.isView(options.body)) { + options.body = new TextDecoder().decode(options.body); + } else if (options.body instanceof URLSearchParams) { + options.body = options.body.toString(); + } + } catch { /* leave as-is */ } + } + // Only intercept POST/PUT/PATCH with a body if ( (method === 'POST' || method === 'PUT' || method === 'PATCH') && diff --git a/src/options/options.html b/src/options/options.html index 05f5d7a..a4291ff 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -591,7 +591,7 @@