mirror of
https://github.com/bytedream/stream-bypass.git
synced 2026-08-05 05:20:41 +02:00
only listen to send headers and redirect request where it's necessary
This commit is contained in:
@@ -1,12 +1,23 @@
|
||||
import { BackgroundMessageData, BackgroundMessageType } from '@/lib/communication';
|
||||
import { getHost } from '@/lib/host';
|
||||
import { HostSettings, UrlReferer } from '@/lib/settings';
|
||||
import { getHost, hosts } from '@/lib/host';
|
||||
import { HostSettings } from '@/lib/settings';
|
||||
|
||||
const temporaryReferers: Record<string, string> = {};
|
||||
const allHostDomains = hosts.flatMap((host) => host.domains);
|
||||
|
||||
function domainToMatch(domain: string) {
|
||||
return `*://${domain}/*`;
|
||||
}
|
||||
|
||||
function domainsToMatch(domains: string[]) {
|
||||
return domains.map(domainToMatch);
|
||||
}
|
||||
|
||||
async function reInjectContentScript(domain: string) {
|
||||
const contentScript: Browser.scripting.RegisteredContentScript = {
|
||||
id: 'temporary-hosts',
|
||||
js: ['content-scripts/content.js'],
|
||||
matches: [`*://${domain}/*`],
|
||||
matches: [domainToMatch(domain)],
|
||||
persistAcrossSessions: false,
|
||||
allFrames: true,
|
||||
runAt: 'document_end'
|
||||
@@ -26,75 +37,115 @@ async function reInjectContentScript(domain: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export default defineBackground(() => {
|
||||
browser.runtime.onMessage.addListener(async (message, sender) => {
|
||||
const type = message.type as BackgroundMessageType;
|
||||
let data = message.data;
|
||||
/* --- listeners --- */
|
||||
async function browserRuntimeOnMessageListener(message: any, sender: Browser.runtime.MessageSender) {
|
||||
const type = message.type as BackgroundMessageType;
|
||||
let data = message.data;
|
||||
|
||||
let response;
|
||||
let response;
|
||||
|
||||
switch (type) {
|
||||
case BackgroundMessageType.Ff2mpv: {
|
||||
data = data as BackgroundMessageData<typeof type>;
|
||||
switch (type) {
|
||||
case BackgroundMessageType.Ff2mpv: {
|
||||
data = data as BackgroundMessageData<typeof type>;
|
||||
|
||||
await browser.runtime.sendNativeMessage('ff2mpv', { url: data.url });
|
||||
break;
|
||||
}
|
||||
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<typeof type>;
|
||||
await reInjectContentScript(data.domain);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
await browser.runtime.sendNativeMessage('ff2mpv', { url: data.url });
|
||||
break;
|
||||
}
|
||||
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;
|
||||
|
||||
return response;
|
||||
data = data as BackgroundMessageData<typeof type>;
|
||||
await reInjectContentScript(data.domain);
|
||||
|
||||
break;
|
||||
}
|
||||
case BackgroundMessageType.RegisterTemporaryReferer: {
|
||||
// requires "dynamic" host permissions, which is only available in mv2
|
||||
if (import.meta.env.MANIFEST_VERSION === 3) break;
|
||||
|
||||
data = data as BackgroundMessageData<typeof type>;
|
||||
if (data.domain in temporaryReferers) break;
|
||||
temporaryReferers[data.domain] = data.referer;
|
||||
|
||||
// remount before send headers listener which to also listen on the new temporary referer domain
|
||||
registerBrowserWebRequestOnBeforeSendHeadersListener();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
function registerBrowserRuntimeOnMessageListener() {
|
||||
browser.runtime.onMessage.addListener(browserRuntimeOnMessageListener);
|
||||
}
|
||||
|
||||
function browserWebRequestOnBeforeSendHeadersListener(
|
||||
details: Browser.webRequest.OnBeforeSendHeadersDetails
|
||||
): Browser.webRequest.BlockingResponse | undefined {
|
||||
const referer = temporaryReferers[new URL(details.url).host];
|
||||
if (!referer) return;
|
||||
|
||||
details.requestHeaders!.push({
|
||||
name: 'Referer',
|
||||
value: `https://${referer}/`
|
||||
});
|
||||
|
||||
// the following listener is only available in mv2
|
||||
return { requestHeaders: details.requestHeaders };
|
||||
}
|
||||
function registerBrowserWebRequestOnBeforeSendHeadersListener() {
|
||||
// only available in mv2
|
||||
if (import.meta.env.MANIFEST_VERSION === 3) return;
|
||||
// background crashes when a listener with empty url is registered
|
||||
else if (Object.keys(temporaryReferers).length === 0) return;
|
||||
|
||||
browser.webRequest.onBeforeSendHeaders.removeListener(browserWebRequestOnBeforeSendHeadersListener);
|
||||
browser.webRequest.onBeforeSendHeaders.addListener(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
async (details) => {
|
||||
const referer = await UrlReferer.get(new URL(details.url).hostname);
|
||||
if (!referer) return;
|
||||
|
||||
details.requestHeaders!.push({
|
||||
name: 'Referer',
|
||||
value: `https://${referer}/`
|
||||
});
|
||||
|
||||
return { requestHeaders: details.requestHeaders };
|
||||
browserWebRequestOnBeforeSendHeadersListener,
|
||||
{
|
||||
urls: domainsToMatch(Object.keys(temporaryReferers)),
|
||||
types: ['xmlhttprequest']
|
||||
},
|
||||
{ urls: ['<all_urls>'], types: ['xmlhttprequest'] },
|
||||
['blocking', 'requestHeaders']
|
||||
);
|
||||
}
|
||||
|
||||
browser.webRequest.onBeforeRedirect.addListener(
|
||||
async (details) => {
|
||||
const domain = new URL(details.url).host;
|
||||
const host = await getHost(domain);
|
||||
if (!host) return;
|
||||
async function browserWebRequestOnBeforeRedirectListener(details: Browser.webRequest.OnBeforeRedirectDetails) {
|
||||
const domain = new URL(details.url).host;
|
||||
const host = await getHost(domain);
|
||||
if (!host) return;
|
||||
|
||||
const newDomain = new URL(details.redirectUrl).host;
|
||||
const newDomain = new URL(details.redirectUrl).host;
|
||||
|
||||
await Promise.all([
|
||||
HostSettings.addTemporaryHostDomain(host.id, newDomain, { registerContentScript: false }),
|
||||
// must be called manually, a message sent from a background script is only received on non-background pages
|
||||
reInjectContentScript(newDomain)
|
||||
]);
|
||||
},
|
||||
{ urls: ['<all_urls>'], types: ['main_frame', 'sub_frame'] }
|
||||
);
|
||||
await Promise.all([
|
||||
HostSettings.addTemporaryHostDomain(host.id, newDomain, { registerContentScript: false }),
|
||||
// must be called manually, a message sent from a background script is only received on non-background pages
|
||||
reInjectContentScript(newDomain)
|
||||
]);
|
||||
|
||||
// add new domain to internal list of supported hosts and remount listener to also listen on the new domain
|
||||
if (allHostDomains.indexOf(newDomain) === -1) allHostDomains.push(newDomain);
|
||||
queueMicrotask(registerBrowserWebRequestOnBeforeRedirectListener);
|
||||
}
|
||||
function registerBrowserWebRequestOnBeforeRedirectListener() {
|
||||
// only available in mv2
|
||||
if (import.meta.env.MANIFEST_VERSION === 3) return;
|
||||
|
||||
browser.webRequest.onBeforeRedirect.removeListener(browserWebRequestOnBeforeRedirectListener);
|
||||
browser.webRequest.onBeforeRedirect.addListener(browserWebRequestOnBeforeRedirectListener, {
|
||||
urls: domainsToMatch(allHostDomains),
|
||||
types: ['main_frame', 'sub_frame']
|
||||
});
|
||||
}
|
||||
|
||||
export default defineBackground(() => {
|
||||
registerBrowserRuntimeOnMessageListener();
|
||||
registerBrowserWebRequestOnBeforeRedirectListener();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user