firefox_webdriver/browser/tab/
storage.rs

1//! Cookie and web storage methods.
2
3use serde_json::Value;
4use tracing::debug;
5
6use crate::error::Result;
7use crate::protocol::{Command, Cookie, StorageCommand};
8
9use super::Tab;
10use super::script::json_string;
11
12// ============================================================================
13// Tab - Storage (Cookies)
14// ============================================================================
15
16impl Tab {
17    /// Gets a cookie by name.
18    pub async fn get_cookie(&self, name: &str) -> Result<Option<Cookie>> {
19        debug!(tab_id = %self.inner.tab_id, name = %name, "Getting cookie");
20
21        let command = Command::Storage(StorageCommand::GetCookie {
22            name: name.to_string(),
23            url: None,
24        });
25
26        let response = self.send_command(command).await?;
27
28        let cookie = response
29            .result
30            .as_ref()
31            .and_then(|v| v.get("cookie"))
32            .and_then(|v| serde_json::from_value::<Cookie>(v.clone()).ok());
33
34        debug!(tab_id = %self.inner.tab_id, name = %name, found = cookie.is_some(), "Got cookie");
35        Ok(cookie)
36    }
37
38    /// Sets a cookie.
39    ///
40    /// # Example
41    ///
42    /// ```ignore
43    /// use firefox_webdriver::Cookie;
44    ///
45    /// tab.set_cookie(Cookie::new("session", "abc123")).await?;
46    /// ```
47    pub async fn set_cookie(&self, cookie: Cookie) -> Result<()> {
48        debug!(tab_id = %self.inner.tab_id, name = %cookie.name, "Setting cookie");
49
50        let command = Command::Storage(StorageCommand::SetCookie { cookie, url: None });
51        self.send_command(command).await?;
52        Ok(())
53    }
54
55    /// Deletes a cookie by name.
56    pub async fn delete_cookie(&self, name: &str) -> Result<()> {
57        debug!(tab_id = %self.inner.tab_id, name = %name, "Deleting cookie");
58
59        let command = Command::Storage(StorageCommand::DeleteCookie {
60            name: name.to_string(),
61            url: None,
62        });
63
64        self.send_command(command).await?;
65        Ok(())
66    }
67
68    /// Gets all cookies for the current page.
69    pub async fn get_all_cookies(&self) -> Result<Vec<Cookie>> {
70        debug!(tab_id = %self.inner.tab_id, "Getting all cookies");
71
72        let command = Command::Storage(StorageCommand::GetAllCookies { url: None });
73        let response = self.send_command(command).await?;
74
75        let cookies: Vec<Cookie> = response
76            .result
77            .as_ref()
78            .and_then(|v| v.get("cookies"))
79            .and_then(|v| v.as_array())
80            .map(|arr| {
81                arr.iter()
82                    .filter_map(|v| serde_json::from_value::<Cookie>(v.clone()).ok())
83                    .collect()
84            })
85            .unwrap_or_default();
86
87        debug!(tab_id = %self.inner.tab_id, count = cookies.len(), "Got all cookies");
88        Ok(cookies)
89    }
90}
91
92// ============================================================================
93// Tab - Storage (localStorage)
94// ============================================================================
95
96impl Tab {
97    /// Gets a value from localStorage.
98    pub async fn local_storage_get(&self, key: &str) -> Result<Option<String>> {
99        debug!(tab_id = %self.inner.tab_id, key = %key, "Getting localStorage");
100
101        let script = format!("return localStorage.getItem({});", json_string(key));
102        let value = self.execute_script(&script).await?;
103
104        let result = match value {
105            Value::Null => None,
106            Value::String(s) => Some(s),
107            _ => value.as_str().map(|s| s.to_string()),
108        };
109
110        debug!(tab_id = %self.inner.tab_id, key = %key, found = result.is_some(), "Got localStorage");
111        Ok(result)
112    }
113
114    /// Sets a value in localStorage.
115    pub async fn local_storage_set(&self, key: &str, value: &str) -> Result<()> {
116        debug!(tab_id = %self.inner.tab_id, key = %key, value_len = value.len(), "Setting localStorage");
117
118        let script = format!(
119            "localStorage.setItem({}, {});",
120            json_string(key),
121            json_string(value)
122        );
123
124        self.execute_script(&script).await?;
125        Ok(())
126    }
127
128    /// Deletes a key from localStorage.
129    pub async fn local_storage_delete(&self, key: &str) -> Result<()> {
130        debug!(tab_id = %self.inner.tab_id, key = %key, "Deleting localStorage");
131
132        let script = format!("localStorage.removeItem({});", json_string(key));
133        self.execute_script(&script).await?;
134        Ok(())
135    }
136
137    /// Clears all localStorage.
138    pub async fn local_storage_clear(&self) -> Result<()> {
139        debug!(tab_id = %self.inner.tab_id, "Clearing localStorage");
140
141        self.execute_script("localStorage.clear();").await?;
142        Ok(())
143    }
144}
145
146// ============================================================================
147// Tab - Storage (sessionStorage)
148// ============================================================================
149
150impl Tab {
151    /// Gets a value from sessionStorage.
152    pub async fn session_storage_get(&self, key: &str) -> Result<Option<String>> {
153        debug!(tab_id = %self.inner.tab_id, key = %key, "Getting sessionStorage");
154
155        let script = format!("return sessionStorage.getItem({});", json_string(key));
156        let value = self.execute_script(&script).await?;
157
158        let result = match value {
159            Value::Null => None,
160            Value::String(s) => Some(s),
161            _ => value.as_str().map(|s| s.to_string()),
162        };
163
164        debug!(tab_id = %self.inner.tab_id, key = %key, found = result.is_some(), "Got sessionStorage");
165        Ok(result)
166    }
167
168    /// Sets a value in sessionStorage.
169    pub async fn session_storage_set(&self, key: &str, value: &str) -> Result<()> {
170        debug!(tab_id = %self.inner.tab_id, key = %key, value_len = value.len(), "Setting sessionStorage");
171
172        let script = format!(
173            "sessionStorage.setItem({}, {});",
174            json_string(key),
175            json_string(value)
176        );
177
178        self.execute_script(&script).await?;
179        Ok(())
180    }
181
182    /// Deletes a key from sessionStorage.
183    pub async fn session_storage_delete(&self, key: &str) -> Result<()> {
184        debug!(tab_id = %self.inner.tab_id, key = %key, "Deleting sessionStorage");
185
186        let script = format!("sessionStorage.removeItem({});", json_string(key));
187        self.execute_script(&script).await?;
188        Ok(())
189    }
190
191    /// Clears all sessionStorage.
192    pub async fn session_storage_clear(&self) -> Result<()> {
193        debug!(tab_id = %self.inner.tab_id, "Clearing sessionStorage");
194
195        self.execute_script("sessionStorage.clear();").await?;
196        Ok(())
197    }
198}