1use std::collections::HashMap;
6use std::collections::hash_map::{Entry, Values, ValuesMut};
7
8use base::id::WebViewId;
9
10use crate::webview_renderer::{UnknownWebView, WebViewRenderer};
11
12#[derive(Debug)]
13pub struct WebViewManager<WebView> {
14 webviews: HashMap<WebViewId, WebView>,
17
18 pub(crate) painting_order: Vec<WebViewId>,
20}
21
22impl<WebView> Default for WebViewManager<WebView> {
23 fn default() -> Self {
24 Self {
25 webviews: Default::default(),
26 painting_order: Default::default(),
27 }
28 }
29}
30
31impl<WebView> WebViewManager<WebView> {
32 pub fn remove(&mut self, webview_id: WebViewId) -> Result<WebView, UnknownWebView> {
33 self.painting_order.retain(|b| *b != webview_id);
34 self.webviews
35 .remove(&webview_id)
36 .ok_or(UnknownWebView(webview_id))
37 }
38
39 pub fn get(&self, webview_id: WebViewId) -> Option<&WebView> {
40 self.webviews.get(&webview_id)
41 }
42
43 pub fn get_mut(&mut self, webview_id: WebViewId) -> Option<&mut WebView> {
44 self.webviews.get_mut(&webview_id)
45 }
46
47 pub fn show(&mut self, webview_id: WebViewId) -> Result<bool, UnknownWebView> {
49 if !self.webviews.contains_key(&webview_id) {
50 return Err(UnknownWebView(webview_id));
51 }
52 if !self.painting_order.contains(&webview_id) {
53 self.painting_order.push(webview_id);
54 return Ok(true);
55 }
56 Ok(false)
57 }
58
59 pub fn hide(&mut self, webview_id: WebViewId) -> Result<bool, UnknownWebView> {
61 if !self.webviews.contains_key(&webview_id) {
62 return Err(UnknownWebView(webview_id));
63 }
64 if self.painting_order.contains(&webview_id) {
65 self.painting_order.retain(|b| *b != webview_id);
66 return Ok(true);
67 }
68 Ok(false)
69 }
70
71 pub fn hide_all(&mut self) -> bool {
73 if !self.painting_order.is_empty() {
74 self.painting_order.clear();
75 return true;
76 }
77 false
78 }
79
80 pub fn raise_to_top(&mut self, webview_id: WebViewId) -> Result<bool, UnknownWebView> {
82 if !self.webviews.contains_key(&webview_id) {
83 return Err(UnknownWebView(webview_id));
84 }
85 if self.painting_order.last() != Some(&webview_id) {
86 self.hide(webview_id)?;
87 self.show(webview_id)?;
88 return Ok(true);
89 }
90 Ok(false)
91 }
92
93 pub fn painting_order(&self) -> impl Iterator<Item = (&WebViewId, &WebView)> {
94 self.painting_order
95 .iter()
96 .flat_map(move |webview_id| self.get(*webview_id).map(|b| (webview_id, b)))
97 }
98
99 pub fn entry(&mut self, webview_id: WebViewId) -> Entry<'_, WebViewId, WebView> {
100 self.webviews.entry(webview_id)
101 }
102
103 pub fn iter(&self) -> Values<'_, WebViewId, WebView> {
104 self.webviews.values()
105 }
106
107 pub fn iter_mut(&mut self) -> ValuesMut<'_, WebViewId, WebView> {
108 self.webviews.values_mut()
109 }
110}
111
112impl WebViewManager<WebViewRenderer> {
113 pub(crate) fn scroll_trees_memory_usage(
114 &self,
115 ops: &mut malloc_size_of::MallocSizeOfOps,
116 ) -> usize {
117 self.iter()
118 .map(|renderer| renderer.scroll_trees_memory_usage(ops))
119 .sum::<usize>()
120 }
121}
122
123#[cfg(test)]
124mod test {
125 use base::id::{BrowsingContextId, Index, PipelineNamespace, PipelineNamespaceId, WebViewId};
126
127 use crate::webview_manager::WebViewManager;
128 use crate::webview_renderer::UnknownWebView;
129
130 fn top_level_id(namespace_id: u32, index: u32) -> WebViewId {
131 WebViewId(BrowsingContextId {
132 namespace_id: PipelineNamespaceId(namespace_id),
133 index: Index::new(index).unwrap(),
134 })
135 }
136
137 fn webviews_sorted<WebView: Clone>(
138 webviews: &WebViewManager<WebView>,
139 ) -> Vec<(WebViewId, WebView)> {
140 let mut keys = webviews.webviews.keys().collect::<Vec<_>>();
141 keys.sort_unstable();
142 keys.iter()
143 .map(|&id| (*id, webviews.webviews.get(id).cloned().unwrap()))
144 .collect()
145 }
146
147 #[test]
148 fn test() {
149 PipelineNamespace::install(PipelineNamespaceId(0));
150 let mut webviews = WebViewManager::default();
151
152 webviews.entry(WebViewId::new()).or_insert('a');
154 webviews.entry(WebViewId::new()).or_insert('b');
155 webviews.entry(WebViewId::new()).or_insert('c');
156 assert!(webviews.get(top_level_id(0, 1)).is_some());
157 assert!(webviews.get(top_level_id(0, 2)).is_some());
158 assert!(webviews.get(top_level_id(0, 3)).is_some());
159 assert_eq!(
160 webviews_sorted(&webviews),
161 vec![
162 (top_level_id(0, 1), 'a'),
163 (top_level_id(0, 2), 'b'),
164 (top_level_id(0, 3), 'c'),
165 ]
166 );
167 assert!(webviews.painting_order.is_empty());
168
169 webviews.entry(top_level_id(0, 3)).or_insert('d');
171 assert!(webviews.get(top_level_id(0, 3)).is_some());
172
173 assert_eq!(
175 webviews.remove(top_level_id(1, 1)),
176 Err(UnknownWebView(top_level_id(1, 1)))
177 );
178 assert_eq!(webviews.get(top_level_id(1, 1)), None);
179 assert_eq!(webviews.get_mut(top_level_id(1, 1)), None);
180 assert_eq!(
181 webviews.show(top_level_id(1, 1)),
182 Err(UnknownWebView(top_level_id(1, 1)))
183 );
184 assert_eq!(
185 webviews.hide(top_level_id(1, 1)),
186 Err(UnknownWebView(top_level_id(1, 1)))
187 );
188 assert_eq!(
189 webviews.raise_to_top(top_level_id(1, 1)),
190 Err(UnknownWebView(top_level_id(1, 1)))
191 );
192
193 assert_eq!(webviews.show(top_level_id(0, 2)), Ok(true));
195 assert_eq!(webviews.show(top_level_id(0, 2)), Ok(false));
196 assert_eq!(webviews.painting_order, vec![top_level_id(0, 2)]);
197 assert_eq!(webviews.raise_to_top(top_level_id(0, 1)), Ok(true));
198 assert_eq!(webviews.raise_to_top(top_level_id(0, 1)), Ok(false));
199 assert_eq!(
200 webviews.painting_order,
201 vec![top_level_id(0, 2), top_level_id(0, 1)]
202 );
203 assert_eq!(webviews.show(top_level_id(0, 3)), Ok(true));
204 assert_eq!(webviews.show(top_level_id(0, 3)), Ok(false));
205 assert_eq!(
206 webviews.painting_order,
207 vec![top_level_id(0, 2), top_level_id(0, 1), top_level_id(0, 3)]
208 );
209
210 assert_eq!(webviews.show(top_level_id(0, 1)), Ok(false));
212 assert_eq!(
213 webviews.painting_order,
214 vec![top_level_id(0, 2), top_level_id(0, 1), top_level_id(0, 3)]
215 );
216 assert_eq!(webviews.raise_to_top(top_level_id(0, 1)), Ok(true));
217 assert_eq!(webviews.raise_to_top(top_level_id(0, 1)), Ok(false));
218 assert_eq!(
219 webviews.painting_order,
220 vec![top_level_id(0, 2), top_level_id(0, 3), top_level_id(0, 1)]
221 );
222
223 assert_eq!(webviews.hide(top_level_id(0, 3)), Ok(true));
225 assert_eq!(webviews.hide(top_level_id(0, 3)), Ok(false));
226 assert_eq!(
227 webviews.painting_order,
228 vec![top_level_id(0, 2), top_level_id(0, 1)]
229 );
230 assert_eq!(
231 webviews_sorted(&webviews),
232 vec![
233 (top_level_id(0, 1), 'a'),
234 (top_level_id(0, 2), 'b'),
235 (top_level_id(0, 3), 'c'),
236 ]
237 );
238
239 let mut painting_order = webviews.painting_order();
241 assert_eq!(painting_order.next(), Some((&top_level_id(0, 2), &'b')));
242 assert_eq!(painting_order.next(), Some((&top_level_id(0, 1), &'a')));
243 assert_eq!(painting_order.next(), None);
244 drop(painting_order);
245
246 assert!(webviews.remove(top_level_id(0, 1)).is_ok());
248 assert!(webviews.remove(top_level_id(0, 2)).is_ok());
249 assert!(webviews.remove(top_level_id(0, 3)).is_ok());
250 assert!(webviews_sorted(&webviews).is_empty());
251 assert!(webviews.painting_order.is_empty());
252 }
253}