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:
@@ -3,6 +3,7 @@ import { browser } from 'wxt/browser';
|
|||||||
import { MessageAction, onMessage, sendMessage } from '@/utils/messages';
|
import { MessageAction, onMessage, sendMessage } from '@/utils/messages';
|
||||||
import { createAllContextMenus, parseContextMenuClick } from '@/utils/contextMenu';
|
import { createAllContextMenus, parseContextMenuClick } from '@/utils/contextMenu';
|
||||||
import { saveContextMenuData } from '@/utils/useContextMenuData';
|
import { saveContextMenuData } from '@/utils/useContextMenuData';
|
||||||
|
import { mainWorldInjectionScript } from '@/utils/rightClickInjection';
|
||||||
|
|
||||||
export default defineBackground(() => {
|
export default defineBackground(() => {
|
||||||
// 1. 扩展初次安装或更新时,注册右键上下文菜单
|
// 1. 扩展初次安装或更新时,注册右键上下文菜单
|
||||||
@@ -71,68 +72,7 @@ export default defineBackground(() => {
|
|||||||
try {
|
try {
|
||||||
await browser.scripting.executeScript({
|
await browser.scripting.executeScript({
|
||||||
target: { tabId },
|
target: { tabId },
|
||||||
func: () => {
|
func: mainWorldInjectionScript,
|
||||||
'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,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
world: 'MAIN',
|
world: 'MAIN',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user