@@ -19,52 +19,80 @@ import path from 'path';
1919
2020puppeteer . use ( StealthPlugin ( ) ) ;
2121
22+ export async function launchBrowser ( url , options ) {
23+ const preCfg = getPreLaunchConfig ( url , options || { } ) ;
24+ const launchArgs = [
25+ '--no-sandbox' ,
26+ '--disable-gpu' ,
27+ '--disable-setuid-sandbox' ,
28+ '--disable-dev-shm-usage' ,
29+ '--disable-crash-reporter' ,
30+ '--no-first-run' ,
31+ '--no-default-browser-check' ,
32+ preCfg . langArg ,
33+ preCfg . windowSizeArg ,
34+ ...preCfg . extraArgs ,
35+ ] ;
36+ if ( options ?. proxyUrl ) {
37+ launchArgs . push ( `--proxy-server=${ options . proxyUrl } ` ) ;
38+ }
39+
40+ let userDataDir ;
41+ let removeUserDataDir = false ;
42+ if ( options && options . userDataDir ) {
43+ userDataDir = options . userDataDir ;
44+ } else {
45+ const prefix = path . join ( os . tmpdir ( ) , 'puppeteer-fredy-' ) ;
46+ userDataDir = fs . mkdtempSync ( prefix ) ;
47+ removeUserDataDir = true ;
48+ }
49+
50+ const browser = await puppeteer . launch ( {
51+ headless : options ?. puppeteerHeadless ?? true ,
52+ args : launchArgs ,
53+ timeout : options ?. puppeteerTimeout || 30_000 ,
54+ userDataDir,
55+ executablePath : options ?. executablePath ,
56+ } ) ;
57+
58+ browser . __fredy_userDataDir = userDataDir ;
59+ browser . __fredy_removeUserDataDir = removeUserDataDir ;
60+
61+ return browser ;
62+ }
63+
64+ export async function closeBrowser ( browser ) {
65+ if ( ! browser ) return ;
66+ const userDataDir = browser . __fredy_userDataDir ;
67+ const removeUserDataDir = browser . __fredy_removeUserDataDir ;
68+ try {
69+ await browser . close ( ) ;
70+ } catch {
71+ // ignore
72+ }
73+ if ( removeUserDataDir && userDataDir ) {
74+ try {
75+ await fs . promises . rm ( userDataDir , { recursive : true , force : true } ) ;
76+ } catch {
77+ // ignore
78+ }
79+ }
80+ }
81+
2282export default async function execute ( url , waitForSelector , options ) {
23- let browser ;
83+ let browser = options ?. browser ;
84+ let isExternalBrowser = ! ! browser ;
2485 let page ;
2586 let result ;
26- let userDataDir ;
27- let removeUserDataDir = false ;
2887 try {
2988 debug ( `Sending request to ${ url } using Puppeteer.` ) ;
3089
31- // Prepare a dedicated temporary userDataDir to avoid leaking /tmp/.org.chromium.* dirs
32- if ( options && options . userDataDir ) {
33- userDataDir = options . userDataDir ;
34- removeUserDataDir = ! ! options . cleanupUserDataDir ;
35- } else {
36- const prefix = path . join ( os . tmpdir ( ) , 'puppeteer-fredy-' ) ;
37- userDataDir = fs . mkdtempSync ( prefix ) ;
38- removeUserDataDir = true ;
90+ if ( ! isExternalBrowser ) {
91+ browser = await launchBrowser ( url , options ) ;
3992 }
4093
41- const launchArgs = [
42- '--no-sandbox' ,
43- '--disable-gpu' ,
44- '--disable-setuid-sandbox' ,
45- '--disable-dev-shm-usage' ,
46- '--disable-crash-reporter' ,
47- '--no-first-run' ,
48- '--no-default-browser-check' ,
49- ] ;
50- if ( options ?. proxyUrl ) {
51- launchArgs . push ( `--proxy-server=${ options . proxyUrl } ` ) ;
52- }
53- // Prepare bot prevention pre-launch config
54- const preCfg = getPreLaunchConfig ( url , options || { } ) ;
55- launchArgs . push ( preCfg . langArg ) ;
56- launchArgs . push ( preCfg . windowSizeArg ) ;
57- launchArgs . push ( ...preCfg . extraArgs ) ;
58-
59- browser = await puppeteer . launch ( {
60- headless : options ?. puppeteerHeadless ?? true ,
61- args : launchArgs ,
62- timeout : options ?. puppeteerTimeout || 30_000 ,
63- userDataDir,
64- executablePath : options ?. executablePath , // allow using system Chrome
65- } ) ;
66-
6794 page = await browser . newPage ( ) ;
95+ const preCfg = getPreLaunchConfig ( url , options || { } ) ;
6896 await applyBotPreventionToPage ( page , preCfg ) ;
6997 // Provide languages value before navigation
7098 await applyLanguagePersistence ( page , preCfg ) ;
@@ -104,7 +132,7 @@ export default async function execute(url, waitForSelector, options) {
104132 result = pageSource || ( await page . content ( ) ) ;
105133 }
106134 } catch ( error ) {
107- if ( error ?. message ?. includes ( 'Timeout' ) ) {
135+ if ( error ?. name ?. includes ( 'Timeout' ) ) {
108136 logger . debug ( 'Error executing with puppeteer executor' , error ) ;
109137 } else {
110138 logger . warn ( 'Error executing with puppeteer executor' , error ) ;
@@ -118,19 +146,8 @@ export default async function execute(url, waitForSelector, options) {
118146 } catch {
119147 // ignore
120148 }
121- try {
122- if ( browser != null ) {
123- await browser . close ( ) ;
124- }
125- } catch {
126- // ignore
127- }
128- try {
129- if ( removeUserDataDir && userDataDir ) {
130- await fs . promises . rm ( userDataDir , { recursive : true , force : true } ) ;
131- }
132- } catch {
133- // ignore
149+ if ( browser != null && ! isExternalBrowser ) {
150+ await closeBrowser ( browser ) ;
134151 }
135152 }
136153 return result ;
0 commit comments