summaryrefslogtreecommitdiffstats
path: root/WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m
diff options
context:
space:
mode:
authorUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
committerUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
commitd8543bb6618c17b12da906afa77d216f58cf4058 (patch)
treec58dc05ed86825bd0ef8d305d58c8205106b540f /WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m
downloadexternal_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.zip
external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.gz
external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.bz2
external/webkit r30707
Diffstat (limited to 'WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m')
-rw-r--r--WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m165
1 files changed, 165 insertions, 0 deletions
diff --git a/WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m b/WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m
new file mode 100644
index 0000000..8c6eb84
--- /dev/null
+++ b/WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+static void enableWebKitNightlyBehaviour() __attribute__ ((constructor));
+
+static NSString *WKNERunState = @"WKNERunState";
+static NSString *WKNEShouldMonitorShutdowns = @"WKNEShouldMonitorShutdowns";
+
+typedef enum {
+ RunStateShutDown,
+ RunStateInitializing,
+ RunStateRunning
+} WKNERunStates;
+
+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;
+
+ NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+ [userDefaults setInteger:RunStateRunning forKey:WKNERunState];
+ [userDefaults synchronize];
+
+ if (extensionBundlesWereLoaded)
+ NSRunInformationalAlertPanel(@"Safari extensions detected",
+ @"Safari extensions were detected on your system. Extensions 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 setInteger:RunStateShutDown forKey:WKNERunState];
+ [userDefaults synchronize];
+}
+
+extern char **_CFGetProcessPath() __attribute__((weak));
+
+static void poseAsWebKitApp()
+{
+ char *webKitAppPath = getenv("WebKitAppPath");
+ if (!webKitAppPath || !_CFGetProcessPath)
+ return;
+
+ // Set up the main bundle early so it points at Safari.app
+ CFBundleGetMainBundle();
+
+ // Fiddle with CoreFoundation to have it pick up the executable path as being within WebKit.app
+ char **processPath = _CFGetProcessPath();
+ *processPath = NULL;
+ setenv("CFProcessPath", webKitAppPath, 1);
+ _CFGetProcessPath();
+
+ // Clean up
+ unsetenv("CFProcessPath");
+ unsetenv("WebKitAppPath");
+}
+
+static void enableWebKitNightlyBehaviour()
+{
+ unsetenv("DYLD_INSERT_LIBRARIES");
+ poseAsWebKitApp();
+
+ 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:RunStateShutDown], WKNERunState,
+ [NSNumber numberWithBool:YES], WKNEShouldMonitorShutdowns, nil];
+ [userDefaults registerDefaults:defaultPrefs];
+ if ([userDefaults boolForKey:WKNEShouldMonitorShutdowns]) {
+ WKNERunStates savedState = (WKNERunStates)[userDefaults integerForKey:WKNERunState];
+ if (savedState == RunStateInitializing) {
+ // Use CoreFoundation here as AppKit hasn't been initialized at this stage of Safari's lifetime
+ CFOptionFlags responseFlags;
+ CFUserNotificationDisplayAlert(0, kCFUserNotificationCautionAlertLevel,
+ NULL, NULL, NULL,
+ CFSTR("WebKit failed to open correctly"),
+ CFSTR("WebKit failed to open correctly on your previous attempt. Please disable any Safari extensions that you may have installed. If the problem continues to occur, please file a bug report at http://webkit.org/quality/reporting.html"),
+ CFSTR("Continue"), NULL, NULL, &responseFlags);
+ }
+ else if (savedState == RunStateRunning) {
+ NSLog(@"WebKit failed to shut down cleanly. Checking for Safari extensions.");
+ CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), &myBundleDidLoad,
+ myBundleDidLoad, (CFStringRef) NSBundleDidLoadNotification,
+ NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
+ }
+ }
+ [userDefaults setInteger:RunStateInitializing forKey:WKNERunState];
+ [userDefaults synchronize];
+
+ CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), &myApplicationWillFinishLaunching,
+ myApplicationWillFinishLaunching, (CFStringRef) NSApplicationWillFinishLaunchingNotification,
+ NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
+ CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), &myApplicationWillTerminate,
+ myApplicationWillTerminate, (CFStringRef) NSApplicationWillTerminateNotification,
+ NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
+ [pool release];
+}