Skip to content

Commit c96aa2e

Browse files
committed
The finish_installation tool will not relaunch the host app if it's using the "Install on Quit" functionality.
1 parent e71915b commit c96aa2e

5 files changed

+78
-76
lines changed

SUAutomaticUpdateDriver.m

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ - (void)automaticUpdateAlert:(SUAutomaticUpdateAlert *)aua finishedWithChoice:(S
4444
switch (choice)
4545
{
4646
case SUInstallNowChoice:
47-
[self installUpdate];
47+
[self installWithToolAndRelaunch:YES];
4848
break;
4949

5050
case SUInstallLaterChoice:
@@ -61,15 +61,15 @@ - (void)automaticUpdateAlert:(SUAutomaticUpdateAlert *)aua finishedWithChoice:(S
6161

6262
- (BOOL)shouldInstallSynchronously { return postponingInstallation; }
6363

64-
- (void)installUpdate
64+
- (void)installWithToolAndRelaunch:(BOOL)relaunch
6565
{
6666
showErrors = YES;
67-
[super installUpdate];
67+
[super installWithToolAndRelaunch:relaunch];
6868
}
6969

7070
- (void)applicationWillTerminate:(NSNotification *)note
7171
{
72-
[self installUpdate];
72+
[self installWithToolAndRelaunch:NO];
7373
}
7474

7575
- (void)abortUpdateWithError:(NSError *)error

SUBasicUpdateDriver.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@
4646
- (void)unarchiverDidFail:(SUUnarchiver *)ua;
4747
- (void)failedToApplyDeltaUpdate;
4848

49-
- (void)installUpdate;
49+
- (void)installWithToolAndRelaunch:(BOOL)relaunch;
5050
- (void)installerForHost:(SUHost *)host failedWithError:(NSError *)error;
5151

52-
- (void)installAndRelaunchWithTool;
52+
- (void)installWithToolAndRelaunch:(BOOL)relaunch;
5353
- (void)cleanUpDownload;
5454

5555
- (void)abortUpdate;

SUBasicUpdateDriver.m

+40-44
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ - (void)failedToApplyDeltaUpdate
237237
- (void)unarchiverDidFinish:(SUUnarchiver *)ua
238238
{
239239
if (ua) { CFRelease(ua); }
240-
[self installUpdate];
240+
[self installWithToolAndRelaunch:YES];
241241
}
242242

243243
- (void)unarchiverDidFail:(SUUnarchiver *)ua
@@ -254,8 +254,28 @@ - (void)unarchiverDidFail:(SUUnarchiver *)ua
254254

255255
- (BOOL)shouldInstallSynchronously { return NO; }
256256

257-
- (void)installUpdate
257+
- (void)installWithToolAndRelaunch:(BOOL)relaunch
258258
{
259+
if (![updater mayUpdateAndRestart])
260+
{
261+
[self abortUpdate];
262+
return;
263+
}
264+
265+
// Give the host app an opportunity to postpone the install and relaunch.
266+
static BOOL postponedOnce = NO;
267+
if (!postponedOnce && [[updater delegate] respondsToSelector:@selector(updater:shouldPostponeRelaunchForUpdate:untilInvoking:)])
268+
{
269+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(installWithToolAndRelaunch:)]];
270+
[invocation setSelector:@selector(installWithToolAndRelaunch:)];
271+
[invocation setArgument:&relaunch atIndex:0];
272+
[invocation setTarget:self];
273+
postponedOnce = YES;
274+
if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
275+
return;
276+
}
277+
278+
259279
if ([[updater delegate] respondsToSelector:@selector(updater:willInstallUpdate:)])
260280
[[updater delegate] updater:updater willInstallUpdate:updateItem];
261281

@@ -276,49 +296,25 @@ - (void)installUpdate
276296
else
277297
[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]]];
278298

