2023-03-21 15:28:48 +03:00
/*
* Copyright ( C ) 2023 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
2024-01-22 09:40:47 +03:00
import Foundation
2023-03-21 15:28:48 +03:00
import NCDesktopClientSocketKit
import NextcloudKit
2024-04-15 12:30:08 +03:00
import NextcloudFileProviderKit
2024-01-22 09:40:47 +03:00
import OSLog
2023-03-21 15:28:48 +03:00
2024-01-02 09:12:49 +03:00
extension FileProviderExtension : NSFileProviderServicing {
2024-01-23 17:37:49 +03:00
/*
This FileProviderExtension extension contains everything needed to communicate with the client .
We have two systems for communicating between the extensions and the client .
Apple ' s XPC based File Provider APIs let us easily communicate client -> extension .
This is what ClientCommunicationService is for .
We also use sockets , because the File Provider XPC system does not let us easily talk from
extension -> client .
We need this because the extension needs to be able to request account details . We can ' t
reliably do this via XPC because the extensions get torn down by the system , out of the control
of the app , and we can receive nil / no services from NSFileProviderManager . Once this is done
then XPC works ok .
*/
2024-01-02 09:12:49 +03:00
func supportedServiceSources (
for itemIdentifier : NSFileProviderItemIdentifier ,
completionHandler : @ escaping ( [ NSFileProviderServiceSource ] ? , Error ? ) -> Void
) -> Progress {
Logger . desktopClientConnection . debug ( " Serving supported service sources " )
let clientCommService = ClientCommunicationService ( fpExtension : self )
2024-02-27 16:25:22 +03:00
let fpuiExtService = FPUIExtensionServiceSource ( fpExtension : self )
let services : [ NSFileProviderServiceSource ] = [ clientCommService , fpuiExtService ]
2024-01-02 09:12:49 +03:00
completionHandler ( services , nil )
let progress = Progress ( )
progress . cancellationHandler = {
let error = NSError ( domain : NSCocoaErrorDomain , code : NSUserCancelledError )
completionHandler ( nil , error )
}
return progress
}
2023-11-21 05:40:54 +03:00
@objc func sendFileProviderDomainIdentifier ( ) {
2023-03-21 15:28:48 +03:00
let command = " FILE_PROVIDER_DOMAIN_IDENTIFIER_REQUEST_REPLY "
let argument = domain . identifier . rawValue
let message = command + " : " + argument + " \n "
socketClient ? . sendMessage ( message )
}
private func signalEnumeratorAfterAccountSetup ( ) {
guard let fpManager = NSFileProviderManager ( for : domain ) else {
2024-01-22 09:40:47 +03:00
Logger . fileProviderExtension . error (
" Could not get file provider manager for domain \( self . domain . displayName , privacy : . public ) , cannot notify after account setup "
)
2023-03-21 15:28:48 +03:00
return
}
assert ( ncAccount != nil )
fpManager . signalErrorResolved ( NSFileProviderError ( . notAuthenticated ) ) { error in
if error != nil {
2024-01-22 09:40:47 +03:00
Logger . fileProviderExtension . error (
" Error resolving not authenticated, received error: \( error ! . localizedDescription ) "
)
2023-03-21 15:28:48 +03:00
}
}
2024-01-22 09:40:47 +03:00
Logger . fileProviderExtension . debug (
" Signalling enumerators for user \( self . ncAccount ! . username ) at server \( self . ncAccount ! . serverUrl , privacy : . public ) "
)
2023-03-21 15:28:48 +03:00
fpManager . signalEnumerator ( for : . workingSet ) { error in
if error != nil {
2024-01-22 09:40:47 +03:00
Logger . fileProviderExtension . error (
" Error signalling enumerator for working set, received error: \( error ! . localizedDescription , privacy : . public ) "
)
2023-03-21 15:28:48 +03:00
}
}
}
2023-11-21 10:57:04 +03:00
@objc func setupDomainAccount ( user : String , serverUrl : String , password : String ) {
2024-04-15 12:30:08 +03:00
let newNcAccount = Account ( user : user , serverUrl : serverUrl , password : password )
2024-01-30 08:38:55 +03:00
guard newNcAccount != ncAccount else { return }
ncAccount = newNcAccount
2024-01-22 09:40:47 +03:00
ncKit . setup (
2024-04-16 13:22:53 +03:00
account : newNcAccount . ncKitAccount ,
user : newNcAccount . username ,
userId : newNcAccount . username ,
password : newNcAccount . password ,
urlBase : newNcAccount . serverUrl ,
2024-01-22 09:40:47 +03:00
userAgent : " Nextcloud-macOS/FileProviderExt " ,
nextcloudVersion : 25 ,
2024-01-30 08:38:55 +03:00
delegate : nil ) // TODO: a d d d e l e g a t e m e t h o d s f o r s e l f
2023-03-21 15:28:48 +03:00
2024-04-16 19:48:59 +03:00
changeObserver = RemoteChangeObserver ( ncKit : ncKit , domain : domain )
2024-04-16 21:47:21 +03:00
ncKit . setup ( delegate : changeObserver )
2024-04-16 19:48:59 +03:00
2024-01-22 09:40:47 +03:00
Logger . fileProviderExtension . info (
" Nextcloud account set up in File Provider extension for user: \( user , privacy : . public ) at server: \( serverUrl , privacy : . public ) "
)
2023-03-21 15:28:48 +03:00
signalEnumeratorAfterAccountSetup ( )
}
2023-11-21 05:40:54 +03:00
@objc func removeAccountConfig ( ) {
2024-01-22 09:40:47 +03:00
Logger . fileProviderExtension . info (
" Received instruction to remove account data for user \( self . ncAccount ! . username , privacy : . public ) at server \( self . ncAccount ! . serverUrl , privacy : . public ) "
)
2023-03-21 15:28:48 +03:00
ncAccount = nil
}
}