Skip to content
49 changes: 49 additions & 0 deletions src/app/service/service_worker/dnr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* scheduler 用于 Service Worker 或 Event Page, Chrome 94+, Firefox 142+
*/
const scheduler_ =
typeof scheduler !== "undefined" &&
typeof scheduler?.postTask === "function" &&
typeof scheduler?.yield === "function"
? scheduler
: null;

// 用于扩充初始化时新增 SessionRules. FireFox 需要等一等才加,否则会失效。
export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[]) => {
await scheduler_?.yield?.();
try {
await chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: [...rules.map((rule) => rule.id)],
addRules: rules,
});
return true;
} catch (e) {
console.error("chrome.declarativeNetRequest.updateSessionRules:", e);
return e;
}
};

export const sessionRuleDynamicAdd = async (rule: chrome.declarativeNetRequest.Rule): Promise<any> => {
try {
await chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: [rule.id],
addRules: [rule],
});
return true;
} catch (e) {
console.error("chrome.declarativeNetRequest.updateSessionRules:", e);
return e;
}
};

export const sessionRuleDynamicRemove = async (ruleId: number): Promise<any> => {
try {
await chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: [ruleId],
});
return true;
} catch (e) {
console.error("chrome.declarativeNetRequest.updateSessionRules:", e);
return e;
}
};
56 changes: 11 additions & 45 deletions src/app/service/service_worker/gm_api/gm_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { BgGMXhr } from "@App/pkg/utils/xhr/bg_gm_xhr";
import { mightPrepareSetClipboard, setClipboard } from "../clipboard";
import { nativePageWindowOpen } from "../../offscreen/gm_api";
import { nextSessionRuleId, removeSessionRuleIdEntry } from "./dnr_id_controller";
import { addSessionRules, sessionRuleDynamicAdd, sessionRuleDynamicRemove } from "../dnr";

let generatedUniqueMarkerIDs = "";
let generatedUniqueMarkerIDWhen = "";
Expand Down Expand Up @@ -87,20 +88,11 @@ const headersSettled = (markerID: string) => {
headerModifierMap.delete(markerID);
}
if (ruleID) {
chrome.declarativeNetRequest.updateSessionRules(
{
removeRuleIds: [ruleID],
},
() => {
const lastError = chrome.runtime.lastError;
if (lastError) {
// removeRuleIds 失败: 浏览器里仍保留该规则,本地不释放 ruleID 避免复用
console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError);
return;
}
removeSessionRuleIdEntry(ruleID);
}
);
sessionRuleDynamicRemove(ruleID).then((removeResult) => {
// removeRuleIds 失败: 浏览器里仍保留该规则,本地不释放 ruleID 避免复用
if (removeResult !== true) return;
removeSessionRuleIdEntry(ruleID);
});
}
};

Expand Down Expand Up @@ -749,16 +741,12 @@ export default class GMApi {
},
} as chrome.declarativeNetRequest.Rule;
headerModifierMap.set(markerID, { rule, redirectNotManual });
try {
await chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: [ruleId],
addRules: [rule],
});
} catch (e) {
const addResult = await sessionRuleDynamicAdd(rule);
if (addResult !== true) {
// addRules 失败: 回滚本地 headerModifierMap 关联并释放 ruleId,避免永久占位导致限额锁死
headerModifierMap.delete(markerID);
removeSessionRuleIdEntry(ruleId);
throw e;
throw addResult;
}
}
return true;
Expand Down Expand Up @@ -1648,18 +1636,7 @@ export default class GMApi {
},
};
headerModifierMap.set(markerID, { rule: newRule, redirectNotManual });
chrome.declarativeNetRequest.updateSessionRules(
{
removeRuleIds: [rule.id],
addRules: [newRule],
},
() => {
const lastError = chrome.runtime.lastError;
if (lastError) {
console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError);
}
}
);
sessionRuleDynamicAdd(newRule);
return;
}
}
Expand Down Expand Up @@ -1723,18 +1700,7 @@ export default class GMApi {
tabIds: [chrome.tabs.TAB_ID_NONE], // 只限于后台 service_worker / offscreen
},
} as chrome.declarativeNetRequest.Rule;
chrome.declarativeNetRequest.updateSessionRules(
{
removeRuleIds: [ruleId],
addRules: [rule],
},
() => {
const lastError = chrome.runtime.lastError;
if (lastError) {
console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError);
}
}
);
addSessionRules([rule]);
}

start() {
Expand Down
16 changes: 2 additions & 14 deletions src/app/service/service_worker/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { getSimilarityScore, ScriptUpdateCheck } from "./script_update_check";
import { LocalStorageDAO } from "@App/app/repo/localStorage";
import { CompiledResourceDAO } from "@App/app/repo/resource";
import { initRegularUpdateCheck } from "./regular_updatecheck";
import { addSessionRules } from "./dnr";

export type TCheckScriptUpdateOption = Partial<
{ checkType: "user"; noUpdateCheck?: number } | ({ checkType: "system" } & Record<string, any>)
Expand Down Expand Up @@ -299,20 +300,7 @@ export class ScriptService {
}
}
);
chrome.declarativeNetRequest.updateSessionRules(
{
removeRuleIds: [...rules.map((rule) => rule.id)],
addRules: rules,
},
() => {
if (chrome.runtime.lastError) {
console.error(
"chrome.runtime.lastError in chrome.declarativeNetRequest.updateSessionRules:",
chrome.runtime.lastError
);
}
}
);
addSessionRules(rules);
}

public async openInstallPageByUrl(
Expand Down
14 changes: 14 additions & 0 deletions src/types/main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ declare module "@App/app/types.d.ts";
type Override<T, U> = Omit<T, keyof U> & U;
type ValueOf<T> = T[keyof T];
type ReactStateSetter<T> = (value: T | ((prev: T) => T)) => void;
type ResolveFn<T = void> = (val: T) => void;

interface SchedulerPostTaskOptions {
delay?: number;
priority?: "user-blocking" | "user-visible" | "background";
signal?: AbortSignal;
}

interface Scheduler {
postTask<T>(callback: () => T | Promise<T>, options?: SchedulerPostTaskOptions): Promise<T>;
yield(): Promise<void>;
}

declare let scheduler: Scheduler | undefined;

declare const sandbox: Window;

Expand Down
Loading