1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! Support for the Chrome browser.

use super::*;

use std::process::{Command, Child, Stdio};
use std::thread;
use std::time::Duration;
use std::ffi::OsString;

use super::util;

pub struct ChromeDriverBuilder {
    driver_binary: OsString,
    port: Option<u16>,
    kill_on_drop: bool,
}

impl ChromeDriverBuilder {
    pub fn new() -> Self {
        ChromeDriverBuilder {
            driver_binary: "chromedriver".into(),
            port: None,
            kill_on_drop: true,
        }
    }
    pub fn driver_path<S: Into<OsString>>(mut self, path: S) -> Self {
        self.driver_binary = path.into();
        self
    }
    pub fn port(mut self, port: u16) -> Self {
        self.port = Some(port);
        self
    }
    pub fn kill_on_drop(mut self, kill: bool) -> Self {
        self.kill_on_drop = kill;
        self
    }
    pub fn spawn(self) -> Result<ChromeDriver, Error> {
        let port = util::check_tcp_port(self.port)?;

        let child = Command::new(self.driver_binary)
            .arg(format!("--port={}", port))
            .stdin(Stdio::null())
            .stderr(Stdio::null())
            .stdout(Stdio::null())
            .spawn()?;

        // TODO: parameterize this
        thread::sleep(Duration::new(1, 500));
        Ok(ChromeDriver {
            child: child,
            url: format!("http://localhost:{}", port),
            kill_on_drop: self.kill_on_drop,
        })
    }
}


/// A chromedriver process
pub struct ChromeDriver {
    child: Child,
    url: String,
    kill_on_drop: bool,
}

impl ChromeDriver {
    pub fn spawn() -> Result<Self, Error> {
        ChromeDriverBuilder::new().spawn()
    }
    pub fn build() -> ChromeDriverBuilder {
        ChromeDriverBuilder::new()
    }
}

impl Drop for ChromeDriver {
    fn drop(&mut self) {
        if self.kill_on_drop {
            let _ = self.child.kill();
        }
    }
}

impl Driver for ChromeDriver {
    fn url(&self) -> &str {
        &self.url
    }
}