gm 菜单响应
Some checks failed
test / Run tests (push) Failing after 8s
build / Build (push) Failing after 10s
Some checks failed
test / Run tests (push) Failing after 8s
build / Build (push) Failing after 10s
This commit is contained in:
parent
f26aecd10f
commit
42975d47cf
@ -134,4 +134,27 @@ export default class Cache {
|
||||
public list(): Promise<string[]> {
|
||||
return this.storage.list();
|
||||
}
|
||||
|
||||
private txPromise: Map<string, Promise<any>> = new Map();
|
||||
|
||||
// 事务处理,如果有事务正在进行,则等待
|
||||
public async tx(key: string, set: (result: any) => Promise<any>): Promise<void> {
|
||||
let promise = this.txPromise.get(key);
|
||||
if (promise) {
|
||||
await promise;
|
||||
}
|
||||
|
||||
promise = this.get(key)
|
||||
.then((result) => set(result))
|
||||
.then((value) => {
|
||||
console.log("tx", key, value);
|
||||
if (value) {
|
||||
return this.set(key, value);
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
this.txPromise.set(key, promise);
|
||||
await promise;
|
||||
this.txPromise.delete(key);
|
||||
}
|
||||
}
|
||||
|
@ -103,45 +103,49 @@ export class PopupService {
|
||||
|
||||
async registerMenuCommand(message: ScriptMenuRegisterCallbackValue) {
|
||||
// 给脚本添加菜单
|
||||
const data = await this.getScriptMenu(message.tabId);
|
||||
const script = data.find((item) => item.uuid === message.uuid);
|
||||
if (script) {
|
||||
const menu = script.menus.find((item) => item.id === message.id);
|
||||
if (!menu) {
|
||||
script.menus.push({
|
||||
id: message.id,
|
||||
name: message.name,
|
||||
accessKey: message.accessKey,
|
||||
tabId: message.tabId,
|
||||
frameId: message.frameId,
|
||||
documentId: message.documentId,
|
||||
});
|
||||
} else {
|
||||
menu.name = message.name;
|
||||
menu.accessKey = message.accessKey;
|
||||
menu.tabId = message.tabId;
|
||||
return this.txUpdateScriptMenu(message.tabId, async (data) => {
|
||||
console.log("register menu", message, data);
|
||||
const script = data.find((item) => item.uuid === message.uuid);
|
||||
if (script) {
|
||||
const menu = script.menus.find((item) => item.id === message.id);
|
||||
if (!menu) {
|
||||
script.menus.push({
|
||||
id: message.id,
|
||||
name: message.name,
|
||||
accessKey: message.accessKey,
|
||||
tabId: message.tabId,
|
||||
frameId: message.frameId,
|
||||
documentId: message.documentId,
|
||||
});
|
||||
} else {
|
||||
menu.name = message.name;
|
||||
menu.accessKey = message.accessKey;
|
||||
menu.tabId = message.tabId;
|
||||
menu.frameId = message.frameId;
|
||||
menu.documentId = message.documentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log("set menu", data);
|
||||
await Cache.getInstance().set("tabScript:" + message.tabId, data);
|
||||
console.log("update menu");
|
||||
this.updateScriptMenu();
|
||||
this.updateScriptMenu();
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
async unregisterMenuCommand({ id, uuid, tabId }: { id: number; uuid: string; tabId: number }) {
|
||||
const data = await this.getScriptMenu(tabId);
|
||||
// 删除脚本菜单
|
||||
const script = data.find((item) => item.uuid === uuid);
|
||||
if (script) {
|
||||
script.menus = script.menus.filter((item) => item.id !== id);
|
||||
}
|
||||
await Cache.getInstance().set("tabScript:" + tabId, data);
|
||||
this.updateScriptMenu();
|
||||
return this.txUpdateScriptMenu(tabId, async (data) => {
|
||||
// 删除脚本菜单
|
||||
const script = data.find((item) => item.uuid === uuid);
|
||||
if (script) {
|
||||
script.menus = script.menus.filter((item) => item.id !== id);
|
||||
}
|
||||
console.log("unregister menu", data);
|
||||
this.updateScriptMenu();
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
updateScriptMenu() {
|
||||
// 获取当前页面并更新菜单
|
||||
chrome.tabs.query({ active: true }, (tabs) => {
|
||||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
||||
console.log("query", tabs);
|
||||
if (!tabs.length) {
|
||||
return;
|
||||
@ -192,6 +196,13 @@ export class PopupService {
|
||||
return ((await Cache.getInstance().get("tabScript:" + tabId)) || []) as ScriptMenu[];
|
||||
}
|
||||
|
||||
// 事务更新脚本菜单
|
||||
txUpdateScriptMenu(tabId: number, callback: (menu: ScriptMenu[]) => Promise<any>) {
|
||||
return Cache.getInstance().tx("tabScript:" + tabId, async (menu) => {
|
||||
return callback(menu || []);
|
||||
});
|
||||
}
|
||||
|
||||
async addScriptRunNumber({
|
||||
tabId,
|
||||
frameId,
|
||||
@ -201,30 +212,28 @@ export class PopupService {
|
||||
frameId: number;
|
||||
scripts: ScriptMatchInfo[];
|
||||
}) {
|
||||
if (frameId === undefined) {
|
||||
// 清理数据
|
||||
await Cache.getInstance().del("tabScript:" + tabId);
|
||||
}
|
||||
// 设置数据
|
||||
const data = await this.getScriptMenu(tabId);
|
||||
// 设置脚本运行次数
|
||||
scripts.forEach((script) => {
|
||||
const scriptMenu = data.find((item) => item.uuid === script.uuid);
|
||||
if (scriptMenu) {
|
||||
scriptMenu.runNum = (scriptMenu.runNum || 0) + 1;
|
||||
if (frameId) {
|
||||
scriptMenu.runNumByIframe = (scriptMenu.runNumByIframe || 0) + 1;
|
||||
return this.txUpdateScriptMenu(tabId, async (data) => {
|
||||
data = [];
|
||||
// 设置脚本运行次数
|
||||
scripts.forEach((script) => {
|
||||
const scriptMenu = data.find((item) => item.uuid === script.uuid);
|
||||
if (scriptMenu) {
|
||||
scriptMenu.runNum = (scriptMenu.runNum || 0) + 1;
|
||||
if (frameId) {
|
||||
scriptMenu.runNumByIframe = (scriptMenu.runNumByIframe || 0) + 1;
|
||||
}
|
||||
} else {
|
||||
const item = this.scriptToMenu(script);
|
||||
item.runNum = 1;
|
||||
if (frameId) {
|
||||
item.runNumByIframe = 1;
|
||||
}
|
||||
data.push(item);
|
||||
}
|
||||
} else {
|
||||
const item = this.scriptToMenu(script);
|
||||
item.runNum = 1;
|
||||
if (frameId) {
|
||||
item.runNumByIframe = 1;
|
||||
}
|
||||
data.push(item);
|
||||
}
|
||||
});
|
||||
return data;
|
||||
});
|
||||
Cache.getInstance().set("tabScript:" + tabId, data);
|
||||
}
|
||||
|
||||
dealBackgroundScriptInstall() {
|
||||
@ -233,21 +242,17 @@ export class PopupService {
|
||||
if (script.type === SCRIPT_TYPE_NORMAL) {
|
||||
return;
|
||||
}
|
||||
const menu = await this.getScriptMenu(-1);
|
||||
const scriptMenu = menu.find((item) => item.uuid === script.uuid);
|
||||
if (script.status === SCRIPT_STATUS_ENABLE) {
|
||||
// 加入菜单
|
||||
if (!scriptMenu) {
|
||||
const item = this.scriptToMenu(script);
|
||||
menu.push(item);
|
||||
return this.txUpdateScriptMenu(-1, async (menu) => {
|
||||
const scriptMenu = menu.find((item) => item.uuid === script.uuid);
|
||||
if (script.status === SCRIPT_STATUS_ENABLE) {
|
||||
// 加入菜单
|
||||
if (!scriptMenu) {
|
||||
const item = this.scriptToMenu(script);
|
||||
menu.push(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 移出菜单
|
||||
if (scriptMenu) {
|
||||
menu.splice(menu.indexOf(scriptMenu), 1);
|
||||
}
|
||||
}
|
||||
Cache.getInstance().set("tabScript:" + -1, menu);
|
||||
return menu;
|
||||
});
|
||||
});
|
||||
subscribeScriptEnable(this.mq, async ({ uuid }) => {
|
||||
const script = await this.scriptDAO.get(uuid);
|
||||
@ -257,37 +262,42 @@ export class PopupService {
|
||||
if (script.type === SCRIPT_TYPE_NORMAL) {
|
||||
return;
|
||||
}
|
||||
const menu = await this.getScriptMenu(-1);
|
||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
||||
if (script.status === SCRIPT_STATUS_ENABLE) {
|
||||
// 加入菜单
|
||||
if (!scriptMenu) {
|
||||
const item = this.scriptToMenu(script);
|
||||
menu.push(item);
|
||||
return this.txUpdateScriptMenu(-1, async (menu) => {
|
||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
||||
if (script.status === SCRIPT_STATUS_ENABLE) {
|
||||
// 加入菜单
|
||||
if (!scriptMenu) {
|
||||
const item = this.scriptToMenu(script);
|
||||
menu.push(item);
|
||||
}
|
||||
} else {
|
||||
// 移出菜单
|
||||
if (scriptMenu) {
|
||||
menu.splice(menu.indexOf(scriptMenu), 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 移出菜单
|
||||
if (scriptMenu) {
|
||||
menu.splice(menu.indexOf(scriptMenu), 1);
|
||||
}
|
||||
}
|
||||
Cache.getInstance().set("tabScript:" + -1, menu);
|
||||
return menu;
|
||||
});
|
||||
});
|
||||
subscribeScriptDelete(this.mq, async ({ uuid }) => {
|
||||
const menu = await this.getScriptMenu(-1);
|
||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
||||
if (scriptMenu) {
|
||||
menu.splice(menu.indexOf(scriptMenu), 1);
|
||||
Cache.getInstance().set("tabScript:" + -1, menu);
|
||||
}
|
||||
return this.txUpdateScriptMenu(-1, async (menu) => {
|
||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
||||
if (scriptMenu) {
|
||||
menu.splice(menu.indexOf(scriptMenu), 1);
|
||||
return menu;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
});
|
||||
subscribeScriptRunStatus(this.mq, async ({ uuid, runStatus }) => {
|
||||
const menu = await this.getScriptMenu(-1);
|
||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
||||
if (scriptMenu) {
|
||||
scriptMenu.runStatus = runStatus;
|
||||
Cache.getInstance().set("tabScript:" + -1, menu);
|
||||
}
|
||||
return this.txUpdateScriptMenu(-1, async (menu) => {
|
||||
const scriptMenu = menu.find((item) => item.uuid === uuid);
|
||||
if (scriptMenu) {
|
||||
scriptMenu.runStatus = runStatus;
|
||||
return menu;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -305,7 +315,6 @@ export class PopupService {
|
||||
documentId: string;
|
||||
}) {
|
||||
// 菜单点击事件
|
||||
console.log("click menu", uuid, id, tabId, frameId, documentId);
|
||||
this.runtime.sendMessageToTab(
|
||||
tabId,
|
||||
"menuClick",
|
||||
@ -333,7 +342,9 @@ export class PopupService {
|
||||
// 监听tab开关
|
||||
chrome.tabs.onRemoved.addListener((tabId) => {
|
||||
// 清理数据
|
||||
Cache.getInstance().del("tabScript:" + tabId);
|
||||
this.txUpdateScriptMenu(tabId, async () => {
|
||||
return [];
|
||||
});
|
||||
});
|
||||
// 监听页面切换加载菜单
|
||||
chrome.tabs.onActivated.addListener((activeInfo) => {
|
||||
|
@ -212,6 +212,7 @@ export class RuntimeService {
|
||||
return runScript(this.sender, res);
|
||||
}
|
||||
|
||||
// 注册inject.js
|
||||
registerInjectScript() {
|
||||
chrome.userScripts.getScripts({ ids: ["scriptcat-inject"] }).then((res) => {
|
||||
if (res.length == 0) {
|
||||
|
@ -17,6 +17,7 @@ const server = new Server("inject", msg);
|
||||
|
||||
server.on("pageLoad", (data: { scripts: ScriptRunResouce[] }) => {
|
||||
logger.logger().debug("inject start");
|
||||
const runtime = new InjectRuntime(msg, data.scripts);
|
||||
// 监听事件
|
||||
const runtime = new InjectRuntime(server, msg, data.scripts);
|
||||
runtime.start();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ScriptRunResouce } from "@App/app/repo/scripts";
|
||||
import { Client } from "@Packages/message/client";
|
||||
import { Client, sendMessage } from "@Packages/message/client";
|
||||
import { forwardMessage, Message, MessageSend, Server } from "@Packages/message/server";
|
||||
|
||||
// content页的处理
|
||||
@ -7,49 +7,55 @@ export default class ContentRuntime {
|
||||
constructor(
|
||||
private extServer: Server,
|
||||
private server: Server,
|
||||
private send: MessageSend,
|
||||
private extSend: MessageSend,
|
||||
private msg: Message
|
||||
) {}
|
||||
|
||||
start(scripts: ScriptRunResouce[]) {
|
||||
this.extServer.on("runtime/menuClick", (action, data) => {
|
||||
// gm菜单点击
|
||||
console.log("runtime/menuClick", action, data);
|
||||
this.extServer.on("runtime/menuClick", (data) => {
|
||||
// 转发给inject
|
||||
return sendMessage(this.msg, "inject/runtime/menuClick", data);
|
||||
});
|
||||
this.extServer.on("runtime/valueUpdate", (action, data) => {
|
||||
// gm value变化
|
||||
console.log(action, data);
|
||||
this.extServer.on("runtime/valueUpdate", (data) => {
|
||||
// 转发给inject
|
||||
return sendMessage(this.msg, "inject/runtime/valueUpdate", data);
|
||||
});
|
||||
forwardMessage("serviceWorker", "runtime/gmApi", this.server, this.send, (data: { api: string; params: any }) => {
|
||||
// 拦截关注的api
|
||||
switch (data.api) {
|
||||
case "CAT_createBlobUrl": {
|
||||
const file = data.params[0] as File;
|
||||
const url = URL.createObjectURL(file);
|
||||
setTimeout(() => {
|
||||
URL.revokeObjectURL(url);
|
||||
}, 60 * 1000);
|
||||
return Promise.resolve(url);
|
||||
}
|
||||
case "CAT_fetchBlob": {
|
||||
return fetch(data.params[0]).then((res) => res.blob());
|
||||
}
|
||||
case "CAT_fetchDocument": {
|
||||
return new Promise((resolve) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.responseType = "document";
|
||||
xhr.open("GET", data.params[0]);
|
||||
xhr.onload = () => {
|
||||
resolve({
|
||||
relatedTarget: xhr.response,
|
||||
});
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
forwardMessage(
|
||||
"serviceWorker",
|
||||
"runtime/gmApi",
|
||||
this.server,
|
||||
this.extSend,
|
||||
(data: { api: string; params: any }) => {
|
||||
// 拦截关注的api
|
||||
switch (data.api) {
|
||||
case "CAT_createBlobUrl": {
|
||||
const file = data.params[0] as File;
|
||||
const url = URL.createObjectURL(file);
|
||||
setTimeout(() => {
|
||||
URL.revokeObjectURL(url);
|
||||
}, 60 * 1000);
|
||||
return Promise.resolve(url);
|
||||
}
|
||||
case "CAT_fetchBlob": {
|
||||
return fetch(data.params[0]).then((res) => res.blob());
|
||||
}
|
||||
case "CAT_fetchDocument": {
|
||||
return new Promise((resolve) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.responseType = "document";
|
||||
xhr.open("GET", data.params[0]);
|
||||
xhr.onload = () => {
|
||||
resolve({
|
||||
relatedTarget: xhr.response,
|
||||
});
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
});
|
||||
);
|
||||
const client = new Client(this.msg, "inject");
|
||||
client.do("pageLoad", { scripts });
|
||||
}
|
||||
|
@ -72,6 +72,10 @@ export default class ExecScript {
|
||||
this.sandboxContent?.valueUpdate(data);
|
||||
}
|
||||
|
||||
menuClick(id: number) {
|
||||
this.sandboxContent?.menuClick(id);
|
||||
}
|
||||
|
||||
exec() {
|
||||
this.logger.debug("script start");
|
||||
return this.scriptFunc.apply(this.proxyContent, [this.proxyContent, this.GM_info]);
|
||||
|
@ -7,6 +7,7 @@ import { Message, MessageConnect } from "@Packages/message/server";
|
||||
import { CustomEventMessage } from "@Packages/message/custom_event_message";
|
||||
import LoggerCore from "@App/app/logger/core";
|
||||
import { connect, sendMessage } from "@Packages/message/client";
|
||||
import EventEmitter from "eventemitter3";
|
||||
|
||||
interface ApiParam {
|
||||
depend?: string[];
|
||||
@ -106,6 +107,10 @@ export default class GMApi {
|
||||
}
|
||||
}
|
||||
|
||||
menuClick(id: number) {
|
||||
this.EE.emit("menuClick" + id);
|
||||
}
|
||||
|
||||
// 获取脚本信息和管理器信息
|
||||
static GM_info(script: ScriptRunResouce) {
|
||||
const metadataStr = getMetadataStr(script.code);
|
||||
@ -202,18 +207,21 @@ export default class GMApi {
|
||||
|
||||
menuMap: Map<number, string> | undefined;
|
||||
|
||||
EE: EventEmitter = new EventEmitter();
|
||||
|
||||
@GMContext.API()
|
||||
GM_registerMenuCommand(name: string, listener: () => void, accessKey?: string): number {
|
||||
if (!this.menuMap) {
|
||||
this.menuMap = new Map();
|
||||
}
|
||||
let flag = 0;
|
||||
this.menuMap.forEach((val, key) => {
|
||||
this.menuMap.forEach((val, menuId) => {
|
||||
if (val === name) {
|
||||
flag = key;
|
||||
flag = menuId;
|
||||
}
|
||||
});
|
||||
if (flag) {
|
||||
this.EE.addListener("menuClick" + flag, listener);
|
||||
return flag;
|
||||
}
|
||||
if (!this.menuId) {
|
||||
@ -222,18 +230,9 @@ export default class GMApi {
|
||||
this.menuId += 1;
|
||||
}
|
||||
const id = this.menuId;
|
||||
this.sendMessage("GM_registerMenuCommand", [id, name, accessKey]);
|
||||
// .then((con) => {
|
||||
// con.onMessage((data: { action: string; data: any }) => {
|
||||
// if (data.action === "onClick") {
|
||||
// listener();
|
||||
// }
|
||||
// });
|
||||
// con.onDisconnect(() => {
|
||||
// this.menuMap?.delete(id);
|
||||
// });
|
||||
// });
|
||||
this.menuMap.set(id, name);
|
||||
this.EE.addListener("menuClick" + id, listener);
|
||||
this.sendMessage("GM_registerMenuCommand", [id, name, accessKey]);
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -243,6 +242,7 @@ export default class GMApi {
|
||||
this.menuMap = new Map();
|
||||
}
|
||||
this.menuMap.delete(id);
|
||||
this.EE.removeAllListeners("menuClick" + id);
|
||||
this.sendMessage("GM_unregisterMenuCommand", [id]);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ScriptRunResouce } from "@App/app/repo/scripts";
|
||||
import { Message } from "@Packages/message/server";
|
||||
import { Message, Server } from "@Packages/message/server";
|
||||
import ExecScript from "./exec_script";
|
||||
import { addStyle, ScriptFunc } from "./utils";
|
||||
|
||||
@ -7,6 +7,7 @@ export class InjectRuntime {
|
||||
execList: ExecScript[] = [];
|
||||
|
||||
constructor(
|
||||
private server: Server,
|
||||
private msg: Message,
|
||||
private scripts: ScriptRunResouce[]
|
||||
) {}
|
||||
@ -27,6 +28,19 @@ export class InjectRuntime {
|
||||
});
|
||||
}
|
||||
});
|
||||
this.server.on("runtime/menuClick", (data: { id: number; uuid: string }) => {
|
||||
// 转发给脚本
|
||||
const exec = this.execList.find((val) => val.scriptRes.uuid === data.uuid);
|
||||
if (exec) {
|
||||
exec.menuClick(data.id);
|
||||
}
|
||||
});
|
||||
this.server.on("runtime/valueUpdate", (data: { uuid: string; key: string; value: any }) => {
|
||||
const exec = this.execList.find((val) => val.scriptRes.uuid === data.uuid);
|
||||
if (exec) {
|
||||
// exec.valueUpdate(data.key,);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
execScript(script: ScriptRunResouce, scriptFunc: ScriptFunc) {
|
||||
|
@ -3,6 +3,7 @@ import { v4 as uuidv4 } from "uuid";
|
||||
import GMApi, { ApiValue, GMContext } from "./gm_api";
|
||||
import { has } from "@App/pkg/utils/lodash";
|
||||
import { Message } from "@Packages/message/server";
|
||||
import EventEmitter from "eventemitter3";
|
||||
|
||||
// 构建脚本运行代码
|
||||
export function compileScriptCode(scriptRes: ScriptRunResouce): string {
|
||||
@ -64,6 +65,8 @@ export function createContext(scriptRes: ScriptRunResouce, GMInfo: any, envPrefi
|
||||
connect: GMApi.prototype.connect,
|
||||
runFlag: uuidv4(),
|
||||
valueUpdate: GMApi.prototype.valueUpdate,
|
||||
menuClick: GMApi.prototype.menuClick,
|
||||
EE: new EventEmitter(),
|
||||
GM: { Info: GMInfo },
|
||||
GM_info: GMInfo,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user