337 lines
8.6 KiB
JavaScript
337 lines
8.6 KiB
JavaScript
import browser from "webextension-polyfill";
|
|
import {
|
|
MSG_FETCH,
|
|
MSG_GET_HTTPCACHE,
|
|
MSG_PUT_HTTPCACHE,
|
|
MSG_TRANS_TOGGLE,
|
|
MSG_OPEN_OPTIONS,
|
|
MSG_SAVE_RULE,
|
|
MSG_TRANS_TOGGLE_STYLE,
|
|
MSG_OPEN_TRANBOX,
|
|
MSG_CONTEXT_MENUS,
|
|
MSG_COMMAND_SHORTCUTS,
|
|
MSG_INJECT_JS,
|
|
MSG_INJECT_CSS,
|
|
MSG_UPDATE_CSP,
|
|
MSG_BUILTINAI_DETECT,
|
|
MSG_BUILTINAI_TRANSLATE,
|
|
CMD_TOGGLE_TRANSLATE,
|
|
CMD_TOGGLE_STYLE,
|
|
CMD_OPEN_OPTIONS,
|
|
CMD_OPEN_TRANBOX,
|
|
CLIENT_THUNDERBIRD,
|
|
MSG_SET_LOGLEVEL,
|
|
MSG_CLEAR_CACHES,
|
|
} from "./config";
|
|
import { getSettingWithDefault, tryInitDefaultData } from "./libs/storage";
|
|
import { trySyncSettingAndRules } from "./libs/sync";
|
|
import { fetchHandle } from "./libs/fetch";
|
|
import { tryClearCaches, getHttpCache, putHttpCache } from "./libs/cache";
|
|
import { sendTabMsg } from "./libs/msg";
|
|
import { trySyncAllSubRules } from "./libs/subRules";
|
|
import { saveRule } from "./libs/rules";
|
|
import { getCurTabId } from "./libs/msg";
|
|
import { injectInlineJsBg, injectInternalCss } from "./libs/injector";
|
|
import { kissLog, logger } from "./libs/log";
|
|
import { chromeDetect, chromeTranslate } from "./libs/builtinAI";
|
|
|
|
globalThis.ContextType = "BACKGROUND";
|
|
|
|
const CSP_RULE_START_ID = 1;
|
|
const ORI_RULE_START_ID = 10000;
|
|
const CSP_REMOVE_HEADERS = [
|
|
`content-security-policy`,
|
|
`content-security-policy-report-only`,
|
|
`x-webkit-csp`,
|
|
`x-content-security-policy`,
|
|
];
|
|
|
|
/**
|
|
* 添加右键菜单
|
|
*/
|
|
async function addContextMenus(contextMenuType = 1) {
|
|
// 添加前先删除,避免重复ID的错误
|
|
try {
|
|
await browser.contextMenus.removeAll();
|
|
} catch (err) {
|
|
kissLog("remove contextMenus", err);
|
|
}
|
|
|
|
switch (contextMenuType) {
|
|
case 1:
|
|
browser.contextMenus.create({
|
|
id: CMD_TOGGLE_TRANSLATE,
|
|
title: browser.i18n.getMessage("app_name"),
|
|
contexts: ["page", "selection"],
|
|
});
|
|
break;
|
|
case 2:
|
|
browser.contextMenus.create({
|
|
id: CMD_TOGGLE_TRANSLATE,
|
|
title: browser.i18n.getMessage("toggle_translate"),
|
|
contexts: ["page", "selection"],
|
|
});
|
|
browser.contextMenus.create({
|
|
id: CMD_TOGGLE_STYLE,
|
|
title: browser.i18n.getMessage("toggle_style"),
|
|
contexts: ["page", "selection"],
|
|
});
|
|
browser.contextMenus.create({
|
|
id: CMD_OPEN_TRANBOX,
|
|
title: browser.i18n.getMessage("open_tranbox"),
|
|
contexts: ["page", "selection"],
|
|
});
|
|
browser.contextMenus.create({
|
|
id: "options_separator",
|
|
type: "separator",
|
|
contexts: ["page", "selection"],
|
|
});
|
|
browser.contextMenus.create({
|
|
id: CMD_OPEN_OPTIONS,
|
|
title: browser.i18n.getMessage("open_options"),
|
|
contexts: ["page", "selection"],
|
|
});
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新CSP策略
|
|
* @param {*} csplist
|
|
*/
|
|
async function updateCspRules({ csplist, orilist }) {
|
|
try {
|
|
const oldRules = await browser.declarativeNetRequest.getDynamicRules();
|
|
|
|
const rulesToAdd = [];
|
|
const idsToRemove = [];
|
|
|
|
if (csplist !== undefined) {
|
|
let processedCspList = csplist;
|
|
if (typeof processedCspList === "string") {
|
|
processedCspList = processedCspList
|
|
.split(/\n|,/)
|
|
.map((url) => url.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|
|
const oldCspRuleIds = oldRules
|
|
.filter(
|
|
(rule) => rule.id >= CSP_RULE_START_ID && rule.id < ORI_RULE_START_ID
|
|
)
|
|
.map((rule) => rule.id);
|
|
idsToRemove.push(...oldCspRuleIds);
|
|
|
|
const newCspRules = processedCspList.map((url, index) => ({
|
|
id: CSP_RULE_START_ID + index,
|
|
action: {
|
|
type: "modifyHeaders",
|
|
responseHeaders: CSP_REMOVE_HEADERS.map((header) => ({
|
|
operation: "remove",
|
|
header,
|
|
})),
|
|
},
|
|
condition: {
|
|
urlFilter: url,
|
|
resourceTypes: ["main_frame", "sub_frame"],
|
|
},
|
|
}));
|
|
rulesToAdd.push(...newCspRules);
|
|
}
|
|
|
|
if (orilist !== undefined) {
|
|
let processedOriList = orilist;
|
|
if (typeof processedOriList === "string") {
|
|
processedOriList = processedOriList
|
|
.split(/\n|,/)
|
|
.map((url) => url.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|
|
const oldOriRuleIds = oldRules
|
|
.filter((rule) => rule.id >= ORI_RULE_START_ID)
|
|
.map((rule) => rule.id);
|
|
idsToRemove.push(...oldOriRuleIds);
|
|
|
|
const newOriRules = processedOriList.map((url, index) => ({
|
|
id: ORI_RULE_START_ID + index,
|
|
action: {
|
|
type: "modifyHeaders",
|
|
requestHeaders: [{ header: "Origin", operation: "set", value: url }],
|
|
},
|
|
condition: {
|
|
urlFilter: url,
|
|
resourceTypes: ["xmlhttprequest"],
|
|
},
|
|
}));
|
|
rulesToAdd.push(...newOriRules);
|
|
}
|
|
|
|
if (idsToRemove.length > 0 || rulesToAdd.length > 0) {
|
|
await browser.declarativeNetRequest.updateDynamicRules({
|
|
removeRuleIds: idsToRemove,
|
|
addRules: rulesToAdd,
|
|
});
|
|
}
|
|
} catch (err) {
|
|
kissLog("update csp rules", err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 注册邮件显示脚本
|
|
*/
|
|
async function registerMsgDisplayScript() {
|
|
await messenger.messageDisplayScripts.register({
|
|
js: [{ file: "/content.js" }],
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 插件安装
|
|
*/
|
|
browser.runtime.onInstalled.addListener(async () => {
|
|
await tryInitDefaultData();
|
|
|
|
//在thunderbird中注册脚本
|
|
if (process.env.REACT_APP_CLIENT === CLIENT_THUNDERBIRD) {
|
|
registerMsgDisplayScript();
|
|
}
|
|
|
|
const { contextMenuType, csplist, orilist } = await getSettingWithDefault();
|
|
|
|
// 右键菜单
|
|
addContextMenus(contextMenuType);
|
|
|
|
// 禁用CSP
|
|
updateCspRules({ csplist, orilist });
|
|
});
|
|
|
|
/**
|
|
* 浏览器启动
|
|
*/
|
|
browser.runtime.onStartup.addListener(async () => {
|
|
const {
|
|
clearCache,
|
|
contextMenuType,
|
|
subrulesList,
|
|
csplist,
|
|
orilist,
|
|
logLevel,
|
|
} = await getSettingWithDefault();
|
|
|
|
// 设置日志
|
|
logger.setLevel(logLevel);
|
|
|
|
// 清除缓存
|
|
if (clearCache) {
|
|
tryClearCaches();
|
|
}
|
|
|
|
//在thunderbird中注册脚本
|
|
if (process.env.REACT_APP_CLIENT === CLIENT_THUNDERBIRD) {
|
|
registerMsgDisplayScript();
|
|
}
|
|
|
|
// 右键菜单
|
|
// firefox重启后菜单会消失,故重复添加
|
|
addContextMenus(contextMenuType);
|
|
|
|
// 禁用CSP
|
|
updateCspRules({ csplist, orilist });
|
|
|
|
// 同步数据
|
|
trySyncSettingAndRules();
|
|
|
|
// 同步订阅规则
|
|
trySyncAllSubRules({ subrulesList });
|
|
});
|
|
|
|
/**
|
|
* 向当前活动标签页注入脚本或CSS
|
|
*/
|
|
const injectToCurrentTab = async (func, args) => {
|
|
const tabId = await getCurTabId();
|
|
return browser.scripting.executeScript({
|
|
target: { tabId, allFrames: true },
|
|
func: func,
|
|
args: [args],
|
|
world: "MAIN",
|
|
});
|
|
};
|
|
|
|
// 动作处理器映射表
|
|
const messageHandlers = {
|
|
[MSG_FETCH]: (args) => fetchHandle(args),
|
|
[MSG_GET_HTTPCACHE]: (args) => getHttpCache(args),
|
|
[MSG_PUT_HTTPCACHE]: (args) => putHttpCache(args),
|
|
[MSG_OPEN_OPTIONS]: () => browser.runtime.openOptionsPage(),
|
|
[MSG_SAVE_RULE]: (args) => saveRule(args),
|
|
[MSG_INJECT_JS]: (args) => injectToCurrentTab(injectInlineJsBg, args),
|
|
[MSG_INJECT_CSS]: (args) => injectToCurrentTab(injectInternalCss, args),
|
|
[MSG_UPDATE_CSP]: (args) => updateCspRules(args),
|
|
[MSG_CONTEXT_MENUS]: (args) => addContextMenus(args),
|
|
[MSG_COMMAND_SHORTCUTS]: () => browser.commands.getAll(),
|
|
[MSG_BUILTINAI_DETECT]: (args) => chromeDetect(args),
|
|
[MSG_BUILTINAI_TRANSLATE]: (args) => chromeTranslate(args),
|
|
[MSG_SET_LOGLEVEL]: (args) => logger.setLevel(args),
|
|
[MSG_CLEAR_CACHES]: () => tryClearCaches(),
|
|
};
|
|
|
|
/**
|
|
* 监听消息
|
|
* todo: 返回含错误的结构化信息
|
|
*/
|
|
browser.runtime.onMessage.addListener(async ({ action, args }) => {
|
|
const handler = messageHandlers[action];
|
|
if (!handler) {
|
|
throw new Error(`Message action is unavailable: ${action}`);
|
|
}
|
|
|
|
return handler(args);
|
|
});
|
|
|
|
/**
|
|
* 监听快捷键
|
|
*/
|
|
browser.commands.onCommand.addListener((command) => {
|
|
// console.log(`Command: ${command}`);
|
|
switch (command) {
|
|
case CMD_TOGGLE_TRANSLATE:
|
|
sendTabMsg(MSG_TRANS_TOGGLE);
|
|
break;
|
|
case CMD_OPEN_TRANBOX:
|
|
sendTabMsg(MSG_OPEN_TRANBOX);
|
|
break;
|
|
case CMD_TOGGLE_STYLE:
|
|
sendTabMsg(MSG_TRANS_TOGGLE_STYLE);
|
|
break;
|
|
case CMD_OPEN_OPTIONS:
|
|
browser.runtime.openOptionsPage();
|
|
break;
|
|
default:
|
|
}
|
|
});
|
|
|
|
/**
|
|
* 监听右键菜单
|
|
*/
|
|
browser.contextMenus.onClicked.addListener(({ menuItemId }) => {
|
|
switch (menuItemId) {
|
|
case CMD_TOGGLE_TRANSLATE:
|
|
sendTabMsg(MSG_TRANS_TOGGLE);
|
|
break;
|
|
case CMD_TOGGLE_STYLE:
|
|
sendTabMsg(MSG_TRANS_TOGGLE_STYLE);
|
|
break;
|
|
case CMD_OPEN_TRANBOX:
|
|
sendTabMsg(MSG_OPEN_TRANBOX);
|
|
break;
|
|
case CMD_OPEN_OPTIONS:
|
|
browser.runtime.openOptionsPage();
|
|
break;
|
|
default:
|
|
}
|
|
});
|