From 6c008feb3f00a8584d70db00b171a11edf2e6d76 Mon Sep 17 00:00:00 2001 From: IndieKKY Date: Sun, 6 Oct 2024 12:35:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/consts/const.ts | 1 - src/messaging/ExtensionMessage.ts | 49 ++++++++++++++---------------- src/messaging/InjectMessage.ts | 44 +++++++++++++-------------- src/messaging/const.ts | 17 +++++++++++ src/messaging/useMessage.ts | 19 +++++------- src/messaging/useMessageService.ts | 29 ++++++++---------- 6 files changed, 83 insertions(+), 76 deletions(-) diff --git a/src/consts/const.ts b/src/consts/const.ts index 02737ef..9af800a 100644 --- a/src/consts/const.ts +++ b/src/consts/const.ts @@ -2,7 +2,6 @@ export const MESSAGE_TARGET_EXTENSION = 'BilibiliExtension' export const MESSAGE_TARGET_INJECT = 'BilibiliInject' export const MESSAGE_TARGET_APP = 'BilibiliAPP' -export const MESSAGE_TO_EXTENSION_ROUTE_MSG = 'routeMsg' export const MESSAGE_TO_EXTENSION_CLOSE_SIDE_PANEL = 'closeSidePanel' export const MESSAGE_TO_EXTENSION_ADD_TASK = 'addTask' export const MESSAGE_TO_EXTENSION_GET_TASK = 'getTask' diff --git a/src/messaging/ExtensionMessage.ts b/src/messaging/ExtensionMessage.ts index a9ae039..37ff43d 100644 --- a/src/messaging/ExtensionMessage.ts +++ b/src/messaging/ExtensionMessage.ts @@ -1,5 +1,7 @@ -import { MESSAGE_TARGET_INJECT, MESSAGE_TO_EXTENSION_ROUTE_MSG } from '@/consts/const' +import { MESSAGE_TARGET_INJECT } from '@/consts/const' import Layer1Protocol from './Layer1Protocol' +import { L2ReqMsg, L2ResMsg, MESSAGE_TO_EXTENSION_ROUTE_MSG } from './const' + export type PortContext = { id: string @@ -17,9 +19,6 @@ class ExtensionMessage { methods?: { [key: string]: (params: any, context: MethodContext) => Promise } - innerMethods?: { - [key: string]: (params: any, context: MethodContext) => Promise - } debug = (...args: any[]) => { console.debug('[Extension Messaging]', ...args) @@ -28,39 +27,37 @@ class ExtensionMessage { init = (methods: { [key: string]: (params: any, context: MethodContext) => Promise }) => { - this.innerMethods = { + const innerMethods = { [MESSAGE_TO_EXTENSION_ROUTE_MSG]: (params: any, context: MethodContext) => { return this.broadcastMessageExact([context.tabId!], params.target, params.method, params.params) } } - this.methods = {...this.innerMethods, ...methods} - const handler = async (event: MessageData, portContext: PortContext): Promise => { + this.methods = {...innerMethods, ...methods} + + const handler = async (req: L2ReqMsg, portContext: PortContext): Promise => { const { tabId } = portContext - const method = this.methods?.[event.method] + const method = this.methods?.[req.method] if (method != null) { - return method(event.params, { - from: event.from, - event, + return method(req.params, { + from: req.from, + event: req, tabId, // sender: portContext.port.sender, }).then(data => ({ - success: true, code: 200, data, })).catch(err => { console.error(err) return { - success: false, code: 500, message: err.message, } }) } else { return { - success: false, code: 501, - message: 'Unknown method: ' + event.method, + message: 'Unknown method: ' + req.method, } } } @@ -70,11 +67,11 @@ class ExtensionMessage { const id = crypto.randomUUID() const name = port.name - const portMessageHandler = new Layer1Protocol(async (value: MessageData) => { + const portMessageHandler = new Layer1Protocol(async (req: L2ReqMsg) => { // 初始化消息 - if (value.method === '_init') { - const type = value.params.type - let tabId = value.params.tabId + if (req.method === '_init') { + const type = req.params.type + let tabId = req.params.tabId //get current tabId if (tabId == null) { @@ -90,13 +87,12 @@ class ExtensionMessage { portContext.ready = true return { - success: true, code: 200, - } as MessageResult + } as L2ResMsg } // 处理消息 - return handler(value, portContext) + return handler(req, portContext) }, port) const portContext: PortContext = {id, name, port, portMessageHandler, ready: false} this.portIdToPort.set(id, portContext) @@ -109,22 +105,23 @@ class ExtensionMessage { }) } + //返回:最后一个响应(因此如果只发送给一个tab,则返回的是该tab的响应) broadcastMessageExact = async (tabIds: number[], target: string, method: string, params?: any) => { const targetType = target === MESSAGE_TARGET_INJECT ? 'inject' : 'app' - let resp: MessageResult | undefined + let res: L2ResMsg | undefined for (const portContext of this.portIdToPort.values()) { if (tabIds.includes(portContext.tabId!)) { if (targetType === portContext.type) { try { - const messageData: MessageData = {target, method, params, from: 'extension'} - resp = await portContext.portMessageHandler.sendMessage(messageData) + const req: L2ReqMsg = {target, method, params, from: 'extension'} + res = await portContext.portMessageHandler.sendMessage(req) } catch (e) { console.error('send message to port error', portContext.id, e) } } } } - return resp?.data + return res?.data } broadcastMessage = async (ignoreTabIds: number[] | undefined | null, target: string, method: string, params?: any) => { diff --git a/src/messaging/InjectMessage.ts b/src/messaging/InjectMessage.ts index 89cce1b..3dc97a8 100644 --- a/src/messaging/InjectMessage.ts +++ b/src/messaging/InjectMessage.ts @@ -1,38 +1,38 @@ -import { MESSAGE_TARGET_APP, MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT, MESSAGE_TO_EXTENSION_ROUTE_MSG } from '@/consts/const' +import { MESSAGE_TARGET_APP, MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT } from '@/consts/const' import Layer1Protocol from './Layer1Protocol' +import { L2ReqMsg, L2ResMsg, MESSAGE_TO_EXTENSION_ROUTE_MSG } from './const' class InjectMessage { port?: chrome.runtime.Port - portMessageHandler?: Layer1Protocol + portMessageHandler?: Layer1Protocol //类实例 methods?: { - [key: string]: (params: any, context: MethodContext) => Promise + [key: string]: (params: any, context: MethodContext) => Promise } debug = (...args: any[]) => { console.debug('[Inject Messaging]', ...args) } - messageHandler = async (event: MessageData): Promise => { - this.debug(`${event.from} => `, JSON.stringify(event)) + messageHandler = async (req: L2ReqMsg): Promise => { + this.debug(`${req.from} => `, JSON.stringify(req)) // check event target - if (event.target !== MESSAGE_TARGET_INJECT) return Promise.resolve({ + if (req.target !== MESSAGE_TARGET_INJECT) return Promise.resolve({ success: false, code: 501, - message: 'Target Error: ' + event.target, + message: 'Target Error: ' + req.target, }) - const method = this.methods?.[event.method] + const method = this.methods?.[req.method] if (method != null) { - return method(event.params, { - from: event.from, - event, + return method(req.params, { + from: req.from, + event: req, // sender, }).then(data => { // debug(`${source} <= `, event.method, JSON.stringify(data)) return { - success: true, code: 200, data, } @@ -47,16 +47,14 @@ class InjectMessage { message = 'error: ' + JSON.stringify(err) } return { - success: false, code: 500, message, } }) } else { return { - success: false, code: 501, - message: 'Unknown method: ' + event.method, + message: 'Unknown method: ' + req.method, } } } @@ -68,27 +66,29 @@ class InjectMessage { this.port = chrome.runtime.connect(import.meta.env.VITE_EXTENSION_ID, { name: MESSAGE_TARGET_INJECT, }) - this.portMessageHandler = new Layer1Protocol(this.messageHandler, this.port) + this.portMessageHandler = new Layer1Protocol(this.messageHandler, this.port) this.portMessageHandler.sendMessage({ + from: 'inject', + target: MESSAGE_TARGET_EXTENSION, method: '_init', params: { type: 'inject', }, - } as MessageData) + }) } sendExtension = async (method: string, params?: any): Promise => { - const messageData: MessageData = { + const req: L2ReqMsg = { from: 'inject', target: MESSAGE_TARGET_EXTENSION, method, params: params ?? {}, } - return await this.portMessageHandler!.sendMessage(messageData).then((messageResult) => { - if (messageResult.success) { - return messageResult.data as T + return await this.portMessageHandler!.sendMessage(req).then((res) => { + if (res.code === 200) { + return res.data as T } else { - throw new Error(messageResult.message) + throw new Error(res.message) } }) } diff --git a/src/messaging/const.ts b/src/messaging/const.ts index e69de29..c5d50b4 100644 --- a/src/messaging/const.ts +++ b/src/messaging/const.ts @@ -0,0 +1,17 @@ +// 请求信息 +export type L2ReqMsg = { + from: 'extension' | 'inject' | 'app' + target: string + method: string + params?: any + // [key: string]: any +} + +// 响应信息 +export type L2ResMsg = { + code: number + message?: string + data?: L2Res +} + +export const MESSAGE_TO_EXTENSION_ROUTE_MSG = 'routeMsg' diff --git a/src/messaging/useMessage.ts b/src/messaging/useMessage.ts index 97d0271..bd4dc1c 100644 --- a/src/messaging/useMessage.ts +++ b/src/messaging/useMessage.ts @@ -1,27 +1,24 @@ -import { MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT, MESSAGE_TO_EXTENSION_ROUTE_MSG } from '@/consts/const' +import { MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT } from '@/consts/const' import { injectWaiter } from './useMessageService' import { useCallback } from 'react' import Layer1Protocol from './Layer1Protocol' +import { L2ReqMsg, L2ResMsg, MESSAGE_TO_EXTENSION_ROUTE_MSG } from './const' const useMessage = () => { const sendExtension = useCallback(async (method: string, params?: any) => { // wait - const portMessageHandler = await injectWaiter.wait() as Layer1Protocol + const pmh = await injectWaiter.wait() as Layer1Protocol // send message - const messageResult = await portMessageHandler.sendMessage({ + const res = await pmh.sendMessage({ from: 'app', target: MESSAGE_TARGET_EXTENSION, method, params: params ?? {}, - }) as MessageResult | undefined - if (messageResult != null) { - if (messageResult.success) { - return messageResult.data as T - } else { - throw new Error(messageResult.message) - } + }) + if (res.code === 200) { + return res.data as T } else { - throw new Error('no response') + throw new Error(res.message) } }, []) diff --git a/src/messaging/useMessageService.ts b/src/messaging/useMessageService.ts index cf92cad..5053a8e 100644 --- a/src/messaging/useMessageService.ts +++ b/src/messaging/useMessageService.ts @@ -4,13 +4,14 @@ import { } from '@/consts/const' import { Waiter } from '@kky002/kky-util' import Layer1Protocol from './Layer1Protocol' +import { L2ReqMsg, L2ResMsg } from './const' const debug = (...args: any[]) => { console.debug('[App Messaging]', ...args) } let portMessageHandlerInit: boolean = false -let portMessageHandler: Layer1Protocol | undefined +let portMessageHandler: Layer1Protocol | undefined // let postInjectMessage: (method: string, params: PostMessagePayload) => Promise | undefined export const injectWaiter = new Waiter(() => ({ @@ -21,25 +22,23 @@ export const injectWaiter = new Waiter(() => ({ const useMessageService = (methods?: { [key: string]: (params: any, context: MethodContext) => Promise }) => { - const messageHandler = useCallback(async (event: MessageData): Promise => { - debug(`${event.from} => `, JSON.stringify(event)) + const messageHandler = useCallback(async (req: L2ReqMsg): Promise => { + debug(`${req.from} => `, JSON.stringify(req)) // check event target - if (event.target !== MESSAGE_TARGET_APP) return { - success: false, + if (req.target !== MESSAGE_TARGET_APP) return { code: 501, - message: 'Target Error: ' + event.target, + message: 'Target Error: ' + req.target, } - const method = methods?.[event.method] + const method = methods?.[req.method] if (method != null) { - return method(event.params, { - from: event.from, - event, + return method(req.params, { + from: req.from, + event: req, }).then(data => { // debug(`${source} <= `, event.method, JSON.stringify(data)) return { - success: true, code: 200, data, } @@ -54,16 +53,14 @@ const useMessageService = (methods?: { message = 'error: ' + JSON.stringify(err) } return { - success: false, code: 500, message, } }) } else { return { - success: false, code: 501, - message: 'Unknown method: ' + event.method, + message: 'Unknown method: ' + req.method, } } }, [methods]) @@ -75,7 +72,7 @@ const useMessageService = (methods?: { }, []) portMessageHandler = useMemo(() => { if (messageHandler && port) { - const pmh = new Layer1Protocol(messageHandler, port) + const pmh = new Layer1Protocol(messageHandler, port) //get tabId from url params let tabIdStr = window.location.search.split('tabId=')[1] @@ -87,7 +84,7 @@ const useMessageService = (methods?: { type: 'app', tabId, }, - } as MessageData) + } as L2ReqMsg) portMessageHandlerInit = true return pmh