]> dgit.raspbian.org Git - nextcloud-desktop.git/commitdiff
Add file provider init code
authorClaudio Cambra <claudio.cambra@gmail.com>
Tue, 29 Mar 2022 13:00:59 +0000 (15:00 +0200)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 12 May 2023 05:21:06 +0000 (13:21 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
15 files changed:
.gitignore
shell_integration/MacOSX/CMakeLists.txt
shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderEnumerator.swift [new file with mode: 0644]
shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderExt.entitlements [new file with mode: 0644]
shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderExtension.swift [new file with mode: 0644]
shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderItem.swift [new file with mode: 0644]
shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/Info.plist [new file with mode: 0644]
shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist
shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj
shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.xcworkspace/contents.xcworkspacedata [new file with mode: 0644]
shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist [new file with mode: 0644]
src/gui/CMakeLists.txt
src/gui/fileprovider.h [new file with mode: 0644]
src/gui/fileprovider_mac.mm [new file with mode: 0644]
src/gui/main.cpp

index 249c4a2c7c346f5c45b96fa8390bb59e0b7a8129..85a87ed91464e2f5c5e003d552db89f43034b5d5 100644 (file)
@@ -88,6 +88,7 @@ dlldata.c
 # macOS specific
 xcuserdata/
 **/.DS_Store
+**/Carthage/
 
 # Visual C++ cache files
 ipch/
index 99116c76d987b950888ff7418420265ee4644cd3..da91e9c13b475831d737e4ecc5f798c1426cbe26 100644 (file)
@@ -15,12 +15,26 @@ if(APPLE)
     "OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
     COMMENT building Mac Overlay icons
     VERBATIM)
-  add_dependencies(mac_overlayplugin nextcloud) # for the ownCloud.icns to be generated
+
+  add_custom_target( mac_fileproviderplugin ALL
+    xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO
+    -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
+    -target FileProviderExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
+    "OC_APPLICATION_NAME=${APPLICATION_NAME}"
+    "OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
+    "OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
+    COMMENT building macOS File Provider extension
+    VERBATIM)
+
+  add_dependencies(mac_overlayplugin mac_fileproviderplugin nextcloud) # for the ownCloud.icns to be generated
 
   if (BUILD_OWNCLOUD_OSX_BUNDLE)
     install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
       DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
       USE_SOURCE_PERMISSIONS)
