You've already forked bilibili-subtitle
消息传递重构&支持侧边面板
This commit is contained in:
@@ -1,9 +1,23 @@
|
||||
import { MESSAGE_TARGET_EXTENSION } from '@/const'
|
||||
import { MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT, MESSAGE_TO_EXTENSION_ROUTE_MSG } from '@/const'
|
||||
import PortMessageHandler from './PortMessageHandler'
|
||||
|
||||
export type PortContext = {
|
||||
id: string
|
||||
name: string
|
||||
tabId: number
|
||||
type: 'inject' | 'app'
|
||||
port: chrome.runtime.Port
|
||||
portMessageHandler: PortMessageHandler
|
||||
}
|
||||
|
||||
class ExtensionMessage {
|
||||
portIdToPort: Map<string, PortContext> = new Map()
|
||||
methods?: {
|
||||
[key: string]: (params: any, context: MethodContext) => Promise<any>
|
||||
}
|
||||
innerMethods?: {
|
||||
[key: string]: (params: any, context: MethodContext) => Promise<any>
|
||||
}
|
||||
|
||||
debug = (...args: any[]) => {
|
||||
console.debug('[Extension Messaging]', ...args)
|
||||
@@ -12,78 +26,162 @@ class ExtensionMessage {
|
||||
init = (methods: {
|
||||
[key: string]: (params: any, context: MethodContext) => Promise<any>
|
||||
}) => {
|
||||
this.methods = methods
|
||||
|
||||
/**
|
||||
* Note: Return true when sending a response asynchronously.
|
||||
*/
|
||||
chrome.runtime.onMessage.addListener((event: MessageData, sender: chrome.runtime.MessageSender, sendResponse: (result: any) => void) => {
|
||||
this.debug((sender.tab != null) ? `tab ${sender.tab.url ?? ''} => ` : 'extension => ', event)
|
||||
|
||||
// check event target
|
||||
if (event.target !== MESSAGE_TARGET_EXTENSION) return
|
||||
this.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<MessageResult> => {
|
||||
const { tabId } = portContext
|
||||
const method = this.methods?.[event.method]
|
||||
if (method != null) {
|
||||
method(event.params, {
|
||||
return method(event.params, {
|
||||
from: event.from,
|
||||
event,
|
||||
sender,
|
||||
}).then(data => sendResponse({
|
||||
tabId,
|
||||
// sender: portContext.port.sender,
|
||||
}).then(data => ({
|
||||
success: true,
|
||||
code: 200,
|
||||
data,
|
||||
})).catch(err => {
|
||||
console.error(err)
|
||||
let message
|
||||
if (err instanceof Error) {
|
||||
message = err.message
|
||||
} else if (typeof err === 'string') {
|
||||
message = err
|
||||
} else {
|
||||
message = 'error: ' + JSON.stringify(err)
|
||||
}
|
||||
sendResponse({
|
||||
return {
|
||||
success: false,
|
||||
code: 500,
|
||||
message,
|
||||
})
|
||||
message: err.message,
|
||||
}
|
||||
})
|
||||
return true
|
||||
} else {
|
||||
console.error('Unknown method:', event.method)
|
||||
sendResponse({
|
||||
return {
|
||||
success: false,
|
||||
code: 501,
|
||||
message: 'Unknown method: ' + event.method,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chrome.runtime.onConnect.addListener((port: chrome.runtime.Port) => {
|
||||
this.debug('onConnect', port)
|
||||
|
||||
const id = crypto.randomUUID()
|
||||
const name = port.name
|
||||
|
||||
const listener = async (firstMessage: any) => {
|
||||
console.log('firstMessage', name, firstMessage)
|
||||
|
||||
let tabId = firstMessage.tabId
|
||||
let type = firstMessage.type
|
||||
if (tabId == null) {
|
||||
//get current tabId
|
||||
const tabs = await chrome.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
})
|
||||
tabId = tabs[0]?.id
|
||||
console.log('current tabId: ', tabId)
|
||||
}
|
||||
if (tabId != null) {
|
||||
// @ts-ignore
|
||||
const portContext: PortContext = {id, name, tabId, port, type}
|
||||
const portMessageHandler = new PortMessageHandler<MessageData, MessageResult>(async (value: MessageData) => {
|
||||
return handler(value, portContext)
|
||||
}, port)
|
||||
portContext.portMessageHandler = portMessageHandler
|
||||
this.portIdToPort.set(id, portContext)
|
||||
|
||||
// 移除监听
|
||||
port.onMessage.removeListener(listener)
|
||||
// 开始监听
|
||||
portMessageHandler.startListen()
|
||||
|
||||
console.log('start listen>>>', name)
|
||||
}else {
|
||||
console.log('no tabId>>>', name)
|
||||
}
|
||||
}
|
||||
port.onMessage.addListener(listener)
|
||||
|
||||
port.onDisconnect.addListener(() => {
|
||||
this.portIdToPort.delete(id)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Note: Return true when sending a response asynchronously.
|
||||
*/
|
||||
// chrome.runtime.onMessage.addListener((event: MessageData, sender: chrome.runtime.MessageSender, sendResponse: (result: any) => void) => {
|
||||
// this.debug((sender.tab != null) ? `tab ${sender.tab.url ?? ''} => ` : 'extension => ', event)
|
||||
|
||||
// // check event target
|
||||
// if (event.target !== MESSAGE_TARGET_EXTENSION) return
|
||||
|
||||
// const method = this.methods?.[event.method]
|
||||
// if (method != null) {
|
||||
// method(event.params, {
|
||||
// from: event.from,
|
||||
// event,
|
||||
// sender,
|
||||
// }).then(data => sendResponse({
|
||||
// success: true,
|
||||
// code: 200,
|
||||
// data,
|
||||
// })).catch(err => {
|
||||
// console.error(err)
|
||||
// let message
|
||||
// if (err instanceof Error) {
|
||||
// message = err.message
|
||||
// } else if (typeof err === 'string') {
|
||||
// message = err
|
||||
// } else {
|
||||
// message = 'error: ' + JSON.stringify(err)
|
||||
// }
|
||||
// sendResponse({
|
||||
// success: false,
|
||||
// code: 500,
|
||||
// message,
|
||||
// })
|
||||
// })
|
||||
// return true
|
||||
// } else {
|
||||
// console.error('Unknown method:', event.method)
|
||||
// sendResponse({
|
||||
// success: false,
|
||||
// code: 501,
|
||||
// message: 'Unknown method: ' + event.method,
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
broadcastMessageExact = async (tabIds: number[], target: string, method: string, params?: any) => {
|
||||
for (const tabId of tabIds) {
|
||||
try {
|
||||
await chrome.tabs.sendMessage(tabId, {target, method, params})
|
||||
} catch (e) {
|
||||
console.error('send message to tab error', tabId, e)
|
||||
//遍历portIdToPort
|
||||
const targetType = target === MESSAGE_TARGET_INJECT ? 'inject' : 'app'
|
||||
let resp: MessageResult | 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)
|
||||
} catch (e) {
|
||||
console.error('send message to port error', portContext.id, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resp?.data
|
||||
}
|
||||
|
||||
broadcastMessage = async (ignoreTabIds: number[] | undefined | null, target: string, method: string, params?: any) => {
|
||||
const tabs = await chrome.tabs.query({
|
||||
discarded: false,
|
||||
})
|
||||
for (const tab of tabs) {
|
||||
try {
|
||||
if (tab.id && ((ignoreTabIds == null) || !ignoreTabIds.includes(tab.id))) {
|
||||
await chrome.tabs.sendMessage(tab.id, {target, method, params})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('send message to tab error', tab.id, e)
|
||||
}
|
||||
}
|
||||
const tabIds: number[] = tabs.map(tab => tab.id).filter(tabId => tabId != null) as number[]
|
||||
const filteredTabIds: number[] = tabIds.filter(tabId => !ignoreTabIds?.includes(tabId))
|
||||
await this.broadcastMessageExact(filteredTabIds, target, method, params)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,12 +1,15 @@
|
||||
import { MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT } from '@/const'
|
||||
import { MESSAGE_TARGET_APP, MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT, MESSAGE_TO_EXTENSION_ROUTE_MSG } from '@/const'
|
||||
import { PostMessagePayload, PostMessageResponse, startListening } from 'postmessage-promise'
|
||||
import PortMessageHandler from './PortMessageHandler'
|
||||
|
||||
class InjectMessage {
|
||||
port?: chrome.runtime.Port
|
||||
portMessageHandler?: PortMessageHandler
|
||||
//类实例
|
||||
methods?: {
|
||||
[key: string]: (params: any, context: MethodContext) => Promise<any>
|
||||
}
|
||||
postMessageToApp?: (method: string, payload: PostMessagePayload) => Promise<PostMessageResponse>
|
||||
// postMessageToApp?: (method: string, payload: PostMessagePayload) => Promise<PostMessageResponse>
|
||||
|
||||
debug = (...args: any[]) => {
|
||||
console.debug('[Inject Messaging]', ...args)
|
||||
@@ -15,27 +18,30 @@ class InjectMessage {
|
||||
/**
|
||||
* @param sendResponse No matter what is returned, this method will definitely be called.
|
||||
*/
|
||||
messageHandler = (event: MessageData, sender: chrome.runtime.MessageSender | null, sendResponse: (response?: MessageResult) => void) => {
|
||||
const source = sender != null ? ((sender.tab != null) ? `tab ${sender.tab.url ?? ''}` : 'extension') : 'app'
|
||||
this.debug(`${source} => `, JSON.stringify(event))
|
||||
messageHandler = async (event: MessageData): Promise<MessageResult> => {
|
||||
this.debug(`${event.from} => `, JSON.stringify(event))
|
||||
|
||||
// check event target
|
||||
if (event.target !== MESSAGE_TARGET_INJECT) return
|
||||
if (event.target !== MESSAGE_TARGET_INJECT) return Promise.resolve({
|
||||
success: false,
|
||||
code: 501,
|
||||
message: 'Target Error: ' + event.target,
|
||||
})
|
||||
|
||||
const method = this.methods?.[event.method]
|
||||
if (method != null) {
|
||||
method(event.params, {
|
||||
return method(event.params, {
|
||||
from: event.from,
|
||||
event,
|
||||
sender,
|
||||
// sender,
|
||||
}).then(data => {
|
||||
// debug(`${source} <= `, event.method, JSON.stringify(data))
|
||||
return data
|
||||
}).then(data => sendResponse({
|
||||
success: true,
|
||||
code: 200,
|
||||
data,
|
||||
})).catch(err => {
|
||||
return {
|
||||
success: true,
|
||||
code: 200,
|
||||
data,
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
let message
|
||||
if (err instanceof Error) {
|
||||
@@ -45,55 +51,60 @@ class InjectMessage {
|
||||
} else {
|
||||
message = 'error: ' + JSON.stringify(err)
|
||||
}
|
||||
sendResponse({
|
||||
return {
|
||||
success: false,
|
||||
code: 500,
|
||||
message,
|
||||
})
|
||||
}
|
||||
})
|
||||
return true
|
||||
} else {
|
||||
console.error('Unknown method:', event.method)
|
||||
sendResponse({
|
||||
return {
|
||||
success: false,
|
||||
code: 501,
|
||||
message: 'Unknown method: ' + event.method,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init(methods: {
|
||||
[key: string]: (params: any, context: MethodContext) => Promise<any>
|
||||
}) {
|
||||
this.port = chrome.runtime.connect(import.meta.env.VITE_EXTENSION_ID, {
|
||||
name: MESSAGE_TARGET_INJECT,
|
||||
})
|
||||
this.portMessageHandler = new PortMessageHandler<MessageData, MessageResult>(this.messageHandler, this.port)
|
||||
this.portMessageHandler!.startListen()
|
||||
this.portMessageHandler!.init('inject')
|
||||
this.methods = methods
|
||||
// listen message from app
|
||||
startListening({}).then(e => {
|
||||
const { postMessage, listenMessage, destroy } = e
|
||||
this.postMessageToApp = postMessage
|
||||
listenMessage((method, params, sendResponse) => {
|
||||
this.messageHandler({
|
||||
from: 'app',
|
||||
target: MESSAGE_TARGET_INJECT,
|
||||
method,
|
||||
params,
|
||||
}, null, sendResponse)
|
||||
})
|
||||
}).catch(console.error)
|
||||
// startListening({}).then(e => {
|
||||
// const { postMessage, listenMessage, destroy } = e
|
||||
// this.postMessageToApp = postMessage
|
||||
// listenMessage((method, params, sendResponse) => {
|
||||
// this.messageHandler({
|
||||
// from: 'app',
|
||||
// target: MESSAGE_TARGET_INJECT,
|
||||
// method,
|
||||
// params,
|
||||
// }, null, sendResponse)
|
||||
// })
|
||||
// }).catch(console.error)
|
||||
|
||||
/**
|
||||
* listen message from extension
|
||||
* Attention: return true if you need to sendResponse asynchronously
|
||||
*/
|
||||
chrome.runtime.onMessage.addListener(this.messageHandler)
|
||||
// chrome.runtime.onMessage.addListener(this.messageHandler)
|
||||
}
|
||||
|
||||
sendExtension = async <T = any>(method: string, params?: any): Promise<T> => {
|
||||
return await chrome.runtime.sendMessage<MessageData, MessageResult>({
|
||||
const messageData: MessageData = {
|
||||
from: 'inject',
|
||||
target: MESSAGE_TARGET_EXTENSION,
|
||||
method,
|
||||
params: params ?? {},
|
||||
}).then((messageResult) => {
|
||||
}
|
||||
return await this.portMessageHandler!.sendMessage(messageData).then((messageResult) => {
|
||||
if (messageResult.success) {
|
||||
return messageResult.data as T
|
||||
} else {
|
||||
@@ -103,20 +114,14 @@ class InjectMessage {
|
||||
}
|
||||
|
||||
sendApp = async <T>(method: string, params: any): Promise<T> => {
|
||||
if (this.postMessageToApp != null) {
|
||||
const messageResult = await this.postMessageToApp(method, params) as MessageResult | undefined
|
||||
if (messageResult != null) {
|
||||
if (messageResult.success) {
|
||||
return messageResult.data as T
|
||||
} else {
|
||||
throw new Error(messageResult.message)
|
||||
}
|
||||
} else {
|
||||
throw new Error('no response')
|
||||
}
|
||||
} else {
|
||||
throw new Error('error: postMessageToApp is not initialized')
|
||||
if (method === 'setVideoInfo') {
|
||||
console.log('sendApp>>>', method, params)
|
||||
}
|
||||
return this.sendExtension(MESSAGE_TO_EXTENSION_ROUTE_MSG, {
|
||||
target: MESSAGE_TARGET_APP,
|
||||
method,
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,3 @@
|
||||
//暂时没用到
|
||||
|
||||
export type RespMsg<T = any> = {
|
||||
code: number
|
||||
data?: T
|
||||
@@ -21,15 +19,29 @@ class PortMessageHandler<Req = any, Res = any> {
|
||||
private timeout: number
|
||||
private messageMap: Map<string, { resolve: (value: Res) => void, timer: number }>
|
||||
private handler: (value: Req) => Promise<Res>
|
||||
private type?: 'inject' | 'app'
|
||||
private tabId?: number
|
||||
|
||||
constructor(handler: (value: Req) => Promise<Res>, port: chrome.runtime.Port, timeout = 30000) { // 默认超时 30 秒
|
||||
this.port = port;
|
||||
this.timeout = timeout;
|
||||
this.messageMap = new Map();
|
||||
this.handler = handler
|
||||
}
|
||||
|
||||
init(type: 'inject' | 'app', tabId?: number) {
|
||||
this.type = type
|
||||
this.tabId = tabId
|
||||
this.port.postMessage({
|
||||
type,
|
||||
tabId,
|
||||
})
|
||||
}
|
||||
|
||||
startListen() {
|
||||
// 持久监听 port.onMessage
|
||||
this.port.onMessage.addListener((msg: PortMessage<Req, Res>) => {
|
||||
console.log('msg', this.type, this.tabId, msg)
|
||||
const { msgId, msgType, req, res } = msg;
|
||||
if (msgType === 'req') {
|
||||
this.handler(req!).then(res => {
|
||||
@@ -77,6 +89,7 @@ class PortMessageHandler<Req = any, Res = any> {
|
||||
|
||||
// 发送消息,并附带 ID
|
||||
this.port.postMessage({ msgId, msgType: 'req', req });
|
||||
console.log('sendMessage>>>', msgId, 'req', req)
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -1,28 +1,19 @@
|
||||
import { MESSAGE_TARGET_EXTENSION } from '@/const'
|
||||
import { MESSAGE_TARGET_EXTENSION, MESSAGE_TARGET_INJECT, MESSAGE_TO_EXTENSION_ROUTE_MSG } from '@/const'
|
||||
import { injectWaiter } from './useMessageService'
|
||||
import { useCallback } from 'react'
|
||||
import PortMessageHandler from './PortMessageHandler'
|
||||
|
||||
const useMessage = () => {
|
||||
const sendExtension = useCallback(async <T = any>(method: string, params?: any) => {
|
||||
return await chrome.runtime.sendMessage<MessageData, MessageResult>({
|
||||
// wait
|
||||
const portMessageHandler = await injectWaiter.wait() as PortMessageHandler<MessageData, MessageResult>
|
||||
// send message
|
||||
const messageResult = await portMessageHandler.sendMessage({
|
||||
from: 'app',
|
||||
target: MESSAGE_TARGET_EXTENSION,
|
||||
method,
|
||||
params: params ?? {},
|
||||
}).then((messageResult) => {
|
||||
if (messageResult.success) {
|
||||
return messageResult.data as T
|
||||
} else {
|
||||
throw new Error(messageResult.message)
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
const sendInject = useCallback(async <T = any>(method: string, params?: any) => {
|
||||
// wait
|
||||
const postInjectMessage = await injectWaiter.wait()
|
||||
// send message
|
||||
const messageResult = await postInjectMessage(method, params) as MessageResult | undefined
|
||||
}) as MessageResult | undefined
|
||||
if (messageResult != null) {
|
||||
if (messageResult.success) {
|
||||
return messageResult.data as T
|
||||
@@ -34,6 +25,14 @@ const useMessage = () => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
const sendInject = useCallback(async <T = any>(method: string, params?: any): Promise<T> => {
|
||||
return await sendExtension(MESSAGE_TO_EXTENSION_ROUTE_MSG, {
|
||||
target: MESSAGE_TARGET_INJECT,
|
||||
method,
|
||||
params: params ?? {},
|
||||
})
|
||||
}, [])
|
||||
|
||||
return {
|
||||
sendExtension,
|
||||
sendInject
|
||||
|
@@ -1,94 +1,159 @@
|
||||
import {useCallback, useEffect} from 'react'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import {
|
||||
MESSAGE_TARGET_APP,
|
||||
MESSAGE_TARGET_EXTENSION,
|
||||
MESSAGE_TARGET_INJECT,
|
||||
} from '@/const'
|
||||
import {callServer, PostMessagePayload, PostMessageResponse} from 'postmessage-promise'
|
||||
import {Waiter} from '@kky002/kky-util'
|
||||
import { callServer, PostMessagePayload, PostMessageResponse } from 'postmessage-promise'
|
||||
import { Waiter } from '@kky002/kky-util'
|
||||
import PortMessageHandler from './PortMessageHandler'
|
||||
|
||||
const debug = (...args: any[]) => {
|
||||
console.debug('[App Messaging]', ...args)
|
||||
}
|
||||
|
||||
let postInjectMessage: (method: string, params: PostMessagePayload) => Promise<PostMessageResponse> | undefined
|
||||
let portMessageHandlerInit: boolean = false
|
||||
let portMessageHandler: PortMessageHandler<MessageData, MessageResult> | undefined
|
||||
// let postInjectMessage: (method: string, params: PostMessagePayload) => Promise<PostMessageResponse> | undefined
|
||||
|
||||
export const injectWaiter = new Waiter<typeof postInjectMessage>(() => ({
|
||||
finished: postInjectMessage != null,
|
||||
data: postInjectMessage
|
||||
export const injectWaiter = new Waiter<any>(() => ({
|
||||
finished: portMessageHandlerInit,
|
||||
data: portMessageHandler
|
||||
}), 100, 15000)
|
||||
|
||||
const useMessageService = (methods?: {
|
||||
[key: string]: (params: any, context: MethodContext) => boolean
|
||||
[key: string]: (params: any, context: MethodContext) => Promise<any>
|
||||
}) => {
|
||||
const messageHandler = useCallback((method: string, params: any, context: MethodContext): boolean => {
|
||||
const handler = methods?.[method]
|
||||
if (handler != null) {
|
||||
return handler(params, context)
|
||||
}else {
|
||||
debug('unknown message method: ', method)
|
||||
return false
|
||||
const messageHandler = useCallback(async (event: MessageData): Promise<MessageResult> => {
|
||||
debug(`${event.from} => `, JSON.stringify(event))
|
||||
|
||||
// check event target
|
||||
if (event.target !== MESSAGE_TARGET_APP) return {
|
||||
success: false,
|
||||
code: 501,
|
||||
message: 'Target Error: ' + event.target,
|
||||
}
|
||||
|
||||
const method = methods?.[event.method]
|
||||
if (method != null) {
|
||||
return method(event.params, {
|
||||
from: event.from,
|
||||
event,
|
||||
}).then(data => {
|
||||
// debug(`${source} <= `, event.method, JSON.stringify(data))
|
||||
return {
|
||||
success: true,
|
||||
code: 200,
|
||||
data,
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
let message
|
||||
if (err instanceof Error) {
|
||||
message = err.message
|
||||
} else if (typeof err === 'string') {
|
||||
message = err
|
||||
} else {
|
||||
message = 'error: ' + JSON.stringify(err)
|
||||
}
|
||||
return {
|
||||
success: false,
|
||||
code: 500,
|
||||
message,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
code: 501,
|
||||
message: 'Unknown method: ' + event.method,
|
||||
}
|
||||
}
|
||||
}, [methods])
|
||||
|
||||
// connect to inject
|
||||
useEffect(() => {
|
||||
let destroyFunc: (() => void) | undefined
|
||||
|
||||
const serverObject = {
|
||||
server: window.parent, // openedWindow / window.parent / window.opener;
|
||||
origin: '*', // target-window's origin or *
|
||||
}
|
||||
const options = {}
|
||||
callServer(serverObject, options).then(e => {
|
||||
const { postMessage, listenMessage, destroy } = e
|
||||
postInjectMessage = postMessage
|
||||
destroyFunc = destroy
|
||||
|
||||
listenMessage((method, params, sendResponse) => {
|
||||
debug('inject => ', method, params)
|
||||
|
||||
const success = messageHandler(method, params, {
|
||||
from: 'inject',
|
||||
event: {
|
||||
method,
|
||||
params,
|
||||
},
|
||||
})
|
||||
sendResponse({
|
||||
success,
|
||||
code: success ? 200 : 500
|
||||
})
|
||||
})
|
||||
|
||||
debug('message ready')
|
||||
}).catch(console.error)
|
||||
|
||||
return () => {
|
||||
destroyFunc?.()
|
||||
}
|
||||
}, [messageHandler])
|
||||
|
||||
const extensionMessageCallback = useCallback((event: MessageData, sender: chrome.runtime.MessageSender, sendResponse: (response?: any) => void) => {
|
||||
debug((sender.tab != null) ? `tab ${sender.tab.url??''} => ` : 'extension => ', JSON.stringify(event))
|
||||
|
||||
// check event target
|
||||
if (!event || event.target !== MESSAGE_TARGET_APP) return
|
||||
|
||||
messageHandler(event.method, event.params, {
|
||||
from: 'extension',
|
||||
event,
|
||||
sender,
|
||||
const port = useMemo(() => {
|
||||
return chrome.runtime.connect(import.meta.env.VITE_EXTENSION_ID, {
|
||||
name: MESSAGE_TARGET_APP,
|
||||
})
|
||||
}, [messageHandler])
|
||||
|
||||
// listen for message
|
||||
useEffect(() => {
|
||||
chrome.runtime.onMessage.addListener(extensionMessageCallback)
|
||||
return () => {
|
||||
chrome.runtime.onMessage.removeListener(extensionMessageCallback)
|
||||
}, [])
|
||||
portMessageHandler = useMemo(() => {
|
||||
if (messageHandler && port) {
|
||||
const pmh = new PortMessageHandler<MessageData, MessageResult>(messageHandler, port)
|
||||
|
||||
//get tabId from url params
|
||||
let tabId = window.location.search.split('tabId=')[1]
|
||||
if (!tabId) {
|
||||
pmh.startListen()
|
||||
pmh.init('app')
|
||||
portMessageHandlerInit = true
|
||||
}else {
|
||||
pmh.startListen()
|
||||
pmh.init('app', parseInt(tabId))
|
||||
portMessageHandlerInit = true
|
||||
}
|
||||
|
||||
return pmh
|
||||
}
|
||||
}, [extensionMessageCallback])
|
||||
}, [messageHandler, port])
|
||||
|
||||
// connect to inject
|
||||
// useEffect(() => {
|
||||
// let destroyFunc: (() => void) | undefined
|
||||
|
||||
// const serverObject = {
|
||||
// server: window.parent, // openedWindow / window.parent / window.opener;
|
||||
// origin: '*', // target-window's origin or *
|
||||
// }
|
||||
// const options = {}
|
||||
// callServer(serverObject, options).then(e => {
|
||||
// const { postMessage, listenMessage, destroy } = e
|
||||
// postInjectMessage = postMessage
|
||||
// destroyFunc = destroy
|
||||
|
||||
// listenMessage((method, params, sendResponse) => {
|
||||
// debug('inject => ', method, params)
|
||||
|
||||
// const success = messageHandler(method, params, {
|
||||
// from: 'inject',
|
||||
// event: {
|
||||
// method,
|
||||
// params,
|
||||
// },
|
||||
// })
|
||||
// sendResponse({
|
||||
// success,
|
||||
// code: success ? 200 : 500
|
||||
// })
|
||||
// })
|
||||
|
||||
// debug('message ready')
|
||||
// }).catch(console.error)
|
||||
|
||||
// return () => {
|
||||
// destroyFunc?.()
|
||||
// }
|
||||
// }, [messageHandler])
|
||||
|
||||
// const extensionMessageCallback = useCallback((event: MessageData, sender: chrome.runtime.MessageSender, sendResponse: (response?: any) => void) => {
|
||||
// debug((sender.tab != null) ? `tab ${sender.tab.url??''} => ` : 'extension => ', JSON.stringify(event))
|
||||
|
||||
// // check event target
|
||||
// if (!event || event.target !== MESSAGE_TARGET_APP) return
|
||||
|
||||
// messageHandler(event.method, event.params, {
|
||||
// from: 'extension',
|
||||
// event,
|
||||
// sender,
|
||||
// })
|
||||
// }, [messageHandler])
|
||||
|
||||
// // listen for message
|
||||
// useEffect(() => {
|
||||
// chrome.runtime.onMessage.addListener(extensionMessageCallback)
|
||||
// return () => {
|
||||
// chrome.runtime.onMessage.removeListener(extensionMessageCallback)
|
||||
// }
|
||||
// }, [extensionMessageCallback])
|
||||
}
|
||||
|
||||
export default useMessageService
|
||||
|
Reference in New Issue
Block a user