Skip to content

Instantly share code, notes, and snippets.

@lutangar
Created June 3, 2020 13:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lutangar/fd8c0c486d85f8e8c007080600bb9715 to your computer and use it in GitHub Desktop.
Save lutangar/fd8c0c486d85f8e8c007080600bb9715 to your computer and use it in GitHub Desktop.
An attempt at creating a postMessage window communication class implementing the Port interface
type ResponseCallback = (response: object) => void;
type PortCallback = (port: browser.runtime.Port) => void;
interface EventListenerRegistry {
listeners: [];
}
class WindowPort implements browser.runtime.Port {
private readonly window: Window;
private readonly targetOrigin: string;
private readonly transfer: Transferable[] | undefined;
public error: Error | undefined;
public name: string;
public onDisconnect: WebExtEvent<(port: browser.runtime.Port) => void>;
public onMessage: WebExtEvent<ResponseCallback>;
public sender: browser.runtime.MessageSender | undefined;
private disconnectCallback: PortCallback | undefined;
constructor(
window: Window,
name: string,
targetOrigin: string = '*',
transfer?: Transferable[]
) {
this.window = window;
this.name = name;
this.targetOrigin = targetOrigin;
this.transfer = transfer;
this.onMessage = {
addListener: (cb: ResponseCallback) => {
this.window.addEventListener('message', event => {
if (
// event.source == window.parent &&
event.data
// && event.data.direction == 'from-page-script'
) {
console.log(
'WindowPostMessagePort: Content script received message:',
event
);
cb(event.data);
}
});
},
removeListener: (cb: ResponseCallback) => {
// @todo this is not right need reference to the callback previously added
window.removeEventListener('message', cb);
},
hasListener: (cb: ResponseCallback) => {
// @todo
return true;
}
};
this.onDisconnect = {
addListener: (cb: PortCallback) => {
this.disconnectCallback = cb;
// @todo onMessage with a disconnect info call the callback
},
removeListener: (cb: PortCallback) => {
// @todo this is not right need reference to the callback previously added
window.removeEventListener('message', cb);
},
hasListener: (cb: PortCallback) => {
// @todo
return true;
}
};
}
public disconnect = () => {
// @todo remove all event listeners
this.window.removeEventListener('message', () => {});
// trigger onDisconnect callback if exists
if (this.disconnectCallback) {
this.disconnectCallback(this);
}
};
postMessage = (message: object) => {
this.window.postMessage(
{
...message
},
this.targetOrigin,
this.transfer
);
};
public toString = (): string => {
return `WindowPostMessagePort:(name: ${this.name}, window: ${this.window.name})`;
};
}
const connect = (
extensionId?: string,
connectInfo?: {
/** Will be passed into onConnect for processes that are listening for the connection event. */
name: string;
/**
* Whether the TLS channel ID will be passed into onConnectExternal for processes that are listening for the
* connection event.
*/
includeTlsChannelId?: boolean;
}
): browser.runtime.Port => {
const port = new WindowPort(window, name);
port.postMessage(`Message de la page ${extensionId}, ${connectInfo.name}`);
return port;
};
export default connect;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment