Skip to content

Commit d878cca

Browse files
committed
fix: ImageInfo overflow check, add initial size builder and URL/title getters, HashMap for view tracking
1 parent 80f82e6 commit d878cca

4 files changed

Lines changed: 57 additions & 20 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@
33
## [Unreleased]
44

55
### Added
6+
- `.with_initial_size()` builder method for setting viewport size before first resize
7+
- `current_url()` / `current_title()` getters on basic WebView
8+
- `url_for(id)` / `title_for(id)` getters on advanced WebView
69
- Doc comments on WebView structs noting the required `Action::Update` subscription
710
- Improved `on_action()` docs — now states it's required for litehtml/blitz engines
811

912
### Changed
13+
- Advanced WebView urls/titles tracking switched from Vec to HashMap for O(1) lookups
1014
- Reduced hot-path allocations — URL/title strings moved instead of cloned, pixel buffer avoids double copy
1115
- `on_action()` error messages now suggest the fix; doc comments name affected engines
1216

1317
### Fixed
18+
- ImageInfo::blank() integer overflow — checked arithmetic with fallback to 1x1
1419
- Widget crash on stale/invalid view index — lookups now return Option with graceful fallback
1520
- CEF pixel buffer integer overflow — checked arithmetic prevents buffer over-read on corrupted dimensions
1621
- Advanced widget HiDPI scaling — scroll offset and content height now scaled correctly

src/lib.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,7 @@ pub struct ImageInfo {
6464

6565
impl Default for ImageInfo {
6666
fn default() -> Self {
67-
let pixels = vec![255; (Self::WIDTH as usize * Self::HEIGHT as usize) * 4];
68-
let raw_pixels = Arc::new(pixels.clone());
69-
Self {
70-
width: Self::WIDTH,
71-
height: Self::HEIGHT,
72-
handle: image::Handle::from_rgba(Self::WIDTH, Self::HEIGHT, pixels),
73-
raw_pixels,
74-
}
67+
Self::blank(Self::WIDTH, Self::HEIGHT)
7568
}
7669
}
7770

@@ -118,12 +111,17 @@ impl ImageInfo {
118111
}
119112

120113
fn blank(width: u32, height: u32) -> Self {
121-
let pixels = vec![255; (width as usize * height as usize) * 4];
114+
let (w, h) = (width as usize)
115+
.checked_mul(height as usize)
116+
.and_then(|n| n.checked_mul(4))
117+
.map_or((1u32, 1u32), |_| (width, height));
118+
119+
let pixels = vec![255; (w as usize * h as usize) * 4];
122120
let raw_pixels = Arc::new(pixels.clone());
123121
Self {
124-
width,
125-
height,
126-
handle: image::Handle::from_rgba(width, height, pixels),
122+
width: w,
123+
height: h,
124+
handle: image::Handle::from_rgba(w, h, pixels),
127125
raw_pixels,
128126
}
129127
}

src/webview/advanced.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ where
7474
on_close_view: Option<Box<dyn Fn(ViewId) -> Message>>,
7575
on_create_view: Option<Box<dyn Fn(ViewId) -> Message>>,
7676
on_url_change: Option<Box<dyn Fn(ViewId, String) -> Message>>,
77-
urls: Vec<(ViewId, String)>,
77+
urls: HashMap<ViewId, String>,
7878
on_title_change: Option<Box<dyn Fn(ViewId, String) -> Message>>,
79-
titles: Vec<(ViewId, String)>,
79+
titles: HashMap<ViewId, String>,
8080
on_copy: Option<Box<dyn Fn(String) -> Message>>,
8181
action_mapper: Option<Arc<dyn Fn(Action) -> Message + Send + Sync>>,
8282
inflight_images: usize,
@@ -94,9 +94,9 @@ impl<Engine: engines::Engine + Default, Message: Send + Clone + 'static> Default
9494
on_close_view: None,
9595
on_create_view: None,
9696
on_url_change: None,
97-
urls: Vec::new(),
97+
urls: HashMap::new(),
9898
on_title_change: None,
99-
titles: Vec::new(),
99+
titles: HashMap::new(),
100100
on_copy: None,
101101
action_mapper: None,
102102
inflight_images: 0,
@@ -162,6 +162,13 @@ impl<Engine: engines::Engine + Default, Message: Send + Clone + 'static> WebView
162162
self
163163
}
164164

