feat: custom domains for OpenWebUI + fix README issues
- Add custom domain support in Options page so users can add self-hosted AI services (e.g. https://ai.myserver.com) - Background worker dynamically injects content scripts on custom domains using scripting.executeScript - Add optional_host_permissions so Chrome can grant per-domain access - Rewrite README: add clone step to Firefox instructions, clarify what "credentials" means in step 3, add Windows commands alongside Mac/Linux for every terminal step - Bump version to 0.2.0 https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw
This commit is contained in:
+59
-53
@@ -8,63 +8,69 @@
|
||||
* Communication: page script <-> content script via window.postMessage
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// Cross-browser API
|
||||
const api =
|
||||
typeof browser !== 'undefined' && browser.runtime
|
||||
? browser
|
||||
: typeof chrome !== 'undefined'
|
||||
? chrome
|
||||
: null;
|
||||
// Prevent double-injection on custom domains
|
||||
if (window.__silentSendInjected) return;
|
||||
window.__silentSendInjected = true;
|
||||
|
||||
// Load mappings and settings, then inject into page
|
||||
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 };
|
||||
// Cross-browser API
|
||||
const api =
|
||||
typeof browser !== 'undefined' && browser.runtime
|
||||
? browser
|
||||
: typeof chrome !== 'undefined'
|
||||
? chrome
|
||||
: null;
|
||||
|
||||
// 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');
|
||||
(document.head || document.documentElement).appendChild(script);
|
||||
script.onload = () => script.remove();
|
||||
// Load mappings and settings, then inject into page
|
||||
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 };
|
||||
|
||||
// Listen for substitution events from the page script
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source !== window) return;
|
||||
if (event.data?.type === 'ss:substitution-performed') {
|
||||
api.runtime.sendMessage({
|
||||
type: 'substitution:performed',
|
||||
count: event.data.count,
|
||||
replacements: event.data.replacements,
|
||||
}).catch(() => {});
|
||||
}
|
||||
});
|
||||
// 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');
|
||||
(document.head || document.documentElement).appendChild(script);
|
||||
script.onload = () => script.remove();
|
||||
|
||||
// Forward storage changes to the page script
|
||||
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,
|
||||
}, '*');
|
||||
}
|
||||
});
|
||||
// Listen for substitution events from the page script
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source !== window) return;
|
||||
if (event.data?.type === 'ss:substitution-performed') {
|
||||
api.runtime.sendMessage({
|
||||
type: 'substitution:performed',
|
||||
count: event.data.count,
|
||||
replacements: event.data.replacements,
|
||||
}).catch(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for settings updates from popup via runtime messages
|
||||
api.runtime.onMessage.addListener((message) => {
|
||||
if (message.type === 'settings:updated') {
|
||||
window.postMessage({
|
||||
type: 'ss:config-updated',
|
||||
settings: message.settings,
|
||||
}, '*');
|
||||
}
|
||||
});
|
||||
}
|
||||
// Forward storage changes to the page script
|
||||
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,
|
||||
}, '*');
|
||||
}
|
||||
});
|
||||
|
||||
init();
|
||||
// Listen for settings updates from popup via runtime messages
|
||||
api.runtime.onMessage.addListener((message) => {
|
||||
if (message.type === 'settings:updated') {
|
||||
window.postMessage({
|
||||
type: 'ss:config-updated',
|
||||
settings: message.settings,
|
||||
}, '*');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user