1use std::collections::hash_map::{Entry, Values, ValuesMut};
6
7use base::id::WebViewId;
8use rustc_hash::FxHashMap;
9
10use crate::webview_renderer::{UnknownWebView, WebViewRenderer};
11
12#[derive(Debug)]
13pub struct WebViewManager<WebView> {
14 webviews: FxHashMap<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::{
126 BrowsingContextId, Index, PipelineNamespace, PipelineNamespaceId, TEST_PAINTER_ID,
127 WebViewId,
128 };
129
130 use crate::webview_manager::WebViewManager;
131 use crate::webview_renderer::UnknownWebView;
132
133 fn webview_id(namespace_id: u32, index: u32) -> WebViewId {
134 WebViewId::mock_for_testing(BrowsingContextId {
135 namespace_id: PipelineNamespaceId(namespace_id),
136 index: Index::new(index).unwrap(),
137 })
138 }
139
140 fn webviews_sorted<WebView: Clone>(
141 webviews: &WebViewManager<WebView>,
142 ) -> Vec<(WebViewId, WebView)> {
143 let mut keys = webviews.webviews.keys().collect::<Vec<_>>();
144 keys.sort_unstable();
145 keys.iter()
146 .map(|&id| (*id, webviews.webviews.get(id).cloned().unwrap()))
147 .collect()
148 }
149
150 #[test]
151 fn test() {
152 PipelineNamespace::install(PipelineNamespaceId(0));
153 let mut webviews = WebViewManager::default();
154
155 let painter_id = TEST_PAINTER_ID;
157 webviews.entry(WebViewId::new(painter_id)).or_insert('a');
158 webviews.entry(WebViewId::new(painter_id)).or_insert('b');
159 webviews.entry(WebViewId::new(painter_id)).or_insert('c');
160 assert!(webviews.get(webview_id(0, 1)).is_some());
161 assert!(webviews.get(webview_id(0, 2)).is_some());
162 assert!(webviews.get(webview_id(0, 3)).is_some());
163 assert_eq!(
164 webviews_sorted(&webviews),
165 vec![
166 (webview_id(0, 1), 'a'),
167 (webview_id(0, 2), 'b'),
168 (webview_id(0, 3), 'c'),
169 ]
170 );
171 assert!(webviews.painting_order.is_empty());
172
173 webviews.entry(webview_id(0, 3)).or_insert('d');
175 assert!(webviews.get(webview_id(0, 3)).is_some());
176
177 assert_eq!(
179 webviews.remove(webview_id(1, 1)),
180 Err(UnknownWebView(webview_id(1, 1)))
181 );
182 assert_eq!(webviews.get(webview_id(1, 1)), None);
183 assert_eq!(webviews.get_mut(webview_id(1, 1)), None);
184 assert_eq!(
185 webviews.show(webview_id(1, 1)),
186 Err(UnknownWebView(webview_id(1, 1)))
187 );
188 assert_eq!(
189 webviews.hide(webview_id(1, 1)),
190 Err(UnknownWebView(webview_id(1, 1)))
191 );
192 assert_eq!(
193 webviews.raise_to_top(webview_id(1, 1)),
194 Err(UnknownWebView(webview_id(1, 1)))
195 );
196
197 assert_eq!(webviews.show(webview_id(0, 2)), Ok(true));
199 assert_eq!(webviews.show(webview_id(0, 2)), Ok(false));
200 assert_eq!(webviews.painting_order, vec![webview_id(0, 2)]);
201 assert_eq!(webviews.raise_to_top(webview_id(0, 1)), Ok(true));
202 assert_eq!(webviews.raise_to_top(webview_id(0, 1)), Ok(false));
203 assert_eq!(
204 webviews.painting_order,
205 vec![webview_id(0, 2), webview_id(0, 1)]
206 );
207 assert_eq!(webviews.show(webview_id(0, 3)), Ok(true));
208 assert_eq!(webviews.show(webview_id(0, 3)), Ok(false));
209 assert_eq!(
210 webviews.painting_order,
211 vec![webview_id(0, 2), webview_id(0, 1), webview_id(0, 3)]
212 );
213
214 assert_eq!(webviews.show(webview_id(0, 1)), Ok(false));
216 assert_eq!(
217 webviews.painting_order,
218 vec![webview_id(0, 2), webview_id(0, 1), webview_id(0, 3)]
219 );
220 assert_eq!(webviews.raise_to_top(webview_id(0, 1)), Ok(true));
221 assert_eq!(webviews.raise_to_top(webview_id(0, 1)), Ok(false));
222 assert_eq!(
223 webviews.painting_order,
224 vec![webview_id(0, 2), webview_id(0, 3), webview_id(0, 1)]
225 );
226
227 assert_eq!(webviews.hide(webview_id(0, 3)), Ok(true));
229 assert_eq!(webviews.hide(webview_id(0, 3)), Ok(false));
230 assert_eq!(
231 webviews.painting_order,
232 vec![webview_id(0, 2), webview_id(0, 1)]
233 );
234 assert_eq!(
235 webviews_sorted(&webviews),
236 vec![
237 (webview_id(0, 1), 'a'),
238 (webview_id(0, 2), 'b'),
239 (webview_id(0, 3), 'c'),
240 ]
241 );
242
243 let mut painting_order = webviews.painting_order();
245 assert_eq!(painting_order.next(), Some((&webview_id(0, 2), &'b')));
246 assert_eq!(painting_order.next(), Some((&webview_id(0, 1), &'a')));
247 assert_eq!(painting_order.next(), None);
248 drop(painting_order);
249
250 assert!(webviews.remove(webview_id(0, 1)).is_ok());
252 assert!(webviews.remove(webview_id(0, 2)).is_ok());
253 assert!(webviews.remove(webview_id(0, 3)).is_ok());
254 assert!(webviews_sorted(&webviews).is_empty());
255 assert!(webviews.painting_order.is_empty());
256 }
257}