From 7662270b169d52077a6d8c3a17b33bd1eccc6f5a Mon Sep 17 00:00:00 2001 From: mjs Date: Thu, 6 Apr 2006 04:14:24 +0000 Subject: [PATCH] Reviewed by Darin, landed by Maciej. * BuildSlaveSupport/build-launcher-app: Added. Builds WebKit.app from WebKitLauncher and bundles the WebKit frameworks inside it. * BuildSlaveSupport/build-launcher-dmg: Added. Builds, and optionally uploads, a disk image containing WebKit.app. * BuildSlaveSupport/run-performance-tests: Use currentSVNRevision. * Scripts/webkitdirs.pm: Add currentSVNRevision to retrieve the revision number of the SVN working copy. * WebKitLauncher: Added. * WebKitLauncher/Info.plist: Added. * WebKitLauncher/WebKitLauncher.xcodeproj: Added. * WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj: Added. * WebKitLauncher/WebKitNightlyEnabler.m: Added. This makes up the WebKitNightlyEnabler dylib which is loaded into Safari's address space to cause LaunchServices to treat Safari.app as WebKit.app when it is run from the nightly launcher. * WebKitLauncher/main.m: Added. The WebKit.app launcher. It sets up the environment to have Safari use the bundled frameworks and load the WebKitNightlyEnabler dylib before exec'ing Safari * WebKitLauncher/start.html: Added. * WebKitLauncher/webkit.icns: Added. git-svn-id: https://svn.webkit.org/repository/webkit/trunk@13710 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- .../BuildSlaveSupport/build-launcher-app | 80 +++ .../BuildSlaveSupport/build-launcher-dmg | 111 ++++ .../BuildSlaveSupport/run-performance-tests | 8 +- WebKitTools/ChangeLog | 25 + WebKitTools/Scripts/webkitdirs.pm | 21 +- WebKitTools/WebKitLauncher/Info.plist | 482 ++++++++++++++++++ .../WebKitLauncher.xcodeproj/project.pbxproj | 392 ++++++++++++++ .../WebKitLauncher/WebKitNightlyEnabler.m | 168 ++++++ WebKitTools/WebKitLauncher/main.m | 147 ++++++ WebKitTools/WebKitLauncher/start.html | 10 + WebKitTools/WebKitLauncher/webkit.icns | Bin 0 -> 56937 bytes 11 files changed, 1436 insertions(+), 8 deletions(-) create mode 100644 WebKitTools/BuildSlaveSupport/build-launcher-app create mode 100644 WebKitTools/BuildSlaveSupport/build-launcher-dmg create mode 100644 WebKitTools/WebKitLauncher/Info.plist create mode 100644 WebKitTools/WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj create mode 100644 WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m create mode 100644 WebKitTools/WebKitLauncher/main.m create mode 100644 WebKitTools/WebKitLauncher/start.html create mode 100644 WebKitTools/WebKitLauncher/webkit.icns diff --git a/WebKitTools/BuildSlaveSupport/build-launcher-app b/WebKitTools/BuildSlaveSupport/build-launcher-app new file mode 100644 index 000000000000..395b6253d3fd --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build-launcher-app @@ -0,0 +1,80 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2006 Mark Rowe . 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. + +# Creates the launcher WebKit.app with bundled frameworks. + +use strict; + +use FindBin; +use lib "$FindBin::Bin/../Scripts"; +use webkitdirs; + +my @xcodeBuildArguments = XcodeOptions(); +my $nightlyLauncherTemplatePath = "$FindBin::Bin/../WebKitLauncher"; +my $nightlyLauncherStagingPath = productDir() . "/WebKit.app"; + +sub buildNightlyLauncher +{ + chdir($nightlyLauncherTemplatePath); + system("xcodebuild", "clean", @xcodeBuildArguments) == 0 or die "Failed cleaning WebKitLauncher project"; + system("xcodebuild", @xcodeBuildArguments) == 0 or die "Failed building WebKitLauncher project"; + chdirWebKit(); +} + +sub copyNightlyLauncher +{ + my $revision = currentSVNRevision(); + my $infoPlist = "$nightlyLauncherStagingPath/Contents/Info.plist"; + my $data; + open(IN, $infoPlist) or die "Couldn't open Info.plist in built application for reading"; + { + undef $/; + $data = ; + } + close(IN); + open(OUT, ">$infoPlist") or die "Couldn't open Info.plist in built application for writing"; + $data =~ s/VERSION/$revision/g; + print OUT $data; + close(OUT); + + my @frameworks = ("JavaScriptCore", "JavaScriptGlue", "WebCore", "WebKit"); + for my $framework (@frameworks) { + system("ditto", productDir() . "/$framework.framework", "$nightlyLauncherStagingPath/Contents/Resources/$framework.framework") == 0 or die "Failed copying $framework.framework into $nightlyLauncherStagingPath"; + } +} + +chdirWebKit(); +buildNightlyLauncher(); +copyNightlyLauncher(); + +Property changes on: WebKitTools/BuildSlaveSupport/build-launcher-app +___________________________________________________________________ +Name: svn:executable + + * + diff --git a/WebKitTools/BuildSlaveSupport/build-launcher-dmg b/WebKitTools/BuildSlaveSupport/build-launcher-dmg new file mode 100644 index 000000000000..51eaec3f570a --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build-launcher-dmg @@ -0,0 +1,111 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2006 Mark Rowe . 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. + +# Script used by build slaves to create a disk-image containing WebKit.app. + +use strict; + +use File::Basename; +use Getopt::Long; +use FindBin; +use lib "$FindBin::Bin/../Scripts"; +use webkitdirs; + +my $nightlyLauncherStagingPath = productDir() . "/WebKit.app"; +my $nightlyLauncherDiskImagePath; + +my $nightlyRemoteHost = 'webkit-nightlies@nightly.webkit.org'; +my $nightlyRemotePath = "/home/webkit-nightlies"; +my $nightlyRemoteLatestPath = "$nightlyRemotePath/update-latest.sh"; + +sub buildDiskImage +{ + my $revision = currentSVNRevision(); + my $productDir = productDir(); + $nightlyLauncherDiskImagePath = productDir() . "/WebKit-SVN-r$revision.dmg"; + + print "Creating disk image...\n"; + my $output = `hdiutil create \"$nightlyLauncherDiskImagePath\" -ov -megabytes 50 -fs HFS+ -volname \"WebKit\"`; + die "Creating disk image failed" if $?; + + $output = `hdiutil attach \"$nightlyLauncherDiskImagePath\"`; + die "Mounting disk image failed" if $?; + + my ($mountedDevice) = ($output =~ /(\/dev\/.+?)\s*Apple_partition_scheme/im); + my ($mountedPath) = ($output =~ /Apple_HFS\s+(.+?)\s*$/im); + + print "Copying files to disk image...\n"; + system("ditto", $nightlyLauncherStagingPath, "$mountedPath/WebKit.app") == 0 or die "Failed copying $nightlyLauncherStagingPath to $mountedPath"; + + system("hdiutil", "detach", "-quiet", $mountedDevice) == 0 or die "Unmounting disk image failed"; + + print "Compressing disk image...\n"; + system("mv", "-f", $nightlyLauncherDiskImagePath, "$nightlyLauncherDiskImagePath.uncompressed") == 0 or die "Renaming disk image failed"; + system("hdiutil", "convert", "-quiet", "$nightlyLauncherDiskImagePath.uncompressed", "-format", "UDZO", "-imagekey", "zlib-level=9", "-o", "$nightlyLauncherDiskImagePath"); + die "Compressing disk image failed" if $?; + + unlink "$nightlyLauncherDiskImagePath.uncompressed"; +} + +sub uploadNightlyDiskImage +{ + my $nightlyRemoteDiskImagePath = "$nightlyRemotePath/builds/" . basename($nightlyLauncherDiskImagePath); + system("rsync", "-vP", $nightlyLauncherDiskImagePath, "$nightlyRemoteHost:$nightlyRemoteDiskImagePath") == 0 or die "Failed uploading disk image"; + system("ssh", $nightlyRemoteHost, $nightlyRemoteLatestPath, $nightlyRemoteDiskImagePath) == 0 or die "Failed linking disk image to latest"; +} + +sub uploadBuildSlaveDiskImage +{ + my $remoteDiskImagePath = shift(@_) . basename($nightlyLauncherDiskImagePath); + system("rsync", "-vP", $nightlyLauncherDiskImagePath, $remoteDiskImagePath) == 0 or die "Failed uploading disk image"; +} + + +my $uploadTo; +my $nightlyBuild = 0; +GetOptions('upload-to-host=s' => \$uploadTo, + 'upload-as-nightly!' => \$nightlyBuild); + +chdirWebKit(); +buildDiskImage(); + +if ($nightlyBuild) { + uploadNightlyDiskImage(); +} elsif ($uploadTo) { + uploadBuildSlaveDiskImage($uploadTo); +} else { + print "Disk image left at $nightlyLauncherDiskImagePath\n"; +} + + +Property changes on: WebKitTools/BuildSlaveSupport/build-launcher-dmg +___________________________________________________________________ +Name: svn:executable + + * + diff --git a/WebKitTools/BuildSlaveSupport/run-performance-tests b/WebKitTools/BuildSlaveSupport/run-performance-tests index 20a518d4d7b1..5d6ea44e5de8 100755 --- a/WebKitTools/BuildSlaveSupport/run-performance-tests +++ b/WebKitTools/BuildSlaveSupport/run-performance-tests @@ -63,14 +63,8 @@ my $sock = new IO::Socket::INET(LocalHost => $perfMaster, Reuse => 1); die "Could not create socket for port $reportPort: $!\n" unless $sock; -print "Determining source version...\n"; -chdirWebKit(); -my $svnInfo = `svn info .`; -my ($revision) = ($svnInfo =~ m/Revision: (\d+)/g); -die "Failed to determine svn revision!\n" unless (defined $revision); - print "Starting performance tests on PLT slave...\n"; -die "Failed to start slave!\n" unless (system("ssh", $userAndHost, "autovicki", $slaveDirectory, "--safari", "$slaveDirectory/Safari.app", "--count", 5, "--clean-exit", "--webkit-revision", $revision, "--show-results", "send-completed-results.command") == 0); +die "Failed to start slave!\n" unless (system("ssh", $userAndHost, "autovicki", $slaveDirectory, "--safari", "$slaveDirectory/Safari.app", "--count", 5, "--clean-exit", "--webkit-revision", currentSVNRevision(), "--show-results", "send-completed-results.command") == 0); print "Waiting for PLT slave to respond...\n"; my $new_sock = $sock->accept(); diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog index aaa5c3245876..1575ac87b21a 100644 --- a/WebKitTools/ChangeLog +++ b/WebKitTools/ChangeLog @@ -1,3 +1,28 @@ +2006-04-06 Mark Rowe + + Reviewed by Darin, landed by Maciej. + + * BuildSlaveSupport/build-launcher-app: Added. Builds WebKit.app from WebKitLauncher + and bundles the WebKit frameworks inside it. + * BuildSlaveSupport/build-launcher-dmg: Added. Builds, and optionally uploads, a disk image + containing WebKit.app. + * BuildSlaveSupport/run-performance-tests: Use currentSVNRevision. + * Scripts/webkitdirs.pm: Add currentSVNRevision to retrieve the revision + number of the SVN working copy. + * WebKitLauncher: Added. + * WebKitLauncher/Info.plist: Added. + * WebKitLauncher/WebKitLauncher.xcodeproj: Added. + * WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj: Added. + * WebKitLauncher/WebKitNightlyEnabler.m: Added. This makes + up the WebKitNightlyEnabler dylib which is loaded into Safari's address space + to cause LaunchServices to treat Safari.app as WebKit.app when it is run from + the nightly launcher. + * WebKitLauncher/main.m: Added. The WebKit.app launcher. + It sets up the environment to have Safari use the bundled frameworks + and load the WebKitNightlyEnabler dylib before exec'ing Safari + * WebKitLauncher/start.html: Added. + * WebKitLauncher/webkit.icns: Added. + 2006-04-05 Darin Adler Reviewed by Maciej. diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm index 409ddc34da1e..a2191f4774eb 100644 --- a/WebKitTools/Scripts/webkitdirs.pm +++ b/WebKitTools/Scripts/webkitdirs.pm @@ -35,7 +35,7 @@ BEGIN { our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); $VERSION = 1.00; @ISA = qw(Exporter); - @EXPORT = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks); + @EXPORT = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks ¤tSVNRevision); %EXPORT_TAGS = ( ); @EXPORT_OK = (); } @@ -47,6 +47,8 @@ my @baseProductDirOption; my $configuration; my $configurationProductDir; my $sourceDir; +my $currentSVNRevision; + # Variables for Win32 support my $devenvPath; @@ -133,6 +135,17 @@ sub determineConfigurationProductDir $configurationProductDir = "$baseProductDir/$configuration"; } +sub determineCurrentSVNRevision +{ + return if defined $currentSVNRevision; + determineSourceDir(); + my $svnInfo = `svn info $sourceDir | grep Revision:`; + ($currentSVNRevision) = ($svnInfo =~ m/Revision: (\d+).*/g); + die "Unable to determine current SVN revision in $sourceDir" unless (defined $currentSVNRevision); + return $currentSVNRevision; +} + + sub chdirWebKit { determineSourceDir(); @@ -157,6 +170,12 @@ sub configuration() return $configuration; } +sub currentSVNRevision +{ + determineCurrentSVNRevision(); + return $currentSVNRevision; +} + sub XcodeOptions { determineBaseProductDir(); diff --git a/WebKitTools/WebKitLauncher/Info.plist b/WebKitTools/WebKitLauncher/Info.plist new file mode 100644 index 000000000000..5ab5bd9199df --- /dev/null +++ b/WebKitTools/WebKitLauncher/Info.plist @@ -0,0 +1,482 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + css + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + text/css + + CFBundleTypeName + CSS style sheet + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + pdf + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + application/pdf + + CFBundleTypeName + PDF document + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + webarchive + + CFBundleTypeIconFile + webarchive.icns + CFBundleTypeMIMETypes + + application/x-webarchive + + CFBundleTypeName + Web archive + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + syndarticle + + CFBundleTypeIconFile + document.icns + CFBundleTypeName + RSS article + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + webbookmark + + CFBundleTypeIconFile + document.icns + CFBundleTypeName + Safari bookmark + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + webloc + + CFBundleTypeIconFile + document.icns + CFBundleTypeName + Web internet location + CFBundleTypeOSTypes + + ilht + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + download + + CFBundleTypeIconFile + download10.icns + CFBundleTypeName + Safari download + CFBundleTypeRole + Editor + LSTypeIsPackage + + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + gif + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + image/gif + + CFBundleTypeName + GIF image + CFBundleTypeOSTypes + + GIFf + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + html + htm + shtml + jhtml + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + text/html + + CFBundleTypeName + HTML document + CFBundleTypeOSTypes + + HTML + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + js + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + application/x-javascript + + CFBundleTypeName + JavaScript script + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + jpg + jpeg + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + image/jpeg + + CFBundleTypeName + JPEG image + CFBundleTypeOSTypes + + JPEG + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + jp2 + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + image/jp2 + + CFBundleTypeName + JPEG 2000 image + CFBundleTypeOSTypes + + jp2 + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + txt + text + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + text/plain + + CFBundleTypeName + Plain text document + CFBundleTypeOSTypes + + TEXT + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + png + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + image/png + + CFBundleTypeName + PNG image + CFBundleTypeOSTypes + + PNGf + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + rtf + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + application/rtf + + CFBundleTypeName + Rich Text Format (RTF) document + CFBundleTypeOSTypes + + RTF + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + tiff + tif + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + image/tiff + + CFBundleTypeName + TIFF image + CFBundleTypeOSTypes + + TIFF + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + url + + CFBundleTypeIconFile + document.icns + CFBundleTypeName + Web site location + CFBundleTypeOSTypes + + LINK + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + ico + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + image/x-icon + + CFBundleTypeName + Windows icon image + CFBundleTypeOSTypes + + ICO + + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + xhtml + xhtm + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + application/xhtml+xml + + CFBundleTypeName + XHTML document + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleTypeExtensions + + xml + xbl + xsl + xslt + + CFBundleTypeIconFile + document.icns + CFBundleTypeMIMETypes + + application/xml + text/xml + + CFBundleTypeName + XML document + CFBundleTypeRole + Viewer + NSDocumentClass + BrowserDocument + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + webkit.icns + CFBundleIdentifier + org.webkit.nightly.WebKit + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + wbkt + CFBundleVersion + VERSION + NSPrincipalClass + BrowserApplication + + CFBundleHelpBookFolder + SafariHelp + CFBundleHelpBookName + Safari Help + CFBundleURLTypes + + + CFBundleURLName + Web site URL + CFBundleURLSchemes + + http + https + + + + CFBundleURLName + local file URL + CFBundleURLSchemes + + file + + + + CFBundleURLName + RSS URL + CFBundleURLSchemes + + feed + feeds + feedsearch + + + + NSAppleScriptEnabled + Yes + UTExportedTypeDeclarations + + + UTTypeConformsTo + public.data + UTTypeDescription + Safari bookmark + UTTypeIdentifier + com.apple.safari.bookmark + UTTypeTagSpecification + + public.filename-extension + + webbookmark + + + + + + + diff --git a/WebKitTools/WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj b/WebKitTools/WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..f8e7d533e5f6 --- /dev/null +++ b/WebKitTools/WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj @@ -0,0 +1,392 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 5D4DF982097F89FB0083D5E5 /* start.html in Resources */ = {isa = PBXBuildFile; fileRef = 5D4DF981097F89FB0083D5E5 /* start.html */; }; + 5D650F3609DB8B370075E9A8 /* WebKitNightlyEnabler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D650F3509DB8B370075E9A8 /* WebKitNightlyEnabler.m */; }; + 5D650F3A09DB8B410075E9A8 /* WebKitNightlyEnabler.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 5D650F3409DB8B280075E9A8 /* WebKitNightlyEnabler.dylib */; }; + 5D650F7609DB8CB40075E9A8 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D650F7509DB8CB40075E9A8 /* CoreFoundation.framework */; }; + 5DB70525097B94CD009875EC /* webkit.icns in Resources */ = {isa = PBXBuildFile; fileRef = 5DB70524097B94CD009875EC /* webkit.icns */; }; + 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXBuildStyle section */ + 4A9504CCFFE6A4B311CA0CBA /* Debug */ = { + isa = PBXBuildStyle; + buildSettings = { + }; + name = Debug; + }; + 4A9504CDFFE6A4B311CA0CBA /* Release */ = { + isa = PBXBuildStyle; + buildSettings = { + }; + name = Release; + }; +/* End PBXBuildStyle section */ + +/* Begin PBXContainerItemProxy section */ + 5D650F4409DB8B830075E9A8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5D650F3309DB8B280075E9A8; + remoteInfo = WebKitNightlyEnabler; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 5D4DF981097F89FB0083D5E5 /* start.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html; path = start.html; sourceTree = ""; }; + 5D650F3409DB8B280075E9A8 /* WebKitNightlyEnabler.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = WebKitNightlyEnabler.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D650F3509DB8B370075E9A8 /* WebKitNightlyEnabler.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = WebKitNightlyEnabler.m; sourceTree = ""; }; + 5D650F7509DB8CB40075E9A8 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + 5DB70524097B94CD009875EC /* webkit.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = webkit.icns; sourceTree = ""; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8D1107320486CEB800E47090 /* WebKit.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = WebKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5D650F3209DB8B280075E9A8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D650F7609DB8CB40075E9A8 /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D11072E0486CEB800E47090 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + ); + name = Classes; + sourceTree = ""; + }; + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 5D650F7509DB8CB40075E9A8 /* CoreFoundation.framework */, + 29B97324FDCFA39411CA2CEA /* AppKit.framework */, + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, + 29B97325FDCFA39411CA2CEA /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D1107320486CEB800E47090 /* WebKit.app */, + 5D650F3409DB8B280075E9A8 /* WebKitNightlyEnabler.dylib */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* WebKit */ = { + isa = PBXGroup; + children = ( + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = WebKit; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 5D650F3509DB8B370075E9A8 /* WebKitNightlyEnabler.m */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 5D4DF981097F89FB0083D5E5 /* start.html */, + 5DB70524097B94CD009875EC /* webkit.icns */, + 8D1107310486CEB800E47090 /* Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 5D650F3009DB8B280075E9A8 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 5D650F3309DB8B280075E9A8 /* WebKitNightlyEnabler */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5D650F3709DB8B370075E9A8 /* Build configuration list for PBXNativeTarget "WebKitNightlyEnabler" */; + buildPhases = ( + 5D650F3009DB8B280075E9A8 /* Headers */, + 5D650F3109DB8B280075E9A8 /* Sources */, + 5D650F3209DB8B280075E9A8 /* Frameworks */, + ); + buildRules = ( + ); + buildSettings = { + EXECUTABLE_PREFIX = lib; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/lib; + PREBINDING = NO; + PRODUCT_NAME = WebKitNightlyEnabler; + ZERO_LINK = YES; + }; + dependencies = ( + ); + name = WebKitNightlyEnabler; + productName = WebKitNightlyEnabler; + productReference = 5D650F3409DB8B280075E9A8 /* WebKitNightlyEnabler.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; + 8D1107260486CEB800E47090 /* WebKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "WebKit" */; + buildPhases = ( + 8D1107290486CEB800E47090 /* Resources */, + 8D11072C0486CEB800E47090 /* Sources */, + 8D11072E0486CEB800E47090 /* Frameworks */, + ); + buildRules = ( + ); + buildSettings = { + }; + dependencies = ( + 5D650F4509DB8B830075E9A8 /* PBXTargetDependency */, + ); + name = WebKit; + productInstallPath = "$(HOME)/Applications"; + productName = WebKit; + productReference = 8D1107320486CEB800E47090 /* WebKit.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NightlyLauncher" */; + buildSettings = { + }; + buildStyles = ( + 4A9504CCFFE6A4B311CA0CBA /* Debug */, + 4A9504CDFFE6A4B311CA0CBA /* Release */, + ); + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* WebKit */; + projectDirPath = ""; + targets = ( + 8D1107260486CEB800E47090 /* WebKit */, + 5D650F3309DB8B280075E9A8 /* WebKitNightlyEnabler */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D1107290486CEB800E47090 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D650F3A09DB8B410075E9A8 /* WebKitNightlyEnabler.dylib in Resources */, + 5DB70525097B94CD009875EC /* webkit.icns in Resources */, + 5D4DF982097F89FB0083D5E5 /* start.html in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5D650F3109DB8B280075E9A8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D650F3609DB8B370075E9A8 /* WebKitNightlyEnabler.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D11072C0486CEB800E47090 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072D0486CEB800E47090 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 5D650F4509DB8B830075E9A8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5D650F3309DB8B280075E9A8 /* WebKitNightlyEnabler */; + targetProxy = 5D650F4409DB8B830075E9A8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 5D650F3809DB8B370075E9A8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + MACOSX_DEPLOYMENT_TARGET_ppc = 10.4; + PRODUCT_NAME = WebKitNightlyEnabler; + SDKROOT_ppc = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Debug; + }; + 5D650F3909DB8B370075E9A8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + MACOSX_DEPLOYMENT_TARGET_ppc = 10.4; + PRODUCT_NAME = WebKitNightlyEnabler; + SDKROOT_ppc = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Release; + }; + C01FCF4B08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DEBUGGING_SYMBOLS = full; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = WebKit; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + C01FCF4C08A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEAD_CODE_STRIPPING = YES; + DEPLOYMENT_POSTPROCESSING = YES; + GCC_DEBUGGING_SYMBOLS = full; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + INFOPLIST_FILE = Info.plist; + PRODUCT_NAME = WebKit; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.2; + MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; + MACOSX_DEPLOYMENT_TARGET_ppc = 10.2; + PREBINDING = NO; + SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk; + SDKROOT_ppc = /Developer/SDKs/MacOSX10.2.8.sdk; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; + MACOSX_DEPLOYMENT_TARGET_ppc = 10.2; + PREBINDING = NO; + SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk; + SDKROOT_ppc = /Developer/SDKs/MacOSX10.2.8.sdk; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5D650F3709DB8B370075E9A8 /* Build configuration list for PBXNativeTarget "WebKitNightlyEnabler" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D650F3809DB8B370075E9A8 /* Debug */, + 5D650F3909DB8B370075E9A8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "WebKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4B08A954540054247B /* Debug */, + C01FCF4C08A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "NightlyLauncher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m b/WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m new file mode 100644 index 000000000000..589826736ddf --- /dev/null +++ b/WebKitTools/WebKitLauncher/WebKitNightlyEnabler.m @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 +#include +#include +#include +#include +#include + +static void cleanUpAfterOurselves(void) __attribute__ ((constructor)); + +void *symbol_lookup(char *symbol); + +void cleanUpAfterOurselves(void) +{ + char **args = *(char***)_NSGetArgv(); + char **procPath = symbol_lookup("___CFProcessPath"); + char *procPathBackup = *procPath; + *procPath = args[0]; + CFBundleGetMainBundle(); + *procPath = procPathBackup; + unsetenv("DYLD_INSERT_LIBRARIES"); + unsetenv("CFProcessPath"); +} + +#if __LP64__ +#define LC_SEGMENT_COMMAND LC_SEGMENT_64 +#define macho_header mach_header_64 +#define macho_segment_command segment_command_64 +#define macho_section section_64 +#define getsectdatafromheader getsectdatafromheader_64 +#define macho_nlist nlist_64 +#else +#define LC_SEGMENT_COMMAND LC_SEGMENT +#define macho_header mach_header +#define macho_segment_command segment_command +#define macho_section section +#define macho_nlist nlist +#endif + +void *GDSymbolLookup(const struct macho_header *header, const char *symbol); + +void *symbol_lookup(char *symbol) +{ + int i; + for(i=0;i<_dyld_image_count();i++) + { + void *symbolResult = GDSymbolLookup((const struct macho_header*)_dyld_get_image_header(i), symbol); + if (symbolResult) + return symbolResult; + } + return NULL; +} + +void *GDSymbolLookup(const struct macho_header *header, const char *symbol) +{ + if (!header || !symbol) + return NULL; + if ((header->magic != MH_MAGIC) && (header->magic != MH_MAGIC_64)) + return NULL; + + uint32_t currCommand; + const struct load_command *loadCommand = (const struct load_command *)( ((void *)header) + sizeof(struct macho_header)); + const struct macho_segment_command *segCommand; + + const struct symtab_command *symtabCommand = NULL; + const struct dysymtab_command *dysymtabCommand = NULL; + const struct macho_segment_command *textSegment = NULL; + const struct macho_segment_command *linkEditSegment = NULL; + + for (currCommand = 0; currCommand < header->ncmds; currCommand++) + { + switch (loadCommand->cmd) + { + case LC_SEGMENT_COMMAND: + segCommand = (const struct macho_segment_command *)loadCommand; + if (strcmp(segCommand->segname, "__TEXT")==0) + textSegment = segCommand; + else if (strcmp(segCommand->segname, "__LINKEDIT")==0) + linkEditSegment = segCommand; + break; + + case LC_SYMTAB: + symtabCommand = (const struct symtab_command *)loadCommand; + break; + + case LC_DYSYMTAB: + dysymtabCommand = (const struct dysymtab_command *)loadCommand; + break; + } + + loadCommand = (const struct load_command *)(((void*)loadCommand) + loadCommand->cmdsize); + } + if (textSegment==NULL || linkEditSegment==NULL || symtabCommand==NULL || dysymtabCommand==NULL) { + return NULL; + } + + typedef enum { Start = 0, LocalSymbols, ExternalSymbols, Done } SymbolSearchState; + uint32_t currentSymbolIndex; + uint32_t maximumSymbolIndex; + SymbolSearchState state; + + for (state = Start + 1; state < Done; state++) + { + switch(state) { + case LocalSymbols: + currentSymbolIndex = dysymtabCommand->ilocalsym; + maximumSymbolIndex = dysymtabCommand->ilocalsym + dysymtabCommand->nlocalsym; + break; + + case ExternalSymbols: + currentSymbolIndex = dysymtabCommand->iextdefsym; + maximumSymbolIndex = dysymtabCommand->nextdefsym; + break; + + default: + return NULL; + } + for (; currentSymbolIndex < maximumSymbolIndex; currentSymbolIndex++) + { + const struct macho_nlist *symbolTableEntry; + symbolTableEntry = (const struct macho_nlist *)(currentSymbolIndex*sizeof(struct macho_nlist) + + (ptrdiff_t)header + symtabCommand->symoff + + linkEditSegment->vmaddr - linkEditSegment->fileoff + - textSegment->vmaddr); + int32_t stringTableIndex = symbolTableEntry->n_un.n_strx; + if (stringTableIndex<0) + continue; + const char *stringTableEntry = (const char*)(stringTableIndex + (ptrdiff_t)header + symtabCommand->stroff + + linkEditSegment->vmaddr - linkEditSegment->fileoff + - textSegment->vmaddr); + if (strcmp(symbol, stringTableEntry)==0) { + return ((void*)header) - textSegment->vmaddr + symbolTableEntry->n_value; + } + } + state++; + } + return NULL; +} + + diff --git a/WebKitTools/WebKitLauncher/main.m b/WebKitTools/WebKitLauncher/main.m new file mode 100644 index 000000000000..7167d32f795c --- /dev/null +++ b/WebKitTools/WebKitLauncher/main.m @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Mark Rowe. 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 +#import + +void displayErrorAndQuit(NSString *title, NSString *message) +{ + NSApplicationLoad(); + NSRunCriticalAlertPanel(title, message, @"Quit", nil, nil); + exit(0); +} + +void checkMacOSXVersion() +{ + long versionNumber = 0; + OSErr error = Gestalt(gestaltSystemVersion, &versionNumber); + if (error != noErr || versionNumber < 0x1040) + displayErrorAndQuit(@"Mac OS X 10.4 is Required", @"Nightly builds of WebKit require Mac OS X 10.4 or newer."); +} + +int getLastVersionShown() +{ + [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObject:@"-1" forKey:@"StartPageShownInVersion"]]; + return [[NSUserDefaults standardUserDefaults] integerForKey:@"StartPageShownInVersion"]; +} + +void saveLastVersionShown(int lastVersion) +{ + [[NSUserDefaults standardUserDefaults] setInteger:lastVersion forKey:@"StartPageShownInVersion"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +NSString *getPathForStartPage() +{ + return [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"start.html"]; +} + +int getShowStartPageVersion() +{ + return getCurrentVersion() + 1; +} + +int getCurrentVersion() +{ + return [[[[NSBundle mainBundle] infoDictionary] valueForKey:(NSString *)kCFBundleVersionKey] intValue]; +} + +BOOL startPageDisabled() +{ + return [[NSUserDefaults standardUserDefaults] boolForKey:@"StartPageDisabled"]; +} + +void addStartPageToArgumentsIfNeeded(NSMutableArray *arguments) +{ + if (startPageDisabled()) + return; + + if (getLastVersionShown() < getShowStartPageVersion()) { + saveLastVersionShown(getCurrentVersion()); + NSString *startPagePath = getPathForStartPage(); + if (startPagePath) + [arguments addObject:startPagePath]; + } +} + +static void myExecve(NSString *executable, NSArray *args, NSDictionary *environment) +{ + char **argv = (char **)calloc(sizeof(char *), [args count] + 1); + char **env = (char **)calloc(sizeof(char *), [environment count] + 1); + + NSEnumerator *e = [args objectEnumerator]; + NSString *s; + int i = 0; + while (s = [e nextObject]) + argv[i++] = (char *) [s UTF8String]; + + e = [environment keyEnumerator]; + i = 0; + while (s = [e nextObject]) + env[i++] = (char *) [[NSString stringWithFormat:@"%@=%@", s, [environment objectForKey:s]] UTF8String]; + + execve([executable fileSystemRepresentation], argv, env); +} + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + checkMacOSXVersion(); + + CFURLRef safariURL = nil; + OSStatus err = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("com.apple.Safari"), nil, nil, &safariURL); + if (err != noErr) + displayErrorAndQuit(@"Unable to locate Safari", @"Nightly builds of WebKit require Safari to run. Please check that it is available and then try again."); + + NSString *frameworkPath = [[NSBundle mainBundle] resourcePath]; + NSString *executablePath = [[NSBundle bundleWithPath:[(NSURL *)safariURL path]] executablePath]; + NSString *pathToEnablerLib = [[NSBundle mainBundle] pathForResource:@"WebKitNightlyEnabler" ofType:@"dylib"]; + + NSMutableArray *arguments = [NSMutableArray arrayWithObjects:executablePath, @"-WebKitDeveloperExtras", @"YES", nil]; + addStartPageToArgumentsIfNeeded(arguments); + + while (*++argv) + [arguments addObject:[NSString stringWithUTF8String:*argv]]; + + myExecve(executablePath, + arguments, + [NSDictionary dictionaryWithObjectsAndKeys:frameworkPath, @"DYLD_FRAMEWORK_PATH", + @"YES", @"WEBKIT_UNSET_DYLD_FRAMEWORK_PATH", + pathToEnablerLib, @"DYLD_INSERT_LIBRARIES", + [[NSBundle mainBundle] executablePath], @"CFProcessPath", + nil]); + + char *error = strerror(errno); + NSString *errorMessage = [NSString stringWithFormat:@"Launching Safari at %@ failed with the error '%s' (%d)", [(NSURL *)safariURL path], error, errno]; + displayErrorAndQuit(@"Unable to launch Safari", errorMessage); + + [pool release]; + return 0; +} +\ No newline at end of file diff --git a/WebKitTools/WebKitLauncher/start.html b/WebKitTools/WebKitLauncher/start.html new file mode 100644 index 000000000000..e987feafeada --- /dev/null +++ b/WebKitTools/WebKitLauncher/start.html @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/WebKitTools/WebKitLauncher/webkit.icns b/WebKitTools/WebKitLauncher/webkit.icns new file mode 100644 index 0000000000000000000000000000000000000000..bf629bfd28fb793b1d70aacc29771382cc67691b GIT binary patch literal 56937 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