chromiumoxide/
detection.rs1use std::env;
2use std::path::{Path, PathBuf};
3
4#[derive(Debug, Clone)]
5pub struct DetectionOptions {
6 pub msedge: bool,
8 pub unstable: bool,
10}
11
12impl Default for DetectionOptions {
13 fn default() -> Self {
14 Self {
15 msedge: true,
16 unstable: false,
17 }
18 }
19}
20
21pub fn default_executable(options: DetectionOptions) -> Result<std::path::PathBuf, String> {
30 if let Some(path) = get_by_env_var() {
31 return Ok(path);
32 }
33
34 if let Some(path) = get_by_name(&options) {
35 return Ok(path);
36 }
37
38 #[cfg(windows)]
39 if let Some(path) = get_by_registry() {
40 return Ok(path);
41 }
42
43 if let Some(path) = get_by_path(&options) {
44 return Ok(path);
45 }
46
47 Err("Could not auto detect a chrome executable".to_string())
48}
49
50fn get_by_env_var() -> Option<PathBuf> {
51 if let Ok(path) = env::var("CHROME") {
52 if Path::new(&path).exists() {
53 return Some(path.into());
54 }
55 }
56
57 None
58}
59
60#[cfg(feature = "auto-detect-executable")]
61fn get_by_name(options: &DetectionOptions) -> Option<PathBuf> {
62 let default_apps = [
63 ("chrome", true),
64 ("chrome-browser", true),
65 ("google-chrome-stable", true),
66 ("google-chrome-beta", options.unstable),
67 ("google-chrome-dev", options.unstable),
68 ("google-chrome-unstable", options.unstable),
69 ("chromium", true),
70 ("chromium-browser", true),
71 ("msedge", options.msedge),
72 ("microsoft-edge", options.msedge),
73 ("microsoft-edge-stable", options.msedge),
74 ("microsoft-edge-beta", options.msedge && options.unstable),
75 ("microsoft-edge-dev", options.msedge && options.unstable),
76 ];
77 for (app, allowed) in default_apps {
78 if !allowed {
79 continue;
80 }
81 if let Ok(path) = which::which(app) {
82 return Some(path);
83 }
84 }
85
86 None
87}
88
89#[cfg(not(feature = "auto-detect-executable"))]
90fn get_by_name(_options: &DetectionOptions) -> Option<PathBuf> {
91 None
92}
93
94#[allow(unused_variables)]
95fn get_by_path(options: &DetectionOptions) -> Option<PathBuf> {
96 #[cfg(all(unix, not(target_os = "macos")))]
97 let default_paths: [(&str, bool); 3] = [
98 ("/opt/chromium.org/chromium", true),
99 ("/opt/google/chrome", true),
100 ("/tmp/aws/lib", true),
102 ];
103 #[cfg(windows)]
104 let default_paths = [(
105 r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
106 options.msedge,
107 )];
108 #[cfg(target_os = "macos")]
109 let default_paths = [
110 (
111 "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
112 true,
113 ),
114 (
115 "/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta",
116 options.unstable,
117 ),
118 (
119 "/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev",
120 options.unstable,
121 ),
122 (
123 "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
124 options.unstable,
125 ),
126 ("/Applications/Chromium.app/Contents/MacOS/Chromium", true),
127 (
128 "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
129 options.msedge,
130 ),
131 (
132 "/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta",
133 options.msedge && options.unstable,
134 ),
135 (
136 "/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev",
137 options.msedge && options.unstable,
138 ),
139 (
140 "/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary",
141 options.msedge && options.unstable,
142 ),
143 ];
144
145 for (path, allowed) in default_paths {
146 if !allowed {
147 continue;
148 }
149 if Path::new(path).exists() {
150 return Some(path.into());
151 }
152 }
153
154 None
155}
156
157#[cfg(windows)]
158fn get_by_registry() -> Option<PathBuf> {
159 winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE)
160 .open_subkey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe")
161 .or_else(|_| {
162 winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER)
163 .open_subkey("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe")
164 })
165 .and_then(|key| key.get_value::<String, _>(""))
166 .map(PathBuf::from)
167 .ok()
168}