Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJocelyn Turcotte <jturcotte@woboq.com>2015-06-15 15:57:33 +0300
committerJocelyn Turcotte <jturcotte@woboq.com>2015-06-15 16:28:21 +0300
commit02f6dbba46a44aed3fc9550090646f13c1bf59ae (patch)
tree4e99ae7ab980fd74af52687d597861c8b21933ee /shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt
parentbfcfdeec64978189d7dec057de9465732e464500 (diff)
shell_i: Add a FinderSync-based implementation #2340
This uses the new official API to show overlay icons and add our custom context menu entry instead of hooking directly into the Finder process and intercept drawind routines. A dummy desktopclient target is also in the project to allow debugging directly in Xcode while the official client can be started from the command line. Otherwise Xcode won't allow attaching to the debugee. Dummy icon files have been added while we get proper icon produced. We can't use the old icons since what we use for the legacy shell integration is already padded according to where the badge should appear on the full icon.
Diffstat (limited to 'shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt')
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h28
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m161
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSyncExt.entitlements12
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist43
4 files changed, 244 insertions, 0 deletions
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
new file mode 100644
index 000000000..749f84931
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.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 <Cocoa/Cocoa.h>
+#import <FinderSync/FinderSync.h>
+#import "SyncClientProxy.h"
+
+@interface FinderSync : FIFinderSync <SyncClientProxyDelegate>
+{
+ SyncClientProxy *_syncClientProxy;
+ NSMutableSet *_registeredDirectories;
+ NSMutableSet *_requestedUrls;
+ NSString *_shareMenuTitle;
+}
+
+@end
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
new file mode 100644
index 000000000..8c0c2c0a8
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.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 "FinderSync.h"
+
+
+@implementation FinderSync
+
+- (instancetype)init
+{
+ self = [super init];
+
+ FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
+ NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
+ // This was added to the bundle's Info.plist to get it from the build system
+ NSString *teamIdentifierPrefix = [extBundle objectForInfoDictionaryKey:@"TeamIdentifierPrefix"];
+
+ [syncController setBadgeImage:[extBundle imageForResource:@"ok.icns"] label:nil forBadgeIdentifier:@"OK"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"sync.icns"] label:nil forBadgeIdentifier:@"SYNC"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"sync.icns"] label:nil forBadgeIdentifier:@"NEW"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"warning.icns"] label:nil forBadgeIdentifier:@"IGNORE"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"error.icns"] label:nil forBadgeIdentifier:@"ERROR"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"ok_swm.icns"] label:nil forBadgeIdentifier:@"OK+SWM"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"sync_swm.icns"] label:nil forBadgeIdentifier:@"SYNC+SWM"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"sync_swm.icns"] label:nil forBadgeIdentifier:@"NEW+SWM"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"warning_swm.icns"] label:nil forBadgeIdentifier:@"IGNORE+SWM"];
+ [syncController setBadgeImage:[extBundle imageForResource:@"error_swm.icns"] label:nil forBadgeIdentifier:@"ERROR+SWM"];
+
+ // The Mach post name needs to be prefixed with the code signing Team ID
+ // https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
+ NSString *serverName = [[teamIdentifierPrefix stringByAppendingString:[extBundle bundleIdentifier]]
+ stringByReplacingOccurrencesOfString:@".FinderSyncExt" withString:@".socketApi"];
+
+ _syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
+ _registeredDirectories = [[NSMutableSet alloc] init];
+ _requestedUrls = [[NSMutableSet alloc] init];
+ _shareMenuTitle = nil;
+
+ [_syncClientProxy start];
+ return self;
+}
+
+#pragma mark - Primary Finder Sync protocol methods
+
+- (void)endObservingDirectoryAtURL:(NSURL *)url
+{
+ // The user is no longer seeing the container's contents.
+ // At this point we know that the status of any file as a direct child of url.filePathURL
+ // won't be displayed. Filter our _requestedUrls to get rid of them.
+ NSString *observedDirectoryPath = [url.filePathURL path];
+ [_requestedUrls filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
+ NSURL *requestedUrl = (NSURL *)evaluatedObject;
+ NSString *parentDir = [[requestedUrl path] stringByDeletingLastPathComponent];
+ return [parentDir isEqualToString:observedDirectoryPath];
+ }]];
+}
+
+- (void)requestBadgeIdentifierForURL:(NSURL *)url
+{
+ [_requestedUrls addObject:url.filePathURL];
+
+ BOOL isDir;
+ if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory: &isDir] == NO) {
+ NSLog(@"ERROR: Could not determine file type of %@", [url path]);
+ isDir = NO;
+ }
+
+ NSString* normalizedPath = [[url path] decomposedStringWithCanonicalMapping];
+ [_syncClientProxy askForIcon:normalizedPath isDirectory:isDir];
+}
+
+#pragma mark - Menu and toolbar item support
+
+- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu
+{
+ if (_shareMenuTitle) {
+ NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
+ [menu addItemWithTitle:_shareMenuTitle action:@selector(shareMenuAction:) keyEquivalent:@"title"];
+
+ return menu;
+ }
+ return nil;
+}
+
+- (IBAction)shareMenuAction:(id)sender
+{
+ NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
+
+ [items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
+ NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
+ [_syncClientProxy askOnSocket:normalizedPath query:@"SHARE"];
+ }];
+}
+
+#pragma mark - SyncClientProxyDelegate implementation
+
+- (void)setResultForPath:(NSString*)path result:(NSString*)result
+{
+ NSString *normalizedPath = [path decomposedStringWithCanonicalMapping];
+ [[FIFinderSyncController defaultController] setBadgeIdentifier:result forURL:[NSURL fileURLWithPath:normalizedPath]];
+}
+
+- (void)reFetchFileNameCacheForPath:(NSString*)path
+{
+ // This shouldn't be necessary, and will be a problem when we
+ // filter values of _requestedUrls even though Finder might still
+ // have an old status in its cache (and therefore won't re-request it)
+ // but will do OK until we get the socket API to re-push the status of everything needed.
+ [_requestedUrls enumerateObjectsUsingBlock: ^(id url, BOOL *stop) {
+ if ([[url path] hasPrefix:path])
+ [self requestBadgeIdentifierForURL: url];
+ }];
+}
+
+- (void)registerPath:(NSString*)path
+{
+ assert(_registeredDirectories);
+ [_registeredDirectories addObject:[NSURL fileURLWithPath:path]];
+ [FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
+}
+
+- (void)unregisterPath:(NSString*)path
+{
+ [_registeredDirectories removeObject:[NSURL fileURLWithPath:path]];
+ [FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
+}
+
+- (void)setShareMenuTitle:(NSString*)title
+{
+ _shareMenuTitle = title;
+}
+
+- (void)loadIconResourcePath:(NSString*)path
+{
+#pragma unused(path)
+}
+
+- (void)connectionDidDie
+{
+ _shareMenuTitle = nil;
+
+ // This will tell Finder that this extension isn't attached to any directory
+ // until we can reconnect to the sync client.
+ [_registeredDirectories removeAllObjects];
+ [FIFinderSyncController defaultController].directoryURLs = nil;
+}
+
+@end
+
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSyncExt.entitlements b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSyncExt.entitlements
new file mode 100644
index 000000000..20605791a
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSyncExt.entitlements
@@ -0,0 +1,12 @@
+<?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.security.app-sandbox</key>
+ <true/>
+ <key>com.apple.security.application-groups</key>
+ <array>
+ <string>$(TeamIdentifierPrefix)$(OC_APPLICATION_REV_DOMAIN)</string>
+ </array>
+</dict>
+</plist>
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist
new file mode 100644
index 000000000..36fe63e7c
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/Info.plist
@@ -0,0 +1,43 @@
+<?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>TeamIdentifierPrefix</key>
+ <string>$(TeamIdentifierPrefix)</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>$(OC_APPLICATION_NAME) Extensions</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME:rfc1034identifier)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>XPC!</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+ <key>LSUIElement</key>
+ <true/>
+ <key>NSExtension</key>
+ <dict>
+ <key>NSExtensionAttributes</key>
+ <dict/>
+ <key>NSExtensionPointIdentifier</key>
+ <string>com.apple.FinderSync</string>
+ <key>NSExtensionPrincipalClass</key>
+ <string>FinderSync</string>
+ </dict>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>