type recvCallback = ( data : any ) => void ; export interface Client { Recv ( callback ) : void ; Send ( msg ) : void ; } type serverRecvCallback = ( client : Client , data : any ) => void ; export interface Server { Accept ( callback ) : void ; } export function NewExtensionServerMessage ( port ) { return new extensionServerMessage ( port ) ; } class extensionServerMessage implements Server { private port : string ; private acceptCallback : serverRecvCallback ; constructor ( port ) { this . port = port ; this . recv ( ) ; } private recv ( ) { chrome . runtime . onConnect . addListener ( ( port ) => { if ( port . name != this . port ) { return ; } port . onMessage . addListener ( ( request ) => { this . acceptCallback ( new extensionClientMessage ( port ) , request ) ; } ) ; } ) ; } public Accept ( callback ) { this . acceptCallback = callback ; } } abstract class msg { protected tag : string ; protected recvCallback : recvCallback ; constructor ( tag ) { this . tag = tag ; } public Recv ( callback ) { this . recvCallback = callback ; } } export function NewExtensionClientMessage ( tag ) { return new extensionClientMessage ( tag ) ; } class extensionClientMessage extends msg implements Client { private conn : chrome . runtime . Port ; constructor ( param ) { if ( typeof param === 'string' ) { super ( param as string ) ; this . connect ( ) ; } else { this . conn = param as chrome . runtime . Port ; } this . recv ( ) ; } private connect ( ) { this . conn = chrome . runtime . connect ( { name : this . tag } ) ; } private recv ( ) { this . conn . onMessage . addListener ( ( response ) => { this . recvCallback ( response ) ; } ) ; } public Send ( msg ) { this . conn . postMessage ( msg ) ; } } export function NewChromeServerMessage ( tag ) { return new chromeServerMessage ( tag ) ; } class chromeServerMessage implements Server { private tag : string ; private acceptCallback : serverRecvCallback ; constructor ( tag ) { this . tag = tag ; this . recv ( ) ; } private recv ( ) { window . addEventListener ( 'message' , ( event ) => { if ( event . data . tag == this . tag && event . data . conn_tag && event . data . source == "client" ) { this . acceptCallback ( new chromeClientMessage ( this . tag , event . data . conn_tag ) , event . data . msg ) ; } } ) ; } public Accept ( callback ) { this . acceptCallback = callback ; } } export function NewChromeClientMessage ( tag ) { return new chromeClientMessage ( tag ) ; } class chromeClientMessage extends msg implements Client { private source : string ; private connTag : number ; constructor ( tag , conn ? ) { if ( conn !== undefined ) { super ( tag ) ; this . connTag = conn ; this . source = "server" ; } else { super ( tag ) ; this . connect ( ) ; this . source = "client" ; } } private connect ( ) { this . connTag = Math . random ( ) ; window . addEventListener ( 'message' , ( event ) => { if ( event . data . tag == this . tag && event . data . conn_tag == this . connTag && event . data . source == "server" ) { this . recvCallback && this . recvCallback ( event . data . msg ) ; } } ) ; } public Send ( msg ) { window . postMessage ( { tag : this . tag , conn_tag : this . connTag , msg : msg , source : this . source } , '*' ) ; } }