-
Notifications
You must be signed in to change notification settings - Fork 332
Expand file tree
/
Copy pathcommon.ts
More file actions
95 lines (86 loc) · 3.74 KB
/
common.ts
File metadata and controls
95 lines (86 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { type TExtensionEnv } from "@App/app/service/extension/extension_env";
import { randomMessageFlag } from "@App/pkg/utils/utils";
// 避免页面载入后改动全域物件导致消息传递失败
export const MouseEventClone = MouseEvent;
export const CustomEventClone = CustomEvent;
const performanceClone = (process.env.VI_TESTING === "true" ? new EventTarget() : performance) as Performance;
// 避免页面载入后改动 EventTarget.prototype 的方法导致消息传递失败
export const pageDispatchEvent = performanceClone.dispatchEvent.bind(performanceClone);
export const pageAddEventListener = performanceClone.addEventListener.bind(performanceClone);
export const pageRemoveEventListener = performanceClone.removeEventListener.bind(performanceClone);
const detailClone = typeof cloneInto === "function" ? cloneInto : null;
export const pageDispatchCustomEvent = <T = any>(eventType: string, detail: T) => {
if (detailClone && detail) detail = <T>detailClone(detail, performanceClone);
const ev = new CustomEventClone(eventType, {
detail,
cancelable: true,
});
return pageDispatchEvent(ev);
};
// flag协商
export function negotiateEventFlag(
messageFlag: string,
extensionEnv: TExtensionEnv,
readyCount: number,
onInit: (eventFlag: string) => void
): void {
const eventFlag = randomMessageFlag();
onInit(eventFlag);
// 监听 inject/content 发来的请求 eventFlag 的消息
let ready = 0;
const fnEventFlagRequestHandler: EventListener = (ev: Event) => {
if (!(ev instanceof CustomEvent)) return;
switch (ev.detail?.action) {
case "receivedEventFlag":
// 对方已收到 eventFlag
ready += 1;
if (ready >= readyCount) {
// 已收到两个环境的请求,移除监听
pageRemoveEventListener(messageFlag, fnEventFlagRequestHandler);
}
break;
case "requestEventFlag":
// 广播通信 flag 给 inject/content
pageDispatchCustomEvent(messageFlag, { action: "broadcastEventFlag", eventFlag: eventFlag, extensionEnv });
break;
}
};
// 设置事件,然后广播通信 flag 给 inject/content
pageAddEventListener(messageFlag, fnEventFlagRequestHandler);
pageDispatchCustomEvent(messageFlag, { action: "broadcastEventFlag", eventFlag: eventFlag, extensionEnv });
}
// 获取协商后的 eventFlag
export function getEventFlag(
messageFlag: string,
onReady: (eventFlag: string, extensionEnv: TExtensionEnv | undefined) => void
) {
let eventFlag = "";
let extensionEnv: TExtensionEnv | undefined = undefined;
const fnEventFlagListener: EventListener = (ev: Event) => {
if (!(ev instanceof CustomEvent)) return;
if (ev.detail?.action != "broadcastEventFlag") return;
eventFlag = ev.detail.eventFlag;
extensionEnv = ev.detail.extensionEnv;
pageRemoveEventListener(messageFlag, fnEventFlagListener);
// 告知对方已收到 eventFlag
pageDispatchCustomEvent(messageFlag, { action: "receivedEventFlag" });
onReady(eventFlag, extensionEnv);
};
// 设置事件,然后对 scripting 请求 flag
pageAddEventListener(messageFlag, fnEventFlagListener);
pageDispatchCustomEvent(messageFlag, { action: "requestEventFlag" });
}
export const createMouseEvent =
process.env.VI_TESTING === "true"
? (type: string, eventInitDict?: MouseEventInit | undefined): MouseEvent => {
const ev = new MouseEventClone(type, eventInitDict);
eventInitDict = eventInitDict || {};
for (const [key, value] of Object.entries(eventInitDict)) {
//@ts-ignore
if (ev[key] === undefined) ev[key] = value;
}
return ev;
}
: (type: string, eventInitDict?: MouseEventInit | undefined): MouseEvent => {
return new MouseEventClone(type, eventInitDict);
};