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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use std::collections::HashMap;
use super::Page;
use crate::error::{Error, Result};
impl Page {
/// Check a navigation result for errors.
/// ERR_HTTP_RESPONSE_CODE_FAILURE (4xx/5xx) is ignored — the page still loaded.
fn check_nav_result(result: &crate::cdp::types::PageNavigateResult) -> Result<()> {
if let Some(ref error) = result.error_text {
if error != "net::ERR_HTTP_RESPONSE_CODE_FAILURE" {
return Err(Error::Navigation(error.clone()));
}
}
Ok(())
}
/// Navigate and verify a new document or same-document navigation commit.
/// The full operation, including the target queue, obeys the configured deadline.
/// Use an explicit expectation when application readiness requires more than a commit.
pub async fn goto(&self, url: &str) -> Result<()> {
self.act(
crate::Action::Navigate {
url: url.into(),
referrer: None,
},
self.action_options.clone(),
)
.await
.map(|_| ())
}
/// Navigate an auxiliary tab to an attachment URL. Native events, not this
/// acknowledgment, determine whether a download actually started.
pub async fn navigate_for_download(&self, url: &str, referrer: Option<&str>) -> Result<()> {
let result = self.session.navigate(url, referrer).await?;
self.invalidate_document();
if result.is_download == Some(true)
|| result.error_text.as_deref() == Some("net::ERR_ABORTED")
{
return Ok(());
}
Self::check_nav_result(&result)
}
/// Reload the page
pub async fn reload(&self) -> Result<()> {
self.act(crate::Action::Reload, self.action_options.clone())
.await
.map(|_| ())
}
/// Go back in history
pub async fn back(&self) -> Result<()> {
self.act(crate::Action::Back, self.action_options.clone())
.await
.map(|_| ())
}
/// Go forward in history
pub async fn forward(&self) -> Result<()> {
self.act(crate::Action::Forward, self.action_options.clone())
.await
.map(|_| ())
}
/// Get current URL
pub async fn url(&self) -> Result<String> {
let frame_tree = self.session.get_frame_tree().await?;
Ok(frame_tree.frame.url)
}
/// Navigate to `url` while sending custom HTTP headers.
/// Headers are set before navigation and cleared to an empty map afterward,
/// including on error or cancellation; previous headers are not restored.
/// Navigation and header changes on the same target are serialized.
/// Cancelled cleanup continues in the background for up to five seconds.
/// Later commands wait for it and report any failure until a successful
/// `clear_extra_headers` explicitly recovers the target.
pub async fn goto_with_headers(
&self,
url: &str,
headers: HashMap<String, String>,
) -> Result<()> {
self.act(
crate::Action::NavigateWithHeaders {
url: url.into(),
headers,
},
self.action_options.clone(),
)
.await
.map(|_| ())
}
/// Navigate to `url` with a custom Referer header.
pub async fn goto_with_referrer(&self, url: &str, referrer: &str) -> Result<()> {
self.act(
crate::Action::Navigate {
url: url.into(),
referrer: Some(referrer.into()),
},
self.action_options.clone(),
)
.await
.map(|_| ())
}
/// Disable CSP enforcement for the current page.
/// Must be called before navigation to take effect.
pub async fn set_bypass_csp(&self, enabled: bool) -> Result<()> {
self.session.set_bypass_csp(enabled).await
}
/// Enable or disable JavaScript execution for the current page.
/// Must be called before navigation to take effect.
pub async fn set_javascript_enabled(&self, enabled: bool) -> Result<()> {
self.session.set_script_execution_disabled(!enabled).await
}
/// Override the User-Agent string for this page.
pub async fn set_user_agent(&self, user_agent: &str) -> Result<()> {
self.session.set_user_agent(user_agent, None).await
}
/// Ignore TLS certificate errors for this session.
pub async fn ignore_cert_errors(&self, ignore: bool) -> Result<()> {
self.session.set_ignore_cert_errors(ignore).await
}
/// Accept a pending JS dialog (alert / confirm / prompt).
/// For prompt() dialogs, provide `prompt_text` to fill the input.
pub async fn accept_dialog(&self, prompt_text: Option<&str>) -> Result<()> {
self.session.handle_dialog(true, prompt_text).await
}
/// Dismiss a pending JS dialog (cancel / close).
pub async fn dismiss_dialog(&self) -> Result<()> {
self.session.handle_dialog(false, None).await
}
}