Skip to content

Commit 24e58c8

Browse files
committed
新增 extensionEnv 处理 isIncognito (early-start & bgScript), userAgent (bgScript) 及 run-in (bgScript)
1 parent f8e76e6 commit 24e58c8

13 files changed

Lines changed: 111 additions & 37 deletions

File tree

packages/message/common.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { extensionEnv, type TExtensionEnv } from "@App/app/service/extension/extension_env";
12
import { randomMessageFlag } from "@App/pkg/utils/utils";
23

34
// 避免页面载入后改动全域物件导致消息传递失败
@@ -40,7 +41,7 @@ export function negotiateEventFlag(messageFlag: string, readyCount: number, onIn
4041
break;
4142
case "requestEventFlag":
4243
// 广播通信 flag 给 inject/content
43-
pageDispatchCustomEvent(messageFlag, { action: "broadcastEventFlag", eventFlag: eventFlag });
44+
pageDispatchCustomEvent(messageFlag, { action: "broadcastEventFlag", eventFlag: eventFlag, extensionEnv });
4445
break;
4546
}
4647
};
@@ -51,16 +52,21 @@ export function negotiateEventFlag(messageFlag: string, readyCount: number, onIn
5152
}
5253

5354
// 获取协商后的 eventFlag
54-
export function getEventFlag(messageFlag: string, onReady: (eventFlag: string) => void) {
55+
export function getEventFlag(
56+
messageFlag: string,
57+
onReady: (eventFlag: string, extensionEnv: TExtensionEnv | undefined) => void
58+
) {
5559
let eventFlag = "";
60+
let extensionEnv = null;
5661
const fnEventFlagListener: EventListener = (ev: Event) => {
5762
if (!(ev instanceof CustomEvent)) return;
5863
if (ev.detail?.action != "broadcastEventFlag") return;
5964
eventFlag = ev.detail.eventFlag;
65+
extensionEnv = ev.detail.extensionEnv;
6066
pageRemoveEventListener(messageFlag, fnEventFlagListener);
6167
// 告知对方已收到 eventFlag
6268
pageDispatchCustomEvent(messageFlag, { action: "receivedEventFlag" });
63-
onReady(eventFlag);
69+
onReady(eventFlag, extensionEnv);
6470
};
6571

6672
// 设置事件,然后对 scripting 请求 flag

src/app/service/content/exec_warp.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ExecScript from "./exec_script";
22
import type { Message } from "@Packages/message/types";
33
import type { ScriptLoadInfo } from "../service_worker/types";
44
import type { GMInfoEnv } from "./types";
5+
import { type TExtensionEnv } from "../extension/extension_env";
56

67
export class CATRetryError {
78
msg: string;
@@ -23,7 +24,7 @@ export class BgExecScriptWarp extends ExecScript {
2324

2425
setInterval: Map<number, boolean>;
2526

26-
constructor(scriptRes: ScriptLoadInfo, message: Message) {
27+
constructor(scriptRes: ScriptLoadInfo, message: Message, extensionEnv: TExtensionEnv | undefined) {
2728
const thisContext: { [key: string]: any } = {};
2829
const setTimeout = new Map<number, any>();
2930
const setInterval = new Map<number, any>();
@@ -73,6 +74,9 @@ export class BgExecScriptWarp extends ExecScript {
7374
},
7475
isIncognito: false,
7576
};
77+
const { inIncognitoContext, userAgentData } = extensionEnv || {};
78+
if (typeof inIncognitoContext === "boolean") envInfo.isIncognito = inIncognitoContext;
79+
if (userAgentData) envInfo.userAgentData = userAgentData;
7680
super(scriptRes, {
7781
envPrefix: "offscreen",
7882
message: message,

src/app/service/content/script_executor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ export type ExecScriptEntry = {
1717
scriptFunc: any;
1818
};
1919

20-
export const initEnvInfo = {
20+
export const initEnvInfo: GMInfoEnv = {
2121
/** userAgentData - 从全局变量获取 */
2222
userAgentData: typeof UserAgentData === "object" ? UserAgentData : {},
2323
/** sandboxMode - 预留字段,当前固定为 raw */
2424
sandboxMode: "raw",
25-
/** isIncognito - inject/content 环境下无法判断,固定为 false */
25+
/** isIncognito - inject/content 环境下透過 scripting 环境判断 */
2626
/** 使用者可透过 「 await navigator.storage.persisted() 」来判断,但ScriptCat不会主动执行此代码来判断 */
2727
isIncognito: false,
2828
} satisfies GMInfoEnv;

src/app/service/content/script_runtime.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import type { GMInfoEnv, ValueUpdateDataEncoded } from "./types";
77
import type { ScriptEnvTag } from "@Packages/message/consts";
88
import { onInjectPageLoaded } from "./external";
99
import type { CustomEventMessage } from "@Packages/message/custom_event_message";
10+
import { type TExtensionEnv } from "../extension/extension_env";
1011

1112
export class ScriptRuntime {
1213
constructor(
1314
private readonly scripEnvTag: ScriptEnvTag,
1415
private readonly server: Server,
1516
private readonly msg: Message,
16-
private readonly scriptExecutor: ScriptExecutor
17+
private readonly scriptExecutor: ScriptExecutor,
18+
private readonly extensionEnv: TExtensionEnv | undefined
1719
) {}
1820

1921
// content环境的特殊初始化
@@ -66,8 +68,13 @@ export class ScriptRuntime {
6668
this.startScripts(data.scripts, data.envInfo);
6769
});
6870

71+
// 用于 early-start 的扩充参数
72+
const { inIncognitoContext } = this.extensionEnv || {};
73+
const initialEnvInfo = { ...initEnvInfo };
74+
if (typeof inIncognitoContext === "boolean") initialEnvInfo.isIncognito = inIncognitoContext;
75+
6976
// 检查early-start的脚本
70-
this.scriptExecutor.checkEarlyStartScript(this.scripEnvTag, initEnvInfo);
77+
this.scriptExecutor.checkEarlyStartScript(this.scripEnvTag, initialEnvInfo);
7178
}
7279

7380
startScripts(scripts: TScriptInfo[], envInfo: GMInfoEnv) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
export type TExtensionEnv = {
2+
inIncognitoContext: boolean;
3+
userAgentData?: GMUserAgentData | null;
4+
};
5+
6+
type GMUserAgentData = typeof GM_info.userAgentData;
7+
8+
export const extensionEnv: TExtensionEnv = {
9+
inIncognitoContext: chrome.extension.inIncognitoContext,
10+
} satisfies TExtensionEnv;
11+
12+
export const getExtensionUserAgentData = async (): Promise<GMUserAgentData | null> => {
13+
// @ts-ignore
14+
const userAgentData = navigator.userAgentData;
15+
if (userAgentData) {
16+
const resultData: GMUserAgentData = {
17+
brands: userAgentData.brands,
18+
mobile: userAgentData.mobile,
19+
platform: userAgentData.platform,
20+
} satisfies GMUserAgentData;
21+
// 处理architecture和bitness
22+
if (chrome.runtime.getPlatformInfo) {
23+
try {
24+
const platformInfo = await chrome.runtime.getPlatformInfo();
25+
resultData.architecture = platformInfo.nacl_arch;
26+
resultData.bitness = platformInfo.arch.includes("64") ? "64" : "32";
27+
} catch (e) {
28+
// 避免 API 无法执行的问题。不影响整体运作
29+
console.warn(e);
30+
}
31+
}
32+
return resultData;
33+
}
34+
return null;
35+
};

src/app/service/offscreen/client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ export function preparationSandbox(windowMessage: WindowMessage) {
88
return sendMessage(windowMessage, "offscreen/preparationSandbox");
99
}
1010

11+
export function getExtensionEnv(windowMessage: WindowMessage) {
12+
return sendMessage(windowMessage, "offscreen/getExtensionEnv", { requireUAD: true });
13+
}
14+
1115
// 代理发送消息到ServiceWorker
1216
export function sendMessageToServiceWorker(windowMessage: WindowMessage, action: string, data?: any) {
1317
return sendMessage(windowMessage, "offscreen/sendMessageToServiceWorker", { action, data });

src/app/service/offscreen/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ export class OffscreenManager {
3939
this.serviceWorker.preparationOffscreen();
4040
}
4141

42+
async getExtensionEnv(data: { requireUAD: boolean }) {
43+
return this.sendMessageToServiceWorker({
44+
action: "getExtensionEnv",
45+
data: data,
46+
});
47+
}
48+
4249
sendMessageToServiceWorker(data: { action: string; data: any }) {
4350
return sendMessage(this.extMsgSender, `serviceWorker/${data.action}`, data.data);
4451
}
@@ -47,6 +54,7 @@ export class OffscreenManager {
4754
// 监听消息
4855
this.windowServer.on("logger", this.logger.bind(this));
4956
this.windowServer.on("preparationSandbox", this.preparationSandbox.bind(this));
57+
this.windowServer.on("getExtensionEnv", this.getExtensionEnv.bind(this));
5058
this.windowServer.on("sendMessageToServiceWorker", this.sendMessageToServiceWorker.bind(this));
5159
const script = new ScriptService(
5260
this.windowServer.group("script"),
@@ -55,7 +63,7 @@ export class OffscreenManager {
5563
this.messageQueue
5664
);
5765
script.init();
58-
// 转发从sandbox来的gm api请求
66+
// 转发从sandbox来的请求
5967
forwardMessage("serviceWorker", "runtime/gmApi", this.windowServer, this.extMsgSender);
6068
// 转发valueUpdate与emitEvent
6169
forwardMessage("sandbox", "runtime/valueUpdate", this.windowServer, this.windowMessage);

src/app/service/sandbox/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Server } from "@Packages/message/server";
22
import { type WindowMessage } from "@Packages/message/window_message";
3-
import { preparationSandbox } from "../offscreen/client";
3+
import { getExtensionEnv, preparationSandbox } from "../offscreen/client";
44
import { Runtime } from "./runtime";
55

66
// sandbox环境的管理器
@@ -12,7 +12,8 @@ export class SandboxManager {
1212
}
1313

1414
initManager() {
15-
const runtime = new Runtime(this.windowMessage, this.api);
15+
const extensionEnvAsync = getExtensionEnv(this.windowMessage);
16+
const runtime = new Runtime(this.windowMessage, this.api, extensionEnvAsync);
1617
runtime.init();
1718
// 通知初始化好环境了
1819
preparationSandbox(this.windowMessage);

src/app/service/sandbox/runtime.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { parseUserConfig } from "@App/pkg/utils/yaml";
2121
import { decodeRValue } from "@App/pkg/utils/message_value";
2222
import { extractCronExpr } from "@App/pkg/utils/cron";
2323
import { changeLanguage, initLanguage, t } from "@App/locales/locales";
24+
import { type TExtensionEnv } from "../extension/extension_env";
2425

2526
const utime_1min = 60 * 1000;
2627
const utime_1hr = 60 * 60 * 1000;
@@ -40,7 +41,8 @@ export class Runtime {
4041

4142
constructor(
4243
private windowMessage: WindowMessage,
43-
private api: Server
44+
private api: Server,
45+
private readonly extensionEnvAsync: Promise<TExtensionEnv | undefined>
4446
) {
4547
this.logger = LoggerCore.getInstance().logger({ component: "sandbox" });
4648
// 重试队列,5s检查一次
@@ -171,7 +173,20 @@ export class Runtime {
171173
// 暂未实现执行完成后立马释放,会在下一次执行时释放
172174
await this.stopScript(script.uuid);
173175
}
174-
const exec = new BgExecScriptWarp(script, this.windowMessage);
176+
const extensionEnv = await this.extensionEnvAsync;
177+
178+
// 判断 run-in
179+
const runIn = script.metadata?.["run-in"]?.[0];
180+
const inIncognitoContext = extensionEnv?.inIncognitoContext;
181+
if (runIn && runIn !== "all" && typeof inIncognitoContext === "boolean") {
182+
// 判断插件运行环境
183+
const contextType = inIncognitoContext ? "incognito-tabs" : "normal-tabs";
184+
if (runIn !== contextType) {
185+
return;
186+
}
187+
}
188+
189+
const exec = new BgExecScriptWarp(script, this.windowMessage, extensionEnv);
175190
this.execScriptMap.set(script.uuid, exec);
176191
proxyUpdateRunStatus(this.windowMessage, { uuid: script.uuid, runStatus: SCRIPT_RUN_STATUS_RUNNING });
177192
// 修改掉脚本掉最后运行时间, 数据库也需要修改

src/app/service/service_worker/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { FaviconDAO } from "@App/app/repo/favicon";
2121
import { onRegularUpdateCheckAlarm } from "./regular_updatecheck";
2222
import { cacheInstance } from "@App/app/cache";
2323
import { InfoNotification } from "./utils";
24+
import { extensionEnv, getExtensionUserAgentData } from "../extension/extension_env";
2425

2526
// service worker的管理器
2627
export default class ServiceWorkerManager {
@@ -36,8 +37,17 @@ export default class ServiceWorkerManager {
3637
dao.save(data);
3738
}
3839

40+
async getExtensionEnv(data: { requireUAD: boolean }) {
41+
const result = { ...extensionEnv };
42+
if (data.requireUAD) {
43+
result.userAgentData = await getExtensionUserAgentData();
44+
}
45+
return result;
46+
}
47+
3948
initManager() {
4049
this.api.on("logger", this.logger.bind(this));
50+
this.api.on("getExtensionEnv", this.getExtensionEnv.bind(this));
4151
this.api.on("preparationOffscreen", async () => {
4252
// 准备好环境
4353
await this.sender.init();

0 commit comments

Comments
 (0)