165+
/// Set the initial viewport size used before the first resize event.
166+
/// Defaults to 1920x1080.
167+
pub fn with_initial_size(mut self, size: Size<u32>) -> Self {
168+
self.view_size = size;
169+
self
170+
}
171+
165172
/// Passes update to webview
166173
pub fn update(&mut self, action: Action) -> Task<Message> {
167174
let mut tasks = Vec::new();
@@ -189,8 +196,8 @@ impl<Engine: engines::Engine + Default, Message: Send + Clone + 'static> WebView
189196
match action {
190197
Action::CloseView(id) => {
191198
self.engine.remove_view(id);
192-
self.urls.retain(|url| url.0 != id);
193-
self.titles.retain(|title| title.0 != id);
199+
self.urls.remove(&id);
200+
self.titles.remove(&id);
194201

195202
if let Some(on_view_close) = &self.on_close_view {
196203
tasks.push(Task::done((on_view_close)(id)))
@@ -226,8 +233,8 @@ impl<Engine: engines::Engine + Default, Message: Send + Clone + 'static> WebView
226233
self.engine.new_view(self.view_size, Some(page_type))
227234
};
228235

229-
self.urls.push((id, String::new()));
230-
self.titles.push((id, String::new()));
236+
self.urls.insert(id, String::new());
237+
self.titles.insert(id, String::new());
231238

232239
if let Some(on_view_create) = &self.on_create_view {
233240
tasks.push(Task::done((on_view_create)(id)))
@@ -466,6 +473,16 @@ impl<Engine: engines::Engine + Default, Message: Send + Clone + 'static> WebView
466473
Task::batch(tasks)
467474
}
468475

476+
/// Get the URL for a specific view
477+
pub fn url_for(&self, id: ViewId) -> Option<&str> {
478+
self.urls.get(&id).map(|s| s.as_str())
479+
}
480+
481+
/// Get the title for a specific view
482+
pub fn title_for(&self, id: ViewId) -> Option<&str> {
483+
self.titles.get(&id).map(|s| s.as_str())
484+
}
485+
469486
/// Like a normal `view()` method in iced, but takes an id of the desired view
470487
pub fn view<'a, T: 'a>(&'a self, id: usize) -> Element<'a, Action, T> {
471488
let content_height = self.engine.get_content_height(id);

src/webview/basic.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ impl<Engine: engines::Engine + Default, Message: Send + Clone + 'static> WebView
185185
self
186186
}
187187

188+
/// Set the initial viewport size used before the first resize event.
189+
/// Defaults to 1920x1080.
190+
pub fn with_initial_size(mut self, size: Size<u32>) -> Self {
191+
self.view_size = size;
192+
self
193+
}
194+
188195
/// Passes update to webview
189196
pub fn update(&mut self, action: Action) -> Task<Message> {
190197
let mut tasks = Vec::new();
@@ -569,6 +576,16 @@ impl<Engine: engines::Engine + Default, Message: Send + Clone + 'static> WebView
569576
self.get_current_view_id()
570577
.map(|id| self.engine.get_view(id))
571578
}
579+
580+
/// Get the current view's URL
581+
pub fn current_url(&self) -> &str {
582+
&self.url
583+
}
584+
585+
/// Get the current view's title
586+
pub fn current_title(&self) -> &str {
587+
&self.title
588+
}
572589
}
573590

574591
struct WebViewWidget<'a> {

0 commit comments

Comments
 (0)