From ac1b11708fbdc89d93e11b892ad8ab914eeb7c74 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Thu, 18 Apr 2024 01:58:38 +0800 Subject: [PATCH 1/5] Improve logging across file provider sharing Signed-off-by: Claudio Cambra --- .../DocumentActionViewController.swift | 8 +++- .../FileProviderUIExt/ShareController.swift | 42 +++++++++++++++---- .../FileProviderUIExt/ShareOptionsView.swift | 8 ++-- .../ShareViewController.swift | 8 +++- 4 files changed, 49 insertions(+), 17 deletions(-) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/DocumentActionViewController.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/DocumentActionViewController.swift index dd068f0ac..96363e962 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/DocumentActionViewController.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/DocumentActionViewController.swift @@ -34,7 +34,7 @@ class DocumentActionViewController: FPUIActionExtensionViewController { override func prepare( forAction actionIdentifier: String, itemIdentifiers: [NSFileProviderItemIdentifier] ) { - Logger.actionViewController.info("Preparing for action: \(actionIdentifier)") + Logger.actionViewController.info("Preparing action: \(actionIdentifier, privacy: .public)") if actionIdentifier == "com.nextcloud.desktopclient.FileProviderUIExt.ShareAction" { prepare(childViewController: ShareViewController(itemIdentifiers)) @@ -43,7 +43,11 @@ class DocumentActionViewController: FPUIActionExtensionViewController { } override func prepare(forError error: Error) { - Logger.actionViewController.info("Preparing for error: \(error.localizedDescription)") + Logger.actionViewController.info( + """ + Preparing for error: \(error.localizedDescription, privacy: .public) + """ + ) } override public func loadView() { diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareController.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareController.swift index ba2666f8b..161d18700 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareController.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareController.swift @@ -42,14 +42,18 @@ class ShareController: ObservableObject { ) { account, share, data, error in defer { continuation.resume(returning: error) } guard error == .success else { - Logger.shareController.error("Error creating link share: \(error)") + Logger.shareController.error( + """ + Error creating link share: \(error.errorDescription, privacy: .public) + """ + ) return } } } else { guard let shareWith = shareWith else { let errorString = "No recipient for share!" - Logger.shareController.error("\(errorString)") + Logger.shareController.error("\(errorString, privacy: .public)") let error = NKError(statusCode: 0, fallbackDescription: errorString) continuation.resume(returning: error) return @@ -66,7 +70,11 @@ class ShareController: ObservableObject { ) { account, share, data, error in defer { continuation.resume(returning: error) } guard error == .success else { - Logger.shareController.error("Error creating share: \(error)") + Logger.shareController.error( + """ + Error creating share: \(error.errorDescription, privacy: .public) + """ + ) return } } @@ -90,7 +98,7 @@ class ShareController: ObservableObject { attributes: String? = nil, options: NKRequestOptions = NKRequestOptions() ) async -> NKError? { - Logger.shareController.info("Saving share: \(self.share.url)") + Logger.shareController.info("Saving share: \(self.share.url, privacy: .public)") return await withCheckedContinuation { continuation in kit.updateShare( idShare: share.idShare, @@ -104,10 +112,18 @@ class ShareController: ObservableObject { attributes: attributes, options: options ) { account, share, data, error in - Logger.shareController.info("Received update response: \(share?.url ?? "")") + Logger.shareController.info( + """ + Received update response: \(share?.url ?? "", privacy: .public) + """ + ) defer { continuation.resume(returning: error) } guard error == .success, let share = share else { - Logger.shareController.error("Error updating save: \(error.errorDescription)") + Logger.shareController.error( + """ + Error updating save: \(error.errorDescription, privacy: .public) + """ + ) return } self.share = share @@ -116,13 +132,21 @@ class ShareController: ObservableObject { } func delete() async -> NKError? { - Logger.shareController.info("Deleting share: \(self.share.url)") + Logger.shareController.info("Deleting share: \(self.share.url, privacy: .public)") return await withCheckedContinuation { continuation in kit.deleteShare(idShare: share.idShare) { account, error in - Logger.shareController.info("Received delete response: \(self.share.url)") + Logger.shareController.info( + """ + Received delete response: \(self.share.url, privacy: .public) + """ + ) defer { continuation.resume(returning: error) } guard error == .success else { - Logger.shareController.error("Error deleting save: \(error.errorDescription)") + Logger.shareController.error( + """ + Error deleting save: \(error.errorDescription, privacy: .public) + """ + ) return } } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareOptionsView.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareOptionsView.swift index 516909055..995bc1f29 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareOptionsView.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareOptionsView.swift @@ -71,7 +71,7 @@ class ShareOptionsView: NSView { } var createMode = false { didSet { - Logger.shareOptionsView.info("Create mode set: \(self.createMode)") + Logger.shareOptionsView.info("Create mode set: \(self.createMode, privacy: .public)") shareTypePicker.isHidden = !createMode shareRecipientTextField.isHidden = !createMode labelTextField.isHidden = createMode // Cannot set label on create API call @@ -259,10 +259,10 @@ class ShareOptionsView: NSView { let itemServerRelativePath = dataSource.itemServerRelativePath else { Logger.shareOptionsView.error("Cannot create new share due to missing data.") - Logger.shareOptionsView.error("dataSource: \(self.dataSource)") - Logger.shareOptionsView.error("kit: \(self.kit)") + Logger.shareOptionsView.error("dataSource: \(self.dataSource, privacy: .public)") + Logger.shareOptionsView.error("kit: \(self.kit, privacy: .public)") Logger.shareOptionsView.error( - "path: \(self.dataSource?.itemServerRelativePath ?? "")" + "path: \(self.dataSource?.itemServerRelativePath ?? "", privacy: .public)" ) return } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift index 55955f143..e6d969e85 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift @@ -79,7 +79,7 @@ class ShareViewController: NSViewController, ShareViewDataSourceUIDelegate { optionsView.dataSource = shareDataSource } catch let error { let errorString = "Error processing item: \(error)" - Logger.shareViewController.error("\(errorString)") + Logger.shareViewController.error("\(errorString, privacy: .public)") fileNameLabel.stringValue = "Unknown item" descriptionLabel.stringValue = errorString } @@ -99,7 +99,11 @@ class ShareViewController: NSViewController, ShareViewDataSourceUIDelegate { let fileThumbnail = await withCheckedContinuation { continuation in generator.generateRepresentations(for: request) { thumbnail, type, error in if thumbnail == nil || error != nil { - Logger.shareViewController.error("Could not get thumbnail: \(error)") + Logger.shareViewController.error( + """ + Could not get thumbnail: \(error, privacy: .public) + """ + ) } continuation.resume(returning: thumbnail) } From 19cf69ccd3b3f8dbdfe3fc7d7d8861f53c226db7 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Thu, 18 Apr 2024 02:07:48 +0800 Subject: [PATCH 2/5] Make sure network error is shown in UI instead of generic error Signed-off-by: Claudio Cambra --- .../FileProviderUIExt/ShareTableViewDataSource.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareTableViewDataSource.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareTableViewDataSource.swift index 70aeb8c50..3cca1d1a9 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareTableViewDataSource.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareTableViewDataSource.swift @@ -99,6 +99,7 @@ class ShareTableViewDataSource: NSObject, NSTableViewDataSource, NSTableViewDele account = convertedAccount await sharesTableView?.deselectAll(self) capabilities = await fetchCapabilities() + guard capabilities != nil else { return } guard capabilities?.filesSharing?.apiEnabled == true else { presentError("Server does not support shares.") return From 96f1ba656f881c6a385d6c2ef654d3e8fbf212e5 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Thu, 18 Apr 2024 02:26:49 +0800 Subject: [PATCH 3/5] Unify FileProviderUIExt entitlements Signed-off-by: Claudio Cambra --- .../FileProviderUIExt.entitlements | 4 ++++ .../FileProviderUIExtRelease.entitlements | 16 ---------------- .../project.pbxproj | 8 +++----- 3 files changed, 7 insertions(+), 21 deletions(-) delete mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExtRelease.entitlements diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExt.entitlements b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExt.entitlements index 5d2a36d31..eab912dc4 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExt.entitlements +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExt.entitlements @@ -8,5 +8,9 @@ $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) + com.apple.security.network.client + + com.apple.security.network.server + diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExtRelease.entitlements b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExtRelease.entitlements deleted file mode 100644 index eab912dc4..000000000 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExtRelease.entitlements +++ /dev/null @@ -1,16 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.application-groups - - $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) - - com.apple.security.network.client - - com.apple.security.network.server - - - diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj index cd05dd8ef..d5bed2cee 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj +++ b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj @@ -157,7 +157,6 @@ 536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderSocketLineProcessor.swift; sourceTree = ""; }; 5374FD432B95EE1400C78D54 /* ShareController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareController.swift; sourceTree = ""; }; 5376307C2B85E2ED0026BFAB /* Logger+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logger+Extensions.swift"; sourceTree = ""; }; - 5376307E2B85E5650026BFAB /* FileProviderUIExt.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = FileProviderUIExt.entitlements; sourceTree = ""; }; 537630902B85F4980026BFAB /* ShareViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ShareViewController.xib; sourceTree = ""; }; 537630922B85F4B00026BFAB /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; 537630942B860D560026BFAB /* FPUIExtensionServiceSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FPUIExtensionServiceSource.swift; sourceTree = ""; }; @@ -181,7 +180,7 @@ 53D666602B70C9A70042C03D /* FileProviderConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderConfig.swift; sourceTree = ""; }; 53ED472F29C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderExtension+ClientInterface.swift"; sourceTree = ""; }; 53FE144F2B8E0658006C4193 /* ShareTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareTableViewDataSource.swift; sourceTree = ""; }; - 53FE14572B8E3A7C006C4193 /* FileProviderUIExtRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FileProviderUIExtRelease.entitlements; sourceTree = ""; }; + 53FE14572B8E3A7C006C4193 /* FileProviderUIExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FileProviderUIExt.entitlements; sourceTree = ""; }; 53FE14582B8E3F6C006C4193 /* ShareTableItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareTableItemView.swift; sourceTree = ""; }; 53FE145A2B8F1305006C4193 /* NKShare+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NKShare+Extensions.swift"; sourceTree = ""; }; 53FE14642B8F6700006C4193 /* ShareViewDataSourceUIDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewDataSourceUIDelegate.swift; sourceTree = ""; }; @@ -329,8 +328,7 @@ 537630922B85F4B00026BFAB /* ShareViewController.swift */, 537630902B85F4980026BFAB /* ShareViewController.xib */, 53FE14642B8F6700006C4193 /* ShareViewDataSourceUIDelegate.swift */, - 5376307E2B85E5650026BFAB /* FileProviderUIExt.entitlements */, - 53FE14572B8E3A7C006C4193 /* FileProviderUIExtRelease.entitlements */, + 53FE14572B8E3A7C006C4193 /* FileProviderUIExt.entitlements */, 53B979852B84C81F002DA742 /* Info.plist */, ); path = FileProviderUIExt; @@ -1070,7 +1068,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = FileProviderUIExt/FileProviderUIExtRelease.entitlements; + CODE_SIGN_ENTITLEMENTS = FileProviderUIExt/FileProviderUIExt.entitlements; CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; From 59928a6c3364c5cf4b4e883544939fc89889d410 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Thu, 18 Apr 2024 04:54:40 +0800 Subject: [PATCH 4/5] Explicitly set bundle name and identifiers from env vars in FileProviderUIExt Signed-off-by: Claudio Cambra --- .../NextcloudIntegration/FileProviderUIExt/Info.plist | 10 ++++++++-- .../NextcloudIntegration.xcodeproj/project.pbxproj | 2 -- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Info.plist b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Info.plist index f559d75c4..85f108b15 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Info.plist +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/Info.plist @@ -2,6 +2,12 @@ + CFBundleName + $(PRODUCT_NAME) + CFBundleDisplayName + $(OC_APPLICATION_NAME) File Provider UI Extension + CFBundleIdentifier + $(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME) NSExtension NSExtensionFileProviderActions @@ -15,10 +21,10 @@ Share options - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).DocumentActionViewController NSExtensionPointIdentifier com.apple.fileprovider-actionsui + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).DocumentActionViewController diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj index d5bed2cee..aadb372da 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj +++ b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj @@ -1021,7 +1021,6 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = FileProviderUIExt/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = FileProviderUIExt; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_OUTPUT_FORMAT = "same-as-input"; INFOPLIST_PREPROCESS = NO; @@ -1082,7 +1081,6 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = FileProviderUIExt/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = FileProviderUIExt; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_OUTPUT_FORMAT = "same-as-input"; INFOPLIST_PREPROCESS = NO; From b80afca177d93b1587134dce7149f43a156a85e4 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Thu, 18 Apr 2024 04:55:14 +0800 Subject: [PATCH 5/5] Wrap access of itemUrl in security scoping Signed-off-by: Claudio Cambra --- .../FileProviderUIExt/ShareViewController.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift index e6d969e85..058708a65 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/ShareViewController.swift @@ -47,6 +47,13 @@ class ShareViewController: NSViewController, ShareViewDataSourceUIDelegate { return } + Logger.shareViewController.info( + """ + Instantiated with itemIdentifiers: + \(itemIdentifiers.map { $0.rawValue }, privacy: .public) + """ + ) + Task { await processItemIdentifier(firstItem) } @@ -72,11 +79,16 @@ class ShareViewController: NSViewController, ShareViewDataSourceUIDelegate { do { let itemUrl = try await manager.getUserVisibleURL(for: itemIdentifier) + guard itemUrl.startAccessingSecurityScopedResource() else { + Logger.shareViewController.error("Could not access scoped resource for item url!") + return + } await updateDisplay(itemUrl: itemUrl) shareDataSource.uiDelegate = self shareDataSource.sharesTableView = tableView shareDataSource.loadItem(url: itemUrl) optionsView.dataSource = shareDataSource + itemUrl.stopAccessingSecurityScopedResource() } catch let error { let errorString = "Error processing item: \(error)" Logger.shareViewController.error("\(errorString, privacy: .public)")