[stable-33.0] Server Actions Integration for File Provider Extension#9486
[stable-33.0] Server Actions Integration for File Provider Extension#9486i2h3 merged 2 commits intostable-33.0from
Conversation
…ension - Introduced a new presentFileActions: method in the XPC interface of the main app. - Implemented the presentFileActions: method in the main app to call existing code for file action presentation. - Added the new custom action to the build-time declarations of custom actions in the Info.plist of the file provider extension. - Extended the custom actions handling code switch to process the invocation and call the main app via XPC. Chores: - Created a shared file provider manager object and related stored property for the lifetime of the file provider extension object to be used in various places in its implementation. In example: resolving the user-visible URL of the item to present file actions for. Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
ce3a6f2 to
0011247
Compare
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
0011247 to
489eda6
Compare
|
Artifact containing the AppImage: nextcloud-appimage-pr-9486.zip Digest: To test this change/fix you can download the above artifact file, unzip it, and run it. Please make sure to quit your existing Nextcloud app and backup your data. |
There was a problem hiding this comment.
Pull request overview
This pull request is a backport of #9469 to the stable-33.0 branch, implementing server actions integration for the macOS file provider extension. The implementation enables context menu items defined by the server to be displayed and executed for files managed by the file provider extension, extending file actions support beyond traditional synchronized folders to virtual file systems.
Changes:
- Added XPC communication support for displaying file actions dialogs from the file provider extension
- Extended FileActionsModel to support both synchronized folders and file provider-managed files via optional fileId and remoteItemPath parameters
- Integrated server-defined context menu item filtering based on MIME types using NextcloudCapabilitiesKit 2.5.0
- Modernized macOS extension logging from NSLog to os_log framework
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/gui/systray.h | Added method declarations for file provider file actions dialog support |
| src/gui/systray.cpp | Implemented file provider file actions dialog creation and account state resolution |
| src/gui/owncloudgui.cpp | Connected file provider service signal to systray slot for showing file actions |
| src/gui/integration/fileactionsmodel.h | Added fileId and remoteItemPath properties to support file provider scenarios |
| src/gui/integration/fileactionsmodel.cpp | Implemented property setters and updated logic to handle both sync folders and file providers |
| src/gui/integration/FileActionsWindow.qml | Added fileId and remoteItemPath properties to QML component |
| src/gui/macOS/fileproviderservice.h | Declared new signal for showing file actions dialog |
| src/gui/macOS/fileproviderservice.mm | Implemented XPC callback for presentFileActions with thread-safe signal emission |
| shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/Info.plist | Added NCApplicationGroupIdentifier configuration |
| shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m | Replaced NSLog with os_log and updated to use NCApplicationGroupIdentifier |
| shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m | Migrated logging to os_log framework |
| shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/AppProtocol.h | Added presentFileActions XPC protocol method |
| shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist | Added File Actions custom action configuration |
| shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift | Added manager property and refactored to use it consistently |
| shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift | Implemented FileActionsAction handler to present file actions |
| shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Item/Item.swift | Added displayFileActions property and included it in userInfo |
| shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Item/Item+*.swift | Updated Item initialization calls to include displayFileActions parameter |
| shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Item/Item+typeHasApplicableContextMenuItems.swift | Added methods to check MIME type against context menu filters |
| shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Item/Item+getContextMenuItemTypeFilters.swift | Added method to fetch MIME type filters from server capabilities |
| shell_integration/MacOSX/NextcloudFileProviderKit/Sources/NextcloudFileProviderKit/Metadata/SendableItemMetadata+Array.swift | Optimized to fetch filters once and reuse for all items |
| shell_integration/MacOSX/NextcloudFileProviderKit/Tests/**/*.swift | Updated test code to include displayFileActions parameter |
| shell_integration/MacOSX/NextcloudFileProviderKit/Package.swift | Updated NextcloudCapabilitiesKit dependency to 2.5.0 |
| shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved | Updated resolved package version to 2.5.0 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| _fileId = fileId; | ||
|
|
||
| if (_accountState && !_localPath.isEmpty()) { | ||
| parseEndpoints(); | ||
| } | ||
|
|
There was a problem hiding this comment.
When creating a file actions dialog for a synchronized folder, the fileId parameter defaults to an empty string. This empty string will overwrite the correct _fileId that was retrieved from the sync journal database in setupFileProperties() (line 168). This happens because the QML property binding sets fileId: root.fileId after localPath has already been set, and the empty fileId value overwrites the database-retrieved value.
To fix this, setFileId should check if the incoming fileId is empty and avoid overwriting _fileId when it's already been set from the database. Alternatively, the property initialization order in QML could be changed, or setFileId could be made smarter about when to update.
| _fileId = fileId; | |
| if (_accountState && !_localPath.isEmpty()) { | |
| parseEndpoints(); | |
| } | |
| // Avoid overwriting a valid fileId (e.g. loaded from the sync journal) | |
| // with an empty one coming from default QML property initialization. | |
| if (fileId.isEmpty() && !_fileId.isEmpty()) { | |
| return; | |
| } | |
| _fileId = fileId; | |
| if (_accountState && !_localPath.isEmpty()) { | |
| parseEndpoints(); | |
| } |
| - (void)presentFileActions:(NSString *)fileId path:(NSString *)path remoteItemPath:(NSString *)remoteItemPath withDomainIdentifier:(NSString *)domainIdentifier | ||
| { | ||
| qCDebug(OCC::lcMacFileProviderService) << "Should present file actions for item with fileId:" | ||
| << fileId | ||
| << "and path:" | ||
| << path | ||
| << "remote item path:" | ||
| << remoteItemPath | ||
| << "domain identifier:" | ||
| << domainIdentifier; | ||
|
|
||
| const auto qFileId = QString::fromNSString(fileId); | ||
| const auto localPath = QString::fromNSString(path); | ||
| const auto qRemoteItemPath = QString::fromNSString(remoteItemPath); | ||
| const auto domainId = QString::fromNSString(domainIdentifier); | ||
|
|
||
| // Use QMetaObject::invokeMethod to emit the signal on the correct thread | ||
| // since this callback may be called on an XPC dispatch queue (non-main thread) | ||
| QMetaObject::invokeMethod(_service, "showFileActionsDialog", Qt::QueuedConnection, | ||
| Q_ARG(QString, qFileId), | ||
| Q_ARG(QString, localPath), | ||
| Q_ARG(QString, qRemoteItemPath), | ||
| Q_ARG(QString, domainId)); | ||
| } |
There was a problem hiding this comment.
The presentFileActions method accesses _service pointer without checking if it's null (line 51). In contrast, the reportSyncStatus method includes a null check for _service before using it (lines 67-69). If the FileProviderService is destroyed while an XPC callback is pending, this could lead to accessing a dangling pointer. Consider adding a null check similar to reportSyncStatus before calling QMetaObject::invokeMethod.
| /** | ||
| * @param fileId This is optional and null by default. Only when there are no synchronization folders configured (for example when only a file provider is used) is this value required. | ||
| * @param remoteItemPath The server-side path of the item. Used as a fallback to determine the success response URL when no sync folder is configured. | ||
| */ | ||
| void createFileActionsDialogWithAccountState(const QString &localPath, AccountState *accountState, const QString &fileId = {}, const QString &remoteItemPath = {}); |
There was a problem hiding this comment.
The documentation comment says "This is optional and null by default" but QString in C++ doesn't have a null state in the traditional sense - it can be empty but is always a valid object. Consider updating the comment to say "This is optional and empty by default" to be more precise about QString's behavior.
|




Backport of #9469
Warning, This backport's changes differ from the original and might be incomplete⚠️
Todo
Learn more about backports at https://docs.nextcloud.com/server/stable/go.php?to=developer-backports.