From 30326d633e1c098e43e40ea6a0f494e1f890e208 Mon Sep 17 00:00:00 2001 From: michael starke Date: Thu, 18 Dec 2014 11:34:48 +0100 Subject: [PATCH] Added FileWatcher based on DTFileMontior from Cocoanetics --- MacPass.xcodeproj/project.pbxproj | 6 +++ MacPass/MPDocument.m | 1 + MacPass/MPFileWatcher.h | 25 +++++++++ MacPass/MPFileWatcher.m | 86 +++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 MacPass/MPFileWatcher.h create mode 100644 MacPass/MPFileWatcher.m diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 0f939a75..e77bb333 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -214,6 +214,7 @@ 4C888C9316EB6F5E003D34A1 /* MPToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C888C9216EB6F5E003D34A1 /* MPToolbarItem.m */; }; 4C888C9716EB754B003D34A1 /* MPActionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C888C9616EB754B003D34A1 /* MPActionHelper.m */; }; 4C88C66918D9F8D600F43852 /* MPTemporaryFileStorageCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C88C66818D9F8D600F43852 /* MPTemporaryFileStorageCenter.m */; }; + 4C8913661A422C8C0071A4CB /* MPFileWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C8913651A422C8C0071A4CB /* MPFileWatcher.m */; }; 4C89B71019B4B4A300DC0A6A /* MPTreeDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C89B70F19B4B4A300DC0A6A /* MPTreeDelegate.m */; }; 4C89F521182F9FDD0069C73C /* NSString+Commands.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C89F520182F9FDD0069C73C /* NSString+Commands.m */; }; 4C89F524182FB4740069C73C /* MPAutotypeCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C89F523182FB4740069C73C /* MPAutotypeCommand.m */; }; @@ -771,6 +772,8 @@ 4C888C9616EB754B003D34A1 /* MPActionHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPActionHelper.m; sourceTree = ""; }; 4C88C66718D9F8D600F43852 /* MPTemporaryFileStorageCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTemporaryFileStorageCenter.h; sourceTree = ""; }; 4C88C66818D9F8D600F43852 /* MPTemporaryFileStorageCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTemporaryFileStorageCenter.m; sourceTree = ""; }; + 4C8913641A422C8C0071A4CB /* MPFileWatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPFileWatcher.h; sourceTree = ""; }; + 4C8913651A422C8C0071A4CB /* MPFileWatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPFileWatcher.m; sourceTree = ""; }; 4C89B70E19B4B4A300DC0A6A /* MPTreeDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTreeDelegate.h; sourceTree = ""; }; 4C89B70F19B4B4A300DC0A6A /* MPTreeDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTreeDelegate.m; sourceTree = ""; }; 4C89F51F182F9FDD0069C73C /* NSString+Commands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Commands.h"; sourceTree = ""; }; @@ -1353,6 +1356,8 @@ 4C4B728418E4B9B400A1A5D5 /* MPDockTileHelper.m */, 4CB63A6018986530002DEC4C /* MPFlagsHelper.h */, 4C978E0C19AE54AB003067DF /* MPFlagsHelper.m */, + 4C8913641A422C8C0071A4CB /* MPFileWatcher.h */, + 4C8913651A422C8C0071A4CB /* MPFileWatcher.m */, ); name = Helper; sourceTree = ""; @@ -2398,6 +2403,7 @@ 4CC3AABD175F4983003EF01B /* HNHRoundedTextFieldCell.m in Sources */, 4C9D6AA917615199001C660C /* HNHRoundedSecureTextFieldCell.m in Sources */, 4C4A100F176286FD00BBF2CA /* MPTableView.m in Sources */, + 4C8913661A422C8C0071A4CB /* MPFileWatcher.m in Sources */, 4CAF62FC1763604000CD7084 /* HNHBadgedTextFieldCell.m in Sources */, 4CA334CA18AD60D1008A3322 /* MPWindowAssociationsTableViewDelegate.m in Sources */, 4C58BD4F176370B100B8178C /* HNHBadgedTextField.m in Sources */, diff --git a/MacPass/MPDocument.m b/MacPass/MPDocument.m index 167dd811..aaff2334 100644 --- a/MacPass/MPDocument.m +++ b/MacPass/MPDocument.m @@ -784,6 +784,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey # pragma mark File Watching - (void) _watchForFileChanges:(BOOL)watch { + } @end diff --git a/MacPass/MPFileWatcher.h b/MacPass/MPFileWatcher.h new file mode 100644 index 00000000..199e63e5 --- /dev/null +++ b/MacPass/MPFileWatcher.h @@ -0,0 +1,25 @@ +// +// MPFileWatcher.h +// MacPass +// +// Created by Michael Starke on 17/12/14. +// Copyright (c) 2014 HicknHack Software GmbH. All rights reserved. +// + +#import + +@class MPFileWatcher; +typedef void (^MPFileWatcherBlock)(void); +/* TODO: Cocoanetics DTFileMonitor */ +@interface MPFileWatcher : NSObject + +@property (copy, readonly) NSURL *URL; + ++ (instancetype)fileWatcherWithURL:(NSURL *)url changeBlock:(MPFileWatcherBlock)block; + +- (instancetype)initWithURL:(NSURL *)url changeBlock:(MPFileWatcherBlock)block; + +- (void)startMonitoring; +- (void)stopMonitoring; + +@end diff --git a/MacPass/MPFileWatcher.m b/MacPass/MPFileWatcher.m new file mode 100644 index 00000000..80288fd6 --- /dev/null +++ b/MacPass/MPFileWatcher.m @@ -0,0 +1,86 @@ +// +// MPFileWatcher.m +// MacPass +// +// Created by Michael Starke on 17/12/14. +// Copyright (c) 2014 HicknHack Software GmbH. All rights reserved. +// + +#import "MPFileWatcher.h" + +@interface MPFileWatcher () + +@property (copy) NSURL *URL; +@property (copy) MPFileWatcherBlock block; +@property (assign) int fileDescriptor; +@property (strong) dispatch_queue_t queue; +@property (strong) dispatch_source_t source; + +@end + +@implementation MPFileWatcher + ++ (instancetype)fileWatcherWithURL:(NSURL *)url changeBlock:(MPFileWatcherBlock)block { + return [[MPFileWatcher alloc] initWithURL:url changeBlock:block]; +} + +- (instancetype)initWithURL:(NSURL *)url changeBlock:(MPFileWatcherBlock)block { + NSAssert([url isFileURL], @"URL needs to be a valid file URL"); + self = [super init]; + if(self) { + _block = [block copy]; + _URL = [url copy]; + _queue = dispatch_queue_create("MPFileMonitor Queue", 0); + } + return self; +} + +- (void)startMonitoring +{ + @synchronized(self) { + if(self.source) { + return; + } + + self.fileDescriptor = open([self.URL.path fileSystemRepresentation], O_EVTONLY); + + if(!self.fileDescriptor) { + return; + } + + // watch the file descriptor for writes + self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, self.fileDescriptor, DISPATCH_VNODE_WRITE, self.queue); + + // call the passed block if the source is modified + + /* dispatch_source_set_event_handler(source, ^{ + unsigned long flags = dispatch_source_get_data(source); + if(flags & DISPATCH_VNODE_DELETE) { + dispatch_source_cancel(source); + [blockSelf watchFileAtURL:url]; + } + }); */ + + dispatch_source_set_event_handler(self.source, self.block); + + // close the file descriptor when the dispatch source is cancelled + dispatch_source_set_cancel_handler(self.source, ^{ + + close(self.fileDescriptor); + }); + + // at this point the dispatch source is paused, so start watching + dispatch_resume(self.source); + } +} + +- (void)stopMonitoring { + @synchronized(self) { + if(!self.source) { + return; + } + dispatch_source_cancel(self.source); + self.source = nil; + } +} +@end