Struct headless_chrome::browser::Browser
source · 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§
source§impl Browser
impl Browser
sourcepub fn new(launch_options: LaunchOptions<'_>) -> Result<Self>
pub fn new(launch_options: LaunchOptions<'_>) -> Result<Self>
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.
sourcepub fn default() -> Result<Self>
pub fn default() -> Result<Self>
Calls [new
] with options to launch a headless browser using whatever Chrome / Chromium
binary can be found on the system.
sourcepub fn connect(debug_ws_url: String) -> Result<Self>
pub fn connect(debug_ws_url: String) -> Result<Self>
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.
sourcepub fn connect_with_timeout(
debug_ws_url: String,
idle_browser_timeout: Duration
) -> Result<Self>
pub fn connect_with_timeout(
debug_ws_url: String,
idle_browser_timeout: Duration
) -> Result<Self>
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.
sourcepub fn get_process_id(&self) -> Option<u32>
pub fn get_process_id(&self) -> Option<u32>
Examples found in repository?
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)
}
sourcepub fn get_tabs(&self) -> &Arc<Mutex<Vec<Arc<Tab>>>>
pub fn get_tabs(&self) -> &Arc<Mutex<Vec<Arc<Tab>>>>
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?
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)
}
sourcepub fn wait_for_initial_tab(&self) -> Result<Arc<Tab>>
pub fn wait_for_initial_tab(&self) -> Result<Arc<Tab>>
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 Arc
s
because they each have their own thread which handles events and method responses directed to them.
Wait timeout: 10 secs
Examples found in repository?
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)
}
sourcepub fn new_tab(&self) -> Result<Arc<Tab>>
pub fn new_tab(&self) -> Result<Arc<Tab>>
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);
sourcepub fn new_tab_with_options(
&self,
create_target_params: CreateTarget
) -> Result<Arc<Tab>>
pub fn new_tab_with_options(
&self,
create_target_params: CreateTarget
) -> Result<Arc<Tab>>
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?
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
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)
}
sourcepub fn new_context(&self) -> Result<Context<'_>>
pub fn new_context(&self) -> Result<Context<'_>>
Creates the equivalent of a new incognito window, AKA a browser context
sourcepub fn get_version(&self) -> Result<GetVersionReturnObject>
pub fn get_version(&self) -> Result<GetVersionReturnObject>
Get version information
let version_info = browser.get_version()?;
println!("User-Agent is `{}`", version_info.user_agent);