+    install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FileProviderExt.appex
+      DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
+      USE_SOURCE_PERMISSIONS)
   endif()
 endif()
 
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderEnumerator.swift b/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderEnumerator.swift
new file mode 100644 (file)
index 0000000..9cd3563
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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 FileProvider
+
+class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
+    
+    private let enumeratedItemIdentifier: NSFileProviderItemIdentifier
+    private let anchor = NSFileProviderSyncAnchor("an anchor".data(using: .utf8)!)
+    
+    init(enumeratedItemIdentifier: NSFileProviderItemIdentifier) {
+        self.enumeratedItemIdentifier = enumeratedItemIdentifier
+        super.init()
+    }
+
+    func invalidate() {
+        // TODO: perform invalidation of server connection if necessary
+    }
+
+    func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) {
+        /* TODO:
+         - inspect the page to determine whether this is an initial or a follow-up request
+         
+         If this is an enumerator for a directory, the root container or all directories:
+         - perform a server request to fetch directory contents
+         If this is an enumerator for the active set:
+         - perform a server request to update your local database
+         - fetch the active set from your local database
+         
+         - inform the observer about the items returned by the server (possibly multiple times)
+         - inform the observer that you are finished with this page
+         */
+        observer.didEnumerate([FileProviderItem(identifier: NSFileProviderItemIdentifier("a file"))])
+        observer.finishEnumerating(upTo: nil)
+    }
+    
+    func enumerateChanges(for observer: NSFileProviderChangeObserver, from anchor: NSFileProviderSyncAnchor) {
+        /* TODO:
+         - query the server for updates since the passed-in sync anchor
+         
+         If this is an enumerator for the active set:
+         - note the changes in your local database
+         
+         - inform the observer about item deletions and updates (modifications + insertions)
+         - inform the observer when you have finished enumerating up to a subsequent sync anchor
+         */
+        observer.finishEnumeratingChanges(upTo: anchor, moreComing: false)
+    }
+
+    func currentSyncAnchor(completionHandler: @escaping (NSFileProviderSyncAnchor?) -> Void) {
+        completionHandler(anchor)
+    }
+}
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderExt.entitlements b/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderExt.entitlements
new file mode 100644 (file)
index 0000000..f399700
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>com.apple.application-identifier</key>
+       <string>$(AppIdentifierPrefix)$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+       <key>com.apple.security.app-sandbox</key>
+       <true/>
+       <key>com.apple.security.application-groups</key>
+       <array>
+               <string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
+       </array>
+</dict>
+</plist>
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderExtension.swift b/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderExtension.swift
new file mode 100644 (file)
index 0000000..df2f2e8
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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 FileProvider
+
+class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension {
+    required init(domain: NSFileProviderDomain) {
+        // TODO: 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.
+        super.init()
+    }
+    
+    func invalidate() {
+        // TODO: cleanup any resources
+    }
+    
+    func item(for identifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress {
+        // resolve the given identifier to a record in the model
+        
+        // TODO: implement the actual lookup
+
+        completionHandler(FileProviderItem(identifier: identifier), nil)
+        return Progress()
+    }
+    
+    func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier, version requestedVersion: NSFileProviderItemVersion?, request: NSFileProviderRequest, completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress {
+        // TODO: implement fetching of the contents for the itemIdentifier at the specified version
+        
+        completionHandler(nil, nil, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
+        return Progress()
+    }
+    
+    func createItem(basedOn itemTemplate: NSFileProviderItem, fields: NSFileProviderItemFields, contents url: URL?, options: NSFileProviderCreateItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
+        // TODO: a new item was created on disk, process the item's creation
+        
+        completionHandler(itemTemplate, [], false, nil)
+        return Progress()
+    }
+    
+    func modifyItem(_ item: NSFileProviderItem, baseVersion version: NSFileProviderItemVersion, changedFields: NSFileProviderItemFields, contents newContents: URL?, options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
+        // TODO: an item was modified on disk, process the item's modification
+        
+        completionHandler(nil, [], false, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
+        return Progress()
+    }
+    
+    func deleteItem(identifier: NSFileProviderItemIdentifier, baseVersion version: NSFileProviderItemVersion, options: NSFileProviderDeleteItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (Error?) -> Void) -> Progress {
+        // TODO: an item was deleted on disk, process the item's deletion
+        
+        completionHandler(NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
+        return Progress()
+    }
+    
+    func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier, request: NSFileProviderRequest) throws -> NSFileProviderEnumerator {
+        return FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
+    }
+}
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderItem.swift b/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/FileProviderItem.swift
new file mode 100644 (file)
index 0000000..fa793e4
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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 FileProvider
+import UniformTypeIdentifiers
+
+class FileProviderItem: NSObject, NSFileProviderItem {
+
+    // TODO: implement an initializer to create an item from your extension's backing model
+    // TODO: implement the accessors to return the values from your extension's backing model
+    
+    private let identifier: NSFileProviderItemIdentifier
+    
+    init(identifier: NSFileProviderItemIdentifier) {
+        self.identifier = identifier
+    }
+    
+    var itemIdentifier: NSFileProviderItemIdentifier {
+        return identifier
+    }
+    
+    var parentItemIdentifier: NSFileProviderItemIdentifier {
+        return .rootContainer
+    }
+    
+    var capabilities: NSFileProviderItemCapabilities {
+        return [.allowsReading, .allowsWriting, .allowsRenaming, .allowsReparenting, .allowsTrashing, .allowsDeleting]
+    }
+    
+    var itemVersion: NSFileProviderItemVersion {
+        NSFileProviderItemVersion(contentVersion: "a content version".data(using: .utf8)!, metadataVersion: "a metadata version".data(using: .utf8)!)
+    }
+    
+    var filename: String {
+        return identifier.rawValue
+    }
+    
+    var contentType: UTType {
+        return identifier == NSFileProviderItemIdentifier.rootContainer ? .folder : .plainText
+    }
+}
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/Info.plist b/shell_integration/MacOSX/OwnCloudFinderSync/FileProviderExt/Info.plist
new file mode 100644 (file)
index 0000000..5072333
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>NSExtension</key>
+       <dict>
+               <key>NSExtensionFileProviderDocumentGroup</key>
+               <string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
+               <key>NSExtensionFileProviderSupportsEnumeration</key>
+               <true/>
+               <key>NSExtensionPointIdentifier</key>
+               <string>com.apple.fileprovider-nonui</string>
+               <key>NSExtensionPrincipalClass</key>
+               <string>$(PRODUCT_MODULE_NAME).FileProviderExtension</string>
+       </dict>
+</dict>
+</plist>
index 88bb87e9163c187084f4a3168b1a39918f64c405..2a669ce7374d9ec3fbcbe7ac7d9f92acd8617567 100644 (file)
@@ -2,8 +2,6 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
-       <key>SocketApiPrefix</key>
-       <string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleDisplayName</key>
@@ -39,5 +37,7 @@
        </dict>
        <key>NSPrincipalClass</key>
        <string>NSApplication</string>
+       <key>SocketApiPrefix</key>
+       <string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
 </dict>
 </plist>
index ad6d849dce408fe2eaa2086db86cb67411acff69..f15453b20e1ed41192ce61fb22ceb3d7b18a08e6 100644 (file)
@@ -7,6 +7,11 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               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 */; };
+               538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */; };
+               538E397627F4765000FA63D5 /* FileProviderExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 538E396727F4765000FA63D5 /* FileProviderExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
                539158AC27BE71A900816F56 /* LineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* LineProcessor.m */; };
                539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158B227BEC98A00816F56 /* LocalSocketClient.m */; };
                C2B573BA1B1CD91E00303B36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+               538E397427F4765000FA63D5 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = C2B573951B1CD88000303B36 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 538E396627F4765000FA63D5;
