diff --git a/src/entrypoints/background/index.ts b/src/entrypoints/background/index.ts index 3c98631..7fc4652 100644 --- a/src/entrypoints/background/index.ts +++ b/src/entrypoints/background/index.ts @@ -4,19 +4,54 @@ import { HostSettings, UrlReferer } from '@/lib/settings'; export default defineBackground(() => { browser.runtime.onMessage.addListener(async (message, sender) => { - const messageType = message.type as BackgroundMessageType; - const messageData = message.data as BackgroundMessageData; + const type = message.type as BackgroundMessageType; + let data = message.data; let response; - switch (messageType) { - case BackgroundMessageType.Ff2mpv: - await browser.runtime.sendNativeMessage('ff2mpv', { url: messageData!.url }); + + switch (type) { + case BackgroundMessageType.Ff2mpv: { + data = data as BackgroundMessageData; + + await browser.runtime.sendNativeMessage('ff2mpv', { url: data.url }); break; - case BackgroundMessageType.RequestTabUrl: + } + case BackgroundMessageType.RequestTabUrl: { response = sender.tab?.url ?? null; break; + } + case BackgroundMessageType.RegisterContentScript: { + // requires "dynamic" host permissions, which is only available in mv2 + if (import.meta.env.MANIFEST_VERSION === 3) break; + + data = data as BackgroundMessageData; + + const contentScript: Browser.scripting.RegisteredContentScript = { + id: 'temporary-hosts', + js: ['content-scripts/content.js'], + matches: [`*://${data.domain}/*`], + persistAcrossSessions: false, + allFrames: true, + runAt: 'document_end' + }; + + const contentScripts = await browser.scripting.getRegisteredContentScripts({ ids: [contentScript.id] }); + if (contentScripts.length !== 0) { + const registeredContentScript = contentScripts[0]; + + // do not double register for same domain + if (registeredContentScript.matches!.indexOf(contentScript.matches![0]) !== -1) break; + + contentScript.matches!.push(...contentScripts[0].matches!); + await browser.scripting.updateContentScripts([contentScript]); + } else { + await browser.scripting.registerContentScripts([contentScript]); + } + + break; + } default: - return; + break; } return response; diff --git a/src/entrypoints/content/index.ts b/src/entrypoints/content/index.ts index 4d3a746..29c094c 100644 --- a/src/entrypoints/content/index.ts +++ b/src/entrypoints/content/index.ts @@ -3,11 +3,7 @@ import { getHost, HostMatchType, hosts, type HostMatch } from '@/lib/host'; import { FF2MPVSettings, PerDomainSettings } from '@/lib/settings'; export default defineContentScript({ - matches: [ - ...Object.values(hosts).flatMap((h) => h.domains.map((d) => `*://${d}/*`)), - // only mv2 allows to match all urls - ...(import.meta.env.MANIFEST_VERSION === 2 ? [''] : []) - ], + matches: [...Object.values(hosts).flatMap((h) => h.domains.map((d) => `*://${d}/*`))], allFrames: true, runAt: 'document_end', main diff --git a/src/lib/communication.ts b/src/lib/communication.ts index 7daae85..6daa955 100644 --- a/src/lib/communication.ts +++ b/src/lib/communication.ts @@ -1,6 +1,6 @@ // --- tab communication --- // export enum TabMessageType { - RequestActiveMatch, + RequestActiveMatch = 10, NotifyActiveMatch } @@ -35,8 +35,9 @@ export function listenTabMessages(listener: (type: TabMessageType, data: any) => // --- background script communication --- // export enum BackgroundMessageType { - Ff2mpv, - RequestTabUrl + Ff2mpv = 20, + RequestTabUrl, + RegisterContentScript } export type BackgroundMessageData = { @@ -44,11 +45,15 @@ export type BackgroundMessageData = { url: string; }; [BackgroundMessageType.RequestTabUrl]: undefined; + [BackgroundMessageType.RegisterContentScript]: { + domain: string; + }; }[T]; export type BackgroundMessageReply = { [BackgroundMessageType.Ff2mpv]: undefined; [BackgroundMessageType.RequestTabUrl]: string | null; + [BackgroundMessageType.RegisterContentScript]: undefined; }[T]; export async function sendBackgroundMessage( diff --git a/src/lib/settings.ts b/src/lib/settings.ts index 7e6c103..2496cc7 100644 --- a/src/lib/settings.ts +++ b/src/lib/settings.ts @@ -1,4 +1,5 @@ import { storage } from '#imports'; +import { BackgroundMessageType, sendBackgroundMessage } from './communication'; import type { HostId } from '@/lib/host'; class Setting { @@ -38,11 +39,19 @@ export class HostSettings { /* tmp */ private static temporaryHostDomain = new Setting>('local:temporaryHostDomain', {}); - static addTemporaryHostDomain = (hostId: HostId, domain: string) => - this.temporaryHostDomain.update((val) => { + static addTemporaryHostDomain = async (hostId: HostId, domain: string) => { + // only has an effect with mv2 + const backgroundScriptInject = + import.meta.env.MANIFEST_VERSION === 2 + ? sendBackgroundMessage(BackgroundMessageType.RegisterContentScript, { domain: domain }) + : Promise.resolve(); + const temporaryHostDomainUpdate = this.temporaryHostDomain.update((val) => { val[domain] = hostId; return val; }); + + return Promise.all([backgroundScriptInject, temporaryHostDomainUpdate]); + }; static checkTemporaryHostDomain = (domain: string) => this.temporaryHostDomain.get().then((val) => val[domain]); } diff --git a/wxt.config.ts b/wxt.config.ts index 6a2d364..4f16c7b 100644 --- a/wxt.config.ts +++ b/wxt.config.ts @@ -26,7 +26,10 @@ export default defineConfig({ gecko_android: {} } : undefined, - permissions: ['storage', ...(manifestVersion === 2 ? ['webRequest', 'webRequestBlocking', ''] : [])], + permissions: [ + 'storage', + ...(manifestVersion === 2 ? ['scripting', 'webRequest', 'webRequestBlocking', ''] : []) + ], optional_permissions: ['nativeMessaging'], web_accessible_resources: [ {