Add ability for FileProvider app extension to reply to file provider domain identifie...
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Wed, 28 Dec 2022 23:21:33 +0000 (00:21 +0100)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 12 May 2023 05:21:09 +0000 (13:21 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift [new file with mode: 0644]
shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj

index c30fa4c3f3208695cb0c0bc4db4120f2990b5688..b162508daedb7e05051c54a0a3d9631ece2886b3 100644 (file)
@@ -18,30 +18,21 @@ import NCDesktopClientSocketKit
 
 class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension {
     let domain: NSFileProviderDomain
-    let socketClient: LocalSocketClient
-    
+    var socketClient: LocalSocketClient = LocalSocketClient()
+
     required init(domain: NSFileProviderDomain) {
         self.domain = domain
         // The containing application must create a domain using `NSFileProviderManager.add(_:, completionHandler:)`. The system will then launch the application extension process, call `FileProviderExtension.init(domain:)` to instantiate the extension for that domain, and call methods on the instance.
 
-        let bundle = Bundle(for: type(of: self))
-        guard let fileProviderSocketApiPrefix = bundle.object(forInfoDictionaryKey: "SocketApiPrefix") as? String else {
-            NSLog("Could not start file provider socket client properly as SocketApiPrefix is missing")
-            self.socketClient = LocalSocketClient()
-            super.init()
-            return;
-        }
-
-        let containerUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: fileProviderSocketApiPrefix)
-        let socketPath = containerUrl?.appendingPathComponent(".fileprovidersocket", conformingTo: .archive)
-        self.socketClient = LocalSocketClient(socketPath: socketPath?.path, lineProcessor: nil)
-        self.socketClient.start();
         super.init()
+        startLocalSocketClient()
     }
     
     func invalidate() {
         // TODO: cleanup any resources
     }
+
+    // MARK: NSFileProviderReplicatedExtension protocol methods
     
     func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress {
         // resolve the given identifier to a record in the model
@@ -83,4 +74,29 @@ class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension {
     func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest) throws -> NSFileProviderEnumerator {
         return FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
     }
+
+    // MARK: Nextcloud desktop client communication
+
+    func startLocalSocketClient() {
+        let bundle = Bundle(for: type(of: self))
+        guard let fileProviderSocketApiPrefix = bundle.object(forInfoDictionaryKey: "SocketApiPrefix") as? String else {
+            NSLog("Could not start file provider socket client properly as SocketApiPrefix is missing")
+
+            return;
+        }
+
+        let containerUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: fileProviderSocketApiPrefix)
+        let socketPath = containerUrl?.appendingPathComponent(".fileprovidersocket", conformingTo: .archive)
+        let lineProcessor = FileProviderSocketLineProcessor(delegate: self)
+
+        self.socketClient = LocalSocketClient(socketPath: socketPath?.path, lineProcessor: lineProcessor)
+        self.socketClient.start();
+    }
+
+    func sendDelegateFileProviderDomainIdentifier() {
+        let command = "FILE_PROVIDER_DOMAIN_IDENTIFIER_REQUEST_REPLY"
+        let argument = domain.identifier.rawValue
+        let message = command + ":" + argument + "\n"
+        socketClient.sendMessage(message)
+    }
 }
diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderSocketLineProcessor.swift
new file mode 100644 (file)
index 0000000..038bb74
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+import Foundation
+import NCDesktopClientSocketKit
+
+class FileProviderSocketLineProcessor: NSObject, LineProcessor {
+    var delegate: FileProviderExtension
+
+    init(delegate: FileProviderExtension) {
+        self.delegate = delegate
+    }
+
+    func process(_ line: String) {
+        NSLog("Processing file provider line: %@", line)
+
+        let splitLine = line.split(separator: ":")
+        guard let commandSubsequence = splitLine.first else {
+            NSLog("Input line did not have a first element")
+            return;
+        }
+        let command = String(commandSubsequence);
+
+        NSLog("Received command: %@", command)
+        if (command == "SEND_FILE_PROVIDER_DOMAIN_IDENTIFIER") {
+            delegate.sendDelegateFileProviderDomainIdentifier()
+        }
+    }
+}
index 7a215a8c99593a05111b50a564a4c1f4e7551625..bb8d5b755b344984f64b8b07883e06b1b11c1bb0 100644 (file)
@@ -7,6 +7,7 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               536EFBF7295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */; };
                538E396A27F4765000FA63D5 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */; };
                538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E396C27F4765000FA63D5 /* FileProviderExtension.swift */; };
                538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E396E27F4765000FA63D5 /* FileProviderItem.swift */; };
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+               536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderSocketLineProcessor.swift; sourceTree = "<group>"; };
                538E396727F4765000FA63D5 /* FileProviderExt.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = FileProviderExt.appex; sourceTree = BUILT_PRODUCTS_DIR; };
                538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
                538E396C27F4765000FA63D5 /* FileProviderExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderExtension.swift; sourceTree = "<group>"; };
                                538E396C27F4765000FA63D5 /* FileProviderExtension.swift */,
                                538E396E27F4765000FA63D5 /* FileProviderItem.swift */,
                                538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */,
+                               536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */,
                                538E397227F4765000FA63D5 /* Info.plist */,
                                538E397327F4765000FA63D5 /* FileProviderExt.entitlements */,
                        );
                        buildActionMask = 2147483647;
                        files = (
                                538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */,
+                               536EFBF7295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift in Sources */,
                                538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */,
                                538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */,
                        );