pub struct Browser { /* private fields */ }
Expand description

A handle to an instance of Chrome / Chromium, which wraps a WebSocket connection to its debugging port.

Most of your actual “driving” (e.g. clicking, typing, navigating) will be via instances of Tab, which are accessible via methods such as get_tabs.

A Browser can either manage its own Chrome process or connect to a remote one.

Browser::default().unwrap() will return a headless instance of whatever browser can be found using default_executable, which will search on your PATH for relevant binaries or use the path specified in the CHROME env var.

You can use LaunchOptions to automatically download a revision of Chromium that has a compatible API into your $XDG_DATA_DIR. Alternatively, you can specify your own path to a binary, or make use of the default_executable function to use your already-installed copy of Chrome.

Option 1: Managing a Chrome process

use headless_chrome::Browser;
let browser = Browser::default()?;
let first_tab = browser.wait_for_initial_tab()?;
assert_eq!("about:blank", first_tab.get_url());

Option 2: Connecting to a remote Chrome service

  • see /examples/print_to_pdf.rs for a working example

While the Chrome DevTools Protocol (CDTP) does define some methods in a “Browser” domain (such as for resizing the window in non-headless mode), we currently don’t implement those.

Implementations§

Launch a new Chrome browser.

The browser will have its user data (aka “profile”) directory stored in a temporary directory. The browser process will be killed when this struct is dropped.

Examples found in repository?
src/browser/mod.rs (line 111)
106
107
108
109
110
111
112
    pub fn default() -> Result<Self> {
        let launch_options = LaunchOptions::default_builder()
            .path(Some(default_executable().unwrap()))
            .build()
            .unwrap();
        Ok(Self::new(launch_options).unwrap())
    }

Calls [new] with options to launch a headless browser using whatever Chrome / Chromium binary can be found on the system.

Allows you to drive an externally-launched Chrome process instead of launch one via [new]. If the browser is idle for 30 seconds, the connection will be dropped.

Allows you to drive an externally-launched Chrome process instead of launch one via [new]. If the browser is idle for idle_browser_timeout, the connection will be dropped.

Examples found in repository?
src/browser/mod.rs (line 117)
116
117
118
    pub fn connect(debug_ws_url: String) -> Result<Self> {
        Self::connect_with_timeout(debug_ws_url, Duration::from_secs(30))
    }
Examples found in repository?
src/browser/mod.rs (line 156)
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
    fn create_browser(
        process: Option<Process>,
        transport: Arc<Transport>,
        idle_browser_timeout: Duration,
    ) -> Result<Self> {
        let tabs = Arc::new(Mutex::new(vec![]));

        let (shutdown_tx, shutdown_rx) = mpsc::sync_channel(100);

        let browser = Browser {
            inner: Arc::new(BrowserInner {
                process,
                tabs,
                transport,
                loop_shutdown_tx: shutdown_tx,
            }),
        };

        let incoming_events_rx = browser.inner.transport.listen_to_browser_events();

        browser.handle_browser_level_events(
            incoming_events_rx,
            browser.get_process_id(),
            shutdown_rx,
            idle_browser_timeout,
        );
        trace!("created browser event listener");

        // so we get events like 'targetCreated' and 'targetDestroyed'
        trace!("Calling set discover");
        browser.call_method(SetDiscoverTargets { discover: true })?;

        let tab = browser.wait_for_initial_tab()?;

        tab.call_method(DOM::Enable(None))?;
        tab.call_method(CSS::Enable(None))?;

        Ok(browser)
    }

The tabs are behind an Arc and Mutex because they’re accessible from multiple threads (including the one that handles incoming protocol events about new or changed tabs).

Examples found in repository?
src/browser/context.rs (line 44)
43
44
45
46
47
48
49
50
51
52
53
54
    pub fn get_tabs(&self) -> Result<Vec<Arc<Tab>>> {
        let browser_tabs = self.browser.get_tabs().lock().unwrap();
        let mut tabs = vec![];
        for tab in browser_tabs.iter() {
            if let Some(context_id) = tab.get_browser_context_id()? {
                if context_id == self.id {
                    tabs.push(Arc::clone(tab));
                }
            }
        }
        Ok(tabs)
    }

Chrome always launches with at least one tab. The reason we have to ‘wait’ is because information about that tab isn’t available immediately after starting the process. Tabs are behind Arcs because they each have their own thread which handles events and method responses directed to them.

Wait timeout: 10 secs

Examples found in repository?
src/browser/mod.rs (line 166)
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
    fn create_browser(
        process: Option<Process>,
        transport: Arc<Transport>,
        idle_browser_timeout: Duration,
    ) -> Result<Self> {
        let tabs = Arc::new(Mutex::new(vec![]));

        let (shutdown_tx, shutdown_rx) = mpsc::sync_channel(100);

        let browser = Browser {
            inner: Arc::new(BrowserInner {
                process,
                tabs,
                transport,
                loop_shutdown_tx: shutdown_tx,
            }),
        };

        let incoming_events_rx = browser.inner.transport.listen_to_browser_events();

        browser.handle_browser_level_events(
            incoming_events_rx,
            browser.get_process_id(),
            shutdown_rx,
            idle_browser_timeout,
        );
        trace!("created browser event listener");

        // so we get events like 'targetCreated' and 'targetDestroyed'
        trace!("Calling set discover");
        browser.call_method(SetDiscoverTargets { discover: true })?;

        let tab = browser.wait_for_initial_tab()?;

        tab.call_method(DOM::Enable(None))?;
        tab.call_method(CSS::Enable(None))?;

        Ok(browser)
    }

Create a new tab and return a handle to it.

If you want to specify its starting options, see new_tab_with_options.

let first_tab = browser.wait_for_initial_tab()?;
let new_tab = browser.new_tab()?;
let num_tabs = browser.get_tabs().lock().unwrap().len();
assert_eq!(2, num_tabs);

Create a new tab with a starting url, height / width, context ID and ‘frame control’

   let new_tab = browser.new_tab_with_options(CreateTarget {
   url: "chrome://version",
   width: Some(1024),
   height: Some(800),
   browser_context_id: None,
   enable_begin_frame_control: None,
   })?;
Examples found in repository?
src/browser/mod.rs (line 227)
217
218
219
220
221
222
223
224
225
226
227
228
    pub fn new_tab(&self) -> Result<Arc<Tab>> {
        let default_blank_tab = CreateTarget {
            url: "about:blank".to_string(),
            width: None,
            height: None,
            browser_context_id: None,
            enable_begin_frame_control: None,
            new_window: None,
            background: None,
        };
        self.new_tab_with_options(default_blank_tab)
    }
More examples
Hide additional examples
src/browser/context.rs (line 34)
24
25
26
27
28
29
30
31
32
33
34
35
    pub fn new_tab(&self) -> Result<Arc<Tab>> {
        let tab_in_context = CreateTarget {
            url: "about:blank".to_string(),
            width: None,
            height: None,
            browser_context_id: Some(self.id.clone()),
            enable_begin_frame_control: None,
            new_window: None,
            background: None,
        };
        self.browser.new_tab_with_options(tab_in_context)
    }

Creates the equivalent of a new incognito window, AKA a browser context

Get version information

let version_info = browser.get_version()?;
println!("User-Agent is `{}`", version_info.user_agent);

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
Get the TypeId of this object.