browsing/browser/
storage.rs1use crate::actor::Page;
4use crate::error::{BrowsingError, Result};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct StorageEntry {
10 pub key: String,
12 pub value: String,
14}
15
16#[derive(Debug, Clone, Copy, Default)]
18pub struct StorageManager;
19
20impl StorageManager {
21 pub fn new() -> Self {
23 Self
24 }
25
26 pub async fn get_local_storage(&self, page: &Page, key: &str) -> Result<Option<String>> {
28 let script = format!(
29 "(function() {{ try {{ return window.localStorage.getItem({}) || ''; }} catch(e) {{ return ''; }} }})()",
30 serde_json::json!(key)
31 );
32 let result = page.evaluate(&script).await?;
33 if result.is_empty() {
34 Ok(None)
35 } else {
36 Ok(Some(result))
37 }
38 }
39
40 pub async fn set_local_storage(&self, page: &Page, key: &str, value: &str) -> Result<()> {
42 let script = format!(
43 "(function() {{ try {{ window.localStorage.setItem({}, {}); return 'ok'; }} catch(e) {{ return e.message; }} }})()",
44 serde_json::json!(key),
45 serde_json::json!(value)
46 );
47 let result = page.evaluate(&script).await?;
48 if result != "ok" {
49 return Err(BrowsingError::Browser(format!(
50 "localStorage setItem failed: {result}"
51 )));
52 }
53 Ok(())
54 }
55
56 pub async fn remove_local_storage(&self, page: &Page, key: &str) -> Result<()> {
58 let script = format!(
59 "(function() {{ try {{ window.localStorage.removeItem({}); return 'ok'; }} catch(e) {{ return e.message; }} }})()",
60 serde_json::json!(key)
61 );
62 page.evaluate(&script).await?;
63 Ok(())
64 }
65
66 pub async fn clear_local_storage(&self, page: &Page) -> Result<()> {
68 let script = "(function() { try { window.localStorage.clear(); return 'ok'; } catch(e) { return e.message; } })()";
69 let result = page.evaluate(script).await?;
70 if result != "ok" {
71 return Err(BrowsingError::Browser(format!(
72 "localStorage clear failed: {result}"
73 )));
74 }
75 Ok(())
76 }
77
78 pub async fn get_all_local_storage(&self, page: &Page) -> Result<Vec<StorageEntry>> {
80 let script = r#"
81 (function() {
82 try {
83 var entries = [];
84 for (var i = 0; i < window.localStorage.length; i++) {
85 var key = window.localStorage.key(i);
86 entries.push({ key: key, value: window.localStorage.getItem(key) });
87 }
88 return JSON.stringify(entries);
89 } catch(e) {
90 return '[]';
91 }
92 })()
93 "#;
94 let result = page.evaluate(script).await?;
95 let entries: Vec<StorageEntry> =
96 serde_json::from_str(&result).unwrap_or_default();
97 Ok(entries)
98 }
99
100 pub async fn get_session_storage(&self, page: &Page, key: &str) -> Result<Option<String>> {
102 let script = format!(
103 "(function() {{ try {{ return window.sessionStorage.getItem({}) || ''; }} catch(e) {{ return ''; }} }})()",
104 serde_json::json!(key)
105 );
106 let result = page.evaluate(&script).await?;
107 if result.is_empty() {
108 Ok(None)
109 } else {
110 Ok(Some(result))
111 }
112 }
113
114 pub async fn set_session_storage(&self, page: &Page, key: &str, value: &str) -> Result<()> {
116 let script = format!(
117 "(function() {{ try {{ window.sessionStorage.setItem({}, {}); return 'ok'; }} catch(e) {{ return e.message; }} }})()",
118 serde_json::json!(key),
119 serde_json::json!(value)
120 );
121 let result = page.evaluate(&script).await?;
122 if result != "ok" {
123 return Err(BrowsingError::Browser(format!(
124 "sessionStorage setItem failed: {result}"
125 )));
126 }
127 Ok(())
128 }
129
130 pub async fn remove_session_storage(&self, page: &Page, key: &str) -> Result<()> {
132 let script = format!(
133 "(function() {{ try {{ window.sessionStorage.removeItem({}); return 'ok'; }} catch(e) {{ return e.message; }} }})()",
134 serde_json::json!(key)
135 );
136 page.evaluate(&script).await?;
137 Ok(())
138 }
139
140 pub async fn clear_session_storage(&self, page: &Page) -> Result<()> {
142 let script = "(function() { try { window.sessionStorage.clear(); return 'ok'; } catch(e) { return e.message; } })()";
143 let result = page.evaluate(script).await?;
144 if result != "ok" {
145 return Err(BrowsingError::Browser(format!(
146 "sessionStorage clear failed: {result}"
147 )));
148 }
149 Ok(())
150 }
151
152 pub async fn get_all_session_storage(&self, page: &Page) -> Result<Vec<StorageEntry>> {
154 let script = r#"
155 (function() {
156 try {
157 var entries = [];
158 for (var i = 0; i < window.sessionStorage.length; i++) {
159 var key = window.sessionStorage.key(i);
160 entries.push({ key: key, value: window.sessionStorage.getItem(key) });
161 }
162 return JSON.stringify(entries);
163 } catch(e) {
164 return '[]';
165 }
166 })()
167 "#;
168 let result = page.evaluate(script).await?;
169 let entries: Vec<StorageEntry> =
170 serde_json::from_str(&result).unwrap_or_default();
171 Ok(entries)
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178
179 #[test]
180 fn test_storage_entry_creation() {
181 let entry = StorageEntry {
182 key: "token".to_string(),
183 value: "abc123".to_string(),
184 };
185 assert_eq!(entry.key, "token");
186 assert_eq!(entry.value, "abc123");
187 }
188
189 #[test]
190 fn test_storage_entry_serialization() {
191 let entry = StorageEntry {
192 key: "foo".to_string(),
193 value: "bar".to_string(),
194 };
195 let json = serde_json::to_string(&entry).unwrap();
196 assert!(json.contains("foo"));
197 assert!(json.contains("bar"));
198 }
199
200 #[test]
201 fn test_storage_entry_deserialization() {
202 let json = r#"{"key":"foo","value":"bar"}"#;
203 let entry: StorageEntry = serde_json::from_str(json).unwrap();
204 assert_eq!(entry.key, "foo");
205 assert_eq!(entry.value, "bar");
206 }
207
208 #[test]
209 fn test_storage_manager_default() {
210 let manager = StorageManager::default();
211 let _ = std::format!("{:?}", manager);
212 }
213}