refactor(background): extract main world injection script

Move the 62-line inline main world injection function from background.ts
to a dedicated utils/rightClickInjection.ts file.

This separates the RightClickRestorer's DOM patching logic from the
service worker's message routing concerns.

- background.ts: -62 lines, now delegates to imported function
- utils/rightClickInjection.ts: new file with mainWorldInjectionScript()

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
雨霖铃
2026-05-29 20:20:11 +08:00
parent e97f4cae9a
commit c9fe27a26b
2 changed files with 73 additions and 62 deletions
+71
View File
@@ -0,0 +1,71 @@
/**
* 右键解锁功能的主环境注入脚本
*
* 由于 content script 运行在 Isolated World,无法直接修改网页主环境的
* Event.prototype.preventDefault 等原生方法。需要通过 background
* 的 scripting.executeScript({ world: 'MAIN' }) 注入此脚本。
*/
/**
* 在网页主环境中执行的注入函数
* 注意:此函数会被序列化后通过 executeScript 注入,不能引用外部变量
*/
export function mainWorldInjectionScript(): void {
'use strict';
const w = window as unknown as Record<string, unknown>;
if (w.__testingToolsRightClickPatched) return;
w.__testingToolsRightClickPatched = true;
const PROTECTED = ['contextmenu', 'copy', 'paste', 'cut', 'selectstart'];
const _origPreventDefault = MouseEvent.prototype.preventDefault;
Object.defineProperty(MouseEvent.prototype, 'preventDefault', {
value: function (this: MouseEvent) {
const t = this.type;
if (PROTECTED.includes(t) || (t === 'mousedown' && this.button === 2)) {
return;
}
return _origPreventDefault.call(this);
},
writable: true,
configurable: true,
});
const _origStopPropagation = Event.prototype.stopPropagation;
Object.defineProperty(Event.prototype, 'stopPropagation', {
value: function (this: Event) {
if (PROTECTED.includes(this.type)) return;
return _origStopPropagation.call(this);
},
writable: true,
configurable: true,
});
const _origStopImmediatePropagation = Event.prototype.stopImmediatePropagation;
Object.defineProperty(Event.prototype, 'stopImmediatePropagation', {
value: function (this: Event) {
if (PROTECTED.includes(this.type)) return;
return _origStopImmediatePropagation.call(this);
},
writable: true,
configurable: true,
});
let _docOnContextMenu: unknown = null;
Object.defineProperty(document, 'oncontextmenu', {
get() {
return _docOnContextMenu;
},
set(fn: unknown) {
if (typeof fn === 'function') {
_docOnContextMenu = function (this: GlobalEventHandlers, e: MouseEvent) {
const r = (fn as (this: GlobalEventHandlers, ev: MouseEvent) => unknown).call(this, e);
return r === false ? true : r;
};
} else {
_docOnContextMenu = fn;
}
},
configurable: true,
});
}