Extras/GrowlSafari/GrowlSafariLoader.m
author Peter Hosey <hg@boredzo.org>
Tue Sep 15 13:23:39 2009 -0700 (2009-09-15)
changeset 4402 fc7016ea4fc2
parent 4401 24c2a3482ec3
permissions -rw-r--r--
Forgot to qrefresh these extra parentheses before qfinishing. Fixes these comparisons being quite indiscriminate (at one point, GrowlSafari even tried to inject into Accessorizer).
     1 //
     2 //  GrowlSafariLoader.m
     3 //  GrowlSafari
     4 //
     5 //  Created by Peter Hosey on 2009-06-14.
     6 //  Copyright 2009 Peter Hosey. All rights reserved.
     7 //
     8 
     9 #import "GrowlSafariLoader.h"
    10 
    11 #import "InterestingBundleIdentifiers.h"
    12 
    13 @interface GrowlSafariLoader ()
    14 
    15 - (void) workspaceDidLaunchApplication:(NSNotification *)notification;
    16 
    17 @end
    18 
    19 @implementation GrowlSafariLoader
    20 
    21 - (id) init {
    22 	if((self = [super init])) {
    23 		workspace = [[NSWorkspace sharedWorkspace] retain];
    24 		NSNotificationCenter *nc = [workspace notificationCenter];
    25 		NSLog(@"Adding %@ as an observer on %@ for %@ with object %@", self, nc, NSWorkspaceDidLaunchApplicationNotification, workspace);
    26 		[nc addObserver:self
    27 			   selector:@selector(workspaceDidLaunchApplication:)
    28 				   name:NSWorkspaceDidLaunchApplicationNotification
    29 				 object:nil];
    30 	}
    31 	return self;
    32 }
    33 
    34 - (void) dealloc {
    35 	NSNotificationCenter *nc = [workspace notificationCenter];
    36 	[nc removeObserver:self
    37 				  name:NSWorkspaceDidLaunchApplicationNotification
    38 				object:workspace];
    39 	[workspace release];
    40 
    41 	[super dealloc];
    42 }
    43 
    44 - (void) applicationDidFinishLaunching:(NSNotification *)notification {
    45 	//Scan for running Safari instances, and send ourselves messages as if NSWorkspace had posted notifications about them.
    46 	NSEnumerator *appsEnum = [[workspace launchedApplications] objectEnumerator];
    47 	NSDictionary *appDict;
    48 	while ((appDict = [appsEnum nextObject])) {
    49 		NSNotification *notification = [NSNotification notificationWithName:NSWorkspaceDidLaunchApplicationNotification object:workspace userInfo:appDict];
    50 		[self workspaceDidLaunchApplication:notification];
    51 	}
    52 }
    53 
    54 - (BOOL) isOnSnowLeopardOrLater {
    55 	OSStatus err;
    56 
    57 	SInt32 majorOSVersion = 10, minorOSVersion = 0;
    58 	err = Gestalt(gestaltSystemVersionMajor, &majorOSVersion);
    59 	NSAssert2(err == noErr, @"Could not get operating-system major version number: %li/%s", (long)err, GetMacOSStatusCommentString(err));
    60 	err = Gestalt(gestaltSystemVersionMinor, &minorOSVersion);
    61 	NSAssert2(err == noErr, @"Could not get operating-system minor version number: %li/%s", (long)err, GetMacOSStatusCommentString(err));
    62 
    63 	return (majorOSVersion == 10 && minorOSVersion >= 6) || (majorOSVersion > 10);
    64 }
    65 
    66 - (void) workspaceDidLaunchApplication:(NSNotification *)notification {
    67 	NSDictionary *launchedProcessInfo = [notification userInfo];
    68 	NSString *bundleID = [launchedProcessInfo objectForKey:@"NSApplicationBundleIdentifier"];
    69 	if (bundleID && (([bundleID caseInsensitiveCompare:SAFARI_BUNDLE_ID] == NSOrderedSame) || ([bundleID caseInsensitiveCompare:WEBKIT_LAUNCHER_BUNDLE_ID] == NSOrderedSame))) {
    70 		NSString *bundlePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"GrowlSafari" ofType:@"bundle"];
    71 		if (bundlePath) {
    72 			NSNumber *PIDNum = [launchedProcessInfo objectForKey:@"NSApplicationProcessIdentifier"];
    73 			pid_t pid = [PIDNum intValue];
    74 			
    75 			NSArray *arguments = [NSArray arrayWithObjects:
    76 				@"-arch",
    77 #if defined(__i386__)
    78 				@"i386",
    79 #elif defined(__x86_64__)
    80 				//Safari did not exist in x86_64 before Snow Leopard, so, on older versions of Mac OS X, run the helper as i386.
    81 				[self isOnSnowLeopardOrLater] ? @"x86_64" : @"i386",
    82 #elif defined(__ppc__)
    83 				@"ppc",
    84 #else
    85 #error Unsupported architecture
    86 #endif
    87 				[[NSBundle bundleForClass:[self class]] pathForAuxiliaryExecutable:@"GrowlSafariHelper"],
    88 				[NSString stringWithFormat:@"%d", pid],
    89 				nil];
    90 			NSTask *task = [[[NSTask alloc] init] autorelease];
    91 			[task setLaunchPath:@"/usr/bin/arch"];
    92 			[task setArguments:arguments];
    93 			[task launch];
    94 		}
    95 	}
    96 }
    97 
    98 @end