welsonjs/lib/chrome.js

510 lines
13 KiB
JavaScript
Raw Normal View History

2020-11-09 10:06:34 +00:00
//////////////////////////////////////////////////////////////////////////////////
// Google Chrome API
/////////////////////////////////////////////////////////////////////////////////
var SHELL = require("lib/shell");
2020-11-15 04:31:35 +00:00
var SYS = require("lib/system");
2020-11-18 08:46:26 +00:00
var FILE = require("lib/file");
2021-06-19 20:51:34 +00:00
var HTTP = require("lib/http");
2021-06-19 21:59:41 +00:00
var Websocket = require("lib/websocket");
2020-11-09 10:06:34 +00:00
2021-06-20 17:54:46 +00:00
// for remote debugging
var pageEventId = 0;
2020-11-15 04:31:35 +00:00
var ChromeObject = function() {
2020-11-20 08:44:50 +00:00
this.workingDirectory = SYS.getEnvString("PROGRAMFILES") + "\\Google\\Chrome\\Application";
this.binPath = SYS.getEnvString("PROGRAMFILES") + "\\Google\\:installedDir\\Application\\chrome.exe";
2021-06-19 20:51:34 +00:00
//this.processID = 0;
2020-11-20 08:44:50 +00:00
this.installedDir = "Chrome";
2020-11-09 19:06:58 +00:00
this.profileName = "Default";
2020-11-20 08:44:50 +00:00
this.userDataDir = null;
2021-06-19 20:51:34 +00:00
this.proxy = {
"protocol": "socks5",
"host": "127.0.0.1",
"port": 1080
};
2020-12-10 01:26:33 +00:00
this.inPrivate = false;
2021-07-05 11:09:01 +00:00
this.oAutoIt = null;
2021-06-19 21:59:41 +00:00
// for remote debugging
2021-06-19 20:51:34 +00:00
this.debuggingPort = 0;
2021-06-19 21:59:41 +00:00
this.pageId = "";
this.ws = Websocket.create();
2021-07-19 12:24:30 +00:00
this.isAttached = false;
2021-07-19 16:27:22 +00:00
this.pageList = [];
2020-11-15 04:31:35 +00:00
2021-07-05 11:09:01 +00:00
this.create = function() {
try {
this.oAutoIt = CreateObject("AutoItX3.Control");
} catch (e) {
console.log("ChromeObject.create() -> " + e.message);
}
};
2020-11-15 04:31:35 +00:00
this.setBinPath = function(path) {
this.binPath = path;
return this;
};
2020-11-09 19:06:58 +00:00
2020-11-20 08:44:50 +00:00
this.setProfile = function(profileName, installedDir) {
2020-11-18 04:13:38 +00:00
this.profileName = (profileName == "Default" ? "Chrome" : profileName);
2021-06-24 20:47:31 +00:00
this.setInstalledDir(installedDir);
2021-06-19 20:51:34 +00:00
this.workingDirectory = this.workingDirectory.replace(":installedDir", this.installedDir);
this.binPath = this.binPath.replace(":installedDir", this.installedDir);
//this.binPath = this.binPath.replace(":installedDir", "Chrome");
2020-11-20 08:44:50 +00:00
return this;
};
2021-06-19 20:51:34 +00:00
2020-11-20 08:44:50 +00:00
this.setUserDataDir = function(dirname) {
2021-06-24 20:47:31 +00:00
if (dirname != null) {
this.userDataDir = dirname;
} else {
this.userDataDir = SHELL.getPathOfMyDocuments() + "\\UserData_Chrome_" + this.profileName;
}
2020-11-20 08:44:50 +00:00
return this;
};
this.setInstalledDir = function(dirname) {
2021-06-24 20:47:31 +00:00
if (dirname != null) {
this.installedDir = dirname;
}
2020-11-15 04:31:35 +00:00
return this;
2020-11-09 19:06:58 +00:00
};
2021-06-19 20:51:34 +00:00
this.setProxy = function(obj) {
this.proxy = obj;
return this;
};
2020-11-09 10:06:34 +00:00
2021-06-19 20:51:34 +00:00
this.setProxyProtocol = function(s) {
this.proxy.protocol = s;
2020-11-15 04:31:35 +00:00
return this;
2020-11-09 19:06:58 +00:00
};
2020-11-15 04:31:35 +00:00
2021-06-19 20:51:34 +00:00
this.setProxyHost = function(s) {
this.proxy.host = s;
return this;
};
this.setProxyPort = function(n) {
this.proxy.port = n;
return this;
2020-11-09 19:43:19 +00:00
};
2021-06-19 20:51:34 +00:00
2021-07-19 16:27:22 +00:00
this.setDebuggingPort = function(port) {
this.debuggingPort = port;
console.log("Debugging port setted: " + port);
2021-06-24 20:47:31 +00:00
return this;
2021-06-19 20:51:34 +00:00
}
2021-06-19 21:59:41 +00:00
this.setPageId = function(s) {
this.pageId = s;
};
2020-11-09 10:06:34 +00:00
2020-11-20 08:44:50 +00:00
this.createShoutcut = function(url) {
if (!this.userDataDir) {
this.userDataDir = SHELL.getPathOfMyDocuments() + "\\UserData_Chrome_" + this.profileName;
}
2021-06-19 20:51:34 +00:00
var cmd = [
"cscript",
"app.js",
"shoutcut",
"chrome",
this.installedDir,
];
if (this.inPrivate) {
cmd.push("--incognito");
}
if (this.debuggingPort > 0) {
cmd.push("--remote-debugging-port=" + this.debuggingPort);
2020-12-10 01:26:33 +00:00
}
2021-06-19 20:51:34 +00:00
cmd.push("--profile-directory=\"" + this.profileName + "\"");
cmd.push("--user-data-dir=\"" + this.userDataDir + "\"");
cmd.push("\"" + url + "\"");
SHELL.createDesktopIcon("Chrome Prototype (" + this.installedDir + ")", cmd.join(' '), SYS.getCurrentScriptDirectory());
2020-12-10 01:26:33 +00:00
};
this.setInPrivate = function(flag) {
this.inPrivate = flag;
return this;
2020-11-20 08:44:50 +00:00
};
2020-11-09 19:06:58 +00:00
this.open = function(url) {
2020-11-20 08:44:50 +00:00
this.setProfile(this.profileName, this.installedDir);
2020-11-18 04:13:38 +00:00
2021-06-19 20:56:20 +00:00
// if the file does not exists, Check the 32bit installation folder again
2020-11-18 10:55:06 +00:00
if (!FILE.fileExists(this.binPath)) {
2020-11-20 08:44:50 +00:00
this.workingDirectory = SYS.getEnvString("PROGRAMFILES(X86)") + "\\Google\\Chrome\\Application";
this.binPath = SYS.getEnvString("PROGRAMFILES(X86)") + "\\Google\\:installedDir\\Application\\chrome.exe";
this.setProfile(this.profileName, this.installedDir);
2020-11-18 10:55:06 +00:00
}
2021-06-19 20:56:20 +00:00
// find profile
2020-11-18 08:46:26 +00:00
if (!FILE.fileExists(this.binPath)) {
2021-06-19 20:56:20 +00:00
console.error("ChromeObject.open() -> '" + this.profileName + "' profile does not exists. You have to create it.");
2020-11-18 08:46:26 +00:00
return this;
}
2021-06-19 20:56:20 +00:00
// create shoutcut to desktop
2021-06-19 21:13:00 +00:00
if (this.debuggingPort == 0) {
this.createShoutcut();
}
2020-11-18 10:55:06 +00:00
2020-11-20 08:44:50 +00:00
/*
2020-11-15 04:31:35 +00:00
var process;
while (this.processID == 0) {
try {
2020-11-20 08:44:50 +00:00
if (!this.userDataDir) {
this.userDataDir = SHELL.getPathOfMyDocuments() + "\\UserData_Chrome_" + this.profileName;
}
2020-11-18 04:13:38 +00:00
var shell = SHELL.create().setWorkingDirectory(this.workingDirectory);
var process = shell.createProcess([
"\"" + this.binPath + "\"",
"--profile-directory=\"" + this.profileName + "\"",
"--proxy-server=\"socks5://127.0.0.1:" + this.proxyPort + "\"",
2020-11-20 08:44:50 +00:00
"--user-data-dir=\"" + this.userDataDir + "\"",
2020-11-18 04:13:38 +00:00
"\"" + url + "\""
].join(" "));
2020-12-10 02:19:07 +00:00
sleep(1500);
2020-11-15 04:31:35 +00:00
this.processID = process.ProcessID;
2020-12-10 02:19:07 +00:00
sleep(1500);
2020-11-18 04:13:38 +00:00
shell.release();
2020-11-15 04:31:35 +00:00
} catch (e) {
2020-11-18 04:13:38 +00:00
console.error("ChromeObject.open() -> " + e.message);
2020-12-10 02:19:07 +00:00
sleep(1500);
2020-11-15 04:31:35 +00:00
}
}
2020-11-20 08:44:50 +00:00
*/
try {
if (!this.userDataDir) {
this.userDataDir = SHELL.getPathOfMyDocuments() + "\\UserData_Chrome_" + this.profileName;
}
2020-12-07 03:48:37 +00:00
2020-12-08 06:43:59 +00:00
var shell = SHELL.create();
shell.setWorkingDirectory(this.workingDirectory);
2021-06-19 20:51:34 +00:00
var cmd = [];
if (this.inPrivate) {
cmd.push("--incognito");
}
2021-06-19 21:11:44 +00:00
2021-06-19 20:51:34 +00:00
if (this.debuggingPort > 0) {
cmd.push("--remote-debugging-port=" + this.debuggingPort);
2020-12-10 01:26:33 +00:00
}
2021-06-19 20:51:34 +00:00
cmd.push("--profile-directory=\"" + this.profileName + "\"");
2021-06-24 20:47:31 +00:00
if (this.proxy != null) {
2021-07-05 11:09:01 +00:00
console.log("--proxy-server=\"" + this.proxy.protocol + "://" + this.proxy.host + ":" + this.proxy.port + "\"");
cmd.push("--proxy-server=\"" + this.proxy.protocol + "://" + this.proxy.host + ":" + this.proxy.port + "\"");
2021-06-24 20:47:31 +00:00
}
2021-06-19 20:51:34 +00:00
cmd.push("--user-data-dir=\"" + this.userDataDir + "\"");
cmd.push("\"" + url + "\"");
2021-06-19 20:53:58 +00:00
shell.runAs(this.binPath, cmd);
2021-06-19 20:51:34 +00:00
2020-12-10 02:19:07 +00:00
sleep(1500);
2020-11-20 08:44:50 +00:00
shell.release();
} catch (e) {
console.error("ChromeObject.open() -> " + e.message);
2020-12-10 02:19:07 +00:00
sleep(1500);
2020-11-20 08:44:50 +00:00
}
2020-11-15 04:31:35 +00:00
return this;
2020-11-09 19:06:58 +00:00
};
2021-06-19 20:51:34 +00:00
this.getPageList = function() {
2021-07-19 16:27:22 +00:00
var pageList = [];
2021-06-19 20:51:34 +00:00
if (this.debuggingPort > 0) {
2021-07-19 12:24:30 +00:00
try {
2021-07-19 16:27:22 +00:00
pageList = JSON.parse(HTTP.get("http://127.0.0.1:" + this.debuggingPort + "/json"));
this.pageList = pageList;
return pageList;
2021-07-19 12:24:30 +00:00
} catch (e) {
console.error("ChromeObject.getPageList() -> " + e.message);
2021-07-19 14:31:59 +00:00
return this.getPageList();
2021-07-19 12:24:30 +00:00
}
2021-06-19 20:51:34 +00:00
} else {
console.error("Remote debugging unavailable");
2021-07-19 16:27:22 +00:00
return pageList;
2021-06-19 20:51:34 +00:00
}
};
2020-11-09 19:06:58 +00:00
2021-06-19 20:51:34 +00:00
this.getPageById = function(id) {
2021-06-19 20:52:30 +00:00
var pages = this.getPageList().filter(function(x) {
2021-06-19 21:14:29 +00:00
return (x.id = id);
2021-06-19 20:51:34 +00:00
});
return (pages.length > 0 ? pages[0] : null);
};
this.getPagesByUrl = function(url) {
2021-06-19 20:52:30 +00:00
return this.getPageList().filter(function(x) {
2021-06-19 20:51:34 +00:00
return (x.url == url);
});
};
this.getPagesByTitle = function(title) {
2021-06-19 20:52:30 +00:00
return this.getPageList().filter(function(x) {
2021-06-19 20:51:34 +00:00
return (x.title == title);
});
};
2021-07-19 12:24:30 +00:00
2021-06-19 22:01:38 +00:00
this.sendPageRPC = function(method, params) {
2021-06-24 20:47:31 +00:00
var result = null;
try {
if (this.pageId != "") {
result = this.ws.send("ws://127.0.0.1:" + this.debuggingPort + "/devtools/page/" + this.pageId, JSON.stringify({
"id": pageEventId,
"method": method,
"params": params
}));
pageEventId++;
console.info("ChromeObject().sendPageRPC() -> Sent");
} else {
var pageList = this.getPageList();
if (pageList instanceof Array && pageList.length > 0) {
this.pageId = pageList[0].id;
if (this.pageId != "") {
result = this.sendPageRPC(method, params);
} else {
console.error("Got invaild list of pages");
}
}
}
} catch (e) {
console.log("ChromeObject.sendPageRPC() -> " + e.message);
2021-06-19 22:05:02 +00:00
}
2021-06-24 20:47:31 +00:00
return result;
2021-06-19 21:59:41 +00:00
};
this.navigate = function(url) {
2021-06-19 22:01:38 +00:00
return this.sendPageRPC("Page.navigate", {
2021-06-19 21:59:41 +00:00
"url": url
});
};
2021-06-19 22:01:38 +00:00
this.evaluate = function(expression) {
2021-06-24 20:47:31 +00:00
try {
return this.sendPageRPC("Runtime.evaluate", {
"expression": expression
});
} catch (e) {
console.error("ChromeObject.evaluate() -> " + e.message);
}
};
this.close = function() {
return this.sendPageRPC("Browser.close", {});
2021-06-19 21:59:41 +00:00
};
2021-07-19 12:24:30 +00:00
this.terminate = function() {
2021-07-19 16:27:22 +00:00
var pageList = this.pageList;
2021-07-19 12:24:30 +00:00
for (var i = 0; i < pageList.length; i++) {
this.oAutoIt.WinKill(pageList[i].title);
}
};
2021-06-20 17:54:46 +00:00
this.focus = function() {
2021-06-24 20:47:31 +00:00
if (this.debuggingPort > 0) {
try {
2021-07-19 12:24:30 +00:00
// if page ID is empty
if (this.pageId == "") {
var pageList = this.getPageList();
if (pageList instanceof Array && pageList.length > 0) {
this.pageId = pageList[0].id;
}
}
2021-07-05 11:09:01 +00:00
// change webpage title for focusing window
this.setTitle(this.pageId);
// find window by title
2021-06-24 20:47:31 +00:00
var pageList = this.getPageList();
for (var i = 0; i < pageList.length; i++) {
if (pageList[i].id == this.pageId) {
2021-07-05 11:09:01 +00:00
this.oAutoIt.WinActivate(pageList[i].title);
2021-06-24 20:47:31 +00:00
}
}
} catch (e) {
console.error("ChromeObject.focus() -> " + e.message);
}
}
};
2021-07-25 11:56:56 +00:00
this.scrollToBottom = function() {
return this.evaluate('window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight)');
};
2021-07-19 12:24:30 +00:00
this.focusWithoutActivate = function() {
if (this.debuggingPort > 0) {
try {
// if page ID is empty
if (this.pageId == "") {
var pageList = this.getPageList();
if (pageList instanceof Array && pageList.length > 0) {
this.pageId = pageList[0].id;
}
}
// change webpage title for focusing window
this.setTitle(this.pageId);
} catch (e) {
console.error("ChromeObject.focusWithoutActivate() -> " + e.message);
}
}
};
this.arrange = function() {
// resolution: 1920x1080
// 화면 하단은 작업표시줄 또는 알림창이 떠있을 수 있음. 클릭 방지를 위해 높이(h) 값은 -200 으로 조정함.
var x = this.getRandomInt(0, 960);
var y = this.getRandomInt(0, 540);
var w = this.getRandomInt(960, 1920 - x);
var h = this.getRandomInt(540, 1080 - y - 200);
this.oAutoIt.WinMove(this.pageId, "", x, y, w, h);
};
2021-06-24 20:47:31 +00:00
this.blur = function() {
return this.evaluate("window.blur()");
2021-06-20 17:54:46 +00:00
};
2021-06-24 20:47:31 +00:00
2021-07-05 11:09:01 +00:00
this.downMouseWheel = function(times) {
if (this.debuggingPort > 0) {
try {
var pos = this.getScreenPosition();
this.oAutoIt.MouseMove(pos.x + 100, pos.y + 100);
this.oAutoIt.MouseWheel("down", times);
} catch (e) {
console.error("ChromeObject.downMouseWheel() -> " + e.message);
}
}
};
this.upMouseWheel = function(times) {
if (this.debuggingPort > 0) {
try {
var pos = this.getScreenPosition();
this.oAutoIt.MouseMove(pos.x + 100, pos.y + 100);
this.oAutoIt.MouseWheel("up", times);
} catch (e) {
console.error("ChromeObject.upMouseWheel() -> " + e.message);
}
}
};
this.setTitle = function(title) {
if (this.debuggingPort > 0) {
2021-07-19 14:31:59 +00:00
for (var i = 0; i < 3; i++) {
2021-07-19 12:24:30 +00:00
this.evaluate('document.title = "' + title + '"');
}
2021-07-05 11:09:01 +00:00
}
};
2021-07-19 16:27:22 +00:00
this.getTitle = function() {
if (this.debuggingPort > 0) {
var response = this.evaluate('document.title');
return JSON.parse(response).result.result.value;
}
};
2021-07-05 11:09:01 +00:00
this.getScreenPosition = function() {
var response = this.evaluate('(function() { return [window.screenX, window.screenY].join(","); })();');
var result = JSON.parse(response).result.result.value;
var pos = result.split(',');
return {
"x": parseInt(pos[0]),
"y": parseInt(pos[1])
};
};
this.getPageHeight = function() {
var height = 0;
if (this.debuggingPort > 0) {
var response = this.evaluate('(function(obj) { return Math.max(obj.scrollHeight, obj.clientHeight); })(document.querySelector("html"))');
var result = JSON.parse(response).result.result.value;
height = parseInt(result);
}
return height;
};
2021-07-19 12:24:30 +00:00
this.setIsAttached = function(isAttached) {
this.isAttached = isAttached;
return this;
};
this.getRandomInt = function(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
};
2021-07-19 14:31:59 +00:00
this.checkDebuggingPort = function() {
var isChecked = false;
if (this.debuggingPort > 0) {
var result = SHELL.exec("netstat -ano | findstr :" + this.debuggingPort);
if (result.indexOf(":" + this.debuggingPort) > -1) {
isChecked = true;
}
}
return isChecked;
};
2021-07-05 11:09:01 +00:00
2021-07-21 02:40:14 +00:00
this.getCurrentUrl = function() {
2021-07-21 02:41:43 +00:00
var page = this.getPageById(this.pageId);
return page.url;
2021-07-21 02:40:14 +00:00
};
2021-07-25 11:56:56 +00:00
2021-07-22 01:42:32 +00:00
this.triggerEvent = function(eventName, selector) {
return this.evaluate('document.querySelector("' + selector + '").dispatchEvent(new Event("' + eventName + '"))');
};
2021-07-25 11:56:56 +00:00
this.scrollBy = function(dx, dy) {
var dx = (typeof(dx) !== "undefined" ? dx : '0');
var dy = (typeof(dy) !== "undefined" ? dy : '0');
return this.evaluate('window.scrollBy(' + dx + ', ' + dy + ')');
};
this.reload = function() {
return this.sendPageRPC("Page.reload", {});
};
2021-07-22 01:42:32 +00:00
2021-07-05 11:09:01 +00:00
this.create();
2020-11-20 08:44:50 +00:00
};
2021-06-19 20:51:34 +00:00
exports.create = function() {
return new ChromeObject();
2020-11-15 04:31:35 +00:00
};
2020-11-20 08:44:50 +00:00
exports.start = function(url, proxyPort, profileName, userDataDir, installedDir) {
return (new ChromeObject())
.setProxyPort(proxyPort)
.setProfile(profileName, installedDir)
.setUserDataDir(userDataDir)
2021-06-19 20:57:17 +00:00
.open(url)
2020-11-20 08:44:50 +00:00
;
2020-11-09 19:06:58 +00:00
};
2021-06-19 20:51:34 +00:00
2021-06-24 20:47:31 +00:00
exports.startWithDebugging = function(url, proxy, profileName, debuggingPort) {
2021-07-19 16:27:22 +00:00
return (new ChromeObject())
2021-07-19 14:32:47 +00:00
.setProxy(proxy)
.setProfile(profileName, null)
.setUserDataDir(null)
.setDebuggingPort(debuggingPort)
2021-07-19 16:27:22 +00:00
.open(url)
2021-06-19 20:57:17 +00:00
;
2021-06-19 20:51:34 +00:00
};