+                       remoteInfo = FileProviderExt;
+               };
                C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = C2B573951B1CD88000303B36 /* Project object */;
@@ -38,6 +50,7 @@
                        dstSubfolderSpec = 13;
                        files = (
                                C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */,
+                               538E397627F4765000FA63D5 /* FileProviderExt.appex in Embed App Extensions */,
                        );
                        name = "Embed App Extensions";
                        runOnlyForDeploymentPostprocessing = 1;
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+               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>"; };
+               538E396E27F4765000FA63D5 /* FileProviderItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderItem.swift; sourceTree = "<group>"; };
+               538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderEnumerator.swift; sourceTree = "<group>"; };
+               538E397227F4765000FA63D5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+               538E397327F4765000FA63D5 /* FileProviderExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FileProviderExt.entitlements; sourceTree = "<group>"; };
                539158A927BE606500816F56 /* LineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LineProcessor.h; sourceTree = "<group>"; };
                539158AA27BE67CC00816F56 /* SyncClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SyncClient.h; sourceTree = "<group>"; };
                539158AB27BE71A900816F56 /* LineProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LineProcessor.m; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
+               538E396427F4765000FA63D5 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               538E396A27F4765000FA63D5 /* UniformTypeIdentifiers.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                C2B573AE1B1CD91E00303B36 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+               538E396827F4765000FA63D5 /* Frameworks */ = {
+                       isa = PBXGroup;
+                       children = (
+                               538E396927F4765000FA63D5 /* UniformTypeIdentifiers.framework */,
+                       );
+                       name = Frameworks;
+                       sourceTree = "<group>";
+               };
+               538E396B27F4765000FA63D5 /* FileProviderExt */ = {
+                       isa = PBXGroup;
+                       children = (
+                               538E396C27F4765000FA63D5 /* FileProviderExtension.swift */,
+                               538E396E27F4765000FA63D5 /* FileProviderItem.swift */,
+                               538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */,
+                               538E397227F4765000FA63D5 /* Info.plist */,
+                               538E397327F4765000FA63D5 /* FileProviderExt.entitlements */,
+                       );
+                       path = FileProviderExt;
+                       sourceTree = "<group>";
+               };
                C2B573941B1CD88000303B36 = {
                        isa = PBXGroup;
                        children = (
                                C2B573B31B1CD91E00303B36 /* desktopclient */,
                                C2B573D81B1CD9CE00303B36 /* FinderSyncExt */,
+                               538E396B27F4765000FA63D5 /* FileProviderExt */,
+                               538E396827F4765000FA63D5 /* Frameworks */,
                                C2B573B21B1CD91E00303B36 /* Products */,
                        );
                        sourceTree = "<group>";
                        children = (
                                C2B573B11B1CD91E00303B36 /* desktopclient.app */,
                                C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */,
+                               538E396727F4765000FA63D5 /* FileProviderExt.appex */,
                        );
                        name = Products;
                        sourceTree = "<group>";
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
+               538E396627F4765000FA63D5 /* FileProviderExt */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 538E397927F4765000FA63D5 /* Build configuration list for PBXNativeTarget "FileProviderExt" */;
+                       buildPhases = (
+                               538E396327F4765000FA63D5 /* Sources */,
+                               538E396427F4765000FA63D5 /* Frameworks */,
+                               538E396527F4765000FA63D5 /* Resources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = FileProviderExt;
+                       packageProductDependencies = (
+                       );
+                       productName = FileProviderExt;
+                       productReference = 538E396727F4765000FA63D5 /* FileProviderExt.appex */;
+                       productType = "com.apple.product-type.app-extension";
+               };
                C2B573B01B1CD91E00303B36 /* desktopclient */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */;
                        );
                        dependencies = (
                                C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */,
+                               538E397527F4765000FA63D5 /* PBXTargetDependency */,
                        );
                        name = desktopclient;
                        productName = desktopclient;
                C2B573951B1CD88000303B36 /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
