-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix failed downloads (file coordination) #2467
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great engineering, @mallexxx! 👏
In major refactoring like this, I’d recommend to use tech designs more. It can help with the review and also later in case someone else has to fix/enhance the functionality.
I tested all kinds of scenarios and it worked very well 👏 :
✔️ Tested simultanous downloads of files
✔️ Tested custom download location
✔️ Tested asking for download destination on every
❔ Couldn’t remove the item replacement directory because: Operation not permitted. Not sure if it's a big deal
✔️ Tested download cancellation
✔️ Tested download resuming after the cancelation
✔️ Tested download cancellation by removing a .duckload file in Finder
✔️ Tested cancelation and resuming with wifi problems
✔️ Validated downloads list is properly restored after the app restart
✔️ Validated downloads list is refreshed according to the file system changes when the app is turned off
✔️ Validated opening files from the download list
✔️ Validated renaming of the .duckload file
There are couple of issues I experienced:
- After clicking "clear" in the Downloads panel, .duckload files were not removed from Desktop (custom download location)
- Removing a completed download file from Downloads panel didn't remove it from the file system. (Not really sure if this is the requirement, just assuming from testing steps)
- It often takes very long to see .duckload being renamed to the final name. Sometimes even 10 seconds
- Experienced following assertion when clicking multiple times on the download link
And I have 2 product suggestions we can bring to Asana:
- Does it make sense to rephrase “Open Downloads Folder” in case of custom downloads folder is set?
- The download list truncates the file name with "...". Should it be able to show the full filename, at least when the item is selected or on hover?
modified = Date() | ||
} | ||
} | ||
|
||
var destinationURL: URL? { | ||
var destinationBookmarkData: Data? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that it won't be trivial to rename this across the whole PR, but I'd recommend to avoid using 'bookmark' word in this context, because it might be very confusing when looking at the codebase later after the merge. Would destinationPersistedData
, tempFilePersistedURLData
, etc, work better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I‘d stick with the API naming (i.e. bookmarkData), we could use URLBookmarkData
or FileBookmarkData
if it‘s better
delegate?.presentedItemDidMove(to: newURL) | ||
} | ||
|
||
final func accommodatePresentedItemDeletion() async throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is async
necessary here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not really
completionHandler: @escaping (URL?, UTType?) -> Void) | ||
func fileDownloadTask(_ task: WebKitDownloadTask, didFinishWith result: Result<URL, FileDownloadError>) | ||
func fileDownloadTaskNeedsDestinationURL(_ task: WebKitDownloadTask, suggestedFilename: String, suggestedFileType: UTType?) async -> (URL?, UTType?) | ||
func fileDownloadTask(_ task: WebKitDownloadTask, didFinishWith result: Result<Void, FileDownloadError>) | ||
} | ||
|
||
/// WKDownload wrapper managing Finder File Progress and coordinating file URLs | ||
final class WebKitDownloadTask: NSObject, ProgressReporting, @unchecked Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WebKitDownloadTask
class is quite complex and covers a wide range of functionalities. Is it possible to break it down into smaller components?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I‘ve moved out the progress/fileProgress from it, otherwise it‘s now mainly related to file coordination
TBD: test on macOS 11 |
Fixed the issues we‘ve discussed including the "duckload" download corner case,
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> actually I couldn‘t reproduce this one, is there some special steps?
As discussed on MM, the behavior is expected.
> It often takes very long to see .duckload being renamed to the final name. Sometimes even 10 seconds
I don't experience this anymore. In the previous testing, a download finished correctly and I could see it completed in the Download panel. But in Finder, I saw .duckload file and it took ~10 seconds until it changed.
I performed the testing again on macOS 14, both sandboxed and non-sandboxed app. Everything works great! 💯 Job job, Alex 👏
Two last comments from me:
-
Please don't forget to perform smoke tests on macOS 11
-
One more product suggestion is to keep Downloads panel button in the stack after the manual activation for at least a minute. It was slightly annoying to activate it through the menu all the time.
Task/Issue URL: https://app.asana.com/0/1199178362774117/1201330245678289/f
Notarized build: https://github.com/duckduckgo/macos-browser/actions/runs/8388376828/artifacts/1349521698
CC: @ayoy
Description:
Steps to test this PR:
setupTemporaryDownloadURL
method atreturn
, remove the item replacement directory (po itemReplacementDirectory
;rm /tmp/path/to/the/dir
) manually and continue – this should lead to download failure.duckload
file in Finder/Dock; by clicking "x" in the Downloads panel - download should stay in the panel with "cancelled" state.duckload
file in Finder (to Trash or by Cmd+Shift+Del); byrm filename.duckload
,rm destinationFileName.zip
; by overwriting a download file (.duckload
or the target one) from another app - removed downloads should disappear from the downloads panel.duckload
and target files should stay in ~/Downloads; Click "clear" in the Downloads panel - both.duckload
and target files should be removed14.
.duckload
and target files should be removed if one of them was removed - for non-complete downloads.duckload
and target file for non-completed download, but not remove a completed download file.duckload
file, target download file should be also renamed (but not moved), download should continue, the rename should be displayed in the Downloads panel. If there‘s an existing file with the target name (i.e. renamingmyload.duckload
totest.duckload
-myload.zip
should be renamed totest.zip
but if there‘s already atest.zip
file present, the target file should remainmyload.zip
. This won‘t work when the sandboxed build downloads a file to a user-selected non-Downloads location - in this case the download should go-on with an old target name.mv myload.zip test.zip
) - the name change should be reflected in the downloads panel, the download should complete successfully to the new locationInternal references:
Pull Request Review Checklist
Software Engineering Expectations
Technical Design Template
Pull Request Documentation