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 ("brave", true),
72 ("msedge", options.msedge),
73 ("microsoft-edge", options.msedge),
74 ("microsoft-edge-stable", options.msedge),
75 ("microsoft-edge-beta", options.msedge && options.unstable),
76 ("microsoft-edge-dev", options.msedge && options.unstable),
77 ];
78 for (app, allowed) in default_apps {
79 if !allowed {
80 continue;
81 }
82 if let Ok(path) = which::which(app) {
83 return Some(path);
84 }
85 }
86
87 None
88}
89
90#[cfg(not(feature = "auto-detect-executable"))]
91fn get_by_name(_options: &DetectionOptions) -> Option<PathBuf> {
92 None
93}
94
95#[allow(unused_variables)]
96fn get_by_path(options: &DetectionOptions) -> Option<PathBuf> {
97 #[cfg(all(unix, not(target_os = "macos")))]
98 let default_paths: [(&str, bool); 3] = [
99 ("/opt/chromium.org/chromium", true),
100 ("/opt/google/chrome", true),
101 ("/tmp/aws/lib", true),
103 ];
104 #[cfg(windows)]
105 let default_paths = [(
106 r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
107 options.msedge,
108 )];
109 #[cfg(target_os = "macos")]
110 let default_paths = [
111 (
112 "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
113 true,
114 ),
115 (
116 "/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta",
117 options.unstable,
118 ),
119 (
120 "/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev",
121 options.unstable,
122 ),
123 (
124 "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
125 options.unstable,
126 ),
127 ("/Applications/Chromium.app/Contents/MacOS/Chromium", true),
128 (
129 "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
130 options.msedge,
131 ),
132 (
133 "/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta",
134 options.msedge && options.unstable,
135 ),
136 (
137 "/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev",
138 options.msedge && options.unstable,
139 ),
140 (
141 "/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary",
142 options.msedge && options.unstable,
143 ),
144 ];
145
146 for (path, allowed) in default_paths {
147 if !allowed {
148 continue;
149 }
150 if Path::new(path).exists() {
151 return Some(path.into());
152 }
153 }
154
155 None
156}
157
158#[cfg(windows)]
159fn get_by_registry() -> Option<PathBuf> {
160 winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE)
161 .open_subkey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe")
162 .or_else(|_| {
163 winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER)
164 .open_subkey("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe")
165 })
166 .and_then(|key| key.get_value::<String, _>(""))
167 .map(PathBuf::from)
168 .ok()
169}