Skip to content

Fix hanging WebDAV downloads by resuming transfers after File Provider registration#467

Merged
tobihagemann merged 1 commit into
developfrom
fix/449-resume-after-registration
Jun 17, 2026
Merged

Fix hanging WebDAV downloads by resuming transfers after File Provider registration#467
tobihagemann merged 1 commit into
developfrom
fix/449-resume-after-registration

Conversation

@tobihagemann

Copy link
Copy Markdown
Member

Fixes #449.

In Files.app, tapping a WebDAV file to open it never downloads or opens: the spinner just spins forever. Some users also see "Couldn't communicate with a helper application" when they tap the stuck item again, and locking/unlocking the vault clears it temporarily. Reported on 2.8.3 through 3.1.0.

Root cause: FileProviderAdapter resumed the transfer's URLSessionTask before NSFileProviderManager.register(_:forItemWithIdentifier:) had completed. That ordering shipped in 2.8.0 (ec9703b), as a side effect of the #272 upload fix in #438, which moved resume() out of the registration completion handler. Starting the transfer before the system has registered it can leave the File Provider hanging.

The fix moves urlSessionTask.resume() back inside the registration completion handler, on both the success and error branches, so a transfer still always resumes even when registration fails (the guarantee #272 needed). Applied to both the download and upload paths.

Flow

sequenceDiagram
  participant FP as FileProviderAdapter
  participant M as NSFileProviderManager
  participant T as URLSessionTask
  FP->>M: register(task, forItemWithIdentifier:)
  M-->>FP: completion (success or error)
  FP->>T: resume()
Loading

iOS side only, no cloud-access-swift change.

Validated on a physical device (iOS 26.5): the hang no longer reproduces. New regression tests (FileProviderAdapterResumeOrderingTests) cover the download and upload paths for both the success-ordering and registration-failure cases, and the CryptomatorFileProvider suite is green.

Out of scope: re-tapping a still-downloading file triggers the unimplemented stopProvidingItem and crashes the extension. That's a separate, pre-existing bug, not addressed here.

@tobihagemann tobihagemann added this to the 3.1.1 milestone Jun 17, 2026
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6d091a5a-bf40-4737-983f-ffec0449f33f

📥 Commits

Reviewing files that changed from the base of the PR and between 5c52791 and 813999e.

📒 Files selected for processing (4)
  • Cryptomator.xcodeproj/project.pbxproj
  • CryptomatorFileProvider/FileProviderAdapter.swift
  • CryptomatorFileProviderTests/FileProviderAdapter/FileProviderAdapterResumeOrderingTests.swift
  • CryptomatorFileProviderTests/Middleware/TaskExecutor/CloudTaskExecutorTestCase.swift

Walkthrough

FileProviderAdapter changes the sequencing of URLSessionTask.resume() in both uploadFile(...) and downloadFile(...): instead of resuming the task immediately after calling taskRegistrator.register(...), the call is now placed inside the registration completion handler so the task starts only after registration finishes. A new test file, FileProviderAdapterResumeOrderingTests.swift, is added with four unit tests covering the download and upload success and failure paths, using a ResumeRecordingURLSessionTask helper to count resume() invocations. DownloadTaskManagerMock gains a property to capture the onURLSessionTaskCreation closure. The new test file is registered in the Xcode project.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • cryptomator/ios#438: Both PRs adjust FileProviderAdapter's upload flow to delay URLSessionTask.resume() until after NSFileProviderManager.register(...)/task registration completes, with corresponding test coverage — these changes are directly related.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main fix: resuming WebDAV transfers after File Provider registration to address the hanging downloads issue.
Description check ✅ Passed The description comprehensively explains the root cause, fix, and validation, directly addressing issue #449 about hanging WebDAV downloads.
Linked Issues check ✅ Passed The code changes directly address issue #449 by fixing the resume ordering in both download and upload paths, with comprehensive test coverage for the fix.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the resume ordering issue: FileProviderAdapter sequencing, new regression tests, and test infrastructure updates directly support the fix.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/449-resume-after-registration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tobihagemann tobihagemann merged commit 4bc31be into develop Jun 17, 2026
6 checks passed
@tobihagemann tobihagemann deleted the fix/449-resume-after-registration branch June 17, 2026 15:19
@aarononeal

Copy link
Copy Markdown

@tobihagemann Why resume in the error case instead of calling urlSessionTask.cancel() and returning?

@tobihagemann

Copy link
Copy Markdown
Member Author

register(...) only wires the task into the system for progress/lifecycle tracking. It's resume() that actually starts the transfer (tasks begin suspended). So a failed registration doesn't make the transfer impossible and cancelling there would just put us back to #272 (transfer silently stuck).

I must admit that I'm also looking at reference clients like ownCloud, which logs the error and resumes anyway, and Nextcloud, which catches it and resumes anyway. Neither cancels. So I hope and guess that this is the right way to do it. 😅

@aarononeal

Copy link
Copy Markdown

Oh! So register has to be called prior to resume to avoid the UI from appearing hung, but if registration fails you can still proceed to download without the UI showing it. That makes sense.

However, an edge case that comes to mind is this:

register fails
→ task resumes anyway
→ Files UI is not tracking progress/cancel
→ user retries/open again
→ Cryptomator may start a second download for the same item

Would you happen to know if that's a possibility? I couldn't find a guard check around this path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS 26.4-26.5, app 2.8.3-3.1.0: Integration with files app broken for WebDAV Nextcloud and MagentaCloud

2 participants