148 lines
3.6 KiB
JavaScript
148 lines
3.6 KiB
JavaScript
export default ({ browserName, browserInfo }, { evaluate, addScriptToEvaluateOnNewDocument, pageLoadPromise }) => {
|
|
const injection = `(() => {
|
|
if (window.Gluon) return;
|
|
let onIPCReply = {}, ipcListeners = {};
|
|
window.Gluon = {
|
|
versions: {
|
|
gluon: '${process.versions.gluon}',
|
|
builder: '${'GLUGUN_VERSION' === 'G\LUGUN_VERSION' ? 'nothing' : 'Glugun GLUGUN_VERSION'}',
|
|
node: '${process.versions.node}',
|
|
browser: '${browserInfo.product.split('/')[1]}',
|
|
browserType: '${browserName.startsWith('Firefox') ? 'firefox' : 'chromium'}',
|
|
product: '${browserName}',
|
|
|
|
js: {
|
|
node: '${process.versions.v8}',
|
|
browser: '${browserInfo.jsVersion}'
|
|
},
|
|
|
|
embedded: {
|
|
node: ${'EMBEDDED_NODE' === 'true' ? 'true' : 'false'},
|
|
browser: false
|
|
}
|
|
},
|
|
|
|
ipc: {
|
|
send: async (type, data, id = undefined) => {
|
|
id = id ?? Math.random().toString().split('.')[1];
|
|
|
|
window.Gluon.ipc._send(JSON.stringify({
|
|
id,
|
|
type,
|
|
data
|
|
}));
|
|
|
|
if (id) return;
|
|
|
|
const reply = await new Promise(res => {
|
|
onIPCReply[id] = msg => res(msg);
|
|
});
|
|
|
|
return reply;
|
|
},
|
|
|
|
on: (type, cb) => {
|
|
if (!ipcListeners[type]) ipcListeners[type] = [];
|
|
ipcListeners[type].push(cb);
|
|
},
|
|
|
|
removeListener: (type, cb) => {
|
|
if (!ipcListeners[type]) return false;
|
|
ipcListeners[type].splice(ipcListeners[type].indexOf(cb), 1);
|
|
},
|
|
|
|
_receive: async msg => {
|
|
const { id, type, data } = msg;
|
|
|
|
if (onIPCReply[id]) {
|
|
onIPCReply[id]({ type, data });
|
|
delete onIPCReply[id];
|
|
return;
|
|
}
|
|
|
|
if (ipcListeners[type]) {
|
|
let reply;
|
|
|
|
for (const cb of ipcListeners[type]) {
|
|
const ret = await cb(data);
|
|
if (!reply) reply = ret; // use first returned value as reply
|
|
}
|
|
|
|
if (reply) return Gluon.ipc.send('reply', reply, id); // reply with wanted reply
|
|
}
|
|
|
|
Gluon.ipc.send('pong', null, id);
|
|
},
|
|
|
|
_send: window._gluonSend
|
|
},
|
|
};
|
|
|
|
delete window._gluonSend;
|
|
})();`;
|
|
|
|
evaluate({
|
|
expression: injection
|
|
});
|
|
|
|
addScriptToEvaluateOnNewDocument({
|
|
source: injection
|
|
});
|
|
|
|
let onIPCReply = {}, ipcListeners = {};
|
|
const sendToWindow = async (type, data, id = undefined) => {
|
|
id = id ?? Math.random().toString().split('.')[1];
|
|
|
|
await pageLoadPromise; // wait for page to load before sending, otherwise messages won't be heard
|
|
evalInWindow(`window.Gluon.ipc._receive(${JSON.stringify({
|
|
id,
|
|
type,
|
|
data
|
|
})})`);
|
|
|
|
if (id) return; // we are replying, don't expect reply back
|
|
|
|
const reply = await new Promise(res => {
|
|
onIPCReply[id] = msg => res(msg);
|
|
});
|
|
|
|
return reply;
|
|
};
|
|
|
|
const onWindowMessage = async ({ id, type, data }) => {
|
|
if (onIPCReply[id]) {
|
|
onIPCReply[id]({ type, data });
|
|
delete onIPCReply[id];
|
|
return;
|
|
}
|
|
|
|
if (ipcListeners[type]) {
|
|
let reply;
|
|
|
|
for (const cb of ipcListeners[type]) {
|
|
const ret = await cb(data);
|
|
if (!reply) reply = ret; // use first returned value as reply
|
|
}
|
|
|
|
if (reply) return sendToWindow('reply', reply, id); // reply with wanted reply
|
|
}
|
|
|
|
sendToWindow('pong', null, id); // send simple pong to confirm
|
|
};
|
|
|
|
return [ onWindowMessage, () => evaluate({
|
|
expression: injection
|
|
}), {
|
|
on: (type, cb) => {
|
|
if (!ipcListeners[type]) ipcListeners[type] = [];
|
|
ipcListeners[type].push(cb);
|
|
},
|
|
|
|
removeListener: (type, cb) => {
|
|
if (!ipcListeners[type]) return false;
|
|
ipcListeners[type].splice(ipcListeners[type].indexOf(cb), 1);
|
|
},
|
|
|
|
send: sendToWindow,
|
|
} ];
|
|
}; |