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 ---
|
// --- 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) {
|
async function injectOnCustomDomain(tabId, tabUrl) {
|
||||||
const settings = await Storage.getSettings();
|
const settings = await Storage.getSettings();
|
||||||
const customDomains = settings.customDomains || [];
|
const customDomains = settings.customDomains || [];
|
||||||
@@ -362,6 +400,11 @@ api.storage.onChanged.addListener(async (changes, areaName) => {
|
|||||||
const settings = await Storage.getSettings();
|
const settings = await Storage.getSettings();
|
||||||
await updateIcon(settings);
|
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)
|
// Push to browser.storage.sync when local data changes (same-browser cross-device)
|
||||||
if (areaName === 'local' && settings.browserSync) {
|
if (areaName === 'local' && settings.browserSync) {
|
||||||
await SilentSendSync.pushToSyncStorage();
|
await SilentSendSync.pushToSyncStorage();
|
||||||
@@ -487,6 +530,7 @@ api.runtime.onInstalled.addListener(async () => {
|
|||||||
api.action.setBadgeBackgroundColor({ color: '#6b7280' });
|
api.action.setBadgeBackgroundColor({ color: '#6b7280' });
|
||||||
const settings = await Storage.getSettings();
|
const settings = await Storage.getSettings();
|
||||||
await updateIcon(settings);
|
await updateIcon(settings);
|
||||||
|
await syncCustomDomainScripts();
|
||||||
// Set up alarms on install
|
// Set up alarms on install
|
||||||
await setupAutoSyncAlarm();
|
await setupAutoSyncAlarm();
|
||||||
await setupOrgPolicyAlarm();
|
await setupOrgPolicyAlarm();
|
||||||
@@ -496,6 +540,7 @@ api.runtime.onInstalled.addListener(async () => {
|
|||||||
(async () => {
|
(async () => {
|
||||||
const settings = await Storage.getSettings();
|
const settings = await Storage.getSettings();
|
||||||
await updateIcon(settings);
|
await updateIcon(settings);
|
||||||
|
await syncCustomDomainScripts();
|
||||||
|
|
||||||
// Check if extension is locked (encrypted data, no cached key)
|
// Check if extension is locked (encrypted data, no cached key)
|
||||||
const locked = await Storage.isLocked();
|
const locked = await Storage.isLocked();
|
||||||
|
|||||||
@@ -620,9 +620,17 @@ function renderDomains() {
|
|||||||
btn.addEventListener('click', async () => {
|
btn.addEventListener('click', async () => {
|
||||||
const idx = parseInt(btn.dataset.index, 10);
|
const idx = parseInt(btn.dataset.index, 10);
|
||||||
const domains = settings.customDomains || [];
|
const domains = settings.customDomains || [];
|
||||||
domains.splice(idx, 1);
|
const removed = domains.splice(idx, 1)[0];
|
||||||
settings.customDomains = domains;
|
settings.customDomains = domains;
|
||||||
await Storage.saveSettings({ 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();
|
renderDomains();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user