+                               LastSwiftUpdateCheck = 1330;
                                LastUpgradeCheck = 1240;
                                TargetAttributes = {
+                                       538E396627F4765000FA63D5 = {
+                                               CreatedOnToolsVersion = 13.3;
+                                               ProvisioningStyle = Manual;
+                                       };
                                        C2B573B01B1CD91E00303B36 = {
                                                CreatedOnToolsVersion = 6.3.1;
                                                DevelopmentTeam = 9B5WD74GWJ;
                                Base,
                        );
                        mainGroup = C2B573941B1CD88000303B36;
+                       packageReferences = (
+                       );
                        productRefGroup = C2B573B21B1CD91E00303B36 /* Products */;
                        projectDirPath = "";
                        projectRoot = "";
                        targets = (
                                C2B573B01B1CD91E00303B36 /* desktopclient */,
                                C2B573D61B1CD9CE00303B36 /* FinderSyncExt */,
+                               538E396627F4765000FA63D5 /* FileProviderExt */,
                        );
                };
 /* End PBXProject section */
 
 /* Begin PBXResourcesBuildPhase section */
+               538E396527F4765000FA63D5 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                C2B573AF1B1CD91E00303B36 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
+               538E396327F4765000FA63D5 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               538E396D27F4765000FA63D5 /* FileProviderExtension.swift in Sources */,
+                               538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */,
+                               538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                C2B573AD1B1CD91E00303B36 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+               538E397527F4765000FA63D5 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 538E396627F4765000FA63D5 /* FileProviderExt */;
+                       targetProxy = 538E397427F4765000FA63D5 /* PBXContainerItemProxy */;
+               };
                C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = C2B573D61B1CD9CE00303B36 /* FinderSyncExt */;
 /* End PBXTargetDependency section */
 
 /* Begin XCBuildConfiguration section */
+               538E397727F4765000FA63D5 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CODE_SIGN_ENTITLEMENTS = FileProviderExt/FileProviderExt.entitlements;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Manual;
+                               COPY_PHASE_STRIP = NO;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               DEVELOPMENT_TEAM = "";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               INFOPLIST_FILE = FileProviderExt/Info.plist;
+                               INFOPLIST_KEY_CFBundleDisplayName = FileProviderExt;
+                               INFOPLIST_KEY_NSHumanReadableCopyright = "";
+                               LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
+                               MACOSX_DEPLOYMENT_TARGET = 12.3;
+                               MARKETING_VERSION = 1.0;
+                               MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                               MTL_FAST_MATH = YES;
+                               ONLY_ACTIVE_ARCH = YES;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.desktopclient.FileProviderExt;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               PROVISIONING_PROFILE_SPECIFIER = "";
+                               SDKROOT = macosx;
+                               SKIP_INSTALL = YES;
+                               SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                               SWIFT_VERSION = 5.0;
+                       };
+                       name = Debug;
+               };
+               538E397827F4765000FA63D5 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CODE_SIGN_ENTITLEMENTS = FileProviderExt/FileProviderExt.entitlements;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Manual;
+                               COPY_PHASE_STRIP = NO;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               DEVELOPMENT_TEAM = "";
+                               ENABLE_NS_ASSERTIONS = NO;
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               INFOPLIST_FILE = FileProviderExt/Info.plist;
+                               INFOPLIST_KEY_CFBundleDisplayName = FileProviderExt;
+                               INFOPLIST_KEY_NSHumanReadableCopyright = "";
+                               LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
+                               MACOSX_DEPLOYMENT_TARGET = 12.3;
+                               MARKETING_VERSION = 1.0;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               MTL_FAST_MATH = YES;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.desktopclient.FileProviderExt;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               PROVISIONING_PROFILE_SPECIFIER = "";
+                               SDKROOT = macosx;
+                               SKIP_INSTALL = YES;
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+                               SWIFT_VERSION = 5.0;
+                       };
+                       name = Release;
+               };
                C2B573991B1CD88000303B36 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                C2B573CD1B1CD91E00303B36 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                PROVISIONING_PROFILE = "";
                                SDKROOT = macosx;
+                               SWIFT_OBJC_BRIDGING_HEADER = "desktopclient/desktopclient-Bridging-Header.h";
+                               SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                               SWIFT_VERSION = 5.0;
                        };
                        name = Debug;
                };
                C2B573CE1B1CD91E00303B36 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                PROVISIONING_PROFILE = "";
                                SDKROOT = macosx;
