nextcloud-desktop/shell_integration/MacOSX/OwnCloudFinder/RequestManager.m
Jocelyn Turcotte bfcfdeec64 shell_i: Use an NSConnection instead of a local socket #2340
This prepares the switch to the official FinderSync API on Yosemite
which requires the extension to run in a sandbox. This complicates
the usage of a local socket to communicate with a non-sandboxed GUI
client. An NSConnection is easier to use in this case, which we can
use as long as the server name (i.e. Mach port registered name) is
prefixed with the code signing Team Identifier.

A placeholder server implementation is also added to the client's
SocketApi which basically reproduces the interface of a QLocalSocket.
Most of the references to individual sockets we're only using
QIODevice methods so the type was simply reduced. A typedef to
replace the QLocalServer was the only other part needed.
2015-06-15 15:28:17 +02:00

166 lines
4.4 KiB
Objective-C

/**
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
#import "ContentManager.h"
#import "IconCache.h"
#import "RequestManager.h"
#define READ_TAG 2422
static RequestManager* sharedInstance = nil;
@implementation RequestManager
- (id)init
{
if ((self = [super init]))
{
// For the sake of allowing both the legacy and the FinderSync extensions to work with the same
// client build, use the same server name including the Team ID even though we won't be signing the bundle.
NSString *serverName = @"9B5WD74GWJ.com.owncloud.desktopclient.socketApi";
_syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
_registeredPathes = [[NSMutableDictionary alloc] init];
_requestedPaths = [[NSMutableSet alloc] init];
_shareMenuTitle = nil;
// The NSConnection will block until the distant object came back and this creates a loop hanging Finder.
// Start from a timer to have time to unwind the stack first.
[NSTimer scheduledTimerWithTimeInterval:0 target:_syncClientProxy selector:@selector(start) userInfo:nil repeats:NO];
}
return self;
}
- (void)dealloc
{
[_syncClientProxy release];
sharedInstance = nil;
[super dealloc];
}
+ (RequestManager*)sharedInstance
{
@synchronized(self)
{
if (sharedInstance == nil)
{
sharedInstance = [[self alloc] init];
}
}
return sharedInstance;
}
- (BOOL)isRegisteredPath:(NSString*)path isDirectory:(BOOL)isDir
{
// check if the file in question is underneath a registered directory
NSArray *regPathes = [_registeredPathes allKeys];
BOOL registered = NO;
NSString* checkPath = [NSString stringWithString:path];
if (isDir && ![checkPath hasSuffix:@"/"]) {
// append a slash
checkPath = [path stringByAppendingString:@"/"];
}
for( NSString *regPath in regPathes ) {
if( [checkPath hasPrefix:regPath]) {
// the path was registered
registered = YES;
break;
}
}
return registered;
}
- (void)askForIcon:(NSString*)path isDirectory:(BOOL)isDir
{
if( [self isRegisteredPath:path isDirectory:isDir] ) {
[_requestedPaths addObject:path];
[_syncClientProxy askForIcon:path isDirectory:isDir];
}
}
- (void)setResultForPath:(NSString*)path result:(NSString*)result
{
// The client will broadcast all changes, do not fill the cache for paths that Finder didn't ask for.
if ([_requestedPaths containsObject:path]) {
[[ContentManager sharedInstance] setResultForPath:path result:result];
}
}
- (void)reFetchFileNameCacheForPath:(NSString*)path
{
[_requestedPaths removeAllObjects];
[[ContentManager sharedInstance] reFetchFileNameCacheForPath:path];
}
- (void)registerPath:(NSString*)path
{
NSNumber *one = [NSNumber numberWithInt:1];
[_registeredPathes setObject:one forKey:path];
[[ContentManager sharedInstance] repaintAllWindows];
}
- (void)unregisterPath:(NSString*)path
{
[_registeredPathes removeObjectForKey:path];
[[ContentManager sharedInstance] repaintAllWindows];
}
- (void)setShareMenuTitle:(NSString*)title
{
_shareMenuTitle = title;
}
- (void)loadIconResourcePath:(NSString*)path
{
[[ContentManager sharedInstance] loadIconResourcePath:path];
}
- (void)connectionDidDie
{
// NSLog(@"Socket DISconnected! %@", [err localizedDescription]);
// clear the registered pathes.
[_registeredPathes release];
_registeredPathes = [[NSMutableDictionary alloc] init];
[_requestedPaths removeAllObjects];
// clear the caches in conent manager
ContentManager *contentman = [ContentManager sharedInstance];
[contentman clearFileNameCache];
[contentman repaintAllWindows];
}
- (void)menuItemClicked:(NSDictionary*)actionDictionary
{
// NSLog(@"RequestManager menuItemClicked %@", actionDictionary);
NSArray *filePaths = [actionDictionary valueForKey:@"files"];
for (int i = 0; i < filePaths.count; i++) {
[_syncClientProxy askOnSocket:[filePaths objectAtIndex:i] query:@"SHARE"];
}
}
- (NSString*) shareItemTitle
{
return _shareMenuTitle;
}
@end