diff --git a/packages/message/custom_event_message.ts b/packages/message/custom_event_message.ts new file mode 100644 index 0000000..40b5a07 --- /dev/null +++ b/packages/message/custom_event_message.ts @@ -0,0 +1,133 @@ +import { Message, MessageConnect } from "./server"; +import { v4 as uuidv4 } from "uuid"; +import { PostMessage, WindowMessageBody, WindowMessageConnect } from "./window_message"; +import LoggerCore from "@App/app/logger/core"; +import EventEmitter from "eventemitter3"; + +export class CustomEventPostMessage implements PostMessage { + constructor(private send: CustomEventMessage) {} + + postMessage(message: any): void { + this.send.nativeSend(message); + } +} + +// 使用CustomEvent来进行通讯, 可以在content与inject中传递一些dom对象 +export class CustomEventMessage implements Message { + EE: EventEmitter = new EventEmitter(); + + // 关联dom目标 + relatedTarget: Map = new Map(); + + constructor( + protected flag: string, + protected isContent: boolean + ) { + window.addEventListener((isContent ? "ct" : "fd") + flag, (event) => { + if (event instanceof MouseEvent) { + this.relatedTarget.set(event.clientX, event.relatedTarget); + return; + } else if (event instanceof CustomEvent) { + this.messageHandle(event.detail, new CustomEventPostMessage(this)); + } + }); + } + + messageHandle(data: WindowMessageBody, target: PostMessage) { + // 处理消息 + if (data.type === "sendMessage") { + // 接收到消息 + this.EE.emit("message", data.data, (resp: any) => { + // 发送响应消息 + // 无消息id则不发送响应消息 + if (!data.messageId) { + return; + } + const body: WindowMessageBody = { + messageId: data.messageId, + type: "respMessage", + data: resp, + }; + target.postMessage(body); + }); + } else if (data.type === "respMessage") { + // 接收到响应消息 + this.EE.emit("response:" + data.messageId, data); + } else if (data.type === "connect") { + this.EE.emit("connect", data.data, new WindowMessageConnect(data.messageId, this.EE, target)); + } else if (data.type === "disconnect") { + this.EE.emit("disconnect:" + data.messageId); + } else if (data.type === "connectMessage") { + this.EE.emit("connectMessage:" + data.messageId, data.data); + } + } + + onConnect(callback: (data: any, con: MessageConnect) => void): void { + this.EE.addListener("connect", callback); + } + + onMessage(callback: (data: any, sendResponse: (data: any) => void) => void): void { + this.EE.addListener("message", callback); + } + + connect(data: any): Promise { + return new Promise((resolve) => { + const body: WindowMessageBody = { + messageId: uuidv4(), + type: "connect", + data, + }; + this.nativeSend(body); + resolve(new WindowMessageConnect(body.messageId, this.EE, new CustomEventPostMessage(this))); + }); + } + + nativeSend(data: any) { + let detail = data; + + // 特殊处理relatedTarget + if (detail.data && typeof detail.data.relatedTarget === "object") { + // 先将relatedTarget转换成id发送过去 + const target = detail.data.relatedTarget; + delete detail.data.relatedTarget; + detail.data.relatedTarget = Math.ceil(Math.random() * 1000000); + // 可以使用此种方式交互element + const ev = new MouseEvent((this.isContent ? "fd" : "ct") + this.flag, { + clientX: detail.data.relatedTarget, + relatedTarget: target, + }); + window.dispatchEvent(ev); + } + + if (typeof cloneInto !== "undefined") { + try { + LoggerCore.logger().info("nativeSend"); + detail = cloneInto(detail, document.defaultView); + } catch (e) { + console.log(e); + LoggerCore.logger().info("error data"); + } + } + + const ev = new CustomEvent((this.isContent ? "fd" : "ct") + this.flag, { + detail, + }); + window.dispatchEvent(ev); + } + + sendMessage(data: any): Promise { + return new Promise((resolve) => { + const body: WindowMessageBody = { + messageId: uuidv4(), + type: "sendMessage", + data, + }; + const callback = (body: WindowMessageBody) => { + this.EE.removeListener("response:" + body.messageId, callback); + resolve(body.data); + }; + this.EE.addListener("response:" + body.messageId, callback); + this.nativeSend(body); + }); + } +} diff --git a/packages/message/window_message.ts b/packages/message/window_message.ts index f0cbe75..60102b6 100644 --- a/packages/message/window_message.ts +++ b/packages/message/window_message.ts @@ -5,7 +5,7 @@ import { Message, MessageConnect, MessageSend } from "./server"; import EventEmitter from "eventemitter3"; -interface PostMessage { +export interface PostMessage { postMessage(message: any): void; } diff --git a/rspack.config.ts b/rspack.config.ts index 1166fae..f4fc5b2 100644 --- a/rspack.config.ts +++ b/rspack.config.ts @@ -28,6 +28,8 @@ export default defineConfig({ service_worker: `${src}/service_worker.ts`, offscreen: `${src}/offscreen.ts`, sandbox: `${src}/sandbox.ts`, + content: `${src}/content.ts`, + inject: `${src}/inject.ts`, popup: `${src}/pages/popup/main.tsx`, install: `${src}/pages/install/main.tsx`, options: `${src}/pages/options/main.tsx`, diff --git a/src/app/service/offscreen/script.ts b/src/app/service/offscreen/script.ts index 2d0ccf3..9e67c43 100644 --- a/src/app/service/offscreen/script.ts +++ b/src/app/service/offscreen/script.ts @@ -6,7 +6,7 @@ import { ResourceClient, ScriptClient, ValueClient } from "../service_worker/cli import { SCRIPT_STATUS_ENABLE, SCRIPT_TYPE_NORMAL, ScriptRunResouce } from "@App/app/repo/scripts"; import { disableScript, enableScript, runScript, stopScript } from "../sandbox/client"; import { Group, MessageSend } from "@Packages/message/server"; -import { subscribeScriptEnable, subscribeScriptInstall } from "../queue"; +import { subscribeScriptDelete, subscribeScriptEnable, subscribeScriptInstall } from "../queue"; export class ScriptService { logger: Logger; @@ -34,7 +34,6 @@ export class ScriptService { async init() { subscribeScriptEnable(this.messageQueue, async (data) => { - console.log("subscribeScriptEnable", data); const script = await this.scriptClient.info(data.uuid); if (script.type === SCRIPT_TYPE_NORMAL) { return; @@ -48,7 +47,6 @@ export class ScriptService { } }); subscribeScriptInstall(this.messageQueue, async (data) => { - console.log("subscribeScriptInstall", data); // 判断是开启还是关闭 if (data.script.status === SCRIPT_STATUS_ENABLE) { // 构造脚本运行资源,发送给沙盒运行 @@ -58,6 +56,9 @@ export class ScriptService { disableScript(this.windowMessage, data.script.uuid); } }); + subscribeScriptDelete(this.messageQueue, async (data) => { + disableScript(this.windowMessage, data.uuid); + }); this.group.on("runScript", this.runScript.bind(this)); this.group.on("stopScript", this.stopScript.bind(this)); diff --git a/src/app/service/service_worker/client.ts b/src/app/service/service_worker/client.ts index eb0e859..e0cd17d 100644 --- a/src/app/service/service_worker/client.ts +++ b/src/app/service/service_worker/client.ts @@ -81,4 +81,8 @@ export class RuntimeClient extends Client { stopScript(uuid: string) { return this.do("stopScript", uuid); } + + pageLoad(): Promise<{ flag: string; scripts: ScriptRunResouce[] }> { + return this.do("pageLoad"); + } } diff --git a/src/app/service/service_worker/runtime.ts b/src/app/service/service_worker/runtime.ts index 5004f4b..3e9e2f5 100644 --- a/src/app/service/service_worker/runtime.ts +++ b/src/app/service/service_worker/runtime.ts @@ -1,16 +1,29 @@ import { MessageQueue } from "@Packages/message/message_queue"; import { Group, MessageSend } from "@Packages/message/server"; -import { Script, SCRIPT_STATUS_ENABLE, SCRIPT_TYPE_NORMAL, ScriptAndCode, ScriptDAO } from "@App/app/repo/scripts"; +import { + Script, + SCRIPT_STATUS_ENABLE, + SCRIPT_TYPE_NORMAL, + ScriptDAO, + ScriptRunResouce, +} from "@App/app/repo/scripts"; import { ValueService } from "./value"; import GMApi from "./gm_api"; -import { subscribeScriptEnable } from "../queue"; +import { subscribeScriptDelete, subscribeScriptEnable, subscribeScriptInstall } from "../queue"; import { ScriptService } from "./script"; import { runScript, stopScript } from "../offscreen/client"; -import { dealMatches } from "./utils"; +import { dealMatches, getRunAt } from "./utils"; +import { randomString } from "@App/pkg/utils/utils"; +import { compileInjectScript, compileScriptCode } from "@App/runtime/content/utils"; export class RuntimeService { scriptDAO: ScriptDAO = new ScriptDAO(); + scriptFlag: string = randomString(8); + + // 运行中的页面脚本 + runningPageScript = new Map(); + constructor( private group: Group, private sender: MessageSend, @@ -20,6 +33,8 @@ export class RuntimeService { ) {} async init() { + // 读取inject.js注入页面 + this.registerInjectScript(); // 监听脚本开启 subscribeScriptEnable(this.mq, async (data) => { const script = await this.scriptDAO.getAndCode(data.uuid); @@ -37,6 +52,26 @@ export class RuntimeService { } } }); + // 监听脚本安装 + subscribeScriptInstall(this.mq, async (data) => { + const script = await this.scriptDAO.get(data.script.uuid); + if (!script) { + return; + } + if (script.type === SCRIPT_TYPE_NORMAL) { + this.registryPageScript(script); + } + }); + // 监听脚本删除 + subscribeScriptDelete(this.mq, async (data) => { + const script = await this.scriptDAO.get(data.uuid); + if (!script) { + return; + } + if (script.type === SCRIPT_TYPE_NORMAL) { + this.unregistryPageScript(script); + } + }); // 将开启的脚本发送一次enable消息 const scriptDao = new ScriptDAO(); @@ -63,6 +98,11 @@ export class RuntimeService { this.group.on("stopScript", this.stopScript.bind(this)); this.group.on("runScript", this.runScript.bind(this)); + this.group.on("pageLoad", this.pageLoad.bind(this)); + } + + pageLoad() { + return Promise.resolve({ flag: this.scriptFlag }); } // 停止脚本 @@ -80,16 +120,41 @@ export class RuntimeService { return runScript(this.sender, res); } - registryPageScript(script: ScriptAndCode) { - console.log(script); + registerInjectScript() { + fetch("inject.js") + .then((res) => res.text()) + .then((injectJs) => { + // 替换ScriptFlag + const code = `(function (ScriptFlag) {\n${injectJs}\n})('${this.scriptFlag}')`; + chrome.userScripts.register([ + { + id: "scriptcat-inject", + js: [{ code }], + matches: [""], + allFrames: true, + world: "MAIN", + runAt: "document_start", + }, + ]); + }); + } + + async registryPageScript(script: Script) { const matches = script.metadata["match"]; if (!matches) { return; } + const scriptRes = await this.script.buildScriptRunResource(script); + + scriptRes.code = compileScriptCode(scriptRes); + scriptRes.code = compileInjectScript(scriptRes); + + this.runningPageScript.set(scriptRes.uuid, scriptRes); + matches.push(...(script.metadata["include"] || [])); const registerScript: chrome.userScripts.RegisteredUserScript = { - id: script.uuid, - js: [{ code: script.code }], + id: scriptRes.uuid, + js: [{ code: scriptRes.code }], matches: dealMatches(matches), world: "MAIN", }; @@ -102,7 +167,7 @@ export class RuntimeService { registerScript.excludeMatches = dealMatches(excludeMatches); } if (script.metadata["run-at"]) { - registerScript.runAt = script.metadata["run-at"][0] as chrome.userScripts.RunAt; + registerScript.runAt = getRunAt(script.metadata["run-at"]); } chrome.userScripts.register([registerScript]); } diff --git a/src/app/service/service_worker/script.ts b/src/app/service/service_worker/script.ts index 27cb558..37d167f 100644 --- a/src/app/service/service_worker/script.ts +++ b/src/app/service/service_worker/script.ts @@ -273,7 +273,8 @@ export class ScriptService { if (!code) { throw new Error("code is null"); } - ret.code = compileScriptCode(ret, code.code); + ret.code = code.code; + ret.code = compileScriptCode(ret); return Promise.resolve(ret); } diff --git a/src/app/service/service_worker/utils.ts b/src/app/service/service_worker/utils.ts index 47cec55..faba5d7 100644 --- a/src/app/service/service_worker/utils.ts +++ b/src/app/service/service_worker/utils.ts @@ -9,3 +9,16 @@ export function isExtensionRequest(details: chrome.webRequest.ResourceRequest & export function dealMatches(matches: string[]) { return matches; } + +export function getRunAt(runAts: string[]): chrome.userScripts.RunAt { + if (runAts.length === 0) { + return "document_idle"; + } + const runAt = runAts[0]; + if (runAt === "document-start") { + return "document_start"; + } else if (runAt === "document-end") { + return "document_end"; + } + return "document_idle"; +} diff --git a/src/content.ts b/src/content.ts index 633ed9e..98e4e89 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1,24 +1,25 @@ import LoggerCore from "./app/logger/core"; import MessageWriter from "./app/logger/message_writer"; -import { SandboxManager } from "./app/service/sandbox"; import { ExtensionMessageSend } from "@Packages/message/extension_message"; +import { CustomEventMessage } from "@Packages/message/custom_event_message"; +import { RuntimeClient } from "./app/service/service_worker/client"; import ContentRuntime from "./runtime/content/content"; -function main() { - // 建立与service_worker页面的连接 - const msg = new ExtensionMessageSend(); +// 建立与service_worker页面的连接 +const send = new ExtensionMessageSend(); - // 初始化日志组件 - const loggerCore = new LoggerCore({ - writer: new MessageWriter(msg), - labels: { env: "content" }, - }); +// 初始化日志组件 +const loggerCore = new LoggerCore({ + writer: new MessageWriter(send), + labels: { env: "content" }, +}); + +const client = new RuntimeClient(send); +client.pageLoad().then((data) => { loggerCore.logger().debug("content start"); - + console.log("content", data); + const msg = new CustomEventMessage(data.flag, true); // 初始化运行环境 - const contentMessage = new MessageContent(scriptFlag, true); - const runtime = new ContentRuntime(contentMessage, internalMessage); - runtime.start(); -} - -main(); + const runtime = new ContentRuntime(send, msg); + runtime.start(data.scripts); +}); diff --git a/src/inject.ts b/src/inject.ts new file mode 100644 index 0000000..d5fa843 --- /dev/null +++ b/src/inject.ts @@ -0,0 +1,26 @@ +import LoggerCore from "./app/logger/core"; +import MessageWriter from "./app/logger/message_writer"; +import { CustomEventMessage } from "@Packages/message/custom_event_message"; +import { Server } from "@Packages/message/server"; +import { InjectRuntime } from "./runtime/content/inject"; +import { ScriptRunResouce } from "./app/repo/scripts"; + +// 通过flag与content建立通讯,这个ScriptFlag是后端注入时候生成的 +const flag = ScriptFlag; + +const msg = new CustomEventMessage(flag, false); + +// 加载logger组件 +const logger = new LoggerCore({ + writer: new MessageWriter(msg), + labels: { env: "inject", href: window.location.href }, +}); + +const server = new Server("inject", msg); + +server.on("pageLoad", (data: ScriptRunResouce[]) => { + logger.logger().debug("inject start"); + console.log("inject", data); + const runtime = new InjectRuntime(msg, data); + runtime.start(); +}); diff --git a/src/injected.ts b/src/injected.ts deleted file mode 100644 index 1a5a407..0000000 --- a/src/injected.ts +++ /dev/null @@ -1,23 +0,0 @@ -import LoggerCore from "./app/logger/core"; -import MessageWriter from "./app/logger/message_writer"; -import MessageContent from "./app/message/content"; -import InjectRuntime from "./runtime/content/inject"; - -// 通过flag与content建立通讯,这个ScriptFlag是后端注入时候生成的 -// eslint-disable-next-line no-undef -const flag = ScriptFlag; - -const message = new MessageContent(flag, false); - -// 加载logger组件 -const logger = new LoggerCore({ - debug: process.env.NODE_ENV === "development", - writer: new MessageWriter(message), - labels: { env: "inject", href: window.location.href }, -}); - -message.setHandler("pageLoad", (_action, data) => { - logger.logger().debug("inject start"); - const runtime = new InjectRuntime(message, data.scripts, flag); - runtime.start(); -}); diff --git a/src/manifest.json b/src/manifest.json index c86dc3e..623c425 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -17,6 +17,18 @@ "128": "assets/logo.png" } }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "src/content.js" + ], + "run_at": "document_start", + "all_frames": true + } + ], "icons": { "128": "assets/logo.png" }, diff --git a/src/runtime/content/content.ts b/src/runtime/content/content.ts index ed57b9f..f7074fd 100644 --- a/src/runtime/content/content.ts +++ b/src/runtime/content/content.ts @@ -1,115 +1,94 @@ -import { ExternalMessage } from "@App/app/const"; -import MessageContent from "@App/app/message/content"; -import MessageInternal from "@App/app/message/internal"; -import { MessageHander, MessageManager } from "@App/app/message/message"; import { ScriptRunResouce } from "@App/app/repo/scripts"; +import { Client } from "@Packages/message/client"; +import { Message, MessageSend } from "@Packages/message/server"; // content页的处理 export default class ContentRuntime { - contentMessage: MessageHander & MessageManager; - - internalMessage: MessageInternal; - constructor( - contentMessage: MessageHander & MessageManager, - internalMessage: MessageInternal - ) { - this.contentMessage = contentMessage; - this.internalMessage = internalMessage; - } + private send: MessageSend, + private msg: Message + ) {} - start(resp: { scripts: ScriptRunResouce[] }) { + start(scripts: ScriptRunResouce[]) { // 由content到background // 转发gmApi消息 - this.contentMessage.setHandler("gmApi", (action, data) => { - return this.internalMessage.syncSend(action, data); - }); - // 转发log消息 - this.contentMessage.setHandler("log", (action, data) => { - this.internalMessage.send(action, data); - }); - // 转发externalMessage消息 - this.contentMessage.setHandler(ExternalMessage, (action, data) => { - return this.internalMessage.syncSend(action, data); - }); + // this.contentMessage.setHandler("gmApi", (action, data) => { + // return this.internalMessage.syncSend(action, data); + // }); + // // 转发log消息 + // this.contentMessage.setHandler("log", (action, data) => { + // this.internalMessage.send(action, data); + // }); + // // 转发externalMessage消息 + // this.contentMessage.setHandler(ExternalMessage, (action, data) => { + // return this.internalMessage.syncSend(action, data); + // }); // 处理GM_addElement // @ts-ignore - this.contentMessage.setHandler("GM_addElement", (action, data) => { - const parma = data.param; - let attr: { [x: string]: any; textContent?: any }; - let textContent = ""; - if (!parma[1]) { - attr = {}; - } else { - attr = { ...parma[1] }; - if (attr.textContent) { - textContent = attr.textContent; - delete attr.textContent; - } - } - const el = document.createElement(parma[0]); - Object.keys(attr).forEach((key) => { - el.setAttribute(key, attr[key]); - }); - if (textContent) { - el.innerHTML = textContent; - } - let parentNode; - if (data.relatedTarget) { - parentNode = (( - this.contentMessage - )).getAndDelRelatedTarget(data.relatedTarget); - } - ( - parentNode || - document.head || - document.body || - document.querySelector("*") - ).appendChild(el); - return { - relatedTarget: el, - }; - }); - - // 转发长连接的gmApi消息 - this.contentMessage.setHandlerWithChannel( - "gmApiChannel", - (inject, action, data) => { - const background = this.internalMessage.channel(); - // 转发inject->background - inject.setHandler((req) => { - background.send(req.data); - }); - inject.setCatch((err) => { - background.throw(err); - }); - inject.setDisChannelHandler(() => { - background.disChannel(); - }); - // 转发background->inject - background.setHandler((bgResp) => { - inject.send(bgResp); - }); - background.setCatch((err) => { - inject.throw(err); - }); - background.setDisChannelHandler(() => { - inject.disChannel(); - }); - // 建立连接 - background.channel(action, data); - } - ); - - this.listenCATApi(); - - // 由background到content - // 转发value更新事件 - this.internalMessage.setHandler("valueUpdate", (action, data) => { - this.contentMessage.send(action, data); - }); - - this.contentMessage.send("pageLoad", resp); + // this.contentMessage.setHandler("GM_addElement", (action, data) => { + // const parma = data.param; + // let attr: { [x: string]: any; textContent?: any }; + // let textContent = ""; + // if (!parma[1]) { + // attr = {}; + // } else { + // attr = { ...parma[1] }; + // if (attr.textContent) { + // textContent = attr.textContent; + // delete attr.textContent; + // } + // } + // const el = document.createElement(parma[0]); + // Object.keys(attr).forEach((key) => { + // el.setAttribute(key, attr[key]); + // }); + // if (textContent) { + // el.innerHTML = textContent; + // } + // let parentNode; + // if (data.relatedTarget) { + // parentNode = (this.contentMessage).getAndDelRelatedTarget(data.relatedTarget); + // } + // (parentNode || document.head || document.body || document.querySelector("*")).appendChild(el); + // return { + // relatedTarget: el, + // }; + // }); + // // 转发长连接的gmApi消息 + // this.contentMessage.setHandlerWithChannel("gmApiChannel", (inject, action, data) => { + // const background = this.internalMessage.channel(); + // // 转发inject->background + // inject.setHandler((req) => { + // background.send(req.data); + // }); + // inject.setCatch((err) => { + // background.throw(err); + // }); + // inject.setDisChannelHandler(() => { + // background.disChannel(); + // }); + // // 转发background->inject + // background.setHandler((bgResp) => { + // inject.send(bgResp); + // }); + // background.setCatch((err) => { + // inject.throw(err); + // }); + // background.setDisChannelHandler(() => { + // inject.disChannel(); + // }); + // // 建立连接 + // background.channel(action, data); + // }); + // this.listenCATApi(); + // // 由background到content + // // 转发value更新事件 + // this.internalMessage.setHandler("valueUpdate", (action, data) => { + // this.contentMessage.send(action, data); + // }); + // this.msg.sendMessage({ action: "pageLoad", data: { scripts } }); + const client = new Client(this.msg, "inject"); + client.do("pageLoad", { scripts }); } listenCATApi() { @@ -117,16 +96,13 @@ export default class ContentRuntime { this.contentMessage.setHandler("CAT_fetchBlob", (_action, data: string) => { return fetch(data).then((res) => res.blob()); }); - this.contentMessage.setHandler( - "CAT_createBlobUrl", - (_action, data: Blob) => { - const url = URL.createObjectURL(data); - setTimeout(() => { - URL.revokeObjectURL(url); - }, 60 * 1000); - return Promise.resolve(url); - } - ); + this.contentMessage.setHandler("CAT_createBlobUrl", (_action, data: Blob) => { + const url = URL.createObjectURL(data); + setTimeout(() => { + URL.revokeObjectURL(url); + }, 60 * 1000); + return Promise.resolve(url); + }); // 处理CAT_fetchDocument this.contentMessage.setHandler("CAT_fetchDocument", (_action, data) => { return new Promise((resolve) => { diff --git a/src/runtime/content/inject.ts b/src/runtime/content/inject.ts new file mode 100644 index 0000000..0441090 --- /dev/null +++ b/src/runtime/content/inject.ts @@ -0,0 +1,11 @@ +import { ScriptRunResouce } from "@App/app/repo/scripts"; +import { Message } from "@Packages/message/server"; + +export class InjectRuntime { + constructor( + private msg: Message, + private scripts: ScriptRunResouce[] + ) {} + + start(){} +} diff --git a/src/runtime/content/utils.ts b/src/runtime/content/utils.ts index c26e2b9..c350ea5 100644 --- a/src/runtime/content/utils.ts +++ b/src/runtime/content/utils.ts @@ -5,7 +5,7 @@ import { has } from "@App/pkg/utils/lodash"; import { Message } from "@Packages/message/server"; // 构建脚本运行代码 -export function compileScriptCode(scriptRes: ScriptRunResouce, code: string): string { +export function compileScriptCode(scriptRes: ScriptRunResouce): string { let require = ""; if (scriptRes.metadata.require) { scriptRes.metadata.require.forEach((val) => { @@ -15,7 +15,7 @@ export function compileScriptCode(scriptRes: ScriptRunResouce, code: string): st } }); } - code = require + code; + const code = require + scriptRes.code; return `with (context) return (async ()=>{\n${code}\n//# sourceURL=${chrome.runtime.getURL( `/${encodeURI(scriptRes.name)}.user.js` )}\n})()`; diff --git a/src/service_worker.ts b/src/service_worker.ts index 1f8a545..cb90b48 100644 --- a/src/service_worker.ts +++ b/src/service_worker.ts @@ -55,7 +55,8 @@ async function main() { }); loggerCore.logger().debug("service worker start"); // 初始化管理器 - const server = new Server("serviceWorker", new ExtensionMessage()); + const message = new ExtensionMessage(); + const server = new Server("serviceWorker", message); const manager = new ServiceWorkerManager(server, new MessageQueue(), new ServiceWorkerMessageSend()); manager.initManager(); // 初始化沙盒环境 diff --git a/src/types/main.d.ts b/src/types/main.d.ts index 2054099..78fcfc5 100644 --- a/src/types/main.d.ts +++ b/src/types/main.d.ts @@ -7,6 +7,11 @@ declare const sandbox: Window; declare const self: ServiceWorkerGlobalScope; +declare const ScriptFlag: string; + +// 可以让content与inject环境交换携带dom的对象 +declare let cloneInto: ((detail: any, view: any) => any) | undefined; + declare namespace GMSend { interface XHRDetails { method?: "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS";