use inject-into replace unsafeWindow

This commit is contained in:
Gabe Yuan
2023-08-29 00:06:50 +08:00
parent 47c7048538
commit 45ba9d3320
6 changed files with 106 additions and 19 deletions

View File

@@ -89,7 +89,7 @@ const userscriptWebpack = (config, env) => {
// @grant GM.getValue
// @grant GM.deleteValue
// @grant GM.info
// @grant unsafeWindow
// @inject-into content
// @connect translate.googleapis.com
// @connect api-edge.cognitive.microsofttranslator.com
// @connect edge.microsoft.com

View File

@@ -37,8 +37,7 @@
"react-app/jest"
],
"globals": {
"GM": true,
"unsafeWindow": true
"GM": true
}
},
"browserslist": {

View File

@@ -19,7 +19,7 @@ import { msAuth } from "./auth";
* @param {*} init
* @returns
*/
const fetchGM = async (input, { method = "GET", headers, body } = {}) =>
export const fetchGM = async (input, { method = "GET", headers, body } = {}) =>
new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method,
@@ -74,11 +74,21 @@ const fetchApi = async ({ input, init = {}, translator, token }) => {
}
if (isGm) {
const connects = GM?.info?.script?.connects || [];
let info;
if (window.KISS_GM) {
info = await window.KISS_GM.getInfo();
} else {
info = GM.info;
}
const connects = info?.script?.connects || [];
const url = new URL(input);
const isSafe = connects.find((item) => url.hostname.endsWith(item));
if (isSafe) {
return fetchGM(input, init);
if (window.KISS_GM) {
return window.KISS_GM.fetch(input, init);
} else {
return fetchGM(input, init);
}
}
}
return fetch(input, init);

View File

@@ -1,8 +1,22 @@
export const injectScript = ({ eventName }) => {
window.callGM = ({ action, args }, timeout = 5000) =>
import { fetchGM } from "./fetch";
/**
* 注入页面的脚本请求并接受GM接口信息
* @param {*} param0
*/
export const injectScript = (ping) => {
const MSG_GM_xmlHttpRequest = "xmlHttpRequest";
const MSG_GM_setValue = "setValue";
const MSG_GM_getValue = "getValue";
const MSG_GM_deleteValue = "deleteValue";
const MSG_GM_info = "info";
let GM_info;
const promiseGM = (action, args, timeout = 5000) =>
new Promise((resolve, reject) => {
const pong = btoa(Math.random()).slice(3, 11);
const handleEvent = (e) => {
window.removeEventListener(eventName + "_pong", handleEvent);
window.removeEventListener(pong, handleEvent);
const { data, error } = e.detail;
if (error) {
reject(new Error(error));
@@ -11,13 +25,73 @@ export const injectScript = ({ eventName }) => {
}
};
window.addEventListener(eventName + "_pong", handleEvent);
window.addEventListener(pong, handleEvent);
window.dispatchEvent(
new CustomEvent(eventName + "_ping", { action, args })
new CustomEvent(ping, { detail: { action, args, pong } })
);
setTimeout(() => {
handleEvent({ detail: { error: "timeout" } });
window.removeEventListener(pong, handleEvent);
reject(new Error("timeout"));
}, timeout);
});
window.KISS_GM = {
fetch: (input, init) => promiseGM(MSG_GM_xmlHttpRequest, { input, init }),
setValue: (key, val) => promiseGM(MSG_GM_setValue, { key, val }),
getValue: (key) => promiseGM(MSG_GM_getValue, { key }),
deleteValue: (key) => promiseGM(MSG_GM_deleteValue, { key }),
getInfo: () => {
if (GM_info) {
return GM_info;
}
return promiseGM(MSG_GM_info);
},
};
window.APP_NAME = process.env.REACT_APP_NAME;
};
/**
* 监听并回应页面对GM接口的请求
* @param {*} param0
*/
export const handlePing = async (e) => {
const MSG_GM_xmlHttpRequest = "xmlHttpRequest";
const MSG_GM_setValue = "setValue";
const MSG_GM_getValue = "getValue";
const MSG_GM_deleteValue = "deleteValue";
const MSG_GM_info = "info";
const { action, args, pong } = e.detail;
let res;
try {
switch (action) {
case MSG_GM_xmlHttpRequest:
const { input, init } = args;
res = await fetchGM(input, init);
break;
case MSG_GM_setValue:
const { key, val } = args;
await GM.setValue(key, val);
res = val;
break;
case MSG_GM_getValue:
res = await GM.getValue(args.key);
break;
case MSG_GM_deleteValue:
await GM.deleteValue(args.key);
res = "ok";
break;
case MSG_GM_info:
res = GM.info;
break;
default:
throw new Error(`message action is unavailable: ${action}`);
}
window.dispatchEvent(new CustomEvent(pong, { detail: { data: res } }));
} catch (err) {
window.dispatchEvent(
new CustomEvent(pong, { detail: { error: err.message } })
);
}
};

View File

@@ -4,8 +4,8 @@ async function set(key, val) {
if (isExt) {
await browser.storage.local.set({ [key]: val });
} else if (isGm) {
const oldValue = await GM.getValue(key);
await GM.setValue(key, val);
const oldValue = await (window.KISS_GM || GM).getValue(key);
await (window.KISS_GM || GM).setValue(key, val);
window.dispatchEvent(
new StorageEvent("storage", {
key,
@@ -31,7 +31,7 @@ async function get(key) {
const val = await browser.storage.local.get([key]);
return val[key];
} else if (isGm) {
const val = await GM.getValue(key);
const val = await (window.KISS_GM || GM).getValue(key);
return val;
}
return window.localStorage.getItem(key);
@@ -41,8 +41,8 @@ async function del(key) {
if (isExt) {
await browser.storage.local.remove([key]);
} else if (isGm) {
const oldValue = await GM.getValue(key);
await GM.deleteValue(key);
const oldValue = await (window.KISS_GM || GM).getValue(key);
await (window.KISS_GM || GM).deleteValue(key);
window.dispatchEvent(
new StorageEvent("storage", {
key,

View File

@@ -9,6 +9,7 @@ import { trySyncAllSubRules } from "./libs/rules";
import { isGm } from "./libs/browser";
import { MSG_TRANS_TOGGLE, MSG_TRANS_PUTRULE } from "./config";
import { isIframe } from "./libs/iframe";
import { genEventName, handlePing, injectScript } from "./libs/gm";
/**
* 入口函数
@@ -20,8 +21,11 @@ const init = async () => {
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE) ||
document.location.href.includes(process.env.REACT_APP_OPTIONSPAGE2)
) {
unsafeWindow.GM = GM;
unsafeWindow.APP_NAME = process.env.REACT_APP_NAME;
// unsafeWindow.GM = GM;
// unsafeWindow.APP_NAME = process.env.REACT_APP_NAME;
const ping = btoa(Math.random()).slice(3, 11);
window.addEventListener(ping, handlePing);
window.eval(`(${injectScript})("${ping}")`);
return;
}