diff --git a/src/app/service/offscreen/gm_api.ts b/src/app/service/offscreen/gm_api.ts index d1ccbd6..0af8eee 100644 --- a/src/app/service/offscreen/gm_api.ts +++ b/src/app/service/offscreen/gm_api.ts @@ -1,4 +1,4 @@ -import { Group, MessageConnect } from "@Packages/message/server"; +import { GetSender, Group, MessageConnect } from "@Packages/message/server"; export default class GMApi { constructor(private group: Group) {} @@ -24,8 +24,9 @@ export default class GMApi { return response; } - xmlHttpRequest(details: GMSend.XHRDetails, con: MessageConnect | null) { + xmlHttpRequest(details: GMSend.XHRDetails, sender: GetSender) { const xhr = new XMLHttpRequest(); + const con = sender.getConnect(); xhr.open(details.method || "GET", details.url); // 添加header if (details.headers) { @@ -34,7 +35,7 @@ export default class GMApi { } } xhr.onload = () => { - this.dealXhrResponse(con!, details, "onload", xhr); + this.dealXhrResponse(con, details, "onload", xhr); }; xhr.onloadstart = () => { this.dealXhrResponse(con!, details, "onloadstart", xhr); diff --git a/src/app/service/service_worker/gm_api.ts b/src/app/service/service_worker/gm_api.ts index 7617428..40574ff 100644 --- a/src/app/service/service_worker/gm_api.ts +++ b/src/app/service/service_worker/gm_api.ts @@ -1,7 +1,7 @@ import LoggerCore from "@App/app/logger/core"; import Logger from "@App/app/logger/logger"; import { Script, ScriptDAO } from "@App/app/repo/scripts"; -import { GetSender, Group, MessageConnect, MessageSend, MessageSender } from "@Packages/message/server"; +import { GetSender, Group, MessageSend, MessageSender } from "@Packages/message/server"; import { ValueService } from "@App/app/service/service_worker/value"; import PermissionVerify from "./permission_verify"; import { connect } from "@Packages/message/client"; @@ -23,7 +23,7 @@ export type Request = MessageRequest & { sender: MessageSender; }; -export type Api = (request: Request, con: MessageConnect | null) => Promise; +export type Api = (request: Request, con: GetSender) => Promise; export default class GMApi { logger: Logger; @@ -34,7 +34,7 @@ export default class GMApi { constructor( private group: Group, - private sender: MessageSend, + private send: MessageSend, private value: ValueService ) { this.logger = LoggerCore.logger().with({ service: "runtime/gm_api" }); @@ -53,7 +53,7 @@ export default class GMApi { this.logger.error("verify error", { api: data.api }, Logger.E(e)); return Promise.reject(e); } - return api.api.call(this, req, con.getConnect()); + return api.api.call(this, req, con); } // 解析请求 @@ -80,11 +80,12 @@ export default class GMApi { } // 根据header生成dnr规则 - async buildDNRRule(reqeustId: number, params: GMSend.XHRDetails) { + async buildDNRRule(reqeustId: number, params: GMSend.XHRDetails): Promise<{ [key: string]: string }> { // 检查是否有unsafe header,有则生成dnr规则 const headers = params.headers; + console.log(headers, !headers); if (!headers) { - return; + return Promise.resolve({}); } const requestHeaders = [ { @@ -100,6 +101,7 @@ export default class GMApi { operation: chrome.declarativeNetRequest.HeaderOperation.SET, value: headers[key], }); + delete headers[key]; } }); const ruleId = reqeustId; @@ -119,20 +121,23 @@ export default class GMApi { }); rule.condition = { resourceTypes: [chrome.declarativeNetRequest.ResourceType.XMLHTTPREQUEST], - urlFilter: "^" + params.url + "$", + urlFilter: params.url, + requestMethods: [(params.method || "GET").toLowerCase() as chrome.declarativeNetRequest.RequestMethod], excludedTabIds: excludedTabIds, }; + console.log(rule); await chrome.declarativeNetRequest.updateSessionRules({ removeRuleIds: [ruleId], addRules: [rule], }); - return ruleId; + return Promise.resolve(headers); } gmXhrHeadersReceived: EventEmitter = new EventEmitter(); @PermissionVerify.API() - async GM_xmlhttpRequest(request: Request, con: MessageConnect) { + async GM_xmlhttpRequest(request: Request, con: GetSender) { + console.log("GM XHR", request); if (request.params.length === 0) { return Promise.reject(new Error("param is failed")); } @@ -145,7 +150,8 @@ export default class GMApi { params.headers = {}; } params.headers["X-Scriptcat-GM-XHR-Request-Id"] = requestId.toString(); - await this.buildDNRRule(requestId, request.params[0]); + params.headers = await this.buildDNRRule(requestId, request.params[0]); + console.log(" params.headers", params.headers); let responseHeader = ""; // 等待response this.gmXhrHeadersReceived.addListener( @@ -157,12 +163,12 @@ export default class GMApi { } ); // 再发送到offscreen, 处理请求 - const offscreenCon = await connect(this.sender, "gmApi/xmlHttpRequest", request.params[0]); + const offscreenCon = await connect(this.send, "offscreen/gmApi/xmlHttpRequest", request.params[0]); offscreenCon.onMessage((msg: { action: string; data: any }) => { // 发送到content // 替换msg.data.responseHeaders msg.data.responseHeaders = responseHeader; - con.sendMessage(msg); + con.getConnect().sendMessage(msg); }); } @@ -171,6 +177,7 @@ export default class GMApi { chrome.webRequest.onBeforeSendHeaders.addListener( (details) => { if (details.tabId === -1) { + console.log(details); // 判断是否存在X-Scriptcat-GM-XHR-Request-Id // 讲请求id与chrome.webRequest的请求id关联 if (details.requestHeaders) { diff --git a/src/app/service/service_worker/runtime.ts b/src/app/service/service_worker/runtime.ts index 383f7a0..8185141 100644 --- a/src/app/service/service_worker/runtime.ts +++ b/src/app/service/service_worker/runtime.ts @@ -8,7 +8,7 @@ import { ScriptService } from "./script"; import { runScript, stopScript } from "../offscreen/client"; import { getRunAt } from "./utils"; import { randomString } from "@App/pkg/utils/utils"; -import { compileInjectScript, compileScriptCode } from "@App/runtime/content/utils"; +import { compileInjectScript } from "@App/runtime/content/utils"; import Cache from "@App/app/cache"; import { dealPatternMatches, UrlMatch } from "@App/pkg/utils/match"; @@ -113,7 +113,6 @@ export class RuntimeService { // 匹配当前页面的脚本 const matchScriptUuid = match.match(chromeSender.url!); - console.log("pageLoad", match.match(chromeSender.url!)); const scripts = await Promise.all( matchScriptUuid.map( (uuid) => @@ -249,7 +248,6 @@ export class RuntimeService { } const scriptRes = await this.script.buildScriptRunResource(script); - scriptRes.code = compileScriptCode(scriptRes); scriptRes.code = compileInjectScript(scriptRes); matches.push(...(script.metadata["include"] || [])); diff --git a/src/content.ts b/src/content.ts index 98e4e89..d09d009 100644 --- a/src/content.ts +++ b/src/content.ts @@ -4,6 +4,7 @@ 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"; +import { Server } from "@Packages/message/server"; // 建立与service_worker页面的连接 const send = new ExtensionMessageSend(); @@ -17,9 +18,9 @@ const loggerCore = new LoggerCore({ 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 server = new Server("content", msg); // 初始化运行环境 - const runtime = new ContentRuntime(send, msg); + const runtime = new ContentRuntime(server, send, msg); runtime.start(data.scripts); }); diff --git a/src/inject.ts b/src/inject.ts index d3418a1..46815b0 100644 --- a/src/inject.ts +++ b/src/inject.ts @@ -17,7 +17,6 @@ const server = new Server("inject", msg); server.on("pageLoad", (data: { scripts: ScriptRunResouce[] }) => { logger.logger().debug("inject start"); - console.log("inject", data); const runtime = new InjectRuntime(msg, data.scripts); runtime.start(); }); diff --git a/src/pkg/utils/match.ts b/src/pkg/utils/match.ts index e6ecf17..20664ad 100644 --- a/src/pkg/utils/match.ts +++ b/src/pkg/utils/match.ts @@ -149,6 +149,9 @@ export default class Match { } protected static getId(val: any): string { + if (typeof val === "string") { + return val; + } return (<{ uuid: string }>(val)).uuid; } diff --git a/src/runtime/content/content.ts b/src/runtime/content/content.ts index 05d2f3a..24d97ef 100644 --- a/src/runtime/content/content.ts +++ b/src/runtime/content/content.ts @@ -1,19 +1,23 @@ import { ScriptRunResouce } from "@App/app/repo/scripts"; import { Client } from "@Packages/message/client"; -import { Message, MessageSend } from "@Packages/message/server"; +import { forwardMessage, Message, MessageSend, Server } from "@Packages/message/server"; // content页的处理 export default class ContentRuntime { constructor( + private server: Server, private send: MessageSend, private msg: Message ) {} start(scripts: ScriptRunResouce[]) { - console.log("onMessage"); this.msg.onMessage((msg, sendResponse) => { console.log("content onMessage", msg); }); + this.msg.onConnect((msg, connect) => { + console.log(msg, connect); + }); + forwardMessage("serviceWorker", "runtime/gmApi", this.server, this.send); // 由content到background // 转发gmApi消息 // this.contentMessage.setHandler("gmApi", (action, data) => { diff --git a/src/runtime/content/exec_script.test.ts b/src/runtime/content/exec_script.test.ts index ac464be..1c0019e 100644 --- a/src/runtime/content/exec_script.test.ts +++ b/src/runtime/content/exec_script.test.ts @@ -2,7 +2,8 @@ import { ScriptRunResouce } from "@App/app/repo/scripts"; import ExecScript from "./exec_script"; import { compileScript, compileScriptCode } from "./utils"; import { ExtVersion } from "@App/app/const"; -import initTestEnv from "@Tests/utils"; +import { initTestEnv } from "@Tests/utils"; +import { describe, expect, it } from "vitest"; initTestEnv(); diff --git a/src/runtime/content/exec_script.ts b/src/runtime/content/exec_script.ts index 7b9e5f7..04a03ef 100644 --- a/src/runtime/content/exec_script.ts +++ b/src/runtime/content/exec_script.ts @@ -35,6 +35,7 @@ export default class ExecScript { constructor( scriptRes: ScriptRunResouce, + envPrefix: "content" | "offscreen", message: Message, code: string | ScriptFunc, thisContext?: { [key: string]: any } @@ -61,7 +62,7 @@ export default class ExecScript { this.proxyContent = global; } else { // 构建脚本GM上下文 - this.sandboxContent = createContext(scriptRes, this.GM_info, message); + this.sandboxContent = createContext(scriptRes, this.GM_info, envPrefix, message); this.proxyContent = proxyContext(global, this.sandboxContent, thisContext); } } @@ -76,7 +77,6 @@ export default class ExecScript { return this.scriptFunc.apply(this.proxyContent, [this.proxyContent, this.GM_info]); } - // TODO: 实现脚本的停止,资源释放 stop() { this.logger.debug("script stop"); return true; diff --git a/src/runtime/content/exec_warp.ts b/src/runtime/content/exec_warp.ts index b8cb22b..4ead277 100644 --- a/src/runtime/content/exec_warp.ts +++ b/src/runtime/content/exec_warp.ts @@ -63,7 +63,7 @@ export class BgExecScriptWarp extends ExecScript { }; // @ts-ignore thisContext.CATRetryError = CATRetryError; - super(scriptRes, message, thisContext); + super(scriptRes, "offscreen", message, scriptRes.code, thisContext); this.setTimeout = setTimeout; this.setInterval = setInterval; } diff --git a/src/runtime/content/gm_api.ts b/src/runtime/content/gm_api.ts index 2efacdf..76e686d 100644 --- a/src/runtime/content/gm_api.ts +++ b/src/runtime/content/gm_api.ts @@ -58,12 +58,15 @@ export default class GMApi { valueChangeListener = new Map(); - constructor(private message: Message) {} + constructor( + private prefix: string, + private message: Message + ) {} // 单次回调使用 public sendMessage(api: string, params: any[]) { return this.message.sendMessage({ - action: "runtime/gmApi", + action: this.prefix + "/runtime/gmApi", data: { uuid: this.scriptRes.uuid, api, @@ -75,7 +78,7 @@ export default class GMApi { // 长连接使用,connect只用于接受消息,不发送消息 public connect(api: string, params: any[]) { return this.message.connect({ - action: "runtime/gmApi", + action: this.prefix + "/runtime/gmApi", data: { uuid: this.scriptRes.uuid, api, diff --git a/src/runtime/content/inject.ts b/src/runtime/content/inject.ts index 3637eb4..08912eb 100644 --- a/src/runtime/content/inject.ts +++ b/src/runtime/content/inject.ts @@ -32,7 +32,7 @@ export class InjectRuntime { execScript(script: ScriptRunResouce, scriptFunc: ScriptFunc) { // @ts-ignore delete window[script.flag]; - const exec = new ExecScript(script, this.msg, scriptFunc); + const exec = new ExecScript(script, "content", this.msg, scriptFunc); this.execList.push(exec); // 注入css if (script.metadata["require-css"]) { diff --git a/src/runtime/content/utils.ts b/src/runtime/content/utils.ts index c350ea5..24db6cf 100644 --- a/src/runtime/content/utils.ts +++ b/src/runtime/content/utils.ts @@ -53,9 +53,10 @@ function setDepend(context: { [key: string]: any }, apiVal: ApiValue) { } // 构建沙盒上下文 -export function createContext(scriptRes: ScriptRunResouce, GMInfo: any, message: Message): GMApi { +export function createContext(scriptRes: ScriptRunResouce, GMInfo: any, envPrefix: string, message: Message): GMApi { // 按照GMApi构建 const context: { [key: string]: any } = { + prefix: envPrefix, message: message, scriptRes, valueChangeListener: new Map(),