/* * Copyright (C) 2022 by Claudio Cambra * * 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. */ #include "fileproviderxpc.h" #include #import #import "ClientCommunicationProtocol.h" namespace { static const auto clientCommunicationServiceName = "com.nextcloud.desktopclient.ClientCommunicationService"; static NSString *const nsClientCommunicationServiceName = [NSString stringWithUTF8String:clientCommunicationServiceName]; } namespace OCC { namespace Mac { Q_LOGGING_CATEGORY(lcFileProviderXPC, "nextcloud.gui.macos.fileprovider.xpc", QtInfoMsg) FileProviderXPC::FileProviderXPC(QObject *parent) : QObject{parent} { } void FileProviderXPC::start() { qCInfo(lcFileProviderXPC) << "Starting file provider XPC"; dispatch_group_t group = dispatch_group_create(); __block NSMutableArray *managers = NSMutableArray.array; dispatch_group_enter(group); // Set up connections for each domain [NSFileProviderManager getDomainsWithCompletionHandler:^(NSArray *const domains, NSError *const error){ if (error != nil) { qCWarning(lcFileProviderXPC) << "Error getting domains" << error; dispatch_group_leave(group); return; } for (NSFileProviderDomain *const domain in domains) { qCInfo(lcFileProviderXPC) << "Got domain" << domain.identifier; NSFileProviderManager *const manager = [NSFileProviderManager managerForDomain:domain]; [managers addObject:manager]; } dispatch_group_leave(group); }]; dispatch_group_wait(group, DISPATCH_TIME_FOREVER); if (managers.count == 0) { qCWarning(lcFileProviderXPC) << "No domains found"; return; } __block NSMutableArray *urls = NSMutableArray.array; for (NSFileProviderManager *const manager in managers) { dispatch_group_enter(group); [manager getUserVisibleURLForItemIdentifier:NSFileProviderRootContainerItemIdentifier completionHandler:^(NSURL *const url, NSError *const error){ if (error != nil) { qCWarning(lcFileProviderXPC) << "Error getting user visible url" << error; dispatch_group_leave(group); return; } qCDebug(lcFileProviderXPC) << "Got user visible url" << url; [urls addObject:url]; dispatch_group_leave(group); }]; } dispatch_group_wait(group, DISPATCH_TIME_FOREVER); if (urls.count == 0) { qCWarning(lcFileProviderXPC) << "No urls found"; return; } NSMutableArray *> *const fpServices = NSMutableArray.array; for (NSURL *const url in urls) { dispatch_group_enter(group); [NSFileManager.defaultManager getFileProviderServicesForItemAtURL:url completionHandler:^(NSDictionary *const services, NSError *const error){ if (error != nil) { qCWarning(lcFileProviderXPC) << "Error getting file provider services" << error; dispatch_group_leave(group); return; } qCInfo(lcFileProviderXPC) << "Got file provider services for" << url.absoluteString << "has number of services:" << services.count; [fpServices addObject:services]; dispatch_group_leave(group); }]; } dispatch_group_wait(group, DISPATCH_TIME_FOREVER); if (fpServices.count == 0) { qCWarning(lcFileProviderXPC) << "No file provider services found"; return; } for (NSDictionary *const services in fpServices) { NSArray *const serviceNamesArray = services.allKeys; for (NSFileProviderServiceName serviceName in serviceNamesArray) { qCInfo(lcFileProviderXPC) << "Got service" << serviceName; if (![serviceName isEqualToString:nsClientCommunicationServiceName]) { continue; } NSFileProviderService *const service = services[serviceName]; dispatch_group_enter(group); [service getFileProviderConnectionWithCompletionHandler:^(NSXPCConnection *const connection, NSError *const error){ if (error != nil) { qCWarning(lcFileProviderXPC) << "Error getting file provider connection" << error; dispatch_group_leave(group); return; } qCInfo(lcFileProviderXPC) << "Got file provider connection" << connection; if (connection == nil) { qCWarning(lcFileProviderXPC) << "Connection is nil"; dispatch_group_leave(group); return; } connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(ClientCommunicationProtocol)]; [connection resume]; const id clientCommService = (id)[connection remoteObjectProxyWithErrorHandler:^(NSError *const error){ qCWarning(lcFileProviderXPC) << "Error getting remote object proxy" << error; dispatch_group_leave(group); }]; if (clientCommService == nil) { qCWarning(lcFileProviderXPC) << "Client communication service is nil"; dispatch_group_leave(group); return; } dispatch_group_leave(group); }]; } } dispatch_group_wait(group, DISPATCH_TIME_FOREVER); } } // namespace OCC } // namespace Mac