1/* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#import <Cocoa/Cocoa.h> 30#import <CoreFoundation/CoreFoundation.h> 31 32void displayErrorAndQuit(NSString *title, NSString *message) 33{ 34 NSApplicationLoad(); 35 NSRunCriticalAlertPanel(title, message, @"Quit", nil, nil); 36 exit(0); 37} 38 39void checkMacOSXVersion() 40{ 41 long versionNumber = 0; 42 OSErr error = Gestalt(gestaltSystemVersion, &versionNumber); 43 if (error != noErr || versionNumber < 0x1040) 44 displayErrorAndQuit(@"Mac OS X 10.4 is Required", @"Nightly builds of WebKit require Mac OS X 10.4 or newer."); 45} 46 47int getLastVersionShown() 48{ 49 [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObject:@"-1" forKey:@"StartPageShownInVersion"]]; 50 return [[NSUserDefaults standardUserDefaults] integerForKey:@"StartPageShownInVersion"]; 51} 52 53void saveLastVersionShown(int lastVersion) 54{ 55 [[NSUserDefaults standardUserDefaults] setInteger:lastVersion forKey:@"StartPageShownInVersion"]; 56 [[NSUserDefaults standardUserDefaults] synchronize]; 57} 58 59NSString *getPathForStartPage() 60{ 61 return [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"start.html"]; 62} 63 64int getShowStartPageVersion() 65{ 66 return getCurrentVersion() + 1; 67} 68 69int getCurrentVersion() 70{ 71 return [[[[NSBundle mainBundle] infoDictionary] valueForKey:(NSString *)kCFBundleVersionKey] intValue]; 72} 73 74BOOL startPageDisabled() 75{ 76 return [[NSUserDefaults standardUserDefaults] boolForKey:@"StartPageDisabled"]; 77} 78 79void addStartPageToArgumentsIfNeeded(NSMutableArray *arguments) 80{ 81 if (startPageDisabled()) 82 return; 83 84 if (getLastVersionShown() < getShowStartPageVersion()) { 85 saveLastVersionShown(getCurrentVersion()); 86 NSString *startPagePath = getPathForStartPage(); 87 if (startPagePath) 88 [arguments addObject:startPagePath]; 89 } 90} 91 92static void myExecve(NSString *executable, NSArray *args, NSDictionary *environment) 93{ 94 char **argv = (char **)calloc(sizeof(char *), [args count] + 1); 95 char **env = (char **)calloc(sizeof(char *), [environment count] + 1); 96 97 NSEnumerator *e = [args objectEnumerator]; 98 NSString *s; 99 int i = 0; 100 while (s = [e nextObject]) 101 argv[i++] = (char *) [s UTF8String]; 102 103 e = [environment keyEnumerator]; 104 i = 0; 105 while (s = [e nextObject]) 106 env[i++] = (char *) [[NSString stringWithFormat:@"%@=%@", s, [environment objectForKey:s]] UTF8String]; 107 108 execve([executable fileSystemRepresentation], argv, env); 109} 110 111NSBundle *locateSafariBundle() 112{ 113 NSArray *applicationDirectories = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSAllDomainsMask, YES); 114 NSEnumerator *e = [applicationDirectories objectEnumerator]; 115 NSString *applicationDirectory; 116 while (applicationDirectory = [e nextObject]) { 117 NSString *possibleSafariPath = [applicationDirectory stringByAppendingPathComponent:@"Safari.app"]; 118 NSBundle *possibleSafariBundle = [NSBundle bundleWithPath:possibleSafariPath]; 119 if ([[possibleSafariBundle bundleIdentifier] isEqualToString:@"com.apple.Safari"]) 120 return possibleSafariBundle; 121 } 122 123 CFURLRef safariURL = nil; 124 OSStatus err = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.Safari"), nil, nil, &safariURL); 125 if (err != noErr) 126 displayErrorAndQuit(@"Unable to locate Safari", @"Nightly builds of WebKit require Safari to run. Please check that it is available and then try again."); 127 128 NSBundle *safariBundle = [NSBundle bundleWithPath:[(NSURL *)safariURL path]]; 129 CFRelease(safariURL); 130 return safariBundle; 131} 132 133int main(int argc, char *argv[]) 134{ 135 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 136 checkMacOSXVersion(); 137 138 NSBundle *safariBundle = locateSafariBundle(); 139 NSString *executablePath = [safariBundle executablePath]; 140 NSString *frameworkPath = [[NSBundle mainBundle] resourcePath]; 141 NSString *pathToEnablerLib = [[NSBundle mainBundle] pathForResource:@"WebKitNightlyEnabler" ofType:@"dylib"]; 142 143 if ([frameworkPath rangeOfString:@":"].location != NSNotFound || 144 [pathToEnablerLib rangeOfString:@":"].location != NSNotFound) 145 displayErrorAndQuit(@"Unable to launch Safari", 146 @"WebKit is located at a path containing an unsupported character. Please move WebKit to a different location and try again."); 147 148 NSMutableArray *arguments = [NSMutableArray arrayWithObjects:executablePath, @"-WebKitDeveloperExtras", @"YES", @"-WebKitScriptDebuggerEnabled", @"YES", nil]; 149 NSMutableDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys:frameworkPath, @"DYLD_FRAMEWORK_PATH", @"YES", @"WEBKIT_UNSET_DYLD_FRAMEWORK_PATH", 150 pathToEnablerLib, @"DYLD_INSERT_LIBRARIES", [[NSBundle mainBundle] executablePath], @"WebKitAppPath", nil]; 151 addStartPageToArgumentsIfNeeded(arguments); 152 153 while (*++argv) 154 [arguments addObject:[NSString stringWithUTF8String:*argv]]; 155 156 myExecve(executablePath, arguments, environment); 157 158 char *error = strerror(errno); 159 NSString *errorMessage = [NSString stringWithFormat:@"Launching Safari at %@ failed with the error '%s' (%d)", [safariBundle bundlePath], error, errno]; 160 displayErrorAndQuit(@"Unable to launch Safari", errorMessage); 161 162 [pool release]; 163 return 0; 164} 165