Skip to content

Commit 78634b3

Browse files
authored
fix(linux): set suggested filename for download started handler (#1594)
1 parent 43e78ff commit 78634b3

File tree

4 files changed

+82
-14
lines changed

4 files changed

+82
-14
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wry": "patch"
3+
---
4+
5+
On Linux, the `download_started_handler` will now get the correct suggested destination path.

Cargo.lock

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ soup3 = { version = "0.5", optional = true }
6565
x11-dl = { version = "2.21", optional = true }
6666
gdkx11 = { version = "0.18", optional = true }
6767
percent-encoding = "2.3"
68+
dirs = "6"
6869

6970
[target."cfg(target_os = \"windows\")".dependencies]
7071
webview2-com = "0.38"

src/webkitgtk/web_context.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::{
1212
borrow::Cow,
1313
cell::RefCell,
1414
collections::VecDeque,
15+
env::current_dir,
1516
path::{Path, PathBuf},
1617
rc::Rc,
1718
sync::{
@@ -312,27 +313,49 @@ impl WebContextExt for super::WebContext {
312313
) {
313314
let context = &self.os.context;
314315

315-
let download_started_handler = RefCell::new(download_started_handler);
316+
let download_started_handler = Rc::new(RefCell::new(download_started_handler));
316317
let failed = Rc::new(RefCell::new(false));
317318

318319
context.connect_download_started(move |_context, download| {
319-
if let Some(uri) = download.request().and_then(|req| req.uri()) {
320-
let uri = uri.to_string();
321-
let mut download_location = download
322-
.destination()
323-
.map(PathBuf::from)
324-
.unwrap_or_default();
320+
let download_started_handler = download_started_handler.clone();
321+
download.connect_decide_destination(move |download, suggested_filename| {
322+
if let Some(uri) = download.request().and_then(|req| req.uri()) {
323+
let uri = uri.to_string();
324+
325+
if let Some(download_started_handler) = download_started_handler.borrow_mut().as_mut() {
326+
let mut download_location =
327+
dirs::download_dir().unwrap_or_else(|| current_dir().unwrap_or_default());
328+
329+
let (mut suggested_filename, mut ext) = suggested_filename
330+
.split_once('.')
331+
.map(|(base, ext)| (base, format!(".{ext}")))
332+
.unwrap_or((suggested_filename, "".to_string()));
333+
334+
// for `data:` downloads, webkitgtk will suggest to use the raw data as the filename
335+
// for example `"data:attachment/text,sometext"` will result in `text,sometext`
336+
if uri.starts_with("data:") {
337+
suggested_filename = "Unknown";
338+
}
339+
340+
download_location.push(format!("{suggested_filename}{ext}"));
341+
342+
// WebView2 does not overwrite files but appends numbers
343+
let mut counter = 1;
344+
while download_location.exists() {
345+
download_location.set_file_name(format!("{suggested_filename} ({counter}){ext}"));
346+
counter += 1;
347+
}
325348

326-
if let Some(download_started_handler) = download_started_handler.borrow_mut().as_mut() {
327-
if download_started_handler(uri, &mut download_location) {
328-
download.connect_response_notify(move |download| {
349+
if download_started_handler(uri, &mut download_location) {
329350
download.set_destination(&download_location.to_string_lossy());
330-
});
331-
} else {
332-
download.cancel();
351+
} else {
352+
download.cancel();
353+
}
333354
}
334355
}
335-
}
356+
// TODO: check if we may also need `false`
357+
true
358+
});
336359

337360
download.connect_failed({
338361
let failed = failed.clone();

0 commit comments

Comments
 (0)