279-
[self installAndRelaunchWithTool];
280-
}
281-
282-
- (void)installAndRelaunchWithTool
283-
{
284-
BOOL mayRelaunchAtAll = [updater mayUpdateAndRestart];
299+
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
300+
if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
301+
[[updater delegate] updaterWillRelaunchApplication:updater];
302+
303+
if(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath])
304+
{
305+
// Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin.
306+
[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]]];
307+
// We intentionally don't abandon the update here so that the host won't initiate another.
308+
return;
309+
}
310+
311+
NSString *pathToRelaunch = [host bundlePath];
312+
if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
313+
pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
314+
NSString *relaunchToolPath = [relaunchPath stringByAppendingPathComponent: @"/Contents/MacOS/finish_installation"];
315+
[NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, relaunch ? @"1" : @"0", nil]];
285316

286-
if( mayRelaunchAtAll )
287-
{
288-
// Give the host app an opportunity to postpone the relaunch.
289-
static BOOL postponedOnce = NO;
290-
if (!postponedOnce && [[updater delegate] respondsToSelector:@selector(updater:shouldPostponeRelaunchForUpdate:untilInvoking:)])
291-
{
292-
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(installAndRelaunchWithTool)]];
293-
[invocation setSelector:@selector(installAndRelaunchWithTool)];
294-
[invocation setTarget:self];
295-
postponedOnce = YES;
296-
if ([[updater delegate] updater:updater shouldPostponeRelaunchForUpdate:updateItem untilInvoking:invocation])
297-
return;
298-
}
299-
300-
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
301-
if ([[updater delegate] respondsToSelector:@selector(updaterWillRelaunchApplication:)])
302-
[[updater delegate] updaterWillRelaunchApplication:updater];
303-
304-
if(!relaunchPath || ![[NSFileManager defaultManager] fileExistsAtPath:relaunchPath])
305-
{
306-
// Note that we explicitly use the host app's name here, since updating plugin for Mail relaunches Mail, not just the plugin.
307-
[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]]];
308-
// We intentionally don't abandon the update here so that the host won't initiate another.
309-
return;
310-
}
311-
312-
NSString *pathToRelaunch = [host bundlePath];
313-
if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
314-
pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
315-
NSString *relaunchToolPath = [relaunchPath stringByAppendingPathComponent: @"/Contents/MacOS/finish_installation"];
316-
[NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, nil]];
317-
318-
[NSApp terminate:self];
319-
}
320-
else
321-
[self abortUpdate];
317+
[NSApp terminate:self];
322318
}
323319

324320
- (void)cleanUpDownload

SUUIBasedUpdateDriver.m

+3-4
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,14 @@ - (void)unarchiverDidFinish:(SUUnarchiver *)ua
162162

163163
- (void)installAndRestart: (id)sender
164164
{
165-
if( [updater mayUpdateAndRestart] )
166-
[self installUpdate];
165+
[self installWithToolAndRelaunch:YES];
167166
}
168167

169-
- (void)installUpdate
168+
- (void)installWithToolAndRelaunch:(BOOL)relaunch
170169
{
171170
[statusController beginActionWithTitle:SULocalizedString(@"Installing update...", @"Take care not to overflow the status window.") maxProgressValue:0.0 statusText:nil];
172171
[statusController setButtonEnabled:NO];
173-
[super installUpdate];
172+
[super installWithToolAndRelaunch:relaunch];
174173

175174

176175
// if a user chooses to NOT relaunch the app (as is the case with WebKit

finish_installation.m

+29-22
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ @interface TerminationListener : NSObject
2121
NSTimer *watchdogTimer;
2222
NSTimer *longInstallationTimer;
2323
SUHost *host;
24+
BOOL shouldRelaunch;
2425
}
2526

2627
- (void) parentHasQuit;
@@ -35,7 +36,7 @@ - (void) watchdog:(NSTimer *)aTimer;
3536

3637
@implementation TerminationListener
3738

