Skip to content

Commit 5ad1a6b

Browse files
committed
webdriver refactor
Signed-off-by: Andrei Gherghescu <[email protected]>
1 parent a31eff6 commit 5ad1a6b

File tree

1 file changed

+75
-62
lines changed

1 file changed

+75
-62
lines changed

plotly_static/src/webdriver.rs

Lines changed: 75 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -208,95 +208,108 @@ impl WebDriver {
208208

209209
fn spawn_process(&self, driver_path: &Option<PathBuf>, port: u32) -> Result<Child> {
210210
let driver_path = driver_path.as_ref().unwrap(); // Safe unwrap since we validated above
211-
let mut command = Command::new(driver_path);
212-
command.arg(format!("--port={port}"));
213-
214-
// Add verbose flag only for chromedriver
215-
#[cfg(feature = "chromedriver")]
216-
command.arg("--verbose");
217-
218-
command
219-
.stdin(Stdio::piped())
220-
.stdout(Stdio::piped())
221-
.stderr(Stdio::piped());
222-
223-
info!(
224-
"Executing command: {:?} {:?}",
225-
command.get_program(),
226-
command.get_args()
227-
);
228-
229-
#[cfg(target_os = "windows")]
230-
{
231-
use std::os::windows::process::CommandExt;
232-
// Try with CREATE_NO_WINDOW for headless operation
233-
command.creation_flags(0x08000000); // CREATE_NO_WINDOW flag
234-
}
211+
212+
let mut command = Self::create_command(driver_path, port);
213+
Self::log_command(&command);
235214

236-
// Try to spawn the process
237215
match command.spawn() {
238216
Ok(child) => Ok(child),
239217
Err(e) => {
218+
#[cfg(not(target_os = "windows"))]
219+
{
220+
Err(self.handle_spawn_error(e, &command, "standard method"))
221+
}
240222
#[cfg(target_os = "windows")]
241223
{
242224
// If CREATE_NO_WINDOW fails, try without any special flags
243225
error!("Failed to spawn with CREATE_NO_WINDOW: {e}");
244226
error!("Trying without special creation flags...");
245227

246-
let mut fallback_command = Command::new(driver_path);
247-
fallback_command.arg(format!("--port={port}"));
248-
249-
#[cfg(feature = "chromedriver")]
250-
fallback_command.arg("--verbose");
251-
252-
fallback_command
253-
.stdin(Stdio::piped())
254-
.stdout(Stdio::piped())
255-
.stderr(Stdio::piped());
228+
let fallback_command = Self::standard_command(driver_path, port);
229+
Self::log_command(&fallback_command);
256230

257231
match fallback_command.spawn() {
258232
Ok(child) => {
259233
info!("Successfully spawned WebDriver without special creation flags");
260234
Ok(child)
261235
}
262236
Err(fallback_e) => {
263-
error!("Failed to spawn '{WEBDRIVER_BIN}' with fallback method: {fallback_e}");
264237
error!("Original error: {e}");
265238
error!("Fallback error: {fallback_e}");
266-
error!(
267-
"Command was: {:?} {:?}",
268-
command.get_program(),
269-
command.get_args()
270-
);
271-
error!("Windows: Check if antivirus is blocking the process");
272-
error!("Windows: Check if the binary has proper permissions");
273-
error!(
274-
"WebDriver diagnostics after spawn failure:\n{}",
275-
self.get_diagnostics()
276-
);
277-
Err(anyhow!("Failed to spawn '{WEBDRIVER_BIN}': {}", fallback_e))
239+
Err(self.handle_spawn_error(fallback_e, &fallback_command, "fallback method"))
278240
}
279241
}
280242
}
281243

282-
#[cfg(not(target_os = "windows"))]
283-
{
284-
error!("Failed to spawn '{WEBDRIVER_BIN}': {e}");
285-
error!(
286-
"Command was: {:?} {:?}",
287-
command.get_program(),
288-
command.get_args()
289-
);
290-
error!(
291-
"WebDriver diagnostics after spawn failure:\n{}",
292-
self.get_diagnostics()
293-
);
294-
Err(anyhow!("Failed to spawn '{WEBDRIVER_BIN}': {}", e))
295-
}
296244
}
297245
}
298246
}
299247

248+
/// Creates a command with standard configuration (no Windows flags)
249+
fn standard_command(driver_path: &PathBuf, port: u32) -> Command {
250+
let mut command = Command::new(driver_path);
251+
command.arg(format!("--port={port}"));
252+
253+
// Add verbose flag only for chromedriver
254+
#[cfg(feature = "chromedriver")]
255+
command.arg("--verbose");
256+
257+
command
258+
.stdin(Stdio::piped())
259+
.stdout(Stdio::piped())
260+
.stderr(Stdio::piped());
261+
262+
command
263+
}
264+
265+
/// Creates a command with Windows-specific flags
266+
#[cfg(target_os = "windows")]
267+
fn create_command(driver_path: &PathBuf, port: u32) -> Command {
268+
use std::os::windows::process::CommandExt;
269+
270+
let mut command = Self::standard_command(driver_path, port);
271+
// Try with CREATE_NO_WINDOW for headless operation
272+
command.creation_flags(0x08000000); // CREATE_NO_WINDOW flag
273+
command
274+
}
275+
276+
#[cfg(not(target_os = "windows"))]
277+
fn create_command(driver_path: &PathBuf, port: u32) -> Command {
278+
Self::standard_command(driver_path, port)
279+
}
280+
281+
/// Logs command execution details
282+
fn log_command(command: &Command) {
283+
info!(
284+
"Executing command: {:?} {:?}",
285+
command.get_program(),
286+
command.get_args()
287+
);
288+
}
289+
290+
/// Handles spawn errors with appropriate logging and diagnostics
291+
fn handle_spawn_error(&self, e: std::io::Error, command: &Command, attempt: &str) -> anyhow::Error {
292+
error!("Failed to spawn '{WEBDRIVER_BIN}' with {attempt}: {e}");
293+
error!(
294+
"Command was: {:?} {:?}",
295+
command.get_program(),
296+
command.get_args()
297+
);
298+
299+
#[cfg(target_os = "windows")]
300+
if attempt == "CREATE_NO_WINDOW" {
301+
error!("Windows: Check if antivirus is blocking the process");
302+
error!("Windows: Check if the binary has proper permissions");
303+
}
304+
305+
error!(
306+
"WebDriver diagnostics after spawn failure:\n{}",
307+
self.get_diagnostics()
308+
);
309+
310+
anyhow!("Failed to spawn '{WEBDRIVER_BIN}': {}", e)
311+
}
312+
300313
fn setup_output_monitoring(&self, child: &mut Child, port: u32) {
301314
// Monitor stderr
302315
if let Some(stderr) = child.stderr.take() {

0 commit comments

Comments
 (0)