Files
kiss-translator/src/background.js

342 lines
8.6 KiB
JavaScript
Raw Normal View History

2023-08-05 18:15:01 +08:00
import browser from "webextension-polyfill";
2023-07-20 13:45:41 +08:00
import {
MSG_FETCH,
MSG_GET_HTTPCACHE,
MSG_PUT_HTTPCACHE,
2023-08-21 14:03:39 +08:00
MSG_TRANS_TOGGLE,
2023-09-23 19:16:51 +08:00
MSG_OPEN_OPTIONS,
MSG_SAVE_RULE,
2023-08-21 16:06:21 +08:00
MSG_TRANS_TOGGLE_STYLE,
2023-11-22 11:02:48 +08:00
MSG_OPEN_TRANBOX,
2023-12-11 11:25:02 +08:00
MSG_CONTEXT_MENUS,
2024-01-22 13:11:02 +08:00
MSG_COMMAND_SHORTCUTS,
2024-03-14 18:06:28 +08:00
MSG_INJECT_JS,
MSG_INJECT_CSS,
2024-03-26 12:00:09 +08:00
MSG_UPDATE_CSP,
2025-10-04 21:25:54 +08:00
MSG_BUILTINAI_DETECT,
MSG_BUILTINAI_TRANSLATE,
2024-03-26 12:00:09 +08:00
DEFAULT_CSPLIST,
2025-10-03 18:28:50 +08:00
DEFAULT_ORILIST,
2023-08-21 14:03:39 +08:00
CMD_TOGGLE_TRANSLATE,
2023-08-21 16:06:21 +08:00
CMD_TOGGLE_STYLE,
2023-09-10 13:56:11 +08:00
CMD_OPEN_OPTIONS,
2023-11-22 11:02:48 +08:00
CMD_OPEN_TRANBOX,
2025-05-18 00:34:20 +08:00
CLIENT_THUNDERBIRD,
2023-07-20 13:45:41 +08:00
} from "./config";
2023-08-30 18:05:37 +08:00
import { getSettingWithDefault, tryInitDefaultData } from "./libs/storage";
2023-08-31 13:38:06 +08:00
import { trySyncSettingAndRules } from "./libs/sync";
import { fetchHandle } from "./libs/fetch";
2025-09-27 21:21:56 +08:00
import { tryClearCaches, getHttpCache, putHttpCache } from "./libs/cache";
2023-08-21 14:03:39 +08:00
import { sendTabMsg } from "./libs/msg";
2023-08-30 18:05:37 +08:00
import { trySyncAllSubRules } from "./libs/subRules";
2023-09-23 19:16:51 +08:00
import { saveRule } from "./libs/rules";
2024-03-14 18:06:28 +08:00
import { getCurTabId } from "./libs/msg";
import { injectInlineJs, injectInternalCss } from "./libs/injector";
import { kissLog, logger } from "./libs/log";
2025-10-04 21:25:54 +08:00
import { chromeDetect, chromeTranslate } from "./libs/builtinAI";
2023-07-20 13:45:41 +08:00
2023-09-20 16:02:17 +08:00
globalThis.ContextType = "BACKGROUND";
2025-10-03 18:28:50 +08:00
const CSP_RULE_START_ID = 1;
const ORI_RULE_START_ID = 10000;
const CSP_REMOVE_HEADERS = [
2024-03-26 12:00:09 +08:00
`content-security-policy`,
`content-security-policy-report-only`,
`x-webkit-csp`,
`x-content-security-policy`,
];
2023-07-20 13:45:41 +08:00
/**
2023-12-11 11:25:02 +08:00
* 添加右键菜单
2023-07-20 13:45:41 +08:00
*/
2025-02-18 12:44:06 +08:00
async function addContextMenus(contextMenuType = 1) {
2024-02-05 10:51:42 +08:00
// 添加前先删除,避免重复ID的错误
try {
await browser.contextMenus.removeAll();
2024-02-05 10:51:42 +08:00
} catch (err) {
kissLog("remove contextMenus", err);
2024-02-05 10:51:42 +08:00
}
2024-02-05 11:28:34 +08:00
switch (contextMenuType) {
case 1:
browser.contextMenus.create({
2024-02-05 11:28:34 +08:00
id: CMD_TOGGLE_TRANSLATE,
2024-02-21 17:01:11 +08:00
title: browser.i18n.getMessage("app_name"),
2024-02-05 11:28:34 +08:00
contexts: ["page", "selection"],
});
break;
case 2:
browser.contextMenus.create({
2024-02-05 11:28:34 +08:00
id: CMD_TOGGLE_TRANSLATE,
title: browser.i18n.getMessage("toggle_translate"),
contexts: ["page", "selection"],
});
browser.contextMenus.create({
2024-02-05 11:28:34 +08:00
id: CMD_TOGGLE_STYLE,
title: browser.i18n.getMessage("toggle_style"),
contexts: ["page", "selection"],
});
browser.contextMenus.create({
2024-02-05 11:28:34 +08:00
id: CMD_OPEN_TRANBOX,
title: browser.i18n.getMessage("open_tranbox"),
contexts: ["page", "selection"],
});
browser.contextMenus.create({
2024-02-05 11:28:34 +08:00
id: "options_separator",
type: "separator",
contexts: ["page", "selection"],
});
browser.contextMenus.create({
2024-02-05 11:28:34 +08:00
id: CMD_OPEN_OPTIONS,
title: browser.i18n.getMessage("open_options"),
contexts: ["page", "selection"],
});
break;
default:
}
2023-12-11 11:25:02 +08:00
}
2024-03-26 12:00:09 +08:00
/**
* 更新CSP策略
2024-03-26 12:05:35 +08:00
* @param {*} csplist
2024-03-26 12:00:09 +08:00
*/
2025-10-03 18:28:50 +08:00
async function updateCspRules({ csplist, orilist }) {
2024-03-26 12:00:09 +08:00
try {
2025-10-03 18:28:50 +08:00
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,
2024-03-26 12:00:09 +08:00
action: {
type: "modifyHeaders",
2025-10-03 18:28:50 +08:00
responseHeaders: CSP_REMOVE_HEADERS.map((header) => ({
2024-03-26 12:00:09 +08:00
operation: "remove",
header,
})),
},
condition: {
urlFilter: url,
resourceTypes: ["main_frame", "sub_frame"],
},
}));
2025-10-03 18:28:50 +08:00
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",
2025-10-04 22:29:03 +08:00
requestHeaders: [{ header: "Origin", operation: "set", value: url }],
2025-10-03 18:28:50 +08:00
},
condition: {
urlFilter: url,
resourceTypes: ["xmlhttprequest"],
},
}));
rulesToAdd.push(...newOriRules);
}
if (idsToRemove.length > 0 || rulesToAdd.length > 0) {
await browser.declarativeNetRequest.updateDynamicRules({
removeRuleIds: idsToRemove,
addRules: rulesToAdd,
});
}
2024-03-26 12:00:09 +08:00
} catch (err) {
kissLog("update csp rules", err);
2024-03-26 12:00:09 +08:00
}
}
2025-02-18 11:42:47 +08:00
/**
* 注册邮件显示脚本
*/
async function registerMsgDisplayScript() {
2025-07-03 19:08:33 +08:00
await messenger.messageDisplayScripts.register({
js: [{ file: "/content.js" }],
});
}
2025-02-18 11:42:47 +08:00
2023-12-11 11:25:02 +08:00
/**
* 插件安装
*/
browser.runtime.onInstalled.addListener(() => {
tryInitDefaultData();
2023-12-11 17:26:49 +08:00
2025-02-18 11:42:47 +08:00
//在thunderbird中注册脚本
2025-05-18 00:34:20 +08:00
if (process.env.REACT_APP_CLIENT === CLIENT_THUNDERBIRD) {
2025-02-18 11:42:47 +08:00
registerMsgDisplayScript();
}
2025-07-03 19:08:33 +08:00
2023-12-11 17:26:49 +08:00
// 右键菜单
2025-02-18 12:44:06 +08:00
addContextMenus();
2024-03-26 12:42:39 +08:00
// 禁用CSP
2025-10-03 18:28:50 +08:00
updateCspRules({ csplist: DEFAULT_CSPLIST, orilist: DEFAULT_ORILIST });
2023-07-20 13:45:41 +08:00
});
/**
* 浏览器启动
*/
2025-02-18 12:44:06 +08:00
browser.runtime.onStartup.addListener(async () => {
const {
clearCache,
contextMenuType,
subrulesList,
csplist,
orilist,
logLevel,
} = await getSettingWithDefault();
2023-07-31 03:10:09 +08:00
// 设置日志
logger.setLevel(logLevel);
2023-12-11 11:25:02 +08:00
2023-07-31 03:10:09 +08:00
// 清除缓存
2023-12-11 11:25:02 +08:00
if (clearCache) {
2023-08-30 18:05:37 +08:00
tryClearCaches();
2023-07-20 13:45:41 +08:00
}
2025-02-18 11:42:47 +08:00
//在thunderbird中注册脚本
2025-05-18 00:34:20 +08:00
if (process.env.REACT_APP_CLIENT === CLIENT_THUNDERBIRD) {
2025-02-18 11:42:47 +08:00
registerMsgDisplayScript();
}
2023-12-11 11:25:02 +08:00
// 右键菜单
2024-02-05 11:28:34 +08:00
// firefox重启后菜单会消失,故重复添加
2025-02-18 12:44:06 +08:00
addContextMenus(contextMenuType);
2023-12-11 11:25:02 +08:00
2024-03-26 12:05:35 +08:00
// 禁用CSP
2025-10-03 18:28:50 +08:00
updateCspRules({ csplist, orilist });
2024-03-26 12:05:35 +08:00
// 同步数据
trySyncSettingAndRules();
// 同步订阅规则
2023-12-11 11:25:02 +08:00
trySyncAllSubRules({ subrulesList });
2023-07-20 13:45:41 +08:00
});
2025-10-04 21:25:54 +08:00
/**
* 向当前活动标签页注入脚本或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(injectInlineJs, 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),
};
2023-07-20 13:45:41 +08:00
/**
* 监听消息
2025-10-04 21:25:54 +08:00
* todo: 返回含错误的结构化信息
2023-07-20 13:45:41 +08:00
*/
browser.runtime.onMessage.addListener(async ({ action, args }) => {
2025-10-04 21:25:54 +08:00
const handler = messageHandlers[action];
if (!handler) {
const errorMessage = `Message action is unavailable: ${action}`;
kissLog("runtime onMessage", action, new Error(errorMessage));
return null;
}
try {
const result = await handler(args);
return result;
} catch (err) {
kissLog("runtime onMessage", action, err);
return null;
2023-07-20 13:45:41 +08:00
}
});
2023-08-21 14:03:39 +08:00
/**
* 监听快捷键
*/
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;
2023-08-21 16:06:21 +08:00
case CMD_TOGGLE_STYLE:
sendTabMsg(MSG_TRANS_TOGGLE_STYLE);
break;
2023-09-10 13:56:11 +08:00
case CMD_OPEN_OPTIONS:
browser.runtime.openOptionsPage();
break;
2023-08-21 14:03:39 +08:00
default:
}
});
2023-11-21 11:20:05 +08:00
2023-12-11 11:25:02 +08:00
/**
* 监听右键菜单
*/
2025-02-18 12:44:06 +08:00
browser.contextMenus.onClicked.addListener(({ menuItemId }) => {
2023-11-21 11:20:05 +08:00
switch (menuItemId) {
case CMD_TOGGLE_TRANSLATE:
sendTabMsg(MSG_TRANS_TOGGLE);
break;
case CMD_TOGGLE_STYLE:
sendTabMsg(MSG_TRANS_TOGGLE_STYLE);
break;
2023-11-22 11:02:48 +08:00
case CMD_OPEN_TRANBOX:
sendTabMsg(MSG_OPEN_TRANBOX);
break;
2023-11-21 11:20:05 +08:00
case CMD_OPEN_OPTIONS:
browser.runtime.openOptionsPage();
break;
default:
}
});