viewpoint_core/page/scripts/
mod.rs

1//! Init script methods for Page.
2//!
3//! This module provides methods for adding scripts that run before page loads.
4
5use tracing::{info, instrument};
6
7use super::Page;
8use crate::error::PageError;
9
10impl Page {
11    /// Add a script to be evaluated before every page load.
12    ///
13    /// The script will run before any scripts on the page, and will persist
14    /// across navigations.
15    ///
16    /// # Example
17    ///
18    /// ```no_run
19    /// # async fn example(page: viewpoint_core::Page) -> Result<(), viewpoint_core::CoreError> {
20    /// // Modify the navigator before page loads
21    /// page.add_init_script("Object.defineProperty(navigator, 'webdriver', { get: () => false })").await?;
22    /// # Ok(())
23    /// # }
24    /// ```
25    #[instrument(level = "info", skip(self, script), fields(script_len = script.as_ref().len()))]
26    pub async fn add_init_script(&self, script: impl AsRef<str>) -> Result<String, PageError> {
27        if self.is_closed() {
28            return Err(PageError::Closed);
29        }
30
31        use viewpoint_cdp::protocol::page::AddScriptToEvaluateOnNewDocumentParams;
32
33        let result: viewpoint_cdp::protocol::page::AddScriptToEvaluateOnNewDocumentResult = self
34            .connection()
35            .send_command(
36                "Page.addScriptToEvaluateOnNewDocument",
37                Some(AddScriptToEvaluateOnNewDocumentParams {
38                    source: script.as_ref().to_string(),
39                    world_name: None,
40                    include_command_line_api: None,
41                    run_immediately: None,
42                }),
43                Some(self.session_id()),
44            )
45            .await?;
46
47        info!(identifier = %result.identifier, "Init script added");
48        Ok(result.identifier)
49    }
50
51    /// Add an init script from a file path.
52    ///
53    /// # Errors
54    ///
55    /// Returns an error if the file cannot be read or the script cannot be added.
56    #[instrument(level = "info", skip(self), fields(path = %path.as_ref().display()))]
57    pub async fn add_init_script_path(&self, path: impl AsRef<std::path::Path>) -> Result<String, PageError> {
58        let content = tokio::fs::read_to_string(path.as_ref()).await.map_err(|e| {
59            PageError::EvaluationFailed(format!("Failed to read init script file: {e}"))
60        })?;
61
62        self.add_init_script(&content).await
63    }
64}