优化消息
This commit is contained in:
parent
84261e22bd
commit
177594b638
10
packages/message/README.md
Normal file
10
packages/message/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# 消息
|
||||
|
||||
对扩展内消息交互的抽象
|
||||
|
||||
主要会有以下几种类型的消息:
|
||||
|
||||
- 从脚本发起的GM请求,需要层层传递到service_worker/offscreen进行处理,有的GM只需要进行一次调用获取一次结果,有的需要进行
|
||||
多次调用获取多次结果,使用connect的方式实现
|
||||
- 从service_woker/offscreen发起的请求,类似消息队列,其它页面进行监听,触发后广播给所有页面,使用connect方式实现
|
||||
- 从扩展页面发起的请求,需要传递到service_worker/offscreen进行处理,如果只是单次调用,获取一次结果,使用message方式实现
|
@ -1,54 +0,0 @@
|
||||
import EventEmitter from "eventemitter3";
|
||||
import { IConnect, IServer } from ".";
|
||||
|
||||
export class ExtServer implements IServer {
|
||||
private EE: EventEmitter;
|
||||
|
||||
constructor() {
|
||||
this.EE = new EventEmitter();
|
||||
chrome.runtime.onConnect.addListener((port) => {
|
||||
this.EE.emit("connect", new ExtConnect(port));
|
||||
});
|
||||
}
|
||||
|
||||
onConnect(callback: (con: IConnect) => void) {
|
||||
this.EE.on("connect", callback);
|
||||
}
|
||||
}
|
||||
|
||||
export function extConnect() {
|
||||
return new ExtConnect(chrome.runtime.connect());
|
||||
}
|
||||
|
||||
export class ExtConnect implements IConnect {
|
||||
private EE: EventEmitter;
|
||||
private port: chrome.runtime.Port;
|
||||
|
||||
constructor(port: chrome.runtime.Port) {
|
||||
this.EE = new EventEmitter();
|
||||
this.port = port;
|
||||
port.onMessage.addListener((message) => {
|
||||
this.EE.emit("message", message);
|
||||
});
|
||||
port.onDisconnect.addListener(() => {
|
||||
this.EE.emit("disconnect");
|
||||
this.EE.removeAllListeners();
|
||||
});
|
||||
}
|
||||
|
||||
postMessage(message: unknown) {
|
||||
this.port.postMessage(message);
|
||||
}
|
||||
|
||||
onMessage(callback: (message: unknown) => void) {
|
||||
this.EE.on("message", callback);
|
||||
}
|
||||
|
||||
onDisconnect(callback: () => void) {
|
||||
this.EE.on("disconnect", callback);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.port.disconnect();
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import EventEmitter from "eventemitter3";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
export interface IServer {
|
||||
onConnect: (callback: (con: IConnect) => void) => void;
|
||||
}
|
||||
|
||||
export interface IConnect {
|
||||
postMessage: (message: unknown) => void;
|
||||
onMessage: (callback: (message: unknown) => void) => void;
|
||||
onDisconnect: (callback: () => void) => void;
|
||||
disconnect: () => void;
|
||||
}
|
||||
|
||||
// 消息通道, 通过连接封装消息通道
|
||||
export class Server {
|
||||
private EE: EventEmitter;
|
||||
|
||||
constructor(private connect: IServer) {
|
||||
this.EE = new EventEmitter();
|
||||
this.connect.onConnect((con) => {
|
||||
this.EE.emit("connection", con);
|
||||
});
|
||||
}
|
||||
|
||||
on(eventName: "connection", callback: (con: IConnect) => void): void;
|
||||
on(eventName: string, callback: (con: IConnect) => void) {
|
||||
this.EE.on(eventName, callback);
|
||||
}
|
||||
}
|
||||
|
||||
export class Connect {
|
||||
private EE: EventEmitter;
|
||||
|
||||
constructor(private con: IConnect) {
|
||||
this.EE = new EventEmitter();
|
||||
this.con.onMessage((message) => {
|
||||
this.messageHandler(message);
|
||||
});
|
||||
this.con.onDisconnect(() => {
|
||||
this.EE.emit("disconnect");
|
||||
this.EE.removeAllListeners();
|
||||
});
|
||||
}
|
||||
|
||||
private callbackFunc(msgId: string): (...data: unknown[]) => void {
|
||||
return (...data: unknown[]) => {
|
||||
this.con.postMessage({ eventName: "callback", data, messageId: msgId });
|
||||
};
|
||||
}
|
||||
|
||||
private messageHandler(data: unknown) {
|
||||
const subData = data as { eventName: string; data: unknown[]; messageId: string; conType: string; id: string };
|
||||
if (subData.eventName === "callback") {
|
||||
this.EE.emit(subData.eventName + subData.messageId, ...subData.data);
|
||||
return;
|
||||
}
|
||||
subData.data.push(this.callbackFunc(subData.messageId));
|
||||
this.EE.emit(subData.eventName, ...subData.data);
|
||||
}
|
||||
|
||||
on(eventName: string, callback: (...args: any[]) => void) {
|
||||
this.EE.on(eventName, callback);
|
||||
}
|
||||
|
||||
send(eventName: string, ...data: unknown[]) {
|
||||
this.con.postMessage({ eventName, data });
|
||||
}
|
||||
|
||||
emit(eventName: string, ...data: any[]) {
|
||||
// 判断最后一个参数是否为函数
|
||||
const callback = data.pop();
|
||||
const messageId = uuidv4();
|
||||
if (typeof callback !== "function") {
|
||||
data.push(callback);
|
||||
} else {
|
||||
this.EE.on("callback" + messageId, (...args) => {
|
||||
callback(...args);
|
||||
});
|
||||
}
|
||||
const sendData = { eventName, data, messageId };
|
||||
this.con.postMessage(sendData);
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
// @vitest-environment jsdom
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { Server, Connect } from ".";
|
||||
import { windowConnect, WindowServer } from "./window";
|
||||
|
||||
describe("server", () => {
|
||||
it("hello", async () => {
|
||||
const myFunc = vi.fn();
|
||||
const server = new Server(new WindowServer(global.window));
|
||||
server.on("connection", (con) => {
|
||||
myFunc();
|
||||
con.onMessage((message) => {
|
||||
myFunc(message);
|
||||
});
|
||||
});
|
||||
const client = windowConnect(window, window);
|
||||
client.postMessage("hello");
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
expect(myFunc).toHaveBeenCalledTimes(2);
|
||||
expect(myFunc).toHaveBeenCalledWith("hello");
|
||||
});
|
||||
});
|
||||
|
||||
describe("connect", async () => {
|
||||
it("hello", async () => {
|
||||
const server = new Server(new WindowServer(global.window));
|
||||
const myFunc = vi.fn();
|
||||
server.on("connection", (con) => {
|
||||
myFunc();
|
||||
const wrapCon = new Connect(con);
|
||||
wrapCon.on("hello", (message) => {
|
||||
myFunc(message);
|
||||
wrapCon.emit("world", "world");
|
||||
});
|
||||
});
|
||||
const client = new Connect(windowConnect(window, window));
|
||||
client.on("world", (message) => {
|
||||
myFunc(message);
|
||||
});
|
||||
client.emit("hello", "hello");
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
expect(myFunc).toHaveBeenCalledTimes(3);
|
||||
expect(myFunc).toHaveBeenCalledWith("hello");
|
||||
expect(myFunc).toHaveBeenCalledWith("world");
|
||||
});
|
||||
it("response", async () => {
|
||||
const server = new Server(new WindowServer(global.window));
|
||||
const myFunc = vi.fn();
|
||||
server.on("connection", (con) => {
|
||||
const wrapCon = new Connect(con);
|
||||
wrapCon.on("ping", (message, response) => {
|
||||
myFunc(message);
|
||||
response("pong");
|
||||
});
|
||||
});
|
||||
const client = new Connect(windowConnect(window, window));
|
||||
client.emit("ping", "ping", (message: string) => {
|
||||
myFunc(message);
|
||||
});
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
expect(myFunc).toHaveBeenCalledTimes(2);
|
||||
expect(myFunc).toHaveBeenCalledWith("ping");
|
||||
expect(myFunc).toHaveBeenCalledWith("pong");
|
||||
});
|
||||
});
|
66
packages/message/message_queue.ts
Normal file
66
packages/message/message_queue.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { ApiFunction } from "./server";
|
||||
|
||||
export class Broker {
|
||||
constructor() {}
|
||||
|
||||
// 订阅
|
||||
subscribe(topic: string, handler: (message: any) => void) {
|
||||
const con = chrome.runtime.connect({ name: topic });
|
||||
con.postMessage({ action: "subscribe", topic });
|
||||
con.onMessage.addListener((msg: { action: string; topic: string; message: any }) => {
|
||||
if (msg.action === "message") {
|
||||
handler(msg.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 发布
|
||||
publish(topic: string, message: any) {
|
||||
chrome.runtime.sendMessage({ action: "publish", topic, message });
|
||||
}
|
||||
}
|
||||
|
||||
// 消息队列
|
||||
export class MessageQueue {
|
||||
topicConMap: Map<string, { name: string; con: chrome.runtime.Port }[]> = new Map();
|
||||
|
||||
handler(): ApiFunction {
|
||||
return ({ action, topic, message }: { action: string; topic: string; message: any }, con) => {
|
||||
if (!con) {
|
||||
throw new Error("con is required");
|
||||
}
|
||||
if (!topic) {
|
||||
throw new Error("topic is required");
|
||||
}
|
||||
switch (action) {
|
||||
case "subscribe":
|
||||
this.subscribe(topic, con as chrome.runtime.Port);
|
||||
break;
|
||||
case "publish":
|
||||
this.publish(topic, message);
|
||||
break;
|
||||
default:
|
||||
throw new Error("action not found");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private subscribe(topic: string, con: chrome.runtime.Port) {
|
||||
let list = this.topicConMap.get(topic);
|
||||
if (!list) {
|
||||
list = [];
|
||||
this.topicConMap.set(topic, list);
|
||||
}
|
||||
list.push({ name: topic, con });
|
||||
con.onDisconnect.addListener(() => {
|
||||
list = list!.filter((item) => item.con !== con);
|
||||
});
|
||||
}
|
||||
|
||||
publish(topic: string, message: any) {
|
||||
const list = this.topicConMap.get(topic);
|
||||
list?.forEach((item) => {
|
||||
item.con.postMessage({ action: "message", topic, message });
|
||||
});
|
||||
}
|
||||
}
|
45
packages/message/server.ts
Normal file
45
packages/message/server.ts
Normal file
@ -0,0 +1,45 @@
|
||||
export type ApiFunction = (params: any, con: chrome.runtime.Port | chrome.runtime.MessageSender) => any;
|
||||
|
||||
export class Server {
|
||||
apiFunctionMap: Map<string, ApiFunction> = new Map();
|
||||
|
||||
constructor() {
|
||||
chrome.runtime.onConnect.addListener((port) => {
|
||||
port.onMessage.addListener((msg: { action: string }) => {
|
||||
this.connectHandle(msg.action, msg, port);
|
||||
});
|
||||
});
|
||||
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
this.messageHandle(msg.action, msg, sender, sendResponse);
|
||||
});
|
||||
}
|
||||
|
||||
on(name: string, func: ApiFunction) {
|
||||
this.apiFunctionMap.set(name, func);
|
||||
}
|
||||
|
||||
private connectHandle(msg: string, params: any, con: chrome.runtime.Port) {
|
||||
const func = this.apiFunctionMap.get(msg);
|
||||
if (func) {
|
||||
func(params, con);
|
||||
}
|
||||
}
|
||||
|
||||
private messageHandle(
|
||||
msg: string,
|
||||
params: any,
|
||||
sender: chrome.runtime.MessageSender,
|
||||
sendResponse: (response: any) => void
|
||||
) {
|
||||
const func = this.apiFunctionMap.get(msg);
|
||||
if (func) {
|
||||
try {
|
||||
const ret = func(params, sender);
|
||||
sendResponse({ code: 0, data: ret });
|
||||
} catch (e: any) {
|
||||
sendResponse({ code: -1, message: e.message });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
import EventEmitter from "eventemitter3";
|
||||
import { IConnect, IServer } from ".";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
export class WindowServer implements IServer {
|
||||
private EE: EventEmitter;
|
||||
|
||||
constructor(win: Window) {
|
||||
this.EE = new EventEmitter();
|
||||
win.addEventListener("message", (event) => {
|
||||
if (event.data.type === "connect") {
|
||||
this.EE.emit("connection", new WindowConnect(event.data.connectId, win, event.source as Window));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onConnect(callback: (con: IConnect) => void) {
|
||||
this.EE.on("connection", callback);
|
||||
}
|
||||
}
|
||||
|
||||
export function windowConnect(source: Window, target: Window) {
|
||||
const connectId = uuidv4();
|
||||
target.postMessage({ type: "connect", connectId }, "*");
|
||||
const con = new WindowConnect(connectId, source, target);
|
||||
return con;
|
||||
}
|
||||
|
||||
export class WindowConnect implements IConnect {
|
||||
private EE: EventEmitter;
|
||||
|
||||
constructor(
|
||||
private id: string,
|
||||
private source: Window,
|
||||
private target: Window
|
||||
) {
|
||||
this.EE = new EventEmitter();
|
||||
this.source.addEventListener("message", (event) => {
|
||||
if (event.data.eventName === "message" && event.data.id === id) {
|
||||
this.EE.emit("message", event.data.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
postMessage(data: unknown) {
|
||||
this.target.postMessage({ eventName: "message", id: this.id, data }, "*");
|
||||
}
|
||||
|
||||
onMessage(callback: (message: unknown) => void) {
|
||||
this.EE.on("message", callback);
|
||||
}
|
||||
|
||||
onDisconnect(callback: () => void) {
|
||||
this.EE.on("disconnect", callback);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.EE.emit("disconnect");
|
||||
this.EE.removeAllListeners();
|
||||
}
|
||||
}
|
@ -1,124 +1,11 @@
|
||||
import { fetchScriptInfo } from "@App/pkg/utils/script";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { Connect } from "@Packages/message";
|
||||
import Cache from "@App/app/cache";
|
||||
import CacheKey from "@App/app/cache_key";
|
||||
import { openInCurrentTab } from "@App/pkg/utils/utils";
|
||||
import LoggerCore from "@App/app/logger/core";
|
||||
import { Server } from "@Packages/message/server";
|
||||
|
||||
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
|
||||
|
||||
export default class Manager {
|
||||
constructor(private connect: Connect) {}
|
||||
|
||||
listenerScriptInstall() {
|
||||
// 初始化脚本安装监听
|
||||
chrome.webRequest.onCompleted.addListener(
|
||||
(req: chrome.webRequest.WebResponseCacheDetails) => {
|
||||
// 处理url, 实现安装脚本
|
||||
if (req.method !== "GET") {
|
||||
return;
|
||||
}
|
||||
const url = new URL(req.url);
|
||||
// 判断是否有hash
|
||||
if (!url.hash) {
|
||||
return;
|
||||
}
|
||||
// 判断是否有url参数
|
||||
if (!url.hash.includes("url=")) {
|
||||
return;
|
||||
}
|
||||
// 获取url参数
|
||||
const targetUrl = url.hash.split("url=")[1];
|
||||
// 读取脚本url内容, 进行安装
|
||||
LoggerCore.getInstance().logger().debug("install script", { url: targetUrl });
|
||||
this.openInstallPageByUrl(targetUrl).catch(() => {
|
||||
// 如果打开失败, 则重定向到安装页
|
||||
chrome.scripting.executeScript({
|
||||
target: { tabId: req.tabId },
|
||||
func: function () {
|
||||
history.back();
|
||||
},
|
||||
});
|
||||
// 并不再重定向当前url
|
||||
chrome.declarativeNetRequest.updateDynamicRules(
|
||||
{
|
||||
removeRuleIds: [2],
|
||||
addRules: [
|
||||
{
|
||||
id: 2,
|
||||
priority: 1,
|
||||
action: {
|
||||
type: chrome.declarativeNetRequest.RuleActionType.ALLOW,
|
||||
},
|
||||
condition: {
|
||||
regexFilter: targetUrl,
|
||||
resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
|
||||
requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
() => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
{
|
||||
urls: [
|
||||
"https://docs.scriptcat.org/docs/script_installation",
|
||||
"https://www.tampermonkey.net/script_installation.php",
|
||||
],
|
||||
types: ["main_frame"],
|
||||
}
|
||||
);
|
||||
// 重定向到脚本安装页
|
||||
chrome.declarativeNetRequest.updateDynamicRules(
|
||||
{
|
||||
removeRuleIds: [1],
|
||||
addRules: [
|
||||
{
|
||||
id: 1,
|
||||
priority: 1,
|
||||
action: {
|
||||
type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,
|
||||
redirect: {
|
||||
regexSubstitution: "https://docs.scriptcat.org/docs/script_installation#url=\\0",
|
||||
},
|
||||
},
|
||||
condition: {
|
||||
regexFilter: "^([^#]+?)\\.user(\\.bg|\\.sub)?\\.js((\\?).*|$)",
|
||||
resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
|
||||
requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET],
|
||||
// 排除常见的复合上述条件的域名
|
||||
excludedRequestDomains: ["github.com"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
() => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public openInstallPageByUrl(url: string) {
|
||||
return fetchScriptInfo(url, "user", false, uuidv4()).then((info) => {
|
||||
Cache.getInstance().set(CacheKey.scriptInfo(info.uuid), info);
|
||||
setTimeout(() => {
|
||||
// 清理缓存
|
||||
Cache.getInstance().del(CacheKey.scriptInfo(info.uuid));
|
||||
}, 60 * 1000);
|
||||
openInCurrentTab(`/src/install.html?uuid=${info.uuid}`);
|
||||
});
|
||||
}
|
||||
// offscreen环境的管理器
|
||||
export class Manager {
|
||||
private api: Server = new Server();
|
||||
|
||||
initManager() {
|
||||
this.listenerScriptInstall();
|
||||
// 监听消息
|
||||
|
||||
}
|
||||
}
|
||||
|
139
src/app/service/service_worker/index.ts
Normal file
139
src/app/service/service_worker/index.ts
Normal file
@ -0,0 +1,139 @@
|
||||
import { fetchScriptInfo } from "@App/pkg/utils/script";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import Cache from "@App/app/cache";
|
||||
import CacheKey from "@App/app/cache_key";
|
||||
import { openInCurrentTab } from "@App/pkg/utils/utils";
|
||||
import LoggerCore from "@App/app/logger/core";
|
||||
import { Server } from "@Packages/message/server";
|
||||
import { MessageQueue } from "@Packages/message/message_queue";
|
||||
|
||||
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
|
||||
|
||||
// service worker的管理器
|
||||
export default class ServiceWorkerManager {
|
||||
constructor() {}
|
||||
|
||||
listenerScriptInstall() {
|
||||
// 初始化脚本安装监听
|
||||
chrome.webRequest.onCompleted.addListener(
|
||||
(req: chrome.webRequest.WebResponseCacheDetails) => {
|
||||
// 处理url, 实现安装脚本
|
||||
if (req.method !== "GET") {
|
||||
return;
|
||||
}
|
||||
const url = new URL(req.url);
|
||||
// 判断是否有hash
|
||||
if (!url.hash) {
|
||||
return;
|
||||
}
|
||||
// 判断是否有url参数
|
||||
if (!url.hash.includes("url=")) {
|
||||
return;
|
||||
}
|
||||
// 获取url参数
|
||||
const targetUrl = url.hash.split("url=")[1];
|
||||
// 读取脚本url内容, 进行安装
|
||||
LoggerCore.getInstance().logger().debug("install script", { url: targetUrl });
|
||||
this.openInstallPageByUrl(targetUrl).catch(() => {
|
||||
// 如果打开失败, 则重定向到安装页
|
||||
chrome.scripting.executeScript({
|
||||
target: { tabId: req.tabId },
|
||||
func: function () {
|
||||
history.back();
|
||||
},
|
||||
});
|
||||
// 并不再重定向当前url
|
||||
chrome.declarativeNetRequest.updateDynamicRules(
|
||||
{
|
||||
removeRuleIds: [2],
|
||||
addRules: [
|
||||
{
|
||||
id: 2,
|
||||
priority: 1,
|
||||
action: {
|
||||
type: chrome.declarativeNetRequest.RuleActionType.ALLOW,
|
||||
},
|
||||
condition: {
|
||||
regexFilter: targetUrl,
|
||||
resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
|
||||
requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
() => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
{
|
||||
urls: [
|
||||
"https://docs.scriptcat.org/docs/script_installation",
|
||||
"https://www.tampermonkey.net/script_installation.php",
|
||||
],
|
||||
types: ["main_frame"],
|
||||
}
|
||||
);
|
||||
// 重定向到脚本安装页
|
||||
chrome.declarativeNetRequest.updateDynamicRules(
|
||||
{
|
||||
removeRuleIds: [1],
|
||||
addRules: [
|
||||
{
|
||||
id: 1,
|
||||
priority: 1,
|
||||
action: {
|
||||
type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,
|
||||
redirect: {
|
||||
regexSubstitution: "https://docs.scriptcat.org/docs/script_installation#url=\\0",
|
||||
},
|
||||
},
|
||||
condition: {
|
||||
regexFilter: "^([^#]+?)\\.user(\\.bg|\\.sub)?\\.js((\\?).*|$)",
|
||||
resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
|
||||
requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET],
|
||||
// 排除常见的复合上述条件的域名
|
||||
excludedRequestDomains: ["github.com"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
() => {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public openInstallPageByUrl(url: string) {
|
||||
return fetchScriptInfo(url, "user", false, uuidv4()).then((info) => {
|
||||
Cache.getInstance().set(CacheKey.scriptInfo(info.uuid), info);
|
||||
setTimeout(() => {
|
||||
// 清理缓存
|
||||
Cache.getInstance().del(CacheKey.scriptInfo(info.uuid));
|
||||
}, 60 * 1000);
|
||||
openInCurrentTab(`/src/install.html?uuid=${info.uuid}`);
|
||||
});
|
||||
}
|
||||
|
||||
private api: Server = new Server();
|
||||
|
||||
private mq: MessageQueue = new MessageQueue();
|
||||
|
||||
// 获取安装信息
|
||||
getInstallInfo(params: { uuid: string }) {
|
||||
const info = Cache.getInstance().get(CacheKey.scriptInfo(params.uuid));
|
||||
return info;
|
||||
}
|
||||
|
||||
initManager() {
|
||||
// 监听消息
|
||||
this.api.on("getInstallInfo", this.getInstallInfo);
|
||||
|
||||
this.listenerScriptInstall();
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import {
|
||||
ScriptDAO,
|
||||
UserConfig,
|
||||
} from "@App/app/repo/scripts";
|
||||
import { InstallSource } from "@App/app/service/manager";
|
||||
import { InstallSource } from "@App/app/service/service_worker";
|
||||
import YAML from "yaml";
|
||||
import { Subscribe, SUBSCRIBE_STATUS_ENABLE, SubscribeDAO } from "@App/app/repo/subscribe";
|
||||
import { nextTime } from "./utils";
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { extConnect } from "@Packages/message/extension";
|
||||
import Manager from "./app/service/manager";
|
||||
import { Connect } from "@Packages/message";
|
||||
import ServiceWorkerManager from "./app/service/service_worker";
|
||||
import migrate from "./app/migrate";
|
||||
import LoggerCore from "./app/logger/core";
|
||||
import DBWriter from "./app/logger/db_writer";
|
||||
@ -55,10 +53,8 @@ async function main() {
|
||||
loggerCore.logger().debug("background start");
|
||||
// 初始化沙盒环境
|
||||
await setupOffscreenDocument();
|
||||
// 初始化连接
|
||||
const extClient = new Connect(extConnect());
|
||||
// 初始化管理器
|
||||
const manager = new Manager(extClient);
|
||||
const manager = new ServiceWorkerManager();
|
||||
manager.initManager();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user