Rename to hkt.sh
This commit is contained in:
92
node_modules/chrome-remote-interface/lib/api.js
generated
vendored
Normal file
92
node_modules/chrome-remote-interface/lib/api.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
|
||||
function arrayToObject(parameters) {
|
||||
const keyValue = {};
|
||||
parameters.forEach((parameter) =>{
|
||||
const name = parameter.name;
|
||||
delete parameter.name;
|
||||
keyValue[name] = parameter;
|
||||
});
|
||||
return keyValue;
|
||||
}
|
||||
|
||||
function decorate(to, category, object) {
|
||||
to.category = category;
|
||||
Object.keys(object).forEach((field) => {
|
||||
// skip the 'name' field as it is part of the function prototype
|
||||
if (field === 'name') {
|
||||
return;
|
||||
}
|
||||
// commands and events have parameters whereas types have properties
|
||||
if (category === 'type' && field === 'properties' ||
|
||||
field === 'parameters') {
|
||||
to[field] = arrayToObject(object[field]);
|
||||
} else {
|
||||
to[field] = object[field];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addCommand(chrome, domainName, command) {
|
||||
const commandName = `${domainName}.${command.name}`;
|
||||
const handler = (params, sessionId, callback) => {
|
||||
return chrome.send(commandName, params, sessionId, callback);
|
||||
};
|
||||
decorate(handler, 'command', command);
|
||||
chrome[commandName] = chrome[domainName][command.name] = handler;
|
||||
}
|
||||
|
||||
function addEvent(chrome, domainName, event) {
|
||||
const eventName = `${domainName}.${event.name}`;
|
||||
const handler = (sessionId, handler) => {
|
||||
if (typeof sessionId === 'function') {
|
||||
handler = sessionId;
|
||||
sessionId = undefined;
|
||||
}
|
||||
const rawEventName = sessionId ? `${eventName}.${sessionId}` : eventName;
|
||||
if (typeof handler === 'function') {
|
||||
chrome.on(rawEventName, handler);
|
||||
return () => chrome.removeListener(rawEventName, handler);
|
||||
} else {
|
||||
return new Promise((fulfill, reject) => {
|
||||
chrome.once(rawEventName, fulfill);
|
||||
});
|
||||
}
|
||||
};
|
||||
decorate(handler, 'event', event);
|
||||
chrome[eventName] = chrome[domainName][event.name] = handler;
|
||||
}
|
||||
|
||||
function addType(chrome, domainName, type) {
|
||||
const typeName = `${domainName}.${type.id}`;
|
||||
const help = {};
|
||||
decorate(help, 'type', type);
|
||||
chrome[typeName] = chrome[domainName][type.id] = help;
|
||||
}
|
||||
|
||||
function prepare(object, protocol) {
|
||||
// assign the protocol and generate the shorthands
|
||||
object.protocol = protocol;
|
||||
protocol.domains.forEach((domain) => {
|
||||
const domainName = domain.domain;
|
||||
object[domainName] = {};
|
||||
// add commands
|
||||
(domain.commands || []).forEach((command) => {
|
||||
addCommand(object, domainName, command);
|
||||
});
|
||||
// add events
|
||||
(domain.events || []).forEach((event) => {
|
||||
addEvent(object, domainName, event);
|
||||
});
|
||||
// add types
|
||||
(domain.types || []).forEach((type) => {
|
||||
addType(object, domainName, type);
|
||||
});
|
||||
// add utility listener for each domain
|
||||
object[domainName].on = (eventName, handler) => {
|
||||
return object[domainName][eventName](handler);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.prepare = prepare;
|
||||
302
node_modules/chrome-remote-interface/lib/chrome.js
generated
vendored
Normal file
302
node_modules/chrome-remote-interface/lib/chrome.js
generated
vendored
Normal file
@@ -0,0 +1,302 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const util = require('util');
|
||||
const formatUrl = require('url').format;
|
||||
const parseUrl = require('url').parse;
|
||||
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const api = require('./api.js');
|
||||
const defaults = require('./defaults.js');
|
||||
const devtools = require('./devtools.js');
|
||||
const errors = require('./errors.js');
|
||||
|
||||
class Chrome extends EventEmitter {
|
||||
constructor(options, notifier) {
|
||||
super();
|
||||
// options
|
||||
const defaultTarget = (targets) => {
|
||||
// prefer type = 'page' inspectable targets as they represents
|
||||
// browser tabs (fall back to the first inspectable target
|
||||
// otherwise)
|
||||
let backup;
|
||||
let target = targets.find((target) => {
|
||||
if (target.webSocketDebuggerUrl) {
|
||||
backup = backup || target;
|
||||
return target.type === 'page';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
target = target || backup;
|
||||
if (target) {
|
||||
return target;
|
||||
} else {
|
||||
throw new Error('No inspectable targets');
|
||||
}
|
||||
};
|
||||
options = options || {};
|
||||
this.host = options.host || defaults.HOST;
|
||||
this.port = options.port || defaults.PORT;
|
||||
this.secure = !!(options.secure);
|
||||
this.useHostName = !!(options.useHostName);
|
||||
this.alterPath = options.alterPath || ((path) => path);
|
||||
this.protocol = options.protocol;
|
||||
this.local = !!(options.local);
|
||||
this.target = options.target || defaultTarget;
|
||||
// locals
|
||||
this._notifier = notifier;
|
||||
this._callbacks = {};
|
||||
this._nextCommandId = 1;
|
||||
// properties
|
||||
this.webSocketUrl = undefined;
|
||||
// operations
|
||||
this._start();
|
||||
}
|
||||
|
||||
// avoid misinterpreting protocol's members as custom util.inspect functions
|
||||
inspect(depth, options) {
|
||||
options.customInspect = false;
|
||||
return util.inspect(this, options);
|
||||
}
|
||||
|
||||
send(method, params, sessionId, callback) {
|
||||
// handle optional arguments
|
||||
const optionals = Array.from(arguments).slice(1);
|
||||
params = optionals.find(x => typeof x === 'object');
|
||||
sessionId = optionals.find(x => typeof x === 'string');
|
||||
callback = optionals.find(x => typeof x === 'function');
|
||||
// return a promise when a callback is not provided
|
||||
if (typeof callback === 'function') {
|
||||
this._enqueueCommand(method, params, sessionId, callback);
|
||||
return undefined;
|
||||
} else {
|
||||
return new Promise((fulfill, reject) => {
|
||||
this._enqueueCommand(method, params, sessionId, (error, response) => {
|
||||
if (error) {
|
||||
const request = {method, params, sessionId};
|
||||
reject(
|
||||
error instanceof Error
|
||||
? error // low-level WebSocket error
|
||||
: new errors.ProtocolError(request, response)
|
||||
);
|
||||
} else {
|
||||
fulfill(response);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
close(callback) {
|
||||
const closeWebSocket = (callback) => {
|
||||
// don't close if it's already closed
|
||||
if (this._ws.readyState === 3) {
|
||||
callback();
|
||||
} else {
|
||||
// don't notify on user-initiated shutdown ('disconnect' event)
|
||||
this._ws.removeAllListeners('close');
|
||||
this._ws.once('close', () => {
|
||||
this._ws.removeAllListeners();
|
||||
this._handleConnectionClose();
|
||||
callback();
|
||||
});
|
||||
this._ws.close();
|
||||
}
|
||||
};
|
||||
if (typeof callback === 'function') {
|
||||
closeWebSocket(callback);
|
||||
return undefined;
|
||||
} else {
|
||||
return new Promise((fulfill, reject) => {
|
||||
closeWebSocket(fulfill);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// initiate the connection process
|
||||
async _start() {
|
||||
const options = {
|
||||
host: this.host,
|
||||
port: this.port,
|
||||
secure: this.secure,
|
||||
useHostName: this.useHostName,
|
||||
alterPath: this.alterPath
|
||||
};
|
||||
try {
|
||||
// fetch the WebSocket debugger URL
|
||||
const url = await this._fetchDebuggerURL(options);
|
||||
// allow the user to alter the URL
|
||||
const urlObject = parseUrl(url);
|
||||
urlObject.pathname = options.alterPath(urlObject.pathname);
|
||||
this.webSocketUrl = formatUrl(urlObject);
|
||||
// update the connection parameters using the debugging URL
|
||||
options.host = urlObject.hostname;
|
||||
options.port = urlObject.port || options.port;
|
||||
// fetch the protocol and prepare the API
|
||||
const protocol = await this._fetchProtocol(options);
|
||||
api.prepare(this, protocol);
|
||||
// finally connect to the WebSocket
|
||||
await this._connectToWebSocket();
|
||||
// since the handler is executed synchronously, the emit() must be
|
||||
// performed in the next tick so that uncaught errors in the client code
|
||||
// are not intercepted by the Promise mechanism and therefore reported
|
||||
// via the 'error' event
|
||||
process.nextTick(() => {
|
||||
this._notifier.emit('connect', this);
|
||||
});
|
||||
} catch (err) {
|
||||
this._notifier.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch the WebSocket URL according to 'target'
|
||||
async _fetchDebuggerURL(options) {
|
||||
const userTarget = this.target;
|
||||
switch (typeof userTarget) {
|
||||
case 'string': {
|
||||
let idOrUrl = userTarget;
|
||||
// use default host and port if omitted (and a relative URL is specified)
|
||||
if (idOrUrl.startsWith('/')) {
|
||||
idOrUrl = `ws://${this.host}:${this.port}${idOrUrl}`;
|
||||
}
|
||||
// a WebSocket URL is specified by the user (e.g., node-inspector)
|
||||
if (idOrUrl.match(/^wss?:/i)) {
|
||||
return idOrUrl; // done!
|
||||
}
|
||||
// a target id is specified by the user
|
||||
else {
|
||||
const targets = await devtools.List(options);
|
||||
const object = targets.find((target) => target.id === idOrUrl);
|
||||
return object.webSocketDebuggerUrl;
|
||||
}
|
||||
}
|
||||
case 'object': {
|
||||
const object = userTarget;
|
||||
return object.webSocketDebuggerUrl;
|
||||
}
|
||||
case 'function': {
|
||||
const func = userTarget;
|
||||
const targets = await devtools.List(options);
|
||||
const result = func(targets);
|
||||
const object = typeof result === 'number' ? targets[result] : result;
|
||||
return object.webSocketDebuggerUrl;
|
||||
}
|
||||
default:
|
||||
throw new Error(`Invalid target argument "${this.target}"`);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch the protocol according to 'protocol' and 'local'
|
||||
async _fetchProtocol(options) {
|
||||
// if a protocol has been provided then use it
|
||||
if (this.protocol) {
|
||||
return this.protocol;
|
||||
}
|
||||
// otherwise user either the local or the remote version
|
||||
else {
|
||||
options.local = this.local;
|
||||
return await devtools.Protocol(options);
|
||||
}
|
||||
}
|
||||
|
||||
// establish the WebSocket connection and start processing user commands
|
||||
_connectToWebSocket() {
|
||||
return new Promise((fulfill, reject) => {
|
||||
// create the WebSocket
|
||||
try {
|
||||
if (this.secure) {
|
||||
this.webSocketUrl = this.webSocketUrl.replace(/^ws:/i, 'wss:');
|
||||
}
|
||||
this._ws = new WebSocket(this.webSocketUrl, [], {
|
||||
maxPayload: 256 * 1024 * 1024,
|
||||
perMessageDeflate: false,
|
||||
followRedirects: true,
|
||||
});
|
||||
} catch (err) {
|
||||
// handles bad URLs
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
// set up event handlers
|
||||
this._ws.on('open', () => {
|
||||
fulfill();
|
||||
});
|
||||
this._ws.on('message', (data) => {
|
||||
const message = JSON.parse(data);
|
||||
this._handleMessage(message);
|
||||
});
|
||||
this._ws.on('close', (code) => {
|
||||
this._handleConnectionClose();
|
||||
this.emit('disconnect');
|
||||
});
|
||||
this._ws.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_handleConnectionClose() {
|
||||
// make sure to complete all the unresolved callbacks
|
||||
const err = new Error('WebSocket connection closed');
|
||||
for (const callback of Object.values(this._callbacks)) {
|
||||
callback(err);
|
||||
}
|
||||
this._callbacks = {};
|
||||
}
|
||||
|
||||
// handle the messages read from the WebSocket
|
||||
_handleMessage(message) {
|
||||
// command response
|
||||
if (message.id) {
|
||||
const callback = this._callbacks[message.id];
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
// interpret the lack of both 'error' and 'result' as success
|
||||
// (this may happen with node-inspector)
|
||||
if (message.error) {
|
||||
callback(true, message.error);
|
||||
} else {
|
||||
callback(false, message.result || {});
|
||||
}
|
||||
// unregister command response callback
|
||||
delete this._callbacks[message.id];
|
||||
// notify when there are no more pending commands
|
||||
if (Object.keys(this._callbacks).length === 0) {
|
||||
this.emit('ready');
|
||||
}
|
||||
}
|
||||
// event
|
||||
else if (message.method) {
|
||||
const {method, params, sessionId} = message;
|
||||
this.emit('event', message);
|
||||
this.emit(method, params, sessionId);
|
||||
this.emit(`${method}.${sessionId}`, params, sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
// send a command to the remote endpoint and register a callback for the reply
|
||||
_enqueueCommand(method, params, sessionId, callback) {
|
||||
const id = this._nextCommandId++;
|
||||
const message = {
|
||||
id,
|
||||
method,
|
||||
sessionId,
|
||||
params: params || {}
|
||||
};
|
||||
this._ws.send(JSON.stringify(message), (err) => {
|
||||
if (err) {
|
||||
// handle low-level WebSocket errors
|
||||
if (typeof callback === 'function') {
|
||||
callback(err);
|
||||
}
|
||||
} else {
|
||||
this._callbacks[id] = callback;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Chrome;
|
||||
4
node_modules/chrome-remote-interface/lib/defaults.js
generated
vendored
Normal file
4
node_modules/chrome-remote-interface/lib/defaults.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
module.exports.HOST = 'localhost';
|
||||
module.exports.PORT = 9222;
|
||||
127
node_modules/chrome-remote-interface/lib/devtools.js
generated
vendored
Normal file
127
node_modules/chrome-remote-interface/lib/devtools.js
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
'use strict';
|
||||
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
|
||||
const defaults = require('./defaults.js');
|
||||
const externalRequest = require('./external-request.js');
|
||||
|
||||
// options.path must be specified; callback(err, data)
|
||||
function devToolsInterface(path, options, callback) {
|
||||
const transport = options.secure ? https : http;
|
||||
const requestOptions = {
|
||||
method: options.method,
|
||||
host: options.host || defaults.HOST,
|
||||
port: options.port || defaults.PORT,
|
||||
useHostName: options.useHostName,
|
||||
path: (options.alterPath ? options.alterPath(path) : path)
|
||||
};
|
||||
externalRequest(transport, requestOptions, callback);
|
||||
}
|
||||
|
||||
// wrapper that allows to return a promise if the callback is omitted, it works
|
||||
// for DevTools methods
|
||||
function promisesWrapper(func) {
|
||||
return (options, callback) => {
|
||||
// options is an optional argument
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = undefined;
|
||||
}
|
||||
options = options || {};
|
||||
// just call the function otherwise wrap a promise around its execution
|
||||
if (typeof callback === 'function') {
|
||||
func(options, callback);
|
||||
return undefined;
|
||||
} else {
|
||||
return new Promise((fulfill, reject) => {
|
||||
func(options, (err, result) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
fulfill(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function Protocol(options, callback) {
|
||||
// if the local protocol is requested
|
||||
if (options.local) {
|
||||
const localDescriptor = require('./protocol.json');
|
||||
callback(null, localDescriptor);
|
||||
return;
|
||||
}
|
||||
// try to fetch the protocol remotely
|
||||
devToolsInterface('/json/protocol', options, (err, descriptor) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
callback(null, JSON.parse(descriptor));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function List(options, callback) {
|
||||
devToolsInterface('/json/list', options, (err, tabs) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
callback(null, JSON.parse(tabs));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function New(options, callback) {
|
||||
let path = '/json/new';
|
||||
if (Object.prototype.hasOwnProperty.call(options, 'url')) {
|
||||
path += `?${options.url}`;
|
||||
}
|
||||
options.method = options.method || 'PUT'; // see #497
|
||||
devToolsInterface(path, options, (err, tab) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
callback(null, JSON.parse(tab));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function Activate(options, callback) {
|
||||
devToolsInterface('/json/activate/' + options.id, options, (err) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function Close(options, callback) {
|
||||
devToolsInterface('/json/close/' + options.id, options, (err) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function Version(options, callback) {
|
||||
devToolsInterface('/json/version', options, (err, versionInfo) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
callback(null, JSON.parse(versionInfo));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.Protocol = promisesWrapper(Protocol);
|
||||
module.exports.List = promisesWrapper(List);
|
||||
module.exports.New = promisesWrapper(New);
|
||||
module.exports.Activate = promisesWrapper(Activate);
|
||||
module.exports.Close = promisesWrapper(Close);
|
||||
module.exports.Version = promisesWrapper(Version);
|
||||
16
node_modules/chrome-remote-interface/lib/errors.js
generated
vendored
Normal file
16
node_modules/chrome-remote-interface/lib/errors.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
class ProtocolError extends Error {
|
||||
constructor(request, response) {
|
||||
let {message} = response;
|
||||
if (response.data) {
|
||||
message += ` (${response.data})`;
|
||||
}
|
||||
super(message);
|
||||
// attach the original response as well
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.ProtocolError = ProtocolError;
|
||||
44
node_modules/chrome-remote-interface/lib/external-request.js
generated
vendored
Normal file
44
node_modules/chrome-remote-interface/lib/external-request.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
|
||||
const dns = require('dns');
|
||||
const util = require('util');
|
||||
|
||||
const REQUEST_TIMEOUT = 10000;
|
||||
|
||||
// callback(err, data)
|
||||
async function externalRequest(transport, options, callback) {
|
||||
// perform the DNS lookup manually so that the HTTP host header generated by
|
||||
// http.get will contain the IP address, this is needed because since Chrome
|
||||
// 66 the host header cannot contain an host name different than localhost
|
||||
// (see https://github.com/cyrus-and/chrome-remote-interface/issues/340)
|
||||
if (!options.useHostName) {
|
||||
try {
|
||||
const {address} = await util.promisify(dns.lookup)(options.host);
|
||||
options.host = address;
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// perform the actual request
|
||||
const request = transport.request(options, (response) => {
|
||||
let data = '';
|
||||
response.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
response.on('end', () => {
|
||||
if (response.statusCode === 200) {
|
||||
callback(null, data);
|
||||
} else {
|
||||
callback(new Error(data));
|
||||
}
|
||||
});
|
||||
});
|
||||
request.setTimeout(REQUEST_TIMEOUT, () => {
|
||||
request.abort();
|
||||
});
|
||||
request.on('error', callback);
|
||||
request.end();
|
||||
}
|
||||
|
||||
module.exports = externalRequest;
|
||||
27862
node_modules/chrome-remote-interface/lib/protocol.json
generated
vendored
Normal file
27862
node_modules/chrome-remote-interface/lib/protocol.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
39
node_modules/chrome-remote-interface/lib/websocket-wrapper.js
generated
vendored
Normal file
39
node_modules/chrome-remote-interface/lib/websocket-wrapper.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
|
||||
// wrapper around the Node.js ws module
|
||||
// for use in browsers
|
||||
class WebSocketWrapper extends EventEmitter {
|
||||
constructor(url) {
|
||||
super();
|
||||
this._ws = new WebSocket(url); // eslint-disable-line no-undef
|
||||
this._ws.onopen = () => {
|
||||
this.emit('open');
|
||||
};
|
||||
this._ws.onclose = () => {
|
||||
this.emit('close');
|
||||
};
|
||||
this._ws.onmessage = (event) => {
|
||||
this.emit('message', event.data);
|
||||
};
|
||||
this._ws.onerror = () => {
|
||||
this.emit('error', new Error('WebSocket error'));
|
||||
};
|
||||
}
|
||||
|
||||
close() {
|
||||
this._ws.close();
|
||||
}
|
||||
|
||||
send(data, callback) {
|
||||
try {
|
||||
this._ws.send(data);
|
||||
callback();
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebSocketWrapper;
|
||||
Reference in New Issue
Block a user