+                               SWIFT_OBJC_BRIDGING_HEADER = "desktopclient/desktopclient-Bridging-Header.h";
+                               SWIFT_VERSION = 5.0;
                        };
                        name = Release;
                };
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
+               538E397927F4765000FA63D5 /* Build configuration list for PBXNativeTarget "FileProviderExt" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               538E397727F4765000FA63D5 /* Debug */,
+                               538E397827F4765000FA63D5 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "OwnCloudFinderSync" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644 (file)
index 0000000..919434a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644 (file)
index 0000000..18d9810
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>IDEDidComputeMac32BitWarning</key>
+       <true/>
+</dict>
+</plist>
index 7639f95abd7b472bded09323e56a1b0892aa6272..5c4904d115a8c30ded49d51afb3e8313dcb87d05 100644 (file)
@@ -280,6 +280,7 @@ endif()
 IF( APPLE )
     list(APPEND client_SRCS cocoainitializer_mac.mm)
     list(APPEND client_SRCS systray.mm)
+    list(APPEND client_SRCS fileprovider_mac.mm)
 
     if(SPARKLE_FOUND AND BUILD_UPDATER)
         # Define this, we need to check in updater.cpp
@@ -653,7 +654,7 @@ endif()
 
 if (APPLE)
     find_package(Qt5 COMPONENTS MacExtras)
-    target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications")
+    target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications FileProvider")
 endif()
 
 if(WITH_CRASHREPORTER)
diff --git a/src/gui/fileprovider.h b/src/gui/fileprovider.h
new file mode 100644 (file)
index 0000000..0c816fe
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef FILEPROVIDER_H
+#define FILEPROVIDER_H
+
+namespace OCC {
+namespace Mac {
+
+    class FileProviderInitializer
+    {
+    public:
+        FileProviderInitializer();
+        ~FileProviderInitializer();
+
+    private:
+        class Private;
+        Private *d;
+    };
+
+} // namespace Mac
+} // namespace OCC
+
+#endif
diff --git a/src/gui/fileprovider_mac.mm b/src/gui/fileprovider_mac.mm
new file mode 100644 (file)
index 0000000..59a706e
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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/Foundation.h>
+#import <FileProvider/FileProvider.h>
+
+#include "application.h"
+#include "fileprovider.h"
+
+namespace OCC {
+namespace Mac {
+
+class FileProviderInitializer::Private {
+  public:
+    Private() {
+        domainIdentifier = @APPLICATION_REV_DOMAIN;
+        name = @APPLICATION_NAME;
+        fileProviderDomain = [[NSFileProviderDomain alloc] initWithIdentifier:domainIdentifier displayName:name];
+        setupFileProvider();
+    }
+
+    ~Private() = default;
+
+    void setupFileProvider() {
+        [NSFileProviderManager addDomain:fileProviderDomain completionHandler:^(NSError *error) {
+            if(error) {
+                NSLog(@"Add file provider domain: %i %@", [error code], [error localizedDescription]);
+            }
+        }];
+    }
+
+    void removeFileProvider() {
+        [NSFileProviderManager removeDomain:fileProviderDomain completionHandler:^(NSError *error) {
+            if(error) {
+                NSLog(@"Remove file provider domain: %i %@", [error code], [error localizedDescription]);
+            }
+        }];
+    }
+
+    NSFileProviderDomainIdentifier domainIdentifier;
+    NSString *name;
+    NSFileProviderDomain *fileProviderDomain;
+};
+
+FileProviderInitializer::FileProviderInitializer() {
+    d = new FileProviderInitializer::Private();
+    d->setupFileProvider();
+}
+
+FileProviderInitializer::~FileProviderInitializer() {
+    d->removeFileProvider();
+    delete d;
+}
+
+} // namespace Mac
+} // namespace OCC
index 40af80ac019c5f307b2a1713d1e2fd4d82658816..3b746d645e48db6561c918ad6db06f784aa4eecc 100644 (file)
 #include <sys/resource.h>
 #endif
 
+#ifdef Q_OS_MACOS
+#include "fileprovider.h"
+#endif
+
 #include "application.h"
 #include "cocoainitializer.h"
 #include "theme.h"
@@ -74,6 +78,7 @@ int main(int argc, char **argv)
     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
 #ifdef Q_OS_MAC
     Mac::CocoaInitializer cocoaInit; // RIIA
+    Mac::FileProviderInitializer fileProviderInit;
 #endif
 
     auto surfaceFormat = QSurfaceFormat::defaultFormat();