* Scripts/do-webcore-rename: Another cut at renames. About ready to go (later...
[WebKit-https.git] / WebKitTools / WebKitLauncher / WebKitNightlyEnabler.m
index 589826736ddfb8b1be3dd236a1e5bd7c5ba0ca9d..7a6bf169a7e0093edaec6ce2a07efc8162a52092 100644 (file)
 #include <string.h>
 
 static void cleanUpAfterOurselves(void) __attribute__ ((constructor));
+static void *symbol_lookup(char *symbol);
 
-void *symbol_lookup(char *symbol);
+static NSString *WKNEDidShutDownCleanly = @"WKNEDidShutDownCleanly";
+static NSString *WKNEShouldMonitorShutdowns = @"WKNEShouldMonitorShutdowns";
+
+static bool extensionBundlesWereLoaded = NO;
+static NSSet *extensionPaths = nil;
+
+static void myBundleDidLoad(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
+{
+    // Break out early if we have already detected an extension
+    if (extensionBundlesWereLoaded)
+        return;
+
+    NSBundle *bundle = (NSBundle *)object;
+    NSString *bundlePath = [[bundle bundlePath] stringByAbbreviatingWithTildeInPath];
+    NSString *bundleFileName = [bundlePath lastPathComponent];
+
+    // Explicitly ignore SIMBL.bundle, as its only purpose is to load extensions
+    // on a per-application basis.  It's presence indicates a user has application
+    // extensions, but not that any will be loaded into Safari
+    if ([bundleFileName isEqualToString:@"SIMBL.bundle"])
+        return;
+
+    // If the bundle lives inside a known extension path, flag it as an extension
+    NSEnumerator *e = [extensionPaths objectEnumerator];
+    NSString *path = nil;
+    while (path = [e nextObject]) {
+        if ([bundlePath length] < [path length])
+            continue;
+
+        if ([[bundlePath substringToIndex:[path length]] isEqualToString:path]) {
+            extensionBundlesWereLoaded = YES;
+            break;
+        }
+    }
+}
+
+static void myApplicationWillFinishLaunching(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
+{
+    CFNotificationCenterRemoveObserver(CFNotificationCenterGetLocalCenter(), &myApplicationWillFinishLaunching, NULL, NULL);
+    CFNotificationCenterRemoveObserver(CFNotificationCenterGetLocalCenter(), &myBundleDidLoad, NULL, NULL);
+    [extensionPaths release];
+    extensionPaths = nil;
+
+    if (extensionBundlesWereLoaded)
+        NSRunInformationalAlertPanel(@"Safari extensions detected",
+                                     @"Safari extensions were detected on your system. They are incompatible with nightly builds of WebKit, and may cause crashes or incorrect behavior.  Please disable them if you experience such behavior.", @"Continue", nil, nil);
+}
+
+static void myApplicationWillTerminate(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
+{
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    [userDefaults setBool:YES forKey:WKNEDidShutDownCleanly];
+    [userDefaults synchronize];
+}
 
 void cleanUpAfterOurselves(void)
 {
@@ -48,6 +102,34 @@ void cleanUpAfterOurselves(void)
     *procPath = procPathBackup;
     unsetenv("DYLD_INSERT_LIBRARIES");
     unsetenv("CFProcessPath");
+
+    extensionPaths = [[NSSet alloc] initWithObjects:@"~/Library/InputManagers/", @"/Library/InputManagers/",
+                                                    @"~/Library/Application Support/SIMBL/Plugins/", @"/Library/Application Support/SIMBL/Plugins/",
+                                                    @"~/Library/Application Enhancers/", @"/Library/Application Enhancers/",
+                                                    nil];
+
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    NSDictionary *defaultPrefs = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], WKNEDidShutDownCleanly,
+                                                                            [NSNumber numberWithBool:YES], WKNEShouldMonitorShutdowns, nil];
+    [userDefaults registerDefaults:defaultPrefs];
+    if ([userDefaults boolForKey:WKNEShouldMonitorShutdowns] && ![userDefaults boolForKey:WKNEDidShutDownCleanly])
+    {
+        NSLog(@"WebKit failed to shut down cleanly.  Checking for Safari extensions.");
+        CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), &myBundleDidLoad,
+                                        myBundleDidLoad, (CFStringRef) NSBundleDidLoadNotification,
+                                        NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
+        CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), &myApplicationWillFinishLaunching,
+                                        myApplicationWillFinishLaunching, (CFStringRef) NSApplicationWillFinishLaunchingNotification,
+                                        NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
+    }
+    [userDefaults setBool:NO forKey:WKNEDidShutDownCleanly];
+    [userDefaults synchronize];
+
+    CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), &myApplicationWillTerminate,
+                                    myApplicationWillTerminate, (CFStringRef) NSApplicationWillTerminateNotification,
+                                    NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
+    [pool release];
 }
 
 #if __LP64__