UNPKG

@ng1005/chrome-extension-common

Version:

chrome扩展通用库--消息与storage

278 lines (274 loc) 9.2 kB
import MessageEventBus from "./MessageEventBus"; import {isBackgroundScript, isContentScript, isFunctionAsync, isPopupScript, isPromise} from '../utils/Utils' import ResponseUtils, { SendMessage,ResponseMessage } from "../utils/ResponseUtils"; import IMessageInterface from "../interface/IMessageInterface"; import { KeyValue } from "../types/KeyValue"; interface SendMessageBridge{ script:string;//发送方 bridgeType:string;//桥接消息类型---统一 type:string;//消息类型---动态 message:any;//消息数据 } export class RuntimeEventBus extends MessageEventBus implements IMessageInterface{ script:string='content' types:KeyValue={ content2AllTabs:'_message_bridge_content2AllTabs_', } constructor (script?:string) { super(); let defaultScript='content' if(isBackgroundScript()){ defaultScript='background' }else if(isPopupScript()){ defaultScript='popup' } this.script=script||defaultScript;//当前脚本 this.listener() this.listenerBridge() } listener(): void { let _this=this chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){ if(sender.id!=chrome.runtime.id){//不属于当前插件 return; } let script=request.script if(_this.script!==script){//不是当前脚本的请求 return; } _this.handler(request,sender,sendResponse) return true; }); } /** * content2AllTabs需要中转 */ listenerBridge(){ if(this.script==='background'){ let _this=this // console.log('listener bridge-----') chrome.runtime.onMessage.addListener(function(request:SendMessageBridge,sender,sendResponse){ if(sender.id!=chrome.runtime.id&&!_this.crossExtension){//不属于当前插件 return; } let script=request.script if(_this.script!==script){//不是当前脚本的请求 return; } // console.log('bridge-----',_this.script,request) switch (request.bridgeType) { case _this.types.content2AllTabs: _this.$emitAllTabs(request.type,...request.message) break; default: break; } return true; }); } } /** * 消息处理 * @param {*} request:any * @param {*} sender:chrome.runtime.MessageSender * @param {*} sendResponse:any */ async handler(request:SendMessage,sender:chrome.runtime.MessageSender,sendResponse:any){ let type=request.type||''//$emit提交时的事件 let args=request.message let _this=this; let handler = _this._events.get(type)//所有该类型的函数集合 if(!handler)return;//无任何监听则退出 if (Array.isArray(handler)) { // 是数组,说明有多个监听者,需要依次触发里边的函数 for (let i = 0; i < handler.length; ++i) { let res:any='' if(isFunctionAsync(handler[i])){ handler[i].call(_this, ...args,sender,sendResponse).then((data:any)=>{ sendResponse(ResponseUtils.success(data)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else{ res=handler[i].call(_this, ...args,sender,sendResponse) if(isPromise(res)){ res.then((r:any)=>{ sendResponse(ResponseUtils.success(r)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else if(res){ sendResponse(ResponseUtils.success(res))//发送返回值来实现$emit中Promise返回内容 }else{ sendResponse(ResponseUtils.error('未知错误'))//发送返回值来实现$emit中Promise返回内容 } } } } else { // 单个函数的情况直接触发即可 // let res=await handler.call(_this, ...args,sender,sendResponse) let res:any='' if(isFunctionAsync(handler)){ handler.call(_this, ...args,sender,sendResponse).then((data:any)=>{ sendResponse(ResponseUtils.success(data)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else{ res=handler.call(_this, ...args,sender,sendResponse) if(isPromise(res)){ res.then((r:any)=>{ sendResponse(ResponseUtils.success(r)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else if(res){ sendResponse(ResponseUtils.success(res))//发送返回值来实现$emit中Promise返回内容 }else{ sendResponse(ResponseUtils.error('未知错误'))//发送返回值来实现$emit中Promise返回内容 } } } } $emitContent(type: string, ...args: any): Promise<any> { let _this=this let _script='content'; if(_this.script===_script){// return new Promise((resolve,reject)=>{ chrome.runtime.sendMessage({ script:'content',//发送给background的 type: type,//事件名 message: args },(response:ResponseMessage)=>{ if(ResponseUtils.isSuccess(response)){ resolve(response.data) }else{ reject(response.message) } }); }) } return new Promise((resolve,reject)=>{//调整成Promise _this.getCurrentTabs((tabs:any)=>{ const tabId=tabs.length ? tabs[0].id: null if(!tabId){ reject('找到激活的tab') } const message:SendMessage={ script:_script, type: type,//事件名 message: args } // console.log('ssss',message) chrome.tabs.sendMessage(tabId, message, function(response){ // console.log('response=====',response); if(ResponseUtils.isSuccess(response)){ resolve(response.data) }else{ reject(response.message) } }); }) }) } $emitBackground(type: string, ...args: any): Promise<any> { let _this=this let _script='background'; return new Promise((resolve,reject)=>{ const message:SendMessage={ script:_script, type: type,//事件名 message: args } chrome.runtime.sendMessage(message,(response:ResponseMessage)=>{ if(ResponseUtils.isSuccess(response)){ resolve(response.data) }else{ reject(response.message) } }); }) } $emitPopup(type: string, ...args: any): Promise<any> { let _this=this let _script='popup'; return new Promise((resolve,reject)=>{ const message:SendMessage={ script:_script, type: type,//事件名 message: args } chrome.runtime.sendMessage(message,(response:ResponseMessage)=>{ if(ResponseUtils.isSuccess(response)){ resolve(response.data) }else{ reject(response.message) } }); }) } $emitWindow(type: string, ...args: any): Promise<any> { switch (this.script) {//只支持contentScript case 'content': return new Promise((resolve,reject)=>{ window.postMessage({ script:'window', type:type, message:args }) }) default: throw new Error("当前页面不支持发送消息给window."); } } $emitAllTabs(type: string, ...args: any): Promise<any> { let _this=this let _script='content'; if(_this.script===_script){//contentScript本身 return new Promise((resolve,reject)=>{ chrome.runtime.sendMessage({ bridgeType:_this.types.content2AllTabs, script:'background', type: type,//事件名 message: args },(response:ResponseMessage)=>{ // console.log('response=====',response); if(ResponseUtils.isSuccess(response)){ resolve(response.data) }else{ reject(response.message) } }); }) } return new Promise((resolve,reject)=>{//调整成Promise _this.getTabs((tabs:any)=>{ // console.log('tabs----',tabs,args) if(tabs&&Array.isArray(tabs)&&tabs.length>0){ for(let i=0;i<tabs.length;i++){ const tabId=tabs[i].id|| null const message:SendMessage={ script:_script, type: type,//事件名 message: args } chrome.tabs.sendMessage(tabId, message, function(response){ // console.log('response=====',response); if(i===tabs.length){//最后一个发送完成 if(ResponseUtils.isSuccess(response)){ resolve(response.data) }else{ reject(response.message) } } }); } }else{ reject('找到激活的tab') } },{})//{windowType:'normal'} }) } } const $bus=new RuntimeEventBus() export default $bus