diff --git a/OpenRA.Launcher.Mac/Controller.h b/OpenRA.Launcher.Mac/Controller.h index d16ba4bcff..c0084d50c3 100644 --- a/OpenRA.Launcher.Mac/Controller.h +++ b/OpenRA.Launcher.Mac/Controller.h @@ -26,5 +26,5 @@ - (void)populateModInfo; - (SidebarEntry *)sidebarModsTree; - (SidebarEntry *)sidebarOtherTree; - +- (BOOL)downloadUrl:(NSString *)url intoCache:(NSString *)filename withId:(NSString *)key; @end diff --git a/OpenRA.Launcher.Mac/Controller.m b/OpenRA.Launcher.Mac/Controller.m index be31fcda18..bb4c8f579c 100644 --- a/OpenRA.Launcher.Mac/Controller.m +++ b/OpenRA.Launcher.Mac/Controller.m @@ -90,6 +90,12 @@ [game launchMod:mod]; } +- (BOOL)downloadUrl:(NSString *)url intoCache:(NSString *)filename withId:(NSString *)key +{ + id path = [[@"~/Library/Application Support/OpenRA/Downloads/" stringByAppendingPathComponent:filename] stringByExpandingTildeInPath]; + return [game downloadUrl:url toPath:path withId:key]; +} + #pragma mark Sidebar Datasource and Delegate - (int)outlineView:(NSOutlineView *)anOutlineView numberOfChildrenOfItem:(id)item { diff --git a/OpenRA.Launcher.Mac/GameInstall.h b/OpenRA.Launcher.Mac/GameInstall.h index be32a7d3b1..508dc411d9 100644 --- a/OpenRA.Launcher.Mac/GameInstall.h +++ b/OpenRA.Launcher.Mac/GameInstall.h @@ -11,13 +11,14 @@ @class Mod; @interface GameInstall : NSObject { NSURL *gameURL; + NSMutableDictionary *downloadTasks; } @property(readonly) NSURL *gameURL; -(id)initWithURL:(NSURL *)path; -(void)launchMod:(NSString *)mod; - (NSString *)runUtilityQuery:(NSString *)arg; -- (void)runUtilityQuery:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel; - (NSArray *)installedMods; - (NSDictionary *)infoForMods:(NSArray *)mods; +- (BOOL)downloadUrl:(NSString *)url toPath:(NSString *)filename withId:(NSString *)key; @end diff --git a/OpenRA.Launcher.Mac/GameInstall.m b/OpenRA.Launcher.Mac/GameInstall.m index 19cf8bfe17..7ca65e5fbf 100644 --- a/OpenRA.Launcher.Mac/GameInstall.m +++ b/OpenRA.Launcher.Mac/GameInstall.m @@ -18,6 +18,7 @@ if (self != nil) { gameURL = [url retain]; + downloadTasks = [[NSMutableDictionary alloc] init]; } return self; } @@ -25,6 +26,7 @@ - (void)dealloc { [gameURL release]; gameURL = nil; + [downloadTasks release]; downloadTasks = nil; [super dealloc]; } @@ -142,26 +144,71 @@ } -- (void)runUtilityQuery:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel +- (BOOL)downloadUrl:(NSString *)url toPath:(NSString *)filename withId:(NSString *)key { - NSTask *aTask = [[NSTask alloc] init]; - NSPipe *aPipe = [NSPipe pipe]; - NSFileHandle *readHandle = [aPipe fileHandleForReading]; + NSLog(@"Starting download..."); + if ([downloadTasks objectForKey:key] != nil) + { + NSLog(@"Error: a download is already in progress for %@",key); + return NO; + } + + NSTask *task = [[[NSTask alloc] init] autorelease]; + NSPipe *pipe = [NSPipe pipe]; NSMutableArray *taskArgs = [NSMutableArray arrayWithObject:@"OpenRA.Utility.exe"]; + NSString *arg = [NSString stringWithFormat:@"--download-url=%@,%@",url,filename]; [taskArgs addObject:arg]; - [aTask setCurrentDirectoryPath:[gameURL absoluteString]]; - [aTask setLaunchPath:@"/Library/Frameworks/Mono.framework/Commands/mono"]; - [aTask setArguments:taskArgs]; - [aTask setStandardOutput:aPipe]; - [aTask launch]; + [task setCurrentDirectoryPath:[gameURL absoluteString]]; + [task setLaunchPath:@"/Library/Frameworks/Mono.framework/Commands/mono"]; + [task setArguments:taskArgs]; + [task setStandardOutput:pipe]; - NSData *inData = nil; - while ((inData = [readHandle availableData]) && [inData length]) - [obj performSelector:sel withObject:[NSString stringWithUTF8String:[inData bytes]]]; - [aTask waitUntilExit]; - [aTask release]; + NSFileHandle *readHandle = [pipe fileHandleForReading]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(utilityResponded:) + name:NSFileHandleReadCompletionNotification + object:readHandle]; + [nc addObserver:self + selector:@selector(utilityTerminated:) + name:NSTaskDidTerminateNotification + object:task]; + [task launch]; + [readHandle readInBackgroundAndNotify]; + + [downloadTasks setObject:task forKey:key]; + return YES; } +- (void)utilityResponded:(NSNotification *)n +{ + NSData *data = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem]; + NSString *response = [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]; + NSLog(@"r: %@",response); + + // Keep reading + if ([n object] != nil) + [[n object] readInBackgroundAndNotify]; +} + +- (void)utilityTerminated:(NSNotification *)n +{ + id task = [n object]; + id pipe = [task standardOutput]; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self name:NSFileHandleReadCompletionNotification object:[pipe fileHandleForReading]]; + [nc removeObserver:self name:NSTaskDidTerminateNotification object:task]; +} + +- (void)cancelDownload:(NSString *)key +{ + id task = [downloadTasks objectForKey:key]; + if (task == nil) + return; + + [task interrupt]; +} @end diff --git a/OpenRA.Launcher.Mac/JSBridge.m b/OpenRA.Launcher.Mac/JSBridge.m index ebc9760c2c..f5f1f36bc5 100644 --- a/OpenRA.Launcher.Mac/JSBridge.m +++ b/OpenRA.Launcher.Mac/JSBridge.m @@ -40,7 +40,9 @@ static JSBridge *SharedInstance; methods = [[NSDictionary dictionaryWithObjectsAndKeys: @"launchMod", NSStringFromSelector(@selector(launchMod:)), @"log", NSStringFromSelector(@selector(log:)), + @"installCncPackagesFromWeb", NSStringFromSelector(@selector(installCncPackagesFromWeb)), @"fileExistsInMod", NSStringFromSelector(@selector(fileExists:inMod:)), + @"downloadFileToCache",NSStringFromSelector(@selector(downloadFile:intoCacheWithName:id:)), nil] retain]; } return self; @@ -87,6 +89,13 @@ static JSBridge *SharedInstance; return YES; } +- (void)downloadFile:(NSString *)url intoCacheWithName:(NSString *)name id:(NSString *)did +{ + NSLog(@"downloadFile:%@ intoCacheWithName:%@ id:%@",url,name,did); + // Disallow traversing directories; take only the last component + [controller downloadUrl:url intoCache:[name lastPathComponent] withId:did]; +} + - (void)log:(NSString *)message { NSLog(@"js: %@",message); diff --git a/mods/cnc/mod.html b/mods/cnc/mod.html index 2e62d39527..35586081ac 100644 --- a/mods/cnc/mod.html +++ b/mods/cnc/mod.html @@ -78,7 +78,8 @@ .button:hover { - background-color: #333; + border-color:#fff; + background-color:#650b03; cursor:pointer; } @@ -107,7 +108,8 @@ function installFromWeb() { - window.external.log("installFromWeb()"); + window.external.downloadFileToCache("http://www.open-ra.org/get-dependency.php?file=cnc-packages","test.zip","cnc-packages"); + //window.external.installCncPackagesFromWeb(); } function onLoad()