-
Notifications
You must be signed in to change notification settings - Fork 99
Expand file tree
/
Copy pathACBrowserManager.ts
More file actions
127 lines (116 loc) · 4.59 KB
/
ACBrowserManager.ts
File metadata and controls
127 lines (116 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import * as puppeteer from "puppeteer";
import { ACConfigManager } from "./common/config/ACConfigManager.js";
import { IConfigInternal } from "./common/config/IConfig.js";
export class ACBrowserManager {
static browserP;
static config: IConfigInternal;
static numInits: 0;
static pages: any[] = [];
static async getBrowserChrome(force: boolean) {
if (!ACBrowserManager.config) {
ACBrowserManager.config = await ACConfigManager.getConfigUnsupported();
}
if (force || !ACBrowserManager.browserP) {
return ACBrowserManager.browserP = puppeteer.launch({headless: ACBrowserManager.config.headless, ignoreHTTPSErrors: ACBrowserManager.config.ignoreHTTPSErrors || false});
} else {
return ACBrowserManager.browserP;
}
}
static async close() {
if (ACBrowserManager.browserP) {
let browser = await ACBrowserManager.browserP;
await browser.close();
ACBrowserManager.browserP = null;
ACBrowserManager.pages = [];
}
}
/**
* This function is responsible for building an iframe object with the provided URL or local file.
*
* @param {String} URLorLocalFile - Provide a URL or local file to scan.
*
* @return {Object} content - return an object which contains the iframeDoc and also the URL or
* local file name.
*
* PRIVATE METHOD
*
* @memberOf this
*/
static async buildIframeAndGetDoc(URLorLocalFileorContent) {
if (!ACBrowserManager.config) {
ACBrowserManager.config = await ACConfigManager.getConfigUnsupported();
}
const MAX_TABS = ACBrowserManager.config.maxTabs;
const browser = await ACBrowserManager.getBrowserChrome(false);
// Clear out any pages that are already closed
ACBrowserManager.pages = ACBrowserManager.pages.filter((page) => page && !page.isClosed());
// If there's an existing, ready page, use it
let availPage;
for (const page of ACBrowserManager.pages) {
if (!availPage) {
if (!page.aceBusy) {
availPage = page;
page.aceBusy = true;
}
}
}
if (!availPage) {
// All pages are busy. Should we create a new one?
if (ACBrowserManager.pages.length+ACBrowserManager.numInits >= MAX_TABS) {
// Too many pages, restart
return new Promise((resolve, reject) => {
setTimeout(async () => {
resolve(await ACBrowserManager.buildIframeAndGetDoc(URLorLocalFileorContent));
}, 500);
});
} else {
// Let's create a new page
++ACBrowserManager.numInits;
let newPage = await browser.newPage();
newPage.on('console', msg => {
for (let i = 0; i < msg.args.length; ++i)
console.log(`${i}: ${msg.args[i]}`);
});
newPage.aceBusy = true;
availPage = newPage;
ACBrowserManager.pages.push(newPage);
--ACBrowserManager.numInits;
}
}
let err = null,
retVal = null;
async function nav() {
try {
if (URLorLocalFileorContent.toLowerCase().includes("<html")) {
// await page.goto(`data:text/html,encodeURIComponent(${URLorLocalFileorContent})`, { waitUntil: 'networkidle0' });
let urlStr = "data:text/html;charset=utf-8," + encodeURIComponent(URLorLocalFileorContent);
await availPage.goto(urlStr);
} else {
await availPage.goto(URLorLocalFileorContent);
}
} catch (e) {
err = `${e.message} ${URLorLocalFileorContent}`;
console.error(err);
return null;
}
return availPage;
}
try {
retVal = await nav();
} catch (e) {
}
if (!retVal) {
// Page bad or unable to navigate, start over
availPage.close();
return new Promise((resolve, reject) => {
setTimeout(async () => {
resolve(await ACBrowserManager.buildIframeAndGetDoc(URLorLocalFileorContent));
}, 0);
});
}
if (retVal === null) {
console.log("[Internal Error:load content]", err);
}
return retVal;
};
}