inject的GM API调用
Some checks failed
build / Build (push) Failing after 7s
test / Run tests (push) Failing after 8s
Some checks failed
build / Build (push) Failing after 7s
test / Run tests (push) Failing after 8s
This commit is contained in:
@ -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);
|
||||
|
@ -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<any>;
|
||||
export type Api = (request: Request, con: GetSender) => Promise<any>;
|
||||
|
||||
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) {
|
||||
|
@ -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"] || []));
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -149,6 +149,9 @@ export default class Match<T> {
|
||||
}
|
||||
|
||||
protected static getId(val: any): string {
|
||||
if (typeof val === "string") {
|
||||
return val;
|
||||
}
|
||||
return (<{ uuid: string }>(<unknown>val)).uuid;
|
||||
}
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -58,12 +58,15 @@ export default class GMApi {
|
||||
|
||||
valueChangeListener = new Map<number, { name: string; listener: GMTypes.ValueChangeListener }>();
|
||||
|
||||
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,
|
||||
|
@ -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"]) {
|
||||
|
@ -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<number, { name: string; listener: GMTypes.ValueChangeListener }>(),
|
||||
|
Reference in New Issue
Block a user