38-
- (id) initWithExecutablePath:(const char *)execpath parentProcessId:(pid_t)ppid folderPath: (const char*)infolderpath
39+
- (id) initWithExecutablePath:(const char *)execpath parentProcessId:(pid_t)ppid folderPath: (const char*)infolderpath shouldRelaunch:(BOOL)relaunch
3940
selfPath: (NSString*)inSelfPath
4041
{
4142
if( !(self = [super init]) )
@@ -45,6 +46,7 @@ - (id) initWithExecutablePath:(const char *)execpath parentProcessId:(pid_t)ppid
4546
parentprocessid = ppid;
4647
folderpath = infolderpath;
4748
selfPath = [inSelfPath retain];
49+
shouldRelaunch = relaunch;
4850

4951
BOOL alreadyTerminated = (getppid() == 1); // ppid is launchd (1) => parent terminated already
5052

@@ -105,23 +107,27 @@ - (void)showAppIconInDock:(NSTimer *)aTimer;
105107

106108
- (void) relaunch
107109
{
108-
NSString *appPath = nil;
109-
if( !folderpath )
110-
appPath = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:executablepath length:strlen(executablepath)];
111-
else
112-
appPath = [host installationPath];
113-
[[NSWorkspace sharedWorkspace] openFile: appPath];
114-
if( folderpath )
115-
{
116-
NSError* theError = nil;
117-
if( ![SUPlainInstaller _removeFileAtPath: [SUInstaller updateFolder] error: &theError] )
118-
SULog( @"Couldn't remove update folder: %@.", theError );
119-
}
120-
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
121-
[[NSFileManager defaultManager] removeFileAtPath: selfPath handler: nil];
122-
#else
123-
[[NSFileManager defaultManager] removeItemAtPath: selfPath error: NULL];
124-
#endif
110+
if (shouldRelaunch)
111+
{
112+
NSString *appPath = nil;
113+
if( !folderpath )
114+
appPath = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:executablepath length:strlen(executablepath)];
115+
else
116+
appPath = [host installationPath];
117+
[[NSWorkspace sharedWorkspace] openFile: appPath];
118+
if( folderpath )
119+
{
120+
NSError* theError = nil;
121+
if( ![SUPlainInstaller _removeFileAtPath: [SUInstaller updateFolder] error: &theError] )
122+
SULog( @"Couldn't remove update folder: %@.", theError );
123+
}
124+
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
125+
[[NSFileManager defaultManager] removeFileAtPath: selfPath handler: nil];
126+
#else
127+
[[NSFileManager defaultManager] removeItemAtPath: selfPath error: NULL];
128+
#endif
129+
}
130+
125131
exit(EXIT_SUCCESS);
126132
}
127133

@@ -158,7 +164,7 @@ - (void) installerForHost:(SUHost *)host failedWithError:(NSError *)error
158164

159165
int main (int argc, const char * argv[])
160166
{
161-
if( argc < 3 || argc > 4 )
167+
if( argc < 4 || argc > 5 )
162168
return EXIT_FAILURE;
163169

164170
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -182,9 +188,10 @@ int main (int argc, const char * argv[])
182188

183189
[NSApplication sharedApplication];
184190
[[[TerminationListener alloc] initWithExecutablePath: (argc > 1) ? argv[1] : NULL
185-
parentProcessId: (argc > 2) ? atoi(argv[2]) : 0
186-
folderPath: (argc > 3) ? argv[3] : NULL
187-
selfPath: selfPath] autorelease];
191+
parentProcessId: (argc > 2) ? atoi(argv[2]) : 0
192+
folderPath: (argc > 3) ? argv[3] : NULL
193+
shouldRelaunch: (argc > 4) ? atoi(argv[4]) : 1
194+
selfPath: selfPath] autorelease];
188195
[[NSApplication sharedApplication] run];
189196

190197
[pool drain];

0 commit comments

Comments
 (0)