修复一些资源加载问题

This commit is contained in:
王一之 2025-04-14 15:02:01 +08:00
parent d697928fb0
commit 1965137191
11 changed files with 163 additions and 48 deletions

View File

@ -9,13 +9,17 @@ export default class DBWriter implements Writer {
this.dao = dao; this.dao = dao;
} }
write(level: LogLevel, message: string, label: LogLabel): void { async write(level: LogLevel, message: string, label: LogLabel): Promise<void> {
this.dao.save({ try {
await this.dao.save({
id: 0, id: 0,
level, level,
message, message,
label, label,
createtime: new Date().getTime(), createtime: new Date().getTime(),
}); });
} catch (e) {
console.error("DBWriter error", e);
}
} }
} }

View File

@ -32,28 +32,27 @@ export default class Logger {
} }
log(level: LogLevel, message: string, ...label: LogLabel[]) { log(level: LogLevel, message: string, ...label: LogLabel[]) {
const newLabel = buildLabel(this.label, label);
if (levelNumber[level] >= levelNumber[this.core.level]) { if (levelNumber[level] >= levelNumber[this.core.level]) {
this.core.writer.write(level, message, buildLabel(this.label, label)); this.core.writer.write(level, message, newLabel);
} }
if (this.core.debug !== "none" && levelNumber[level] >= levelNumber[this.core.debug]) { if (this.core.debug !== "none" && levelNumber[level] >= levelNumber[this.core.debug]) {
if (typeof message === "object") { if (typeof message === "object") {
message = JSON.stringify(message); message = JSON.stringify(message);
} }
const msg = `${dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss")} [${level}] msg=${message} label=${JSON.stringify( const msg = `${dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss")} [${level}] ${message}`;
buildLabel(this.label, label)
)}`;
switch (level) { switch (level) {
case "error": case "error":
console.error(msg); console.error(msg, newLabel);
break; break;
case "warn": case "warn":
console.warn(msg); console.warn(msg, newLabel);
break; break;
case "trace": case "trace":
console.info(msg); console.info(msg, newLabel);
break; break;
default: default:
console.info(msg); console.info(msg, newLabel);
break; break;
} }
} }

View File

@ -79,6 +79,11 @@ export default class ContentRuntime {
const nodeId = (this.msg as CustomEventMessage).sendRelatedTarget(el); const nodeId = (this.msg as CustomEventMessage).sendRelatedTarget(el);
return nodeId; return nodeId;
} }
case "GM_log":
// 拦截GM_log打印到控制台
// 由于某些页面会处理掉console.log所以丢到这里来打印
console.log(...data.params);
break;
} }
return false; return false;
} }

View File

@ -46,7 +46,7 @@ export default class ExecScript {
this.scriptRes = scriptRes; this.scriptRes = scriptRes;
this.logger = LoggerCore.getInstance().logger({ this.logger = LoggerCore.getInstance().logger({
component: "exec", component: "exec",
script: this.scriptRes.uuid, uuid: this.scriptRes.uuid,
name: this.scriptRes.name, name: this.scriptRes.name,
}); });
this.GM_info = GMApi.GM_info(this.scriptRes); this.GM_info = GMApi.GM_info(this.scriptRes);

View File

@ -198,7 +198,6 @@ export class PopupService {
scriptMenu.push(script); scriptMenu.push(script);
} }
}); });
console.log("popup脚本菜单", runScript);
// 后台脚本只显示开启或者运行中的脚本 // 后台脚本只显示开启或者运行中的脚本
return { scriptList: scriptMenu, backScriptList: await this.getScriptMenu(-1) }; return { scriptList: scriptMenu, backScriptList: await this.getScriptMenu(-1) };
} }

View File

@ -193,6 +193,19 @@ export class ResourceService {
(u.hash.sha512 && u.hash.sha512 !== resource.hash.sha512) (u.hash.sha512 && u.hash.sha512 !== resource.hash.sha512)
) { ) {
resource.content = `console.warn("ScriptCat: couldn't load resource from URL ${url} due to a SRI error ");`; resource.content = `console.warn("ScriptCat: couldn't load resource from URL ${url} due to a SRI error ");`;
// 尝试重新加载
this.loadByUrl(u.url, resource.type).then((reloadRes) => {
this.logger.info("reload resource success", {
url: u.url,
hash: {
expected: u.hash,
old: resource.hash,
new: reloadRes.hash,
},
});
reloadRes.updatetime = new Date().getTime();
this.resourceDAO.save(reloadRes);
});
} }
} }
return Promise.resolve(resource); return Promise.resolve(resource);
@ -214,12 +227,13 @@ export class ResourceService {
sha512: "", sha512: "",
}); });
} else { } else {
const wordArray = crypto.lib.WordArray.create(<ArrayBuffer>reader.result);
resolve({ resolve({
md5: crypto.MD5(<string>reader.result).toString(), md5: crypto.MD5(wordArray).toString(),
sha1: crypto.SHA1(<string>reader.result).toString(), sha1: crypto.SHA1(wordArray).toString(),
sha256: crypto.SHA256(<string>reader.result).toString(), sha256: crypto.SHA256(wordArray).toString(),
sha384: crypto.SHA384(<string>reader.result).toString(), sha384: crypto.SHA384(wordArray).toString(),
sha512: crypto.SHA512(<string>reader.result).toString(), sha512: crypto.SHA512(wordArray).toString(),
}); });
} }
}; };

View File

@ -22,6 +22,8 @@ import { ExtensionContentMessageSend } from "@Packages/message/extension_message
import { sendMessage } from "@Packages/message/client"; import { sendMessage } from "@Packages/message/client";
import { compileInjectScript } from "../content/utils"; import { compileInjectScript } from "../content/utils";
import { PopupService } from "./popup"; import { PopupService } from "./popup";
import Logger from "@App/app/logger/logger";
import LoggerCore from "@App/app/logger/core";
// 为了优化性能存储到缓存时删除了code与value // 为了优化性能存储到缓存时删除了code与value
export interface ScriptMatchInfo extends ScriptRunResouce { export interface ScriptMatchInfo extends ScriptRunResouce {
@ -389,22 +391,27 @@ export class RuntimeService {
world: "MAIN", world: "MAIN",
}; };
// 排除由loadPage时决定, 不使用userScript的excludeMatches处理
if (script.metadata["exclude"]) { if (script.metadata["exclude"]) {
const excludeMatches = script.metadata["exclude"]; const excludeMatches = script.metadata["exclude"];
const result = dealPatternMatches(excludeMatches); const result = dealPatternMatches(excludeMatches, {
exclude: true,
});
registerScript.excludeMatches = result.patternResult; // registerScript.excludeMatches = result.patternResult;
scriptMatchInfo.excludeMatches = result.result; scriptMatchInfo.excludeMatches = result.result;
} }
// 自定义排除 // 自定义排除
if (script.selfMetadata && script.selfMetadata.exclude) { if (script.selfMetadata && script.selfMetadata.exclude) {
const excludeMatches = script.selfMetadata.exclude; const excludeMatches = script.selfMetadata.exclude;
const result = dealPatternMatches(excludeMatches); const result = dealPatternMatches(excludeMatches, {
exclude: true,
});
if (!registerScript.excludeMatches) { if (!registerScript.excludeMatches) {
registerScript.excludeMatches = []; registerScript.excludeMatches = [];
} }
registerScript.excludeMatches.push(...result.patternResult); // registerScript.excludeMatches.push(...result.patternResult);
scriptMatchInfo.customizeExcludeMatches = result.result; scriptMatchInfo.customizeExcludeMatches = result.result;
} }
@ -419,10 +426,22 @@ export class RuntimeService {
if (script.metadata["run-at"]) { if (script.metadata["run-at"]) {
registerScript.runAt = getRunAt(script.metadata["run-at"]); registerScript.runAt = getRunAt(script.metadata["run-at"]);
} }
console.log("registerScript", script.name, registerScript, scriptMatchInfo);
if (await Cache.getInstance().get("registryScript:" + script.uuid)) { if (await Cache.getInstance().get("registryScript:" + script.uuid)) {
await chrome.userScripts.update([registerScript]); await chrome.userScripts.update([registerScript]);
} else { } else {
await chrome.userScripts.register([registerScript]); await chrome.userScripts.register([registerScript], () => {
if (chrome.runtime.lastError) {
LoggerCore.logger().error("registerScript error", {
error: chrome.runtime.lastError,
name: script.name,
registerMatch: {
matches: registerScript.matches,
excludeMatches: registerScript.excludeMatches,
},
});
}
});
} }
await Cache.getInstance().set("registryScript:" + script.uuid, true); await Cache.getInstance().set("registryScript:" + script.uuid, true);
} }

View File

@ -4,9 +4,10 @@ import DBWriter from "./app/logger/db_writer";
import { LoggerDAO } from "./app/repo/logger"; import { LoggerDAO } from "./app/repo/logger";
import { OffscreenManager } from "./app/service/offscreen"; import { OffscreenManager } from "./app/service/offscreen";
// 初始化数据库
migrate();
function main() { function main() {
// 初始化数据库
migrate();
// 初始化日志组件 // 初始化日志组件
const loggerCore = new LoggerCore({ const loggerCore = new LoggerCore({
writer: new DBWriter(new LoggerDAO()), writer: new DBWriter(new LoggerDAO()),

View File

@ -43,10 +43,10 @@ describe("UrlMatch-google-error", () => {
url.add("https://*foo/bar", "ok1"); url.add("https://*foo/bar", "ok1");
}).toThrow(Error); }).toThrow(Error);
}); });
// 从v0.17.0开始允许这种
it("error-2", () => { it("error-2", () => {
expect(() => {
url.add("https://foo.*.bar/baz", "ok1"); url.add("https://foo.*.bar/baz", "ok1");
}).toThrow(Error); expect(url.match("https://foo.api.bar/baz")).toEqual(["ok1"]);
}); });
it("error-3", () => { it("error-3", () => {
expect(() => { expect(() => {
@ -70,6 +70,13 @@ describe("UrlMatch-search", () => {
expect(url.match("https://bbs.tampermonkey.net.cn/")).toEqual(["ok2"]); expect(url.match("https://bbs.tampermonkey.net.cn/")).toEqual(["ok2"]);
expect(url.match("https://bbs.tampermonkey.net.cn/foo/bar.html")).toEqual([]); expect(url.match("https://bbs.tampermonkey.net.cn/foo/bar.html")).toEqual([]);
}); });
it("http://api.*.example.com/*", () => {
const url = new UrlMatch<string>();
url.add("http://api.*.example.com/*", "ok1");
expect(url.match("http://api.foo.example.com/")).toEqual(["ok1"]);
expect(url.match("http://api.bar.example.com/")).toEqual(["ok1"]);
expect(url.match("http://api.example.com/")).toEqual([]);
});
}); });
describe("UrlMatch-port1", () => { describe("UrlMatch-port1", () => {
@ -106,13 +113,47 @@ describe("UrlMatch-port2", () => {
// https://developer.chrome.com/docs/extensions/mv3/match_patterns/ // https://developer.chrome.com/docs/extensions/mv3/match_patterns/
describe("dealPatternMatches", () => { describe("dealPatternMatches", () => {
it("https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns?hl=zh-cn#examples", () => { it("https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns?hl=zh-cn#examples", () => {
const matches = dealPatternMatches(["https://*/*", "http://127.0.0.1/*", "http://127.0.0.1/"]); const matches = dealPatternMatches([
expect(matches.patternResult).toEqual(["https://*/*", "http://127.0.0.1/*", "http://127.0.0.1/"]); "https://*/*",
"http://127.0.0.1/*",
"http://127.0.0.1/",
"https://*.example.com/*",
]);
expect(matches.patternResult).toEqual([
"https://*/*",
"http://127.0.0.1/*",
"http://127.0.0.1/",
"https://*.example.com/*",
]);
}); });
// 处理一些特殊情况 // 处理一些特殊情况
it("*://link.17173.com*", () => { it("特殊情况", () => {
const matches = dealPatternMatches(["*://link.17173.com*"]); const matches = dealPatternMatches([
expect(matches.patternResult).toEqual(["*://link.17173.com/*"]); "*://www.example.com*",
"*://api.*.example.com/*",
"*://api.*.*.example.com/*",
"*://*example.com/*",
]);
expect(matches.patternResult).toEqual([
"*://www.example.com/*",
"*://*.example.com/*",
"*://*.example.com/*",
"*://example.com/*",
]);
expect(matches.result).toEqual([
"*://www.example.com*",
"*://api.*.example.com/*",
"*://api.*.*.example.com/*",
"*://*example.com/*",
]);
});
it("特殊情况-exclude", () => {
const matches = dealPatternMatches(["*://api.*.example.com/*", "*://api.*.*.example.com/*"], {
exclude: true,
});
console.log(matches);
expect(matches.patternResult).toEqual(["*://example.com/*", "*://example.com/*"]);
expect(matches.result).toEqual(["*://api.*.example.com/*", "*://api.*.*.example.com/*"]);
}); });
}); });
@ -146,11 +187,19 @@ describe("parsePatternMatchesURL", () => {
path: "*", path: "*",
}); });
}); });
it("*://link.17173.com*", () => { it("*://www.example.com*", () => {
const matches = parsePatternMatchesURL("*://link.17173.com*"); const matches = parsePatternMatchesURL("*://www.example.com*");
expect(matches).toEqual({ expect(matches).toEqual({
scheme: "*", scheme: "*",
host: "link.17173.com", host: "www.example.com",
path: "*",
});
});
it("*://api.*.example.com/*", () => {
const matches = parsePatternMatchesURL("*://api.*.example.com/*");
expect(matches).toEqual({
scheme: "*",
host: "*.example.com",
path: "*", path: "*",
}); });
}); });

View File

@ -69,8 +69,6 @@ export default class Match<T> {
if (!u.host.endsWith(":*")) { if (!u.host.endsWith(":*")) {
u.host = u.host.substring(0, u.host.length - 1); u.host = u.host.substring(0, u.host.length - 1);
} }
} else if (pos !== -1 && pos !== 0) {
return "";
} }
u.host = u.host.replace(/\*/g, "[^/]*?"); u.host = u.host.replace(/\*/g, "[^/]*?");
// 处理 *.开头 // 处理 *.开头
@ -225,7 +223,12 @@ export interface PatternMatchesUrl {
} }
// 解析URL, 根据https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns?hl=zh-cn进行处理 // 解析URL, 根据https://developer.chrome.com/docs/extensions/develop/concepts/match-patterns?hl=zh-cn进行处理
export function parsePatternMatchesURL(url: string): PatternMatchesUrl | undefined { export function parsePatternMatchesURL(
url: string,
options?: {
exclude?: boolean;
}
): PatternMatchesUrl | undefined {
let result: PatternMatchesUrl | undefined; let result: PatternMatchesUrl | undefined;
const match = /^(.+?):\/\/(.*?)(\/(.*?)(\?.*?|)|)$/.exec(url); const match = /^(.+?):\/\/(.*?)(\/(.*?)(\?.*?|)|)$/.exec(url);
if (match) { if (match) {
@ -260,17 +263,38 @@ export function parsePatternMatchesURL(url: string): PatternMatchesUrl | undefin
if (result.host.endsWith("*")) { if (result.host.endsWith("*")) {
result.host = result.host.slice(0, -1); result.host = result.host.slice(0, -1);
} }
// 处理 www.*.example.com 的情况为 *.example.com
const pos = result.host.lastIndexOf("*");
if (pos > 0 && pos < result.host.length - 1) {
if (options && options.exclude) {
// 如果是exclude, 按最小匹配处理
// 包括*也去掉
result.host = result.host.substring(pos + 1);
if (result.host.startsWith(".")) {
result.host = result.host.substring(1);
}
} else {
// 如果不是exclude
// 将*前面的全部去掉
result.host = result.host.substring(pos);
}
}
} }
} }
return result; return result;
} }
// 处理油猴的match和include为chrome的pattern-matche // 处理油猴的match和include为chrome的pattern-matche
export function dealPatternMatches(matches: string[]) { export function dealPatternMatches(
matches: string[],
options?: {
exclude?: boolean;
}
) {
const patternResult: string[] = []; const patternResult: string[] = [];
const result: string[] = []; const result: string[] = [];
for (let i = 0; i < matches.length; i++) { for (let i = 0; i < matches.length; i++) {
const url = parsePatternMatchesURL(matches[i]); const url = parsePatternMatchesURL(matches[i], options);
if (url) { if (url) {
patternResult.push(`${url.scheme}://${url.host}/${url.path}`); patternResult.push(`${url.scheme}://${url.host}/${url.path}`);
result.push(matches[i]); result.push(matches[i]);

View File

@ -8,6 +8,9 @@ import { Server } from "@Packages/message/server";
import { MessageQueue } from "@Packages/message/message_queue"; import { MessageQueue } from "@Packages/message/message_queue";
import { ServiceWorkerMessageSend } from "@Packages/message/window_message"; import { ServiceWorkerMessageSend } from "@Packages/message/window_message";
// 初始化数据库
migrate();
const OFFSCREEN_DOCUMENT_PATH = "src/offscreen.html"; const OFFSCREEN_DOCUMENT_PATH = "src/offscreen.html";
let creating: Promise<void> | null; let creating: Promise<void> | null;
@ -46,8 +49,6 @@ async function setupOffscreenDocument() {
} }
async function main() { async function main() {
// 初始化数据库
migrate();
// 初始化日志组件 // 初始化日志组件
const loggerCore = new LoggerCore({ const loggerCore = new LoggerCore({
writer: new DBWriter(new LoggerDAO()), writer: new DBWriter(new LoggerDAO()),