UNPKG

@ng1005/chrome-extension-common

Version:

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

208 lines (202 loc) 6.45 kB
import MessageEventBus from "./MessageEventBus"; import {isBackgroundScript, isPopupScript} from '../utils/Utils' import { SendMessage } from "../utils/ResponseUtils"; import IMessageInterface from '../interface/IMessageInterface' export class PortEventBus extends MessageEventBus implements IMessageInterface{ script='content'; port:chrome.runtime.Port|undefined portTab:chrome.runtime.Port|undefined popupListener:boolean=false; constructor (script?:string) { super(); let defaultScript='content' if(isBackgroundScript()){ defaultScript='background' }else if(isPopupScript()){ defaultScript='popup' } this.script=script||defaultScript;//当前脚本 this.connect() } /** * 链接(监听) */ connect(){ let _this=this; if(['popup','background'].indexOf(_this.script)>-1){//当是background和popup的时候就是初始化和当前tab的连接 _this.getCurrentTabs((tabs:any)=>{ const tabId=tabs.length ? tabs[0].id: null if(tabId){// _this.portTab = chrome.tabs.connect(tabId, {name: _this.script}); // console.log('_this.portTab---connect---',tabId,this.portTab) _this.portTab.onMessage.addListener(function(requests) { // console.log('port onMessage---',requests) _this.handler(requests) }); _this.popupListener=true; }else{//没有activeId----如果是background.js中$portBus正常获取不到tabId this.popListener();//监听tabs.onActivated } }) } //初始化和popup和background的连接 // 监听长连接 let port=chrome.runtime.connect({name:this.script}); this.port=port; // console.log('connect------') this.port.onMessage.addListener(function(requests) { // console.log('port onMessage---',requests) _this.handler(requests) }); this.listener() return this } /** * contentScript监听 */ popListener(){ let _this=this; chrome.tabs.onActivated.addListener( ()=>{// if(this.popupListener){ return;//已经监听了 } _this.getCurrentTabs((tabs:any)=>{ const tabId=tabs.length ? tabs[0].id: null _this.popupListener=true; _this.portTab = chrome.tabs.connect(tabId, {name: _this.script}); // console.log('_this.portTab---popListener-----',this.portTab) _this.portTab.onMessage.addListener(function(requests) { // console.log('port onMessage---',requests) _this.handler(requests) }); }); }, ) return this } /** * 需要监听用来接收消息 */ listener(){ let _this=this; chrome.runtime.onConnect.addListener((port)=>{ port.onMessage.addListener((requests)=>{ // console.log('port onMessage---',requests) _this.handler(requests) }) }) return this } /** * 检查链接 */ checkConnect(){ // console.log('this.connect----',this.port) if(this.port==undefined||this.portTab==undefined||this.port.name==''){//空对象的时候自动连接 this.connect(); } return this } /** * 消息处理 * @param {*} request */ async handler(request:SendMessage){ let type=request.type||''//$emit提交时的事件 let args=request.message if(this.script!==request.script){ return; } let _this=this; let handler = _this._events.get(type)//所有该类型的函数集合 if(!handler)return;//无任何监听则退出 let res=''; if (Array.isArray(handler)) { // 是数组,说明有多个监听者,需要依次触发里边的函数 for (let i = 0; i < handler.length; ++i) { //用call代替apply----有些消息需要确认tabId // handler.call(_this, ...args,sender,sendResponse).then(res=>{ let res=await handler[i].call(_this, ...args) //这是无效的发送消息都是通过port port.postMessage({text: '这里并没有sendResponse!'}); } } else { // 单个函数的情况直接触发即可 //用call代替apply----有些消息需要确认tabId // handler.call(_this, ...args,sender,sendResponse).then(res=>{ let res=await handler.call(_this, ...args) //这是无效的发送消息都是通过port port.postMessage({text: '这里并没有sendResponse!'}); } return this } $emitContent(type: string, ...args: any): Promise<any> { if(this.script=='content'){ return this.$emit(type,...args); } return new Promise((resolve,reject)=>{ this.checkConnect(); // console.log('this.portTab-----',this._script,this.portTab) if(this.portTab){ let message:SendMessage={ script:'content', type: type,//事件名 message: args } this.portTab.postMessage(message); }else{ reject('portTab is undefine!') return; // console.log('portTab is undefine!') } resolve('') }) } $emitBackground(type: string, ...args: any): Promise<any> { if(this.script==='background'){ return this.$emit(type,...args); } return new Promise((resolve,reject)=>{ this.checkConnect(); // console.log('this.portTab-----',this._script,this.portTab) if(this.port){ let message:SendMessage={ script:'background', type: type,//事件名 message: args } this.port.postMessage(message); }else{ console.log('port is undefine!') } resolve('') }) } $emitPopup(type: string, ...args: any): Promise<any> { if(this.script==='popup'){ return this.$emit(type,...args); } return new Promise((resolve,reject)=>{ this.checkConnect(); // console.log('this.portTab-----',this._script,this.portTab) if(this.port){ let message:SendMessage={ script:'popup', type: type,//事件名 message: args } this.port.postMessage(message); }else{ console.log('port is undefine!') } resolve('') }) } $emitWindow(type: string, ...args: any): Promise<any> { throw new Error("Method not support."); } $emitAllTabs(type: string, ...args: any): Promise<any> { throw new Error("Method not support."); } } const $bus=new PortEventBus() export default $bus