diff --git a/OpenRA.Launcher.Mac/Controller.h b/OpenRA.Launcher.Mac/Controller.h index 82d902e4d4..62c135e9f4 100644 --- a/OpenRA.Launcher.Mac/Controller.h +++ b/OpenRA.Launcher.Mac/Controller.h @@ -18,6 +18,7 @@ SidebarEntry *sidebarItems; GameInstall *game; NSDictionary *allMods; + NSMutableArray *httpRequests; NSMutableDictionary *downloads; BOOL hasMono; @@ -33,6 +34,7 @@ - (SidebarEntry *)sidebarModsTree; - (SidebarEntry *)sidebarOtherTree; +- (void)fetchURL:(NSString *)url withCallback:(NSString *)cb; - (BOOL)registerDownload:(NSString *)key withURL:(NSString *)url filePath:(NSString *)path; - (Download *)downloadWithKey:(NSString *)key; - (BOOL)hasSupportedMono; diff --git a/OpenRA.Launcher.Mac/Controller.m b/OpenRA.Launcher.Mac/Controller.m index a9eb226bb8..4eb831ccea 100644 --- a/OpenRA.Launcher.Mac/Controller.m +++ b/OpenRA.Launcher.Mac/Controller.m @@ -13,6 +13,7 @@ #import "ImageAndTextCell.h" #import "JSBridge.h" #import "Download.h" +#import "HttpRequest.h" @implementation Controller @synthesize allMods; @@ -32,6 +33,7 @@ game = [[GameInstall alloc] initWithPath:gamePath]; [[JSBridge sharedInstance] setController:self]; downloads = [[NSMutableDictionary alloc] init]; + httpRequests = [[NSMutableArray alloc] init]; hasMono = [self hasSupportedMono]; if (hasMono) { @@ -120,6 +122,7 @@ { [sidebarItems release]; sidebarItems = nil; [downloads release]; downloads = nil; + [httpRequests release]; httpRequests = nil; [super dealloc]; } @@ -176,6 +179,17 @@ return [downloads objectForKey:key]; } +- (void)fetchURL:(NSString *)url withCallback:(NSString *)cb +{ + // Clean up any completed requests + for (int i = [httpRequests count] - 1; i >= 0; i--) + if ([[httpRequests objectAtIndex:i] terminated]) + [httpRequests removeObjectAtIndex:i]; + + // Create request + [httpRequests addObject:[HttpRequest requestWithURL:url callback:cb game:game]]; +} + #pragma mark Sidebar Datasource and Delegate - (NSInteger)outlineView:(NSOutlineView *)anOutlineView numberOfChildrenOfItem:(id)item { @@ -245,6 +259,10 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn #pragma mark WebView delegates - (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame { + // Cancel any in progress http requests + for (HttpRequest *r in httpRequests) + [r cancel]; + [windowObject setValue:[JSBridge sharedInstance] forKey:@"external"]; } diff --git a/OpenRA.Launcher.Mac/Download.m b/OpenRA.Launcher.Mac/Download.m index 304c6f7737..0c90fe3e8c 100644 --- a/OpenRA.Launcher.Mac/Download.m +++ b/OpenRA.Launcher.Mac/Download.m @@ -69,7 +69,7 @@ [[NSFileManager defaultManager] removeItemAtPath:filename error:NULL]; bytesCompleted = bytesTotal = -1; - [[JSBridge sharedInstance] notifyDownloadProgress:self]; + [[JSBridge sharedInstance] runCallback:@"downloadProgressed" withArgument:[self key]]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadCompletionNotification object:[[task standardOutput] fileHandleForReading]]; @@ -120,7 +120,7 @@ } } } - [[JSBridge sharedInstance] notifyDownloadProgress:self]; + [[JSBridge sharedInstance] runCallback:@"downloadProgressed" withArgument:[self key]]; // Keep reading if ([n object] != nil) @@ -171,8 +171,8 @@ } } } - [[JSBridge sharedInstance] notifyExtractProgress:self]; - + [[JSBridge sharedInstance] runCallback:@"extractProgressed" withArgument:[self key]]; + // Keep reading if ([n object] != nil) [[n object] readInBackgroundAndNotify]; diff --git a/OpenRA.Launcher.Mac/JSBridge.h b/OpenRA.Launcher.Mac/JSBridge.h index dfa82e0836..ec31f26bb3 100644 --- a/OpenRA.Launcher.Mac/JSBridge.h +++ b/OpenRA.Launcher.Mac/JSBridge.h @@ -19,6 +19,5 @@ + (JSBridge *)sharedInstance; - (void)setController:(Controller *)aController; -- (void)notifyDownloadProgress:(Download *)download; -- (void)notifyExtractProgress:(Download *)download; +- (void)runCallback:(NSString *)cb withArgument:(NSString *)arg; @end diff --git a/OpenRA.Launcher.Mac/JSBridge.m b/OpenRA.Launcher.Mac/JSBridge.m index 53c9b79be3..09fa40ed38 100644 --- a/OpenRA.Launcher.Mac/JSBridge.m +++ b/OpenRA.Launcher.Mac/JSBridge.m @@ -44,7 +44,7 @@ static JSBridge *SharedInstance; @"log", NSStringFromSelector(@selector(log:)), @"existsInMod", NSStringFromSelector(@selector(fileExists:inMod:)), @"metadata", NSStringFromSelector(@selector(metadata:forMod:)), - @"httpRequest", NSStringFromSelector(@selector(httpRequest:)), + @"httpRequest", NSStringFromSelector(@selector(httpRequest:withCallback:)), // File downloading @"registerDownload", NSStringFromSelector(@selector(registerDownload:withURL:filename:)), @@ -71,6 +71,13 @@ static JSBridge *SharedInstance; [super dealloc]; } +- (void)runCallback:(NSString *)cb withArgument:(NSString *)arg +{ + NSString *cmd = [NSString stringWithFormat:@"%@('%@')", cb, + [arg stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]]; + [[[controller webView] windowScriptObject] evaluateWebScript:cmd]; +} + #pragma mark JS API methods - (BOOL)launchMod:(NSString *)aMod @@ -155,18 +162,6 @@ static JSBridge *SharedInstance; return (d == nil) ? -1 : [d bytesTotal]; } -- (void)notifyDownloadProgress:(Download *)download -{ - [[[controller webView] windowScriptObject] evaluateWebScript: - [NSString stringWithFormat:@"downloadProgressed('%@')",[download key]]]; -} - -- (void)notifyExtractProgress:(Download *)download -{ - [[[controller webView] windowScriptObject] evaluateWebScript: - [NSString stringWithFormat:@"extractProgressed('%@')",[download key]]]; -} - - (BOOL)extractDownload:(NSString *)key toPath:(NSString *)aFile inMod:(NSString *)aMod { Download *d = [controller downloadWithKey:key]; @@ -233,12 +228,9 @@ static JSBridge *SharedInstance; return @""; } -- (NSString *)httpRequest:(NSString *)url +- (void)httpRequest:(NSString *)url withCallback:(NSString *)cb { - NSLog(@"Requesting url %@",url); - NSString *response = [NSString stringWithContentsOfURL:[NSURL URLWithString:url] encoding:NSASCIIStringEncoding error:NULL]; - NSLog(@"Response %@",response); - return response; + [controller fetchURL:url withCallback:cb]; } @end diff --git a/OpenRA.Launcher.Mac/OpenRA.xcodeproj/project.pbxproj b/OpenRA.Launcher.Mac/OpenRA.xcodeproj/project.pbxproj index 1df2076db4..5e6ff11485 100644 --- a/OpenRA.Launcher.Mac/OpenRA.xcodeproj/project.pbxproj +++ b/OpenRA.Launcher.Mac/OpenRA.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ DA81FC3F12911E2B00C48F2F /* GameInstall.m in Sources */ = {isa = PBXBuildFile; fileRef = DA81FC3E12911E2B00C48F2F /* GameInstall.m */; }; DA9295A712921DF900EDB02E /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9295A612921DF900EDB02E /* WebKit.framework */; }; DA9296901292328200EDB02E /* SidebarEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = DA92968F1292328200EDB02E /* SidebarEntry.m */; }; + DAA3F31C12CBF60D00E214BF /* HttpRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA3F31B12CBF60D00E214BF /* HttpRequest.m */; }; DAB887F5129E5D6C00C99407 /* SDL in Resources */ = {isa = PBXBuildFile; fileRef = DAB887EE129E5D6100C99407 /* SDL */; }; /* End PBXBuildFile section */ @@ -49,6 +50,8 @@ DA9295A612921DF900EDB02E /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; DA92968E1292328200EDB02E /* SidebarEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SidebarEntry.h; sourceTree = ""; }; DA92968F1292328200EDB02E /* SidebarEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SidebarEntry.m; sourceTree = ""; }; + DAA3F31A12CBF60D00E214BF /* HttpRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpRequest.h; sourceTree = ""; }; + DAA3F31B12CBF60D00E214BF /* HttpRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpRequest.m; sourceTree = ""; }; DAB887EE129E5D6100C99407 /* SDL */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = SDL; sourceTree = ""; }; /* End PBXFileReference section */ @@ -80,8 +83,10 @@ DA7D85661295E92900E58547 /* Download.m */, DA92968E1292328200EDB02E /* SidebarEntry.h */, DA92968F1292328200EDB02E /* SidebarEntry.m */, - DA38212012925344003B0BB5 /* JSBridge.h */, DA38212112925344003B0BB5 /* JSBridge.m */, + DA38212012925344003B0BB5 /* JSBridge.h */, + DAA3F31A12CBF60D00E214BF /* HttpRequest.h */, + DAA3F31B12CBF60D00E214BF /* HttpRequest.m */, ); name = Classes; sourceTree = ""; @@ -229,6 +234,7 @@ DA9296901292328200EDB02E /* SidebarEntry.m in Sources */, DA38212212925344003B0BB5 /* JSBridge.m in Sources */, DA7D85671295E92900E58547 /* Download.m in Sources */, + DAA3F31C12CBF60D00E214BF /* HttpRequest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/MacOS/OpenRA b/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/MacOS/OpenRA index f22171139b..0a8ad609c0 100755 Binary files a/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/MacOS/OpenRA and b/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/MacOS/OpenRA differ diff --git a/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/Resources/English.lproj/MainMenu.nib b/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/Resources/English.lproj/MainMenu.nib index ee744dd90a..b2340f1712 100644 Binary files a/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/Resources/English.lproj/MainMenu.nib and b/OpenRA.Launcher.Mac/build/Release/OpenRA.app/Contents/Resources/English.lproj/MainMenu.nib differ diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index 191dbdd872..a1247bae9c 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -85,29 +85,48 @@ namespace OpenRA.Utility public static void DownloadUrl(string argValue) { string[] args = argValue.Split(','); + string url = args[0]; + WebClient wc = new WebClient(); + + if (args.Length == 1) + { + wc.DownloadStringCompleted += DownloadStringCompleted; + + wc.DownloadStringAsync(new Uri(url)); + } + else if (args.Length == 2) + { + string path = args[1].Replace("~",Environment.GetFolderPath(Environment.SpecialFolder.Personal)); + + wc.DownloadProgressChanged += DownloadProgressChanged; + wc.DownloadFileCompleted += DownloadFileCompleted; + + Console.WriteLine("Downloading {0} to {1}", url, path); + Console.WriteLine("Status: Initializing"); - if (args.Length != 2) + wc.DownloadFileAsync(new Uri(url), path); + } + else { Console.WriteLine("Error: invalid syntax"); return; } - string url = args[0]; - string path = args[1].Replace("~",Environment.GetFolderPath(Environment.SpecialFolder.Personal)); - WebClient wc = new WebClient(); - wc.DownloadProgressChanged += DownloadProgressChanged; - wc.DownloadFileCompleted += DownloadFileCompleted; - - Console.WriteLine("Downloading {0} to {1}", url, path); - Console.WriteLine("Status: Initializing"); - - wc.DownloadFileAsync(new Uri(url), path); while (!completed) Thread.Sleep(500); } static bool completed = false; + static void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) + { + if (e.Error != null) + Console.WriteLine("Error: {0}", e.Error.Message); + else + Console.WriteLine(e.Result); + completed = true; + } + static void DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { if (e.Error != null) diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs index c3e00f72ba..ccaf377137 100644 --- a/OpenRA.Utility/Program.cs +++ b/OpenRA.Utility/Program.cs @@ -81,7 +81,7 @@ namespace OpenRA.Utility Console.WriteLine(); Console.WriteLine(" -l,--list-mods List currently installed mods"); Console.WriteLine(" -i=MODS,--mod-info=MODS List metadata for MODS (comma separated list of mods)"); - Console.WriteLine(" --download-url=URL,DEST Download a file from URL to DEST"); + Console.WriteLine(" --download-url=URL,DEST Download a file from URL to DEST (omit DEST to print to stdout)"); Console.WriteLine(" --extract-zip=ZIPFILE,PATH Extract the zip ZIPFILE to DEST (relative to openra dir)"); Console.WriteLine(" --install-ra-packages=PATH Install required packages for RA from CD to PATH"); Console.WriteLine(" --install-cnc-packages=PATH Install required packages for C&C from CD to PATH"); diff --git a/mods/cnc/mod.html b/mods/cnc/mod.html index fa15f5cd70..56673dba62 100644 --- a/mods/cnc/mod.html +++ b/mods/cnc/mod.html @@ -123,15 +123,23 @@ window.external.extractDownload("cnc-packages","packages","cnc"); } + function versionCallback(version) + { + document.getElementById("latestversion").innerHTML = version; + } + + function motdCallback(motd) + { + document.getElementById("motd").innerHTML = motd; + } + function onLoad() { refreshSections(); var version = window.external.metadata("VERSION", "cnc"); document.getElementById("installedversion").innerHTML = version; - document.getElementById("latestversion").innerHTML = window.external.httpRequest("http://master.open-ra.org/VERSION"); - var motd = window.external.httpRequest("http://master.open-ra.org/motd.php?v="+version); - if (motd != undefined) - document.getElementById("motd").innerHTML = motd.substring(3); + window.external.httpRequest("http://master.open-ra.org/VERSION", "versionCallback"); + window.external.httpRequest("http://master.open-ra.org/motd.php?v="+version, "motdCallback"); } function refreshSections() @@ -223,7 +231,7 @@
-

Latest version: Unknown

+

Latest version: Checking...