Source

NPAPI-chrome-file-api / Mac / FileWatcherTask.mm

Full commit
 //
//  FileWatcherTask.m
//  FireBreath
//
//  Created by Ryan Ackley on 5/18/12.
//  Copyright (c) 2012 Benryan Software Inc. All rights reserved.
//

#import "FileWatcherTask.h"
#include "variant_list.h"

void fsevents_callback(ConstFSEventStreamRef streamRef,
                       void *userData,
                       size_t numEvents,
                       void *eventPaths,
                       const FSEventStreamEventFlags eventFlags[],
                       const FSEventStreamEventId eventIds[])
{
    FileWatcherTask *fw = (FileWatcherTask *)userData;
	size_t i;
	for(i=0; i<numEvents; i++){
        [fw postCallback:[(NSArray *)eventPaths objectAtIndex:i]];
	}
    
}

@implementation FileWatcherTask

-(id)initWithCallback:(FB::JSObjectPtr)obj
{
    self = [super init];
    callback = obj;
    fm = [NSFileManager defaultManager];
    return self;
    
}

-(void)listenForFileEvents:(NSString*)path
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSArray *pathsToWatch = [NSArray arrayWithObject:path];
    appStartedTimestamp = [NSDate date];
    
    void *appPointer = (void *)self;
    FSEventStreamContext context = {0, appPointer, NULL, NULL, NULL};
    NSTimeInterval latency = 1.0;
    stream = FSEventStreamCreate(NULL,
                                 &fsevents_callback,
                                 &context,
                                 (CFArrayRef) pathsToWatch,
                                 kFSEventStreamEventIdSinceNow, 
                                 (CFAbsoluteTime) latency,
                                 kFSEventStreamCreateFlagUseCFTypes
                                 );
    runLoop = CFRunLoopGetCurrent();
    FSEventStreamScheduleWithRunLoop(stream, runLoop, kCFRunLoopDefaultMode);
	FSEventStreamStart(stream);
    CFRunLoopRun();
    [pool release];
}

-(void)postCallback:(NSString*)path
{
    
    NSArray *contents = [fm directoryContentsAtPath:path];
    NSString* fullPath = nil;
    
    for(NSString* node in contents) 
    {
        fullPath = [NSString stringWithFormat:@"%@%@",path,node];
        
        NSDictionary *fileAttributes = [fm attributesOfItemAtPath:fullPath error:NULL];
        NSDate *fileModDate =
        [fileAttributes objectForKey:NSFileModificationDate];
        if([fileModDate compare:[self lastModificationDateForPath:path]] == NSOrderedDescending) 
        {
            std::string stdPath = [fullPath UTF8String];
            callback->Invoke("",FB::variant_list_of(stdPath));
        }
    }
    [self updateLastModificationDateForPath:path];
}

- (void)updateLastModificationDateForPath: (NSString *)path
{
	[pathModificationDates setObject:[NSDate date] forKey:path];
}

- (void)stopWatching
{
    CFRunLoopStop(runLoop);
}

- (NSDate *)lastModificationDateForPath: (NSString *)path
{
	if(nil != [pathModificationDates valueForKey:path]) {
		return [pathModificationDates valueForKey:path];
	}
	else{
		return appStartedTimestamp;
	}
}

@end