mirror of
https://github.com/movie-web/extension.git
synced 2025-09-13 07:03:24 +00:00
Support both firefox and chrome
This commit is contained in:
@@ -7,7 +7,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "plasmo dev",
|
"dev": "plasmo dev",
|
||||||
"build": "plasmo build",
|
"build": "plasmo build",
|
||||||
|
"build:firefox": "plasmo build --target=firefox-mv2",
|
||||||
"package": "plasmo package",
|
"package": "plasmo package",
|
||||||
|
"package:firefox": "plasmo package --target=firefox-mv2",
|
||||||
"lint": "eslint --ext .tsx,.ts src",
|
"lint": "eslint --ext .tsx,.ts src",
|
||||||
"lint:fix": "eslint --fix --ext .tsx,.ts src",
|
"lint:fix": "eslint --fix --ext .tsx,.ts src",
|
||||||
"lint:report": "eslint --ext .tsx,.ts --output-file eslint_report.json --format json src",
|
"lint:report": "eslint --ext .tsx,.ts --output-file eslint_report.json --format json src",
|
||||||
@@ -22,6 +24,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chrome": "0.0.251",
|
"@types/chrome": "0.0.251",
|
||||||
|
"@types/firefox-webext-browser": "^120.0.0",
|
||||||
"@types/node": "20.9.0",
|
"@types/node": "20.9.0",
|
||||||
"@types/react": "18.2.37",
|
"@types/react": "18.2.37",
|
||||||
"@types/react-dom": "18.2.15",
|
"@types/react-dom": "18.2.15",
|
||||||
|
7
pnpm-lock.yaml
generated
7
pnpm-lock.yaml
generated
@@ -25,6 +25,9 @@ devDependencies:
|
|||||||
'@types/chrome':
|
'@types/chrome':
|
||||||
specifier: 0.0.251
|
specifier: 0.0.251
|
||||||
version: 0.0.251
|
version: 0.0.251
|
||||||
|
'@types/firefox-webext-browser':
|
||||||
|
specifier: ^120.0.0
|
||||||
|
version: 120.0.0
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: 20.9.0
|
specifier: 20.9.0
|
||||||
version: 20.9.0
|
version: 20.9.0
|
||||||
@@ -2767,6 +2770,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Kpi2GXQyYJdjL8mFclL1eDgihn1SIzorMZjD94kdPZh9E4VxGOeyjPxi5LpsM4Zku7P0reqegZTt2GxhmA9VBg==}
|
resolution: {integrity: sha512-Kpi2GXQyYJdjL8mFclL1eDgihn1SIzorMZjD94kdPZh9E4VxGOeyjPxi5LpsM4Zku7P0reqegZTt2GxhmA9VBg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/firefox-webext-browser@120.0.0:
|
||||||
|
resolution: {integrity: sha512-L+tDlwNeq0kQGfAYc2sNfKhRWJz9CNRvlbq9HnLibKUiJ3VTThG8sj7xrJF4CtKpEA9eBAr91Z2nnKIAy+xUJg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/har-format@1.2.15:
|
/@types/har-format@1.2.15:
|
||||||
resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==}
|
resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@@ -13,10 +13,11 @@ interface Request extends BaseRequest {
|
|||||||
|
|
||||||
const mapHeadersToDeclarativeNetRequestHeaders = (
|
const mapHeadersToDeclarativeNetRequestHeaders = (
|
||||||
headers: Record<string, string>,
|
headers: Record<string, string>,
|
||||||
): chrome.declarativeNetRequest.ModifyHeaderInfo[] => {
|
op: string,
|
||||||
|
): { header: string; operation: any; value: string }[] => {
|
||||||
return Object.entries(headers).map(([name, value]) => ({
|
return Object.entries(headers).map(([name, value]) => ({
|
||||||
header: name,
|
header: name,
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
operation: op,
|
||||||
value,
|
value,
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@@ -25,43 +26,91 @@ const handler: PlasmoMessaging.MessageHandler<Request, BaseResponse> = async (re
|
|||||||
try {
|
try {
|
||||||
await assertDomainWhitelist(req.body.requestDomain);
|
await assertDomainWhitelist(req.body.requestDomain);
|
||||||
|
|
||||||
await chrome.declarativeNetRequest.updateDynamicRules({
|
if (chrome) {
|
||||||
removeRuleIds: [req.body.ruleId],
|
await chrome.declarativeNetRequest.updateDynamicRules({
|
||||||
addRules: [
|
removeRuleIds: [req.body.ruleId],
|
||||||
{
|
addRules: [
|
||||||
id: req.body.ruleId,
|
{
|
||||||
condition: {
|
id: req.body.ruleId,
|
||||||
requestDomains: req.body.targetDomains,
|
condition: {
|
||||||
|
requestDomains: req.body.targetDomains,
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
|
||||||
|
...(req.body.requestHeaders
|
||||||
|
? {
|
||||||
|
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(
|
||||||
|
req.body.requestHeaders,
|
||||||
|
chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
responseHeaders: [
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Origin',
|
||||||
|
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Methods',
|
||||||
|
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Headers',
|
||||||
|
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
...mapHeadersToDeclarativeNetRequestHeaders(
|
||||||
|
req.body.responseHeaders ?? {},
|
||||||
|
chrome.declarativeNetRequest.HeaderOperation.SET,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
action: {
|
],
|
||||||
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
|
});
|
||||||
...(req.body.requestHeaders && {
|
if (chrome.runtime.lastError?.message) throw new Error(chrome.runtime.lastError.message);
|
||||||
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(req.body.requestHeaders),
|
} else {
|
||||||
}),
|
browser.declarativeNetRequest.updateDynamicRules({
|
||||||
responseHeaders: [
|
removeRuleIds: [req.body.ruleId],
|
||||||
{
|
addRules: [
|
||||||
header: 'Access-Control-Allow-Origin',
|
{
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
id: req.body.ruleId,
|
||||||
value: '*',
|
condition: {
|
||||||
},
|
requestDomains: req.body.targetDomains,
|
||||||
{
|
},
|
||||||
header: 'Access-Control-Allow-Methods',
|
action: {
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
type: 'modifyHeaders',
|
||||||
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
...(req.body.requestHeaders
|
||||||
},
|
? {
|
||||||
{
|
requestHeaders: mapHeadersToDeclarativeNetRequestHeaders(req.body.requestHeaders, 'set'),
|
||||||
header: 'Access-Control-Allow-Headers',
|
}
|
||||||
operation: chrome.declarativeNetRequest.HeaderOperation.SET,
|
: {}),
|
||||||
value: '*',
|
responseHeaders: [
|
||||||
},
|
{
|
||||||
...mapHeadersToDeclarativeNetRequestHeaders(req.body.responseHeaders ?? {}),
|
header: 'Access-Control-Allow-Origin',
|
||||||
],
|
operation: 'set',
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Methods',
|
||||||
|
operation: 'set',
|
||||||
|
value: 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Access-Control-Allow-Headers',
|
||||||
|
operation: 'set',
|
||||||
|
value: '*',
|
||||||
|
},
|
||||||
|
...mapHeadersToDeclarativeNetRequestHeaders(req.body.responseHeaders ?? {}, 'set'),
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
],
|
});
|
||||||
});
|
if (browser.runtime.lastError?.message) throw new Error(browser.runtime.lastError.message);
|
||||||
|
}
|
||||||
if (chrome.runtime.lastError?.message) throw new Error(chrome.runtime.lastError.message);
|
|
||||||
|
|
||||||
res.send({
|
res.send({
|
||||||
success: true,
|
success: true,
|
||||||
|
@@ -1,28 +1,17 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { makeUrlIntoDomain } from '~utils/domains';
|
import { makeUrlIntoDomain } from '~utils/domains';
|
||||||
|
import { listenToTabChanges, queryCurrentDomain, stopListenToTabChanges } from '~utils/tabs';
|
||||||
function queryCurrentDomain(cb: (domain: string | null) => void) {
|
|
||||||
chrome.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
|
|
||||||
const url = tabs[0]?.url;
|
|
||||||
if (!url) cb(null);
|
|
||||||
else cb(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDomain(): null | string {
|
export function useDomain(): null | string {
|
||||||
const [domain, setDomain] = useState<string | null>(null);
|
const [domain, setDomain] = useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
queryCurrentDomain(setDomain);
|
const listen = () => queryCurrentDomain(setDomain);
|
||||||
function listen() {
|
listen();
|
||||||
queryCurrentDomain(setDomain);
|
listenToTabChanges(listen);
|
||||||
}
|
|
||||||
chrome.tabs.onActivated.addListener(listen);
|
|
||||||
chrome.tabs.onUpdated.addListener(listen);
|
|
||||||
return () => {
|
return () => {
|
||||||
chrome.tabs.onActivated.removeListener(listen);
|
stopListenToTabChanges(listen);
|
||||||
chrome.tabs.onUpdated.removeListener(listen);
|
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
export function getVersion(ops?: { prefixed?: boolean }) {
|
export function getVersion(ops?: { prefixed?: boolean }) {
|
||||||
const prefix = ops?.prefixed ? 'v' : '';
|
const prefix = ops?.prefixed ? 'v' : '';
|
||||||
return `${prefix}${chrome.runtime.getManifest().version}`;
|
const manifest = (chrome || browser).runtime.getManifest();
|
||||||
|
return `${prefix}${manifest.version}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useVersion(ops?: { prefixed?: boolean }) {
|
export function useVersion(ops?: { prefixed?: boolean }) {
|
||||||
|
30
src/utils/tabs.ts
Normal file
30
src/utils/tabs.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export function queryCurrentDomain(cb: (domain: string | null) => void) {
|
||||||
|
const handle = (tabUrl: string | null) => {
|
||||||
|
if (!tabUrl) cb(null);
|
||||||
|
else cb(tabUrl);
|
||||||
|
};
|
||||||
|
const ops = { active: true, currentWindow: true } as const;
|
||||||
|
|
||||||
|
if (chrome) chrome.tabs.query(ops).then((tabs) => handle(tabs[0]?.url));
|
||||||
|
else browser.tabs.query(ops).then((tabs) => handle(tabs[0]?.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listenToTabChanges(cb: () => void) {
|
||||||
|
if (chrome) {
|
||||||
|
chrome.tabs.onActivated.addListener(cb);
|
||||||
|
chrome.tabs.onUpdated.addListener(cb);
|
||||||
|
} else if (browser) {
|
||||||
|
browser.tabs.onActivated.addListener(cb);
|
||||||
|
browser.tabs.onUpdated.addListener(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stopListenToTabChanges(cb: () => void) {
|
||||||
|
if (chrome) {
|
||||||
|
chrome.tabs.onActivated.removeListener(cb);
|
||||||
|
chrome.tabs.onUpdated.removeListener(cb);
|
||||||
|
} else if (browser) {
|
||||||
|
browser.tabs.onActivated.removeListener(cb);
|
||||||
|
browser.tabs.onUpdated.removeListener(cb);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user