Skip to main content

headless_browser_lib/
conf.rs

1use std::sync::atomic::{AtomicBool, AtomicU64};
2
3/// The performance arg count.
4#[cfg(not(feature = "physical_gpu"))]
5pub(crate) const PERF_ARGS: usize = 99;
6
7/// The performance arg count.
8#[cfg(feature = "physical_gpu")]
9pub(crate) const PERF_ARGS: usize = 97;
10
11lazy_static::lazy_static! {
12    /// The chrome args to use test ( basic without anything used for testing ).
13    pub static ref CHROME_ARGS_TEST: [&'static str; 6] = {
14        let headless = std::env::args()
15        .nth(6)
16        .unwrap_or("true".into());
17
18        let headless = if headless != "false" {
19            match std::env::var("HEADLESS") {
20                Ok(h) => {
21                    if h == "false" {
22                        ""
23                    } else if h == "new" {
24                        "--headless=new"
25                    }else {
26                        "--headless"
27                    }
28                }
29                _ => "--headless"
30            }
31        } else {
32            ""
33        };
34
35        let port = if DEFAULT_PORT.eq(&9223) {
36            "--remote-debugging-port=9223"
37        } else if DEFAULT_PORT.eq(&9224) {
38            "--remote-debugging-port=9224"
39        } else {
40            "--remote-debugging-port=9222"
41        };
42
43        let use_gl = match std::env::var("CHROME_GL") {
44            Ok(h) => {
45                if h == "angle" {
46                    "--use-gl=angle"
47                } else {
48                    "--use-gl=swiftshader"
49                }
50            }
51            _ => "--use-gl=angle"
52        };
53
54        let gpu = std::env::var("ENABLE_GPU").unwrap_or_default() == "true";
55
56        let gpu_enabled = if gpu { "--enable-gpu" } else { "--disable-gpu" };
57        let gpu_enabled_sandboxed = if gpu { "--enable-gpu-sandbox" } else { "--disable-gpu-sandbox" };
58
59        [
60            // *SPECIAL*
61            "--remote-debugging-address=0.0.0.0",
62            port,
63            // *SPECIAL*
64            headless,
65            gpu_enabled,
66            gpu_enabled_sandboxed,
67            use_gl,
68        ]
69    };
70}
71
72lazy_static::lazy_static! {
73    /// Is the instance healthy?
74    pub static ref IS_HEALTHY: AtomicBool = AtomicBool::new(true);
75    pub static ref CHROME_INSTANCES: dashmap::DashSet<u32> = dashmap::DashSet::new();
76    pub static ref DEFAULT_PORT: u32 = {
77        let default_port = std::env::args()
78            .nth(4)
79            .unwrap_or("9223".into())
80            .parse::<u32>()
81            .unwrap_or_default();
82
83        let default_port = if default_port == 0 {
84            9223
85        } else {
86            default_port
87        };
88
89        default_port
90    };
91    pub static ref DEFAULT_PORT_SERVER: u16 = {
92        let default_port = std::env::args()
93            .nth(5)
94            .unwrap_or("6000".into())
95            .parse::<u16>()
96            .unwrap_or_default();
97        let default_port = if default_port == 0 {
98            6000
99        } else {
100            default_port
101        };
102
103        default_port
104    };
105    /// Is a brave instance?
106    pub(crate) static ref BRAVE_INSTANCE: bool = {
107        CHROME_PATH.ends_with("Brave Browser")
108        || CHROME_PATH.ends_with("brave-browser")
109    };
110    /// Is a lightpanda instance?
111    pub(crate) static ref LIGHT_PANDA: bool = {
112        CHROME_PATH.ends_with("lightpanda-aarch64-macos")
113        || CHROME_PATH.ends_with("lightpanda-x86_64-linux")
114    };
115    /// The light panda args to use.
116    pub static ref LIGHTPANDA_ARGS: [&'static str; 2] = {
117        let port = if DEFAULT_PORT.eq(&9223) {
118            "--port=9223"
119        } else if DEFAULT_PORT.eq(&9224) {
120            "--port=9224"
121        } else {
122            "--port=9222"
123        };
124
125        [
126            "--host=0.0.0.0",
127            port,
128        ]
129    };
130    /// Return base target and replacement. Target port is the port for chrome.
131    pub(crate) static ref TARGET_REPLACEMENT: (&'static [u8; 5], &'static[u8; 5]) = {
132        if *DEFAULT_PORT == 9223 {
133            let target_port = b":9223";
134            let proxy_port = b":9222";
135
136            (target_port, proxy_port)
137        } else {
138            // we need to allow dynamic ports instead of defaulting to standard and xfvb offport.
139            let target_port = b":9224";
140            let proxy_port = b":9223";
141
142            (target_port, proxy_port)
143        }
144    };
145    /// The hostname of the machine to replace 127.0.0.1 when making request to /json/version on port 6000.
146    pub(crate) static ref HOST_NAME: String = {
147        let mut hostname = String::new();
148
149        if let Ok(name) = std::env::var("HOSTNAME_OVERRIDE") {
150            if !name.is_empty() {
151                hostname = name;
152            }
153        }
154
155        if hostname.is_empty() {
156            if let Ok(name) = std::env::var("HOSTNAME") {
157                if !name.is_empty() {
158                    hostname = name;
159                }
160            }
161        }
162
163        hostname
164    };
165    /// The main endpoint for entry.
166    pub(crate) static ref ENDPOINT_BASE: String = {
167        format!("http://127.0.0.1:{}", *DEFAULT_PORT)
168    };
169    /// The main endpoint json/version.
170    pub(crate) static ref ENDPOINT: String = {
171        format!("http://127.0.0.1:{}/json/version", *DEFAULT_PORT)
172    };
173    /// The chrome launch path.
174    pub static ref CHROME_PATH: String = {
175        // cargo bench will always pass in the first arg
176        let default_path = std::env::args().nth(1).unwrap_or_default();
177        let trimmed_path = default_path.trim();
178
179        // handle testing and default to OS
180        if default_path.is_empty() || trimmed_path == "--nocapture" || trimmed_path == "--bench" {
181            let chrome_path = match std::env::var("CHROME_PATH") {
182                Ok(p) => p,
183                _ => Default::default()
184            };
185
186            if chrome_path.is_empty() {
187                get_default_chrome_bin().to_string()
188            } else {
189                chrome_path
190            }
191        } else {
192            default_path
193        }
194    };
195    /// The chrome address.
196    pub(crate) static ref CHROME_ADDRESS: String = {
197        let mut host_address = std::env::args().nth(2).unwrap_or("127.0.0.1".to_string()).to_string();
198
199        if host_address.is_empty() {
200            host_address = String::from("127.0.0.1").into()
201        }
202
203        host_address
204    };
205    pub(crate) static ref CACHEABLE: AtomicBool = {
206        AtomicBool::new(true)
207    };
208    /// The last cache date period.
209    pub(crate) static ref LAST_CACHE: AtomicU64 = {
210        AtomicU64::new(0)
211    };
212    /// Debug the json version endpoint.
213    pub(crate) static ref DEBUG_JSON: bool = std::env::var("DEBUG_JSON").unwrap_or_default() == "true";
214    /// Test headless without args.
215    pub(crate) static ref TEST_NO_ARGS: bool = std::env::var("TEST_NO_ARGS").unwrap_or_default() == "true";
216    /// Entry port to the proxy.
217    pub(crate) static ref ENTRY: &'static str = {
218        if crate::TARGET_REPLACEMENT.0 == b":9223" {
219            "0.0.0.0:9222"
220        } else {
221            "0.0.0.0:9223"
222        }
223    };
224    /// Target chrome server.
225    pub(crate) static ref TARGET: &'static str = {
226        if crate::TARGET_REPLACEMENT.1 == b":9222" {
227            "0.0.0.0:9223"
228        } else {
229            "0.0.0.0:9224"
230        }
231    };
232    /// The buffer size.
233    pub(crate) static ref BUFFER_SIZE: usize = {
234        let buffer_size = std::env::var("BUFFER_SIZE")
235            .ok()
236            .and_then(|s| s.parse().ok())
237            .unwrap_or(131072); // Default to 128kb
238        buffer_size
239    };
240    /// 10 sec cache
241    pub(crate) static ref TEN_SECONDS: std::time::Duration = {
242        std::time::Duration::from_secs(10)
243    };
244}
245
246#[cfg(not(feature = "physical_gpu"))]
247lazy_static::lazy_static! {
248        /// The chrome args to use.
249        pub static ref CHROME_ARGS: [&'static str; PERF_ARGS] = {
250            let headless = std::env::args()
251            .nth(6)
252            .unwrap_or("true".into());
253
254            let headless = match (headless != "false", std::env::var("HEADLESS").as_deref()) {
255                (false, _) | (true, Ok("false")) => "--test-type=gpu",
256                (_, Ok("new")) => "--headless=new",
257                _ => "--headless",
258            };
259
260            let port = if DEFAULT_PORT.eq(&9223) {
261                "--remote-debugging-port=9223"
262            } else if DEFAULT_PORT.eq(&9224) {
263                "--remote-debugging-port=9224"
264            } else {
265                "--remote-debugging-port=9222"
266            };
267            let gpu = std::env::var("ENABLE_GPU").unwrap_or_default() == "true";
268            let gpu_enabled = if gpu { "--enable-gpu" } else { "--disable-gpu" };
269            let gpu_enabled_sandboxed = if gpu { "--enable-gpu-sandbox" } else { "--disable-gpu-sandbox" };
270
271            let use_gl = match std::env::var("CHROME_GL") {
272                Ok(h) => {
273                    if h == "angle" {
274                        "--use-gl=angle"
275                    } else {
276                        "--use-gl=swiftshader"
277                    }
278                }
279                _ => "--use-gl=swiftshader"
280            };
281
282            [
283                // *SPECIAL*
284                "--remote-debugging-address=0.0.0.0",
285                port,
286                // *SPECIAL*
287                headless,
288                gpu_enabled,
289                gpu_enabled_sandboxed,
290                use_gl,
291                "--no-zygote",
292                "--user-data-dir=~/.config/google-chrome",
293                "--ignore-certificate-errors",
294                "--no-default-browser-check",
295                "--no-first-run",
296                "--no-sandbox",
297                "--enable-webgl",
298                "--enable-webgl2-compute-context",
299                "--enable-webgl-draft-extensions",
300                "--enable-unsafe-webgpu",
301                "--enable-web-bluetooth",
302                "--enable-dom-distiller",
303                "--enable-distillability-service",
304                "--enable-surface-synchronization",
305                "--enable-logging=stderr",
306                "--enable-async-dns",
307                "--disable-setuid-sandbox",
308                "--disable-dev-shm-usage", // required or else container will crash not enough memory
309                "--disable-threaded-scrolling",
310                "--disable-cookie-encryption",
311                "--disable-demo-mode",
312                "--disable-dinosaur-easter-egg",
313                "--disable-fetching-hints-at-navigation-start",
314                "--disable-site-isolation-trials",
315                "--disable-threaded-animation",
316                "--disable-sync",
317                "--disable-print-preview",
318                "--disable-search-engine-choice-screen",
319                "--disable-in-process-stack-traces",
320                "--disable-low-res-tiling",
321                "--disable-oobe-chromevox-hint-timer-for-testing",
322                "--disable-smooth-scrolling",
323                "--disable-prompt-on-repost",
324                "--disable-domain-reliability",
325                "--disable-gesture-typing",
326                "--disable-background-timer-throttling",
327                "--disable-breakpad",
328                "--disable-crash-reporter",
329                "--disable-asynchronous-spellchecking",
330                "--disable-html5-camera",
331                "--disable-hang-monitor",
332                "--disable-checker-imaging",
333                "--disable-image-animation-resync",
334                "--disable-client-side-phishing-detection",
335                "--disable-component-extensions-with-background-pages",
336                "--disable-background-networking",
337                "--disable-renderer-backgrounding",
338                "--disable-field-trial-config",
339                "--disable-back-forward-cache",
340                "--disable-backgrounding-occluded-windows",
341                "--disable-stack-profiler",
342                "--disable-libassistant-logfile",
343                "--disable-datasaver-prompt",
344                "--disable-histogram-customizer",
345                "--disable-vulkan-fallback-to-gl-for-testing",
346                "--disable-vulkan-surface",
347                "--disable-webrtc",
348                "--disable-oopr-debug-crash-dump",
349                "--disable-pnacl-crash-throttling",
350                "--disable-renderer-accessibility",
351                "--disable-pushstate-throttle",
352                "--disable-blink-features=AutomationControlled",
353                "--disable-ipc-flooding-protection", // we do not need to throttle navigation for https://github.com/spider-rs/spider/commit/9ff5bbd7a2656b8edb84b62843b72ae9d09af079#diff-75ce697faf0d37c3dff4a3a19e7524798b3cb5487f8f54beb5d04c4d48e34234R446.
354                "--noerrdialogs",
355                "--hide-scrollbars",
356                "--allow-running-insecure-content",
357                "--autoplay-policy=user-gesture-required",
358                "--run-all-compositor-stages-before-draw",
359                "--log-level=3",
360                "--font-render-hinting=none",
361                "--block-new-web-contents",
362                "--no-subproc-heap-profiling",
363                "--use-fake-device-for-media-stream",
364                "--use-fake-ui-for-media-stream",
365                "--no-pre-read-main-dll",
366                "--ip-protection-proxy-opt-out",
367                "--unsafely-disable-devtools-self-xss-warning",
368                "--metrics-recording-only",
369                "--use-mock-keychain",
370                "--force-color-profile=srgb",
371                "--disable-infobars",
372                "--mute-audio",
373                "--no-service-autorun",
374                "--password-store=basic",
375                "--export-tagged-pdf",
376                "--no-pings",
377                "--rusty-png",
378                "--window-size=800,600",
379                &crate::render_conf::RENDER_PROCESS_LIMIT,
380                // --deterministic-mode 10-20% drop in perf
381                // "--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4",
382                "--enable-features=Vulkan,PdfOopif,SharedArrayBuffer,NetworkService,NetworkServiceInProcess",
383                "--disable-features=PaintHolding,HttpsUpgrades,DeferRendererTasksAfterInput,LensOverlay,ThirdPartyStoragePartitioning,IsolateSandboxedIframes,ProcessPerSiteUpToMainFrameThreshold,site-per-process,WebUIJSErrorReportingExtended,DIPS,InterestFeedContentSuggestions,PrivacySandboxSettings4,AutofillServerCommunication,CalculateNativeWinOcclusion,OptimizationHints,AudioServiceOutOfProcess,IsolateOrigins,ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate",
384                // put these args on the same command for now to prevent empty args cross-platform execution. The args will be one less on gpu enabled builds.
385                "--enable-unsafe-swiftshader",
386                "--use-angle=swiftshader"
387            ]
388        };
389}
390
391#[cfg(feature = "physical_gpu")]
392lazy_static::lazy_static! {
393        /// The chrome args to use.
394        pub static ref CHROME_ARGS: [&'static str; PERF_ARGS] = {
395            let headless = std::env::args()
396            .nth(6)
397            .unwrap_or("true".into());
398
399            let headless = match (headless != "false", std::env::var("HEADLESS").as_deref()) {
400                (false, _) | (true, Ok("false")) => "--test-type=gpu",
401                (_, Ok("new")) => "--headless=new",
402                _ => "--headless",
403            };
404
405            let port = if DEFAULT_PORT.eq(&9223) {
406                "--remote-debugging-port=9223"
407            } else if DEFAULT_PORT.eq(&9224) {
408                "--remote-debugging-port=9224"
409            } else {
410                "--remote-debugging-port=9222"
411            };
412            let use_gl = "--use-gl=angle";
413
414            [
415                // *SPECIAL*
416                "--remote-debugging-address=0.0.0.0",
417                port,
418                // *SPECIAL*
419                headless,
420                "--enable-gpu",
421                "--enable-gpu-sandbox",
422                "--enable-webgl",
423                "--enable-webgl2-compute-context",
424                "--enable-webgl-draft-extensions",
425                "--enable-unsafe-webgpu",
426                use_gl,
427                "--no-first-run",
428                "--no-sandbox",
429                "--disable-setuid-sandbox",
430                "--no-zygote",
431                "--enable-async-dns",
432                "--hide-scrollbars",
433                "--user-data-dir=~/.config/google-chrome",
434                "--allow-running-insecure-content",
435                "--autoplay-policy=user-gesture-required",
436                "--ignore-certificate-errors",
437                "--no-default-browser-check",
438                "--disable-dev-shm-usage", // required or else container will crash not enough memory
439                "--disable-threaded-scrolling",
440                "--disable-cookie-encryption",
441                "--disable-demo-mode",
442                "--disable-dinosaur-easter-egg",
443                "--disable-fetching-hints-at-navigation-start",
444                "--disable-site-isolation-trials",
445                "--disable-threaded-animation",
446                "--disable-sync",
447                "--disable-print-preview",
448                "--disable-search-engine-choice-screen",
449                "--disable-in-process-stack-traces",
450                "--disable-low-res-tiling",
451                "--disable-oobe-chromevox-hint-timer-for-testing",
452                "--disable-smooth-scrolling",
453                "--disable-prompt-on-repost",
454                "--disable-domain-reliability",
455                "--enable-web-bluetooth",
456                "--enable-dom-distiller",
457                "--enable-distillability-service",
458                "--enable-surface-synchronization",
459                "--disable-gesture-typing",
460                "--disable-background-timer-throttling",
461                "--disable-breakpad",
462                "--disable-crash-reporter",
463                "--disable-asynchronous-spellchecking",
464                "--disable-html5-camera",
465                "--noerrdialogs",
466                "--disable-hang-monitor",
467                "--disable-checker-imaging",
468                "--disable-image-animation-resync",
469                "--disable-client-side-phishing-detection",
470                "--disable-component-extensions-with-background-pages",
471                "--run-all-compositor-stages-before-draw",
472                "--disable-background-networking",
473                "--disable-renderer-backgrounding",
474                "--disable-field-trial-config",
475                "--disable-back-forward-cache",
476                "--disable-backgrounding-occluded-windows",
477                "--log-level=3",
478                "--enable-logging=stderr",
479                "--font-render-hinting=none",
480                "--block-new-web-contents",
481                "--no-subproc-heap-profiling",
482                "--use-fake-device-for-media-stream",
483                "--use-fake-ui-for-media-stream",
484                "--no-pre-read-main-dll",
485                "--disable-stack-profiler",
486                "--disable-libassistant-logfile",
487                "--ip-protection-proxy-opt-out",
488                "--unsafely-disable-devtools-self-xss-warning",
489                "--enable-features=Vulkan,PdfOopif,SharedArrayBuffer,NetworkService,NetworkServiceInProcess",
490                "--metrics-recording-only",
491                "--use-mock-keychain",
492                "--force-color-profile=srgb",
493                "--disable-infobars",
494                "--mute-audio",
495                "--disable-datasaver-prompt",
496                "--no-service-autorun",
497                "--password-store=basic",
498                "--export-tagged-pdf",
499                "--no-pings",
500                "--rusty-png",
501                "--disable-histogram-customizer",
502                "--window-size=800,600",
503                "--disable-vulkan-fallback-to-gl-for-testing",
504                "--disable-vulkan-surface",
505                "--disable-webrtc",
506                "--disable-oopr-debug-crash-dump",
507                "--disable-pnacl-crash-throttling",
508                "--disable-renderer-accessibility",
509                &crate::render_conf::RENDER_PROCESS_LIMIT,
510                "--disable-pushstate-throttle",
511                "--disable-blink-features=AutomationControlled",
512                "--disable-ipc-flooding-protection", // we do not need to throttle navigation for https://github.com/spider-rs/spider/commit/9ff5bbd7a2656b8edb84b62843b72ae9d09af079#diff-75ce697faf0d37c3dff4a3a19e7524798b3cb5487f8f54beb5d04c4d48e34234R446.
513                // --deterministic-mode 10-20% drop in perf
514                // "--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4",
515                "--disable-features=PaintHolding,HttpsUpgrades,DeferRendererTasksAfterInput,LensOverlay,ThirdPartyStoragePartitioning,IsolateSandboxedIframes,ProcessPerSiteUpToMainFrameThreshold,site-per-process,WebUIJSErrorReportingExtended,DIPS,InterestFeedContentSuggestions,PrivacySandboxSettings4,AutofillServerCommunication,CalculateNativeWinOcclusion,OptimizationHints,AudioServiceOutOfProcess,IsolateOrigins,ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate",
516            ]
517        };
518}
519
520/// Get the default chrome bin location per OS.
521fn get_default_chrome_bin() -> &'static str {
522    let brave = match std::env::var("BRAVE_ENABLED") {
523        Ok(v) => v == "true",
524        _ => false,
525    };
526
527    if cfg!(target_os = "windows") {
528        if brave {
529            "brave-browser.exe"
530        } else {
531            "chrome.exe"
532        }
533    } else if cfg!(target_os = "macos") {
534        if brave {
535            "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
536        } else {
537            "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
538        }
539    } else if cfg!(target_os = "linux") {
540        if brave {
541            "brave-browser"
542        } else {
543            "chromium"
544        }
545    } else {
546        if brave {
547            "brave"
548        } else {
549            "chrome"
550        }
551    }
552}