Permalink
Browse files

The finish_installation tool will not relaunch the host app if it's u…

…sing the "Install on Quit" functionality.
  • Loading branch information...
1 parent e71915b commit c96aa2eda8c6931cc0cade17099696a8e40015fc @andymatuschak andymatuschak committed Sep 29, 2011
Showing with 78 additions and 76 deletions.
  1. +4 −4 SUAutomaticUpdateDriver.m
  2. +2 −2 SUBasicUpdateDriver.h
  3. +40 −44 SUBasicUpdateDriver.m
  4. +3 −4 SUUIBasedUpdateDriver.m
  5. +29 −22 finish_installation.m
@@ -44,7 +44,7 @@ - (void)automaticUpdateAlert:(SUAutomaticUpdateAlert *)aua finishedWithChoice:(S
switch (choice)
{
case SUInstallNowChoice:
- [self installUpdate];
+ [self installWithToolAndRelaunch:YES];
break;
case SUInstallLaterChoice:
@@ -61,15 +61,15 @@ - (void)automaticUpdateAlert:(SUAutomaticUpdateAlert *)aua finishedWithChoice:(S
- (BOOL)shouldInstallSynchronously { return postponingInstallation; }
-- (void)installUpdate
+- (void)installWithToolAndRelaunch:(BOOL)relaunch
{
showErrors = YES;
- [super installUpdate];
+ [super installWithToolAndRelaunch:relaunch];
}
- (void)applicationWillTerminate:(NSNotification *)note
{
- [self installUpdate];
+ [self installWithToolAndRelaunch:NO];
}
- (void)abortUpdateWithError:(NSError *)error
@@ -46,10 +46,10 @@
- (void)unarchiverDidFail:(SUUnarchiver *)ua;
- (void)failedToApplyDeltaUpdate;
-- (void)installUpdate;
+- (void)installWithToolAndRelaunch:(BOOL)relaunch;
- (void)installerForHost:(SUHost *)host failedWithError:(NSError *)error;
-- (void)installAndRelaunchWithTool;
+- (void)installWithToolAndRelaunch:(BOOL)relaunch;
- (void)cleanUpDownload;
- (void)abortUpdate;
View
@@ -237,7 +237,7 @@ - (void)failedToApplyDeltaUpdate
- (void)unarchiverDidFinish:(SUUnarchiver *)ua
{
if (ua) { CFRelease(ua); }
- [self installUpdate];
+ [self installWithToolAndRelaunch:YES];
}
- (void)unarchiverDidFail:(SUUnarchiver *)ua
@@ -254,8 +254,28 @@ - (void)unarchiverDidFail:(SUUnarchiver *)ua
- (BOOL)shouldInstallSynchronously { return NO; }
-- (void)installUpdate
+- (void)installWithToolAndRelaunch:(BOOL)relaunch
{
+ if (![updater mayUpdateAndRestart])
+ {
+ [self abortUpdate];
+ return;
+ }
+
+ // Give the host app an opportunity to postpone the install and relaunch.
+ static BOOL postponedOnce = NO;
+ if (!postponedOnce && [[updater delegate] respondsToSelector:@selector(updater:shouldPostponeRelaunchForUpdate:untilInvoking:)])
+ {
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(installWithToolAndRelaunch:)]];
+ [invocation setSelector:@selector(installWithToolAndRelaunch:)];
+ [invocation setArgument:&relaunch atIndex:0];
+ [invocation setTarget:self];
+ postponedOnce = YES;
+ if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
+ return;
+ }
+
+
if ([[updater delegate] respondsToSelector:@selector(updater:willInstallUpdate:)])
[[updater delegate] updater:updater willInstallUpdate:updateItem];
@@ -276,49 +296,25 @@ - (void)installUpdate
else
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:SULocalizedString(@"An error occurred while extracting the archive. Please try again later.", nil), NSLocalizedDescriptionKey, [NSString stringWithFormat:@"Couldn't copy relauncher (%@) to temporary path (%@)! %@", relaunchPathToCopy, targetPath, (error ? [error localizedDescription] : @"")], NSLocalizedFailureReasonErrorKey, nil]]];
- [self installAndRelaunchWithTool];
-}
-
-- (void)installAndRelaunchWithTool
-{
- BOOL mayRelaunchAtAll = [updater mayUpdateAndRestart];
+ [[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
+ if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
+ [[updater delegate] updaterWillRelaunchApplication:updater];
+
+ if(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath])
+ {
+ // Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin.
+ [self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:SULocalizedString(@"An error occurred while relaunching %1$@, but the new version will be available next time you run %1$@.", nil), [host name]], NSLocalizedDescriptionKey, [NSString stringWithFormat:@"Couldn't find the relauncher (expected to find it at %@)", relaunchPath], NSLocalizedFailureReasonErrorKey, nil]]];
+ // We intentionally don't abandon the update here so that the host won't initiate another.
+ return;
+ }
+
+ NSString *pathToRelaunch = [host bundlePath];
+ if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
+ pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
+ NSString *relaunchToolPath = [relaunchPath stringByAppendingPathComponent: @"/Contents/MacOS/finish_installation"];
+ [NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, relaunch ? @"1" : @"0", nil]];
- if( mayRelaunchAtAll )
- {
- // Give the host app an opportunity to postpone the relaunch.
- static BOOL postponedOnce = NO;
- if (!postponedOnce && [[updater delegate] respondsToSelector:@selector(updater:shouldPostponeRelaunchForUpdate:untilInvoking:)])
- {
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(installAndRelaunchWithTool)]];
- [invocation setSelector:@selector(installAndRelaunchWithTool)];
- [invocation setTarget:self];
- postponedOnce = YES;
- if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
- return;
- }
-
- [[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
- if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
- [[updater delegate] updaterWillRelaunchApplication:updater];
-
- if(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath])
- {
- // Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin.
- [self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:SULocalizedString(@"An error occurred while relaunching %1$@, but the new version will be available next time you run %1$@.", nil), [host name]], NSLocalizedDescriptionKey, [NSString stringWithFormat:@"Couldn't find the relauncher (expected to find it at %@)", relaunchPath], NSLocalizedFailureReasonErrorKey, nil]]];
- // We intentionally don't abandon the update here so that the host won't initiate another.
- return;
- }
-
- NSString *pathToRelaunch = [host bundlePath];
- if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
- pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
- NSString *relaunchToolPath = [relaunchPath stringByAppendingPathComponent: @"/Contents/MacOS/finish_installation"];
- [NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, nil]];
-
- [NSApp terminate:self];
- }
- else
- [self abortUpdate];
+ [NSApp terminate:self];
}
- (void)cleanUpDownload
@@ -162,15 +162,14 @@ - (void)unarchiverDidFinish:(SUUnarchiver *)ua
- (void)installAndRestart: (id)sender
{
- if( [updater mayUpdateAndRestart] )
- [self installUpdate];
+ [self installWithToolAndRelaunch:YES];
}
-- (void)installUpdate
+- (void)installWithToolAndRelaunch:(BOOL)relaunch
{
[statusController beginActionWithTitle:SULocalizedString(@"Installing update...", @"Take care not to overflow the status window.") maxProgressValue:0.0 statusText:nil];
[statusController setButtonEnabled:NO];
- [super installUpdate];
+ [super installWithToolAndRelaunch:relaunch];
// if a user chooses to NOT relaunch the app (as is the case with WebKit
View
@@ -21,6 +21,7 @@ @interface TerminationListener : NSObject
NSTimer *watchdogTimer;
NSTimer *longInstallationTimer;
SUHost *host;
+ BOOL shouldRelaunch;
}
- (void) parentHasQuit;
@@ -35,7 +36,7 @@ - (void) watchdog:(NSTimer *)aTimer;
@implementation TerminationListener
-- (id) initWithExecutablePath:(const char *)execpath parentProcessId:(pid_t)ppid folderPath: (const char*)infolderpath
+- (id) initWithExecutablePath:(const char *)execpath parentProcessId:(pid_t)ppid folderPath: (const char*)infolderpath shouldRelaunch:(BOOL)relaunch
selfPath: (NSString*)inSelfPath
{
if( !(self = [super init]) )
@@ -45,6 +46,7 @@ - (id) initWithExecutablePath:(const char *)execpath parentProcessId:(pid_t)ppid
parentprocessid = ppid;
folderpath = infolderpath;
selfPath = [inSelfPath retain];
+ shouldRelaunch = relaunch;
BOOL alreadyTerminated = (getppid() == 1); // ppid is launchd (1) => parent terminated already
@@ -105,23 +107,27 @@ - (void)showAppIconInDock:(NSTimer *)aTimer;
- (void) relaunch
{
- NSString *appPath = nil;
- if( !folderpath )
- appPath = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:executablepath length:strlen(executablepath)];
- else
- appPath = [host installationPath];
- [[NSWorkspace sharedWorkspace] openFile: appPath];
- if( folderpath )
- {
- NSError* theError = nil;
- if( ![SUPlainInstaller _removeFileAtPath: [SUInstaller updateFolder] error: &theError] )
- SULog( @"Couldn't remove update folder: %@.", theError );
- }
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
- [[NSFileManager defaultManager] removeFileAtPath: selfPath handler: nil];
-#else
- [[NSFileManager defaultManager] removeItemAtPath: selfPath error: NULL];
-#endif
+ if (shouldRelaunch)
+ {
+ NSString *appPath = nil;
+ if( !folderpath )
+ appPath = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:executablepath length:strlen(executablepath)];
+ else
+ appPath = [host installationPath];
+ [[NSWorkspace sharedWorkspace] openFile: appPath];
+ if( folderpath )
+ {
+ NSError* theError = nil;
+ if( ![SUPlainInstaller _removeFileAtPath: [SUInstaller updateFolder] error: &theError] )
+ SULog( @"Couldn't remove update folder: %@.", theError );
+ }
+ #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+ [[NSFileManager defaultManager] removeFileAtPath: selfPath handler: nil];
+ #else
+ [[NSFileManager defaultManager] removeItemAtPath: selfPath error: NULL];
+ #endif
+ }
+
exit(EXIT_SUCCESS);
}
@@ -158,7 +164,7 @@ - (void) installerForHost:(SUHost *)host failedWithError:(NSError *)error
int main (int argc, const char * argv[])
{
- if( argc < 3 || argc > 4 )
+ if( argc < 4 || argc > 5 )
return EXIT_FAILURE;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -182,9 +188,10 @@ int main (int argc, const char * argv[])
[NSApplication sharedApplication];
[[[TerminationListener alloc] initWithExecutablePath: (argc > 1) ? argv[1] : NULL
- parentProcessId: (argc > 2) ? atoi(argv[2]) : 0
- folderPath: (argc > 3) ? argv[3] : NULL
- selfPath: selfPath] autorelease];
+ parentProcessId: (argc > 2) ? atoi(argv[2]) : 0
+ folderPath: (argc > 3) ? argv[3] : NULL
+ shouldRelaunch: (argc > 4) ? atoi(argv[4]) : 1
+ selfPath: selfPath] autorelease];
[[NSApplication sharedApplication] run];
[pool drain];

0 comments on commit c96aa2e

Please sign in to comment.