Merge pull request #16046 from huffman/feat/mac-launcher-tags

DEV-316: Add build tags to Mac launcher
This commit is contained in:
Shannon Romano 2019-08-23 13:41:52 -07:00 committed by GitHub
commit 264abe7d0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 150 additions and 74 deletions

View file

@ -22,7 +22,10 @@
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
CGFloat prog = (float)totalBytesWritten/totalBytesExpectedToWrite;
NSLog(@"interface downloaded %d%%", (int)(100.0*prog));
if ((int)(100.0 * prog) != (int)self.progressPercentage) {
NSLog(@"interface downloaded %d%%", (int)(100.0*prog));
}
self.progressPercentage = (100.0 * prog);
[[Launcher sharedLauncher] updateProgressIndicator];

View file

@ -1,31 +1,20 @@
#import "LatestBuildRequest.h"
#import "Launcher.h"
#import "Settings.h"
#import "Interface.h"
@implementation LatestBuildRequest
- (NSInteger) getCurrentVersion {
NSInteger currentVersion;
@try {
NSString* interfaceAppPath = [[Launcher.sharedLauncher getAppPath] stringByAppendingString:@"interface.app"];
NSError* error = nil;
Interface* interface = [[Interface alloc] initWith:interfaceAppPath];
currentVersion = [interface getVersion:&error];
if (currentVersion == 0 && error != nil) {
NSLog(@"can't get version from interface, falling back to settings: %@", error);
currentVersion = [Settings.sharedSettings latestBuildVersion];
}
} @catch (NSException *exception) {
NSLog(@"an exception was thrown: %@", exception);
currentVersion = [Settings.sharedSettings latestBuildVersion];
}
return currentVersion;
}
- (void) requestLatestBuildInfo {
NSString* buildsURL = [[[NSProcessInfo processInfo] environment] objectForKey:@"HQ_LAUNCHER_BUILDS_URL"];
if ([buildsURL length] == 0) {
buildsURL = @"https://thunder.highfidelity.com/builds/api/tags/latest?format=json";
}
NSLog(@"Making request for builds to: %@", buildsURL);
NSMutableURLRequest* request = [NSMutableURLRequest new];
[request setURL:[NSURL URLWithString:@"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"]];
[request setURL:[NSURL URLWithString:buildsURL]];
[request setHTTPMethod:@"GET"];
[request setValue:@USER_AGENT_STRING forHTTPHeaderField:@"User-Agent"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
@ -39,7 +28,7 @@
NSLog(@"Latest Build Request Response: %ld", [ne statusCode]);
Launcher* sharedLauncher = [Launcher sharedLauncher];
if ([ne statusCode] == 500) {
if (error || [ne statusCode] == 500) {
dispatch_async(dispatch_get_main_queue(), ^{
[sharedLauncher displayErrorPage];
});
@ -60,36 +49,26 @@
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray* values = [json valueForKey:@"results"];
NSDictionary* launcherValues = [json valueForKey:@"launcher"];
NSDictionary* value = [values objectAtIndex:0];
NSString* defaultBuildTag = [json valueForKey:@"default_tag"];
NSString* launcherVersion = [launcherValues valueForKey:@"version"];
NSString* launcherUrl = [[launcherValues valueForKey:@"mac"] valueForKey:@"url"];
NSString* buildNumber = [value valueForKey:@"latest_version"];
NSDictionary* installers = [value objectForKey:@"installers"];
NSDictionary* macInstallerObject = [installers objectForKey:@"mac"];
NSString* macInstallerUrl = [macInstallerObject valueForKey:@"zip_url"];
BOOL appDirectoryExist = [fileManager fileExistsAtPath:[[sharedLauncher getAppPath] stringByAppendingString:@"interface.app"]];
dispatch_async(dispatch_get_main_queue(), ^{
NSInteger currentVersion = [self getCurrentVersion];
NSInteger currentLauncherVersion = atoi(LAUNCHER_BUILD_VERSION);
NSLog(@"Latest Build Request -> current launcher version %ld", currentLauncherVersion);
NSLog(@"Latest Build Request -> latest launcher version %ld", launcherVersion.integerValue);
NSLog(@"Latest Build Request -> launcher url %@", launcherUrl);
NSLog(@"Latest Build Request -> does build directory exist: %@", appDirectoryExist ? @"TRUE" : @"FALSE");
NSLog(@"Latest Build Request -> current version: %ld", currentVersion);
NSLog(@"Latest Build Request -> latest version: %ld", buildNumber.integerValue);
NSLog(@"Latest Build Request -> mac url: %@", macInstallerUrl);
BOOL latestVersionAvailable = (currentVersion != buildNumber.integerValue);
BOOL latestLauncherVersionAvailable = (currentLauncherVersion != launcherVersion.integerValue);
[[Settings sharedSettings] buildVersion:buildNumber.integerValue];
BOOL shouldDownloadInterface = (latestVersionAvailable || !appDirectoryExist);
NSLog(@"Latest Build Request -> SHOULD DOWNLOAD: %@", shouldDownloadInterface ? @"TRUE" : @"FALSE");
[sharedLauncher shouldDownloadLatestBuild:shouldDownloadInterface :macInstallerUrl
:latestLauncherVersionAvailable :launcherUrl];
[sharedLauncher shouldDownloadLatestBuild:values
:defaultBuildTag
:latestLauncherVersionAvailable
:launcherUrl];
});
}];

View file

@ -55,6 +55,8 @@ struct LatestBuildInfo {
@property (nonatomic) BOOL waitingForInterfaceToTerminate;
@property (nonatomic) BOOL shouldDownloadInterface;
@property (nonatomic) BOOL latestBuildRequestFinished;
@property (nonatomic, assign) NSArray* latestBuilds;
@property (nonatomic, assign) NSString* defaultBuildTag;
@property (nonatomic, assign) NSTimer* updateProgressIndicatorTimer;
@property (nonatomic, assign, readwrite) ProcessState processState;
@property (nonatomic, assign, readwrite) LoginError loginError;
@ -70,6 +72,7 @@ struct LatestBuildInfo {
- (void) domainContentDownloadFinished;
- (void) domainScriptsDownloadFinished;
- (void) setDomainURLInfo:(NSString*) aDomainURL :(NSString*) aDomainContentUrl :(NSString*) aDomainScriptsUrl;
- (void) setOrganizationBuildTag:(NSString*) organizationBuildTag;
- (void) organizationRequestFinished:(BOOL) aOriginzationAccepted;
- (BOOL) loginShouldSetErrorState;
- (void) displayErrorPage;
@ -81,7 +84,9 @@ struct LatestBuildInfo {
- (void) setCurrentProcessState:(ProcessState) aProcessState;
- (void) setLoginErrorState:(LoginError) aLoginError;
- (LoginError) getLoginErrorState;
- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl;
- (void) updateLatestBuildInfo;
- (void) shouldDownloadLatestBuild:(NSArray*) latestBuilds :(NSString*) defaultBuildTag :(BOOL) newLauncherAvailable :(NSString*) launcherUrl;
- (void) tryDownloadLatestBuild:(BOOL)progressScreenAlreadyDisplayed;
- (void) interfaceFinishedDownloading;
- (NSString*) getDownloadPathForContentAndScripts;
- (void) launchInterface;
@ -97,11 +102,9 @@ struct LatestBuildInfo {
- (NSString*) getDownloadFilename;
- (void) startUpdateProgressIndicatorTimer;
- (void) endUpdateProgressIndicatorTimer;
- (BOOL) isLoadedIn;
- (BOOL) isLoggedIn;
- (NSString*) getAppPath;
- (void) updateProgressIndicator;
- (void) setLatestBuildInfo:(struct LatestBuildInfo) latestBuildInfo;
- (struct LatestBuildInfo) getLatestBuildInfo;
+ (id) sharedLauncher;
@end

View file

@ -8,6 +8,7 @@
#import "ErrorViewController.h"
#import "Settings.h"
#import "NSTask+NSTaskExecveAdditions.h"
#import "Interface.h"
@interface Launcher ()
@ -241,7 +242,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
return self.waitingForInterfaceToTerminate;
}
- (BOOL) isLoadedIn
- (BOOL) isLoggedIn
{
return [[Settings sharedSettings] isLoggedIn];
}
@ -255,6 +256,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
[[Settings sharedSettings] setDomainUrl:aDomainURL];
}
- (void) setOrganizationBuildTag:(NSString*) organizationBuildTag;
{
[[Settings sharedSettings] setOrganizationBuildTag:organizationBuildTag];
}
- (NSString*) getAppPath
{
return [self getDownloadPathForContentAndScripts];
@ -275,13 +281,26 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
self.displayName = aDiplayName;
}
- (NSInteger) getCurrentVersion {
NSInteger currentVersion;
@try {
NSString* interfaceAppPath = [[self getAppPath] stringByAppendingString:@"interface.app"];
NSError* error = nil;
Interface* interface = [[Interface alloc] initWith:interfaceAppPath];
currentVersion = [interface getVersion:&error];
if (currentVersion == 0 && error != nil) {
NSLog(@"can't get version from interface: %@", error);
}
} @catch (NSException *exception) {
NSLog(@"an exception was thrown while getting current interface version: %@", exception);
currentVersion = 0;
}
return currentVersion;
}
- (void) domainContentDownloadFinished
{
if (self.shouldDownloadInterface) {
[self.downloadInterface downloadInterface: self.interfaceDownloadUrl];
return;
}
[self interfaceFinishedDownloading];
[self tryDownloadLatestBuild:TRUE];
}
- (void) domainScriptsDownloadFinished
@ -337,6 +356,7 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
{
self.credentialsAccepted = aOriginzationAccepted;
if (aOriginzationAccepted) {
[self updateLatestBuildInfo];
[self.credentialsRequest confirmCredentials:self.username : self.password];
} else {
LoginScreen* loginScreen = [[LoginScreen alloc] initWithNibName:@"LoginScreen" bundle:nil];
@ -349,42 +369,26 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
return YES;
}
- (struct LatestBuildInfo) getLatestBuildInfo
{
return self.buildInfo;
}
- (void) setLatestBuildInfo:(struct LatestBuildInfo) latestBuildInfo
{
self.buildInfo = latestBuildInfo;
}
-(void) showLoginScreen
{
LoginScreen* loginScreen = [[LoginScreen alloc] initWithNibName:@"LoginScreen" bundle:nil];
[[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: loginScreen];
}
- (void) shouldDownloadLatestBuild:(BOOL) shouldDownload :(NSString*) downloadUrl :(BOOL) newLauncherAvailable :(NSString*) launcherUrl
- (void) shouldDownloadLatestBuild:(NSArray*) latestBuilds :(NSString*) defaultBuildTag :(BOOL) newLauncherAvailable :(NSString*) launcherUrl
{
self.latestBuilds = [[NSArray alloc] initWithArray:latestBuilds copyItems:true];
self.defaultBuildTag = defaultBuildTag;
[self updateLatestBuildInfo];
NSDictionary* launcherArguments = [LauncherCommandlineArgs arguments];
if (newLauncherAvailable && ![launcherArguments valueForKey: @"--noUpdate"]) {
[self.downloadLauncher downloadLauncher: launcherUrl];
} else {
self.shouldDownloadInterface = shouldDownload;
self.interfaceDownloadUrl = downloadUrl;
self.latestBuildRequestFinished = TRUE;
if ([self isLoadedIn]) {
Launcher* sharedLauncher = [Launcher sharedLauncher];
[sharedLauncher setCurrentProcessState:CHECKING_UPDATE];
if (shouldDownload) {
ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil];
[[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen];
[self startUpdateProgressIndicatorTimer];
[self.downloadInterface downloadInterface: downloadUrl];
return;
}
[self interfaceFinishedDownloading];
if ([self isLoggedIn]) {
[self tryDownloadLatestBuild:FALSE];
} else {
[[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE];
[self showLoginScreen];
@ -392,6 +396,67 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
}
}
// The latest builds are always retrieved on application start because they contain not only
// the latest interface builds, but also the latest launcher builds, which are required to know if
// we need to self-update first. The interface builds are categorized by build tag, and we may
// not know at application start which build tag we should be using. There are 2 scenarios where
// we call this function to determine our build tag and the correct build:
//
// 1. If we are logged in, we will have our build tag and can immediately get the correct build
// after receiving the builds.
// 2. If we are not logged in, we need to wait until we have logged in and received the org
// metadata for the user. The latest build info also needs to be updated _before_ downloading
// the content set cache because the progress bar value depends on it.
//
- (void) updateLatestBuildInfo {
NSLog(@"Updating latest build info");
NSInteger currentVersion = [self getCurrentVersion];
NSInteger latestVersion = 0;
Launcher* sharedLauncher = [Launcher sharedLauncher];
[sharedLauncher setCurrentProcessState:CHECKING_UPDATE];
BOOL newVersionAvailable = false;
NSString* url = @"";
NSString* buildTag = [[Settings sharedSettings] organizationBuildTag];
if ([buildTag length] == 0) {
buildTag = self.defaultBuildTag;
}
for (NSDictionary* build in self.latestBuilds) {
NSString* name = [build valueForKey:@"name"];
NSLog(@"Checking %@", name);
if ([name isEqual:buildTag]) {
url = [[[build objectForKey:@"installers"] objectForKey:@"mac"] valueForKey:@"zip_url"];
NSString* thisLatestVersion = [build valueForKey:@"latest_version"];
latestVersion = thisLatestVersion.integerValue;
newVersionAvailable = currentVersion != latestVersion;
NSLog(@"Using %@, %ld", name, latestVersion);
break;
}
}
self.shouldDownloadInterface = newVersionAvailable;
self.interfaceDownloadUrl = url;
NSLog(@"Updating latest build info, currentVersion=%ld, latestVersion=%ld, %@ %@",
currentVersion, latestVersion, (self.shouldDownloadInterface ? @"Yes" : @"No"), self.interfaceDownloadUrl);
}
- (void) tryDownloadLatestBuild:(BOOL)progressScreenAlreadyDisplayed
{
if (self.shouldDownloadInterface) {
if (!progressScreenAlreadyDisplayed) {
ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil];
[[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen];
[self startUpdateProgressIndicatorTimer];
}
[self.downloadInterface downloadInterface: self.interfaceDownloadUrl];
return;
}
[self interfaceFinishedDownloading];
}
-(void)runAutoupdater
{
NSTask* task = [[NSTask alloc] init];

View file

@ -2,6 +2,7 @@
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonHMAC.h>
#import "Launcher.h"
#import "Settings.h"
static NSString* const organizationURL = @"https://orgs.highfidelity.com/organizations/";
@ -76,11 +77,16 @@ static NSString* const organizationURL = @"https://orgs.highfidelity.com/organiz
}
NSString* domainURL = [json valueForKey:@"domain"];
NSString* contentSetURL = [json valueForKey:@"content_set_url"];
NSString* buildTag = [json valueForKey:@"build_tag"];
if (buildTag == nil) {
buildTag = @"";
}
if (domainURL != nil && contentSetURL != nil) {
NSLog(@"Organization: getting org file successful");
[sharedLauncher setDomainURLInfo:[json valueForKey:@"domain"] :[json valueForKey:@"content_set_url"] :nil];
[sharedLauncher setLoginErrorState: NONE];
[[Settings sharedSettings] setOrganizationBuildTag:buildTag];
[sharedLauncher organizationRequestFinished:TRUE];
} else {
NSLog(@"Organization: Either domainURL: %@ or contentSetURL: %@ json entries are invalid", domainURL, contentSetURL);

View file

@ -7,6 +7,7 @@
@property (nonatomic, assign) BOOL loggedIn;
@property (nonatomic, assign) NSString* domain;
@property (nonatomic, assign) NSString* launcher;
@property (nonatomic, assign) NSString* _organizationBuildTag;
- (NSInteger) latestBuildVersion;
- (BOOL) isLoggedIn;
- (void) login:(BOOL)aLoggedIn;
@ -15,6 +16,8 @@
- (NSString*) getLaucnherPath;
- (void) setDomainUrl:(NSString*) aDomainUrl;
- (NSString*) getDomainUrl;
- (void) setOrganizationBuildTag:(NSString*) aOrganizationBuildTag;
- (NSString*) organizationBuildTag;
- (void) save;
+ (id) sharedSettings;
@end

View file

@ -32,13 +32,18 @@
NSError * err;
NSData *data =[jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary * json;
if(data!=nil){
if (data != nil) {
json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&err];
self.loggedIn = [[json valueForKey:@"loggedIn"] boolValue];
self.build = [[json valueForKey:@"build_version"] integerValue];
self.launcher = [json valueForKey:@"luancherPath"];
self.domain = [json valueForKey:@"domain"];
self.organizationBuildTag = [json valueForKey:@"organizationBuildTag"];
if ([self.organizationBuildTag length] == 0) {
self.organizationBuildTag = @"";
}
return;
}
}
@ -53,7 +58,9 @@
[NSString stringWithFormat:@"%ld", self.build], @"build_version",
self.loggedIn ? @"TRUE" : @"FALSE", @"loggedIn",
self.domain, @"domain",
self.launcher, @"launcherPath", nil];
self.launcher, @"launcherPath",
self.organizationBuildTag, @"organizationBuildTag",
nil];
NSError * err;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:json options:0 error:&err];
NSString * jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
@ -114,6 +121,16 @@
return self.domain;
}
- (void) setOrganizationBuildTag:(NSString*) aOrganizationBuildTag
{
self._organizationBuildTag = aOrganizationBuildTag;
}
- (NSString*) organizationBuildTag
{
return self._organizationBuildTag;
}
- (NSString*) getLaucnherPath
{
return self.launcher;