Last active
May 16, 2021 14:06
-
-
Save oeway/b3588952e26fab4f7ea1e8b84264b98c to your computer and use it in GitHub Desktop.
Connecting to another ImJoy plugin in the same browser via broadcast channel and webRTC (only works with Chrome and FireFox)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Contains the routines loaded by the plugin iframe under web-browser | |
* in case when worker failed to initialize | |
* | |
* Initializes the web environment version of the platform-dependent | |
* connection object for the plugin site | |
*/ | |
import { connectRPC } from "./pluginCore.js"; | |
import { RPC, API_VERSION } from "./rpc.js"; | |
import { MessageEmitter, randId, normalizeConfig } from "./utils.js"; | |
export { setupRPC, waitForInitialization } from "./main.js"; | |
export { version as VERSION } from "../package.json"; | |
export { RPC, API_VERSION }; | |
export class Connection extends MessageEmitter { | |
constructor(config) { | |
super(config && config.debug); | |
this.config = config || {}; | |
this.config.channel = this.config.channel || "imjoy_webrtc_channel"; | |
this.peer_id = this.config.channel; | |
this.broadcastChannel = new BroadcastChannel(this.config.channel); | |
this.broadcastChannel.onmessage = e => { | |
const data = e.data; | |
if (data.peer_id === this.peer_id) { | |
this._fire(data.type, data); | |
} else if (this.config.debug) { | |
console.log( | |
`connection peer id mismatch ${data.peer_id} !== ${this.peer_id}` | |
); | |
} | |
}; | |
if (this.config.isPlugin) { | |
this.connect(); | |
} | |
} | |
connect() { | |
if (this.config.isPlugin) { | |
this._fire("connected"); | |
this.once("initialize", () => { | |
if (!this.rpc) { | |
this.rpc = connectRPC(this, this.config); | |
} else { | |
this.rpc.once("remoteReady", () => { | |
// this.rpc.sendInterface(); | |
const api = this.rpc.getRemote() || {}; | |
window.dispatchEvent( | |
new CustomEvent("imjoy_remote_api_ready", { detail: api }) | |
); | |
}); | |
} | |
this.emit({ | |
type: "initialized", | |
config: this.config, | |
origin: "*", | |
peer_id: this.peer_id | |
}); | |
}); | |
this.emit({ | |
type: "imjoyRPCReady", | |
config: this.config, | |
peer_id: this.peer_id | |
}); | |
} else { | |
this.emit({ | |
type: "initialize", | |
config: this.config, | |
peer_id: this.peer_id | |
}); | |
} | |
} | |
reset() { | |
this._event_handlers = {}; | |
this._once_handlers = {}; | |
} | |
execute() { | |
throw new Error("Execution is not allowed for socketio connection"); | |
} | |
disconnect() { | |
this._fire("beforeDisconnect"); | |
this.socket.disconnect(); | |
this.init(); | |
this._fire("disconnected"); | |
} | |
emit(data) { | |
data.peer_id = this.peer_id; | |
this.broadcastChannel.postMessage(data); | |
} | |
} | |
export function connectToPeer(config) { | |
config = config || {}; | |
config.name = config.name || randId(); | |
config = normalizeConfig(config); | |
return new Promise((resolve, reject) => { | |
const handleEvent = e => { | |
const api = e.detail; | |
if (config.expose_api_globally) { | |
window.api = api; | |
} | |
// imjoy plugin api | |
resolve(api); | |
window.removeEventListener("imjoy_remote_api_ready", handleEvent); | |
}; | |
window.addEventListener("imjoy_remote_api_ready", handleEvent); | |
config = config || {}; | |
config.dedicated_thread = false; | |
config.lang = "javascript"; | |
config.api_version = API_VERSION; | |
config.isPlugin = true; | |
new Connection(config); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
loadImJoyBasicApp({ | |
base_url: "/", | |
debug: true, | |
process_url_query: true, | |
show_window_title: true, | |
show_progress_bar: true, | |
show_empty_window: true, | |
hide_about_imjoy: false, | |
menu_style: { position: "absolute", right: 0, top: 0, zIndex: 999 }, | |
window_style: { width: "100%", height: "calc(100% - 30px)" }, | |
main_container: null, | |
menu_container: "menu-container", | |
window_manager_container: "window-container", | |
imjoy_api: {}, | |
}).then(async app => { | |
const api = app.imjoy.api; | |
const conn = new imjoyRPCWebRTC.Connection({channel: '123'}); | |
const p = await app.imjoy.pm.connectPlugin(conn); | |
console.log('==============>', p) | |
p.api.setup('hello') | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script | |
type="text/javascript" | |
onload="imjoyRPCWebRTC.connectToPeer({channel: '123'}).then((api)=>{api.export({'setup': (msg)=>{document.body.insertAdjacentHTML( 'beforeend', msg );}})})" | |
src="http://localhost:9090/imjoy-rpc-webrtc.js" | |
></script> | |
<style> | |
body { | |
overscroll-behavior: contain; | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Contains the routines loaded by the plugin iframe under web-browser | |
* in case when worker failed to initialize | |
* | |
* Initializes the web environment version of the platform-dependent | |
* connection object for the plugin site | |
*/ | |
import { connectRPC } from "./pluginCore.js"; | |
import { RPC, API_VERSION } from "./rpc.js"; | |
import { MessageEmitter, randId, normalizeConfig } from "./utils.js"; | |
import adapter from 'webrtc-adapter'; | |
import { serialize, deserialize } from 'bson'; | |
export { setupRPC, waitForInitialization } from "./main.js"; | |
export { version as VERSION } from "../package.json"; | |
export { RPC, API_VERSION }; | |
export class Connection extends MessageEmitter { | |
constructor(config) { | |
super(config && config.debug); | |
this.config = config || {}; | |
this.config.channel = this.config.channel || 'imjoy_webrtc_channel'; | |
this.peer_id = this.config.channel; | |
this.dc = null | |
this.pc = null | |
this.broadcastChannel = new BroadcastChannel(this.config.channel); | |
this.broadcastChannel.onmessage = e => { | |
const msg = JSON.parse(e.data); | |
if(msg.sdp){ | |
if(!this.pc || this.pc.iceConnectionState === 'closed' || this.pc.iceConnectionState === 'connected'){ | |
this.initPeerConnection() | |
} | |
const pc = this.pc; | |
pc.setRemoteDescription(new RTCSessionDescription(msg.sdp)) | |
.then(() => pc.signalingState == "stable" || pc.createAnswer() | |
.then(answer => pc.setLocalDescription(answer)) | |
.then(() => this.broadcast({ | |
sdp: pc.localDescription | |
}))) | |
.catch(console.error) | |
} | |
else if(msg.candidate){ | |
const pc = this.pc; | |
pc.addIceCandidate(new RTCIceCandidate(msg.candidate)).catch(console.error); | |
} | |
}; | |
this.initPeerConnection() | |
if(this.config.isPlugin){ | |
this.connect() | |
} | |
} | |
initDataChannel(dc) { | |
dc.onopen = e => { | |
if(this.config.isPlugin && dc.readyState ==='open'){ | |
this._fire("connected"); | |
this.once("initialize", () => { | |
if (!this.rpc) { | |
this.rpc = connectRPC(this, this.config); | |
} else { | |
this.rpc.once("remoteReady", () => { | |
// this.rpc.sendInterface(); | |
const api = this.rpc.getRemote() || {}; | |
window.dispatchEvent( | |
new CustomEvent("imjoy_remote_api_ready", { detail: api }) | |
); | |
}); | |
} | |
this.emit({ | |
type: "initialized", | |
config: this.config, | |
origin: '*', | |
peer_id: this.peer_id | |
}); | |
}); | |
dc.send(serialize({ | |
type: "imjoyRPCReady", | |
config: this.config, | |
peer_id: this.peer_id | |
})); | |
} | |
else{ | |
dc.send(serialize({ | |
type: "initialize", | |
config: this.config, | |
peer_id: this.peer_id | |
})) | |
} | |
}; | |
dc.onclose = e => {this._fire("disconnected");}; | |
dc.onmessage = e => { | |
const data = deserialize(e.data); | |
if (data.peer_id === this.peer_id) { | |
this._fire(data.type, data); | |
} else if (this.config.debug) { | |
console.log( | |
`connection peer id mismatch ${data.peer_id} !== ${this.peer_id}` | |
); | |
} | |
} | |
}; | |
initPeerConnection(){ | |
if(this.pc) this.pc.close(); | |
const pc = new RTCPeerConnection() | |
pc.ondatachannel = e => this.initDataChannel(this.dc = e.channel); | |
pc.oniceconnectionstatechange = e => { | |
if(pc.iceConnectionState === 'connected'){ | |
if(this.config.isPlugin){ | |
this.dc = this.pc.createDataChannel("plugin-channel") | |
this.initDataChannel(this.dc); | |
} | |
} | |
console.log('peer connection: ', pc.iceConnectionState); | |
} | |
pc.onicecandidate = e => this.broadcast({ | |
candidate: e.candidate | |
}); | |
pc.onnegotiationneeded = e => pc.createOffer() | |
.then(offer => pc.setLocalDescription(offer)) | |
.then(() => this.broadcast({ | |
sdp: pc.localDescription | |
})) | |
.catch(console.error); | |
this.pc = pc; | |
} | |
broadcast(obj){ | |
this.broadcastChannel.postMessage(JSON.stringify(obj)); | |
} | |
connect() { | |
this.dc = this.pc.createDataChannel("plugin-channel") | |
this.initDataChannel(this.dc); | |
} | |
reset() { | |
this._event_handlers = {}; | |
this._once_handlers = {}; | |
} | |
execute() { | |
throw new Error("Execution is not allowed for socketio connection"); | |
} | |
disconnect() { | |
this._fire("beforeDisconnect"); | |
this.socket.disconnect(); | |
this.init(); | |
this._fire("disconnected"); | |
} | |
emit(data) { | |
data.peer_id = this.peer_id; | |
this.dc.send(serialize(data)); | |
} | |
} | |
export function connectToPeer(config) { | |
config = config || {}; | |
config.name = config.name || randId(); | |
config = normalizeConfig(config); | |
return new Promise((resolve, reject) => { | |
const handleEvent = e => { | |
const api = e.detail; | |
if (config.expose_api_globally) { | |
window.api = api; | |
} | |
// imjoy plugin api | |
resolve(api); | |
window.removeEventListener("imjoy_remote_api_ready", handleEvent); | |
}; | |
window.addEventListener("imjoy_remote_api_ready", handleEvent); | |
config = config || {}; | |
config.dedicated_thread = false; | |
config.lang = "javascript"; | |
config.api_version = API_VERSION; | |
config.isPlugin = true; | |
new Connection(config); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment