Merge pull request #25 from outis1one/claude/read-repo-YMu21
feat: dynamic content script registration for custom domains
This commit is contained in:
@@ -61,6 +61,44 @@ api.tabs.onRemoved.addListener((tabId) => {
|
||||
|
||||
// --- Dynamic injection for custom domains ---
|
||||
|
||||
const DYNAMIC_SCRIPT_ID = 'ss-custom-domains';
|
||||
|
||||
/**
|
||||
* Sync the dynamically registered content script with the current
|
||||
* custom domains list. Uses scripting.registerContentScripts so custom
|
||||
* domains inject at document_start (like built-in sites) and persist
|
||||
* across service worker restarts.
|
||||
*/
|
||||
async function syncCustomDomainScripts() {
|
||||
const settings = await Storage.getSettings();
|
||||
const customDomains = settings.customDomains || [];
|
||||
|
||||
// Build match patterns from domains (e.g. "https://my-ai.com" → "https://my-ai.com/*")
|
||||
const matches = customDomains.map(d => d.replace(/\/$/, '') + '/*');
|
||||
|
||||
try {
|
||||
// Remove existing dynamic script first
|
||||
await api.scripting.unregisterContentScripts({ ids: [DYNAMIC_SCRIPT_ID] }).catch(() => {});
|
||||
|
||||
if (matches.length > 0) {
|
||||
await api.scripting.registerContentScripts([{
|
||||
id: DYNAMIC_SCRIPT_ID,
|
||||
matches,
|
||||
js: ['src/content/injector.js'],
|
||||
css: ['src/content/content.css'],
|
||||
runAt: 'document_start',
|
||||
allFrames: true,
|
||||
}]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[Silent Send] Failed to register custom domain scripts:', e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject on an already-open tab for a newly added custom domain.
|
||||
* Only needed for tabs that were open before the content script was registered.
|
||||
*/
|
||||
async function injectOnCustomDomain(tabId, tabUrl) {
|
||||
const settings = await Storage.getSettings();
|
||||
const customDomains = settings.customDomains || [];
|
||||
@@ -362,6 +400,11 @@ api.storage.onChanged.addListener(async (changes, areaName) => {
|
||||
const settings = await Storage.getSettings();
|
||||
await updateIcon(settings);
|
||||
|
||||
// Re-register dynamic content scripts when custom domains change
|
||||
if (changes.ss_settings && areaName === 'local') {
|
||||
await syncCustomDomainScripts();
|
||||
}
|
||||
|
||||
// Push to browser.storage.sync when local data changes (same-browser cross-device)
|
||||
if (areaName === 'local' && settings.browserSync) {
|
||||
await SilentSendSync.pushToSyncStorage();
|
||||
@@ -487,6 +530,7 @@ api.runtime.onInstalled.addListener(async () => {
|
||||
api.action.setBadgeBackgroundColor({ color: '#6b7280' });
|
||||
const settings = await Storage.getSettings();
|
||||
await updateIcon(settings);
|
||||
await syncCustomDomainScripts();
|
||||
// Set up alarms on install
|
||||
await setupAutoSyncAlarm();
|
||||
await setupOrgPolicyAlarm();
|
||||
@@ -496,6 +540,7 @@ api.runtime.onInstalled.addListener(async () => {
|
||||
(async () => {
|
||||
const settings = await Storage.getSettings();
|
||||
await updateIcon(settings);
|
||||
await syncCustomDomainScripts();
|
||||
|
||||
// Check if extension is locked (encrypted data, no cached key)
|
||||
const locked = await Storage.isLocked();
|
||||
|
||||
@@ -620,9 +620,17 @@ function renderDomains() {
|
||||
btn.addEventListener('click', async () => {
|
||||
const idx = parseInt(btn.dataset.index, 10);
|
||||
const domains = settings.customDomains || [];
|
||||
domains.splice(idx, 1);
|
||||
const removed = domains.splice(idx, 1)[0];
|
||||
settings.customDomains = domains;
|
||||
await Storage.saveSettings({ customDomains: domains });
|
||||
|
||||
// Revoke browser permission for the removed domain
|
||||
if (removed) {
|
||||
try {
|
||||
await api.permissions.remove({ origins: [removed + '/*'] });
|
||||
} catch (e) { /* non-fatal */ }
|
||||
}
|
||||
|
||||
renderDomains();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user