• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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