1563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/*
20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc.  All rights reserved.
3563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
4563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Redistribution and use in source and binary forms, with or without
5563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * modification, are permitted provided that the following conditions
6563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * are met:
7563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
8563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 1.  Redistributions of source code must retain the above copyright
9563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     notice, this list of conditions and the following disclaimer.
10563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * 2.  Redistributions in binary form must reproduce the above copyright
11563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     notice, this list of conditions and the following disclaimer in the
12563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     documentation and/or other materials provided with the distribution.
130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     its contributors may be used to endorse or promote products derived
15563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *     from this software without specific prior written permission.
16563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
17563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */
28563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
29563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import <Cocoa/Cocoa.h>
30563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark#import <CoreFoundation/CoreFoundation.h>
31563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// We need to weak-import posix_spawn and friends as they're not available on Tiger.
330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// The BSD-level system headers do not have availability macros, so we redeclare the
340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// functions ourselves with the "weak" attribute.
350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#define WEAK_IMPORT __attribute__((weak))
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#define POSIX_SPAWN_SETEXEC 0x0040
390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochtypedef void *posix_spawnattr_t;
400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochtypedef void *posix_spawn_file_actions_t;
410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochint posix_spawnattr_init(posix_spawnattr_t *) WEAK_IMPORT;
420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochint posix_spawn(pid_t * __restrict, const char * __restrict, const posix_spawn_file_actions_t *, const posix_spawnattr_t * __restrict, char *const __argv[ __restrict], char *const __envp[ __restrict]) WEAK_IMPORT;
430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochint posix_spawnattr_setbinpref_np(posix_spawnattr_t * __restrict, size_t, cpu_type_t *__restrict, size_t *__restrict) WEAK_IMPORT;
440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochint posix_spawnattr_setflags(posix_spawnattr_t *, short) WEAK_IMPORT;
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void displayErrorAndQuit(NSString *title, NSString *message)
48563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
49563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSApplicationLoad();
50563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSRunCriticalAlertPanel(title, message, @"Quit", nil, nil);
51563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    exit(0);
52563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
53563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic int getLastVersionShown()
55563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
56563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObject:@"-1" forKey:@"StartPageShownInVersion"]];
57563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return [[NSUserDefaults standardUserDefaults] integerForKey:@"StartPageShownInVersion"];
58563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
59563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void saveLastVersionShown(int lastVersion)
61563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
62563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[NSUserDefaults standardUserDefaults] setInteger:lastVersion forKey:@"StartPageShownInVersion"];
63563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [[NSUserDefaults standardUserDefaults] synchronize];
64563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
65563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic NSString *getPathForStartPage()
67563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
68563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"start.html"];
69563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
70563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic int getCurrentVersion()
72563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return [[[[NSBundle mainBundle] infoDictionary] valueForKey:(NSString *)kCFBundleVersionKey] intValue];
74563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
75563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic int getShowStartPageVersion()
77563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return getCurrentVersion() + 1;
79563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
80563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic BOOL startPageDisabled()
82563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
83563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return [[NSUserDefaults standardUserDefaults] boolForKey:@"StartPageDisabled"];
84563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
85563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void addStartPageToArgumentsIfNeeded(NSMutableArray *arguments)
87563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
88563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (startPageDisabled())
89563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return;
90563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
91563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (getLastVersionShown() < getShowStartPageVersion()) {
92563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        saveLastVersionShown(getCurrentVersion());
93563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        NSString *startPagePath = getPathForStartPage();
94563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (startPagePath)
95563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            [arguments addObject:startPagePath];
96563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
97563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
98563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic cpu_type_t preferredArchitecture()
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(__ppc__)
1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return CPU_TYPE_POWERPC;
1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#elif defined(__LP64__)
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return CPU_TYPE_X86_64;
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return CPU_TYPE_X86;
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
110563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkstatic void myExecve(NSString *executable, NSArray *args, NSDictionary *environment)
111563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
112563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    char **argv = (char **)calloc(sizeof(char *), [args count] + 1);
113563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    char **env = (char **)calloc(sizeof(char *), [environment count] + 1);
1140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
115563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEnumerator *e = [args objectEnumerator];
116563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSString *s;
117563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    int i = 0;
1180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while ((s = [e nextObject]))
119563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        argv[i++] = (char *) [s UTF8String];
1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
121563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    e = [environment keyEnumerator];
122563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    i = 0;
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while ((s = [e nextObject]))
124563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        env[i++] = (char *) [[NSString stringWithFormat:@"%@=%@", s, [environment objectForKey:s]] UTF8String];
1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (posix_spawnattr_init && posix_spawn && posix_spawnattr_setbinpref_np && posix_spawnattr_setflags) {
1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        posix_spawnattr_t attr;
1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        posix_spawnattr_init(&attr);
1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        cpu_type_t architecturePreference[] = { preferredArchitecture(), CPU_TYPE_X86 };
1300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        posix_spawnattr_setbinpref_np(&attr, 2, architecturePreference, 0);
1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        short flags = POSIX_SPAWN_SETEXEC;
1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        posix_spawnattr_setflags(&attr, flags);
1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        posix_spawn(NULL, [executable fileSystemRepresentation], NULL, &attr, argv, env);
1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    } else
1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        execve([executable fileSystemRepresentation], argv, env);
136563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
137563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic NSBundle *locateSafariBundle()
139563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
140563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSArray *applicationDirectories = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSAllDomainsMask, YES);
141563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSEnumerator *e = [applicationDirectories objectEnumerator];
142563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSString *applicationDirectory;
1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while ((applicationDirectory = [e nextObject])) {
144563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        NSString *possibleSafariPath = [applicationDirectory stringByAppendingPathComponent:@"Safari.app"];
145563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        NSBundle *possibleSafariBundle = [NSBundle bundleWithPath:possibleSafariPath];
146563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if ([[possibleSafariBundle bundleIdentifier] isEqualToString:@"com.apple.Safari"])
147563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            return possibleSafariBundle;
148563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
149563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
150563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    CFURLRef safariURL = nil;
151563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    OSStatus err = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.Safari"), nil, nil, &safariURL);
152563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (err != noErr)
153563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        displayErrorAndQuit(@"Unable to locate Safari", @"Nightly builds of WebKit require Safari to run.  Please check that it is available and then try again.");
154563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
155563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSBundle *safariBundle = [NSBundle bundleWithPath:[(NSURL *)safariURL path]];
156563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    CFRelease(safariURL);
157563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return safariBundle;
158563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
159563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic NSString *currentMacOSXVersion()
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SInt32 version;
1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (Gestalt(gestaltSystemVersion, &version) != noErr)
1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return @"10.4";
1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return [NSString stringWithFormat:@"%x.%x", (version & 0xFF00) >> 8, (version & 0x00F0) >> 4];
1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
169d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic NSString *fallbackMacOSXVersion(NSString *systemVersion)
170d0825bca7fe65beaee391d30da42e937db621564Steve Block{
171d0825bca7fe65beaee391d30da42e937db621564Steve Block    NSDictionary *fallbackVersionMap = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"FallbackSystemVersions"];
172d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!fallbackVersionMap)
173d0825bca7fe65beaee391d30da42e937db621564Steve Block        return nil;
174d0825bca7fe65beaee391d30da42e937db621564Steve Block    NSString *fallbackSystemVersion = [fallbackVersionMap objectForKey:systemVersion];
175d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!fallbackSystemVersion || ![fallbackSystemVersion isKindOfClass:[NSString class]])
176d0825bca7fe65beaee391d30da42e937db621564Steve Block        return nil;
177d0825bca7fe65beaee391d30da42e937db621564Steve Block    return fallbackSystemVersion;
178d0825bca7fe65beaee391d30da42e937db621564Steve Block}
179d0825bca7fe65beaee391d30da42e937db621564Steve Block
1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic BOOL checkFrameworkPath(NSString *frameworkPath)
1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    BOOL isDirectory = NO;
1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return [[NSFileManager defaultManager] fileExistsAtPath:frameworkPath isDirectory:&isDirectory] && isDirectory;
1840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic BOOL checkSafariVersion(NSBundle *safariBundle)
1870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSString *safariBundleVersion = [[safariBundle infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey];
1890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSString *majorComponent = [[safariBundleVersion componentsSeparatedByString:@"."] objectAtIndex:0];
1900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSString *majorVersion = [majorComponent substringFromIndex:[majorComponent length] - 3];
1910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return [majorVersion intValue] >= 530;
1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
194563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkint main(int argc, char *argv[])
195563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark{
196563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSString *systemVersion = currentMacOSXVersion();
1990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSString *frameworkPath = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:systemVersion];
200563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
201d0825bca7fe65beaee391d30da42e937db621564Steve Block    BOOL frameworkPathIsUsable = checkFrameworkPath(frameworkPath);
2020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
203d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!frameworkPathIsUsable) {
204d0825bca7fe65beaee391d30da42e937db621564Steve Block        NSString *fallbackSystemVersion = fallbackMacOSXVersion(systemVersion);
205d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (fallbackSystemVersion) {
206d0825bca7fe65beaee391d30da42e937db621564Steve Block            frameworkPath = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:fallbackSystemVersion];
207d0825bca7fe65beaee391d30da42e937db621564Steve Block            frameworkPathIsUsable = checkFrameworkPath(frameworkPath);
208d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
209d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
210d0825bca7fe65beaee391d30da42e937db621564Steve Block
211d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!frameworkPathIsUsable)
2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        displayErrorAndQuit([NSString stringWithFormat:@"Mac OS X %@ is not supported", systemVersion],
2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            [NSString stringWithFormat:@"Nightly builds of WebKit are not supported on Mac OS X %@ at this time.", systemVersion]);
2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
215d0825bca7fe65beaee391d30da42e937db621564Steve Block    NSString *pathToEnablerLib = [[NSBundle mainBundle] pathForResource:@"WebKitNightlyEnabler" ofType:@"dylib"];
216d0825bca7fe65beaee391d30da42e937db621564Steve Block
217d0825bca7fe65beaee391d30da42e937db621564Steve Block    NSBundle *safariBundle = locateSafariBundle();
218d0825bca7fe65beaee391d30da42e937db621564Steve Block    NSString *executablePath = [safariBundle executablePath];
219d0825bca7fe65beaee391d30da42e937db621564Steve Block
2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!checkSafariVersion(safariBundle)) {
2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        NSString *safariVersion = [[safariBundle localizedInfoDictionary] objectForKey:@"CFBundleShortVersionString"];
2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        displayErrorAndQuit([NSString stringWithFormat:@"Safari %@ is not supported", safariVersion],
2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            [NSString stringWithFormat:@"Nightly builds of WebKit are not supported with Safari %@ at this time. Please update to a newer version of Safari.", safariVersion]);
2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
225563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
226563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if ([frameworkPath rangeOfString:@":"].location != NSNotFound ||
227563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [pathToEnablerLib rangeOfString:@":"].location != NSNotFound)
228563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        displayErrorAndQuit(@"Unable to launch Safari",
229563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                            @"WebKit is located at a path containing an unsupported character.  Please move WebKit to a different location and try again.");
2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSMutableArray *arguments = [NSMutableArray arrayWithObject:executablePath];
2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    NSMutableDictionary *environment = [[[NSDictionary dictionaryWithObjectsAndKeys:frameworkPath, @"DYLD_FRAMEWORK_PATH", @"YES", @"WEBKIT_UNSET_DYLD_FRAMEWORK_PATH",
2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                                                                    pathToEnablerLib, @"DYLD_INSERT_LIBRARIES", [[NSBundle mainBundle] executablePath], @"WebKitAppPath", nil] mutableCopy] autorelease];
2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    [environment addEntriesFromDictionary:[[NSProcessInfo processInfo] environment]];
235563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    addStartPageToArgumentsIfNeeded(arguments);
236563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
237563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    while (*++argv)
238563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        [arguments addObject:[NSString stringWithUTF8String:*argv]];
239563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
240563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    myExecve(executablePath, arguments, environment);
241563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
242563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    char *error = strerror(errno);
243563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    NSString *errorMessage = [NSString stringWithFormat:@"Launching Safari at %@ failed with the error '%s' (%d)", [safariBundle bundlePath], error, errno];
244563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    displayErrorAndQuit(@"Unable to launch Safari", errorMessage);
245563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
246563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    [pool release];
247563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return 0;
248563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
249