1
0
mirror of https://github.com/c9fe/22120.git synced 2024-11-10 04:52:43 +01:00
22120/protocol.js

152 lines
3.8 KiB
JavaScript
Raw Normal View History

import {DEBUG, context} from './common.js';
2021-11-03 05:51:04 +01:00
const ROOT_SESSION = "browser";
// actually we use 'tot' but in chrome.debugger.attach 'tot' is
// not a supported version string
const VERSION = "1.3";
function promisify(context, name, err) {
return async function(...args) {
let resolver, rejector;
const pr = new Promise((res,rej) => ([resolver, rejector] = [res,rej]));
args.push(promisifiedCallback);
context[name](...args);
return pr;
function promisifiedCallback(...result) {
let error = err(name);
if ( !! error ) {
return rejector(error);
}
return resolver(...result);
}
}
}
let Ws, Fetch;
async function loadDependencies() {
if ( context == 'extension' ) {
// no need to do anything here
} else if ( context == 'node' ) {
const {default:ws} = await import('ws');
const {default:nodeFetch} = await import('node-fetch');
Ws = ws;
Fetch = nodeFetch;
}
}
export async function connect({port:port = 9222} = {}) {
if ( ! Ws || ! Fetch ) {
await loadDependencies();
}
try {
const {webSocketDebuggerUrl} = await Fetch(`http://localhost:${port}/json/version`).then(r => r.json());
const socket = new Ws(webSocketDebuggerUrl);
const Resolvers = {};
2021-11-03 05:51:04 +01:00
const Handlers = {};
socket.on('message', handle);
let id = 0;
2021-11-03 05:51:04 +01:00
let resolve;
const promise = new Promise(res => resolve = res);
2021-11-03 05:51:04 +01:00
socket.on('open', () => resolve());
2021-11-03 05:51:04 +01:00
await promise;
2021-11-03 05:51:04 +01:00
return {
send,
on, ons,
close
2021-11-03 05:51:04 +01:00
}
async function send(method, params = {}, sessionId) {
const message = {
method, params, sessionId,
id: ++id
};
if ( ! sessionId ) {
delete message[sessionId];
2021-11-03 05:51:04 +01:00
}
const key = `${sessionId||ROOT_SESSION}:${message.id}`;
let resolve;
const promise = new Promise(res => resolve = res);
Resolvers[key] = resolve;
socket.send(JSON.stringify(message));
DEBUG && console.log("Sent", message);
return promise;
2021-11-03 05:51:04 +01:00
}
async function handle(message) {
const stringMessage = message;
message = JSON.parse(message);
if ( message.error ) {
console.warn(message);
2021-11-03 05:51:04 +01:00
}
const {sessionId} = message;
const {method, params} = message;
const {id, result} = message;
if ( id ) {
const key = `${sessionId||ROOT_SESSION}:${id}`;
const resolve = Resolvers[key];
if ( ! resolve ) {
console.warn(`No resolver for key`, key, stringMessage.slice(0,140));
} else {
Resolvers[key] = undefined;
2021-11-03 05:51:04 +01:00
try {
await resolve(result);
2021-11-03 05:51:04 +01:00
} catch(e) {
console.warn(`Resolver failed`, e, key, stringMessage.slice(0,140), resolve);
2021-11-03 05:51:04 +01:00
}
}
} else if ( method ) {
const listeners = Handlers[method];
if ( Array.isArray(listeners) ) {
for( const func of listeners ) {
2021-11-03 05:51:04 +01:00
try {
func({message, sessionId});
2021-11-03 05:51:04 +01:00
} catch(e) {
console.warn(`Listener failed`, method, e, func.toString().slice(0,140), stringMessage.slice(0,140));
2021-11-03 05:51:04 +01:00
}
}
}
} else {
console.warn(`Unknown message on socket`, message);
2021-11-03 05:51:04 +01:00
}
}
2021-11-03 05:51:04 +01:00
function on(method, handler) {
let listeners = Handlers[method];
if ( ! listeners ) {
Handlers[method] = listeners = [];
2021-11-03 05:51:04 +01:00
}
listeners.push(wrap(handler));
}
2021-11-03 05:51:04 +01:00
function ons(method, handler) {
let listeners = Handlers[method];
if ( ! listeners ) {
Handlers[method] = listeners = [];
2021-11-03 05:51:04 +01:00
}
listeners.push(handler);
}
2021-11-03 05:51:04 +01:00
function close() {
socket.close();
}
2021-11-03 05:51:04 +01:00
function wrap(fn) {
return ({message, sessionId}) => fn(message.params)
2021-11-03 05:51:04 +01:00
}
} catch(e) {
console.log("Error communicating with browser", e);
process.exit(1);
2021-11-03 05:51:04 +01:00
}
}