/SIMBL Agent/SIMBLAgent.m

https://bitbucket.org/vasi/simbl · Objective C · 123 lines · 90 code · 22 blank · 11 comment · 27 complexity · afaaa4120747c1cfafad3fbab6f27459 MD5 · raw file

  1. /**
  2. * Copyright 2003-2009, Mike Solomon <mas63@cornell.edu>
  3. * SIMBL is released under the GNU General Public License v2.
  4. * http://www.opensource.org/licenses/gpl-2.0.php
  5. */
  6. #import "SIMBL.h"
  7. #import "SIMBLAgent.h"
  8. #import "SIMBLApplication.h"
  9. #import <ScriptingBridge/ScriptingBridge.h>
  10. #import <Carbon/Carbon.h>
  11. @implementation NSApplication (SystemVersion)
  12. - (void)getSystemVersionMajor:(unsigned *)major
  13. minor:(unsigned *)minor
  14. bugFix:(unsigned *)bugFix;
  15. {
  16. OSErr err;
  17. SInt32 systemVersion, versionMajor, versionMinor, versionBugFix;
  18. if ((err = Gestalt(gestaltSystemVersion, &systemVersion)) != noErr) goto fail;
  19. if (systemVersion < 0x1040)
  20. {
  21. if (major) *major = ((systemVersion & 0xF000) >> 12) * 10 +
  22. ((systemVersion & 0x0F00) >> 8);
  23. if (minor) *minor = (systemVersion & 0x00F0) >> 4;
  24. if (bugFix) *bugFix = (systemVersion & 0x000F);
  25. }
  26. else
  27. {
  28. if ((err = Gestalt(gestaltSystemVersionMajor, &versionMajor)) != noErr) goto fail;
  29. if ((err = Gestalt(gestaltSystemVersionMinor, &versionMinor)) != noErr) goto fail;
  30. if ((err = Gestalt(gestaltSystemVersionBugFix, &versionBugFix)) != noErr) goto fail;
  31. if (major) *major = versionMajor;
  32. if (minor) *minor = versionMinor;
  33. if (bugFix) *bugFix = versionBugFix;
  34. }
  35. return;
  36. fail:
  37. NSLog(@"Unable to obtain system version: %ld", (long)err);
  38. if (major) *major = 10;
  39. if (minor) *minor = 0;
  40. if (bugFix) *bugFix = 0;
  41. }
  42. @end
  43. @implementation SIMBLAgent
  44. - (void) applicationDidFinishLaunching:(NSNotification*)notificaion
  45. {
  46. NSProcessInfo* procInfo = [NSProcessInfo processInfo];
  47. if ([(NSString*)[[procInfo arguments] lastObject] hasPrefix:@"-psn"]) {
  48. // if we were started interactively, load in launchd and terminate
  49. NSLog(@"installing into launchd");
  50. [self loadInLaunchd];
  51. [NSApp terminate:nil];
  52. }
  53. else {
  54. NSLog(@"initialized");
  55. [[[NSWorkspace sharedWorkspace] notificationCenter]
  56. addObserver:self selector:@selector(injectSIMBL:)
  57. name:NSWorkspaceDidLaunchApplicationNotification object:nil];
  58. }
  59. }
  60. - (void) loadInLaunchd
  61. {
  62. NSTask* task = [NSTask launchedTaskWithLaunchPath:@"/bin/launchctl" arguments:[NSArray arrayWithObjects:@"load", @"-F", @"-S", @"Aqua", @"/Library/ScriptingAdditions/SIMBL.osax/Contents/Resources/SIMBL Agent.app/Contents/Resources/net.culater.SIMBL.Agent.plist", nil]];
  63. [task waitUntilExit];
  64. if ([task terminationStatus] != 0)
  65. NSLog(@"launchctl returned %d", [task terminationStatus]);
  66. }
  67. - (void) injectSIMBL:(NSNotification*)notification
  68. {
  69. NSLog(@"received %@", [notification userInfo]);
  70. SIMBLApplication *app = [SIMBLApplication applicationWithNotification: notification];
  71. // check to see if there are plugins to load
  72. if ([SIMBL shouldInstallPluginsIntoApplication: app] == NO) {
  73. return;
  74. }
  75. // Get the right event ID for this version of OS X
  76. unsigned majorOSVersion = 0;
  77. unsigned minorOSVersion = 0;
  78. unsigned buxfixOSVersion = 0;
  79. [NSApp getSystemVersionMajor:&majorOSVersion minor:&minorOSVersion bugFix:&buxfixOSVersion];
  80. if (majorOSVersion != 10) {
  81. NSLog(@"something fishy - OS X version %u", majorOSVersion);
  82. return;
  83. }
  84. AEEventID eventID = minorOSVersion > 5 ? 'load' : 'leop';
  85. // Find the process to target
  86. SBApplication *scriptApp = [SBApplication applicationWithProcessIdentifier: app.pid];
  87. if (!scriptApp) {
  88. NSLog(@"Can't find app with pid %d", app.pid);
  89. return;
  90. }
  91. [scriptApp setSendMode:kAENoReply];
  92. // Force AppleScript to initialize in the app, by getting the dictionary
  93. [scriptApp sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];
  94. // Inject!
  95. [scriptApp sendEvent:'SIMe' id:eventID parameters:0];
  96. }
  97. @end
  98. int main(int argc, char *argv[])
  99. {
  100. return NSApplicationMain(argc, (const char **) argv);
  101. }