diff options
Diffstat (limited to 'WebKitTools')
407 files changed, 48264 insertions, 0 deletions
diff --git a/WebKitTools/BuildSlaveSupport/build-launcher-app b/WebKitTools/BuildSlaveSupport/build-launcher-app new file mode 100755 index 0000000..79f47bf --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build-launcher-app @@ -0,0 +1,165 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2006 Mark Rowe <opendarwin.org@bdash.net.nz>. 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 Cwd 'realpath'; +use webkitdirs; +use VCSUtils; + +my $tigerProductDir = realpath("$FindBin::Bin/../../WebKitBuildTiger"); +my $leopardProductDir = realpath("$FindBin::Bin/../../WebKitBuildLeopard"); +setBaseProductDir($tigerProductDir); + +my @xcodeBuildArguments = XcodeOptions(); +unshift @xcodeBuildArguments, "SYMROOT=$tigerProductDir"; +unshift @xcodeBuildArguments, "OBJROOT=$tigerProductDir"; + +my $nightlyLauncherTemplatePath = "$FindBin::Bin/../WebKitLauncher"; +my $nightlyLauncherStagingPath = productDir() . "/WebKit.app"; +my $droseraProjectPath = "$FindBin::Bin/../Drosera/mac"; +my $droseraStagingPath = productDir() . "/DroseraLauncher.app"; + + +sub buildNightlyLauncher +{ + chdir($nightlyLauncherTemplatePath); + system("xcodebuild", "clean", "-alltargets", @xcodeBuildArguments, @ARGV) == 0 or die "Failed cleaning WebKitLauncher project"; + system("xcodebuild", @xcodeBuildArguments, @ARGV) == 0 or die "Failed building WebKitLauncher project"; + chdirWebKit(); +} + +sub currentRevision +{ + my $sourceDir = sourceDir(); + if (isSVNDirectory($sourceDir)) { + return currentSVNRevision(); + } elsif (isGitDirectory($sourceDir)) { + my $gitLog = `cd $sourceDir && LC_ALL=C git log --grep='git-svn-id: ' -n 1 | grep git-svn-id:`; + (my $revision) = ($gitLog =~ m/ +git-svn-id: .+@(\d+) /g); + return $revision; + } +} + +sub currentBranch +{ + my $sourceDir = sourceDir(); + my ($url, $branch); + if (isSVNDirectory($sourceDir)) { + my $svnInfo = `LC_ALL=C svn info $sourceDir | grep URL:`; + ($url) = ($svnInfo =~ m/URL: (.+)/g); + } elsif (isGitDirectory($sourceDir)) { + my $gitLog = `cd $sourceDir && LC_ALL=C git log --grep='git-svn-id: ' -n 1 | grep git-svn-id:`; + ($url) = ($gitLog =~ m/ +git-svn-id: (.+)@\d+ /g); + } + ($branch) = ($url =~ m/\/webkit\/(trunk|branches\/[^\/]+)/); + die "Unable to determine current SVN branch in $sourceDir" unless (defined $branch); + $branch =~ s/^branches\///; + return $branch; +} + +sub copyNightlyLauncher +{ + my $revision = currentRevision(); + my $branch = currentBranch(); + my $configuration = configuration(); + + my $infoPlist = "$nightlyLauncherStagingPath/Contents/Info.plist"; + my $versionFile = "$nightlyLauncherStagingPath/Contents/Resources/VERSION"; + my $branchFile = "$nightlyLauncherStagingPath/Contents/Resources/BRANCH"; + my $data; + open(IN, $infoPlist) or die "Couldn't open Info.plist in built application for reading"; + { + undef $/; + $data = <IN>; + } + 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); + + open(OUT, ">$versionFile") or die "Couldn't open VERSION in built application for writing"; + print OUT "$revision\n"; + close(OUT); + + open(OUT, ">$branchFile") or die "Couldn't open BRANCH in built application for writing"; + print OUT "$branch\n"; + close(OUT); + + my @frameworks = ("JavaScriptCore", "JavaScriptGlue", "WebCore", "WebKit"); + for my $framework (@frameworks) { + my $tigerFramework = "$tigerProductDir/$configuration/$framework.framework"; + my $leopardFramework = "$leopardProductDir/$configuration/$framework.framework"; + system("ditto", $tigerFramework, "$nightlyLauncherStagingPath/Contents/Frameworks/10.4/$framework.framework") == 0 or die "Failed copying $tigerFramework into $nightlyLauncherStagingPath"; + system("ditto", $leopardFramework, "$nightlyLauncherStagingPath/Contents/Frameworks/10.5/$framework.framework") == 0 or die "Failed copying $leopardFramework into $nightlyLauncherStagingPath"; + } +} + +sub buildDroseraLauncher +{ + chdir($droseraProjectPath); + system("xcodebuild", "clean", "-alltargets", @xcodeBuildArguments, @ARGV) == 0 or die "Failed cleaning Drosera project"; + # Build native platform only right now, as building universal with the 10.4u SDK cause Xcode to look for WebKit, + # WebCore & JavaScriptCore in the SDK under /Developer/SDKs/MacOSX10.4u.sdk/$(BUILT_PRODUCTS_DIR) where they do not exist + system("xcodebuild", "-alltargets", @xcodeBuildArguments, @ARGV) == 0 or die "Failed building Drosera project"; + chdirWebKit(); +} + +sub setDroseraLauncherVersion +{ + my $revision = currentRevision(); + my $infoPlist = "$droseraStagingPath/Contents/Info.plist"; + my $data; + open(IN, $infoPlist) or die "Couldn't open Info.plist in built application for reading"; + { + undef $/; + $data = <IN>; + } + 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 $b = currentBranch(); +my $r = currentRevision(); +print "Branch: ", $b, "\n"; +print "Revision: ", $r, "\n"; + +chdirWebKit(); +buildNightlyLauncher(); +copyNightlyLauncher(); +buildDroseraLauncher(); +setDroseraLauncherVersion(); diff --git a/WebKitTools/BuildSlaveSupport/build-launcher-dmg b/WebKitTools/BuildSlaveSupport/build-launcher-dmg new file mode 100755 index 0000000..ff1a22d --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build-launcher-dmg @@ -0,0 +1,136 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2006 Mark Rowe <opendarwin.org@bdash.net.nz>. 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 Cwd 'realpath'; +use webkitdirs; +use VCSUtils; + +my $tigerProductDir = realpath("$FindBin::Bin/../../WebKitBuildTiger"); +my $leopardProductDir = realpath("$FindBin::Bin/../../WebKitBuildLeopard"); +setBaseProductDir($tigerProductDir); + +my $nightlyLauncherStagingPath = productDir() . "/WebKit.app"; +my $droseraStagingPath = productDir() . "/DroseraLauncher.app"; +my $nightlyLauncherDiskImagePath; + +my $nightlyRemoteHost = 'webkit-nightlies@live.nightly.webkit.org'; +my $nightlyRemotePath = "/home/webkit-nightlies"; +my $nightlyRemoteLatestPath = "$nightlyRemotePath/update-latest.sh"; + +sub currentRevision +{ + my $sourceDir = sourceDir(); + if (isSVNDirectory($sourceDir)) { + return currentSVNRevision(); + } elsif (isGitDirectory($sourceDir)) { + my $gitLog = `cd $sourceDir && LC_ALL=C git log --grep='git-svn-id: ' -n 1 | grep git-svn-id:`; + (my $revision) = ($gitLog =~ m/ +git-svn-id: .+@(\d+) /g); + return $revision; + } +} + +sub buildDiskImage +{ + my $revision = currentRevision(); + my $productDir = productDir(); + $nightlyLauncherDiskImagePath = productDir() . "/WebKit-SVN-r$revision.dmg"; + + print "Removing previous temp source directory (if any)...\n"; + `rm -rf /tmp/WebKitNightly`; + die "Removing previous temp source directory failed" if $?; + + print "Making a new temp source directory...\n"; + `mkdir /tmp/WebKitNightly`; + die "Making a new temp source directory failed" if $?; + + print "Copying WebKit.app to temp source directory...\n"; + `cp -R \"$nightlyLauncherStagingPath\" /tmp/WebKitNightly/WebKit.app`; + die "Copying WebKit.app to temp source directory failed" if $?; + + print "Copying Drosera.app to temp source directory...\n"; + `cp -R \"$droseraStagingPath\" /tmp/WebKitNightly/Drosera.app`; + die "Copying Drosera.app to temp source directory failed" if $?; + + print "Creating disk image...\n"; + `hdiutil create \"$nightlyLauncherDiskImagePath\" -ov -srcfolder /tmp/WebKitNightly -fs HFS+ -volname \"WebKit\"`; + die "Creating disk image failed" if $?; + + print "Removing temp source directory...\n"; + `rm -rf /tmp/WebKitNightly`; + die "Removing temp source directory failed" if $?; + + print "Compressing disk image...\n"; + system("mv", "-f", $nightlyLauncherDiskImagePath, "$nightlyLauncherDiskImagePath.uncompressed.dmg") == 0 or die "Renaming disk image failed"; + system("hdiutil", "convert", "-quiet", "$nightlyLauncherDiskImagePath.uncompressed.dmg", "-format", "UDBZ", "-imagekey", "zlib-level=9", "-o", "$nightlyLauncherDiskImagePath"); + die "Compressing disk image failed" if $?; + + unlink "$nightlyLauncherDiskImagePath.uncompressed.dmg"; +} + +sub uploadNightlyDiskImage +{ + my $buildTag = shift(@_); + my $nightlyRemoteDiskImagePath = "$nightlyRemotePath/builds/$buildTag/mac/" . basename($nightlyLauncherDiskImagePath); + my $revision = currentRevision(); + system("rsync", "-vP", $nightlyLauncherDiskImagePath, "$nightlyRemoteHost:$nightlyRemoteDiskImagePath") == 0 or die "Failed uploading disk image"; + system("ssh", $nightlyRemoteHost, $nightlyRemoteLatestPath, $buildTag, "mac", $nightlyRemoteDiskImagePath, $revision) == 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; +my $buildTag = 'trunk'; +GetOptions('upload-to-host=s' => \$uploadTo, + 'upload-as-nightly!' => \$nightlyBuild, + 'tag=s' => \$buildTag); + +chdirWebKit(); +buildDiskImage($buildTag); + +if ($nightlyBuild) { + uploadNightlyDiskImage($buildTag); +} elsif ($uploadTo) { + uploadBuildSlaveDiskImage($uploadTo); +} else { + print "Disk image left at $nightlyLauncherDiskImagePath\n"; +} diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/Makefile b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/Makefile new file mode 100644 index 0000000..c3a935f --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/Makefile @@ -0,0 +1,19 @@ +# -*- makefile -*- + +# This is a simple makefile which lives in a buildmaster/buildslave +# directory (next to the buildbot.tac file). It allows you to start/stop the +# master or slave by doing 'make start' or 'make stop'. + +# The 'reconfig' target will tell a buildmaster to reload its config file. + +start: + twistd --no_save -y buildbot.tac + +stop: + kill `cat twistd.pid` + +reconfig: + kill -HUP `cat twistd.pid` + +log: + tail -f twistd.log diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/buildbot.css b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/buildbot.css new file mode 100644 index 0000000..81de950 --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/buildbot.css @@ -0,0 +1,108 @@ +* { + font-family: Verdana, Cursor; + font-size: 10px; + font-weight: bold; +} + +a:link,a:visited,a:active { + color: #444; +} +a:hover { + color: #FFFFFF; +} + +table { + border-spacing: 1px 1px; +} + +table td { + padding: 3px 0px 3px 0px; + text-align: center; +} + +.Project { + width: 100px; +} + +.LastBuild, .Activity { + width: 230px; + padding: 0 0 0 4px; +} + +td.Time { + color: #000; + border-bottom: 1px solid #aaa; + background-color: #eee; +} + +td.Activity, td.Change, td.Builder { + color: #333333; + background-color: #CCCCCC; +} + +td.Change { + border-radius: 5px; + -webkit-border-radius: 5px; +} +td.Event { + color: #777; + background-color: #ddd; + border-radius: 5px; + -webkit-border-radius: 5px; +} + +td.Activity { + border-top-left-radius: 10px; + -webkit-border-top-left-radius: 10px; + min-height: 20px; + padding: 8px 0 8px 0; +} + +td.idle, td.waiting, td.offline, td.building { + border-top-left-radius: 0px; + -webkit-border-top-left-radius: 0px; +} + +.LastBuild { + border-top-left-radius: 5px; + -webkit-border-top-left-radius: 5px; + border-top-right-radius: 5px; + -webkit-border-top-right-radius: 5px; +} + +/* LastBuild, BuildStep states */ +.success { + color: #FFFFFF; + background-color: #8fdf5f; +} + +.failure { + color: #FFFFFF; + background-color: #e98080; +} + +.warnings { + color: #FFFFFF; + background-color: #ffc343; +} + +.exception, td.offline { + color: #FFFFFF; + background-color: #e0b0ff; +} + +.start,.running, td.building { + color: #666666; + background-color: #fffc6c; +} + +.start { + border-bottom-left-radius: 10px; + -webkit-border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + -webkit-border-bottom-right-radius: 10px; +} + +td.Project a:hover, td.start a:hover { + color: #000; +} diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/buildbot.tac b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/buildbot.tac new file mode 100644 index 0000000..f66e068 --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/buildbot.tac @@ -0,0 +1,10 @@ + +from twisted.application import service +from buildbot.master import BuildMaster + +basedir = r'/home/mrowe/sites/build.webkit.org/buildbot' +configfile = r'master.cfg' + +application = service.Application('buildmaster') +BuildMaster(basedir, configfile).setServiceParent(application) + diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg new file mode 100644 index 0000000..ea7966a --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg @@ -0,0 +1,22 @@ +# -*- python -*- + +import os +from twisted.web import static +static.File.contentTypes = static.loadMimeTypes(['/etc/mime.types', os.path.join(basedir, 'mime.types')]) + +from buildbot.changes.pb import PBChangeSource +import webkit +reload(webkit) + +c = BuildmasterConfig = {} + +c['slaves'] = webkit.auth.getSlaveAuthenticationDetails() +c['change_source'] = [PBChangeSource(prefix="trunk")] +c['builders'] = webkit.builders.getBuilders() +c['schedulers'] = webkit.schedulers.getSchedulers(c['builders']) +c['status'] = webkit.status.getStatusListeners() + +c['slavePortnum'] = 9989 +c['projectName'] = "WebKit" +c['projectURL'] = "http://webkit.org/" +c['buildbotURL'] = "http://build.webkit.org/" diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/__init__.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/__init__.py new file mode 100644 index 0000000..f81fcae --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/__init__.py @@ -0,0 +1,5 @@ +from webkit import auth, status, builders, schedulers +reload(auth) +reload(status) +reload(builders) +reload(schedulers) diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/auth.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/auth.py new file mode 100644 index 0000000..b182e16 --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/auth.py @@ -0,0 +1,9 @@ +from buildbot.buildslave import BuildSlave + +def getSlaveAuthenticationDetails(): + def createBuildSlave((name, password)): + return BuildSlave(name, password, max_builds=1) + return map(createBuildSlave, _getSlaveAuthenticationDetails()) + +def _getSlaveAuthenticationDetails(): + return [("slave-name", "password")] diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/basesteps.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/basesteps.py new file mode 100644 index 0000000..8bba881 --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/basesteps.py @@ -0,0 +1,51 @@ +from buildbot.steps import shell, source +import os + + +def buildStepWithDefaultTimeout(klass, default_timeout=75*60): + class Step(klass): + timeout = default_timeout + def __init__(self, *args, **kwargs): + kwargs['timeout'] = self.timeout + klass.__init__(self, *args, **kwargs) + + return Step + + +Test = buildStepWithDefaultTimeout(shell.Test) +Compile = buildStepWithDefaultTimeout(shell.Compile) +ShellCommand = buildStepWithDefaultTimeout(shell.ShellCommand) +SVN = buildStepWithDefaultTimeout(source.SVN) + + +class UploadCommand: + def initializeForUpload(self): + try: + try: + umask = os.umask(0) + os.makedirs(self.getDestinationPath(), 042770) + except OSError, e: + if e.errno != 17: + raise + finally: + os.umask(umask) + + def getDestinationPath(self): + return "/home/buildresults%s" % (self.getURLPath(), ) + + def getRemotePath(self): + return "buildresults@build.webkit.org:%s" % (self.getDestinationPath(), ) + + def getURLPath(self): + return '/results/%s/%s/' % (self.getBuild().builder.name, self.getBuild().getProperty("buildnumber"), ) + + def getBuild(self): + return self.build + + + def getText(self, cmd, results): + return self.getText2(cmd, results) + + def getText2(self, cmd, results): + return ['<a href="%s">%s</a>' % (self.getURLPath(), self.name)] + diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/builders.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/builders.py new file mode 100644 index 0000000..b4e087e --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/builders.py @@ -0,0 +1,35 @@ +from webkit.factories import * +from buildbot import locks + +# There are four build slaves that take care of the majority of builds, with two other specialist slaves at Apple +# Slave 1 isn older G4 PowerMac dedicated to the PLT builds, as it needs extra configuration +# Slave 2 is a Windows PC dedicated to the Windows builds +# Slaves 3 and 4 are older G4 PowerMacs with relatively low amounts of RAM which leads to insanely slow leaks tests +# Slaves 4 and 5 are newer G5 PowerMacs with ATI graphics cards that lead to kernel panics during pixel tests + +nonATIPowerPCBuilders = ['apple-slave-%d' % i for i in (3, 4)] +ATIPowerPCBuilders = ['apple-slave-%d' % i for i in (1, 5, 6)] +allPowerPCBuilders = nonATIPowerPCBuilders + ATIPowerPCBuilders +allIntelBuilders = ['bdash-slave-1', 'bdash-slave-2'] + +_builders = [('post-commit-powerpc-mac-os-x', StandardBuildFactory, allPowerPCBuilders), + ('post-commit-intel-mac-os-x', StandardBuildFactory, allIntelBuilders), + ('post-commit-leaks-powerpc-mac-os-x', LeakBuildFactory, allPowerPCBuilders), + ('post-commit-leaks-intel-mac-os-x', LeakBuildFactory, allIntelBuilders), +# ('page-layout-test-mac-os-x', PageLoadTestBuildFactory, ['apple-slave-1']), +# ('post-commit-pixel-powerpc-mac-os-x', PixelTestBuildFactory, nonATIPowerPCBuilders), + ('post-commit-win32', Win32BuildFactory, ['apple-slave-2']), + ('post-commit-linux-qt', StandardBuildFactory, ['webtroll-slave-1']), + ('post-commit-linux-gtk', GtkBuildFactory, ['zecke-slave-1']), + ('periodic-powerpc-mac-os-x-no-svg', NoSVGBuildFactory, allPowerPCBuilders), + ('periodic-intel-mac-os-x-coverage', CoverageDataBuildFactory, allIntelBuilders), + ] + +def getBuilders(): + result = [] + for name, factory, slaves in _builders: + result.append({'name': name, + 'slavenames': slaves, + 'builddir': name, + 'factory': factory()}) + return result diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/factories.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/factories.py new file mode 100644 index 0000000..781375f --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/factories.py @@ -0,0 +1,70 @@ +from webkit.steps import * +from buildbot.process import factory + +s = factory.s + +class BuildFactory(factory.BuildFactory): + useProgress = False + def __init__(self): + factory.BuildFactory.__init__(self, [s(CheckOutSource)]) + +class StandardBuildFactory(BuildFactory): + def __init__(self): + BuildFactory.__init__(self) + self.steps.append(s(SetConfiguration, configuration="release")) + self.steps.append(s(self.getCompileStep(), configuration="release")) + self.steps.append(s(self.getJavaScriptCoreTestStep())) + self.steps.append(s(LayoutTest)) + self.steps.append(s(UploadLayoutResults)) +# self.steps.append(s(UploadDiskImage)) + + def getCompileStep(self): + return CompileWebKit + + def getJavaScriptCoreTestStep(self): + return JavaScriptCoreTest + + +class NoSVGBuildFactory(StandardBuildFactory): + def getCompileStep(self): + return CompileWebKitNoSVG + + +class PixelTestBuildFactory(BuildFactory): + def __init__(self): + BuildFactory.__init__(self) + self.steps.append(s(SetConfiguration, configuration="release")) + self.steps.append(s(CompileWebKit, configuration="release")) + self.steps.append(s(PixelLayoutTest)) + self.steps.append(s(UploadLayoutResults)) + +class LeakBuildFactory(BuildFactory): + def __init__(self): + BuildFactory.__init__(self) + self.steps.append(s(SetConfiguration, configuration="debug")) + self.steps.append(s(CompileWebKit, configuration="debug")) + self.steps.append(s(JavaScriptCoreTest)) + self.steps.append(s(LeakTest)) + self.steps.append(s(UploadLayoutResults)) +# self.steps.append(s(UploadDiskImage)) + +class PageLoadTestBuildFactory(BuildFactory): + def __init__(self): + BuildFactory.__init__(self) + self.steps.append(s(CompileWebKit, configuration="release")) + self.steps.append(s(PageLoadTest)) + +Win32BuildFactory = StandardBuildFactory + +class GtkBuildFactory(StandardBuildFactory): + def getCompileStep(self): + return CompileWebKitGtk + + def getJavaScriptCoreTestStep(self): + return JavaScriptCoreTestGtk + +class CoverageDataBuildFactory(BuildFactory): + def __init__(self): + BuildFactory.__init__(self) + self.steps.append(s(GenerateCoverageData)) + self.steps.append(s(UploadCoverageData)) diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/schedulers.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/schedulers.py new file mode 100644 index 0000000..11f9d41 --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/schedulers.py @@ -0,0 +1,15 @@ +from buildbot.scheduler import Scheduler, Periodic + +def getSchedulers(builders): + builder_names = map(lambda builder: builder['name'], builders) + post_commit_builders = [name for name in builder_names if name.startswith('post-commit-')] + ['page-layout-test-mac-os-x'] + post_commit_builders = [name for name in post_commit_builders if name in builder_names] + post_commit_builders.sort() + + periodic_builders = [b['name'] for b in builders if b['name'].startswith('periodic-')] + periodic_builders.sort() + + post_commit = Scheduler(name="post-commit", branch=None, treeStableTimer=90, builderNames=post_commit_builders) + periodic = Periodic("periodic", periodic_builders, 6 * 60 * 60) + + return [post_commit, periodic] diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/status.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/status.py new file mode 100644 index 0000000..ad5519e --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/status.py @@ -0,0 +1,19 @@ +from buildbot.status import html, mail, words + +web = html.WebStatus(http_port=8010) + +allBuildsEmail = mail.MailNotifier(fromaddr="buildbot@webkit.org", + extraRecipients=["mark+webkit-builds@bdash.net.nz"], + sendToInterestedUsers=False) +breakageEmail = mail.MailNotifier(fromaddr="buildbot@webkit.org", + lookup=mail.Domain("webkit.org"), + mode="failing") + +IRC = words.IRC(host="irc.freenode.net", + nick="webkit-build", + channels=["#webkit-build"], +# announceAllBuilds=True + ) + +def getStatusListeners(): + return [web, allBuildsEmail, breakageEmail, IRC] diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/steps.py b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/steps.py new file mode 100644 index 0000000..c1933a3 --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/webkit/steps.py @@ -0,0 +1,220 @@ +from webkit.basesteps import ShellCommand, SVN, Test, Compile, UploadCommand +from buildbot.status.builder import SUCCESS, FAILURE, WARNINGS + +class CheckOutSource(SVN): + svnurl = "http://svn.webkit.org/repository/webkit/trunk" + mode = "update" + def __init__(self, *args, **kwargs): + SVN.__init__(self, svnurl=self.svnurl, mode=self.mode, *args, **kwargs) + +class SetConfiguration(ShellCommand): + command = ["./WebKitTools/Scripts/set-webkit-configuration"] + + def __init__(self, *args, **kwargs): + configuration = kwargs.pop('configuration') + self.command = self.command + ['--' + configuration] + self.name = "set-configuration-%s" % (configuration, ) + self.description = ["set configuration %s" % (configuration, )] + self.descriptionDone = ["set configuration %s" % (configuration, )] + ShellCommand.__init__(self, *args, **kwargs) + + +class LayoutTest(Test): + name = "layout-test" + description = ["layout-tests running"] + descriptionDone = ["layout-tests"] + command = ["./WebKitTools/Scripts/run-webkit-tests", "--no-launch-safari", "--no-new-test-results", "--results-directory", "layout-test-results"] + + def commandComplete(self, cmd): + Test.commandComplete(self, cmd) + + logText = cmd.logs['stdio'].getText() + incorrectLayoutLines = [line for line in logText.splitlines() if line.find('had incorrect layout') >= 0 or (line.find('test case') >= 0 and line.find(' crashed') >= 0)] + if incorrectLayoutLines: + self.incorrectLayoutLines = incorrectLayoutLines + else: + self.incorrectLayoutLines = None + + def getText(self, cmd, results): + return self.getText2(cmd, results) + + def getText2(self, cmd, results): + if results != SUCCESS and self.incorrectLayoutLines: + return self.incorrectLayoutLines + + return [self.name] + + +class JavaScriptCoreTest(Test): + name = "jscore-test" + description = ["jscore-tests running"] + descriptionDone = ["jscore-tests"] + command = ["./WebKitTools/Scripts/run-javascriptcore-tests"] + logfiles = {'results': 'JavaScriptCore/tests/mozilla/actual.html'} + + def commandComplete(self, cmd): + Test.commandComplete(self, cmd) + + logText = cmd.logs['stdio'].getText() + statusLines = [line for line in logText.splitlines() if line.find('regression') >= 0 and line.find(' found.') >= 0] + if statusLines and statusLines[0].split()[0] != '0': + self.regressionLine = statusLines[0] + else: + self.regressionLine = None + + def evaluateCommand(self, cmd): + if cmd.rc != 0: + return FAILURE + + if self.regressionLine: + return FAILURE + + return SUCCESS + + def getText(self, cmd, results): + return self.getText2(cmd, results) + + def getText2(self, cmd, results): + if results != SUCCESS and self.regressionLine: + return [self.name, self.regressionLine] + + return [self.name] + +class PixelLayoutTest(LayoutTest): + name = "pixel-layout-test" + description = ["pixel-layout-tests running"] + descriptionDone = ["pixel-layout-tests"] + command = LayoutTest.command + ["--pixel"] + + +class LeakTest(Test): + name = "leak-test" + description = ["leak-tests running"] + descriptionDone = ["leak-tests"] + command = ["./WebKitTools/Scripts/run-webkit-tests", "--no-launch-safari", "--leaks", "--results-directory", "layout-test-results"] + + def commandComplete(self, cmd): + Test.commandComplete(self, cmd) + + logText = cmd.logs['stdio'].getText() + lines = logText.splitlines() + self.totalLeakLines = [line for line in lines if line.find('total leaks found!') >= 0] + self.totalLeakLines += [line for line in lines if line.find('LEAK: ') >= 0] + self.totalLeakLines = [' '.join(x.split()[1:]) for x in self.totalLeakLines] + self.totalLeakLines += [line for line in lines if line.find('test case') >= 0 and line.find('crashed') >= 0] + + + def evaluateCommand(self, cmd): + if cmd.rc != 0: + return FAILURE + + if self.totalLeakLines: + return FAILURE + + return SUCCESS + + def getText(self, cmd, results): + return self.getText2(cmd, results) + + def getText2(self, cmd, results): + if results != SUCCESS and self.totalLeakLines: + return self.totalLeakLines + return [self.name] + + +class UploadLayoutResults(UploadCommand, ShellCommand): + name = "upload-results" + description = ["uploading results"] + descriptionDone = ["uploaded-results"] + command = "echo Disabled for now" + + def __init__(self, *args, **kwargs): + ShellCommand.__init__(self, *args, **kwargs) + + def setBuild(self, build): + ShellCommand.setBuild(self, build) + self.initializeForUpload() + + self.command = '''\ + if [[ -d layout-test-results ]]; then \ + find layout-test-results -type d -print0 | xargs -0 chmod ug+rx; \ + find layout-test-results -type f -print0 | xargs -0 chmod ug+r; \ + rsync -rlvzP --rsync-path="/home/buildresults/bin/rsync" layout-test-results/ %s && rm -rf layout-test-results; \ + fi; \ + CRASH_LOG=~/Library/Logs/CrashReporter/DumpRenderTree*.crash*; \ + if [[ -f $(ls -1 $CRASH_LOG | head -n 1 ) ]]; then \ + chmod ug+r $CRASH_LOG; \ + rsync -rlvzP --rsync-path="/home/buildresults/bin/rsync" $CRASH_LOG %s && rm -rf $CRASH_LOG; \ + fi;''' % (self.getRemotePath(), self.getRemotePath()) + + self.addFactoryArguments(command=self.command) + + +class CompileWebKit(Compile): + command = ["./WebKitTools/Scripts/build-webkit", "--no-color"] + env = {'WEBKITSUPPORTLIBRARIESZIPDIR': 'C:\\cygwin\\home\\buildbot'} + def __init__(self, *args, **kwargs): + configuration = kwargs.pop('configuration') + + self.name = "compile-" + configuration + self.description = ["compiling " + configuration] + self.descriptionDone = ["compiled " + configuration] + + Compile.__init__(self, *args, **kwargs) + + +class CompileWebKitNoSVG(CompileWebKit): + command = 'rm -rf WebKitBuild && ./WebKitTools/Scripts/build-webkit --no-svg --no-color' + +class CompileWebKitGtk(CompileWebKit): + command = CompileWebKit.command + ['--gtk'] + +class JavaScriptCoreTestGtk(JavaScriptCoreTest): + command = JavaScriptCoreTest.command + ['--gtk'] + +class InstallWin32Dependencies(ShellCommand): + description = ["installing Windows dependencies"] + descriptionDone = ["installed Windows dependencies"] + command = ["WebKitTools/Scripts/update-webkit-auxiliary-libs"] + + +# class UploadDiskImage(UploadCommand, ShellCommand): +# description = ["uploading disk image"] +# descriptionDone = ["uploaded disk image"] +# name = "upload-disk-image" + +# def __init__(self, *args, **kwargs): +# UploadCommand.__init__(self, *args, **kwargs) +# self.command = 'umask 002 && ./WebKitTools/BuildSlaveSupport/build-launcher-app && ./WebKitTools/BuildSlaveSupport/build-launcher-dmg --upload-to-host %s' % (self.getRemotePath(), ) +# ShellCommand.__init__(self, *args, **kwargs) + +class GenerateCoverageData(Compile): + command = ["./WebKitTools/Scripts/generate-coverage-data"] + description = ["generating coverage data"] + descriptionDone = ["generated coverage data"] + + +class UploadCoverageData(UploadCommand, ShellCommand): + name = "upload-coverage-data" + description = ["uploading coverage data"] + descriptionDone = ["uploaded-coverage-data"] + command = "echo Disabled for now" + + def __init__(self, *args, **kwargs): + ShellCommand.__init__(self, *args, **kwargs) + + def setBuild(self, build): + ShellCommand.setBuild(self, build) + self.initializeForUpload() + + self.command = '''\ + if [[ -d WebKitBuild/Coverage/html ]]; then \ + find WebKitBuild/Coverage/html -type d -print0 | xargs -0 chmod ug+rx; \ + find WebKitBuild/Coverage/html -type f -print0 | xargs -0 chmod ug+r; \ + rsync -rlvzP --rsync-path="/home/buildresults/bin/rsync" WebKitBuild/Coverage/html/ %s && rm -rf WebKitBuild/Coverage/html; \ + fi;''' % (self.getRemotePath(), ) + + self.addFactoryArguments(command=self.command) + + def getURLPath(self): + return "/results/code-coverage/" diff --git a/WebKitTools/BuildSlaveSupport/run-performance-tests b/WebKitTools/BuildSlaveSupport/run-performance-tests new file mode 100755 index 0000000..5d6ea44 --- /dev/null +++ b/WebKitTools/BuildSlaveSupport/run-performance-tests @@ -0,0 +1,80 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. 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 WebKit build slave to kick off performance tests. + +use strict; + +use FindBin; +use lib "$FindBin::Bin/../Scripts"; +use webkitdirs; + +use Getopt::Long; +use IO::Socket; +my $shouldPrebuild = 1; + +my $perfMaster = "webkit-build-1.local"; +my $perfSlave = "webkit-build-2.local"; +my $slaveUser = "buildbot"; +my $reportPort = 54481; # Something that looks sorta like SAFARI +my $slaveDirectory = "/ToTest"; + +my $buildDirectory = determineConfigurationProductDir(); + +my $userAndHost = $slaveUser . "@" . $perfSlave; +my $resultsUploadDestination; + +GetOptions('upload-results=s' => \$resultsUploadDestination); + +print "Copying built frameworks to PLT slave...\n"; +my @frameworks = ("$buildDirectory/JavaScriptCore.framework", "$buildDirectory/WebCore.framework", "$buildDirectory/WebKit.framework"); +die "Failed to copy to slave\n" unless (system("rsync", "-avz", @frameworks, "$userAndHost:$slaveDirectory") == 0); + +print "Opening reponse port for PLT slave...\n"; +my $sock = new IO::Socket::INET(LocalHost => $perfMaster, + LocalPort => $reportPort, + Proto => 'tcp', + Listen => 1, + Reuse => 1); +die "Could not create socket for port $reportPort: $!\n" unless $sock; + +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", currentSVNRevision(), "--show-results", "send-completed-results.command") == 0); + +print "Waiting for PLT slave to respond...\n"; +my $new_sock = $sock->accept(); +while(<$new_sock>) { + print $_; +} +close($sock); + +if ($resultsUploadDestination) { + print "Uploading results to $resultsUploadDestination\n"; + die "Failed to upload xml results file." unless (system("scp", "$userAndHost:/Results/PerformanceReportSummary.xml", $resultsUploadDestination) == 0); + die "Failed to upload svg results file." unless (system("scp", "$userAndHost:/Results/PerformanceGraph.svg", $resultsUploadDestination) == 0); +} diff --git a/WebKitTools/CLWrapper/CLWrapper.cpp b/WebKitTools/CLWrapper/CLWrapper.cpp new file mode 100644 index 0000000..7d41f2b --- /dev/null +++ b/WebKitTools/CLWrapper/CLWrapper.cpp @@ -0,0 +1,52 @@ +// CLWrapper.cpp : Calls the perl script parallelcl to perform parallel compilation + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include <process.h> +#include <stdio.h> +#include <string> +#include <windows.h> + +using namespace std; + +int wmain(int argc, wchar_t* argv[]) +{ + const int numArgs = 3; + +#ifndef NDEBUG + fwprintf(stderr, L"######### im in ur IDE, compiling ur c0des ########\n"); +#endif + + wstring** args = new wstring*[numArgs]; + + args[0] = new wstring(L"sh"); + args[1] = new wstring(L"-c"); + + args[2] = new wstring(L"\"parallelcl"); + for (int i = 1; i < argc; ++i) { + args[2]->append(L" '"); + args[2]->append(argv[i]); + if (i < argc - 1) + args[2]->append(L"' "); + else + args[2]->append(L"'"); + } + args[2]->append(L"\""); + + for (unsigned i = 0; i < args[2]->length(); i++) { + if (args[2]->at(i) == '\\') + args[2]->at(i) = '/'; + } + + wchar_t** newArgv = new wchar_t*[numArgs + 1]; + for (int i = 0; i < numArgs; i++) + newArgv[i] = (wchar_t*)args[i]->c_str(); + + newArgv[numArgs] = 0; + +#ifndef NDEBUG + fwprintf(stderr, L"exec(\"%s\", \"%s\", \"%s\", \"%s\")\n", L"sh", newArgv[0], newArgv[1], newArgv[2]); +#endif + + return _wspawnvp(_P_WAIT, L"sh", newArgv); +} + diff --git a/WebKitTools/CLWrapper/CLWrapper.sln b/WebKitTools/CLWrapper/CLWrapper.sln new file mode 100644 index 0000000..add0423 --- /dev/null +++ b/WebKitTools/CLWrapper/CLWrapper.sln @@ -0,0 +1,20 @@ +
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CLWrapper", "CLWrapper.vcproj", "{230BF635-9BD8-434A-8857-0B096EBC7233}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {230BF635-9BD8-434A-8857-0B096EBC7233}.Debug|Win32.ActiveCfg = Debug|Win32
+ {230BF635-9BD8-434A-8857-0B096EBC7233}.Debug|Win32.Build.0 = Debug|Win32
+ {230BF635-9BD8-434A-8857-0B096EBC7233}.Release|Win32.ActiveCfg = Release|Win32
+ {230BF635-9BD8-434A-8857-0B096EBC7233}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/WebKitTools/CLWrapper/CLWrapper.vcproj b/WebKitTools/CLWrapper/CLWrapper.vcproj new file mode 100644 index 0000000..668a874 --- /dev/null +++ b/WebKitTools/CLWrapper/CLWrapper.vcproj @@ -0,0 +1,199 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="CLWrapper"
+ ProjectGUID="{230BF635-9BD8-434A-8857-0B096EBC7233}"
+ RootNamespace="CLWrapper"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\vcbin"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\cl.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="..\vcbin"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\cl.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\CLWrapper.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/CodeCoverage/README b/WebKitTools/CodeCoverage/README new file mode 100644 index 0000000..5315f4a --- /dev/null +++ b/WebKitTools/CodeCoverage/README @@ -0,0 +1,22 @@ +Generate coverage on Mac + +call WebKitTools/Script/generate-coverage-data + +or by hand + + +# delete +find . -name '*.gcda' -delete + +# build, -framework CoreFoundation might suffice as well +WebKitTools/Scripts/build-webkit GCC_GENERATE_TEST_COVERAGE_FILES=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES EXTRA_LINK=" -ftest-coverage -fprofile-arcs" OTHER_CFLAGS=" -MD " OTHER_LDFLAGS=" -ftest-coverage -fprofile-arcs -framework AppKit" +WebKitTools/Scripts/run-webkit-tests +WebKitTools/Scripts/run-javascriptcore-tests GCC_GENERATE_TEST_COVERAGE_FILES=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES EXTRA_LINK=" -ftest-coverage -fprofile-arcs" OTHER_CFLAGS=" -MD " OTHER_LDFLAGS=" -ftest-coverage -fprofile-arcs -framework AppKit" + + +# Collect files +WebKitTools/CodeCoverage/run-generate-coverage-data <RUN_ID> ../coverage-results/ + + +# Generate graph +WebKitTools/CodeCoverage/regenerate-coverage-display ../coverage-results/ ../coverage-results/html diff --git a/WebKitTools/CodeCoverage/amber.png b/WebKitTools/CodeCoverage/amber.png Binary files differnew file mode 100644 index 0000000..ee5d920 --- /dev/null +++ b/WebKitTools/CodeCoverage/amber.png diff --git a/WebKitTools/CodeCoverage/cov.py b/WebKitTools/CodeCoverage/cov.py new file mode 100644 index 0000000..443e601 --- /dev/null +++ b/WebKitTools/CodeCoverage/cov.py @@ -0,0 +1,201 @@ +# Copyright (C) 2004, 2005, 2006 Nathaniel Smith +# Copyright (C) 2006, 2007 Holger Hans Peter Freyther +# +# 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 csv +import time +import os.path +import shutil + +def analyze_coverage(possible_gcov_files, source_files, runid, data_dir, base): + + if not os.path.exists(data_dir): + os.makedirs(data_dir) + + output = open(os.path.join(data_dir, runid + ".csv"), "w") + w = csv.writer(output) + # First row: id and time + w.writerow([runid, time.time()]) + + results = scan_gcov_files(possible_gcov_files, source_files) + annotated_dir = os.path.join(data_dir, runid + ".annotated") + if os.path.exists(annotated_dir): + shutil.rmtree(annotated_dir) + + keys = results.keys() + keys.sort() + for path in keys: + (total, covered, annotated_data) = results[path] + path = path[path.find(base)+len(base):] + # Rest of the rows: filename, total_lines, covered_lines + w.writerow([path, total, covered]) + + if path[:1] == "/": + path = path[1:] + annotated_path = os.path.join(annotated_dir, path) + try: + os.makedirs(os.path.dirname(annotated_path)) + except OSError: + pass + a = open(annotated_path, "w") + a.write(annotated_data) + a.close() + + +# zecke's rewrite +STATE_NOT_CODE = -1 +STATE_NOT_SEEN = -2 +STATE_TEST_CODE = -3 + +def find_gcov(f, possible_gcovs): + """ + Find .gcov files that could be of interest for us + """ + try: + return possible_gcovs[f] + except: + return [] + + +def parse_source_file(file): + """ + Parse one source file and return a list of lines + """ + f_source_list = [] + init_state = STATE_NOT_SEEN + in_test_code = False + nesting = 0 + + for line in open(file, "r"): + code = line.split(":", 2)[-1] + if not in_test_code and code.startswith("#ifdef BUILD_UNIT_TESTS"): + in_test_code = 1 + if in_test_code and code.startswith("#if"): + nesting += 1 + if in_test_code and code.startswith("#endif"): + nesting -= 1 + if not nesting: + in_test_code = True + if in_test_code: + init_state = STATE_TEST_CODE + else: + init_state = STATE_NOT_SEEN + f_source_list.append([init_state, line.split(":", 1)[1]]) + + return f_source_list + +# Runner-up, 3rd annual "write Python that looks like Perl" competition, +# Well, not really. It doesn't even use regexps. +# He is right so I'm cleaning it up (zecke) +def scan_gcov_files(possible_gcov_files, source_files): + """Takes a list of gcov filenames and a list of source filenames. + + The gcov files should have names of the form foo.o##foo.cc.gcov, as + created by 'gcov -l'. + + Returns a dict mapping source filenames to tuples + (total_lines, tested_lines, gcov_annotated_source) + which are a number, a number, and a very long string, respectively. + + The fun bit is that we merge .gcov output generated by different object + files; this way we can provide accurate information for header files and + for monotone's current unit test system.""" + results = {} + for f in source_files: + possible_gcovs = find_gcov(f, possible_gcov_files) + base_name = os.path.splitext(os.path.basename(f))[0] + if len(possible_gcovs) == 0: + print "No gcov files found for: '%s' but it was compiled" % f + continue + + (garbage,extension) = os.path.splitext(f) + if extension in [".cc", ".c", ".moc", ".cpp", ".cxx", ".m", ".mm"]: + lines = open(f, "r").readlines() + results[f] = (len(lines), 0, "".join(lines)) + continue + elif len(possible_gcovs) > 1: + print "More than one gcov file for %s %d" % (f,len(possible_gcovs)) + base_gcov_lines = parse_source_file(possible_gcovs[0]) + + # Now we will try hard to merge the results with others + # Our requirement is that we have the same amount of lines as + # as the original file + for cov_file in possible_gcovs: + lines = open(cov_file, "r").readlines() + + # e.g. with phonon we have visualisation.h and we can not know + # which header file (foldername) it is refering to. This is a gcov + # limitation and i have no workaround yet. We just hope we will pick + # the right header file... + if len(lines) != len(base_gcov_lines): + print "Error Base: %s and Target: %s have different amount of lines" % (possible_gcovs[0],cov_file) + continue + + # now do the merging of the file. If it has the same basename + # and the same number of lines things might work out + # In the future take a look at the header of the file + i = 0 + for line in lines: + accumulator = base_gcov_lines[i] + if accumulator[0] != STATE_TEST_CODE: + info = line.split(":", 1)[0] + if info.endswith("-"): + if accumulator[0] == STATE_NOT_SEEN: + accumulator[0] = STATE_NOT_CODE + else: + if info.endswith("#"): + num = 0 + else: + num = int(info) + if accumulator[0] in (STATE_NOT_SEEN, STATE_NOT_CODE): + accumulator[0] = 0 + accumulator[0] += num + i += 1 + + # post processing of ths file + (total_lines, total_covered) = (0, 0) + annotated_lines = [] + for state, line in base_gcov_lines: + if state == STATE_NOT_SEEN: + desc = "?????" + elif state == STATE_TEST_CODE: + desc = "+" + elif state == STATE_NOT_CODE: + desc = "-" + elif state == 0: + desc = "#####" + total_lines += 1 + else: + desc = str(state) + total_lines += 1 + total_covered += 1 + annotated_lines.append(":".join([desc.rjust(9), line])) + results[f] = (total_lines, total_covered, "".join(annotated_lines)) + return results + + + + return results diff --git a/WebKitTools/CodeCoverage/emerald.png b/WebKitTools/CodeCoverage/emerald.png Binary files differnew file mode 100644 index 0000000..0e60294 --- /dev/null +++ b/WebKitTools/CodeCoverage/emerald.png diff --git a/WebKitTools/CodeCoverage/gcov.css b/WebKitTools/CodeCoverage/gcov.css new file mode 100644 index 0000000..71ca080 --- /dev/null +++ b/WebKitTools/CodeCoverage/gcov.css @@ -0,0 +1,116 @@ +body { + color: black; background-color: white; + font-family: Helvetica,Arial,sans-serif; + margin: 0; padding: 0em; + text-align: center; +} + +.title { + text-align:center; + font-weight:bold; + font-style:italic; + font-size:1.8em; + padding:10px; +} + +.ruler { + height:3px; + background-color:#638AD6; + margin-left:10px; + margin-right:10px; +} + +.headerItem { + text-align:right; + font-weight:bold; +} + +.headerValue { + text-align:left; + font-weight:bold; + color:#638AD6; +} + +.tableHead { + text-align:center; + font-weight:bold; + background-color:#638AD6; + color:white; + +} + +.coverFile { + font-family: Courier; + background-color:#DEE7FF; + padding:3px; + width:70%; +} + +.coverBar { + background-color:#DEE7FF; + padding:3px; + width:5%; +} + +.coverBarOutline { +} + +.coverPerHi { + font-family: Times; + text-align:center; + font-weight:bold; + background-color:lightgreen; + padding:3px; + width:5%; +} + +.coverNumHi { + font-family: Times; + text-align:right; + background-color:lightgreen; + padding:3px; + width:25%; +} + +.coverPerMed { + font-family: Times; + text-align:center; + font-weight:bold; + background-color:yellow; + padding:3px; +} + +.coverNumMed { + font-family: Times; + text-align:right; + background-color:yellow; + padding:3px; +} + +.coverPerLo { + font-family: Times; + text-align:center; + font-weight:bold; + background-color:red; + padding:3px; +} + +.coverNumLo { + font-family: Times; + text-align:right; + background-color:red; + padding:3px; +} + +.lineNum { + background-color:#EFE384; +} + +.lineCov { + background-color:#CED7FF; +} + +.lineNoCov { + background-color:#FF6131; +} + diff --git a/WebKitTools/CodeCoverage/glass.png b/WebKitTools/CodeCoverage/glass.png Binary files differnew file mode 100644 index 0000000..a4ba373 --- /dev/null +++ b/WebKitTools/CodeCoverage/glass.png diff --git a/WebKitTools/CodeCoverage/regenerate-coverage-display b/WebKitTools/CodeCoverage/regenerate-coverage-display new file mode 100755 index 0000000..9139c9a --- /dev/null +++ b/WebKitTools/CodeCoverage/regenerate-coverage-display @@ -0,0 +1,408 @@ +#!/usr/bin/env python +# +# Copyright (C) 2004, 2005, 2006 Nathaniel Smith +# Copyright (C) 2007 Holger Hans Peter Freyther +# +# 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. + +# +# HTML output inspired by the output of lcov as found on the GStreamer +# site. I assume this is not copyrightable. +# + + +# +# Read all CSV files and +# Create an overview file +# +# + + +import sys +import csv +import glob +import time +import os +import os.path +import datetime +import shutil + +os.environ["TTFPATH"] = ":".join(["/usr/share/fonts/truetype/" + d + for d in "ttf-bitstream-vera", + "freefont", + "msttcorefonts"]) +import matplotlib +matplotlib.use("Agg") +import matplotlib.pylab as m + +level_LOW = 10 +level_MEDIUM = 70 + +def copy_files(dest_dir): + """ + Copy the CSS and the png's to the destination directory + """ + images = ["amber.png", "emerald.png", "glass.png", "ruby.png", "snow.png"] + css = "gcov.css" + (base_path, name) = os.path.split(__file__) + base_path = os.path.abspath(base_path) + + shutil.copyfile(os.path.join(base_path,css), os.path.join(dest_dir,css)) + map(lambda x: shutil.copyfile(os.path.join(base_path,x), os.path.join(dest_dir,x)), images) + +def sumcov(cov): + return "%.2f%% (%s/%s)" % (cov[1] * 100.0 / (cov[0] or 1), cov[1], cov[0]) + +def create_page(dest_dir, name): + index = open(os.path.join(dest_dir, name), "w") + index.write("""<HTML> + <HEAD> + <TITLE>WebKit test coverage information</TITLE> + <link rel="stylesheet" type="text/css" href="gcov.css"> + </HEAD> + <BODY> + """) + return index + +def generate_header(file, last_time, total_lines, total_executed, path, image): + product = "WebKit" + date = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(last_time)) + covered_lines = sumcov((total_lines, total_executed)) + + file.write("""<table width="100%%" border=0 cellspacing=0 cellpadding=0> + <tr><td class="title">GCOV code coverage report</td></tr> + <tr><td class="ruler"><img src="glass.png" width=3 height=3 alt=""></td></tr> + + <tr> + <td width="100%%"> + <table cellpadding=1 border=0 width="100%%"> + <tr> + <td class="headerItem" width="20%%">Current view:</td> + <td class="headerValue" width="80%%" colspan=4>%(path)s</td> + </tr> + <tr> + <td class="headerItem" width="20%%">Test:</td> + <td class="headerValue" width="80%%" colspan=4>%(product)s</td> + </tr> + <tr> + <td class="headerItem" width="20%%">Date:</td> + <td class="headerValue" width="20%%">%(date)s</td> + <td width="20%%"></td> + <td class="headerItem" width="20%%">Instrumented lines:</td> + <td class="headerValue" width="20%%">%(total_lines)s</td> + </tr> + <tr> + <td class="headerItem" width="20%%">Code covered:</td> + <td class="headerValue" width="20%%">%(covered_lines)s</td> + <td width="20%%"></td> + <td class="headerItem" width="20%%">Executed lines:</td> + <td class="headerValue" width="20%%">%(total_executed)s</td> + </tr> + </table> + </td> + </tr> + <tr><td class="ruler"><img src="glass.png" width=3 height=3 alt=""></td></tr> + </table>""" % vars()) + # disabled for now <tr><td><img src="%(image)s"></td></tr> + +def generate_table_item(file, name, total_lines, covered_lines): + covered_precise = (covered_lines*100.0)/(total_lines or 1.0) + covered = int(round(covered_precise)) + remainder = 100-covered + (image,perClass,numClass) = coverage_icon(covered_precise) + site = "%s.html" % name.replace(os.path.sep,'__') + file.write(""" + <tr> + <td class="coverFile"><a href="%(site)s">%(name)s</a></td> + <td class="coverBar" align="center"> + <table border=0 cellspacing=0 cellpadding=1><tr><td class="coverBarOutline"><img src="%(image)s" width=%(covered)s height=10 alt="%(covered_precise).2f"><img src="snow.png" width=%(remainder)s height=10 alt="%(covered_precise).2f"></td></tr></table> + </td> + <td class="%(perClass)s">%(covered_precise).2f %%</td> + <td class="%(numClass)s">%(covered_lines)s / %(total_lines)s lines</td> + </tr> + """ % vars()) + +def generate_table_header_start(file): + file.write("""<center> + <table width="80%%" cellpadding=2 cellspacing=1 border=0> + + <tr> + <td width="50%%"><br></td> + <td width="15%%"></td> + <td width="15%%"></td> + <td width="20%%"></td> + </tr> + + <tr> + <td class="tableHead">Directory name</td> + <td class="tableHead" colspan=3>Coverage</td> + </tr> + """) + +def coverage_icon(percent): + if percent < level_LOW: + return ("ruby.png", "coverPerLo", "coverNumLo") + elif percent < level_MEDIUM: + return ("amber.png", "coverPerMed", "coverNumMed") + else: + return ("emerald.png", "coverPerHi", "coverNumHi") + +def replace(text, *pairs): + """ + From pydoc... almost identical at least + """ + from string import split, join + while pairs: + (a,b) = pairs[0] + text = join(split(text, a), b) + pairs = pairs[1:] + return text + +def escape(text): + """ + Escape string to be conform HTML + """ + return replace(text, + ('&', '&'), + ('<', '<' ), + ('>', '>' ) ) + +def generate_table_header_end(file): + file.write("""</table> + </center>""") + +def write_title_page(dest_dir,plot_files, last_time, last_tot_lines, last_tot_covered, dir_series): + """ + Write the index.html with a overview of each directory + """ + index= create_page(dest_dir, "index.html") + generate_header(index, last_time, last_tot_lines, last_tot_covered, "directory", "images/Total.png") + # Create the directory overview + generate_table_header_start(index) + dirs = dir_series.keys() + dirs.sort() + for dir in dirs: + (dir_files, total_lines, covered_lines,_) = dir_series[dir][-1] + generate_table_item(index, dir, total_lines, covered_lines) + generate_table_header_end(index) + + index.write("""</BODY></HTML>""") + index.close() + +def write_directory_site(dest_dir, plot_files, dir_name, last_time, dir_series, file_series): + escaped_dir = dir_name.replace(os.path.sep,'__') + site = create_page(dest_dir, "%s.html" % escaped_dir) + (_,tot_lines,tot_covered,files) = dir_series[dir_name][-1] + generate_header(site, last_time, tot_lines, tot_covered, "directory - %s" % dir_name, "images/%s.png" % escaped_dir) + + files.sort() + + generate_table_header_start(site) + for file in files: + (lines,covered) = file_series[file][-1] + generate_table_item(site, file, lines, covered) + + generate_table_header_end(site) + site.write("""</BODY></HTML>""") + site.close() + +def write_file_site(dest_dir, plot_files, file_name, last_time, data_dir, last_id, file_series): + escaped_name = file_name.replace(os.path.sep,'__') + site = create_page(dest_dir, "%s.html" % escaped_name) + (tot_lines,tot_covered) = file_series[file_name][-1] + generate_header(site, last_time, tot_lines, tot_covered, "file - %s" % file_name, "images/%s.png" % escaped_name) + + path = "%s/%s.annotated%s" % (data_dir,last_id,file_name) + + # In contrast to the lcov we want to show files that have been compiled + # but have not been tested at all. This means we have sourcefiles with 0 + # lines covered in the path but they are not lcov files. + # To identify them we check the first line now. If we see that we can + # continue + # -: 0:Source: + try: + file = open(path, "r") + except: + return + all_lines = file.read().split("\n") + + # Convert the gcov file to HTML if we have a chanche to do so + # Scan each line and see if it was covered or not and escape the + # text + if len(all_lines) == 0 or not "-: 0:Source:" in all_lines[0]: + site.write("<p>The file was not excercised</p>") + else: + site.write("""</br><table cellpadding=0 cellspacing=0 border=0> + <tr> + <td><br></td> + </tr> + <tr> + <td><pre class="source"> + """) + for line in all_lines: + split_line = line.split(':',2) + # e.g. at the EOF + if len(split_line) == 1: + continue + line_number = split_line[1].strip() + if line_number == "0": + continue + covered = 15*" " + end = "" + if "#####" in split_line[0]: + covered = '<span class="lineNoCov">%15s' % "0" + end = "</span>" + elif split_line[0].strip() != "-": + covered = '<span class="lineCov">%15s' % split_line[0].strip() + end = "</span>" + + escaped_line = escape(split_line[2]) + str = '<span class="lineNum">%(line_number)10s </span>%(covered)s: %(escaped_line)s%(end)s\n' % vars() + site.write(str) + site.write("</pre></td></tr></table>") + site.write("</BODY></HTML>") + site.close() + +def main(progname, args): + if len(args) != 2: + sys.exit("Usage: %s DATADIR OUTDIR" % progname) + + branch = "WebKit from trunk" + datadir, outdir = args + + # First, load in all data from the data directory. + data = [] + for datapath in glob.glob(os.path.join(datadir, "*.csv")): + data.append(read_csv(datapath)) + # Sort by time + data.sort() + + # Calculate time series for each file. + times = [sample[0] for sample in data] + times = [datetime.datetime.utcfromtimestamp(t) for t in times] + times = m.date2num(times) + all_files = {} + all_dirs = {} + for sample in data: + t, i, tot_line, tot_cover, per_file, per_dir = sample + all_files.update(per_file) + all_dirs.update(per_dir) + total_series = [] + file_serieses = dict([[k, [(0, 0)] * len(times)] for k in all_files.keys()]) + dir_serieses = dict([[k, [(0, 0, 0, [])] * len(times)] for k in all_dirs.keys()]) + data_idx = 0 + for sample in data: + t, i, tot_line, tot_cover, per_file, per_dir = sample + total_series.append([tot_line, tot_cover]) + for f, covinfo in per_file.items(): + file_serieses[f][data_idx] = covinfo + for f, covinfo in per_dir.items(): + dir_serieses[f][data_idx] = covinfo + data_idx += 1 + + + # Okay, ready to start outputting. First make sure our directories + # exist. + if not os.path.exists(outdir): + os.makedirs(outdir) + rel_imgdir = "images" + imgdir = os.path.join(outdir, rel_imgdir) + if not os.path.exists(imgdir): + os.makedirs(imgdir) + + # Now plot the actual graphs + plot_files = {} + #plot_files["Total"] = plot_coverage(times, total_series, imgdir, "Total") + #for dir, series in dir_serieses.items(): + # plot_files[dir] = plot_coverage(times, map(lambda (a,b,c,d):(b,c), series), imgdir, dir) + #for f, series in file_serieses.items(): + # plot_files[f] = plot_coverage(times, series, imgdir, f) + + # And look up the latest revision id, and coverage information + last_time, last_id, last_tot_lines, last_tot_covered = data[-1][:4] + + # Now start generating our html file + copy_files(outdir) + write_title_page(outdir, plot_files, last_time, last_tot_lines, last_tot_covered, dir_serieses) + + dir_keys = dir_serieses.keys() + dir_keys.sort() + for dir_name in dir_keys: + write_directory_site(outdir, plot_files, dir_name, last_time, dir_serieses, file_serieses) + + file_keys = file_serieses.keys() + for file_name in file_keys: + write_file_site(outdir, plot_files, file_name, last_time, datadir, last_id, file_serieses) + +def read_csv(path): + r = csv.reader(open(path, "r")) + # First line is id, time + for row in r: + id, time_str = row + break + time = int(float(time_str)) + # Rest of lines are path, total_lines, covered_lines + per_file = {} + per_dir = {} + grand_total_lines, grand_covered_lines = 0, 0 + for row in r: + path, total_lines_str, covered_lines_str = row + total_lines = int(total_lines_str) + covered_lines = int(covered_lines_str) + grand_total_lines += total_lines + grand_covered_lines += covered_lines + per_file[path] = [total_lines, covered_lines] + + # Update dir statistics + dirname = os.path.dirname(path) + if not dirname in per_dir: + per_dir[dirname] = (0,0,0,[]) + (dir_files,dir_total_lines,dir_covered_lines, files) = per_dir[dirname] + dir_files += 1 + dir_total_lines += total_lines + dir_covered_lines += covered_lines + files.append(path) + per_dir[dirname] = (dir_files,dir_total_lines,dir_covered_lines,files) + return [time, id, grand_total_lines, grand_covered_lines, per_file, per_dir] + + +def plot_coverage(times, series, imgdir, name): + percentages = [cov * 100.0 / (tot or 1) for tot, cov in series] + m.plot_date(times, percentages, "b-") + m.plot_date(times, percentages, "bo") + m.title(name) + m.ylim(0, 100) + m.xlabel("Date") + m.ylabel("Statement Coverage (%)") + outfile_base = name.replace("/", "__") + ".png" + outfile = os.path.join(imgdir, outfile_base) + m.savefig(outfile, dpi=75) + m.close() + return outfile_base + + +if __name__ == "__main__": + import sys + main(sys.argv[0], sys.argv[1:]) diff --git a/WebKitTools/CodeCoverage/ruby.png b/WebKitTools/CodeCoverage/ruby.png Binary files differnew file mode 100644 index 0000000..a582d35 --- /dev/null +++ b/WebKitTools/CodeCoverage/ruby.png diff --git a/WebKitTools/CodeCoverage/run-generate-coverage-data b/WebKitTools/CodeCoverage/run-generate-coverage-data new file mode 100755 index 0000000..a87da1d --- /dev/null +++ b/WebKitTools/CodeCoverage/run-generate-coverage-data @@ -0,0 +1,240 @@ +#!/usr/bin/env python + +# Copyright (C) 2004, 2005, 2006 Nathaniel Smith +# Copyright (C) 2007 Holger Hans Peter Freyther +# +# 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 os, sys + +# from BitBake +def mkdirhier(dir): + """Create a directory like 'mkdir -p', but does not complain if + directory already exists like os.makedirs + """ + try: + os.makedirs(dir) + except OSError, e: + if e.errno != 17: raise e + +def collect_base(src,match_array): + """ + Collect all files that match the match_array. + """ + + sources = [] + for root, dirs, files in os.walk(src): + if ".svn" in root: + continue + + for file in files: + base,ext = os.path.splitext(file) + if ext in match_array: + sources.append( os.path.join(root, file) ) + + return sources + +def collect_depends(src): + return collect_base(src, [".d"]) + +def parse_dependency_file(src, base_dir, black_list): + """ + Parse the .d files of the gcc + + Wow, the first time os.path.join is doing the right thing. We might + have a relative path in the depends using os.path.join(dirname of .d, dep) + we will end up in + """ + file = open(src) + file = file.read() + file = file.replace('\\', '').replace('\n', '') + + # We now have object: dependencies splitted + ar = file.split(':', 1) + obj = ar[0].strip() + dir = os.path.dirname(obj) + deps = ar[1].split(' ') + + # Remove files outside WebKit, make path absolute + deps = filter(lambda x: base_dir in x, deps) + deps = map(lambda x: os.path.abspath(os.path.join(dir, x)), deps) + return (obj, dir, deps) + +def collect_cov(base_path,targets): + """ + Collect gcov files, collect_sources is not used as it also creates + dirs and needs to do substituting. + Actually we will build a mapping from source file to gcov files of + interest. This is because we could have bytestream.h in many different + subdirectories. And we would endup with bla.cpp##bytestream.h and we + do not know which bytestream file was tested + """ + def find_source_file(root,cov_file): + """ Find a Source line or crash + + '#Users#ich#projekte#src#threadmessage.cpp###space#dports#include#qt3#qstring.h.gcov' + '#Users#ich#projekte#src#threadmessage.cpp##..#^#src#threadmessage.cpp.gcov' + + ### is absolute path + ##..#^# is relative path... well a gcov bug as well + ## normal split file in the same directory + """ + if '###' in cov_file: + split = cov_file.split('###') + if not len(split) == 2: + raise "Unexpected split result" + filepath = split[1][:-5].replace('#',os.path.sep) + return os.path.join(os.path.sep,filepath) + elif '##..#^#' in cov_file: + split = cov_file.split('##..#^#') + if not len(split) == 2: + raise "Unexpected split result" + filepath = split[1][:-5].replace('#',os.path.sep) + return os.path.abspath(os.path.join(root,os.path.pardir,os.path.pardir,filepath)) + elif '##' in cov_file: + split = cov_file.split('##') + if not len(split) == 2: + raise "Unexpected split result" + filepath = split[1][:-5].replace('#',os.path.sep) + return os.path.abspath(os.path.join(root,filepath)) + elif '#' in cov_file: + # wow a not broken gcov on OSX + basename=os.path.basename(cov_file).replace('#',os.path.sep)[:-5] + return os.path.abspath(os.path.join(root,basename)) + + else: + raise "No source found %s" % cov_file + + def sanitize_path(path): + """ + Well fix up paths once again /usr/lib/gcc/i486-linux-gnu/4.1.2/^/^/^/^/include/c++/4.1.2/bits/stl_pair.h + according to gcov '^' is a relative path, we will now build one from this one. Somehow it depends + on the gcov version if .. really gets replaced to ^.... + """ + import os + split = path.split(os.path.sep) + str = "" + for part in split: + if part == '': + str = os.path.sep + elif part == '^': + str = "%s..%s" % (str,os.path.sep) + else: + str = "%s%s%s" % (str,part,os.path.sep) + return os.path.abspath(str) + + + gcov = {} + for root, dirs, files in os.walk(base_path): + if ".svn" in root: + continue + for file in files: + base,ext = os.path.splitext(file) + if ext in [".gcov"]: + try: + cov = os.path.join(root, file) + src = find_source_file( root, cov ) + src = sanitize_path( src ) + + if not src in gcov: + gcov[src] = [] + gcov[src].append( cov ) + except Exception,e: + print "Exception on ", e + #import sys + #sys.exit(0) + pass + + #print gcov + return gcov + +def generate_covs(candidates): + """ + Generate gcov files in the right directory + + candidtaes contains the directories we have used when + building. Each directory contains a set of files we will + try to generate gcov files for. + """ + print candidates.keys() + for dir in candidates.keys(): + print "Trying in %s" % (dir) + for dep in candidates[dir].keys(): + cmd = "cd %s; gcov -p -l %s" % (dir, dep) + os.system("%s > /dev/null 2>&1 " % cmd) + + +def analyze_coverage(sources,data,dirs,runid,base): + """ + sources actual source files relative to src_dir e.g kdelibs/kdecore/klibloader.cpp + data Where to put the stuff + dirs Where to take a look for gcov files + base The base directory for files. All files not inside base will be ignored + """ + import cov + print base + gcov = collect_cov(base,dirs) + result = cov.analyze_coverage(gcov, sources, runid, data, base) + print result + +if __name__ == "__main__": + #global targets + if not len(sys.argv) == 3: + print "This script needs three parameters" + print "Call it with generate_cov RUNID ResultsDir" + sys.exit(-1) + runid = sys.argv[1] + results = sys.argv[2] + + # create directories for out result + mkdirhier(results) + + print "Collection Sources and preparing data tree" + base_dir = os.path.abspath(os.path.curdir) + depends = collect_depends(base_dir) + candidates = map(lambda x: parse_dependency_file(x,base_dir,[]), depends) + + # Build a number of sources from the candidates. This is a Set for the poor + # Two level dict. One for + dirs = {} + files = {} + for (_,dir,deps) in candidates: + if not dir in dirs: + dirs[dir] = {} + for dep in deps: + if not dep in dirs[dir]: + dirs[dir][dep] = dep + if not dep in files: + files[dep] = dep + + sources = files.keys() + + print "Found %d candidates" % (len(sources)) + print "Will run inefficient generation of gcov files now" + generate_covs(dirs) + + print "Analyzing Gcov" + analyze_coverage(sources, results, dirs.keys(), runid, base_dir) + print "Done" diff --git a/WebKitTools/CodeCoverage/snow.png b/WebKitTools/CodeCoverage/snow.png Binary files differnew file mode 100644 index 0000000..a4ba373 --- /dev/null +++ b/WebKitTools/CodeCoverage/snow.png diff --git a/WebKitTools/CygwinDownloader/cygwin-downloader.py b/WebKitTools/CygwinDownloader/cygwin-downloader.py new file mode 100644 index 0000000..a0e7089 --- /dev/null +++ b/WebKitTools/CygwinDownloader/cygwin-downloader.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +import os, random, sys, time, urllib + +# +# Options +# + +dry_run = len(sys.argv) > 1 and "--dry-run" in set(sys.argv[1:]) +quiet = len(sys.argv) > 1 and "--quiet" in set(sys.argv[1:]) + +# +# Functions and constants +# + +def download_progress_hook(block_count, block_size, total_blocks): + if quiet or random.random() > 0.5: + return + sys.stdout.write(".") + sys.stdout.flush() + +def download_url_to_file(url, file, message): + if not quiet: + print message + " ", + if not dry_run: + dir = os.path.dirname(file) + if len(dir) and not os.path.exists(dir): + os.makedirs(dir) + urllib.urlretrieve(url, file, download_progress_hook) + if not quiet: + print + +# This is mostly just the list of North America http mirrors from http://cygwin.com/mirrors.html, +# but a few have been removed that seemed unresponsive from Cupertino. +mirror_servers = ["http://cygwin.elite-systems.org/", + "http://mirror.mcs.anl.gov/cygwin/", + "http://cygwin.osuosl.org/", + "http://mirrors.kernel.org/sourceware/cygwin/", + "http://cygwin.mirrors.hoobly.com/", + "http://cygwin.rtin.bz/", + "http://mirrors.wikifusion.info/cygwin/", + "http://mirrors.xmission.com/cygwin/", + "http://sourceware.mirrors.tds.net/pub/sourceware.org/cygwin/"] + +package_mirror_url = mirror_servers[random.choice(range(len(mirror_servers)))] + +def download_package(package, message): + download_url_to_file(package_mirror_url + package["path"], package["path"], message) + +required_packages = frozenset(["apache", + "bc", + "bison", + "curl", + "diffutils", + "e2fsprogs", + "emacs", + "flex", + "gcc", + "gperf", + "keychain", + "make", + "nano", + "openssh", + "patch", + "perl", + "perl-libwin32", + "python", + "rebase", + "rsync", + "subversion", + "unzip", + "vim", + "zip"]) + +# +# Main +# + +print "Using Cygwin mirror server " + package_mirror_url + " to download setup.ini..." + +urllib.urlretrieve(package_mirror_url + "setup.ini", "setup.ini.orig") + +downloaded_packages_file_path = "setup.ini.orig" +downloaded_packages_file = file(downloaded_packages_file_path, "r") +if not dry_run: + modified_packages_file = file("setup.ini", "w") + +packages = {} +current_package = '' +for line in downloaded_packages_file.readlines(): + if line[0] == "@": + current_package = line[2:-1] + packages[current_package] = {"name": current_package, "needs_download": False, "requires": [], "path": ""} + elif line[:10] == "category: ": + if current_package in required_packages: + line = "category: Base\n" + if "Base" in set(line[10:-1].split()): + packages[current_package]["needs_download"] = True + elif line[:10] == "requires: ": + packages[current_package]["requires"] = line[10:].split() + packages[current_package]["requires"].sort() + elif line[:9] == "install: " and not len(packages[current_package]["path"]): + end_of_path = line.find(" ", 9) + if end_of_path != -1: + packages[current_package]["path"] = line[9:end_of_path] + if not dry_run: + modified_packages_file.write(line) + +downloaded_packages_file.close() +os.remove(downloaded_packages_file_path) +if not dry_run: + modified_packages_file.close() + +names_to_download = set() +package_names = packages.keys() +package_names.sort() + +def add_package_and_dependencies(name): + if name in names_to_download: + return + packages[name]["needs_download"] = True + names_to_download.add(name) + for dep in packages[name]["requires"]: + add_package_and_dependencies(dep) + +for name in package_names: + if packages[name]["needs_download"]: + add_package_and_dependencies(name) + +downloaded_so_far = 0 +for name in package_names: + if packages[name]["needs_download"]: + downloaded_so_far += 1 + download_package(packages[name], "Downloading package %3d of %3d (%s)" % (downloaded_so_far, len(names_to_download), name)) + +download_url_to_file("http://cygwin.com/setup.exe", "setup.exe", "Downloading setup.exe") + +seconds_to_sleep = 10 + +print """ +Finished downloading Cygwin. In %d seconds, +I will run setup.exe. Select the "Install +from Local Directory" option and browse to +"%s" +when asked for the "Local Package Directory". +""" % (seconds_to_sleep, os.getcwd()) + + +while seconds_to_sleep > 0: + print "%d..." % seconds_to_sleep, + sys.stdout.flush() + time.sleep(1) + seconds_to_sleep -= 1 +print + +if not dry_run: + os.execl("setup.exe") diff --git a/WebKitTools/CygwinDownloader/cygwin-downloader.zip b/WebKitTools/CygwinDownloader/cygwin-downloader.zip Binary files differnew file mode 100644 index 0000000..40f43b3 --- /dev/null +++ b/WebKitTools/CygwinDownloader/cygwin-downloader.zip diff --git a/WebKitTools/CygwinDownloader/make-zip.sh b/WebKitTools/CygwinDownloader/make-zip.sh new file mode 100755 index 0000000..4a389a9 --- /dev/null +++ b/WebKitTools/CygwinDownloader/make-zip.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +PYTHONEXE=$(cygpath -u "${SYSTEMDRIVE}\\Python25\\python.exe") +ZIPNAME="cygwin-downloader.zip" + +if [[ ! -f "${PYTHONEXE}" ]]; then + echo "Couldn't find python.exe at ${PYTHONEXE}" 1>&2 + exit 1 +fi + +"${PYTHONEXE}" setup.py py2exe || { + echo "Failed executing setup.py" 1>&2 + exit 1 +} + +rm -f "${ZIPNAME}" + +cd dist + +zip -r ../"${ZIPNAME}" * || { + echo "Failed to create cygwin-downloader" 1>&2 + exit 1 +} + +cd .. + +rm -rf build dist || { + echo "Failed to cleanup cygwin-downloader and build directories" 1>&2 + exit 1 +} diff --git a/WebKitTools/CygwinDownloader/setup.py b/WebKitTools/CygwinDownloader/setup.py new file mode 100644 index 0000000..c3171d9 --- /dev/null +++ b/WebKitTools/CygwinDownloader/setup.py @@ -0,0 +1,4 @@ +from distutils.core import setup +import py2exe + +setup(console=['cygwin-downloader.py']) diff --git a/WebKitTools/DrawTest/AppDelegate.h b/WebKitTools/DrawTest/AppDelegate.h new file mode 100644 index 0000000..7103bb8 --- /dev/null +++ b/WebKitTools/DrawTest/AppDelegate.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + + +@interface AppDelegate : NSObject { + IBOutlet NSWindow *svgImageRepTestWindow; +} + +- (IBAction)showTestsPanel:(id)sender; +- (IBAction)showImageRepTestWindow:(id)sender; +- (IBAction)showInspectorPanel:(id)sender; + +@end diff --git a/WebKitTools/DrawTest/AppDelegate.m b/WebKitTools/DrawTest/AppDelegate.m new file mode 100644 index 0000000..0f20b35 --- /dev/null +++ b/WebKitTools/DrawTest/AppDelegate.m @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "AppDelegate.h" + +#import "TestController.h" +#import "DrawTestInspectorController.h" + +@implementation AppDelegate + +- (IBAction)showTestsPanel:(id)sender +{ + [[TestController sharedController] showTestsPanel:sender]; +} + +- (IBAction)showImageRepTestWindow:(id)sender +{ + [svgImageRepTestWindow makeKeyAndOrderFront:sender]; +} + +- (IBAction)showInspectorPanel:(id)sender +{ + [[DrawTestInspectorController sharedInstance] showInspectorPanel:sender]; +} + +- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender +{ + return NO; +} + +@end diff --git a/WebKitTools/DrawTest/DrawTest.xcodeproj/project.pbxproj b/WebKitTools/DrawTest/DrawTest.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8d62751 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTest.xcodeproj/project.pbxproj @@ -0,0 +1,388 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 78662E6D096B4E1600907EA7 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 78662E6C096B4E1600907EA7 /* WebKit.framework */; }; + 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; }; + 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; + 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; + A8C006CF0898634600BA5114 /* SVGTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006B00898634600BA5114 /* SVGTest.m */; }; + A8C006D00898634600BA5114 /* ScalingImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006B20898634600BA5114 /* ScalingImageView.m */; }; + A8C006D20898634600BA5114 /* DrawTestView.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006B50898634600BA5114 /* DrawTestView.m */; }; + A8C006D30898634600BA5114 /* DrawTestToolbarController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006B70898634600BA5114 /* DrawTestToolbarController.m */; }; + A8C006D40898634600BA5114 /* DrawTestInspectorController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006BB0898634600BA5114 /* DrawTestInspectorController.m */; }; + A8C006D50898634600BA5114 /* DrawTestDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006BD0898634600BA5114 /* DrawTestDocument.m */; }; + A8C006E10898634600BA5114 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006CA0898634600BA5114 /* AppDelegate.m */; }; + A8C006E20898634600BA5114 /* TestViewerSplitView.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006CC0898634600BA5114 /* TestViewerSplitView.m */; }; + A8C006E30898634600BA5114 /* TestController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C006CE0898634600BA5114 /* TestController.m */; }; + A8C006F3089865E900BA5114 /* DrawTestDocument.nib in Resources */ = {isa = PBXBuildFile; fileRef = A8C006ED089865E900BA5114 /* DrawTestDocument.nib */; }; + A8C006F4089865E900BA5114 /* Inspector.nib in Resources */ = {isa = PBXBuildFile; fileRef = A8C006EF089865E900BA5114 /* Inspector.nib */; }; + A8C006F5089865E900BA5114 /* TestViewer.nib in Resources */ = {isa = PBXBuildFile; fileRef = A8C006F1089865E900BA5114 /* TestViewer.nib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; + 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; }; + 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; + 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; + 32CA4F630368D1EE00C91783 /* DrawTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawTest_Prefix.pch; sourceTree = "<group>"; }; + 78662E6C096B4E1600907EA7 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; }; + 8D1107320486CEB800E47090 /* DrawTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DrawTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A8C006AF0898634600BA5114 /* TestController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestController.h; sourceTree = "<group>"; }; + A8C006B00898634600BA5114 /* SVGTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVGTest.m; sourceTree = "<group>"; }; + A8C006B10898634600BA5114 /* SVGTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGTest.h; sourceTree = "<group>"; }; + A8C006B20898634600BA5114 /* ScalingImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScalingImageView.m; sourceTree = "<group>"; }; + A8C006B30898634600BA5114 /* ScalingImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScalingImageView.h; sourceTree = "<group>"; }; + A8C006B50898634600BA5114 /* DrawTestView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawTestView.m; sourceTree = "<group>"; }; + A8C006B60898634600BA5114 /* DrawTestView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawTestView.h; sourceTree = "<group>"; }; + A8C006B70898634600BA5114 /* DrawTestToolbarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawTestToolbarController.m; sourceTree = "<group>"; }; + A8C006B80898634600BA5114 /* DrawTestDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawTestDocument.h; sourceTree = "<group>"; }; + A8C006BA0898634600BA5114 /* DrawTestToolbarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawTestToolbarController.h; sourceTree = "<group>"; }; + A8C006BB0898634600BA5114 /* DrawTestInspectorController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawTestInspectorController.m; sourceTree = "<group>"; }; + A8C006BC0898634600BA5114 /* DrawTestInspectorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawTestInspectorController.h; sourceTree = "<group>"; }; + A8C006BD0898634600BA5114 /* DrawTestDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawTestDocument.m; sourceTree = "<group>"; }; + A8C006CA0898634600BA5114 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; + A8C006CB0898634600BA5114 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; + A8C006CC0898634600BA5114 /* TestViewerSplitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestViewerSplitView.m; sourceTree = "<group>"; }; + A8C006CD0898634600BA5114 /* TestViewerSplitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestViewerSplitView.h; sourceTree = "<group>"; }; + A8C006CE0898634600BA5114 /* TestController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestController.m; sourceTree = "<group>"; }; + A8C006EE089865E900BA5114 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/DrawTestDocument.nib; sourceTree = "<group>"; }; + A8C006F0089865E900BA5114 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Inspector.nib; sourceTree = "<group>"; }; + A8C006F2089865E900BA5114 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/TestViewer.nib; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8D11072E0486CEB800E47090 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, + 78662E6D096B4E1600907EA7 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + A8C006E5089863A100BA5114 /* Viewer */, + A8C006E6089863B100BA5114 /* Test Browser */, + A8C006CA0898634600BA5114 /* AppDelegate.m */, + A8C006CB0898634600BA5114 /* AppDelegate.h */, + A8C006B20898634600BA5114 /* ScalingImageView.m */, + A8C006B30898634600BA5114 /* ScalingImageView.h */, + ); + name = Classes; + sourceTree = "<group>"; + }; + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 78662E6C096B4E1600907EA7 /* WebKit.framework */, + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = "<group>"; + }; + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 29B97324FDCFA39411CA2CEA /* AppKit.framework */, + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, + 29B97325FDCFA39411CA2CEA /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = "<group>"; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D1107320486CEB800E47090 /* DrawTest.app */, + ); + name = Products; + sourceTree = "<group>"; + }; + 29B97314FDCFA39411CA2CEA /* DrawTest */ = { + isa = PBXGroup; + children = ( + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = DrawTest; + sourceTree = "<group>"; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* DrawTest_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = "<group>"; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 8D1107310486CEB800E47090 /* Info.plist */, + 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, + 29B97318FDCFA39411CA2CEA /* MainMenu.nib */, + A8C006ED089865E900BA5114 /* DrawTestDocument.nib */, + A8C006EF089865E900BA5114 /* Inspector.nib */, + A8C006F1089865E900BA5114 /* TestViewer.nib */, + ); + name = Resources; + sourceTree = "<group>"; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + A8C006E5089863A100BA5114 /* Viewer */ = { + isa = PBXGroup; + children = ( + A8C006BA0898634600BA5114 /* DrawTestToolbarController.h */, + A8C006B70898634600BA5114 /* DrawTestToolbarController.m */, + A8C006B60898634600BA5114 /* DrawTestView.h */, + A8C006B50898634600BA5114 /* DrawTestView.m */, + A8C006B80898634600BA5114 /* DrawTestDocument.h */, + A8C006BD0898634600BA5114 /* DrawTestDocument.m */, + ); + name = Viewer; + sourceTree = "<group>"; + }; + A8C006E6089863B100BA5114 /* Test Browser */ = { + isa = PBXGroup; + children = ( + A8C006B00898634600BA5114 /* SVGTest.m */, + A8C006B10898634600BA5114 /* SVGTest.h */, + A8C006BB0898634600BA5114 /* DrawTestInspectorController.m */, + A8C006BC0898634600BA5114 /* DrawTestInspectorController.h */, + A8C006AF0898634600BA5114 /* TestController.h */, + A8C006CE0898634600BA5114 /* TestController.m */, + A8C006CC0898634600BA5114 /* TestViewerSplitView.m */, + A8C006CD0898634600BA5114 /* TestViewerSplitView.h */, + ); + name = "Test Browser"; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8D1107260486CEB800E47090 /* DrawTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = A8C006740898624E00BA5114 /* Build configuration list for PBXNativeTarget "DrawTest" */; + buildPhases = ( + 8D1107290486CEB800E47090 /* Resources */, + 8D11072C0486CEB800E47090 /* Sources */, + 8D11072E0486CEB800E47090 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DrawTest; + productInstallPath = "$(HOME)/Applications"; + productName = DrawTest; + productReference = 8D1107320486CEB800E47090 /* DrawTest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = A8C006780898624E00BA5114 /* Build configuration list for PBXProject "DrawTest" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* DrawTest */; + projectDirPath = ""; + projectRoot = ""; + shouldCheckCompatibility = 1; + targets = ( + 8D1107260486CEB800E47090 /* DrawTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D1107290486CEB800E47090 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A8C006F3089865E900BA5114 /* DrawTestDocument.nib in Resources */, + 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, + A8C006F4089865E900BA5114 /* Inspector.nib in Resources */, + 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */, + A8C006F5089865E900BA5114 /* TestViewer.nib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8D11072C0486CEB800E47090 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A8C006E10898634600BA5114 /* AppDelegate.m in Sources */, + A8C006D50898634600BA5114 /* DrawTestDocument.m in Sources */, + A8C006D40898634600BA5114 /* DrawTestInspectorController.m in Sources */, + A8C006D30898634600BA5114 /* DrawTestToolbarController.m in Sources */, + A8C006D20898634600BA5114 /* DrawTestView.m in Sources */, + A8C006CF0898634600BA5114 /* SVGTest.m in Sources */, + A8C006D00898634600BA5114 /* ScalingImageView.m in Sources */, + A8C006E30898634600BA5114 /* TestController.m in Sources */, + A8C006E20898634600BA5114 /* TestViewerSplitView.m in Sources */, + 8D11072D0486CEB800E47090 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C165DFE840E0CC02AAC07 /* English */, + ); + name = InfoPlist.strings; + sourceTree = "<group>"; + }; + 29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = { + isa = PBXVariantGroup; + children = ( + 29B97319FDCFA39411CA2CEA /* English */, + ); + name = MainMenu.nib; + sourceTree = "<group>"; + }; + A8C006ED089865E900BA5114 /* DrawTestDocument.nib */ = { + isa = PBXVariantGroup; + children = ( + A8C006EE089865E900BA5114 /* English */, + ); + name = DrawTestDocument.nib; + sourceTree = "<group>"; + }; + A8C006EF089865E900BA5114 /* Inspector.nib */ = { + isa = PBXVariantGroup; + children = ( + A8C006F0089865E900BA5114 /* English */, + ); + name = Inspector.nib; + sourceTree = "<group>"; + }; + A8C006F1089865E900BA5114 /* TestViewer.nib */ = { + isa = PBXVariantGroup; + children = ( + A8C006F2089865E900BA5114 /* English */, + ); + name = TestViewer.nib; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + A8C006750898624E00BA5114 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = DrawTest_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PREBINDING = NO; + PRODUCT_NAME = DrawTest; + WRAPPER_EXTENSION = app; + ZERO_LINK = YES; + }; + name = Debug; + }; + A8C006760898624E00BA5114 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = DrawTest_Prefix.pch; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PREBINDING = NO; + PRODUCT_NAME = DrawTest; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Release; + }; + A8C006790898624E00BA5114 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu99; + }; + name = Debug; + }; + A8C0067A0898624E00BA5114 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu99; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A8C006740898624E00BA5114 /* Build configuration list for PBXNativeTarget "DrawTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8C006750898624E00BA5114 /* Debug */, + A8C006760898624E00BA5114 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A8C006780898624E00BA5114 /* Build configuration list for PBXProject "DrawTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8C006790898624E00BA5114 /* Debug */, + A8C0067A0898624E00BA5114 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/WebKitTools/DrawTest/DrawTestDocument.h b/WebKitTools/DrawTest/DrawTestDocument.h new file mode 100644 index 0000000..b0b16d9 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestDocument.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + +@class DrawTestView; +@class DrawTestToolbarController; + +@interface DrawTestDocument : NSDocument +{ + IBOutlet DrawTestView *drawView; + IBOutlet NSDrawer *debugDrawer; + + DrawTestToolbarController *toolbarController; +} + +// Debug menu +- (IBAction)dumpSVGToConsole:(id)sender; +- (IBAction)toggleDebugDrawer:(id)sender; +- (IBAction)runWindowResizeTest:(id)sender; + +@end diff --git a/WebKitTools/DrawTest/DrawTestDocument.m b/WebKitTools/DrawTest/DrawTestDocument.m new file mode 100644 index 0000000..c71e7ad --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestDocument.m @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "DrawTestDocument.h" +#import "DrawTestView.h" +#import "DrawTestToolbarController.h" +#import <WebKit/WebView.h> +#import <WebKit/WebFrame.h> +#import <WebKit/WebDataSource.h> + +@implementation DrawTestDocument + +- (id)initWithType:(NSString *)typeName error:(NSError **)outError +{ + if (outError) { + NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys: + @"No document could be created.", NSLocalizedDescriptionKey, + @"New document creation not yet supported.", NSLocalizedFailureReasonErrorKey, + nil]; + *outError = [NSError errorWithDomain:NSCocoaErrorDomain code:0 userInfo:errorInfo]; + } + [self release]; + return nil; +} + +- (void)dealloc +{ + [toolbarController release]; + [super dealloc]; +} + +- (NSString *)windowNibName +{ + return @"DrawTestDocument"; +} + +- (BOOL)readFromFile:(NSString *)filename ofType:(NSString *)docType +{ + // TODO: Check the validity of the document before returning YES. + return YES; +} + +- (void)windowControllerDidLoadNib:(NSWindowController *)aController +{ + [super windowControllerDidLoadNib:aController]; + toolbarController = [[DrawTestToolbarController alloc] initWithDrawView:drawView]; + [drawView setDocument:[self fileURL]]; +} + +- (IBAction)dumpSVGToConsole:(id)sender +{ + WebDataSource* dataSource = [[drawView mainFrame] dataSource]; + NSLog(@"SVG Markup for file %@:\n%@", [self fileURL], [[dataSource representation] documentSource]); +} + +- (IBAction)openSourceForSelection:(id)sender +{ + // TODO: The "path" message (below) will not produce a valid pathname if we are dealing with a remote file. + NSString *filename = [[self fileURL] path]; + [[NSWorkspace sharedWorkspace] openFile:filename withApplication:@"TextEdit"]; +} + +- (NSData *)dataRepresentationOfType:(NSString *)aType +{ + WebDataSource* dataSource = [[drawView mainFrame] dataSource]; + return [dataSource data]; +} + +#pragma mark - +#pragma mark Debug Methods + +- (IBAction)toggleDebugDrawer:(id)sender +{ + [debugDrawer toggle:sender]; +} + +- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item +{ + return nil; +} + +- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item +{ + return NO; +} + +- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item +{ + return 0; +} + +- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item +{ + return nil; +} + +- (IBAction)runWindowResizeTest:(id)sender +{ + NSWindow *window = [drawView window]; + NSScreen *screen = [window screen]; + float screenHeight = [screen visibleFrame].size.height; + NSRect originalFrame = [window frame]; + // initial setup + BOOL toolbarVisible = [[window toolbar] isVisible]; + if (toolbarVisible) [window toggleToolbarShown:self]; + [window setFrame:NSMakeRect(0,screenHeight-100,100,100) display:YES]; + + // grab time. + CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); + + // run test + for (int x = 0; x < 3; x++) { + for (float size = 100; size < 500.f; size += 20.f) { + [window setFrame:NSMakeRect(0, screenHeight-size, size, size) display:YES]; + } + } + + double elapsed = CFAbsoluteTimeGetCurrent() - start; + + // log + NSLog(@"Window resize test: %fs", elapsed); + + // restore + if (toolbarVisible) [window toggleToolbarShown:self]; + [window setFrame:originalFrame display:YES]; +} + +@end diff --git a/WebKitTools/DrawTest/DrawTestInspectorController.h b/WebKitTools/DrawTest/DrawTestInspectorController.h new file mode 100644 index 0000000..43c06f0 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestInspectorController.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + + +@interface DrawTestInspectorController : NSObject { + IBOutlet NSPanel *_inspectorPanel; +} + ++ (id)sharedInstance; + +- (IBAction)showInspectorPanel:(id)sender; + +@end diff --git a/WebKitTools/DrawTest/DrawTestInspectorController.m b/WebKitTools/DrawTest/DrawTestInspectorController.m new file mode 100644 index 0000000..604bf03 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestInspectorController.m @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "DrawTestInspectorController.h" + +@implementation DrawTestInspectorController + ++ (id)sharedInstance +{ + static DrawTestInspectorController *__sharedController = nil; + if (!__sharedController) { + __sharedController = [[self alloc] init]; + } + return __sharedController; +} + +- (IBAction)showInspectorPanel:(id)sender +{ + if (!_inspectorPanel) { + [NSBundle loadNibNamed:@"Inspector" owner:self]; + } + [_inspectorPanel makeKeyAndOrderFront:self]; +} + + +@end diff --git a/WebKitTools/DrawTest/DrawTestToolbarController.h b/WebKitTools/DrawTest/DrawTestToolbarController.h new file mode 100644 index 0000000..a69fb57 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestToolbarController.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + +@class WebView; + +@interface DrawTestToolbarController : NSObject { + WebView *_drawView; + NSMutableDictionary *_toolbarItems; +} + +- (id)initWithDrawView:(WebView *)drawView; + +@end diff --git a/WebKitTools/DrawTest/DrawTestToolbarController.m b/WebKitTools/DrawTest/DrawTestToolbarController.m new file mode 100644 index 0000000..9190252 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestToolbarController.m @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "DrawTestToolbarController.h" + +enum +{ + ToolbarBrowseToolTag = 0, + ToolbarPanToolTag, + ToolbarZoomToolTag, + + ToolbarPointerToolTag, + ToolbarLineToolTag, + ToolbarRectangleToolTag, + ToolbarElipseToolTag, + ToolbarTriangleToolTag, + ToolbarPolyLineToolTag, + ToolbarArcToolTag, + + ToolbarDeleteSelectionTag, + + ToolbarMoveForwardTag, + ToolbarMoveBackwardTag, + ToolbarMoveToFrontTag, + ToolbarMoveToBackTag, + ToolbarMiscItem +}; + +// Constants +NSString *ToolbarIdentifier = @"Main Document Toolbar"; + +NSString *ToolbarBrowseToolIdentifier = @"Browse"; +NSString *ToolbarPanToolIdentifier = @"Pan"; +NSString *ToolbarZoomToolIdentifier = @"Zoom"; + +NSString *ToolbarPointerToolIdentifier = @"Pointer"; +NSString *ToolbarRectangleToolIdentifier = @"Rectangle"; +NSString *ToolbarElipseToolIdentifier = @"Oval"; +NSString *ToolbarTriangleToolIdentifier = @"Triangle"; +NSString *ToolbarPolyLineToolIdentifier = @"PolyLine"; +NSString *ToolbarArcToolIdentifier = @"Arc"; + +NSString *ToolbarDeleteShapeIdentifier = @"Delete"; +NSString *ToolbarMoveForwardIdentifier = @"Forward"; +NSString *ToolbarMoveBackwardIdentifier = @"Backward"; +NSString *ToolbarMoveToFrontIdentifier = @"Front"; +NSString *ToolbarMoveToBackIdentifier = @"Back"; + +NSString *ToolbarPointerToolImage = @"Toolbar_Pointer"; +NSString *ToolbarRectangleToolImage = @"Toolbar_Rectangle"; +NSString *ToolbarElipseToolImage = @"Toolbar_Oval"; +NSString *ToolbarTriangleToolImage = @"Toolbar_Triangle"; + +NSString *ToolbarDeleteShapeImage = @"Toolbar_Delete"; +NSString *ToolbarMoveForwardImage = @"Toolbar_Forward"; +NSString *ToolbarMoveBackwardImage = @"Toolbar_Backward"; +NSString *ToolbarMoveToFrontImage = @"Toolbar_Front"; +NSString *ToolbarMoveToBackImage = @"Toolbar_Back"; + +@interface DrawTestToolbarController (InternalMethods) +- (void)setupToolbar; +- (void)addToolbarItemWithIdentifier:(NSString *)identifier withImage:(NSString *)image withTag:(int)tag; +- (void)addToolbarItemWithIdentifier:(NSString *)identifier withImage:(NSString *)image; +- (void)addToolbarItem:(NSString *)identifier + withLabel:(NSString *)label + withPaletteLabel:(NSString *)paletteLabel + withImage:(NSString *)imageName + withToolTip:(NSString *)toolTip + withTag:(int)tag; +@end + + +@implementation DrawTestToolbarController + +- (id)initWithDrawView:(WebView *)drawView +{ + if (self = [super init]){ + _drawView = [drawView retain]; + [self setupToolbar]; // could be done lazily. + } + return self; +} + +- (void)dealloc +{ + [_toolbarItems release]; + [super dealloc]; +} + + +- (void)addToolbarItemWithIdentifier:(NSString *)identifier withImage:(NSString *)image withTag:(int)tag +{ + + [self addToolbarItem:identifier + withLabel:identifier + withPaletteLabel:identifier + withImage:image + withToolTip:identifier + withTag:tag]; +} + +- (void)addToolbarItemWithIdentifier:(NSString *)identifier withImage:(NSString *)image +{ + [self addToolbarItemWithIdentifier:identifier withImage:image withTag:ToolbarMiscItem]; +} + +- (void)addToolbarItem:(NSString *)identifier + withLabel:(NSString *)label + withPaletteLabel:(NSString *)paletteLabel + withImage:(NSString *)imageName + withToolTip:(NSString *)toolTip + withTag:(int)tag +{ + NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:identifier] autorelease]; + + [item setLabel:label]; + [item setPaletteLabel:paletteLabel]; + [item setToolTip:toolTip]; + [item setImage:[NSImage imageNamed:imageName]]; + [item setTarget:self]; + [item setAction:@selector(clickedToolbarItem:)]; + [item setTag:tag]; + + [_toolbarItems setObject:item forKey:identifier]; +} + +- (void)setupToolbar +{ + _toolbarItems = [[NSMutableDictionary alloc] init]; + + [self addToolbarItemWithIdentifier:ToolbarBrowseToolIdentifier + withImage:ToolbarPointerToolImage + withTag:ToolbarBrowseToolTag]; + [[_toolbarItems objectForKey:ToolbarBrowseToolIdentifier] setImage:[[NSCursor pointingHandCursor] image]]; + + [self addToolbarItemWithIdentifier:ToolbarPanToolIdentifier + withImage:ToolbarPointerToolImage + withTag:ToolbarPanToolTag]; + [[_toolbarItems objectForKey:ToolbarPanToolIdentifier] setImage:[[NSCursor openHandCursor] image]]; + + [self addToolbarItemWithIdentifier:ToolbarZoomToolIdentifier + withImage:ToolbarPointerToolImage + withTag:ToolbarZoomToolTag]; + + + [self addToolbarItemWithIdentifier:ToolbarPointerToolIdentifier + withImage:ToolbarPointerToolImage + withTag:ToolbarPointerToolTag]; + + [self addToolbarItemWithIdentifier:ToolbarRectangleToolIdentifier + withImage:ToolbarRectangleToolImage + withTag:ToolbarRectangleToolTag]; + + [self addToolbarItemWithIdentifier:ToolbarElipseToolIdentifier + withImage:ToolbarElipseToolImage + withTag:ToolbarElipseToolTag]; + + [self addToolbarItemWithIdentifier:ToolbarTriangleToolIdentifier + withImage:ToolbarTriangleToolImage + withTag:ToolbarTriangleToolTag]; + + [self addToolbarItemWithIdentifier:ToolbarDeleteShapeIdentifier + withImage:ToolbarDeleteShapeImage + withTag:ToolbarDeleteSelectionTag]; + + [self addToolbarItemWithIdentifier:ToolbarMoveForwardIdentifier + withImage:ToolbarMoveForwardImage + withTag:ToolbarMoveForwardTag]; + + [self addToolbarItemWithIdentifier:ToolbarMoveBackwardIdentifier + withImage:ToolbarMoveBackwardImage + withTag:ToolbarMoveBackwardTag]; + + [self addToolbarItemWithIdentifier:ToolbarMoveToFrontIdentifier + withImage:ToolbarMoveToFrontImage + withTag:ToolbarMoveToFrontTag]; + + [self addToolbarItemWithIdentifier:ToolbarMoveToBackIdentifier + withImage:ToolbarMoveToBackImage + withTag:ToolbarMoveToBackTag]; + + + NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:ToolbarIdentifier] autorelease]; + + [toolbar setAllowsUserCustomization:YES]; + [toolbar setAutosavesConfiguration:YES]; + [toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel]; + [toolbar setSizeMode:NSToolbarSizeModeSmall]; + [toolbar setDisplayMode:NSToolbarDisplayModeLabelOnly]; + [toolbar setDelegate:self]; + [toolbar setSelectedItemIdentifier:ToolbarBrowseToolIdentifier]; + [toolbar setVisible:NO]; + + [[_drawView window] setToolbar:toolbar]; +} + + +- (void)clickedToolbarItem:(id)sender +{ + int tag = [sender tag]; + + switch(tag) { +#if 0 + case ToolbarBrowseToolTag: + [_drawView setToolMode:DrawViewToolBrowse]; + break; + case ToolbarPanToolTag: + [_drawView setToolMode:DrawViewToolPan]; + break; + case ToolbarZoomToolTag: + [_drawView setToolMode:DrawViewToolZoom]; + break; + case ToolbarPointerToolTag: + [_drawView setToolMode:DrawViewToolArrow]; + break; + case ToolbarRectangleToolTag: + [_drawView setToolMode:DrawViewToolRectangle]; + break; + case ToolbarElipseToolTag: + [_drawView setToolMode:DrawViewToolElipse]; + break; + case ToolbarTriangleToolTag: + [_drawView setToolMode:DrawViewToolTriangle]; + break; + case ToolbarMoveForwardTag: + [_drawView moveSelectionForward:sender]; + break; + case ToolbarMoveBackwardTag: + [_drawView moveSelectionBackward:sender]; + break; + case ToolbarDeleteSelectionTag: + [_drawView deleteSelection:sender]; + break; +#endif + default: + NSLog(@"Toolbar item: %i not implemented!", tag); + } + + [_drawView setNeedsDisplay:YES]; +} + +// NSToolbar delegate methods +- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdent + willBeInsertedIntoToolbar:(BOOL)willBeInserted +{ + NSToolbarItem * toolbarItem = [_toolbarItems objectForKey:itemIdent]; + + if( toolbarItem == nil ) + toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease]; + + return toolbarItem; +} + +- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar +{ + return [NSArray arrayWithObjects: + ToolbarBrowseToolIdentifier, + ToolbarPanToolIdentifier, + ToolbarZoomToolIdentifier, + ToolbarPointerToolIdentifier, + ToolbarRectangleToolIdentifier, + ToolbarElipseToolIdentifier, + ToolbarTriangleToolIdentifier, + ToolbarDeleteShapeIdentifier, + NSToolbarShowColorsItemIdentifier, + ToolbarMoveForwardIdentifier, + ToolbarMoveBackwardIdentifier, + ToolbarMoveToFrontIdentifier, + ToolbarMoveToBackIdentifier, + NSToolbarCustomizeToolbarItemIdentifier, + NSToolbarFlexibleSpaceItemIdentifier, + NSToolbarSpaceItemIdentifier, + NSToolbarSeparatorItemIdentifier, nil]; +} + +- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar +{ + return [NSArray arrayWithObjects: + ToolbarBrowseToolIdentifier, + ToolbarPanToolIdentifier, + //ToolbarZoomToolIdentifier, + NSToolbarFlexibleSpaceItemIdentifier, + ToolbarPointerToolIdentifier, + ToolbarRectangleToolIdentifier, + ToolbarElipseToolIdentifier, + //ToolbarTriangleToolIdentifier, + //NSToolbarSeparatorItemIdentifier, + ToolbarDeleteShapeIdentifier, + //ToolbarMoveForwardIdentifier, + //ToolbarMoveBackwardIdentifier, + //ToolbarMoveToFrontIdentifier, + //ToolbarMoveToBackIdentifier, + NSToolbarSeparatorItemIdentifier, + //NSToolbarShowColorsItemIdentifier, + //NSToolbarFlexibleSpaceItemIdentifier, + NSToolbarCustomizeToolbarItemIdentifier, + nil]; +} + +- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar +{ + return [NSArray arrayWithObjects: + ToolbarBrowseToolIdentifier, + ToolbarPanToolIdentifier, + ToolbarZoomToolIdentifier, + ToolbarPointerToolIdentifier, + ToolbarRectangleToolIdentifier, + ToolbarElipseToolIdentifier, + ToolbarTriangleToolIdentifier, + nil]; +} + +- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem +{ + BOOL enabled = YES; + +#if 0 + switch([theItem tag]) { + case ToolbarMoveForwardTag: + case ToolbarMoveBackwardTag: + case ToolbarMoveToFrontTag: + case ToolbarMoveToBackTag: + case ToolbarDeleteSelectionTag: + enabled = ([[_drawView selectedCanvasItems] count] != 0); + } +#endif + + return enabled; +} + +@end diff --git a/WebKitTools/DrawTest/DrawTestView.h b/WebKitTools/DrawTest/DrawTestView.h new file mode 100644 index 0000000..95d5956 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestView.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + +#import <WebKit/WebView.h> + +@interface DrawTestView : WebView +{ + +} + +- (void)setDocument:(NSURL *)documentURL; + +@end diff --git a/WebKitTools/DrawTest/DrawTestView.m b/WebKitTools/DrawTest/DrawTestView.m new file mode 100644 index 0000000..c865f99 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTestView.m @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 <WebKit/WebFrame.h> + +#import "DrawTestView.h" + +@implementation DrawTestView + +- (void)setDocument:(NSURL *)documentURL +{ + [[self mainFrame] loadRequest:[NSURLRequest requestWithURL:documentURL]]; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +@end diff --git a/WebKitTools/DrawTest/DrawTest_Prefix.pch b/WebKitTools/DrawTest/DrawTest_Prefix.pch new file mode 100644 index 0000000..8393f01 --- /dev/null +++ b/WebKitTools/DrawTest/DrawTest_Prefix.pch @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +// +// Prefix header for all source files of the 'DrawTest' target in the 'DrawTest' project +// + +#ifdef __OBJC__ +#import <Cocoa/Cocoa.h> + +#define foreacharray(__variable, __container) \ + for (int __variable##__i=0, __variable##__n=[__container count]; \ + __variable##__i < __variable##__n && (__variable = [__container objectAtIndex:__variable##__i]); \ + ++__variable##__i) +#endif diff --git a/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/classes.nib b/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/classes.nib new file mode 100644 index 0000000..296ffc3 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/classes.nib @@ -0,0 +1,34 @@ +{ + IBClasses = ( + { + ACTIONS = {toggleShowDebugAxes = id; toggleShowDebugString = id; }; + CLASS = DrawTestView; + LANGUAGE = ObjC; + SUPERCLASS = DrawView; + }, + { + ACTIONS = { + deleteSelection = id; + moveSelectionBackward = id; + moveSelectionForward = id; + zoomIn = id; + zoomOriginal = id; + zoomOut = id; + zoomToFit = id; + }; + CLASS = DrawView; + LANGUAGE = ObjC; + SUPERCLASS = NSView; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {dumpSVGToConsole = id; }; + CLASS = MyDocument; + LANGUAGE = ObjC; + OUTLETS = {drawView = KCanvasTestView; }; + SUPERCLASS = NSDocument; + }, + {CLASS = NSSegmentedControl; LANGUAGE = ObjC; SUPERCLASS = NSControl; } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/info.nib b/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/info.nib new file mode 100644 index 0000000..3c96fd5 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/info.nib @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>86 30 356 240 0 0 1024 746 </string> + <key>IBEditorPositions</key> + <dict> + <key>50</key> + <string>377 327 270 342 0 0 1024 746 </string> + </dict> + <key>IBFramework Version</key> + <string>437.0</string> + <key>IBOpenObjects</key> + <array> + <integer>50</integer> + <integer>5</integer> + </array> + <key>IBSystem Version</key> + <string>8C42</string> +</dict> +</plist> diff --git a/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/keyedobjects.nib b/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000..b78ff2c --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/DrawTestDocument.nib/keyedobjects.nib diff --git a/WebKitTools/DrawTest/English.lproj/InfoPlist.strings b/WebKitTools/DrawTest/English.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 0000000..0a7822d --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/InfoPlist.strings diff --git a/WebKitTools/DrawTest/English.lproj/Inspector.nib/classes.nib b/WebKitTools/DrawTest/English.lproj/Inspector.nib/classes.nib new file mode 100644 index 0000000..725f5a4 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/Inspector.nib/classes.nib @@ -0,0 +1,12 @@ +{ + IBClasses = ( + { + CLASS = DrawTestInspectorController; + LANGUAGE = ObjC; + OUTLETS = {"_inspectorPanel" = NSPanel; }; + SUPERCLASS = NSObject; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/WebKitTools/DrawTest/English.lproj/Inspector.nib/info.nib b/WebKitTools/DrawTest/English.lproj/Inspector.nib/info.nib new file mode 100644 index 0000000..d930763 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/Inspector.nib/info.nib @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>261 184 356 240 0 0 1024 746 </string> + <key>IBFramework Version</key> + <string>437.0</string> + <key>IBOpenObjects</key> + <array> + <integer>7</integer> + </array> + <key>IBSystem Version</key> + <string>8B9</string> +</dict> +</plist> diff --git a/WebKitTools/DrawTest/English.lproj/Inspector.nib/keyedobjects.nib b/WebKitTools/DrawTest/English.lproj/Inspector.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000..02869ca --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/Inspector.nib/keyedobjects.nib diff --git a/WebKitTools/DrawTest/English.lproj/MainMenu.nib/classes.nib b/WebKitTools/DrawTest/English.lproj/MainMenu.nib/classes.nib new file mode 100644 index 0000000..c0ca441 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/MainMenu.nib/classes.nib @@ -0,0 +1,44 @@ +{ + IBClasses = ( + { + ACTIONS = {showImageRepTestWindow = id; showInspectorPanel = id; showTestsPanel = id; }; + CLASS = AppDelegate; + LANGUAGE = ObjC; + OUTLETS = {svgImageRepTestWindow = NSWindow; }; + SUPERCLASS = NSObject; + }, + { + ACTIONS = { + dumpSVGToConsole = id; + openSelectionInViewer = id; + openSourceForSelection = id; + runWindowResizeTest = id; + showCompositeWindow = id; + showImageRepTestWindow = id; + showInspectorPanel = id; + showTestsPanel = id; + toggleDebugDrawer = id; + toggleFilterSupport = id; + toggleShowDebugAxes = id; + toggleShowDebugString = id; + toggleViewersScaleRule = id; + zoomIn = id; + zoomOriginal = id; + zoomOut = id; + zoomToContent = id; + }; + CLASS = FirstResponder; + LANGUAGE = ObjC; + SUPERCLASS = NSObject; + }, + {CLASS = KCanvasTestView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, + { + ACTIONS = {dumpSVGToConsole = id; }; + CLASS = MyDocument; + LANGUAGE = ObjC; + OUTLETS = {canvasView = KCanvasTestView; }; + SUPERCLASS = NSDocument; + } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/WebKitTools/DrawTest/English.lproj/MainMenu.nib/info.nib b/WebKitTools/DrawTest/English.lproj/MainMenu.nib/info.nib new file mode 100644 index 0000000..9b783e0 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/MainMenu.nib/info.nib @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>274 58 356 240 0 0 1024 746 </string> + <key>IBEditorPositions</key> + <dict> + <key>29</key> + <string>128 678 355 44 0 0 1024 746 </string> + </dict> + <key>IBFramework Version</key> + <string>439.0</string> + <key>IBOpenObjects</key> + <array> + <integer>29</integer> + </array> + <key>IBSystem Version</key> + <string>8C32</string> +</dict> +</plist> diff --git a/WebKitTools/DrawTest/English.lproj/MainMenu.nib/keyedobjects.nib b/WebKitTools/DrawTest/English.lproj/MainMenu.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000..642b5ae --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/MainMenu.nib/keyedobjects.nib diff --git a/WebKitTools/DrawTest/English.lproj/TestViewer.nib/classes.nib b/WebKitTools/DrawTest/English.lproj/TestViewer.nib/classes.nib new file mode 100644 index 0000000..eb82ec7 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/TestViewer.nib/classes.nib @@ -0,0 +1,36 @@ +{ + IBClasses = ( + {CLASS = DrawView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = KCanvasTestView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, + {CLASS = MyImageView; LANGUAGE = ObjC; SUPERCLASS = NSImageView; }, + { + ACTIONS = { + browse = id; + jumpToParentDirectory = id; + openSelectionInViewer = id; + openSourceForSelection = id; + openTestViewerForSelection = id; + showCompositeWindow = id; + showTestWindow = id; + showTestsPanel = id; + toggleViewersScaleRule = id; + }; + CLASS = TestController; + LANGUAGE = ObjC; + OUTLETS = { + "_compositeImageView" = NSImageView; + "_compositeWindow" = NSWindow; + "_parentDirectoryPopup" = NSPopUpButton; + "_splitView" = TestViewerSplitView; + "_testPanel" = NSPanel; + "_testWindow" = NSWindow; + "_testsArrayController" = NSArrayController; + "_testsTableView" = NSTableView; + }; + SUPERCLASS = NSObject; + }, + {CLASS = TestViewerSplitView; LANGUAGE = ObjC; SUPERCLASS = NSView; } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/WebKitTools/DrawTest/English.lproj/TestViewer.nib/info.nib b/WebKitTools/DrawTest/English.lproj/TestViewer.nib/info.nib new file mode 100644 index 0000000..ca801e8 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/TestViewer.nib/info.nib @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>263 119 356 240 0 0 1024 746 </string> + <key>IBFramework Version</key> + <string>437.0</string> + <key>IBOpenObjects</key> + <array> + <integer>24</integer> + <integer>60</integer> + </array> + <key>IBSystem Version</key> + <string>8C26</string> +</dict> +</plist> diff --git a/WebKitTools/DrawTest/English.lproj/TestViewer.nib/keyedobjects.nib b/WebKitTools/DrawTest/English.lproj/TestViewer.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000..46b8964 --- /dev/null +++ b/WebKitTools/DrawTest/English.lproj/TestViewer.nib/keyedobjects.nib diff --git a/WebKitTools/DrawTest/Info.plist b/WebKitTools/DrawTest/Info.plist new file mode 100644 index 0000000..0fd092b --- /dev/null +++ b/WebKitTools/DrawTest/Info.plist @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>svg</string> + </array> + <key>CFBundleTypeName</key> + <string>SVG Document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>????</string> + </array> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSTypeIsPackage</key> + <false/> + <key>NSDocumentClass</key> + <string>DrawTestDocument</string> + <key>NSPersistentStoreTypeKey</key> + <string>Binary</string> + </dict> + </array> + <key>CFBundleExecutable</key> + <string>DrawTest</string> + <key>CFBundleGetInfoString</key> + <string>420+, Copyright 2005, 2006 Apple Computer, Inc.</string> + <key>CFBundleIdentifier</key> + <string>com.apple.DrawTest</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/WebKitTools/DrawTest/SVGTest.h b/WebKitTools/DrawTest/SVGTest.h new file mode 100644 index 0000000..70eed41 --- /dev/null +++ b/WebKitTools/DrawTest/SVGTest.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + +@interface SVGTest : NSObject { + NSString *_svgPath; + NSString *_imagePath; + + NSImage *_image; + NSImage *_compositeImage; + BOOL _hasPassed; +} + ++ (id)testWithSVGPath:(NSString *)svgPath imagePath:(NSString *)imagePath; +- (id)initWithSVGPath:(NSString *)svgPath imagePath:(NSString *)imagePath; + +- (NSString *)imagePath; +- (NSString *)svgPath; + +- (NSImage *)image; +- (NSImage *)compositeImage; +- (NSString *)name; + +@end diff --git a/WebKitTools/DrawTest/SVGTest.m b/WebKitTools/DrawTest/SVGTest.m new file mode 100644 index 0000000..4ea562d --- /dev/null +++ b/WebKitTools/DrawTest/SVGTest.m @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "SVGTest.h" + +#import <WebKit/WebView.h> + +@implementation SVGTest + ++ (id)testWithSVGPath:(NSString *)svgPath imagePath:(NSString *)imagePath +{ + SVGTest *test = [[self alloc] initWithSVGPath:svgPath imagePath:imagePath]; + return [test autorelease]; +} + +static WebView *__sharedDrawView = nil; ++ (WebView *)sharedDrawView +{ + if (!__sharedDrawView) { + __sharedDrawView = [[WebView alloc] initWithFrame:NSMakeRect(0,0,0,0)]; + } + return __sharedDrawView; +} + +- (id)initWithSVGPath:(NSString *)svgPath imagePath:(NSString *)imagePath +{ + if (self = [super init]) { + _svgPath = [svgPath copy]; + _imagePath = [imagePath copy]; + } + return self; +} + +- (NSString *)imagePath +{ + return _imagePath; +} + +- (NSString *)svgPath +{ + return _svgPath; +} + +- (NSImage *)image +{ + if (!_image && _imagePath) { + _image = [[NSImage alloc] initByReferencingFile:_imagePath]; + } + return _image; +} + +- (NSString *)name +{ + NSMutableString *name = [[[[_svgPath lastPathComponent] stringByDeletingPathExtension] mutableCopy] autorelease]; + [name replaceOccurrencesOfString:@"_" withString:@" " options:0 range:NSMakeRange(0, [name length])]; + return [name capitalizedString]; +} + +- (void)generateCompositeIfNecessary +{ + if (!_compositeImage) { + WebView *view = [SVGTest sharedDrawView]; + NSSize svgSize = [view bounds].size; + + NSImage *image = [self image]; + NSSize imageSize = [image size]; + + NSBitmapImageRep *svgImage = [view bitmapImageRepForCachingDisplayInRect:[view bounds]]; + [view cacheDisplayInRect:[view bounds] toBitmapImageRep:svgImage]; + + NSSize unionSize = NSMakeSize(MAX(svgSize.width, imageSize.width), MAX(svgSize.height, imageSize.height)); + _compositeImage = [[NSImage alloc] initWithSize:unionSize]; + + [_compositeImage lockFocus]; + [svgImage drawInRect:NSMakeRect(0,0,svgSize.width,svgSize.height)]; + [image drawInRect:NSMakeRect(0,0,imageSize.width,imageSize.height) + fromRect:NSMakeRect(0,0,imageSize.width,imageSize.height) + operation:NSCompositeXOR fraction:1.0]; + [_compositeImage unlockFocus]; + } +} + +- (NSImage *)compositeImage +{ + [self generateCompositeIfNecessary]; + return _compositeImage; +} + + +@end diff --git a/WebKitTools/DrawTest/ScalingImageView.h b/WebKitTools/DrawTest/ScalingImageView.h new file mode 100644 index 0000000..4370ff5 --- /dev/null +++ b/WebKitTools/DrawTest/ScalingImageView.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + + +@interface ScalingImageView : NSImageView { + +} + +@end diff --git a/WebKitTools/DrawTest/ScalingImageView.m b/WebKitTools/DrawTest/ScalingImageView.m new file mode 100644 index 0000000..605397a --- /dev/null +++ b/WebKitTools/DrawTest/ScalingImageView.m @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ScalingImageView.h" + +@implementation ScalingImageView + +/* + This class offers two behaviors different from the standard NSImageView + (and which were not available w/o subclassing) + 1. Scale an image proportionally up to fit a larger view (NSImageView refuses) + 2. Draw a background color w/o needing to show a bezel. +*/ + +- (void)drawRect:(NSRect)dirtyRect +{ + [[NSColor whiteColor] set]; + NSRectFill(dirtyRect); + + NSSize imageSize = [[self image] size]; + float scale = 1.0f; + if ([self imageScaling] == NSScaleProportionally && imageSize.width && imageSize.height) { + float widthScale = [self bounds].size.width / imageSize.width; + float heightScale = [self bounds].size.height / imageSize.height; + scale = MIN(widthScale, heightScale); + } + + float scaledHeight = imageSize.height * scale; + NSRect destRect = NSMakeRect(0,[self bounds].size.height - scaledHeight,imageSize.width * scale, scaledHeight); + [[self image] drawInRect:destRect + fromRect:NSMakeRect(0,0,imageSize.width, imageSize.height) operation:NSCompositeSourceOver fraction:1.0]; +} + +@end diff --git a/WebKitTools/DrawTest/TestController.h b/WebKitTools/DrawTest/TestController.h new file mode 100644 index 0000000..1e781fe --- /dev/null +++ b/WebKitTools/DrawTest/TestController.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + +@class DrawTestView; +@class SVGTest; +@class TestViewerSplitView; + +@interface TestController : NSObject { + IBOutlet NSPanel *_testPanel; + IBOutlet NSWindow *_testWindow; + IBOutlet TestViewerSplitView *_splitView; + + IBOutlet NSArrayController *_testsArrayController; + IBOutlet NSPopUpButton *_parentDirectoryPopup; + IBOutlet NSTableView *_testsTableView; + + IBOutlet NSWindow *_compositeWindow; + IBOutlet NSImageView *_compositeImageView; + +@private + NSString *_currentPath; + NSArray *_tests; + SVGTest *_selectedTest; + + DrawTestView *_drawView; + NSImageView *_imageView; +} + ++ (id)sharedController; + +- (IBAction)showTestsPanel:(id)sender; +- (IBAction)showTestWindow:(id)sender; +- (IBAction)showCompositeWindow:(id)sender; + +- (IBAction)browse:(id)sender; +- (IBAction)jumpToParentDirectory:(id)sender; +- (IBAction)openTestViewerForSelection:(id)sender; +- (IBAction)openSourceForSelection:(id)sender; +- (IBAction)openSelectionInViewer:(id)sender; +- (IBAction)toggleViewersScaleRule:(id)sender; + +- (NSArray *)tests; +- (NSString *)currentPath; +- (void)setCurrentPath:(NSString *)newPath; +- (NSArray *)directoryHierarchy; + +@end diff --git a/WebKitTools/DrawTest/TestController.m b/WebKitTools/DrawTest/TestController.m new file mode 100644 index 0000000..506920b --- /dev/null +++ b/WebKitTools/DrawTest/TestController.m @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nefaur Khandker <nefaurk@gmail.com> 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "TestController.h" +#import "SVGTest.h" +#import "TestViewerSplitView.h" +#import "ScalingImageView.h" +#import "DrawTestView.h" + +#import <WebKit/WebView.h> + +@interface NSArray (TestControllerAdditions) +- (id)firstObject; +@end + +@implementation NSArray (TestControllerAdditions) +- (id)firstObject +{ + if ([self count]) + return [self objectAtIndex:0]; + return nil; +} +@end + +static TestController *__sharedInstance = nil; + +@implementation TestController + +- (id)init +{ + if (self = [super init]) { + NSString *path = [[NSUserDefaults standardUserDefaults] objectForKey:@"TestDirectory"]; + BOOL isDirectory = NO; + if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory] || !isDirectory) { + path = [@"~" stringByStandardizingPath]; + } + [self setCurrentPath:path]; + } + return self; +} + ++ (void)initialize +{ + [self setKeys:[NSArray arrayWithObject:@"currentPath"] triggerChangeNotificationsForDependentKey:@"directoryHierarchy"]; + [self setKeys:[NSArray arrayWithObject:@"currentPath"] triggerChangeNotificationsForDependentKey:@"tests"]; +} + ++ (id)sharedController +{ + if (!__sharedInstance) { + __sharedInstance = [[self alloc] init]; + } + return __sharedInstance; +} + +- (void)loadNibIfNecessary +{ + if (!_testPanel) { + [NSBundle loadNibNamed:@"TestViewer" owner:self]; + } +} + +- (void)awakeFromNib +{ + [_testsTableView setTarget:self]; + [_testsTableView setDoubleAction:@selector(openTestViewerForSelection:)]; + _drawView = [[DrawTestView alloc] initWithFrame:NSZeroRect]; + _imageView = [[ScalingImageView alloc] initWithFrame:NSZeroRect]; + [_splitView addSubview:_drawView]; + [_splitView addSubview:_imageView]; +} + +- (IBAction)showTestsPanel:(id)sender +{ + [self loadNibIfNecessary]; + [_testPanel makeKeyAndOrderFront:sender]; +} + +- (IBAction)showTestWindow:(id)sender +{ + [self loadNibIfNecessary]; + [_testWindow makeKeyAndOrderFront:sender]; +} + +- (IBAction)showCompositeWindow:(id)sender +{ + [self loadNibIfNecessary]; + NSLog(@"showCompositeWindow: %@", _compositeWindow); + [_compositeWindow makeKeyAndOrderFront:sender]; +} + +- (IBAction)browse:(id)sender +{ + NSOpenPanel *openPanel = [NSOpenPanel openPanel]; + [openPanel setCanChooseDirectories:YES]; + [openPanel setCanChooseFiles:NO]; + [openPanel beginSheetForDirectory:nil file:nil modalForWindow:_testPanel modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; +} + +- (void)openPanelDidEnd:(NSOpenPanel *)openPanel returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + if (returnCode == NSOKButton) { + NSArray *folders = [openPanel filenames]; + NSString *selectedFolder = [folders firstObject]; + [self setCurrentPath:selectedFolder]; + } +} + +- (IBAction)jumpToParentDirectory:(id)sender +{ + int index = [_parentDirectoryPopup indexOfSelectedItem]; + NSArray *components = [_currentPath pathComponents]; + NSArray *newComponents = [components subarrayWithRange:NSMakeRange(0, [components count] - index)]; + NSString *newPath = [NSString pathWithComponents:newComponents]; + [self setCurrentPath:newPath]; +} + +- (void)setSelectedTest:(SVGTest *)selectedTest +{ + id oldTest = _selectedTest; + _selectedTest = [selectedTest retain]; + [oldTest release]; + + if ([_testWindow isVisible]) { + [_testWindow setTitle:[NSString stringWithFormat:@"Test Viewer - %@", [_selectedTest name]]]; + [_drawView setDocument:[NSURL fileURLWithPath:[_selectedTest svgPath]]]; + [_imageView setImage:[_selectedTest image]]; + if ([_compositeWindow isVisible]) + [_compositeImageView setImage:[_selectedTest compositeImage]]; + } +} + +- (void)tableViewSelectionDidChange:(NSNotification *)aNotification +{ + [self setSelectedTest:[[_testsArrayController selectedObjects] firstObject]]; +} + +- (IBAction)openTestViewerForSelection:(id)sender +{ + [self showTestWindow:sender]; + [_drawView setDocument:[NSURL fileURLWithPath:[_selectedTest svgPath]]]; + [_imageView setImage:[_selectedTest image]]; +} + +- (IBAction)openSourceForSelection:(id)sender +{ + [[NSWorkspace sharedWorkspace] openFile:[_selectedTest svgPath] withApplication:@"TextEdit"]; +} + +- (IBAction)openSelectionInViewer:(id)sender +{ + [[NSWorkspace sharedWorkspace] openFile:[_selectedTest svgPath]]; +} + +- (NSString *)imagePathForSVGPath:(NSString *)svgPath +{ + // eventually this code will build an array instead... + + NSString *currentDirectory = [self currentPath]; + NSString *parentDirectory = [currentDirectory stringByDeletingLastPathComponent]; + + NSString *testName = [[svgPath lastPathComponent] stringByDeletingPathExtension]; + NSString *imageName, *imageDirectory, *imagePath; + + // first look in ../png/test.png -- SVG 1.1 baselines + // The SVG 1.1 spec has various different pngs, we should allow the + // tester to choose... + imageName = [[@"full-" stringByAppendingString:testName] stringByAppendingPathExtension:@"png"]; + imageDirectory = [parentDirectory stringByAppendingPathComponent:@"png"]; + imagePath = [imageDirectory stringByAppendingPathComponent:imageName]; + if ([[NSFileManager defaultManager] fileExistsAtPath:imagePath]) return imagePath; + + // then look for ../name.png -- openclipart.org + imageName = [testName stringByAppendingPathExtension:@"png"]; + imageDirectory = parentDirectory; + imagePath = [imageDirectory stringByAppendingPathComponent:imageName]; + if ([[NSFileManager defaultManager] fileExistsAtPath:imagePath]) return imagePath; + + // then look for ./name-w3c.png -- WebCore tests + imageName = [[testName stringByAppendingString:@"-w3c"] stringByAppendingPathExtension:@"png"]; + imageDirectory = currentDirectory; + imagePath = [imageDirectory stringByAppendingPathComponent:imageName]; + if ([[NSFileManager defaultManager] fileExistsAtPath:imagePath]) return imagePath; + + // finally try name-baseline.png -- ksvg regression baselines + imageName = [[testName stringByAppendingString:@"-baseline"] stringByAppendingPathExtension:@"png"]; + imageDirectory = currentDirectory; + imagePath = [imageDirectory stringByAppendingPathComponent:imageName]; + if ([[NSFileManager defaultManager] fileExistsAtPath:imagePath]) return imagePath; + + return nil; +} + +- (NSArray *)tests +{ + if (!_tests) { + NSMutableArray *newTests = [[NSMutableArray alloc] init]; + NSArray *files = [[NSFileManager defaultManager] directoryContentsAtPath:[self currentPath]]; + NSString *file = nil; + foreacharray(file, files) { + if ([[file pathExtension] isEqualToString:@"svg"]) { + NSString *svgPath = [[self currentPath] stringByAppendingPathComponent:file]; + NSString *imagePath = [self imagePathForSVGPath:svgPath]; + [newTests addObject:[SVGTest testWithSVGPath:svgPath imagePath:imagePath]]; + } + } + [self setValue:newTests forKey:@"tests"]; + } + return _tests; +} + +- (NSArray *)directoryHierarchy +{ + // A hackish way to reverse an array. + return [[[_currentPath pathComponents] reverseObjectEnumerator] allObjects]; +} + +- (NSString *)currentPath +{ + return _currentPath; +} + +- (void)setCurrentPath:(NSString *)newPath +{ + if (![newPath isEqualToString:_currentPath]) { + [_currentPath release]; + _currentPath = [newPath copy]; + [self setValue:nil forKey:@"tests"]; + } + + [[NSUserDefaults standardUserDefaults] setObject:_currentPath forKey:@"TestDirectory"]; +} + +- (IBAction)toggleViewersScaleRule:(id)sender +{ +#if 0 + if ([_drawView imageScaling] == NSScaleProportionally) { + [_drawView setImageScaling:NSScaleNone]; + [_imageView setImageScaling:NSScaleNone]; + } else { + [_drawView setImageScaling:NSScaleProportionally]; + [_imageView setImageScaling:NSScaleProportionally]; + } +#endif +} + +@end diff --git a/WebKitTools/DrawTest/TestViewerSplitView.h b/WebKitTools/DrawTest/TestViewerSplitView.h new file mode 100644 index 0000000..e663f23 --- /dev/null +++ b/WebKitTools/DrawTest/TestViewerSplitView.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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> + +@interface TestViewerSplitView : NSView { + NSMutableArray *subviewLabels; +} + +@end diff --git a/WebKitTools/DrawTest/TestViewerSplitView.m b/WebKitTools/DrawTest/TestViewerSplitView.m new file mode 100644 index 0000000..96f2055 --- /dev/null +++ b/WebKitTools/DrawTest/TestViewerSplitView.m @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "TestViewerSplitView.h" + +@implementation TestViewerSplitView + +- (void)drawRect:(NSRect)rect +{ + NSArray *subviews = [self subviews]; + int subviewCount = [subviews count]; + for (int x=0; x < subviewCount; x++) { + NSView *subview = [subviews objectAtIndex:x]; + [subview drawRect:rect]; +#if 0 + NSString *label = [subviewLabels objectAtIndex:0]; + [label drawAtPoint:[subview frame].origin withAttributes:NULL]; +#endif + } +} + +- (void)retileSubviews +{ + NSRect bounds = [self bounds]; + NSArray *subviews = [self subviews]; + int subviewCount = [subviews count]; + if (!subviewCount) return; + float subviewWidth = bounds.size.width / subviewCount; + + for (int x=0; x < subviewCount; x++) { + [[subviews objectAtIndex:x] setFrame:NSMakeRect(x * subviewWidth, 0, subviewWidth, bounds.size.height)]; + } +} + +- (void)didAddSubview:(NSView *)subview +{ + [super didAddSubview:subview]; + [self retileSubviews]; +} + +- (void)willRemoveSubview:(NSView *)subview +{ + [super willRemoveSubview:subview]; + [self retileSubviews]; +} + +- (void)setFrame:(NSRect)newFrame +{ + // ideally we also want to catch when the bounds changes without the + // frame changing, but we're not bothering with that now - ECS 7/29/05 + [super setFrame:newFrame]; + [self retileSubviews]; +} + +@end diff --git a/WebKitTools/DrawTest/main.m b/WebKitTools/DrawTest/main.m new file mode 100644 index 0000000..90337b6 --- /dev/null +++ b/WebKitTools/DrawTest/main.m @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +int main (int argc, const char *argv[]) +{ + return NSApplicationMain(argc, argv); +} diff --git a/WebKitTools/Drosera/DebuggerDocument.cpp b/WebKitTools/Drosera/DebuggerDocument.cpp new file mode 100644 index 0000000..f5dbf87 --- /dev/null +++ b/WebKitTools/Drosera/DebuggerDocument.cpp @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "config.h" +#include "DebuggerDocument.h" + +#include "ServerConnection.h" + +#include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/JSStringRefCF.h> +#include <JavaScriptCore/RetainPtr.h> + +DebuggerDocument::DebuggerDocument(ServerConnection* serverConn) + : m_server(serverConn) +{ + ASSERT(m_server); +} + +//-- Callbacks + +JSValueRef DebuggerDocument::breakpointEditorHTMLCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/) +{ + RetainPtr<CFURLRef> htmlURLRef(AdoptCF, ::CFBundleCopyResourceURL(::CFBundleGetBundleWithIdentifier(CFSTR("org.webkit.drosera")), CFSTR("breakpointEditor"), CFSTR("html"), 0)); + if (!htmlURLRef) + return JSValueMakeUndefined(context); + + // FIXME: I'm open to a better way to do this. We convert from UInt8 to CFString to JSString (3 string types!) + RetainPtr<CFReadStreamRef> readStreamRef(AdoptCF, CFReadStreamCreateWithFile(0, htmlURLRef.get())); + CFReadStreamRef readStream = readStreamRef.get(); + + if (!CFReadStreamOpen(readStream)) + return JSValueMakeUndefined(context); + + // Large enough for current BreakPointEditor.html but won't need to be changed if that file changes + // because we loop over the entire file and read it in bufferLength pieces at a time + const CFIndex bufferLength = 740; + UInt8 buffer[bufferLength]; + Vector<UInt8, bufferLength> charBuffer; + CFIndex readResult = bufferLength; + while (readResult == bufferLength) { + readResult = CFReadStreamRead(readStream, buffer, bufferLength); + + // Error condition (-1) will not copy any data + for (int i = 0; i < readResult; i++) + charBuffer.append(buffer[i]); + } + + CFReadStreamClose(readStream); + if (readResult == -1) + return JSValueMakeUndefined(context); + + // FIXME: Is there a way to determine the encoding? + RetainPtr<CFStringRef> fileContents(AdoptCF, CFStringCreateWithBytes(0, charBuffer.data(), charBuffer.size(), kCFStringEncodingUTF8, true)); + JSRetainPtr<JSStringRef> fileContentsJS(Adopt, JSStringCreateWithCFString(fileContents.get())); + JSValueRef ret = JSValueMakeString(context, fileContentsJS.get()); + + return ret; +} + +JSValueRef DebuggerDocument::pauseCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/) +{ + DebuggerDocument* debuggerDocument = reinterpret_cast<DebuggerDocument*>(JSObjectGetPrivate(thisObject)); + + debuggerDocument->platformPause(); + return JSValueMakeUndefined(context); +} + +JSValueRef DebuggerDocument::resumeCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/) +{ + DebuggerDocument* debuggerDocument = reinterpret_cast<DebuggerDocument*>(JSObjectGetPrivate(thisObject)); + debuggerDocument->platformResume(); + return JSValueMakeUndefined(context); +} + +JSValueRef DebuggerDocument::stepIntoCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/) +{ + DebuggerDocument* debuggerDocument = reinterpret_cast<DebuggerDocument*>(JSObjectGetPrivate(thisObject)); + debuggerDocument->platformStepInto(); + return JSValueMakeUndefined(context); +} + +JSValueRef DebuggerDocument::evaluateScriptCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + DebuggerDocument* debuggerDocument = reinterpret_cast<DebuggerDocument*>(JSObjectGetPrivate(thisObject)); + if (argumentCount < 2) + return JSValueMakeUndefined(context); + + if (!JSValueIsNumber(context, arguments[1])) + return JSValueMakeUndefined(context); + + double callFrame = JSValueToNumber(context, arguments[1], exception); + ASSERT(!*exception); + + JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + JSValueRef ret = debuggerDocument->platformEvaluateScript(context, script.get(), (int)callFrame); + + return ret; +} + +JSValueRef DebuggerDocument::currentFunctionStackCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* exception) +{ + DebuggerDocument* debuggerDocument = reinterpret_cast<DebuggerDocument*>(JSObjectGetPrivate(thisObject)); + Vector<JSValueRef> stack; + debuggerDocument->getPlatformCurrentFunctionStack(context, stack); + return DebuggerDocument::toJSArray(context, stack, exception); +} + +JSValueRef DebuggerDocument::localScopeVariableNamesForCallFrameCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + DebuggerDocument* debuggerDocument = reinterpret_cast<DebuggerDocument*>(JSObjectGetPrivate(thisObject)); + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + if (!JSValueIsNumber(context, arguments[0])) + return JSValueMakeUndefined(context); + + double callFrame = JSValueToNumber(context, arguments[0], exception); + ASSERT(!*exception); + + // Get the variable names + Vector<JSValueRef> localVariableNames; + + debuggerDocument->getPlatformLocalScopeVariableNamesForCallFrame(context, static_cast<int>(callFrame), localVariableNames); + return DebuggerDocument::toJSArray(context, localVariableNames, exception); +} + +JSValueRef DebuggerDocument::valueForScopeVariableNamedCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + DebuggerDocument* debuggerDocument = reinterpret_cast<DebuggerDocument*>(JSObjectGetPrivate(thisObject)); + + if (argumentCount < 2) + return JSValueMakeUndefined(context); + + if (!JSValueIsString(context, arguments[0])) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> key(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + if (!JSValueIsNumber(context, arguments[1])) + return JSValueMakeUndefined(context); + + double callFrame = JSValueToNumber(context, arguments[1], exception); + ASSERT(!*exception); + + return debuggerDocument->platformValueForScopeVariableNamed(context, key.get(), (int)callFrame); +} + +JSValueRef DebuggerDocument::logCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + if (!JSValueIsString(context, arguments[0])) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> msg(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + DebuggerDocument::platformLog(msg.get()); + return JSValueMakeUndefined(context); +} + +//-- These are the calls into the JS. --// + +bool DebuggerDocument::isPaused(JSContextRef context) const +{ + JSObjectRef globalObject = JSContextGetGlobalObject(context); + JSRetainPtr<JSStringRef> string(Adopt, JSStringCreateWithUTF8CString("isPaused")); + JSValueRef objectProperty = JSObjectGetProperty(context, globalObject, string.get(), 0); + return JSValueToBoolean(context, objectProperty); +} + +void DebuggerDocument::updateFileSource(JSContextRef context, JSStringRef documentSource, JSStringRef url) +{ + JSValueRef documentSourceValue = JSValueMakeString(context, documentSource); + JSValueRef urlValue = JSValueMakeString(context, url); + JSValueRef forceValue = JSValueMakeBoolean(context, true); + + JSValueRef arguments[] = { documentSourceValue, urlValue, forceValue }; + int argumentsSize = sizeof(arguments)/sizeof(arguments[0]); + + DebuggerDocument::callGlobalFunction(context, "updateFileSource", argumentsSize, arguments); +} + +void DebuggerDocument::didParseScript(JSContextRef context, JSStringRef source, JSStringRef documentSource, JSStringRef url, JSValueRef sourceId, JSValueRef baseLine) +{ + JSValueRef sourceValue = JSValueMakeString(context, source); + JSValueRef documentSourceValue = JSValueMakeString(context, documentSource); + JSValueRef urlValue = JSValueMakeString(context, url); + + JSValueRef arguments[] = { sourceValue, documentSourceValue, urlValue, sourceId, baseLine }; + int argumentsSize = sizeof(arguments)/sizeof(arguments[0]); + + DebuggerDocument::callGlobalFunction(context, "didParseScript", argumentsSize, arguments); +} + +void DebuggerDocument::willExecuteStatement(JSContextRef context, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception) +{ + JSValueRef arguments[] = { sourceId, lineno }; + int argumentsSize = sizeof(arguments)/sizeof(arguments[0]); + + DebuggerDocument::callGlobalFunction(context, "willExecuteStatement", argumentsSize, arguments, exception); + if (exception && *exception) + logException(context, *exception); +} + +void DebuggerDocument::didEnterCallFrame(JSContextRef context, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception) +{ + JSValueRef arguments[] = { sourceId, lineno }; + int argumentsSize = sizeof(arguments)/sizeof(arguments[0]); + + DebuggerDocument::callGlobalFunction(context, "didEnterCallFrame", argumentsSize, arguments, exception); + if (exception && *exception) + logException(context, *exception); +} + +void DebuggerDocument::willLeaveCallFrame(JSContextRef context, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception) +{ + JSValueRef arguments[] = { sourceId, lineno }; + int argumentsSize = sizeof(arguments)/sizeof(arguments[0]); + + DebuggerDocument::callGlobalFunction(context, "willLeaveCallFrame", argumentsSize, arguments, exception); + if (exception && *exception) + logException(context, *exception); +} + +void DebuggerDocument::exceptionWasRaised(JSContextRef context, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception) +{ + JSValueRef arguments[] = { sourceId, lineno }; + int argumentsSize = sizeof(arguments)/sizeof(arguments[0]); + + DebuggerDocument::callGlobalFunction(context, "exceptionWasRaised", argumentsSize, arguments, exception); +} + +void DebuggerDocument::windowScriptObjectAvailable(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> droseraStr(Adopt, JSStringCreateWithUTF8CString("DebuggerDocument")); + JSValueRef droseraObject = JSObjectMake(context, getDroseraJSClass(), this); + + JSObjectSetProperty(context, windowObject, droseraStr.get(), droseraObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); + if (exception && *exception) + logException(context, *exception); +} + +JSValueRef DebuggerDocument::toJSArray(JSContextRef context, Vector<JSValueRef>& vectorValues, JSValueRef* exception) +{ + JSObjectRef globalObject = JSContextGetGlobalObject(context); + JSRetainPtr<JSStringRef> constructorString(Adopt, JSStringCreateWithUTF8CString("Array")); + JSValueRef constructorProperty = JSObjectGetProperty(context, globalObject, constructorString.get(), exception); + ASSERT(!*exception); + + JSObjectRef arrayConstructor = JSValueToObject(context, constructorProperty, exception); + ASSERT(!*exception); + + JSObjectRef array = JSObjectCallAsConstructor(context, arrayConstructor, 0, 0, exception); + ASSERT(!*exception); + + JSRetainPtr<JSStringRef> pushString(Adopt, JSStringCreateWithUTF8CString("push")); + JSValueRef pushValue = JSObjectGetProperty(context, array, pushString.get(), exception); + ASSERT(!*exception); + + JSObjectRef push = JSValueToObject(context, pushValue, exception); + ASSERT(!*exception); + + for (Vector<JSValueRef>::iterator it = vectorValues.begin(); it != vectorValues.end(); ++it) { + JSObjectCallAsFunction(context, push, array, 1, it, exception); + ASSERT(!*exception); + } + + return array; +} + +// Private +JSValueRef DebuggerDocument::callGlobalFunction(JSContextRef context, const char* functionName, int argumentCount, JSValueRef arguments[], JSValueRef* exception) +{ + JSObjectRef globalObject = JSContextGetGlobalObject(context); + return callFunctionOnObject(context, globalObject, functionName, argumentCount, arguments, exception); +} + +JSValueRef DebuggerDocument::callFunctionOnObject(JSContextRef context, JSObjectRef object, const char* functionName, int argumentCount, JSValueRef arguments[], JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> string(Adopt, JSStringCreateWithUTF8CString(functionName)); + JSValueRef objectProperty = JSObjectGetProperty(context, object, string.get(), exception); + + JSObjectRef function = JSValueToObject(context, objectProperty, exception); + ASSERT(JSObjectIsFunction(context, function)); + + JSValueRef returnValue = JSObjectCallAsFunction(context, function, 0, argumentCount, arguments, exception); + if (exception && *exception) + logException(context, *exception); + + return returnValue; +} + +JSClassRef DebuggerDocument::getDroseraJSClass() +{ + static JSClassRef droseraClass = 0; + + if (!droseraClass) { + JSClassDefinition classDefinition = {0}; + classDefinition.staticFunctions = DebuggerDocument::staticFunctions(); + + droseraClass = JSClassCreate(&classDefinition); + } + + return droseraClass; +} + +JSStaticFunction* DebuggerDocument::staticFunctions() +{ + static JSStaticFunction staticFunctions[] = { + { "breakpointEditorHTML", DebuggerDocument::breakpointEditorHTMLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "currentFunctionStack", DebuggerDocument::currentFunctionStackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "evaluateScript", DebuggerDocument::evaluateScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "localScopeVariableNamesForCallFrame", DebuggerDocument::localScopeVariableNamesForCallFrameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "pause", DebuggerDocument::pauseCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "resume", DebuggerDocument::resumeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "stepInto", DebuggerDocument::stepIntoCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "valueForScopeVariableNamed", DebuggerDocument::valueForScopeVariableNamedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "log", DebuggerDocument::logCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { 0, 0, 0 } + }; + + return staticFunctions; +} + +void DebuggerDocument::logException(JSContextRef context, JSValueRef exception) +{ + if (!exception) + return; + + JSRetainPtr<JSStringRef> msg(Adopt, JSValueToStringCopy(context, exception, 0)); + DebuggerDocument::platformLog(msg.get()); +} + diff --git a/WebKitTools/Drosera/DebuggerDocument.h b/WebKitTools/Drosera/DebuggerDocument.h new file mode 100644 index 0000000..7043ba1 --- /dev/null +++ b/WebKitTools/Drosera/DebuggerDocument.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +#ifndef DebuggerDocument_H +#define DebuggerDocument_H + +#pragma warning(push) +#pragma warning(disable: 4510 4512 4610) +#include <JavaScriptCore/JSObjectRef.h> +#pragma warning(pop) + +#include <JavaScriptCore/Vector.h> + +// Forward Declarations +#if PLATFORM(MAC) +#include <JavaScriptCore/RetainPtr.h> +@class ServerConnection; +typedef RetainPtr<ServerConnection> ServerConnectionRef; +#else if PLATFORM(WIN) +#include <wtf/OwnPtr.h> +class ServerConnection; +typedef OwnPtr<ServerConnection> ServerConnectionRef; +#endif + +typedef struct OpaqueJSString* JSStringRef; +typedef struct OpaqueJSValue* JSObjectRef; + +class DebuggerDocument { +public: + DebuggerDocument(ServerConnection*); + + // These are all calls from the JS + static JSValueRef breakpointEditorHTMLCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef pauseCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef resumeCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef stepIntoCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef evaluateScriptCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef currentFunctionStackCallback(JSContextRef /*context*/, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef localScopeVariableNamesForCallFrameCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef valueForScopeVariableNamedCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + static JSValueRef logCallback(JSContextRef context, JSObjectRef /*function*/, JSObjectRef /*thisObject*/, size_t /*argumentCount*/, const JSValueRef /*arguments*/[], JSValueRef* /*exception*/); + + // Non Cross-platform functions + void platformPause(); + void platformResume(); + void platformStepInto(); + JSValueRef platformEvaluateScript(JSContextRef, JSStringRef script, int callFrame); + void getPlatformCurrentFunctionStack(JSContextRef, Vector<JSValueRef>& currentStack); + void getPlatformLocalScopeVariableNamesForCallFrame(JSContextRef, int callFrame, Vector<JSValueRef>& variableNames); + JSValueRef platformValueForScopeVariableNamed(JSContextRef, JSStringRef key, int callFrame); + static void platformLog(JSStringRef msg); + + // These are the calls into the JS. + bool isPaused(JSContextRef) const; + static void updateFileSource(JSContextRef, JSStringRef documentSource, JSStringRef url); + static void didParseScript(JSContextRef, JSStringRef source, JSStringRef documentSource, JSStringRef url, JSValueRef sourceId, JSValueRef baseLine); + static void willExecuteStatement(JSContextRef, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception = 0); + static void didEnterCallFrame(JSContextRef, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception = 0); + static void willLeaveCallFrame(JSContextRef, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception = 0); + static void exceptionWasRaised(JSContextRef, JSValueRef sourceId, JSValueRef lineno, JSValueRef* exception = 0); + + static JSValueRef toJSArray(JSContextRef, Vector<JSValueRef>&, JSValueRef* exception); + static JSValueRef callGlobalFunction(JSContextRef, const char* functionName, int argumentCount, JSValueRef arguments[], JSValueRef* exception = 0); // Implementation for calls into JS + + void windowScriptObjectAvailable(JSContextRef, JSObjectRef windowObject, JSValueRef* exception = 0); + + ServerConnection* server() const { return m_server.get(); } + +private: + static JSValueRef callFunctionOnObject(JSContextRef, JSObjectRef object, const char* functionName, int argumentCount, JSValueRef arguments[], JSValueRef* exception = 0); // Implementation for calls into JS + static JSClassRef getDroseraJSClass(); + static JSStaticFunction* staticFunctions(); + + static void logException(JSContextRef, JSValueRef exception); + + ServerConnectionRef m_server; +}; + +#endif //DebuggerDocument_H + diff --git a/WebKitTools/Drosera/Drosera.icns b/WebKitTools/Drosera/Drosera.icns Binary files differnew file mode 100644 index 0000000..ead895e --- /dev/null +++ b/WebKitTools/Drosera/Drosera.icns diff --git a/WebKitTools/Drosera/DroseraWin.make b/WebKitTools/Drosera/DroseraWin.make new file mode 100644 index 0000000..b69d47d --- /dev/null +++ b/WebKitTools/Drosera/DroseraWin.make @@ -0,0 +1,13 @@ +!IF !defined(BUILDSTYLE) +BUILDSTYLE=Release +!ELSEIF "$(BUILDSTYLE)"=="DEBUG" +BUILDSTYLE=Debug_Internal +!ENDIF + +install: + set WebKitLibrariesDir=$(SRCROOT)\AppleInternal + set WebKitOutputDir=$(OBJROOT) + set PRODUCTION=1 + devenv "win\Drosera.vcproj\Drosera.vcproj" /rebuild $(BUILDSTYLE) + xcopy "$(OBJROOT)\bin\*" "$(DSTROOT)\AppleInternal\bin\" /e/v/i/h/y + xcopy "$(OBJROOT)\bin\Drosera.resources\*" "$(DSTROOT)\AppleInternal\bin\Drosera.resources" /e/v/i/h/y diff --git a/WebKitTools/Drosera/English.lproj/Debugger.nib/classes.nib b/WebKitTools/Drosera/English.lproj/Debugger.nib/classes.nib new file mode 100644 index 0000000..3e0e4cb --- /dev/null +++ b/WebKitTools/Drosera/English.lproj/Debugger.nib/classes.nib @@ -0,0 +1,12 @@ +{ + IBClasses = ( + { + CLASS = DebuggerDocument; + LANGUAGE = ObjC; + OUTLETS = {server = id; webView = WebView; }; + SUPERCLASS = NSWindowController; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/WebKitTools/Drosera/English.lproj/Debugger.nib/info.nib b/WebKitTools/Drosera/English.lproj/Debugger.nib/info.nib new file mode 100644 index 0000000..7564e3e --- /dev/null +++ b/WebKitTools/Drosera/English.lproj/Debugger.nib/info.nib @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>907 177 356 240 0 0 1280 832 </string> + <key>IBFramework Version</key> + <string>446.1</string> + <key>IBOpenObjects</key> + <array> + <integer>5</integer> + </array> + <key>IBSystem Version</key> + <string>8L127</string> +</dict> +</plist> diff --git a/WebKitTools/Drosera/English.lproj/Debugger.nib/keyedobjects.nib b/WebKitTools/Drosera/English.lproj/Debugger.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000..3978af2 --- /dev/null +++ b/WebKitTools/Drosera/English.lproj/Debugger.nib/keyedobjects.nib diff --git a/WebKitTools/Drosera/English.lproj/MainMenu.nib/classes.nib b/WebKitTools/Drosera/English.lproj/MainMenu.nib/classes.nib new file mode 100644 index 0000000..f192cda --- /dev/null +++ b/WebKitTools/Drosera/English.lproj/MainMenu.nib/classes.nib @@ -0,0 +1,40 @@ +{ + IBClasses = ( + { + ACTIONS = {attach = id; showAttachPanel = id; }; + CLASS = DebuggerApplication; + LANGUAGE = ObjC; + OUTLETS = {attachButton = NSButton; attachTable = NSTableView; attachWindow = NSPanel; }; + SUPERCLASS = NSObject; + }, + { + ACTIONS = { + closeCurrentFile = id; + pause = id; + resume = id; + showConsole = id; + stepInto = id; + stepOut = id; + stepOver = id; + }; + CLASS = DebuggerDocument; + LANGUAGE = ObjC; + OUTLETS = {server = id; webView = WebView; }; + SUPERCLASS = NSWindowController; + }, + { + ACTIONS = { + closeCurrentFile = id; + myAction = id; + showConsole = id; + stepInto = id; + stepOut = id; + stepOver = id; + }; + CLASS = FirstResponder; + LANGUAGE = ObjC; + SUPERCLASS = NSObject; + } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/WebKitTools/Drosera/English.lproj/MainMenu.nib/info.nib b/WebKitTools/Drosera/English.lproj/MainMenu.nib/info.nib new file mode 100644 index 0000000..838fde9 --- /dev/null +++ b/WebKitTools/Drosera/English.lproj/MainMenu.nib/info.nib @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>488 89 356 240 0 0 1280 1002 </string> + <key>IBEditorPositions</key> + <dict> + <key>29</key> + <string>190 724 343 44 0 0 1280 1002 </string> + </dict> + <key>IBFramework Version</key> + <string>446.1</string> + <key>IBOpenObjects</key> + <array> + <integer>217</integer> + <integer>29</integer> + </array> + <key>IBSystem Version</key> + <string>8N1037</string> +</dict> +</plist> diff --git a/WebKitTools/Drosera/English.lproj/MainMenu.nib/keyedobjects.nib b/WebKitTools/Drosera/English.lproj/MainMenu.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000..b78326d --- /dev/null +++ b/WebKitTools/Drosera/English.lproj/MainMenu.nib/keyedobjects.nib diff --git a/WebKitTools/Drosera/ForwardingHeaders/wtf/Assertions.h b/WebKitTools/Drosera/ForwardingHeaders/wtf/Assertions.h new file mode 100644 index 0000000..2144410 --- /dev/null +++ b/WebKitTools/Drosera/ForwardingHeaders/wtf/Assertions.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Assertions.h> diff --git a/WebKitTools/Drosera/ForwardingHeaders/wtf/HashTraits.h b/WebKitTools/Drosera/ForwardingHeaders/wtf/HashTraits.h new file mode 100644 index 0000000..412fa98 --- /dev/null +++ b/WebKitTools/Drosera/ForwardingHeaders/wtf/HashTraits.h @@ -0,0 +1 @@ +#include <JavaScriptCore/HashTraits.h> diff --git a/WebKitTools/Drosera/ForwardingHeaders/wtf/Noncopyable.h b/WebKitTools/Drosera/ForwardingHeaders/wtf/Noncopyable.h new file mode 100644 index 0000000..f8484d2 --- /dev/null +++ b/WebKitTools/Drosera/ForwardingHeaders/wtf/Noncopyable.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Noncopyable.h> diff --git a/WebKitTools/Drosera/ForwardingHeaders/wtf/OwnPtr.h b/WebKitTools/Drosera/ForwardingHeaders/wtf/OwnPtr.h new file mode 100644 index 0000000..9211d38 --- /dev/null +++ b/WebKitTools/Drosera/ForwardingHeaders/wtf/OwnPtr.h @@ -0,0 +1 @@ +#include <JavaScriptCore/OwnPtr.h> diff --git a/WebKitTools/Drosera/ForwardingHeaders/wtf/Platform.h b/WebKitTools/Drosera/ForwardingHeaders/wtf/Platform.h new file mode 100644 index 0000000..3b22955 --- /dev/null +++ b/WebKitTools/Drosera/ForwardingHeaders/wtf/Platform.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Platform.h> diff --git a/WebKitTools/Drosera/ForwardingHeaders/wtf/RetainPtr.h b/WebKitTools/Drosera/ForwardingHeaders/wtf/RetainPtr.h new file mode 100644 index 0000000..65fc27b --- /dev/null +++ b/WebKitTools/Drosera/ForwardingHeaders/wtf/RetainPtr.h @@ -0,0 +1 @@ +#include <JavaScriptCore/RetainPtr.h> diff --git a/WebKitTools/Drosera/Images/Drosera.ico b/WebKitTools/Drosera/Images/Drosera.ico Binary files differnew file mode 100644 index 0000000..18a459d --- /dev/null +++ b/WebKitTools/Drosera/Images/Drosera.ico diff --git a/WebKitTools/Drosera/Images/SourceArrow.png b/WebKitTools/Drosera/Images/SourceArrow.png Binary files differnew file mode 100644 index 0000000..f493903 --- /dev/null +++ b/WebKitTools/Drosera/Images/SourceArrow.png diff --git a/WebKitTools/Drosera/Images/SourceArrowBlank.png b/WebKitTools/Drosera/Images/SourceArrowBlank.png Binary files differnew file mode 100644 index 0000000..d178ac0 --- /dev/null +++ b/WebKitTools/Drosera/Images/SourceArrowBlank.png diff --git a/WebKitTools/Drosera/Images/SourceArrowOpen.png b/WebKitTools/Drosera/Images/SourceArrowOpen.png Binary files differnew file mode 100644 index 0000000..4016402 --- /dev/null +++ b/WebKitTools/Drosera/Images/SourceArrowOpen.png diff --git a/WebKitTools/Drosera/Images/background_stripe.png b/WebKitTools/Drosera/Images/background_stripe.png Binary files differnew file mode 100644 index 0000000..d9ddebc --- /dev/null +++ b/WebKitTools/Drosera/Images/background_stripe.png diff --git a/WebKitTools/Drosera/Images/breakPoint.tif b/WebKitTools/Drosera/Images/breakPoint.tif Binary files differnew file mode 100644 index 0000000..95431b4 --- /dev/null +++ b/WebKitTools/Drosera/Images/breakPoint.tif diff --git a/WebKitTools/Drosera/Images/breakPointDisabled.tif b/WebKitTools/Drosera/Images/breakPointDisabled.tif Binary files differnew file mode 100644 index 0000000..2000bd2 --- /dev/null +++ b/WebKitTools/Drosera/Images/breakPointDisabled.tif diff --git a/WebKitTools/Drosera/Images/breakpointeditor.png b/WebKitTools/Drosera/Images/breakpointeditor.png Binary files differnew file mode 100644 index 0000000..8bb992b --- /dev/null +++ b/WebKitTools/Drosera/Images/breakpointeditor.png diff --git a/WebKitTools/Drosera/Images/close.tif b/WebKitTools/Drosera/Images/close.tif Binary files differnew file mode 100644 index 0000000..a221ac7 --- /dev/null +++ b/WebKitTools/Drosera/Images/close.tif diff --git a/WebKitTools/Drosera/Images/close_active.tif b/WebKitTools/Drosera/Images/close_active.tif Binary files differnew file mode 100644 index 0000000..104799d --- /dev/null +++ b/WebKitTools/Drosera/Images/close_active.tif diff --git a/WebKitTools/Drosera/Images/close_hover.tif b/WebKitTools/Drosera/Images/close_hover.tif Binary files differnew file mode 100644 index 0000000..cd86fa5 --- /dev/null +++ b/WebKitTools/Drosera/Images/close_hover.tif diff --git a/WebKitTools/Drosera/Images/console.png b/WebKitTools/Drosera/Images/console.png Binary files differnew file mode 100644 index 0000000..fe7cbe6 --- /dev/null +++ b/WebKitTools/Drosera/Images/console.png diff --git a/WebKitTools/Drosera/Images/continue.tif b/WebKitTools/Drosera/Images/continue.tif Binary files differnew file mode 100644 index 0000000..58b9893 --- /dev/null +++ b/WebKitTools/Drosera/Images/continue.tif diff --git a/WebKitTools/Drosera/Images/fileIcon.jpg b/WebKitTools/Drosera/Images/fileIcon.jpg Binary files differnew file mode 100644 index 0000000..c651a78 --- /dev/null +++ b/WebKitTools/Drosera/Images/fileIcon.jpg diff --git a/WebKitTools/Drosera/Images/finishFunction.tif b/WebKitTools/Drosera/Images/finishFunction.tif Binary files differnew file mode 100644 index 0000000..af75e60 --- /dev/null +++ b/WebKitTools/Drosera/Images/finishFunction.tif diff --git a/WebKitTools/Drosera/Images/glossyFooterFill.tif b/WebKitTools/Drosera/Images/glossyFooterFill.tif Binary files differnew file mode 100644 index 0000000..d5ea4d4 --- /dev/null +++ b/WebKitTools/Drosera/Images/glossyFooterFill.tif diff --git a/WebKitTools/Drosera/Images/glossyHeader.png b/WebKitTools/Drosera/Images/glossyHeader.png Binary files differnew file mode 100644 index 0000000..8c80b6b --- /dev/null +++ b/WebKitTools/Drosera/Images/glossyHeader.png diff --git a/WebKitTools/Drosera/Images/glossyHeaderPressed.png b/WebKitTools/Drosera/Images/glossyHeaderPressed.png Binary files differnew file mode 100644 index 0000000..6b0dd60 --- /dev/null +++ b/WebKitTools/Drosera/Images/glossyHeaderPressed.png diff --git a/WebKitTools/Drosera/Images/gradientBackground.png b/WebKitTools/Drosera/Images/gradientBackground.png Binary files differnew file mode 100644 index 0000000..c0ce0a5 --- /dev/null +++ b/WebKitTools/Drosera/Images/gradientBackground.png diff --git a/WebKitTools/Drosera/Images/gutter.png b/WebKitTools/Drosera/Images/gutter.png Binary files differnew file mode 100644 index 0000000..9b698c1 --- /dev/null +++ b/WebKitTools/Drosera/Images/gutter.png diff --git a/WebKitTools/Drosera/Images/navLeftDisabled.png b/WebKitTools/Drosera/Images/navLeftDisabled.png Binary files differnew file mode 100644 index 0000000..edd7c26 --- /dev/null +++ b/WebKitTools/Drosera/Images/navLeftDisabled.png diff --git a/WebKitTools/Drosera/Images/navLeftNormal.png b/WebKitTools/Drosera/Images/navLeftNormal.png Binary files differnew file mode 100644 index 0000000..9a14bbf --- /dev/null +++ b/WebKitTools/Drosera/Images/navLeftNormal.png diff --git a/WebKitTools/Drosera/Images/navLeftPressed.png b/WebKitTools/Drosera/Images/navLeftPressed.png Binary files differnew file mode 100644 index 0000000..840a4b4 --- /dev/null +++ b/WebKitTools/Drosera/Images/navLeftPressed.png diff --git a/WebKitTools/Drosera/Images/navRightDisabled.png b/WebKitTools/Drosera/Images/navRightDisabled.png Binary files differnew file mode 100644 index 0000000..6057aae --- /dev/null +++ b/WebKitTools/Drosera/Images/navRightDisabled.png diff --git a/WebKitTools/Drosera/Images/navRightNormal.png b/WebKitTools/Drosera/Images/navRightNormal.png Binary files differnew file mode 100644 index 0000000..936cd91 --- /dev/null +++ b/WebKitTools/Drosera/Images/navRightNormal.png diff --git a/WebKitTools/Drosera/Images/navRightPressed.png b/WebKitTools/Drosera/Images/navRightPressed.png Binary files differnew file mode 100644 index 0000000..faf78ce --- /dev/null +++ b/WebKitTools/Drosera/Images/navRightPressed.png diff --git a/WebKitTools/Drosera/Images/pause.tif b/WebKitTools/Drosera/Images/pause.tif Binary files differnew file mode 100644 index 0000000..460aeed --- /dev/null +++ b/WebKitTools/Drosera/Images/pause.tif diff --git a/WebKitTools/Drosera/Images/popUpArrows.png b/WebKitTools/Drosera/Images/popUpArrows.png Binary files differnew file mode 100644 index 0000000..f47eaa5 --- /dev/null +++ b/WebKitTools/Drosera/Images/popUpArrows.png diff --git a/WebKitTools/Drosera/Images/programCounter.tif b/WebKitTools/Drosera/Images/programCounter.tif Binary files differnew file mode 100644 index 0000000..e65d549 --- /dev/null +++ b/WebKitTools/Drosera/Images/programCounter.tif diff --git a/WebKitTools/Drosera/Images/programCounterBreakPoint.tif b/WebKitTools/Drosera/Images/programCounterBreakPoint.tif Binary files differnew file mode 100644 index 0000000..093b639 --- /dev/null +++ b/WebKitTools/Drosera/Images/programCounterBreakPoint.tif diff --git a/WebKitTools/Drosera/Images/programCounterBreakPointDisabled.tif b/WebKitTools/Drosera/Images/programCounterBreakPointDisabled.tif Binary files differnew file mode 100644 index 0000000..1c1a699 --- /dev/null +++ b/WebKitTools/Drosera/Images/programCounterBreakPointDisabled.tif diff --git a/WebKitTools/Drosera/Images/run.tif b/WebKitTools/Drosera/Images/run.tif Binary files differnew file mode 100644 index 0000000..f9e815f --- /dev/null +++ b/WebKitTools/Drosera/Images/run.tif diff --git a/WebKitTools/Drosera/Images/siteCollapsed.tif b/WebKitTools/Drosera/Images/siteCollapsed.tif Binary files differnew file mode 100644 index 0000000..07d8a12 --- /dev/null +++ b/WebKitTools/Drosera/Images/siteCollapsed.tif diff --git a/WebKitTools/Drosera/Images/siteExpanded.tif b/WebKitTools/Drosera/Images/siteExpanded.tif Binary files differnew file mode 100644 index 0000000..8044385 --- /dev/null +++ b/WebKitTools/Drosera/Images/siteExpanded.tif diff --git a/WebKitTools/Drosera/Images/siteIcon.tif b/WebKitTools/Drosera/Images/siteIcon.tif Binary files differnew file mode 100644 index 0000000..d32654f --- /dev/null +++ b/WebKitTools/Drosera/Images/siteIcon.tif diff --git a/WebKitTools/Drosera/Images/small.ico b/WebKitTools/Drosera/Images/small.ico Binary files differnew file mode 100644 index 0000000..18a459d --- /dev/null +++ b/WebKitTools/Drosera/Images/small.ico diff --git a/WebKitTools/Drosera/Images/splitterBar.tif b/WebKitTools/Drosera/Images/splitterBar.tif Binary files differnew file mode 100644 index 0000000..0e7425d --- /dev/null +++ b/WebKitTools/Drosera/Images/splitterBar.tif diff --git a/WebKitTools/Drosera/Images/splitterDimple.tif b/WebKitTools/Drosera/Images/splitterDimple.tif Binary files differnew file mode 100644 index 0000000..d112854 --- /dev/null +++ b/WebKitTools/Drosera/Images/splitterDimple.tif diff --git a/WebKitTools/Drosera/Images/step.tif b/WebKitTools/Drosera/Images/step.tif Binary files differnew file mode 100644 index 0000000..457f1cd --- /dev/null +++ b/WebKitTools/Drosera/Images/step.tif diff --git a/WebKitTools/Drosera/Images/stepOut.tif b/WebKitTools/Drosera/Images/stepOut.tif Binary files differnew file mode 100644 index 0000000..ff9e64b --- /dev/null +++ b/WebKitTools/Drosera/Images/stepOut.tif diff --git a/WebKitTools/Drosera/Images/stepOver.tif b/WebKitTools/Drosera/Images/stepOver.tif Binary files differnew file mode 100644 index 0000000..6c18c71 --- /dev/null +++ b/WebKitTools/Drosera/Images/stepOver.tif diff --git a/WebKitTools/Drosera/Images/stop.tif b/WebKitTools/Drosera/Images/stop.tif Binary files differnew file mode 100644 index 0000000..a65c6df --- /dev/null +++ b/WebKitTools/Drosera/Images/stop.tif diff --git a/WebKitTools/Drosera/Images/toolbarBackground.png b/WebKitTools/Drosera/Images/toolbarBackground.png Binary files differnew file mode 100644 index 0000000..018e001 --- /dev/null +++ b/WebKitTools/Drosera/Images/toolbarBackground.png diff --git a/WebKitTools/Drosera/Images/verticalSplitterBar.tiff b/WebKitTools/Drosera/Images/verticalSplitterBar.tiff Binary files differnew file mode 100644 index 0000000..4810d01 --- /dev/null +++ b/WebKitTools/Drosera/Images/verticalSplitterBar.tiff diff --git a/WebKitTools/Drosera/Images/verticalSplitterDimple.tiff b/WebKitTools/Drosera/Images/verticalSplitterDimple.tiff Binary files differnew file mode 100644 index 0000000..fee927b --- /dev/null +++ b/WebKitTools/Drosera/Images/verticalSplitterDimple.tiff diff --git a/WebKitTools/Drosera/Makefile b/WebKitTools/Drosera/Makefile new file mode 100644 index 0000000..4fce090 --- /dev/null +++ b/WebKitTools/Drosera/Makefile @@ -0,0 +1,3 @@ +OTHER_OPTIONS = -project mac/Drosera.xcodeproj +SCRIPTS_PATH = ../Scripts +include ../../Makefile.shared diff --git a/WebKitTools/Drosera/breakpointEditor.html b/WebKitTools/Drosera/breakpointEditor.html new file mode 100644 index 0000000..30ef0c9 --- /dev/null +++ b/WebKitTools/Drosera/breakpointEditor.html @@ -0,0 +1 @@ +<div class="top">Breakpoint:<label>Enable:<input class="enable" type="checkbox" onclick="window.parent.toggleBreakpointOnLine(this.firstParentWithClass('editor').id)"></input></label><label>Hit Count:<span class="hitCounter">0</span></label><label>Action:<select class="editorDropdown" onchange="window.parent.updateBreakpointTypeOnLine(this.firstParentWithClass('editor').id)"><option value="pause">Pause</option><option value="log">Log</option></select></label><input type="button" class="close" onmouseup="window.parent.toggleBreakpointEditorOnLine(this.firstParentWithClass('editor').id)"> </input></div><div class="bottom"><label class="conditionLabel" for="editorCondition">Condition:</label><div class="condition"></div></div>
\ No newline at end of file diff --git a/WebKitTools/Drosera/config.h b/WebKitTools/Drosera/config.h new file mode 100644 index 0000000..0b4a2c8 --- /dev/null +++ b/WebKitTools/Drosera/config.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2004-2007 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include <wtf/Platform.h> + +#if PLATFORM(MAC) + +#import <WebKit/WebKit.h> +#import <WebKit/WebScriptDebugServer.h> + +#endif + +#if PLATFORM(WIN) + +// If we don't define these, they get defined in windef.h. +// We want to use std::min and std::max +#ifndef max +#define max max +#endif +#ifndef min +#define min min +#endif + +#include <tchar.h> + +#endif // PLATFORM(WIN) + diff --git a/WebKitTools/Drosera/console.css b/WebKitTools/Drosera/console.css new file mode 100644 index 0000000..02c37b7 --- /dev/null +++ b/WebKitTools/Drosera/console.css @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 David Smith (catfish.man@gmail.com) + * + * 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. + */ + +img { padding: 0; margin: 0; } +body { margin: 0; padding: 0; overflow: hidden; } + +#main { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +#top { + position: absolute; + top: 0; + bottom: 50px; + left: 0; + right: 0; +} + +#history { + position: absolute; + top: 0; + bottom: 10px; + left: 0; + right: 0; + overflow-y: auto; + overflow-x: hidden; +} + +#divider { + cursor: row-resize; + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: url(splitterDimple.tif) 50% no-repeat, url(splitterBar.tif) repeat-x; + height: 10px; +} + +#input { + position: absolute; + -webkit-box-sizing: border-box; + height: 50px; + max-height: 150px; + left: 0; + right: 0; + bottom: 0; + -webkit-user-modify: read-write-plaintext-only; + -webkit-nbsp-mode: space; + -webkit-line-break: after-white-space; + word-wrap: break-word; + outline: none; + font-family: monospace; + font-size: 11px; + line-height: 14px; + padding: 3px; +} + +#history .row { + min-height: 38px; + padding: 4px; + -webkit-box-sizing: border-box; + font-family: monospace; + font-size: 12px; +} + +#history .row.alt { + background-color: rgb(237, 243, 254); +} + +.expression { + color: blue; +} + +.result { + color: navy; +} diff --git a/WebKitTools/Drosera/console.html b/WebKitTools/Drosera/console.html new file mode 100644 index 0000000..888878b --- /dev/null +++ b/WebKitTools/Drosera/console.html @@ -0,0 +1,47 @@ +<!-- +Copyright (C) 2006 Apple Computer, Inc. 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. +--> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + <title>Console</title> + <script type="text/javascript" src="console.js"></script> + <style type="text/css"> + @import "console.css"; + </style> +</head> +<body onload="loaded()" onunload="unloading()"> +<div id="main"> +<div id="top"> +<div id="history"></div> +<div id="divider"></div> +</div> +<div id="input"></div> +</div> +</body> +</html> diff --git a/WebKitTools/Drosera/console.js b/WebKitTools/Drosera/console.js new file mode 100644 index 0000000..7db3fb4 --- /dev/null +++ b/WebKitTools/Drosera/console.js @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 David Smith (catfish.man@gmail.com) + * + * 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. + */ + +var inputElement = null; +var mainWindow = window.opener; +var history = [""]; +var historyIndex = 0; + +function loaded() +{ + inputElement = document.getElementById("input"); + inputElement.addEventListener("keydown", inputKeyDown, false); + inputElement.addEventListener("keyup", inputKeyUp, false); + inputElement.focus(); +} + +function inputKeyDown(event) +{ + if (event.keyCode == 13 && !event.altKey) { + if (mainWindow.isPaused && mainWindow.currentStack) { + history[history.length - 1] = inputElement.innerText; + sendScript(inputElement.innerText); + inputElement.innerText = ""; + history.push(""); + historyIndex = history.length - 1; + inputElement.focus(); + } else + alert("The debugger needs to be paused.\tIn order to evaluate your script input you need to pause the debugger in the context of another script."); + event.preventDefault(); + } else if (event.keyCode == 38 && !event.altKey && historyIndex > 0) { + historyIndex--; + inputElement.innerText = history[historyIndex]; + inputElement.focus() + event.preventDefault(); + } else if (event.keyCode == 40 && !event.altKey && historyIndex < (history.length - 1)) { + historyIndex++; + inputElement.innerText = history[historyIndex]; + inputElement.focus() + event.preventDefault(); + } +} + +function inputKeyUp(event) +{ + if (event.keyCode != 38 && event.keyCode != 40 && event.keyCode != 13) { + history[historyIndex] = inputElement.innerText; + } +} + +function appendMessage(exp, msg) +{ + var historyDisplay = document.getElementById("history"); + var row = document.createElement("div"); + row.className = "row"; + if (historyDisplay.childNodes.length % 2) + row.className += " alt"; + + if (exp.length > 0) { + var expression = document.createElement("div"); + expression.className = "expression"; + expression.innerText = exp; + row.appendChild(expression); + } + + var result = document.createElement("div"); + result.className = "result"; + result.innerText = msg; + + row.appendChild(result); + + historyDisplay.appendChild(row); + historyDisplay.scrollTop = historyDisplay.scrollHeight; +} + +function sendScript(script) +{ + appendMessage(script, mainWindow.DebuggerDocument.evaluateScript(script, mainWindow.currentCallFrame.index)); + if (script.indexOf("=") >= 0) + mainWindow.currentCallFrame.loadVariables(); +} + +function unloading() +{ + mainWindow.consoleWindow = null; +} diff --git a/WebKitTools/Drosera/debugger.css b/WebKitTools/Drosera/debugger.css new file mode 100644 index 0000000..f15d572 --- /dev/null +++ b/WebKitTools/Drosera/debugger.css @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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. + */ + +img { padding: 0; margin: 0; } +body { margin: 0; padding: 0; overflow: hidden; } +iframe { border: none; } + +#fileBrowser { position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 220px;} +#fileList { position: absolute; top: 0; bottom: 0; left: 0; right: 10px; padding: 0; margin: 0; } +#filesDivider { position: absolute; z-index: 10; right: 0px; bottom: 0px; top: 0; width: 10px; cursor: col-resize; background: url(verticalSplitterDimple.tiff) 50% no-repeat, url(verticalSplitterBar.tiff) repeat-y; width: 10px; } +#masterMain { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } +#main { position: absolute; top: 0; bottom: 0; left: 220px; right: 0; } +#info { position: absolute; top: 0; height: 175px; left: 0; right: 0; } +#divider { cursor: row-resize; position: absolute; bottom: 0; left: 0; right: 0; background: url(splitterDimple.tif) 50% no-repeat, url(splitterBar.tif) repeat-x; height: 10px } +#body { position: absolute; top: 175px; left: 0; right: 0; bottom: 0; } +#sourcesContainer { position: absolute; top: 16px; left: 0; right: 0; bottom: 21px; background-color: white; } +#sources { width: 100%; height: 100% } +#header { vertical-align: top; height: 16px; -webkit-box-sizing: border-box; border-bottom: 1px solid #aaa; background: url(glossyHeader.png) repeat-x; position: absolute; top: 0; left: 0; right: 0; } +#header > * { vertical-align: top; } +.footer { height: 21px; -webkit-box-sizing: border-box; border-top: 1px solid #aaa; background: url(glossyFooterFill.tif) repeat-x; position: absolute; bottom: 0; left: 0; right: 0; } +#infoDivider { position: absolute; z-index: 10; right: 0; left: 0; top: 0; bottom: 9px; width: 10px; cursor: col-resize; background: url(verticalSplitterDimple.tiff) 50% no-repeat, url(verticalSplitterBar.tiff) repeat-y; width: 10px; } + +#filesBrowserSites { + position: absolute; + font-family: "Lucida Grande", sans-serif; + font-size: 11px; + padding: 2px; + overflow-x: hidden; + overflow-y: auto; + top: 16px; + left: 0; + right: 0; + bottom: 21px; + background-color: white; +} + +#filesBrowserSites div { + font-weight: normal; + overflow: hidden; + white-space: nowrap; + padding-left: 26px; + background: url(siteExpanded.tif) no-repeat 0px 0px; + cursor: default; + margin-bottom: 2px; +} + +#filesBrowserSites div.expanded { + background: url(siteExpanded.tif) no-repeat 0px 0px; +} +#filesBrowserSites div.collapsed { + background: url(siteCollapsed.tif) no-repeat 0px 0px; +} + +#filesBrowserSites div ul { + margin: 0; + padding: 0; + list-style-type: none; + font-weight: normal; +} + +#filesBrowserSites div ul li { + margin-left: -25px; + height: 15px; + padding-left: 38px; + margin-top: 1px; + margin-bottom: 1px; + background: url(fileIcon.jpg) no-repeat 26px 0%; + cursor: default; + overflow: hidden; +} + +#filesBrowserSites div ul li.active { + background-color: #ccc; +} + +#filesBrowserSites div ul li.passive { + background-color: white; +} + +#files, #functions { + opacity: 0; + position: absolute; + top: -2px; + left: -3px; + right: 0; + z-index: 10; + margin: 0; + padding: 0; + min-width: 100px; +} + +button.popup { + background: url(popUpArrows.png) right no-repeat; + border: none; + height: 15px; + font-size: 10px; + line-height: 10px; + padding: 0 20px 0 5px; + margin: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + position: relative; + min-width: 100px; + max-width: 350px; +} + +#filesPopupButtonContent, #functionButtonContent { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + height: 100%; + line-height: 12px; + text-align: left; +} + +.placeholder { color: rgba(0, 0, 0, 0.6) } + +button.nav { + position: relative; + width: 32px; + height: 15px; + border: none; + margin: 0; + padding: 0; + border-left: 1px solid transparent; + border-right: 1px solid #aaa; +} + +button.nav.right { + background: url(navRightNormal.png) no-repeat; +} + +button.nav.right:disabled, button.nav.right:disabled:active { + border-left: 1px solid transparent; + background: url(navRightDisabled.png) no-repeat; +} + +button.nav.right:active { + border-left: 1px solid rgba(0, 0, 0, 0.3); + background: url(navRightPressed.png) no-repeat; +} + +button.nav.left { + background: url(navLeftNormal.png) no-repeat; +} + +button.nav.left:disabled, button.nav.left:disabled:active { + border-left: 1px solid transparent; + background: url(navLeftDisabled.png) no-repeat; +} + +button.nav.left:active { + margin-left: 0; + border-left: 1px solid rgba(0, 0, 0, 0.3); + background: url(navLeftPressed.png) no-repeat; +} + +#leftPane { + position: absolute; + top: 0; + bottom: 10px; + left: 0; + width: 253px; + padding: 0; + margin: 0; +} + +#rightPane { + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 253px; + padding: 0; + margin: 0; +} + +#stackframe { + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 0; +} + +#stackframeBody { + overflow-y: scroll; + overflow-x: hidden; + position: absolute; + top: 16px; + bottom: 0; + right: 0; + left: 0; +} + +#variables { + position: absolute; + top: 0; + bottom: 10px; + right: 0; + left: 10px; +} + +#variablesBody { + overflow-y: scroll; + overflow-x: hidden; + position: absolute; + top: 16px; + bottom: 0; + right: 0; + left: 0; +} + +.infoBackground { + background: url(background_stripe.png) repeat; + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 0; + z-index: -1; +} + +table { + font-family: "Lucida Grande", sans-serif; + font-size: 11px; + border-collapse: collapse; + border-spacing: 0; + width: 100%; + padding: 0; + margin: 0; + border: 0; +} + +td { + padding: 3px 7px 3px 9px; + height: 15px; + -webkit-box-sizing: border-box; + -webkit-user-select: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +tr.current { + background-color: rgb(56, 117, 215); + color: white; +} + +.stackNumber { + width: 2em; + padding: 3px 0; + text-align: center; +} + +.variable { + width: 170px; +} + +.column th.scrollCorner { + width: 15px; + padding: 0; + border-right: none; +} + +#variableColumnResizer { + position: absolute; + top: 0; + left: 168px; + width: 4px; + height: 16px; + cursor: col-resize; +} + +.column th { + background: url(glossyHeader.png) repeat-x; + border-right: 1px solid #d9d9d9; + height: 15px; + -webkit-box-sizing: border-box; + border-bottom: 1px solid #aaa; + font-weight: normal; + vertical-align: middle; + padding: 0 8px; + text-align: left; + -webkit-user-select: none; +} diff --git a/WebKitTools/Drosera/debugger.html b/WebKitTools/Drosera/debugger.html new file mode 100644 index 0000000..4b9685d --- /dev/null +++ b/WebKitTools/Drosera/debugger.html @@ -0,0 +1,92 @@ +<!-- +Copyright (C) 2006 Apple Computer, Inc. All rights reserved. +Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + +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. +--> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + <title>Debugger</title> + <script type="text/javascript" src="debugger.js"></script> + <style type="text/css"> + @import "debugger.css"; + </style> +</head> +<body onload="loaded()"> +<div id="masterMain"> +<div id="fileBrowser"> +<div id="fileList"> +<table id="fileListTableHeader"> +<tr class="column"><th onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Files</th><th class="scrollCorner"></th></tr> +</table> +<div id="filesBrowserSites"> +</div> +<div class="footer"></div> +</div> +<div id="filesDivider"></div> +</div> +<div id="main"> +<div id="info"> +<div id="leftPane"> +<div id="stackframe"> +<table id="stackframeTableHeader"> +<tr class="column"><th class="stackNumber" onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">#</th><th onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Function</th><th class="scrollCorner"></th></tr> +</table> +<div id="stackframeBody"> +<div class="infoBackground"></div> +<table id="stackframeTable"></table> +</div> +</div> +</div> +<div id="rightPane"> +<div id="infoDivider"></div> +<div id="variables"> +<table id="variablesTableHeader"> +<tr class="column"><th class="variable" id="variable" onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Variable<div id="variableColumnResizer"></div> +</th><th onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Value</th><th class="scrollCorner"></th></tr> +</table> +<div id="variablesBody"> +<div class="infoBackground"></div> +<table id="variablesTable"></table> +</div> +</div> +</div> +<div id="divider"></div> +</div> +<div id="body"> +<div id="header"> +<button id="navFileLeftButton" class="nav left" disabled onclick="navFilePrevious(this)"></button><button id="navFileRightButton" class="nav right" disabled onclick="navFileNext(this)"></button> +<button class="popup"><select size="1" id="files" onchange="switchFile()"></select><div id="filesPopupButtonContent"><span class="placeholder"><No files loaded></span></div></button> +<button class="popup" id="functionNamesPopup" style="display: none"><select size="1" id="functions" onchange="switchFunction(this.selectedIndex)"></select><div id="functionPopupButtonContent"><span class="placeholder"><No selected symbol></span></div></button> +</div> +<div id="sourcesContainer"><iframe name="sourcesFrame" id="sources" src="viewer.html"></iframe></div> +<div class="footer"></div> +</div> +</div> +</div> +</body> +</html> diff --git a/WebKitTools/Drosera/debugger.js b/WebKitTools/Drosera/debugger.js new file mode 100644 index 0000000..076fedf --- /dev/null +++ b/WebKitTools/Drosera/debugger.js @@ -0,0 +1,1433 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 David Smith (catfish.man@gmail.com) + * Copyright (C) 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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. + */ + +var files = new Array(); +var filesLookup = new Object(); +var scripts = new Array(); +var currentFile = -1; +var currentRow = null; +var currentStack = null; +var currentCallFrame = null; +var lastStatement = null; +var frameLineNumberStack = new Array(); +var previousFiles = new Array(); +var nextFiles = new Array(); +var isResizingColumn = false; +var draggingBreakpoint = null; +var steppingOut = false; +var steppingOver = false; +var steppingStack = 0; +var pauseOnNextStatement = false; +var pausedWhileLeavingFrame = false; +var consoleWindow = null; +var breakpointEditorHTML = DebuggerDocument.breakpointEditorHTML(); +var pendingAction = null; +var isPaused = false; + +ScriptCallFrame = function (functionName, index, row) +{ + this.functionName = functionName; + this.index = index; + this.row = row; + this.localVariableNames = null; +} + +ScriptCallFrame.prototype.valueForScopeVariable = function (name) +{ + return DebuggerDocument.valueForScopeVariableNamed(name, this.index); +} + +ScriptCallFrame.prototype.loadVariables = function () +{ + if (!this.localVariableNames) + this.localVariableNames = DebuggerDocument.localScopeVariableNamesForCallFrame(this.index); + + var variablesTable = document.getElementById("variablesTable"); + variablesTable.innerHTML = ""; + + if (!this.localVariableNames) + return; + + for(var i = 0; i < this.localVariableNames.length; i++) { + var tr = document.createElement("tr"); + var td = document.createElement("td"); + td.innerText = this.localVariableNames[i]; + td.className = "variable"; + tr.appendChild(td); + + td = document.createElement("td"); + td.innerText = this.valueForScopeVariable(this.localVariableNames[i]); + tr.appendChild(td); + tr.addEventListener("click", selectVariable, true); + + variablesTable.appendChild(tr); + } +} + +function sleep(numberMillis) +{ + var now = new Date(); + var exitTime = now.getTime() + numberMillis; + while (true) { + now = new Date(); + if (now.getTime() > exitTime) + return; + } +} + +function headerMouseDown(element) +{ + if (!isResizingColumn) + element.style.background = "url(glossyHeaderPressed.png) repeat-x"; +} + +function headerMouseUp(element) +{ + element.style.background = "url(glossyHeader.png) repeat-x"; +} + +function headerMouseOut(element) +{ + element.style.background = "url(glossyHeader.png) repeat-x"; +} + +function filesDividerDragStart(event) +{ + dividerDragStart(document.getElementById("filesDivider"), filesDividerDrag, filesDividerDragEnd, event, "col-resize"); +} + +function filesDividerDragEnd(event) +{ + dividerDragEnd(document.getElementById("filesDivider"), filesDividerDrag, filesDividerDragEnd, event); +} + +function filesDividerDrag(event) +{ + var element = document.getElementById("filesDivider"); + if (document.getElementById("filesDivider").dragging == true) { + var masterMain = document.getElementById("masterMain"); + var main = document.getElementById("main"); + var fileBrowser = document.getElementById("fileBrowser"); + var x = event.clientX + window.scrollX; + var delta = element.dragLastX - x; + var newWidth = constrainedWidthFromElement(fileBrowser.clientWidth - delta, masterMain, 0.1, 0.9); + if ((fileBrowser.clientWidth - delta) == newWidth) // the width wasn't constrained + element.dragLastX = x; + fileBrowser.style.width = newWidth + "px"; + main.style.left = newWidth + "px"; + event.preventDefault(); + } +} + +function dividerDragStart(element, dividerDrag, dividerDragEnd, event, cursor) +{ + element.dragging = true; + element.dragLastY = event.clientY + window.scrollY; + element.dragLastX = event.clientX + window.scrollX; + document.addEventListener("mousemove", dividerDrag, true); + document.addEventListener("mouseup", dividerDragEnd, true); + document.body.style.cursor = cursor; + event.preventDefault(); +} + +function dividerDragEnd(element, dividerDrag, dividerDragEnd, event) +{ + element.dragging = false; + document.removeEventListener("mousemove", dividerDrag, true); + document.removeEventListener("mouseup", dividerDragEnd, true); + document.body.style.removeProperty("cursor"); +} + +function dividerDrag(event) +{ + var element = document.getElementById("divider"); + if (document.getElementById("divider").dragging == true) { + var main = document.getElementById("main"); + var top = document.getElementById("info"); + var bottom = document.getElementById("body"); + var y = event.clientY + window.scrollY; + var delta = element.dragLastY - y; + var newHeight = constrainedHeightFromElement(top.clientHeight - delta, main); + if ((top.clientHeight - delta) == newHeight) // the height wasn't constrained + element.dragLastY = y; + top.style.height = newHeight + "px"; + bottom.style.top = newHeight + "px"; + event.preventDefault(); + } +} + +function sourceDividerDragStart(event) +{ + dividerDragStart(document.getElementById("divider"), dividerDrag, sourceDividerDragEnd, event, "row-resize"); +} + +function sourceDividerDragEnd(event) +{ + dividerDragEnd(document.getElementById("divider"), dividerDrag, sourceDividerDragEnd, event); +} + +function infoDividerDragStart(event) +{ + dividerDragStart(document.getElementById("infoDivider"), infoDividerDrag, infoDividerDragEnd, event, "col-resize"); +} + +function infoDividerDragEnd(event) +{ + dividerDragEnd(document.getElementById("infoDivider"), infoDividerDrag, infoDividerDragEnd, event); +} + +function infoDividerDrag(event) +{ + var element = document.getElementById("infoDivider"); + if (document.getElementById("infoDivider").dragging == true) { + var main = document.getElementById("main"); + var leftPane = document.getElementById("leftPane"); + var rightPane = document.getElementById("rightPane"); + var x = event.clientX + window.scrollX; + var delta = element.dragLastX - x; + var newWidth = constrainedWidthFromElement(leftPane.clientWidth - delta, main); + if ((leftPane.clientWidth - delta) == newWidth) // the width wasn't constrained + element.dragLastX = x; + leftPane.style.width = newWidth + "px"; + rightPane.style.left = newWidth + "px"; + event.preventDefault(); + } +} + +function columnResizerDragStart(event) +{ + isResizingColumn = true; + dividerDragStart(document.getElementById("variableColumnResizer"), columnResizerDrag, columnResizerDragEnd, event, "col-resize"); +} + +function columnResizerDragEnd(event) +{ + isResizingColumn = false; + dividerDragEnd(document.getElementById("variableColumnResizer"), columnResizerDrag, columnResizerDragEnd, event); +} + +function columnResizerDrag(event) +{ + var element = document.getElementById("variableColumnResizer"); + if (element.dragging == true) { + var main = document.getElementById("rightPane"); + var variableColumn = document.getElementById("variable"); + var rules = document.defaultView.getMatchedCSSRules(variableColumn, ""); + for (var i = 0; i < rules.length; i++) { + if (rules[i].selectorText == ".variable") { + var columnRule = rules[i]; + break; + } + } + + var x = event.clientX + window.scrollX; + var delta = element.dragLastX - x; + var newWidth = constrainedWidthFromElement(variableColumn.clientWidth - delta, main); + if ((variableColumn.clientWidth - delta) == newWidth) // the width wasn't constrained + element.dragLastX = x; + columnRule.style.width = newWidth + "px"; + element.style.left = newWidth + "px"; + event.preventDefault(); + } +} + +function constrainedWidthFromElement(width, element, constrainLeft, constrainRight) +{ + if (constrainLeft === undefined) constrainLeft = 0.25; + if (constrainRight === undefined) constrainRight = 0.75; + + if (width < element.clientWidth * constrainLeft) + width = element.clientWidth * constrainLeft; + else if (width > element.clientWidth * constrainRight) + width = element.clientWidth * constrainRight; + return width; +} + +function constrainedHeightFromElement(height, element) +{ + if (height < element.clientHeight * 0.25) + height = element.clientHeight * 0.25; + else if (height > element.clientHeight * 0.75) + height = element.clientHeight * 0.75; + return height; +} + +function loaded() +{ + document.getElementById("divider").addEventListener("mousedown", sourceDividerDragStart, false); + document.getElementById("infoDivider").addEventListener("mousedown", infoDividerDragStart, false); + document.getElementById("filesDivider").addEventListener("mousedown", filesDividerDragStart, false); + document.getElementById("variableColumnResizer").addEventListener("mousedown", columnResizerDragStart, false); +} + +function pause() +{ + DebuggerDocument.pause(); + isPaused = true; +} + +function resume() +{ + if (currentRow) { + currentRow.removeStyleClass("current"); + currentRow = null; + } + + var stackframeTable = document.getElementById("stackframeTable"); + stackframeTable.innerHTML = ""; // clear the content + var variablesTable = document.getElementById("variablesTable"); + variablesTable.innerHTML = ""; // clear the content + currentStack = null; + currentCallFrame = null; + + pauseOnNextStatement = false; + pausedWhileLeavingFrame = false; + steppingOut = false; + steppingOver = false; + steppingStack = 0; + + DebuggerDocument.resume(); + isPaused = false; +} + +function stepInto() +{ + pauseOnNextStatement = false; + steppingOut = false; + steppingOver = false; + steppingStack = 0; + DebuggerDocument.stepInto(); +} + +function stepOver() +{ + pauseOnNextStatement = false; + steppingOver = true; + steppingStack = 0; + DebuggerDocument.resume(); +} + +function stepOut() +{ + pauseOnNextStatement = pausedWhileLeavingFrame; + steppingOver = false; + steppingStack = 0; + steppingOut = true; + DebuggerDocument.resume(); +} + +Element.prototype.removeStyleClass = function(className) +{ + if (this.hasStyleClass(className)) + this.className = this.className.replace(className, ""); +} + +Element.prototype.addStyleClass = function(className) +{ + if (!this.hasStyleClass(className)) + this.className += (this.className.length ? " " + className : className); +} + +Element.prototype.hasStyleClass = function(className) +{ + return this.className.indexOf(className) != -1; +} + +Element.prototype.firstParentWithClass = function(className) +{ + var node = this.parentNode; + while(!node.hasStyleClass(className)) { + if (node == document) + return null; + node = node.parentNode; + } + return node; +} + +Element.prototype.query = function(query) +{ + return document.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; +} + +Element.prototype.removeChildren = function() +{ + while (this.firstChild) + this.removeChild(this.firstChild); +} + +function breakpointAction(event) +{ + var file = files[currentFile]; + var lineNum = event.target.title; + + if (!file.breakpoints[lineNum]) + file.breakpoints[lineNum] = new BreakPoint(event.target.parentNode, file, lineNum); + else + toggleBreakpointOnLine(lineNum); +} + +BreakPoint = function(row, file, line) +{ + this.row = row; + this.file = file; + this.line = line; + row.addStyleClass("breakpoint"); + row.removeStyleClass("disabled"); + this.value = "break"; + this.enabled = true; + this.editor = null; + this.type = 0; + this.hitcount = 0; +} + +function toggleBreakpointEditorOnLine(lineNum) +{ + if (pendingAction) { + clearTimeout(pendingAction); + pendingAction = null; + } + var file = files[currentFile]; + bp = file.breakpoints[lineNum]; + if (bp) { + var editor = bp.editor; + if (!editor) { + var sourcesDocument = document.getElementById("sources").contentDocument; + editor = sourcesDocument.createElement("div"); + editor.className = "editor"; + editor.id = lineNum; + editor.innerHTML = breakpointEditorHTML; + + bp.row.childNodes[1].appendChild(editor); + + bp.editor = editor; + file.breakpoints[lineNum] = bp; + + editor.query('.//input[@class="enable"]').checked = bp.enabled; + + editor.query('.//select[@class="editorDropdown"]').selectedIndex = bp.type; + updateBreakpointTypeOnLine(lineNum); + + editor.query('.//span[@class="hitCounter"]').innerText = bp.hitcount; + + setConditionFieldText(bp); + } else { + saveBreakpointOnLine(lineNum); + bp.row.childNodes[1].removeChild(editor); + bp.editor = null; + } + } +} + +function updateBreakpointTypeOnLine(line) +{ + var breakpoint = files[currentFile].breakpoints[line]; + var editor = breakpoint.editor; + var label = editor.query('.//label[@class="conditionLabel"]'); + var dropdown = editor.query('.//select[@class="editorDropdown"]'); + breakpoint.type = dropdown.selectedIndex; + switch(breakpoint.type) { + case 0: + label.innerText = "Condition:"; + break; + case 1: + label.innerText = "Expression:"; + break; + } +} + +function setConditionFieldText(breakpoint) +{ + var conditionField = breakpoint.editor.query('.//div[@class="condition"]'); + + var functionBody = breakpoint.value; + if (!functionBody || functionBody == "break") + functionBody = ""; + else { + var startIndex = functionBody.indexOf("return((") + 8; + var endIndex = null; + if (startIndex != 7) //-1 + 8, yes, that's lame + endIndex = functionBody.lastIndexOf("))"); + else { + startIndex = functionBody.indexOf("{") + 1; + endIndex = functionBody.lastIndexOf("}"); + } + functionBody = functionBody.substring(startIndex, endIndex); + } + conditionField.innerText = functionBody; + conditionField.addEventListener("keyup", new Function("saveBreakpointOnLine(" + breakpoint.line + ");"), false); + conditionField.focus(); +} + +function saveBreakpointOnLine(lineNum) +{ + var file = files[currentFile]; + var breakpoint = file.breakpoints[lineNum]; + row = file.element.firstChild.childNodes.item(lineNum - 1); + var editor = breakpoint.editor; + var body = editor.query('.//div[@class="condition"]').innerText; + var actionIndex = editor.query('.//select[@class="editorDropdown"]').selectedIndex; + if (body.length == 0) + breakpoint.value = "break"; + else if (body.indexOf("return") != -1) + breakpoint.value = "__drosera_breakpoint_conditional_func = function() {" + body + "}; __drosera_breakpoint_conditional_func();"; + else + breakpoint.value = "__drosera_breakpoint_conditional_func = function() { return((" + body + ")); }; __drosera_breakpoint_conditional_func();"; +} + +function toggleBreakpointOnLine(lineNum) +{ + var breakpoint = files[currentFile].breakpoints[lineNum]; + pendingAction = null; + if (breakpoint.enabled) + breakpoint.row.addStyleClass("disabled"); + else + breakpoint.row.removeStyleClass("disabled"); + + var hack = breakpoint.row.offsetTop; // force a relayout if needed. + + breakpoint.enabled = !breakpoint.enabled; + var editor = breakpoint.editor; + if (editor) { + editor.query('.//input[@class="enable"]').checked = breakpoint.enabled; + setConditionFieldText(breakpoint, lineNum); + } +} + +function moveBreakPoint(event) +{ + if (event.target.parentNode.hasStyleClass("breakpoint")) { + draggingBreakpoint = event.target; + draggingBreakpoint.started = false; + draggingBreakpoint.dragLastY = event.clientY + window.scrollY; + draggingBreakpoint.dragLastX = event.clientX + window.scrollX; + var sourcesDocument = document.getElementById("sources").contentDocument; + sourcesDocument.addEventListener("mousemove", breakpointDrag, true); + sourcesDocument.addEventListener("mouseup", breakpointDragEnd, true); + sourcesDocument.body.style.cursor = "default"; + } +} + +function breakpointDrag(event) +{ + var sourcesDocument = document.getElementById("sources").contentDocument; + if (!draggingBreakpoint) { + sourcesDocument.removeEventListener("mousemove", breakpointDrag, true); + sourcesDocument.removeEventListener("mouseup", breakpointDragEnd, true); + sourcesDocument.body.style.removeProperty("cursor"); + return; + } + + var x = event.clientX + window.scrollX; + var y = event.clientY + window.scrollY; + var deltaX = draggingBreakpoint.dragLastX - x; + var deltaY = draggingBreakpoint.dragLastY - y; + if (draggingBreakpoint.started || deltaX > 4 || deltaY > 4 || deltaX < -4 || deltaY < -4) { + + if (!draggingBreakpoint.started) { + var lineNum = draggingBreakpoint.title; + var file = files[currentFile]; + var breakpoint = file.breakpoints[lineNum]; + draggingBreakpoint.breakpoint = breakpoint; + breakpoint.row.removeStyleClass("breakpoint"); + breakpoint.row.removeStyleClass("disabled"); + + var editor = breakpoint.editor; + if (editor) + toggleBreakpointEditorOnLine(lineNum); + + draggingBreakpoint.started = true; + + file.breakpoints[lineNum] = null; + + var dragImage = sourcesDocument.createElement("img"); + if (draggingBreakpoint.breakpoint.enabled) + dragImage.src = "breakPoint.tif"; + else + dragImage.src = "breakPointDisabled.tif"; + + dragImage.id = "breakpointDrag"; + dragImage.style.top = y - 8 + "px"; + dragImage.style.left = x - 12 + "px"; + sourcesDocument.body.appendChild(dragImage); + } else { + var dragImage = sourcesDocument.getElementById("breakpointDrag"); + if (!dragImage) { + sourcesDocument.removeEventListener("mousemove", breakpointDrag, true); + sourcesDocument.removeEventListener("mouseup", breakpointDragEnd, true); + sourcesDocument.body.style.removeProperty("cursor"); + return; + } + + dragImage.style.top = y - 8 + "px"; + dragImage.style.left = x - 12 + "px"; + if (x > 40) + dragImage.style.visibility = "hidden"; + else + dragImage.style.removeProperty("visibility"); + } + + draggingBreakpoint.dragLastX = x; + draggingBreakpoint.dragLastY = y; + } +} + +function breakpointDragEnd(event) +{ + var sourcesDocument = document.getElementById("sources").contentDocument; + sourcesDocument.removeEventListener("mousemove", breakpointDrag, true); + sourcesDocument.removeEventListener("mouseup", breakpointDragEnd, true); + sourcesDocument.body.style.removeProperty("cursor"); + + var dragImage = sourcesDocument.getElementById("breakpointDrag"); + if (!dragImage) + return; + + dragImage.parentNode.removeChild(dragImage); + + var x = event.clientX + window.scrollX; + if (x > 40 || !draggingBreakpoint) + return; + + var y = event.clientY + window.scrollY; + var rowHeight = draggingBreakpoint.parentNode.offsetHeight; + var row = Math.ceil(y / rowHeight); + if (row <= 0) + row = 1; + + var file = files[currentFile]; + var table = file.element.firstChild; + if (row > table.childNodes.length) + return; + + var tr = table.childNodes.item(row - 1); + if (!tr) + return; + + var breakpoint = draggingBreakpoint.breakpoint; + breakpoint.row = tr; + + // leave the editor there if it exists... we'll want to update it to the new values + breakpoint.editor = file.breakpoints[row].editor; + + file.breakpoints[row] = breakpoint; + + if (breakpoint.editor) { + breakpoint.editor.id = row; + updateBreakpointTypeOnLine(row); + setConditionFieldText(breakpoint); + } + + if (!breakpoint.enabled) + tr.addStyleClass("disabled"); + + tr.addStyleClass("breakpoint"); + + draggingBreakpoint = null; +} + +function totalOffsetTop(element, stop) +{ + var currentTop = 0; + while (element.offsetParent) { + currentTop += element.offsetTop + element = element.offsetParent; + if (element == stop) + break; + } + return currentTop; +} + +function switchFile(fileIndex) +{ + var filesSelect = document.getElementById("files"); + + if (fileIndex === undefined) + fileIndex = filesSelect.selectedIndex; + + fileClicked(filesSelect.options[fileIndex].value, false); + loadFile(filesSelect.options[fileIndex].value, true); +} + +function syntaxHighlight(code, file) +{ + var keywords = { 'abstract': 1, 'boolean': 1, 'break': 1, 'byte': 1, 'case': 1, 'catch': 1, 'char': 1, 'class': 1, 'const': 1, 'continue': 1, 'debugger': 1, 'default': 1, 'delete': 1, 'do': 1, 'double': 1, 'else': 1, 'enum': 1, 'export': 1, 'extends': 1, 'false': 1, 'final': 1, 'finally': 1, 'float': 1, 'for': 1, 'function': 1, 'goto': 1, 'if': 1, 'implements': 1, 'import': 1, 'in': 1, 'instanceof': 1, 'int': 1, 'interface': 1, 'long': 1, 'native': 1, 'new': 1, 'null': 1, 'package': 1, 'private': 1, 'protected': 1, 'public': 1, 'return': 1, 'short': 1, 'static': 1, 'super': 1, 'switch': 1, 'synchronized': 1, 'this': 1, 'throw': 1, 'throws': 1, 'transient': 1, 'true': 1, 'try': 1, 'typeof': 1, 'var': 1, 'void': 1, 'volatile': 1, 'while': 1, 'with': 1 }; + + function echoChar(c) { + if (c == '<') + result += '<'; + else if (c == '>') + result += '>'; + else if (c == '&') + result += '&'; + else if (c == '\t') + result += ' '; + else + result += c; + } + + function isDigit(number) { + var string = "1234567890"; + if (string.indexOf(number) != -1) + return true; + return false; + } + + function isHex(hex) { + var string = "1234567890abcdefABCDEF"; + if (string.indexOf(hex) != -1) + return true; + return false; + } + + function isLetter(letter) { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (string.indexOf(letter) != -1) + return true; + return false; + } + + var result = ""; + var cPrev = ""; + var c = ""; + var cNext = ""; + for (var i = 0; i < code.length; i++) { + cPrev = c; + c = code.charAt(i); + cNext = code.charAt(i + 1); + + if (c == "/" && cNext == "*") { + result += "<span class=\"comment\">"; + echoChar(c); + echoChar(cNext); + for (i += 2; i < code.length; i++) { + c = code.charAt(i); + if (c == "\n") + result += "</span>"; + echoChar(c); + if (c == "\n") + result += "<span class=\"comment\">"; + if (cPrev == "*" && c == "/") + break; + cPrev = c; + } + result += "</span>"; + continue; + } else if (c == "/" && cNext == "/") { + result += "<span class=\"comment\">"; + echoChar(c); + echoChar(cNext); + for (i += 2; i < code.length; i++) { + c = code.charAt(i); + if (c == "\n") + break; + echoChar(c); + } + result += "</span>"; + echoChar(c); + continue; + } else if (c == "\"" || c == "'") { + var instringtype = c; + var stringstart = i; + result += "<span class=\"string\">"; + echoChar(c); + for (i += 1; i < code.length; i++) { + c = code.charAt(i); + if (stringstart < (i - 1) && cPrev == instringtype && code.charAt(i - 2) != "\\") + break; + echoChar(c); + cPrev = c; + } + result += "</span>"; + echoChar(c); + continue; + } else if (c == "0" && cNext == "x" && (i == 0 || (!isLetter(cPrev) && !isDigit(cPrev)))) { + result += "<span class=\"number\">"; + echoChar(c); + echoChar(cNext); + for (i += 2; i < code.length; i++) { + c = code.charAt(i); + if (!isHex(c)) + break; + echoChar(c); + } + result += "</span>"; + echoChar(c); + continue; + } else if ((isDigit(c) || ((c == "-" || c == ".") && isDigit(cNext))) && (i == 0 || (!isLetter(cPrev) && !isDigit(cPrev)))) { + result += "<span class=\"number\">"; + echoChar(c); + for (i += 1; i < code.length; i++) { + c = code.charAt(i); + if (!isDigit(c) && c != ".") + break; + echoChar(c); + } + result += "</span>"; + echoChar(c); + continue; + } else if (isLetter(c) && (i == 0 || !isLetter(cPrev))) { + var keyword = c; + var cj = ""; + for (var j = i + 1; j < i + 12 && j < code.length; j++) { + cj = code.charAt(j); + if (!isLetter(cj)) + break; + keyword += cj; + } + + if (keywords[keyword]) { + var functionName = ""; + var functionIsAnonymous = false; + if (keyword == "function") { + var functionKeywordOffset = 8; + for (var j = i + functionKeywordOffset; j < code.length; j++) { + cj = code.charAt(j); + if (cj == " ") + continue; + if (cj == "(") + break; + functionName += cj; + } + + if (!functionName.length) { + functionIsAnonymous = true; + var functionAssignmentFound = false; + var functionNameStart = -1; + var functionNameEnd = -1; + + for (var j = i - 1; j >= 0; j--) { + cj = code.charAt(j); + if (cj == ":" || cj == "=") { + functionAssignmentFound = true; + continue; + } + + var curCharIsSpace = (cj == " " || cj == "\t" || cj == "\n"); + if (functionAssignmentFound && functionNameEnd == -1 && !curCharIsSpace) { + functionNameEnd = j + 1; + } else if (!functionAssignmentFound && !curCharIsSpace) { + break; + } else if (functionNameEnd != -1 && curCharIsSpace) { + functionNameStart = j; + break; + } + } + + if (functionNameStart != -1 && functionNameEnd != -1) + functionName = code.substring(functionNameStart, functionNameEnd); + } + + if (!functionName.length) + functionName = "function"; + + file.functionNames.push(functionName); + } + + var fileIndex = filesLookup[file.url]; + + if (keyword == "function" && functionIsAnonymous) + result += "<span class=\"keyword\"><a name=\"function-" + fileIndex + "-" + file.functionNames.length + "\" id=\"" + fileIndex + "-" + file.functionNames.length + "\">" + keyword + "</a></span>"; + else + result += "<span class=\"keyword\">" + keyword + "</span>"; + + if (functionName.length && !functionIsAnonymous) { + result += " <a name=\"function-" + fileIndex + "-" + file.functionNames.length + "\" id=\"" + fileIndex + "-" + file.functionNames.length + "\">" + functionName + "</a>"; + i += keyword.length + functionName.length; + } else + i += keyword.length - 1; + + continue; + } + } + + echoChar(c); + } + + return result; +} + +function navFilePrevious(element) +{ + if (element.disabled) + return; + var lastFile = previousFiles.pop(); + if (currentFile != -1) + nextFiles.unshift(currentFile); + loadFile(lastFile, false); +} + +function navFileNext(element) +{ + if (element.disabled) + return; + var lastFile = nextFiles.shift(); + if (currentFile != -1) + previousFiles.push(currentFile); + loadFile(lastFile, false); +} + +function updateFunctionStack() +{ + var stackframeTable = document.getElementById("stackframeTable"); + stackframeTable.innerHTML = ""; // clear the content + + currentStack = new Array(); + var stack = DebuggerDocument.currentFunctionStack(); + for(var i = 0; i < stack.length; i++) { + var tr = document.createElement("tr"); + var td = document.createElement("td"); + td.className = "stackNumber"; + td.innerText = i; + tr.appendChild(td); + + td = document.createElement("td"); + td.innerText = stack[i]; + tr.appendChild(td); + tr.addEventListener("click", selectStackFrame, true); + + stackframeTable.appendChild(tr); + + var frame = new ScriptCallFrame(stack[i], i, tr); + tr.callFrame = frame; + currentStack.push(frame); + + if (i == 0) { + tr.addStyleClass("current"); + frame.loadVariables(); + currentCallFrame = frame; + } + } +} + +function selectStackFrame(event) +{ + var stackframeTable = document.getElementById("stackframeTable"); + var rows = stackframeTable.childNodes; + for (var i = 0; i < rows.length; i++) + rows[i].removeStyleClass("current"); + this.addStyleClass("current"); + this.callFrame.loadVariables(); + currentCallFrame = this.callFrame; + + if (frameLineNumberInfo = frameLineNumberStack[this.callFrame.index - 1]) + jumpToLine(frameLineNumberInfo[0], frameLineNumberInfo[1]); + else if (this.callFrame.index == 0) + jumpToLine(lastStatement[0], lastStatement[1]); +} + +function selectVariable(event) +{ + var variablesTable = document.getElementById("variablesTable"); + var rows = variablesTable.childNodes; + for (var i = 0; i < rows.length; i++) + rows[i].removeStyleClass("current"); + this.addStyleClass("current"); +} + +function switchFunction(index, shouldResetPopup) +{ + if (shouldResetPopup === undefined) shouldResetPopup = false; + var sourcesFrame = window.frames['sourcesFrame']; + + if (shouldResetPopup || index == 0) { + document.getElementById("functionPopupButtonContent").innerHTML = '<span class="placeholder"><No selected symbol></span>'; + return; + } + + var functionSelect = document.getElementById("functions"); + var selectedFunction = functionSelect.childNodes[index]; + var selection = sourcesFrame.getSelection(); + var currentFunction = selectedFunction.value; + var currentFunctionElement = sourcesFrame.document.getElementById(currentFunction); + + functionSelect.blur(); + sourcesFrame.focus(); + selection.setBaseAndExtent(currentFunctionElement, 0, currentFunctionElement, 1); + sourcesFrame.location.hash = "#function-" + selectedFunction.value; + document.getElementById("functionPopupButtonContent").innerText = selectedFunction.innerText; +} + +function loadFile(fileIndex, manageNavLists) +{ + var file = files[fileIndex]; + if (!file) + return; + + if (currentFile != -1 && files[currentFile] && files[currentFile].element) + files[currentFile].element.style.display = "none"; + + if (!file.loaded) { + var sourcesDocument = document.getElementById("sources").contentDocument; + var sourcesDiv = sourcesDocument.body; + var sourceDiv = sourcesDocument.createElement("div"); + sourceDiv.id = "file" + fileIndex; + sourcesDiv.appendChild(sourceDiv); + file.element = sourceDiv; + + var table = sourcesDocument.createElement("table"); + sourceDiv.appendChild(table); + + var normalizedSource = file.source.replace(/\r\n|\r/g, "\n"); // normalize line endings + var lines = syntaxHighlight(normalizedSource, file).split("\n"); + for( var i = 0; i < lines.length; i++ ) { + var tr = sourcesDocument.createElement("tr"); + var td = sourcesDocument.createElement("td"); + td.className = "gutter"; + td.title = (i + 1); + td.addEventListener("click", breakpointAction, true); + td.addEventListener("dblclick", function(event) { toggleBreakpointEditorOnLine(event.target.title); }, true); + td.addEventListener("mousedown", moveBreakPoint, true); + tr.appendChild(td); + + td = sourcesDocument.createElement("td"); + td.className = "source"; + td.innerHTML = (lines[i].length ? lines[i] : " "); + tr.appendChild(td); + table.appendChild(tr); + } + + file.loaded = true; + } + + file.element.style.removeProperty("display"); + + document.getElementById("filesPopupButtonContent").innerText = (file.url ? file.url : "(unknown script)"); + + var filesSelect = document.getElementById("files"); + for (var i = 0; i < filesSelect.childNodes.length; i++) { + if (filesSelect.childNodes[i].value == fileIndex) { + filesSelect.selectedIndex = i; + break; + } + } + + // Populate the function names pop-up + if (file.functionNames.length > 0) { + var functionSelect = document.getElementById("functions"); + var functionOption = document.createElement("option"); + + document.getElementById("functionNamesPopup").style.display = "inline"; + switchFunction(0, true); + + functionSelect.removeChildren(); + functionOption.value = null; + functionOption.text = "<No selected symbol>"; + functionSelect.appendChild(functionOption); + + for (var i = 0; i < file.functionNames.length; i++) { + functionOption = document.createElement("option"); + functionOption.value = fileIndex + "-" + (i+1); + functionOption.text = file.functionNames[i] + "()"; + functionSelect.appendChild(functionOption); + } + } else + document.getElementById("functionNamesPopup").style.display = "none"; + + if (manageNavLists) { + nextFiles = new Array(); + if (currentFile != -1) + previousFiles.push(currentFile); + } + + document.getElementById("navFileLeftButton").disabled = (previousFiles.length == 0); + document.getElementById("navFileRightButton").disabled = (nextFiles.length == 0); + + //Remember and recall scroll position for current file and file we just loaded + var frameBody = document.getElementById("sources").contentDocument.body; + if (currentFile != -1) + files[currentFile].scrollPosition = frameBody.scrollTop; + frameBody.scrollTop = file.scrollPosition; + frameBody.scrollLeft = 0; + + currentFile = fileIndex; +} + +function updateFileSource(source, url, force) +{ + var fileIndex = filesLookup[url]; + if (!fileIndex || !source.length) + return; + + var file = files[fileIndex]; + if (force || file.source.length != source.length || file.source != source) { + file.source = source; + file.loaded = false; + + if (file.element) { + file.element.parentNode.removeChild(file.element); + file.element = null; + } + + if (currentFile == fileIndex || force) + loadFile(fileIndex, false); + } +} + +/** +* ParsedURL - this object chops up full URL into two parts: + * 1) The domain: everything from http:// to the end of the domain name + * 2) The relative path: everything after the domain + * + * @param string url URL to be processed + */ +function ParsedURL(url) +{ + // Since we're getting the URL from the browser, we're safe to assume the URL is already well formatted + // and so there is no need for more sophisticated regular expression here + var url_parts = ((url.substring(0,4)).toLowerCase() == "file") ? url.match(/(file:[\/]{2,3}(\w|\.|-|_|\/|\%|\:)+)\/(.*)/) : url.match(/(http[s]?:\/\/(www)?\.?(\w|\.|-)+\w(:\d{1,5})?)\/?(.*)/); + // the domain here is considered the whole http://www.example.org:8000 or file:///Users/user/folder/file.htm string for display purposes + this.domain = url_parts[1]; + // the relative path is everything following the domain + this.relativePath = (url_parts[5] === undefined) ? "/" + url_parts[3] : "/" + url_parts[5]; +} + +/** +* SiteBrowser - modifies the file tree via DOM as new files are being open + * + */ +function SiteBrowser() +{ + var fileBrowser = document.getElementById("filesBrowserSites"); + + this.addURL = function add(url, fileIndex) + { + var parsedURL = new ParsedURL(url); + var divs = fileBrowser.getElementsByTagName("div"); + + if (divs.length == 0) { + addNewDomain(parsedURL, fileIndex); + } else { + var isNew = true; + for (var i = 0; i < divs.length; i++) { + if (divs[i].id == parsedURL.domain) { + var uls = divs[i].getElementsByTagName("ul"); + var ul = (uls.length > 0) ? uls[0] : document.createElement("ul"); + var li = document.createElement("li"); + + li.id = fileIndex; + li.addEventListener("click", fileBrowserMouseEvents, false); + li.title = li.innerText = parsedURL.relativePath ? parsedURL.relativePath : "/"; + ul.appendChild(li); + isNew = false; + break; + } + } + if (isNew) { + addNewDomain(parsedURL, fileIndex); + } + } + } + + this.selectInitialFile = function sf() + { + if (currentFile == -1) + document.getElementById("1").className = "active"; + } + + function addNewDomain(parsedURL, fileIndex) + { + var div = document.createElement("div"); + var ul = document.createElement("ul"); + var li = document.createElement("li"); + + div.id = div.innerText = div.title = parsedURL.domain; + div.addEventListener("click", fileBrowserMouseEvents, false); + // Maybe we can add some roll-overs here... + //div.addEventListener("mouseover", fileBrowserMouseEvents, false); + //div.addEventListener("mouseout", fileBrowserMouseEvents, false); + li.id = fileIndex; + li.addEventListener("click", fileBrowserMouseEvents, false); + li.title = li.innerText = parsedURL.relativePath ? parsedURL.relativePath : "/"; + ul.appendChild(li); + div.appendChild(ul); + fileBrowser.appendChild(div); + } + + function removeFile(fileIndex) + { + var theFile = document.getElementById(fileIndex); + // If we are removing the last file from its site, go ahead and remove the whole site + if (theFile.parentNode.childNodes.length < 2) { + var theSite = theFile.parentNode.parentNode; + theSite.removeChildren(); + theSite.parentNode.removeChild(theSite); + } + else + theFile.parentNode.removeChild(theFile); + } +} + +function fileBrowserMouseEvents(event) +{ + switch (event.type) + { + case "click": + // If we clicked on a site, collapse/expand it, if on a file, display it. Since we're only capturing this + // event from either a DIV or LI element, we don't have to worry about any ambiguity + (event.target.nodeName.toUpperCase() == "DIV") ? toggleCollapseSite(event) : fileClicked(event.target.id); + break; + } +} + +function fileClicked(fileId, shouldLoadFile) +{ + if (shouldLoadFile === undefined) + shouldLoadFile = true; + if (currentFile != -1) + document.getElementById(currentFile).className = "passive"; + document.getElementById(fileId).className = "active"; + if (shouldLoadFile) + loadFile(fileId, false); +} + +function toggleCollapseSite(event) +{ + var thisSite = document.getElementById(event.target.id); + var siteFiles = thisSite.getElementsByTagName("ul"); + + if (siteFiles[0].style.display == "block" || !siteFiles[0].style.display) { + siteFiles[0].style.display = "none"; + thisSite.className = "collapsed"; + } else { + siteFiles[0].style.display = "block"; + thisSite.className = "expanded"; + } +} + +function didParseScript(source, fileSource, url, sourceId, baseLineNumber) +{ + var fileIndex = filesLookup[url]; + var file = files[fileIndex]; + var firstLoad = false; + + if (!fileIndex || !file) { + fileIndex = files.length + 1; + if (url.length) + filesLookup[url] = fileIndex; + + file = new Object(); + file.scripts = new Array(); + file.breakpoints = new Array(); + file.functionNames = new Array(); + file.source = (fileSource.length ? fileSource : source); + file.url = (url.length ? url : null); + file.loaded = false; + + files[fileIndex] = file; + + var filesSelect = document.getElementById("files"); + var option = document.createElement("option"); + files[fileIndex].menuOption = option; + option.value = fileIndex; + option.text = (file.url ? file.url : "(unknown script)"); + filesSelect.appendChild(option); + + var siteBrowser = new SiteBrowser(); + siteBrowser.addURL(file.url, fileIndex); + siteBrowser.selectInitialFile(); + + firstLoad = true; + } + + var sourceObj = new Object(); + sourceObj.file = fileIndex; + sourceObj.baseLineNumber = baseLineNumber; + file.scripts.push(sourceId); + scripts[sourceId] = sourceObj; + + if (!firstLoad) + updateFileSource((fileSource.length ? fileSource : source), url, false); + + if (currentFile == -1) + loadFile(fileIndex, false); +} + +function jumpToLine(sourceId, line) +{ + var script = scripts[sourceId]; + if (line <= 0 || !script) + return; + + var file = files[script.file]; + if (!file) + return; + + if (currentFile != script.file) + loadFile(script.file, true); + if (currentRow) + currentRow.removeStyleClass("current"); + if (!file.element) + return; + if (line > file.element.firstChild.childNodes.length) + return; + + currentRow = file.element.firstChild.childNodes.item(line - 1); + if (!currentRow) + return; + + currentRow.addStyleClass("current"); + + var sourcesDiv = document.getElementById("sources"); + var sourcesDocument = document.getElementById("sources").contentDocument; + var parent = sourcesDocument.body; + var offset = totalOffsetTop(currentRow, parent); + if (offset < (parent.scrollTop + 20) || offset > (parent.scrollTop + sourcesDiv.clientHeight - 20)) + parent.scrollTop = totalOffsetTop(currentRow, parent) - (sourcesDiv.clientHeight / 2) + 10; +} + +function willExecuteStatement(sourceId, line, fromLeavingFrame) +{ + var script = scripts[sourceId]; + if (line <= 0 || !script) + return; + + var file = files[script.file]; + if (!file) + return; + + lastStatement = [sourceId, line]; + + var breakpoint = file.breakpoints[line]; + + var shouldBreak = false; + + if (breakpoint && breakpoint.enabled) { + switch(breakpoint.type) { + case 0: + shouldBreak = (breakpoint.value == "break" || DebuggerDocument.evaluateScript(breakpoint.value, 0) == 1); + if (shouldBreak) + breakpoint.hitcount++; + break; + case 1: + var message = "Hit breakpoint on line " + line; + if (breakpoint.value != "break") + message = DebuggerDocument.evaluateScript(breakpoint.value, 0); + if (consoleWindow) + consoleWindow.appendMessage("", message); + breakpoint.hitcount++; + break; + } + var editor = breakpoint.editor; + var counter = null; + if (editor) + counter = breakpoint.editor.query('.//span[@class="hitCounter"]'); + if (counter) + counter.innerText = breakpoint.hitcount; + } + + if (pauseOnNextStatement || shouldBreak || (steppingOver && !steppingStack)) { + pause(); + pauseOnNextStatement = false; + pausedWhileLeavingFrame = fromLeavingFrame || false; + } + + if (isPaused) { + updateFunctionStack(); + jumpToLine(sourceId, line); + } +} + +function didEnterCallFrame(sourceId, line) +{ + if (steppingOver || steppingOut) + steppingStack++; + + if (lastStatement) + frameLineNumberStack.unshift(lastStatement); + willExecuteStatement(sourceId, line); +} + +function willLeaveCallFrame(sourceId, line) +{ + if (line <= 0) + resume(); + willExecuteStatement(sourceId, line, true); + frameLineNumberStack.shift(); + if (!steppingStack) + steppingOver = false; + if (steppingOut && !steppingStack) { + steppingOut = false; + pauseOnNextStatement = true; + } + if ((steppingOver || steppingOut) && steppingStack >= 1) + steppingStack--; +} + +function exceptionWasRaised(sourceId, line) +{ + pause(); + updateFunctionStack(); + jumpToLine(sourceId, line); +} + +function showConsoleWindow() +{ + if (!consoleWindow) + consoleWindow = window.open("console.html", "console", "top=200, left=200, width=500, height=300, toolbar=yes, resizable=yes"); + else + consoleWindow.focus(); +} + +function closeFile(fileIndex) +{ + if (fileIndex != -1) { + currentFile = -1; + var file = files[fileIndex]; + var sourcesDocument = document.getElementById("sources").contentDocument; + // Clean up our file's content + sourcesDocument.getElementById("file" + fileIndex).removeChildren(); + // Remove the file from the open files pool + delete sourcesDocument.getElementById("file" + fileIndex); + + var filesSelect = document.getElementById("files"); + // Select the next loaded file. If we're at the end of the list, loop back to beginning. + var nextSelectedFile = (filesSelect.selectedIndex + 1 >= filesSelect.options.length) ? 0 : filesSelect.selectedIndex; + // Remove the file from file lists + filesSelect.options[filesSelect.selectedIndex] = null; + SiteBrowser.removeFile(fileIndex); + delete files[fileIndex]; + + // Clean up the function list + document.getElementById("functions").removeChildren(); + + // Display appropriate place-holders, if we closed all files + if (filesSelect.options.length < 1) { + document.getElementById("filesPopupButtonContent").innerHTML = "<span class='placeholder'><No files loaded></span>"; + document.getElementById("functionNamesPopup").style.display = "none"; + } + else + switchFile(nextSelectedFile); + } +} + +function closeCurrentFile() +{ + closeFile(currentFile); +} diff --git a/WebKitTools/Drosera/mac/DebuggerApplication.h b/WebKitTools/Drosera/mac/DebuggerApplication.h new file mode 100644 index 0000000..4722437 --- /dev/null +++ b/WebKitTools/Drosera/mac/DebuggerApplication.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +@interface DebuggerApplication : NSObject { + NSMutableDictionary *knownServerNames; + IBOutlet NSPanel *attachWindow; + IBOutlet NSTableView *attachTable; + IBOutlet NSButton *attachButton; +} +- (IBAction)showAttachPanel:(id)sender; +- (IBAction)attach:(id)sender; + +- (NSDictionary *)knownServers; +@end diff --git a/WebKitTools/Drosera/mac/DebuggerApplication.mm b/WebKitTools/Drosera/mac/DebuggerApplication.mm new file mode 100644 index 0000000..35cfa24 --- /dev/null +++ b/WebKitTools/Drosera/mac/DebuggerApplication.mm @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2006, 2007 Apple Computer, Inc. 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 "config.h" +#import "DebuggerApplication.h" + +#import "DebuggerClient.h" +#import "ServerConnection.h" + +#import <WebKit/WebCoreStatistics.h> + +@implementation DebuggerApplication +- (void)awakeFromNib +{ + NSTableColumn *column = [attachTable tableColumnWithIdentifier:@"name"]; + NSBrowserCell *cell = [[NSBrowserCell alloc] init]; + [cell setLeaf:YES]; + [column setDataCell:cell]; + [cell release]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + [WebCoreStatistics setShouldPrintExceptions:YES]; + + knownServerNames = [[NSMutableDictionary alloc] init]; + + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(serverLoaded:) name:WebScriptDebugServerDidLoadNotification object:nil]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(serverLoaded:) name:WebScriptDebugServerQueryReplyNotification object:nil]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(serverUnloaded:) name:WebScriptDebugServerWillUnloadNotification object:nil]; + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:WebScriptDebugServerQueryNotification object:nil]; + + [self showAttachPanel:nil]; +} + +#pragma mark - +#pragma mark Server Detection Callbacks + +- (void)serverLoaded:(NSNotification *)notification +{ + int processId = [[[notification userInfo] objectForKey:WebScriptDebugServerProcessIdentifierKey] intValue]; + if (processId == [[NSProcessInfo processInfo] processIdentifier]) + return; + + NSMutableDictionary *info = [[notification userInfo] mutableCopy]; + if (!info) + return; + [knownServerNames setObject:info forKey:[notification object]]; + [info release]; + + [attachTable reloadData]; +} + +- (void)serverUnloaded:(NSNotification *)notification +{ + [knownServerNames removeObjectForKey:[notification object]]; + [attachTable reloadData]; +} + +- (NSDictionary *)knownServers +{ + return knownServerNames; +} + +#pragma mark - +#pragma mark Attach Panel Actions + +- (IBAction)showAttachPanel:(id)sender +{ + if (![attachWindow isVisible]) + [attachWindow center]; + [attachTable reloadData]; + [attachTable setTarget:self]; + [attachTable setDoubleAction:@selector(attach:)]; + [attachWindow makeKeyAndOrderFront:sender]; +} + +- (IBAction)attach:(id)sender +{ + if ([[attachTable selectedRowIndexes] count] != 1) + return; + + [attachWindow orderOut:sender]; + + unsigned int row = [[attachTable selectedRowIndexes] firstIndex]; + NSString *key = [[knownServerNames allKeys] objectAtIndex:row]; + + DebuggerClient *document = [[DebuggerClient alloc] initWithServerName:key]; + [document showWindow:sender]; +} + +#pragma mark - +#pragma mark Table View Delegate + +- (int)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [knownServerNames count]; +} + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + return @""; +} + +- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + NSString *key = [[knownServerNames allKeys] objectAtIndex:row]; + NSMutableDictionary *info = [knownServerNames objectForKey:key]; + NSString *processName = [info objectForKey:WebScriptDebugServerProcessNameKey]; + NSImage *icon = [info objectForKey:@"icon"]; + + if (!icon) { + NSString *path = [[NSWorkspace sharedWorkspace] fullPathForApplication:processName]; + if (path) icon = [[NSWorkspace sharedWorkspace] iconForFile:path]; + if (!icon) icon = [[NSWorkspace sharedWorkspace] iconForFileType:@"app"]; + if (icon) [info setObject:icon forKey:@"icon"]; + [icon setScalesWhenResized:YES]; + [icon setSize:NSMakeSize(32, 32)]; + } + + [cell setImage:icon]; + [cell setTitle:processName]; +} + +- (void)tableViewSelectionDidChange:(NSNotification *)notification +{ + [attachButton setEnabled:([[attachTable selectedRowIndexes] count])]; +} +@end diff --git a/WebKitTools/Drosera/mac/DebuggerClient.h b/WebKitTools/Drosera/mac/DebuggerClient.h new file mode 100644 index 0000000..808d331 --- /dev/null +++ b/WebKitTools/Drosera/mac/DebuggerClient.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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. + */ + +class DebuggerDocument; + +@class ServerConnection; +@class WebView; + +@interface DebuggerClient : NSWindowController +{ + IBOutlet WebView *webView; + BOOL webViewLoaded; + DebuggerDocument* debuggerDocument; + ServerConnection *server; +} + +- (id)initWithServerName:(NSString *)serverConn; +- (IBAction)pause:(id)sender; +- (IBAction)resume:(id)sender; +- (IBAction)stepInto:(id)sender; +- (IBAction)stepOver:(id)sender; +- (IBAction)stepOut:(id)sender; +- (IBAction)showConsole:(id)sender; +- (IBAction)closeCurrentFile:(id)sender; + +@end diff --git a/WebKitTools/Drosera/mac/DebuggerClient.mm b/WebKitTools/Drosera/mac/DebuggerClient.mm new file mode 100644 index 0000000..71cfa8b --- /dev/null +++ b/WebKitTools/Drosera/mac/DebuggerClient.mm @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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 "config.h" +#import "DebuggerClient.h" + +#import "DebuggerApplication.h" +#import "DebuggerDocument.h" +#import "ServerConnection.h" + +#import <JavaScriptCore/JSContextRef.h> + +static NSString *DebuggerConsoleToolbarItem = @"DebuggerConsoleToolbarItem"; +static NSString *DebuggerContinueToolbarItem = @"DebuggerContinueToolbarItem"; +static NSString *DebuggerPauseToolbarItem = @"DebuggerPauseToolbarItem"; +static NSString *DebuggerStepIntoToolbarItem = @"DebuggerStepIntoToolbarItem"; +static NSString *DebuggerStepOverToolbarItem = @"DebuggerStepOverToolbarItem"; +static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem"; + +@implementation DebuggerClient ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + return NO; +} + ++ (BOOL)isKeyExcludedFromWebScript:(const char *)name +{ + return NO; +} + +#pragma mark - + +- (id)initWithServerName:(NSString *)serverName; +{ + if ((self = [super init])) { + server = [[ServerConnection alloc] initWithServerName:serverName]; + debuggerDocument = new DebuggerDocument(server); + } + + return self; +} + +- (void)dealloc +{ + delete debuggerDocument; + [server release]; + [super dealloc]; +} + +#pragma mark - +#pragma mark Interface Actions + +- (IBAction)pause:(id)sender +{ + DebuggerDocument::callGlobalFunction([[webView mainFrame] globalContext], "pause", 0, 0); +} + +- (IBAction)resume:(id)sender +{ + DebuggerDocument::callGlobalFunction([[webView mainFrame] globalContext], "resume", 0, 0); +} + +- (IBAction)stepInto:(id)sender +{ + DebuggerDocument::callGlobalFunction([[webView mainFrame] globalContext], "stepInto", 0, 0); +} + +- (IBAction)stepOver:(id)sender +{ + DebuggerDocument::callGlobalFunction([[webView mainFrame] globalContext], "stepOver", 0, 0); +} + +- (IBAction)stepOut:(id)sender +{ + DebuggerDocument::callGlobalFunction([[webView mainFrame] globalContext], "stepOut", 0, 0); +} + +- (IBAction)showConsole:(id)sender +{ + DebuggerDocument::callGlobalFunction([[webView mainFrame] globalContext], "showConsoleWindow", 0, 0); +} + +- (IBAction)closeCurrentFile:(id)sender +{ + DebuggerDocument::callGlobalFunction([[webView mainFrame] globalContext], "closeCurrentFile", 0, 0); +} + +#pragma mark - +#pragma mark Window Controller Overrides + +- (NSString *)windowNibName +{ + return @"Debugger"; +} + +- (void)windowDidLoad +{ + [super windowDidLoad]; + + NSString *path = [[NSBundle mainBundle] pathForResource:@"debugger" ofType:@"html" inDirectory:nil]; + [[webView mainFrame] loadRequest:[[[NSURLRequest alloc] initWithURL:[NSURL fileURLWithPath:path]] autorelease]]; + + NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"debugger"]; + [toolbar setDelegate:self]; + [toolbar setAllowsUserCustomization:YES]; + [toolbar setAutosavesConfiguration:YES]; + [[self window] setToolbar:toolbar]; + [toolbar release]; +} + +- (void)windowWillClose:(NSNotification *)notification +{ + [[webView windowScriptObject] removeWebScriptKey:@"DebuggerDocument"]; + + [server switchToServerNamed:nil]; + + [self autorelease]; // DebuggerApplication expects us to release on close +} + +#pragma mark - +#pragma mark Toolbar Delegate + +- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag +{ + if ([itemIdentifier isEqualToString:DebuggerContinueToolbarItem]) { + NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; + + [item setLabel:@"Continue"]; + [item setPaletteLabel:@"Continue"]; + + [item setToolTip:@"Continue script execution"]; + [item setImage:[NSImage imageNamed:@"continue"]]; + + [item setTarget:self]; + [item setAction:@selector(resume:)]; + + return [item autorelease]; + } else if ([itemIdentifier isEqualToString:DebuggerConsoleToolbarItem]) { + NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; + + [item setLabel:@"Console"]; + [item setPaletteLabel:@"Console"]; + + [item setToolTip:@"Console"]; + [item setImage:[NSImage imageNamed:@"console"]]; + + [item setTarget:self]; + [item setAction:@selector(showConsole:)]; + + return [item autorelease]; + } else if ([itemIdentifier isEqualToString:DebuggerPauseToolbarItem]) { + NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; + + [item setLabel:@"Pause"]; + [item setPaletteLabel:@"Pause"]; + + [item setToolTip:@"Pause script execution"]; + [item setImage:[NSImage imageNamed:@"pause"]]; + + [item setTarget:self]; + [item setAction:@selector(pause:)]; + + return [item autorelease]; + } else if ([itemIdentifier isEqualToString:DebuggerStepIntoToolbarItem]) { + NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; + + [item setLabel:@"Step Into"]; + [item setPaletteLabel:@"Step Into"]; + + [item setToolTip:@"Step into function call"]; + [item setImage:[NSImage imageNamed:@"step"]]; + + [item setTarget:self]; + [item setAction:@selector(stepInto:)]; + + return [item autorelease]; + } else if ([itemIdentifier isEqualToString:DebuggerStepOverToolbarItem]) { + NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; + + [item setLabel:@"Step Over"]; + [item setPaletteLabel:@"Step Over"]; + + [item setToolTip:@"Step over function call"]; + [item setImage:[NSImage imageNamed:@"stepOver"]]; + + [item setTarget:self]; + [item setAction:@selector(stepOver:)]; + + return [item autorelease]; + } else if ([itemIdentifier isEqualToString:DebuggerStepOutToolbarItem]) { + NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; + + [item setLabel:@"Step Out"]; + [item setPaletteLabel:@"Step Over"]; + + [item setToolTip:@"Step out of current function"]; + [item setImage:[NSImage imageNamed:@"stepOut"]]; + + [item setTarget:self]; + [item setAction:@selector(stepOut:)]; + + return [item autorelease]; + } + + return nil; +} + +- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar +{ + return [NSArray arrayWithObjects:DebuggerContinueToolbarItem, DebuggerPauseToolbarItem, + NSToolbarSeparatorItemIdentifier, DebuggerStepIntoToolbarItem, DebuggerStepOutToolbarItem, + DebuggerStepOverToolbarItem, NSToolbarFlexibleSpaceItemIdentifier, DebuggerConsoleToolbarItem, nil]; +} + +- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar +{ + return [NSArray arrayWithObjects:DebuggerConsoleToolbarItem, DebuggerContinueToolbarItem, DebuggerPauseToolbarItem, + DebuggerStepIntoToolbarItem, DebuggerStepOutToolbarItem, DebuggerStepOverToolbarItem, NSToolbarCustomizeToolbarItemIdentifier, + NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; +} + +- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)interfaceItem +{ + SEL action = [interfaceItem action]; + if (action == @selector(pause:)) { + if (!webViewLoaded) + return NO; + + return !debuggerDocument->isPaused([[webView mainFrame] globalContext]); + } + if (action == @selector(resume:) || + action == @selector(stepOver:) || + action == @selector(stepOut:) || + action == @selector(stepInto:)) { + if (!webViewLoaded) + return YES; + + return debuggerDocument->isPaused([[webView mainFrame] globalContext]); + } + return YES; +} + +#pragma mark - +#pragma mark WebView UI Delegate + +- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request +{ + WebView *newWebView = [[WebView alloc] initWithFrame:NSZeroRect frameName:nil groupName:nil]; + [newWebView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [newWebView setUIDelegate:self]; + [newWebView setPolicyDelegate:self]; + [newWebView setFrameLoadDelegate:self]; + if (request) + [[newWebView mainFrame] loadRequest:request]; + + NSWindow *window = [[NSWindow alloc] initWithContentRect:NSZeroRect styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask | NSUnifiedTitleAndToolbarWindowMask) backing:NSBackingStoreBuffered defer:NO screen:[[webView window] screen]]; + [window setReleasedWhenClosed:YES]; + [newWebView setFrame:[[window contentView] frame]]; + [[window contentView] addSubview:newWebView]; + [newWebView release]; + + return newWebView; +} + +- (void)webViewShow:(WebView *)sender +{ + [[sender window] makeKeyAndOrderFront:sender]; +} + +- (BOOL)webViewAreToolbarsVisible:(WebView *)sender +{ + return [[[sender window] toolbar] isVisible]; +} + +- (void)webView:(WebView *)sender setToolbarsVisible:(BOOL)visible +{ + [[[sender window] toolbar] setVisible:visible]; +} + +- (void)webView:(WebView *)sender setResizable:(BOOL)resizable +{ + [[sender window] setShowsResizeIndicator:resizable]; + [[[sender window] standardWindowButton:NSWindowZoomButton] setEnabled:resizable]; +} + +- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + NSRange range = [message rangeOfString:@"\t"]; + NSString *title = @"Alert"; + if (range.location != NSNotFound) { + title = [message substringToIndex:range.location]; + message = [message substringFromIndex:(range.location + range.length)]; + } + + NSBeginInformationalAlertSheet(title, nil, nil, nil, [sender window], nil, NULL, NULL, NULL, message); +} + +- (void)scriptConfirmSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(long *)contextInfo +{ + *contextInfo = returnCode; +} + +- (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + NSRange range = [message rangeOfString:@"\t"]; + NSString *title = @"Alert"; + if (range.location != NSNotFound) { + title = [message substringToIndex:range.location]; + message = [message substringFromIndex:(range.location + range.length)]; + } + + long result = NSNotFound; + NSBeginInformationalAlertSheet(title, nil, @"Cancel", nil, [sender window], self, @selector(scriptConfirmSheetDidEnd:returnCode:contextInfo:), NULL, &result, message); + + while (result == NSNotFound) { + NSEvent *nextEvent = [[NSApplication sharedApplication] nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES]; + [[NSApplication sharedApplication] sendEvent:nextEvent]; + } + + return result; +} + +#pragma mark - +#pragma mark WebView Frame Load Delegate + +- (void)webView:(WebView *)sender windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject +{ + // note: this is the Debuggers's own WebView, not the one being debugged + JSContextRef context = [[webView mainFrame] globalContext]; + JSObjectRef globalObject = JSContextGetGlobalObject(context); + + debuggerDocument->windowScriptObjectAvailable(context, globalObject); +} + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + // note: this is the Debuggers's own WebView, not the one being debugged + if ([[sender window] isEqual:[self window]]) { + webViewLoaded = YES; + [server setGlobalContext:[[webView mainFrame] globalContext]]; + } +} + +- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame +{ + // note: this is the Debuggers's own WebViews, not the one being debugged + if ([frame isEqual:[sender mainFrame]]) { + NSDictionary *info = [[(DebuggerApplication *)[[NSApplication sharedApplication] delegate] knownServers] objectForKey:[server currentServerName]]; + NSString *processName = [info objectForKey:WebScriptDebugServerProcessNameKey]; + if (info && [processName length]) { + NSMutableString *newTitle = [[NSMutableString alloc] initWithString:processName]; + [newTitle appendString:@" - "]; + [newTitle appendString:title]; + [[sender window] setTitle:newTitle]; + [newTitle release]; + } else + [[sender window] setTitle:title]; + } +} + +@end diff --git a/WebKitTools/Drosera/mac/DebuggerDocumentPlatform.mm b/WebKitTools/Drosera/mac/DebuggerDocumentPlatform.mm new file mode 100644 index 0000000..b49338c --- /dev/null +++ b/WebKitTools/Drosera/mac/DebuggerDocumentPlatform.mm @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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 "config.h" +#import "DebuggerDocument.h" + +#import "DebuggerClient.h" +#import "ServerConnection.h" + +#import <JavaScriptCore/JSRetainPtr.h> +#import <JavaScriptCore/JSStringRefCF.h> +#import <JavaScriptCore/RetainPtr.h> + +// Converting string types +NSString* NSStringCreateWithJSStringRef(JSStringRef jsString) +{ + CFStringRef cfString = JSStringCopyCFString(kCFAllocatorDefault, jsString); + return (NSString *)cfString; +} + +JSValueRef JSValueRefCreateWithNSString(JSContextRef context, NSString* nsString) +{ + JSRetainPtr<JSStringRef> jsString(Adopt, JSStringCreateWithCFString((CFStringRef)nsString)); + return JSValueMakeString(context, jsString.get()); +} + +@interface NSString (WebScriptStringExtras) ++ (NSString *)stringOrNilFromWebScriptResult:(id)scriptResult; +@end + +@implementation NSString (WebScriptStringExtras) ++ (NSString *)stringOrNilFromWebScriptResult:(id)scriptResult +{ + NSString *ret = nil; + + if ([scriptResult isKindOfClass:NSClassFromString(@"WebScriptObject")]) + ret = [scriptResult callWebScriptMethod:@"toString" withArguments:nil]; + else if (scriptResult && ![scriptResult isKindOfClass:[NSString class]]) + ret = [scriptResult description]; + else if (scriptResult) + ret = scriptResult; + + return ret; +} +@end + +@interface WebScriptObject (WebScriptObjectExtras) ++ (NSArray *)webScriptAttributeKeys:(WebScriptObject *)object; +@end + +@implementation WebScriptObject (WebScriptObjectExtras) ++ (NSArray *)webScriptAttributeKeys:(WebScriptObject *)object; +{ + WebScriptObject *enumerateAttributes = [object evaluateWebScript:@"(function () { var result = new Array(); for (var x in this) { result.push(x); } return result; })"]; + + NSMutableArray *result = [[NSMutableArray alloc] init]; + WebScriptObject *variables = [enumerateAttributes callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObject:object]]; + unsigned length = [[variables valueForKey:@"length"] intValue]; + for (unsigned i = 0; i < length; i++) { + NSString *key = [variables webScriptValueAtIndex:i]; + [result addObject:key]; + } + + [result sortUsingSelector:@selector(compare:)]; + return [result autorelease]; +} +@end + +// DebuggerDocument platform specific implementations + +void DebuggerDocument::platformPause() +{ + [m_server.get() pause]; +} + +void DebuggerDocument::platformResume() +{ + [m_server.get() resume]; +} + +void DebuggerDocument::platformStepInto() +{ + [m_server.get() stepInto]; +} + +JSValueRef DebuggerDocument::platformEvaluateScript(JSContextRef context, JSStringRef script, int callFrame) +{ + WebScriptCallFrame *cframe = [m_server.get() currentFrame]; + for (unsigned count = 0; count < callFrame; count++) + cframe = [cframe caller]; + + if (!cframe) + return JSValueMakeUndefined(context); + + RetainPtr<NSString> scriptNS(AdoptNS, NSStringCreateWithJSStringRef(script)); + id value = [cframe evaluateWebScript:scriptNS.get()]; + NSString *result = [NSString stringOrNilFromWebScriptResult:value]; + if (!result) + return JSValueMakeNull(context); + + return JSValueRefCreateWithNSString(context, result); +} + +void DebuggerDocument::getPlatformCurrentFunctionStack(JSContextRef context, Vector<JSValueRef>& currentStack) +{ + for (WebScriptCallFrame *frame = [m_server.get() currentFrame]; frame;) { + CFStringRef function; + if ([frame functionName]) + function = (CFStringRef)[frame functionName]; + else if ([frame caller]) + function = CFSTR("(anonymous function)"); + else + function = CFSTR("(global scope)"); + frame = [frame caller]; + + currentStack.append(JSValueRefCreateWithNSString(context, (NSString *)function)); + } +} + +void DebuggerDocument::getPlatformLocalScopeVariableNamesForCallFrame(JSContextRef context, int callFrame, Vector<JSValueRef>& variableNames) +{ + WebScriptCallFrame *cframe = [m_server.get() currentFrame]; + for (unsigned count = 0; count < callFrame; count++) + cframe = [cframe caller]; + + if (!cframe) + return; + if (![[cframe scopeChain] count]) + return; + + WebScriptObject *scope = [[cframe scopeChain] objectAtIndex:0]; // local is always first + NSArray *localScopeVariableNames = [WebScriptObject webScriptAttributeKeys:scope]; + + for (int i = 0; i < [localScopeVariableNames count]; ++i) { + variableNames.append(JSValueRefCreateWithNSString(context, [localScopeVariableNames objectAtIndex:i])); + } +} + +JSValueRef DebuggerDocument::platformValueForScopeVariableNamed(JSContextRef context, JSStringRef key, int callFrame) +{ + WebScriptCallFrame *cframe = [m_server.get() currentFrame]; + for (unsigned count = 0; count < callFrame; count++) + cframe = [cframe caller]; + + if (!cframe) + return JSValueMakeUndefined(context); + + unsigned scopeCount = [[cframe scopeChain] count]; + + if (!scopeCount) + return JSValueMakeUndefined(context); + + NSString *resultString = nil; + + for (unsigned i = 0; i < scopeCount && resultString == nil; i++) { + WebScriptObject *scope = [[cframe scopeChain] objectAtIndex:i]; + + id value = nil; + @try { + RetainPtr<NSString> keyNS(AdoptNS, NSStringCreateWithJSStringRef(key)); + value = [scope valueForKey:keyNS.get()]; + } @catch(NSException* localException) { // The value wasn't found. + } + + resultString = [NSString stringOrNilFromWebScriptResult:value]; + } + + if (!resultString) + return JSValueMakeUndefined(context); + + return JSValueRefCreateWithNSString(context, resultString); +} + +void DebuggerDocument::platformLog(JSStringRef msg) +{ + RetainPtr<NSString> msgNS(AdoptNS, NSStringCreateWithJSStringRef(msg)); + NSLog(@"%@", msgNS.get()); +} + diff --git a/WebKitTools/Drosera/mac/Drosera.xcodeproj/project.pbxproj b/WebKitTools/Drosera/mac/Drosera.xcodeproj/project.pbxproj new file mode 100644 index 0000000..3ef8b64 --- /dev/null +++ b/WebKitTools/Drosera/mac/Drosera.xcodeproj/project.pbxproj @@ -0,0 +1,659 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 15CE85540ADBEA620078A734 /* fileIcon.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 15CE854F0ADBEA610078A734 /* fileIcon.jpg */; }; + 15CE85550ADBEA620078A734 /* siteCollapsed.tif in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85500ADBEA610078A734 /* siteCollapsed.tif */; }; + 15CE85560ADBEA620078A734 /* siteExpanded.tif in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85510ADBEA610078A734 /* siteExpanded.tif */; }; + 15CE85570ADBEA620078A734 /* siteIcon.tif in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85520ADBEA610078A734 /* siteIcon.tif */; }; + 15CE85580ADBEA620078A734 /* SourceArrowOpen.png in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85530ADBEA610078A734 /* SourceArrowOpen.png */; }; + 1C2632D30A4AF0A800EA7CD8 /* verticalSplitterBar.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D10A4AF0A800EA7CD8 /* verticalSplitterBar.tiff */; }; + 1C2632D40A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D20A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff */; }; + 1C2632D70A4AF0B800EA7CD8 /* SourceArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D50A4AF0B800EA7CD8 /* SourceArrow.png */; }; + 1C2632D80A4AF0B800EA7CD8 /* SourceArrowBlank.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D60A4AF0B800EA7CD8 /* SourceArrowBlank.png */; }; + 1C2632DA0A4AF0D200EA7CD8 /* background_stripe.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D90A4AF0D200EA7CD8 /* background_stripe.png */; }; + 1C27ABC60A413B720016ECF4 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C27ABC50A413B720016ECF4 /* WebKit.framework */; }; + 1C27AC200A413D2D0016ECF4 /* debugger.html in Resources */ = {isa = PBXBuildFile; fileRef = 1C27AC1F0A413D2D0016ECF4 /* debugger.html */; }; + 1C27B1260A421D870016ECF4 /* debugger.js in Resources */ = {isa = PBXBuildFile; fileRef = 1C27AC230A413D660016ECF4 /* debugger.js */; }; + 1C3487980A81208400101C5C /* Drosera.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1C3487970A81208400101C5C /* Drosera.icns */; }; + 1C4FF7440A44F52C0000D05D /* debugger.css in Resources */ = {isa = PBXBuildFile; fileRef = 1C4FF7430A44F5260000D05D /* debugger.css */; }; + 1C4FF7540A44F6320000D05D /* gutter.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C4FF7530A44F6320000D05D /* gutter.png */; }; + 1C4FF9210A45F3520000D05D /* glossyHeader.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C4FF91F0A45F3520000D05D /* glossyHeader.png */; }; + 1C4FF94E0A45F5060000D05D /* popUpArrows.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C4FF94D0A45F5060000D05D /* popUpArrows.png */; }; + 1C4FFE5E0A466F5D0000D05D /* programCounterBreakPoint.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1C4FFE5C0A466F5D0000D05D /* programCounterBreakPoint.tif */; }; + 1C4FFE5F0A466F5D0000D05D /* programCounterBreakPointDisabled.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1C4FFE5D0A466F5D0000D05D /* programCounterBreakPointDisabled.tif */; }; + 1C6F83FF0A58E97D004FCD89 /* stepOut.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1C6F83FE0A58E97D004FCD89 /* stepOut.tif */; }; + 1C6F84520A58EDFE004FCD89 /* console.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C6F84510A58EDFE004FCD89 /* console.png */; }; + 1C6F84550A58EE06004FCD89 /* console.css in Resources */ = {isa = PBXBuildFile; fileRef = 1C6F84530A58EE06004FCD89 /* console.css */; }; + 1C6F84560A58EE06004FCD89 /* console.html in Resources */ = {isa = PBXBuildFile; fileRef = 1C6F84540A58EE06004FCD89 /* console.html */; }; + 1C6F86730A59A18B004FCD89 /* console.js in Resources */ = {isa = PBXBuildFile; fileRef = 1C6F861F0A599F65004FCD89 /* console.js */; }; + 1C74F0350A47BF8300FEC632 /* viewer.html in Resources */ = {isa = PBXBuildFile; fileRef = 1C74F0340A47BF8300FEC632 /* viewer.html */; }; + 1C74F04B0A47BFE800FEC632 /* viewer.css in Resources */ = {isa = PBXBuildFile; fileRef = 1C74F03A0A47BFD600FEC632 /* viewer.css */; }; + 1C74F1850A47DEE600FEC632 /* DebuggerApplication.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C74F1840A47DEE600FEC632 /* DebuggerApplication.mm */; }; + 1CC058EE0A44A210006FE533 /* breakPoint.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058B80A44A210006FE533 /* breakPoint.tif */; }; + 1CC058EF0A44A210006FE533 /* breakPointDisabled.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058B90A44A210006FE533 /* breakPointDisabled.tif */; }; + 1CC059020A44A210006FE533 /* glossyFooterFill.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058CC0A44A210006FE533 /* glossyFooterFill.tif */; }; + 1CC0590E0A44A210006FE533 /* navLeftDisabled.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058D80A44A210006FE533 /* navLeftDisabled.png */; }; + 1CC0590F0A44A210006FE533 /* navLeftNormal.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058D90A44A210006FE533 /* navLeftNormal.png */; }; + 1CC059100A44A210006FE533 /* navLeftPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058DA0A44A210006FE533 /* navLeftPressed.png */; }; + 1CC059110A44A210006FE533 /* navRightDisabled.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058DB0A44A210006FE533 /* navRightDisabled.png */; }; + 1CC059120A44A210006FE533 /* navRightNormal.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058DC0A44A210006FE533 /* navRightNormal.png */; }; + 1CC059130A44A210006FE533 /* navRightPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058DD0A44A210006FE533 /* navRightPressed.png */; }; + 1CC059160A44A210006FE533 /* programCounter.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058E00A44A210006FE533 /* programCounter.tif */; }; + 1CC059170A44A210006FE533 /* splitterBar.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058E10A44A210006FE533 /* splitterBar.tif */; }; + 1CC059180A44A210006FE533 /* splitterDimple.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058E20A44A210006FE533 /* splitterDimple.tif */; }; + 1CC0591A0A44A210006FE533 /* continue.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058E40A44A210006FE533 /* continue.tif */; }; + 1CC0591D0A44A210006FE533 /* pause.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058E70A44A210006FE533 /* pause.tif */; }; + 1CC0591E0A44A210006FE533 /* run.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058E80A44A210006FE533 /* run.tif */; }; + 1CC0591F0A44A210006FE533 /* step.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058E90A44A210006FE533 /* step.tif */; }; + 1CC059200A44A210006FE533 /* stepOver.tif in Resources */ = {isa = PBXBuildFile; fileRef = 1CC058EA0A44A210006FE533 /* stepOver.tif */; }; + 1CC059700A44A485006FE533 /* toolbarBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CC0596F0A44A485006FE533 /* toolbarBackground.png */; }; + 1CD434B20A4B86F800A007AB /* glossyHeaderPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CD434B10A4B86F800A007AB /* glossyHeaderPressed.png */; }; + 1CD8D5690A49041C00E5677B /* launcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CD8D5680A49041C00E5677B /* launcher.m */; }; + 1CD8D56C0A49043E00E5677B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; }; + 1CD8D5A60A49102900E5677B /* Drosera.app in Resources */ = {isa = PBXBuildFile; fileRef = 8D15AC370486D014006FF6A4 /* Drosera.app */; }; + 5D2C827F0A816BA700C193FD /* Drosera.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1C3487970A81208400101C5C /* Drosera.icns */; }; + 63D54BD70AE600560064C440 /* breakpointeditor.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D54BD60AE600560064C440 /* breakpointeditor.png */; }; + 63D54CBD0AE72C990064C440 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63D54CBC0AE72C990064C440 /* Carbon.framework */; }; + 63D54D7E0AE75CF10064C440 /* close_active.tif in Resources */ = {isa = PBXBuildFile; fileRef = 63D54D7B0AE75CF10064C440 /* close_active.tif */; }; + 63D54D7F0AE75CF10064C440 /* close_hover.tif in Resources */ = {isa = PBXBuildFile; fileRef = 63D54D7C0AE75CF10064C440 /* close_hover.tif */; }; + 63D54D800AE75CF10064C440 /* close.tif in Resources */ = {isa = PBXBuildFile; fileRef = 63D54D7D0AE75CF10064C440 /* close.tif */; }; + 63D54F780AE8280F0064C440 /* breakpointEditor.html in Resources */ = {isa = PBXBuildFile; fileRef = 63D54F770AE8280F0064C440 /* breakpointEditor.html */; }; + 8D15AC2D0486D014006FF6A4 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 2A37F4B6FDCFA73011CA2CEA /* MainMenu.nib */; }; + 8D15AC2E0486D014006FF6A4 /* Debugger.nib in Resources */ = {isa = PBXBuildFile; fileRef = 2A37F4B4FDCFA73011CA2CEA /* Debugger.nib */; }; + 8D15AC320486D014006FF6A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A37F4B0FDCFA73011CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; + 8D15AC340486D014006FF6A4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; }; + 957876850C9A226A008B6383 /* ServerConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 957876840C9A226A008B6383 /* ServerConnection.mm */; }; + 95B2A4500C95EECD00850C41 /* DebuggerClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95B2A44F0C95EECD00850C41 /* DebuggerClient.mm */; }; + 95B955250C975C7500AAB83B /* DebuggerDocumentPlatform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95B955240C975C7500AAB83B /* DebuggerDocumentPlatform.mm */; }; + D23E47C60C4460C600B7CD07 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D23E47C50C4460C600B7CD07 /* JavaScriptCore.framework */; }; + D2D794FD0C4BED83004784F7 /* DebuggerDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D2D794ED0C4BED83004784F7 /* DebuggerDocument.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 1CD8D5A90A49104E00E5677B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2A37F4A9FDCFA73011CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D15AC270486D014006FF6A4; + remoteInfo = Drosera; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; + 13E42FBA07B3F13500E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; + 15CE854F0ADBEA610078A734 /* fileIcon.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = fileIcon.jpg; path = ../Images/fileIcon.jpg; sourceTree = SOURCE_ROOT; }; + 15CE85500ADBEA610078A734 /* siteCollapsed.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = siteCollapsed.tif; path = ../Images/siteCollapsed.tif; sourceTree = SOURCE_ROOT; }; + 15CE85510ADBEA610078A734 /* siteExpanded.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = siteExpanded.tif; path = ../Images/siteExpanded.tif; sourceTree = SOURCE_ROOT; }; + 15CE85520ADBEA610078A734 /* siteIcon.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = siteIcon.tif; path = ../Images/siteIcon.tif; sourceTree = SOURCE_ROOT; }; + 15CE85530ADBEA610078A734 /* SourceArrowOpen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SourceArrowOpen.png; path = ../Images/SourceArrowOpen.png; sourceTree = SOURCE_ROOT; }; + 1C2632D10A4AF0A800EA7CD8 /* verticalSplitterBar.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = verticalSplitterBar.tiff; path = ../Images/verticalSplitterBar.tiff; sourceTree = SOURCE_ROOT; }; + 1C2632D20A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = verticalSplitterDimple.tiff; path = ../Images/verticalSplitterDimple.tiff; sourceTree = SOURCE_ROOT; }; + 1C2632D50A4AF0B800EA7CD8 /* SourceArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SourceArrow.png; path = ../Images/SourceArrow.png; sourceTree = SOURCE_ROOT; }; + 1C2632D60A4AF0B800EA7CD8 /* SourceArrowBlank.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SourceArrowBlank.png; path = ../Images/SourceArrowBlank.png; sourceTree = SOURCE_ROOT; }; + 1C2632D90A4AF0D200EA7CD8 /* background_stripe.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = background_stripe.png; path = ../Images/background_stripe.png; sourceTree = SOURCE_ROOT; }; + 1C27ABC50A413B720016ECF4 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = /System/Library/Frameworks/WebKit.framework; sourceTree = "<absolute>"; }; + 1C27AC1F0A413D2D0016ECF4 /* debugger.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = debugger.html; path = ../debugger.html; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; }; + 1C27AC230A413D660016ECF4 /* debugger.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = debugger.js; path = ../debugger.js; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; }; + 1C3487970A81208400101C5C /* Drosera.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Drosera.icns; path = ../Drosera.icns; sourceTree = SOURCE_ROOT; }; + 1C4FF7430A44F5260000D05D /* debugger.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = debugger.css; path = ../debugger.css; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; }; + 1C4FF7530A44F6320000D05D /* gutter.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = gutter.png; path = ../Images/gutter.png; sourceTree = SOURCE_ROOT; }; + 1C4FF91F0A45F3520000D05D /* glossyHeader.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = glossyHeader.png; path = ../Images/glossyHeader.png; sourceTree = SOURCE_ROOT; }; + 1C4FF94D0A45F5060000D05D /* popUpArrows.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = popUpArrows.png; path = ../Images/popUpArrows.png; sourceTree = SOURCE_ROOT; }; + 1C4FFE5C0A466F5D0000D05D /* programCounterBreakPoint.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = programCounterBreakPoint.tif; path = ../Images/programCounterBreakPoint.tif; sourceTree = SOURCE_ROOT; }; + 1C4FFE5D0A466F5D0000D05D /* programCounterBreakPointDisabled.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = programCounterBreakPointDisabled.tif; path = ../Images/programCounterBreakPointDisabled.tif; sourceTree = SOURCE_ROOT; }; + 1C6F83FE0A58E97D004FCD89 /* stepOut.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = stepOut.tif; path = ../Images/stepOut.tif; sourceTree = SOURCE_ROOT; }; + 1C6F84510A58EDFE004FCD89 /* console.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = console.png; path = ../Images/console.png; sourceTree = SOURCE_ROOT; }; + 1C6F84530A58EE06004FCD89 /* console.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = console.css; path = ../console.css; sourceTree = SOURCE_ROOT; }; + 1C6F84540A58EE06004FCD89 /* console.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = console.html; path = ../console.html; sourceTree = SOURCE_ROOT; }; + 1C6F861F0A599F65004FCD89 /* console.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = console.js; path = ../console.js; sourceTree = SOURCE_ROOT; }; + 1C74F0340A47BF8300FEC632 /* viewer.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = viewer.html; path = ../viewer.html; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; }; + 1C74F03A0A47BFD600FEC632 /* viewer.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = viewer.css; path = ../viewer.css; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; }; + 1C74F1830A47DEE600FEC632 /* DebuggerApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerApplication.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; + 1C74F1840A47DEE600FEC632 /* DebuggerApplication.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DebuggerApplication.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; + 1CC058B80A44A210006FE533 /* breakPoint.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = breakPoint.tif; path = ../Images/breakPoint.tif; sourceTree = SOURCE_ROOT; }; + 1CC058B90A44A210006FE533 /* breakPointDisabled.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = breakPointDisabled.tif; path = ../Images/breakPointDisabled.tif; sourceTree = SOURCE_ROOT; }; + 1CC058CC0A44A210006FE533 /* glossyFooterFill.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = glossyFooterFill.tif; path = ../Images/glossyFooterFill.tif; sourceTree = SOURCE_ROOT; }; + 1CC058D80A44A210006FE533 /* navLeftDisabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = navLeftDisabled.png; path = ../Images/navLeftDisabled.png; sourceTree = SOURCE_ROOT; }; + 1CC058D90A44A210006FE533 /* navLeftNormal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = navLeftNormal.png; path = ../Images/navLeftNormal.png; sourceTree = SOURCE_ROOT; }; + 1CC058DA0A44A210006FE533 /* navLeftPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = navLeftPressed.png; path = ../Images/navLeftPressed.png; sourceTree = SOURCE_ROOT; }; + 1CC058DB0A44A210006FE533 /* navRightDisabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = navRightDisabled.png; path = ../Images/navRightDisabled.png; sourceTree = SOURCE_ROOT; }; + 1CC058DC0A44A210006FE533 /* navRightNormal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = navRightNormal.png; path = ../Images/navRightNormal.png; sourceTree = SOURCE_ROOT; }; + 1CC058DD0A44A210006FE533 /* navRightPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = navRightPressed.png; path = ../Images/navRightPressed.png; sourceTree = SOURCE_ROOT; }; + 1CC058E00A44A210006FE533 /* programCounter.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = programCounter.tif; path = ../Images/programCounter.tif; sourceTree = SOURCE_ROOT; }; + 1CC058E10A44A210006FE533 /* splitterBar.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = splitterBar.tif; path = ../Images/splitterBar.tif; sourceTree = SOURCE_ROOT; }; + 1CC058E20A44A210006FE533 /* splitterDimple.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = splitterDimple.tif; path = ../Images/splitterDimple.tif; sourceTree = SOURCE_ROOT; }; + 1CC058E40A44A210006FE533 /* continue.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = continue.tif; path = ../Images/continue.tif; sourceTree = SOURCE_ROOT; }; + 1CC058E60A44A210006FE533 /* finishFunction.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = finishFunction.tif; sourceTree = "<group>"; }; + 1CC058E70A44A210006FE533 /* pause.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = pause.tif; path = ../Images/pause.tif; sourceTree = SOURCE_ROOT; }; + 1CC058E80A44A210006FE533 /* run.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = run.tif; path = ../Images/run.tif; sourceTree = SOURCE_ROOT; }; + 1CC058E90A44A210006FE533 /* step.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = step.tif; path = ../Images/step.tif; sourceTree = SOURCE_ROOT; }; + 1CC058EA0A44A210006FE533 /* stepOver.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = stepOver.tif; path = ../Images/stepOver.tif; sourceTree = SOURCE_ROOT; }; + 1CC058EB0A44A210006FE533 /* stop.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = stop.tif; sourceTree = "<group>"; }; + 1CC0596F0A44A485006FE533 /* toolbarBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = toolbarBackground.png; path = ../Images/toolbarBackground.png; sourceTree = SOURCE_ROOT; }; + 1CD434B10A4B86F800A007AB /* glossyHeaderPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = glossyHeaderPressed.png; path = ../Images/glossyHeaderPressed.png; sourceTree = SOURCE_ROOT; }; + 1CD8D54D0A4902B000E5677B /* DroseraLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DroseraLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1CD8D54F0A4902B000E5677B /* LauncherInfo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = LauncherInfo.plist; sourceTree = "<group>"; }; + 1CD8D5680A49041C00E5677B /* launcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = launcher.m; sourceTree = "<group>"; }; + 2A37F4B0FDCFA73011CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; + 2A37F4B5FDCFA73011CA2CEA /* Debugger.nib */ = {isa = PBXFileReference; explicitFileType = wrapper.nib; name = Debugger.nib; path = ../English.lproj/Debugger.nib; sourceTree = "<group>"; }; + 2A37F4B7FDCFA73011CA2CEA /* MainMenu.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = MainMenu.nib; path = ../English.lproj/MainMenu.nib; sourceTree = "<group>"; }; + 2A37F4C4FDCFA73011CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; + 2A37F4C5FDCFA73011CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; + 63D54BD60AE600560064C440 /* breakpointeditor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = breakpointeditor.png; path = ../Images/breakpointeditor.png; sourceTree = SOURCE_ROOT; }; + 63D54CBC0AE72C990064C440 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; }; + 63D54D7B0AE75CF10064C440 /* close_active.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = close_active.tif; path = ../Images/close_active.tif; sourceTree = SOURCE_ROOT; }; + 63D54D7C0AE75CF10064C440 /* close_hover.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = close_hover.tif; path = ../Images/close_hover.tif; sourceTree = SOURCE_ROOT; }; + 63D54D7D0AE75CF10064C440 /* close.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = close.tif; path = ../Images/close.tif; sourceTree = SOURCE_ROOT; }; + 63D54F770AE8280F0064C440 /* breakpointEditor.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html; name = breakpointEditor.html; path = ../breakpointEditor.html; sourceTree = SOURCE_ROOT; }; + 8D15AC360486D014006FF6A4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; + 8D15AC370486D014006FF6A4 /* Drosera.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Drosera.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 957876760C9A221B008B6383 /* ServerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerConnection.h; sourceTree = "<group>"; }; + 957876840C9A226A008B6383 /* ServerConnection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ServerConnection.mm; sourceTree = "<group>"; }; + 957879610C9B37BC008B6383 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../config.h; sourceTree = SOURCE_ROOT; }; + 95B2A44E0C95EECD00850C41 /* DebuggerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerClient.h; sourceTree = "<group>"; }; + 95B2A44F0C95EECD00850C41 /* DebuggerClient.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DebuggerClient.mm; sourceTree = "<group>"; }; + 95B955240C975C7500AAB83B /* DebuggerDocumentPlatform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DebuggerDocumentPlatform.mm; sourceTree = "<group>"; }; + 95C906AF0C8E439200F9BE0F /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = ../ForwardingHeaders/wtf/Platform.h; sourceTree = SOURCE_ROOT; }; + D23E47C50C4460C600B7CD07 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = /System/Library/Frameworks/JavaScriptCore.framework; sourceTree = "<absolute>"; }; + D2D794ED0C4BED83004784F7 /* DebuggerDocument.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; name = DebuggerDocument.cpp; path = ../DebuggerDocument.cpp; sourceTree = SOURCE_ROOT; }; + D2D794EE0C4BED83004784F7 /* DebuggerDocument.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 30; name = DebuggerDocument.h; path = ../DebuggerDocument.h; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1CD8D54B0A4902B000E5677B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD8D56C0A49043E00E5677B /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D15AC330486D014006FF6A4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 63D54CBD0AE72C990064C440 /* Carbon.framework in Frameworks */, + 8D15AC340486D014006FF6A4 /* Cocoa.framework in Frameworks */, + D23E47C60C4460C600B7CD07 /* JavaScriptCore.framework in Frameworks */, + 1C27ABC60A413B720016ECF4 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1058C7A6FEA54F5311CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 63D54CBC0AE72C990064C440 /* Carbon.framework */, + 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */, + 1C27ABC50A413B720016ECF4 /* WebKit.framework */, + ); + name = "Linked Frameworks"; + sourceTree = "<group>"; + }; + 1058C7A8FEA54F5311CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 2A37F4C4FDCFA73011CA2CEA /* AppKit.framework */, + 13E42FBA07B3F13500E4EEF1 /* CoreData.framework */, + 2A37F4C5FDCFA73011CA2CEA /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = "<group>"; + }; + 19C28FB0FE9D524F11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D15AC370486D014006FF6A4 /* Drosera.app */, + 1CD8D54D0A4902B000E5677B /* DroseraLauncher.app */, + ); + name = Products; + sourceTree = "<group>"; + }; + 1CC058B70A44A210006FE533 /* Images */ = { + isa = PBXGroup; + children = ( + 63D54D7B0AE75CF10064C440 /* close_active.tif */, + 63D54D7C0AE75CF10064C440 /* close_hover.tif */, + 63D54D7D0AE75CF10064C440 /* close.tif */, + 63D54BD60AE600560064C440 /* breakpointeditor.png */, + 15CE854F0ADBEA610078A734 /* fileIcon.jpg */, + 15CE85500ADBEA610078A734 /* siteCollapsed.tif */, + 15CE85510ADBEA610078A734 /* siteExpanded.tif */, + 15CE85520ADBEA610078A734 /* siteIcon.tif */, + 15CE85530ADBEA610078A734 /* SourceArrowOpen.png */, + 1C6F84510A58EDFE004FCD89 /* console.png */, + 1C4FF7530A44F6320000D05D /* gutter.png */, + 1C4FF91F0A45F3520000D05D /* glossyHeader.png */, + 1CD434B10A4B86F800A007AB /* glossyHeaderPressed.png */, + 1C4FF94D0A45F5060000D05D /* popUpArrows.png */, + 1CC058B80A44A210006FE533 /* breakPoint.tif */, + 1CC058B90A44A210006FE533 /* breakPointDisabled.tif */, + 1CC058E00A44A210006FE533 /* programCounter.tif */, + 1C4FFE5C0A466F5D0000D05D /* programCounterBreakPoint.tif */, + 1C4FFE5D0A466F5D0000D05D /* programCounterBreakPointDisabled.tif */, + 1CC058CC0A44A210006FE533 /* glossyFooterFill.tif */, + 1CC058D80A44A210006FE533 /* navLeftDisabled.png */, + 1CC058D90A44A210006FE533 /* navLeftNormal.png */, + 1CC058DA0A44A210006FE533 /* navLeftPressed.png */, + 1CC058DB0A44A210006FE533 /* navRightDisabled.png */, + 1CC058DC0A44A210006FE533 /* navRightNormal.png */, + 1CC058DD0A44A210006FE533 /* navRightPressed.png */, + 1CC058E10A44A210006FE533 /* splitterBar.tif */, + 1CC058E20A44A210006FE533 /* splitterDimple.tif */, + 1CC058E60A44A210006FE533 /* finishFunction.tif */, + 1CC058E40A44A210006FE533 /* continue.tif */, + 1CC058E70A44A210006FE533 /* pause.tif */, + 1CC058E80A44A210006FE533 /* run.tif */, + 1CC058E90A44A210006FE533 /* step.tif */, + 1C6F83FE0A58E97D004FCD89 /* stepOut.tif */, + 1CC058EA0A44A210006FE533 /* stepOver.tif */, + 1CC058EB0A44A210006FE533 /* stop.tif */, + 1CC0596F0A44A485006FE533 /* toolbarBackground.png */, + 1C2632D10A4AF0A800EA7CD8 /* verticalSplitterBar.tiff */, + 1C2632D20A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff */, + 1C2632D50A4AF0B800EA7CD8 /* SourceArrow.png */, + 1C2632D60A4AF0B800EA7CD8 /* SourceArrowBlank.png */, + 1C2632D90A4AF0D200EA7CD8 /* background_stripe.png */, + ); + name = Images; + path = ../Images; + sourceTree = "<group>"; + }; + 1CD8D53C0A49025D00E5677B /* Nightly Support */ = { + isa = PBXGroup; + children = ( + 1CD8D54F0A4902B000E5677B /* LauncherInfo.plist */, + 1CD8D5680A49041C00E5677B /* launcher.m */, + ); + name = "Nightly Support"; + sourceTree = "<group>"; + }; + 2A37F4AAFDCFA73011CA2CEA /* SafariBug */ = { + isa = PBXGroup; + children = ( + D23E47C50C4460C600B7CD07 /* JavaScriptCore.framework */, + 2A37F4ABFDCFA73011CA2CEA /* Classes */, + 2A37F4AFFDCFA73011CA2CEA /* Other Sources */, + 2A37F4B8FDCFA73011CA2CEA /* Resources */, + 1CD8D53C0A49025D00E5677B /* Nightly Support */, + 2A37F4C3FDCFA73011CA2CEA /* Frameworks */, + 19C28FB0FE9D524F11CA2CBB /* Products */, + ); + name = SafariBug; + sourceTree = "<group>"; + }; + 2A37F4ABFDCFA73011CA2CEA /* Classes */ = { + isa = PBXGroup; + children = ( + 63D54F770AE8280F0064C440 /* breakpointEditor.html */, + 1C6F84530A58EE06004FCD89 /* console.css */, + 1C6F84540A58EE06004FCD89 /* console.html */, + 1C6F861F0A599F65004FCD89 /* console.js */, + 1C74F1830A47DEE600FEC632 /* DebuggerApplication.h */, + 1C74F1840A47DEE600FEC632 /* DebuggerApplication.mm */, + 95B2A44E0C95EECD00850C41 /* DebuggerClient.h */, + 95B2A44F0C95EECD00850C41 /* DebuggerClient.mm */, + D2D794ED0C4BED83004784F7 /* DebuggerDocument.cpp */, + D2D794EE0C4BED83004784F7 /* DebuggerDocument.h */, + 95B955240C975C7500AAB83B /* DebuggerDocumentPlatform.mm */, + 1C27AC230A413D660016ECF4 /* debugger.js */, + 1C27AC1F0A413D2D0016ECF4 /* debugger.html */, + 1C4FF7430A44F5260000D05D /* debugger.css */, + 95C906AF0C8E439200F9BE0F /* Platform.h */, + 957876760C9A221B008B6383 /* ServerConnection.h */, + 957876840C9A226A008B6383 /* ServerConnection.mm */, + 1C74F0340A47BF8300FEC632 /* viewer.html */, + 1C74F03A0A47BFD600FEC632 /* viewer.css */, + ); + name = Classes; + sourceTree = "<group>"; + tabWidth = 8; + usesTabs = 0; + }; + 2A37F4AFFDCFA73011CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 957879610C9B37BC008B6383 /* config.h */, + 2A37F4B0FDCFA73011CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = "<group>"; + tabWidth = 8; + usesTabs = 0; + }; + 2A37F4B8FDCFA73011CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 1C3487970A81208400101C5C /* Drosera.icns */, + 2A37F4B6FDCFA73011CA2CEA /* MainMenu.nib */, + 2A37F4B4FDCFA73011CA2CEA /* Debugger.nib */, + 8D15AC360486D014006FF6A4 /* Info.plist */, + 1CC058B70A44A210006FE533 /* Images */, + ); + name = Resources; + sourceTree = "<group>"; + tabWidth = 8; + usesTabs = 0; + }; + 2A37F4C3FDCFA73011CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A6FEA54F5311CA2CBB /* Linked Frameworks */, + 1058C7A8FEA54F5311CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1CD8D54C0A4902B000E5677B /* Drosera (Nightly Launcher) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1CD8D5500A4902B000E5677B /* Build configuration list for PBXNativeTarget "Drosera (Nightly Launcher)" */; + buildPhases = ( + 1CD8D5490A4902B000E5677B /* Resources */, + 1CD8D54A0A4902B000E5677B /* Sources */, + 1CD8D54B0A4902B000E5677B /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 1CD8D5AA0A49104E00E5677B /* PBXTargetDependency */, + ); + name = "Drosera (Nightly Launcher)"; + productName = "Drosera (Nightly Launcher)"; + productReference = 1CD8D54D0A4902B000E5677B /* DroseraLauncher.app */; + productType = "com.apple.product-type.application"; + }; + 8D15AC270486D014006FF6A4 /* Drosera */ = { + isa = PBXNativeTarget; + buildConfigurationList = C05733C708A9546B00998B17 /* Build configuration list for PBXNativeTarget "Drosera" */; + buildPhases = ( + 8D15AC2B0486D014006FF6A4 /* Resources */, + 8D15AC300486D014006FF6A4 /* Sources */, + 8D15AC330486D014006FF6A4 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Drosera; + productInstallPath = "$(HOME)/Applications"; + productName = SafariBug; + productReference = 8D15AC370486D014006FF6A4 /* Drosera.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2A37F4A9FDCFA73011CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C05733CB08A9546B00998B17 /* Build configuration list for PBXProject "Drosera" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 2A37F4AAFDCFA73011CA2CEA /* SafariBug */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8D15AC270486D014006FF6A4 /* Drosera */, + 1CD8D54C0A4902B000E5677B /* Drosera (Nightly Launcher) */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1CD8D5490A4902B000E5677B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD8D5A60A49102900E5677B /* Drosera.app in Resources */, + 5D2C827F0A816BA700C193FD /* Drosera.icns in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D15AC2B0486D014006FF6A4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D15AC2E0486D014006FF6A4 /* Debugger.nib in Resources */, + 1C3487980A81208400101C5C /* Drosera.icns in Resources */, + 8D15AC2D0486D014006FF6A4 /* MainMenu.nib in Resources */, + 1C2632D70A4AF0B800EA7CD8 /* SourceArrow.png in Resources */, + 1C2632D80A4AF0B800EA7CD8 /* SourceArrowBlank.png in Resources */, + 15CE85580ADBEA620078A734 /* SourceArrowOpen.png in Resources */, + 1C2632DA0A4AF0D200EA7CD8 /* background_stripe.png in Resources */, + 1CC058EE0A44A210006FE533 /* breakPoint.tif in Resources */, + 1CC058EF0A44A210006FE533 /* breakPointDisabled.tif in Resources */, + 63D54F780AE8280F0064C440 /* breakpointEditor.html in Resources */, + 63D54BD70AE600560064C440 /* breakpointeditor.png in Resources */, + 63D54D800AE75CF10064C440 /* close.tif in Resources */, + 63D54D7E0AE75CF10064C440 /* close_active.tif in Resources */, + 63D54D7F0AE75CF10064C440 /* close_hover.tif in Resources */, + 1C6F84550A58EE06004FCD89 /* console.css in Resources */, + 1C6F84560A58EE06004FCD89 /* console.html in Resources */, + 1C6F86730A59A18B004FCD89 /* console.js in Resources */, + 1C6F84520A58EDFE004FCD89 /* console.png in Resources */, + 1CC0591A0A44A210006FE533 /* continue.tif in Resources */, + 1C4FF7440A44F52C0000D05D /* debugger.css in Resources */, + 1C27AC200A413D2D0016ECF4 /* debugger.html in Resources */, + 1C27B1260A421D870016ECF4 /* debugger.js in Resources */, + 15CE85540ADBEA620078A734 /* fileIcon.jpg in Resources */, + 1CC059020A44A210006FE533 /* glossyFooterFill.tif in Resources */, + 1C4FF9210A45F3520000D05D /* glossyHeader.png in Resources */, + 1CD434B20A4B86F800A007AB /* glossyHeaderPressed.png in Resources */, + 1C4FF7540A44F6320000D05D /* gutter.png in Resources */, + 1CC0590E0A44A210006FE533 /* navLeftDisabled.png in Resources */, + 1CC0590F0A44A210006FE533 /* navLeftNormal.png in Resources */, + 1CC059100A44A210006FE533 /* navLeftPressed.png in Resources */, + 1CC059110A44A210006FE533 /* navRightDisabled.png in Resources */, + 1CC059120A44A210006FE533 /* navRightNormal.png in Resources */, + 1CC059130A44A210006FE533 /* navRightPressed.png in Resources */, + 1CC0591D0A44A210006FE533 /* pause.tif in Resources */, + 1C4FF94E0A45F5060000D05D /* popUpArrows.png in Resources */, + 1CC059160A44A210006FE533 /* programCounter.tif in Resources */, + 1C4FFE5E0A466F5D0000D05D /* programCounterBreakPoint.tif in Resources */, + 1C4FFE5F0A466F5D0000D05D /* programCounterBreakPointDisabled.tif in Resources */, + 1CC0591E0A44A210006FE533 /* run.tif in Resources */, + 15CE85550ADBEA620078A734 /* siteCollapsed.tif in Resources */, + 15CE85560ADBEA620078A734 /* siteExpanded.tif in Resources */, + 15CE85570ADBEA620078A734 /* siteIcon.tif in Resources */, + 1CC059170A44A210006FE533 /* splitterBar.tif in Resources */, + 1CC059180A44A210006FE533 /* splitterDimple.tif in Resources */, + 1CC0591F0A44A210006FE533 /* step.tif in Resources */, + 1C6F83FF0A58E97D004FCD89 /* stepOut.tif in Resources */, + 1CC059200A44A210006FE533 /* stepOver.tif in Resources */, + 1CC059700A44A485006FE533 /* toolbarBackground.png in Resources */, + 1C2632D30A4AF0A800EA7CD8 /* verticalSplitterBar.tiff in Resources */, + 1C2632D40A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff in Resources */, + 1C74F04B0A47BFE800FEC632 /* viewer.css in Resources */, + 1C74F0350A47BF8300FEC632 /* viewer.html in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1CD8D54A0A4902B000E5677B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1CD8D5690A49041C00E5677B /* launcher.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D15AC300486D014006FF6A4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1C74F1850A47DEE600FEC632 /* DebuggerApplication.mm in Sources */, + 95B2A4500C95EECD00850C41 /* DebuggerClient.mm in Sources */, + D2D794FD0C4BED83004784F7 /* DebuggerDocument.cpp in Sources */, + 95B955250C975C7500AAB83B /* DebuggerDocumentPlatform.mm in Sources */, + 957876850C9A226A008B6383 /* ServerConnection.mm in Sources */, + 8D15AC320486D014006FF6A4 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1CD8D5AA0A49104E00E5677B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D15AC270486D014006FF6A4 /* Drosera */; + targetProxy = 1CD8D5A90A49104E00E5677B /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 2A37F4B4FDCFA73011CA2CEA /* Debugger.nib */ = { + isa = PBXVariantGroup; + children = ( + 2A37F4B5FDCFA73011CA2CEA /* Debugger.nib */, + ); + name = Debugger.nib; + sourceTree = "<group>"; + }; + 2A37F4B6FDCFA73011CA2CEA /* MainMenu.nib */ = { + isa = PBXVariantGroup; + children = ( + 2A37F4B7FDCFA73011CA2CEA /* MainMenu.nib */, + ); + name = MainMenu.nib; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1CD8D5510A4902B000E5677B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DEBUGGING_SYMBOLS = full; + GCC_DYNAMIC_NO_PIC = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = LauncherInfo.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = DroseraLauncher; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 1CD8D5520A4902B000E5677B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DEPLOYMENT_POSTPROCESSING = YES; + GCC_DEBUGGING_SYMBOLS = full; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + INFOPLIST_FILE = LauncherInfo.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = DroseraLauncher; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + C05733C808A9546B00998B17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = ""; + HEADER_SEARCH_PATHS = ../ForwardingHeaders; + INFOPLIST_FILE = Info.plist; + PRODUCT_NAME = Drosera; + USER_HEADER_SEARCH_PATHS = ../ForwardingHeaders/; + VALID_ARCHS = "ppc7400 ppc970 i386 ppc"; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Debug; + }; + C05733C908A9546B00998B17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_C_LANGUAGE_STANDARD = c99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PREFIX_HEADER = ""; + HEADER_SEARCH_PATHS = ../ForwardingHeaders; + INFOPLIST_FILE = Info.plist; + PRODUCT_NAME = Drosera; + USER_HEADER_SEARCH_PATHS = ../ForwardingHeaders/; + VALID_ARCHS = "ppc7400 ppc970 i386 ppc"; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Release; + }; + C05733CC08A9546B00998B17 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + USER_HEADER_SEARCH_PATHS = ../ForwardingHeaders/; + }; + name = Debug; + }; + C05733CD08A9546B00998B17 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + USER_HEADER_SEARCH_PATHS = ../ForwardingHeaders/; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1CD8D5500A4902B000E5677B /* Build configuration list for PBXNativeTarget "Drosera (Nightly Launcher)" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1CD8D5510A4902B000E5677B /* Debug */, + 1CD8D5520A4902B000E5677B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C05733C708A9546B00998B17 /* Build configuration list for PBXNativeTarget "Drosera" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C05733C808A9546B00998B17 /* Debug */, + C05733C908A9546B00998B17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C05733CB08A9546B00998B17 /* Build configuration list for PBXProject "Drosera" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C05733CC08A9546B00998B17 /* Debug */, + C05733CD08A9546B00998B17 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2A37F4A9FDCFA73011CA2CEA /* Project object */; +} diff --git a/WebKitTools/Drosera/mac/Info.plist b/WebKitTools/Drosera/mac/Info.plist new file mode 100644 index 0000000..536f5a3 --- /dev/null +++ b/WebKitTools/Drosera/mac/Info.plist @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleGetInfoString</key> + <string>420+, Copyright 2006 Apple Computer, Inc.</string> + <key>CFBundleIdentifier</key> + <string>org.webkit.drosera</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>CFBundleIconFile</key> + <string>Drosera</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/WebKitTools/Drosera/mac/LauncherInfo.plist b/WebKitTools/Drosera/mac/LauncherInfo.plist new file mode 100644 index 0000000..12c4472 --- /dev/null +++ b/WebKitTools/Drosera/mac/LauncherInfo.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string>Drosera</string> + <key>CFBundleIdentifier</key> + <string>org.webkit.drosera.launcher</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>VERSION</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/WebKitTools/Drosera/mac/Makefile b/WebKitTools/Drosera/mac/Makefile new file mode 100644 index 0000000..058c21e --- /dev/null +++ b/WebKitTools/Drosera/mac/Makefile @@ -0,0 +1,2 @@ +SCRIPTS_PATH = ../../Scripts +include ../../../Makefile.shared diff --git a/WebKitTools/Drosera/mac/ServerConnection.h b/WebKitTools/Drosera/mac/ServerConnection.h new file mode 100644 index 0000000..f2b1303 --- /dev/null +++ b/WebKitTools/Drosera/mac/ServerConnection.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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. + */ + +@class DebuggerClient; +@class NSString; +@class WebScriptCallFrame; +@class WebScriptDebugServer; + +@interface ServerConnection : NSObject <WebScriptDebugListener> +{ + NSString *currentServerName; + WebScriptCallFrame *currentFrame; + id<WebScriptDebugServer> server; + JSGlobalContextRef globalContext; +} + +- (id)initWithServerName:(NSString *)serverName; +- (void)setGlobalContext:(JSGlobalContextRef)globalContextRef; +- (void)pause; +- (void)resume; +- (void)stepInto; +- (void)switchToServerNamed:(NSString *)name; +- (void)applicationTerminating:(NSNotification *)notifiction; +- (WebScriptCallFrame *)currentFrame; +- (NSString *)currentServerName; + +@end diff --git a/WebKitTools/Drosera/mac/ServerConnection.mm b/WebKitTools/Drosera/mac/ServerConnection.mm new file mode 100644 index 0000000..8444ee9 --- /dev/null +++ b/WebKitTools/Drosera/mac/ServerConnection.mm @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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 "config.h" +#import "ServerConnection.h" + +#import "DebuggerDocument.h" + +#import <JavaScriptCore/JSContextRef.h> +#import <JavaScriptCore/JSRetainPtr.h> +#import <JavaScriptCore/JSStringRefCF.h> +#import <JavaScriptCore/RetainPtr.h> + +@implementation ServerConnection + +#pragma mark - +- (id)initWithServerName:(NSString *)serverName; +{ + if (!(self = [super init])) + return nil; + + [self switchToServerNamed:serverName]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationTerminating:) name:NSApplicationWillTerminateNotification object:nil]; + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillTerminateNotification object:nil]; + + [currentServerName release]; + [currentFrame release]; + [server release]; + JSGlobalContextRelease(globalContext); + [super dealloc]; +} + +- (void)setGlobalContext:(JSGlobalContextRef)globalContextRef +{ + globalContext = JSGlobalContextRetain(globalContextRef); +} + +#pragma mark - +#pragma mark Pause & Step + +- (void)pause +{ + if ([[(NSDistantObject *)server connectionForProxy] isValid]) + [server pause]; + [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; +} + +- (void)resume +{ + if ([[(NSDistantObject *)server connectionForProxy] isValid]) + [server resume]; +} + +- (void)stepInto +{ + if ([[(NSDistantObject *)server connectionForProxy] isValid]) + [server step]; +} + +#pragma mark - +#pragma mark Connection Handling + +- (void)switchToServerNamed:(NSString *)name +{ + if (server) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSConnectionDidDieNotification object:[(NSDistantObject *)server connectionForProxy]]; + if ([[(NSDistantObject *)server connectionForProxy] isValid]) { + [server removeListener:self]; + [self resume]; + } + } + + id<WebScriptDebugServer> oldServer = server; + server = [name length] ? [[NSConnection rootProxyForConnectionWithRegisteredName:name host:nil] retain] : nil; + [oldServer release]; + + NSString *oldServerName = currentServerName; + currentServerName = [name retain]; + [oldServerName release]; + + if (server) { + @try { + [(NSDistantObject *)server setProtocolForProxy:@protocol(WebScriptDebugServer)]; + [server addListener:self]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(serverConnectionDidDie:) name:NSConnectionDidDieNotification object:[(NSDistantObject *)server connectionForProxy]]; + } @catch (NSException *exception) { + [currentServerName release]; + currentServerName = nil; + [server release]; + server = nil; + } + } +} + +- (void)applicationTerminating:(NSNotification *)notifiction +{ + if (server && [[(NSDistantObject *)server connectionForProxy] isValid]) { + [self switchToServerNamed:nil]; + // call the runloop for a while to make sure our removeListener: is sent to the server + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]]; + } +} + +- (void)serverConnectionDidDie:(NSNotification *)notifiction +{ + [self switchToServerNamed:nil]; +} + +#pragma mark - +#pragma mark Debug Listener Callbacks + +- (void)webView:(WebView *)view didLoadMainResourceForDataSource:(WebDataSource *)dataSource +{ + // Get document source + NSString *documentSource = nil; + id <WebDocumentRepresentation> rep = [dataSource representation]; + if ([rep canProvideDocumentSource]) + documentSource = [rep documentSource]; + + if (!documentSource) + return; + + JSRetainPtr<JSStringRef> documentSourceJS(Adopt, JSStringCreateWithCFString((CFStringRef)documentSource)); + + // Get URL + NSString *url = [[[dataSource response] URL] absoluteString]; + JSRetainPtr<JSStringRef> urlJS(Adopt, JSStringCreateWithCFString(url ? (CFStringRef)url : CFSTR(""))); + + DebuggerDocument::updateFileSource(globalContext, documentSourceJS.get(), urlJS.get()); +} + +- (void)webView:(WebView *)view didParseSource:(NSString *)source baseLineNumber:(unsigned)baseLine fromURL:(NSURL *)url sourceId:(int)sid forWebFrame:(WebFrame *)webFrame +{ + if (!globalContext) + return; + + RetainPtr<NSString> sourceCopy = source; + if (!sourceCopy.get()) + return; + + RetainPtr<NSString> documentSourceCopy; + RetainPtr<NSString> urlCopy = [url absoluteString]; + + WebDataSource *dataSource = [webFrame dataSource]; + if (!url || [[[dataSource response] URL] isEqual:url]) { + id <WebDocumentRepresentation> rep = [dataSource representation]; + if ([rep canProvideDocumentSource]) + documentSourceCopy = [rep documentSource]; + if (!urlCopy.get()) + urlCopy = [[[dataSource response] URL] absoluteString]; + } + + JSRetainPtr<JSStringRef> sourceCopyJS(Adopt, JSStringCreateWithCFString((CFStringRef)sourceCopy.get())); // We checked for NULL earlier. + JSRetainPtr<JSStringRef> documentSourceCopyJS(Adopt, JSStringCreateWithCFString(documentSourceCopy.get() ? (CFStringRef)documentSourceCopy.get() : CFSTR(""))); + JSRetainPtr<JSStringRef> urlCopyJS(Adopt, JSStringCreateWithCFString(urlCopy.get() ? (CFStringRef)urlCopy.get() : CFSTR(""))); + JSValueRef sidJS = JSValueMakeNumber(globalContext, sid); + JSValueRef baseLineJS = JSValueMakeNumber(globalContext, baseLine); + + DebuggerDocument::didParseScript(globalContext, sourceCopyJS.get(), documentSourceCopyJS.get(), urlCopyJS.get(), sidJS, baseLineJS); +} + +- (void)webView:(WebView *)view failedToParseSource:(NSString *)source baseLineNumber:(unsigned)baseLine fromURL:(NSURL *)url withError:(NSError *)error forWebFrame:(WebFrame *)webFrame +{ +} + +- (void)webView:(WebView *)view didEnterCallFrame:(WebScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno forWebFrame:(WebFrame *)webFrame +{ + if (!globalContext) + return; + + id old = currentFrame; + currentFrame = [frame retain]; + [old release]; + + JSValueRef sidJS = JSValueMakeNumber(globalContext, sid); + JSValueRef linenoJS = JSValueMakeNumber(globalContext, lineno); + + DebuggerDocument::didEnterCallFrame(globalContext, sidJS, linenoJS); +} + +- (void)webView:(WebView *)view willExecuteStatement:(WebScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno forWebFrame:(WebFrame *)webFrame +{ + if (!globalContext) + return; + + JSValueRef sidJS = JSValueMakeNumber(globalContext, sid); + JSValueRef linenoJS = JSValueMakeNumber(globalContext, lineno); + + DebuggerDocument::willExecuteStatement(globalContext, sidJS, linenoJS); +} + +- (void)webView:(WebView *)view willLeaveCallFrame:(WebScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno forWebFrame:(WebFrame *)webFrame +{ + if (!globalContext) + return; + + JSValueRef sidJS = JSValueMakeNumber(globalContext, sid); + JSValueRef linenoJS = JSValueMakeNumber(globalContext, lineno); + + DebuggerDocument::willLeaveCallFrame(globalContext, sidJS, linenoJS); + + id old = currentFrame; + currentFrame = [[frame caller] retain]; + [old release]; +} + +- (void)webView:(WebView *)view exceptionWasRaised:(WebScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno forWebFrame:(WebFrame *)webFrame +{ + if (!globalContext) + return; + + JSValueRef sidJS = JSValueMakeNumber(globalContext, sid); + JSValueRef linenoJS = JSValueMakeNumber(globalContext, lineno); + + DebuggerDocument::exceptionWasRaised(globalContext, sidJS, linenoJS); +} + +#pragma mark - +#pragma mark Stack & Variables + +- (WebScriptCallFrame *)currentFrame +{ + return currentFrame; +} + +#pragma mark - +#pragma mark Server Detection Callbacks + +-(NSString *)currentServerName +{ + return currentServerName; +} +@end diff --git a/WebKitTools/Drosera/mac/launcher.m b/WebKitTools/Drosera/mac/launcher.m new file mode 100644 index 0000000..7722312 --- /dev/null +++ b/WebKitTools/Drosera/mac/launcher.m @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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> +#import <CoreFoundation/CoreFoundation.h> + +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 Drosera require Mac OS X 10.4 or newer."); +} + +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); +} + +NSString *currentSystemVersion() +{ + long version; + if (Gestalt(gestaltSystemVersion, &version) != noErr) + return @"10.4"; + + return [NSString stringWithFormat:@"%x.%x", (version & 0xFF00) >> 8, (version & 0x00F0) >> 4]; +} + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + checkMacOSXVersion(); + + CFURLRef webkitURL = nil; + OSStatus err = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR("org.webkit.nightly.WebKit"), nil, nil, &webkitURL); + if (err != noErr) + displayErrorAndQuit(@"Unable to locate WebKit.app", @"Drosera nightly builds require WebKit.app to run. Please check that it is available and then try again."); + + NSBundle *webKitAppBundle = [NSBundle bundleWithPath:[(NSURL *)webkitURL path]]; + NSString *frameworkPath = [[webKitAppBundle privateFrameworksPath] stringByAppendingPathComponent:currentSystemVersion()]; + NSBundle *droseraBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"Drosera" ofType:@"app"]]; + NSString *executablePath = [droseraBundle executablePath]; + NSString *pathToEnablerLib = [webKitAppBundle pathForResource:@"WebKitNightlyEnabler" ofType:@"dylib"]; + + NSMutableArray *arguments = [NSMutableArray arrayWithObjects:executablePath, @"-WebKitDeveloperExtras", @"YES", nil]; + + while (*++argv) + [arguments addObject:[NSString stringWithUTF8String:*argv]]; + + NSDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys:frameworkPath, @"DYLD_FRAMEWORK_PATH", + @"YES", @"WEBKIT_UNSET_DYLD_FRAMEWORK_PATH", pathToEnablerLib, @"DYLD_INSERT_LIBRARIES", + [[NSBundle mainBundle] executablePath], @"WebKitAppPath", nil]; + + myExecve(executablePath, arguments, environment); + + char *error = strerror(errno); + NSString *errorMessage = [NSString stringWithFormat:@"Launching Drosera at %@ failed with the error '%s' (%d)", [(NSURL *)webkitURL path], error, errno]; + displayErrorAndQuit(@"Unable to launch Drosera", errorMessage); + + [pool release]; + return 0; +} diff --git a/WebKitTools/Drosera/mac/main.m b/WebKitTools/Drosera/mac/main.m new file mode 100644 index 0000000..2c09761 --- /dev/null +++ b/WebKitTools/Drosera/mac/main.m @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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. + */ + +#include <Cocoa/Cocoa.h> + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/WebKitTools/Drosera/viewer.css b/WebKitTools/Drosera/viewer.css new file mode 100644 index 0000000..aaac7a9 --- /dev/null +++ b/WebKitTools/Drosera/viewer.css @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +body { background-image: url(gutter.png); background-repeat: repeat-y; margin: 0; padding: 0; } +img { padding: 0; margin: 0; } + +table { border-spacing: 0; padding: 0; margin: 0; width: 100%; } +.gutter { -webkit-user-select: none; cursor: default; width: 32px; min-width: 32px; max-width: 32px; -webkit-box-sizing: border-box; font-size: 9px; font-family: Helvetica; color: #888; text-align: right; padding-right: 4px; } +.source { font-family: Monaco, monospace; white-space: pre; padding-left: 4px; padding-right: 4px; font-size: 11px; line-height: 14px; } + +.keyword { color: #8b0053 } +.string { color: #a00000 } +.number { color: #2900ff } +.comment { color: #007215 } + +td.gutter:after { content: attr(title); -webkit-user-select: none; } + +.breakpoint td.gutter, .current td.gutter { padding-right: 1px; vertical-align: top; } +.breakpoint td.gutter:after { content: url(breakPoint.tif); -webkit-user-select: none; vertical-align: middle; } +.breakpoint.disabled td.gutter:after { content: url(breakPointDisabled.tif); } + +.current td.gutter:after { content: url(programCounter.tif); -webkit-user-select: none; vertical-align: middle; } +.current.breakpoint td.gutter:after { content: url(programCounterBreakPoint.tif); } +.current.breakpoint.disabled td.gutter:after { content: url(programCounterBreakPointDisabled.tif); } +.current td.source { background-color: #abbffe; outline: 1px solid #406ffd; } + +#breakpointDrag { + position: absolute; + top: 0; + left: 0; + z-index: 100; + -webkit-user-select: none; + cursor: default; +} + +.editor { + top: -2px; + left: -2px; + margin-bottom: -2px; + position: relative; + min-width: 350px; + max-width: 500px; + border-width: 20px 12px 11px 36px; + border-color: transparent; + border-style: solid; + -webkit-border-image: url(breakpointeditor.png) 20 12 11 36; + font-size: 11px; + font-family: 'Lucida Grande', sans-serif; +} + +.editor .top { + position: absolute; + height: 20px; + -webkit-border-top-right-radius: 6px; + background-color: rgb(0, 134, 226); + border-bottom: 2px solid rgb(0, 110, 208); + top: -4px; + right: -5px; + left: -5px; + padding-left: 5px; + padding-right: 5px; +} + +.editor .bottom { + position: relative; + padding: 5px 0; + top: 20px; +} + +.editor .top label { + margin-left: 15px; +} + +.editor span.hitCounter { + margin-right: 4px; + margin-top: 1px; + padding-right: 2px; + padding-left: 2px; +} + +.editor select.editorDropdown { + margin-top: -1px; +} + +.editor div.condition { + position: relative; + background-color: white; + -webkit-user-modify: read-write-plaintext-only; + -webkit-nbsp-mode: space; + -webkit-line-break: after-white-space; + word-wrap: break-word; + outline: none; + font-family: monospace; + font-size: 10px; + line-height: 10px; + padding: 3px; + border: 1px solid darkgray; + top: -15px; + left: 65px; + margin-right: 65px; +} + +.editor input.close { + margin:0px; + margin-right: -4px; + float: right; + background-color: transparent; + background-image:url("close.tif"); + background-repeat: no-repeat; + height: 13px; + width: 12px; + border: none; +} + +.editor input.close:active { + background-image:url("close_active.tif"); +} + +.editor input.close:hover { + background-image:url("close_hover.tif"); +} diff --git a/WebKitTools/Drosera/viewer.html b/WebKitTools/Drosera/viewer.html new file mode 100644 index 0000000..fb4a21c --- /dev/null +++ b/WebKitTools/Drosera/viewer.html @@ -0,0 +1,48 @@ +<!-- +Copyright (C) 2006 Apple Computer, Inc. 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. +--> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + <script type="text/javascript"> + Element.prototype.firstParentWithClass = function(className) { + var node = this.parentNode; + while(node.className.indexOf(className) == -1) { + if (node == document) + return null; + node = node.parentNode; + } + return node; + } + </script> + <style type="text/css"> + @import "viewer.css"; + </style> +</head> +<body></body> +</html> diff --git a/WebKitTools/Drosera/win/BaseDelegate.h b/WebKitTools/Drosera/win/BaseDelegate.h new file mode 100644 index 0000000..6bc2f3f --- /dev/null +++ b/WebKitTools/Drosera/win/BaseDelegate.h @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +#ifndef BaseDelegate_H +#define BaseDelegate_H + +#include <WebKit/WebKit.h> + +struct IDataObject; +struct IPropertyBag; +struct IWebView; +struct IWebFrame; +struct IWebError; +struct IWebURLRequest; +struct IWebOpenPanelResultListener; + +class BaseDelegate : public IWebFrameLoadDelegate, public IWebUIDelegate { +public: + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID, + /* [retval][out] */ void**) + { return E_NOTIMPL; }; + + // IWebFrameLoadDelegate + virtual HRESULT STDMETHODCALLTYPE didFinishLoadForFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; }; + + virtual HRESULT STDMETHODCALLTYPE windowScriptObjectAvailable( + /* [in] */ IWebView*, + /* [in] */ JSContextRef, + /* [in] */ JSObjectRef) { return E_NOTIMPL; }; + + virtual HRESULT STDMETHODCALLTYPE didStartProvisionalLoadForFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; }; + + virtual HRESULT STDMETHODCALLTYPE didReceiveServerRedirectForProvisionalLoadForFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didFailProvisionalLoadWithError( + /* [in] */ IWebView*, + /* [in] */ IWebError*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didCommitLoadForFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didReceiveTitle( + /* [in] */ IWebView*, + /* [in] */ BSTR, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didReceiveIcon( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didFailLoadWithError( + /* [in] */ IWebView*, + /* [in] */ IWebError*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didChangeLocationWithinPageForFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformClientRedirectToURL( + /* [in] */ IWebView*, + /* [in] */ BSTR, + /* [in] */ double /*delaySeconds*/, + /* [in] */ DATE, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didCancelClientRedirectForFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willCloseFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*) { return E_NOTIMPL; } + + // IWebUIDelegate + virtual HRESULT STDMETHODCALLTYPE createWebViewWithRequest( + /* [in] */ IWebView*, + /* [in] */ IWebURLRequest*, + /* [retval][out] */ IWebView**) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewShow( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewClose( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewFocus( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewUnfocus( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewFirstResponder( + /* [in] */ IWebView*, + /* [retval][out] */ OLE_HANDLE*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE makeFirstResponder( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setStatusText( + /* [in] */ IWebView*, + /* [in] */ BSTR) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewStatusText( + /* [in] */ IWebView*, + /* [retval][out] */ BSTR*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewAreToolbarsVisible( + /* [in] */ IWebView*, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setToolbarsVisible( + /* [in] */ IWebView*, + /* [in] */ BOOL) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewIsStatusBarVisible( + /* [in] */ IWebView*, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setStatusBarVisible( + /* [in] */ IWebView*, + /* [in] */ BOOL) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewIsResizable( + /* [in] */ IWebView*, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setResizable( + /* [in] */ IWebView*, + /* [in] */ BOOL) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setFrame( + /* [in] */ IWebView*, + /* [in] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewFrame( + /* [in] */ IWebView*, + /* [retval][out] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setContentRect( + /* [in] */ IWebView*, + /* [in] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewContentRect( + /* [in] */ IWebView*, + /* [retval][out] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptAlertPanelWithMessage( + /* [in] */ IWebView*, + /* [in] */ BSTR) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptConfirmPanelWithMessage( + /* [in] */ IWebView*, + /* [in] */ BSTR, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptTextInputPanelWithPrompt( + /* [in] */ IWebView*, + /* [in] */ BSTR /*message*/, + /* [in] */ BSTR /*defaultText*/, + /* [retval][out] */ BSTR*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runBeforeUnloadConfirmPanelWithMessage( + /* [in] */ IWebView*, + /* [in] */ BSTR /*message*/, + /* [in] */ IWebFrame* /*initiatedByFrame*/, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runOpenPanelForFileButtonWithResultListener( + /* [in] */ IWebView*, + /* [in] */ IWebOpenPanelResultListener*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE mouseDidMoveOverElement( + /* [in] */ IWebView*, + /* [in] */ IPropertyBag*, + /* [in] */ UINT /*modifierFlags*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE contextMenuItemsForElement( + /* [in] */ IWebView*, + /* [in] */ IPropertyBag*, + /* [in] */ OLE_HANDLE, + /* [retval][out] */ OLE_HANDLE*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE validateUserInterfaceItem( + /* [in] */ IWebView*, + /* [in] */ UINT, + /* [in] */ BOOL, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE shouldPerformAction( + /* [in] */ IWebView*, + /* [in] */ UINT /*itemCommandID*/, + /* [in] */ UINT /*sender*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE dragDestinationActionMaskForDraggingInfo( + /* [in] */ IWebView*, + /* [in] */ IDataObject*, + /* [retval][out] */ WebDragDestinationAction*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformDragDestinationAction( + /* [in] */ IWebView*, + /* [in] */ WebDragDestinationAction, + /* [in] */ IDataObject*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE dragSourceActionMaskForPoint( + /* [in] */ IWebView*, + /* [in] */ LPPOINT, + /* [retval][out] */ WebDragSourceAction*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformDragSourceAction( + /* [in] */ IWebView*, + /* [in] */ WebDragSourceAction, + /* [in] */ LPPOINT, + /* [in] */ IDataObject*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE contextMenuItemSelected( + /* [in] */ IWebView*, + /* [in] */ void* /*item*/, + /* [in] */ IPropertyBag*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE hasCustomMenuImplementation( + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE trackCustomPopupMenu( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE, + /* [in] */ LPPOINT) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE measureCustomMenuItem( + /* [in] */ IWebView*, + /* [in] */ void* /*measureItem*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE drawCustomMenuItem( + /* [in] */ IWebView*, + /* [in] */ void* /*drawItem*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE addCustomMenuDrawingData( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE cleanUpCustomMenuDrawingData( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE canTakeFocus( + /* [in] */ IWebView*, + /* [in] */ BOOL /*forward*/, + /* [out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE takeFocus( + /* [in] */ IWebView*, + /* [in] */ BOOL /*forward*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE registerUndoWithTarget( + /* [in] */ IWebUndoTarget*, + /* [in] */ BSTR /*actionName*/, + /* [in] */ IUnknown* /*actionArg*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE removeAllActionsWithTarget( + /* [in] */ IWebUndoTarget*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setActionTitle( + /* [in] */ BSTR) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE undo( void) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE redo( void) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE canUndo( + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE canRedo( + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } +}; + +#endif //BaseDelegate_H diff --git a/WebKitTools/Drosera/win/DebuggerClient.cpp b/WebKitTools/Drosera/win/DebuggerClient.cpp new file mode 100644 index 0000000..77b689c --- /dev/null +++ b/WebKitTools/Drosera/win/DebuggerClient.cpp @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2007 Apple, Inc. 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. + */ +#include "config.h" +#include "DebuggerClient.h" + +#include "DebuggerDocument.h" +#include "Drosera.h" +#include "ServerConnection.h" + +#include <WebKit/ForEachCoClass.h> +#include <WebKit/WebKit.h> +#include <JavaScriptCore/JSContextRef.h> + +static LPCTSTR kConsoleTitle = _T("Console"); +static LPCTSTR kConsoleClassName = _T("DroseraConsoleWindowClass"); + +static LRESULT CALLBACK consoleWndProc(HWND, UINT, WPARAM, LPARAM); + +void registerConsoleClass(HINSTANCE hInstance) +{ + static bool haveRegisteredWindowClass = false; + + if (haveRegisteredWindowClass) { + haveRegisteredWindowClass = true; + return; + } + + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = 0; + wcex.lpfnWndProc = consoleWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = sizeof(DebuggerClient*); + wcex.hInstance = hInstance; + wcex.hIcon = 0; + wcex.hCursor = LoadCursor(0, IDC_ARROW); + wcex.hbrBackground = 0; + wcex.lpszMenuName = 0; + wcex.lpszClassName = kConsoleClassName; + wcex.hIconSm = 0; + + RegisterClassEx(&wcex); +} + +static LRESULT CALLBACK consoleWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); + DebuggerClient* client = reinterpret_cast<DebuggerClient*>(longPtr); + + switch (message) { + case WM_SIZE: + if (!client) + return 0; + return client->onSize(wParam, lParam); + case WM_PAINT: { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + break; + } + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return 0; +} + +LRESULT DebuggerClient::onSize(WPARAM, LPARAM) +{ + if (!m_webViewPrivate) + return 0; + + RECT clientRect = {0}; + if (!GetClientRect(m_consoleWindow, &clientRect)) + return 0; + + HWND viewWindow; + if (SUCCEEDED(m_webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + SetWindowPos(viewWindow, 0, clientRect.left, clientRect.top, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, SWP_NOZORDER); + + return 0; +} + +DebuggerClient::DebuggerClient() + : m_webViewLoaded(false) + , m_debuggerDocument(new DebuggerDocument(new ServerConnection())) + , m_globalContext(0) +{ +} + +DebuggerClient::~DebuggerClient() +{ + if (m_globalContext) + JSGlobalContextRelease(m_globalContext); +} + +// IUnknown ------------------------------ +HRESULT STDMETHODCALLTYPE DebuggerClient::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = this; + else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate)) + *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebUIDelegate)) + *ppvObject = static_cast<IWebUIDelegate*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE DebuggerClient::AddRef() +{ + // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView. + return 1; +} + +ULONG STDMETHODCALLTYPE DebuggerClient::Release() +{ + // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView. + return 1; +} + +// IWebFrameLoadDelegate ------------------------------ +HRESULT STDMETHODCALLTYPE DebuggerClient::didFinishLoadForFrame( + /* [in] */ IWebView* webView, + /* [in] */ IWebFrame*) +{ + HRESULT ret = S_OK; + + m_webViewLoaded = true; + + COMPtr<IWebFrame> mainFrame; + ret = webView->mainFrame(&mainFrame); + if (FAILED(ret)) + return ret; + + if (!m_globalContext) { + JSGlobalContextRef context = mainFrame->globalContext(); + if (!context) + return E_FAIL; + + m_globalContext = JSGlobalContextRetain(context); + } + + if (serverConnected()) + m_debuggerDocument->server()->setGlobalContext(m_globalContext); + + return ret; +} + +HRESULT STDMETHODCALLTYPE DebuggerClient::windowScriptObjectAvailable( + /* [in] */ IWebView*, + /* [in] */ JSContextRef context, + /* [in] */ JSObjectRef windowObject) +{ + JSValueRef exception = 0; + if (m_debuggerDocument) + m_debuggerDocument->windowScriptObjectAvailable(context, windowObject, &exception); + + if (exception) + return E_FAIL; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DebuggerClient::createWebViewWithRequest( + /* [in] */ IWebView*, + /* [in] */ IWebURLRequest* request, + /* [retval][out] */ IWebView** newWebView) +{ + HRESULT ret = S_OK; + + if (!newWebView) + return E_POINTER; + + *newWebView = 0; + + HINSTANCE instance = Drosera::getInst(); + + registerConsoleClass(instance); + + m_consoleWindow = CreateWindow(kConsoleClassName, kConsoleTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, 500, 350, 0, 0, instance, 0); + + if (!m_consoleWindow) + return HRESULT_FROM_WIN32(GetLastError()); + + SetLastError(0); + SetWindowLongPtr(m_consoleWindow, 0, reinterpret_cast<LONG_PTR>(this)); + ret = HRESULT_FROM_WIN32(GetLastError()); + if (FAILED(ret)) + return ret; + + CLSID clsid = CLSID_NULL; + ret = CLSIDFromProgID(PROGID(WebView), &clsid); + if (FAILED(ret)) + return ret; + + COMPtr<IWebView> view; + ret = CoCreateInstance(clsid, 0, CLSCTX_ALL, IID_IWebView, (void**)&view); + if (FAILED(ret)) + return ret; + + m_webViewPrivate.query(view); + if (!m_webViewPrivate) + return E_FAIL; + + ret = view->setHostWindow(reinterpret_cast<OLE_HANDLE>(m_consoleWindow)); + if (FAILED(ret)) + return ret; + + RECT clientRect = {0}; + GetClientRect(m_consoleWindow, &clientRect); + ret = view->initWithFrame(clientRect, 0, 0); + if (FAILED(ret)) + return ret; + + ret = view->setUIDelegate(this); + if (FAILED(ret)) + return ret; + + ret = view->setFrameLoadDelegate(this); + if (FAILED(ret)) + return ret; + + if (request) { + BOOL requestIsEmpty = FALSE; + ret = request->isEmpty(&requestIsEmpty); + if (FAILED(ret)) + return ret; + + if (!requestIsEmpty) { + COMPtr<IWebFrame> mainFrame; + ret = view->mainFrame(&mainFrame); + if (FAILED(ret)) + return ret; + + ret = mainFrame->loadRequest(request); + if (FAILED(ret)) + return ret; + } + } + + ShowWindow(m_consoleWindow, SW_SHOW); + UpdateWindow(m_consoleWindow); + + *newWebView = view.releaseRef(); + + return S_OK; +} + +// IWebUIDelegate ------------------------------ +HRESULT STDMETHODCALLTYPE DebuggerClient::runJavaScriptAlertPanelWithMessage( // For debugging purposes + /* [in] */ IWebView*, + /* [in] */ BSTR message) +{ +#ifndef NDEBUG + fwprintf(stderr, L"%s\n", message ? message : L""); +#else + (void)message; +#endif + return S_OK; +} + +// Pause & Step ------------------------------- +void DebuggerClient::resume() +{ + DebuggerDocument::callGlobalFunction(m_globalContext, "resume", 0, 0); +} + +void DebuggerClient::pause() +{ + DebuggerDocument::callGlobalFunction(m_globalContext, "pause", 0, 0); +} + +void DebuggerClient::stepInto() +{ + DebuggerDocument::callGlobalFunction(m_globalContext, "stepInto", 0, 0); +} + +void DebuggerClient::stepOver() +{ + DebuggerDocument::callGlobalFunction(m_globalContext, "stepOver", 0, 0); +} + +void DebuggerClient::stepOut() +{ + DebuggerDocument::callGlobalFunction(m_globalContext, "stepOut", 0, 0); +} + +void DebuggerClient::showConsole() +{ + DebuggerDocument::callGlobalFunction(m_globalContext, "showConsoleWindow", 0, 0); +} + +void DebuggerClient::closeCurrentFile() +{ + DebuggerDocument::callGlobalFunction(m_globalContext, "closeCurrentFile", 0, 0); +} + + +// Server Connection Functions ---------------- +bool DebuggerClient::serverConnected() const +{ + return m_debuggerDocument->server()->serverConnected(); +} + +void DebuggerClient::attemptToCreateServerConnection() +{ + m_debuggerDocument->server()->attemptToCreateServerConnection(m_globalContext); +} diff --git a/WebKitTools/Drosera/win/DebuggerClient.h b/WebKitTools/Drosera/win/DebuggerClient.h new file mode 100644 index 0000000..7297615 --- /dev/null +++ b/WebKitTools/Drosera/win/DebuggerClient.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +#ifndef DebuggerClient_H +#define DebuggerClient_H + +#include "BaseDelegate.h" + +#include <string> +#include <WebCore/COMPtr.h> +#include <wtf/OwnPtr.h> + +class DebuggerDocument; +interface IWebView; +interface IWebFrame; +interface IWebViewPrivate; + +typedef const struct OpaqueJSContext* JSContextRef; +typedef struct OpaqueJSValue* JSObjectRef; + +class DebuggerClient : public BaseDelegate { +public: + DebuggerClient(); + ~DebuggerClient(); + explicit DebuggerClient(const std::wstring& serverName); + + LRESULT DebuggerClient::onSize(WPARAM, LPARAM); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [retval][out] */ void** ppvObject); + + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IWebFrameLoadDelegate + HRESULT STDMETHODCALLTYPE didFinishLoadForFrame( + /* [in] */ IWebView*, + /* [in] */ IWebFrame*); + + HRESULT STDMETHODCALLTYPE windowScriptObjectAvailable( + /* [in] */ IWebView*, + /* [in] */ JSContextRef, + /* [in] */ JSObjectRef); + + // IWebUIDelegate + HRESULT STDMETHODCALLTYPE runJavaScriptAlertPanelWithMessage( + /* [in] */ IWebView*, + /* [in] */ BSTR); + + HRESULT STDMETHODCALLTYPE createWebViewWithRequest( + /* [in] */ IWebView*, + /* [in] */ IWebURLRequest*, + /* [retval][out] */ IWebView**); + + bool webViewLoaded() const { return m_webViewLoaded; } + + // Pause & Step + void resume(); + void pause(); + void stepInto(); + void stepOver(); + void stepOut(); + void showConsole(); + void closeCurrentFile(); + + // Server Connection Functions + bool serverConnected() const; + void attemptToCreateServerConnection(); + +private: + bool m_webViewLoaded; + JSGlobalContextRef m_globalContext; + + HWND m_consoleWindow; + COMPtr<IWebViewPrivate> m_webViewPrivate; + + OwnPtr<DebuggerDocument> m_debuggerDocument; +}; + +#endif //DebuggerClient_H diff --git a/WebKitTools/Drosera/win/DebuggerDocumentPlatform.cpp b/WebKitTools/Drosera/win/DebuggerDocumentPlatform.cpp new file mode 100644 index 0000000..f23daf7 --- /dev/null +++ b/WebKitTools/Drosera/win/DebuggerDocumentPlatform.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2007 Apple, Inc. 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. + */ +#include "config.h" +#include "DebuggerDocument.h" + +#include "ServerConnection.h" + +#include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/JSStringRef.h> +#include <JavaScriptCore/JSStringRefBSTR.h> +#include <WebKit/WebKit.h> + +JSValueRef JSValueRefCreateWithBSTR(JSContextRef context, BSTR string) +{ + JSRetainPtr<JSStringRef> jsString(Adopt, JSStringCreateWithBSTR(string)); + return JSValueMakeString(context, jsString.get()); +} + +// DebuggerDocument platform specific implementations + +void DebuggerDocument::platformPause() +{ + m_server->pause(); +} + +void DebuggerDocument::platformResume() +{ + m_server->resume(); +} + +void DebuggerDocument::platformStepInto() +{ + m_server->stepInto(); +} + +JSValueRef DebuggerDocument::platformEvaluateScript(JSContextRef context, JSStringRef script, int callFrame) +{ + HRESULT ret = S_OK; + + COMPtr<IWebScriptCallFrame> cframe = m_server->getCallerFrame(callFrame); + if (!cframe) + return JSValueMakeUndefined(context); + + // Convert script to BSTR + BSTR scriptBSTR = JSStringCopyBSTR(script); + BSTR value = 0; + ret = cframe->stringByEvaluatingJavaScriptFromString(scriptBSTR, &value); + SysFreeString(scriptBSTR); + if (FAILED(ret)) { + SysFreeString(value); + return JSValueMakeUndefined(context); + } + + JSValueRef returnValue = JSValueRefCreateWithBSTR(context, value); + SysFreeString(value); + return returnValue; + +} + +void DebuggerDocument::getPlatformCurrentFunctionStack(JSContextRef context, Vector<JSValueRef>& currentStack) +{ + COMPtr<IWebScriptCallFrame> frame = m_server->currentFrame(); + while (frame) { + COMPtr<IWebScriptCallFrame> caller; + BSTR function = 0; + if (FAILED(frame->functionName(&function))) + return; + + if (FAILED(frame->caller(&caller))) + return; + + if (!function) { + if (caller) + function = SysAllocString(L"(anonymous function)"); + else + function = SysAllocString(L"(global scope)"); + } + + currentStack.append(JSValueRefCreateWithBSTR(context, function)); + SysFreeString(function); + + frame = caller; + } +} + +void DebuggerDocument::getPlatformLocalScopeVariableNamesForCallFrame(JSContextRef context, int callFrame, Vector<JSValueRef>& variableNames) +{ + COMPtr<IWebScriptCallFrame> cframe = m_server->getCallerFrame(callFrame); + if (!cframe) + return; + + VARIANT var; + VariantInit(&var); + + COMPtr<IEnumVARIANT> localScopeVariableNames; + if (FAILED(cframe->variableNames(&localScopeVariableNames))) + return; + + while (localScopeVariableNames->Next(1, &var, 0) == S_OK) { + ASSERT(V_VT(&var) == VT_BSTR); + BSTR variableName; + + variableName = V_BSTR(&var); + variableNames.append(JSValueRefCreateWithBSTR(context, variableName)); + + SysFreeString(variableName); + VariantClear(&var); + } +} + +JSValueRef DebuggerDocument::platformValueForScopeVariableNamed(JSContextRef context, JSStringRef key, int callFrame) +{ + COMPtr<IWebScriptCallFrame> cframe = m_server->getCallerFrame(callFrame); + if (!cframe) + return JSValueMakeUndefined(context); + + BSTR bstrKey = JSStringCopyBSTR(key); + + BSTR variableValue; + HRESULT hr = cframe->valueForVariable(bstrKey, &variableValue); + SysFreeString(bstrKey); + if (FAILED(hr)) + return JSValueMakeUndefined(context); + + JSValueRef returnValue = JSValueRefCreateWithBSTR(context, variableValue); + SysFreeString(variableValue); + + return returnValue; +} + + +void DebuggerDocument::platformLog(JSStringRef msg) +{ + printf("%S\n", JSStringGetCharactersPtr(msg)); +} diff --git a/WebKitTools/Drosera/win/Drosera.cpp b/WebKitTools/Drosera/win/Drosera.cpp new file mode 100644 index 0000000..820054f --- /dev/null +++ b/WebKitTools/Drosera/win/Drosera.cpp @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "config.h" +#include "Drosera.h" + +#include "DebuggerClient.h" +#include "DebuggerDocument.h" +#include "resource.h" +#include "ServerConnection.h" + +#include <JavaScriptCore/JSStringRef.h> +#include <WebKit/ForEachCoClass.h> +#include <WebKit/WebKit.h> +#include <wtf/RetainPtr.h> + +const unsigned MAX_LOADSTRING = 100; + +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name + +static LPCTSTR s_DroseraPointerProp = TEXT("DroseraPointer"); +static HINSTANCE hInst; + +BSTR cfStringToBSTR(CFStringRef cfstr); + +void registerDroseraClass(HINSTANCE hInstance); +LRESULT CALLBACK droseraWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK aboutWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +HINSTANCE Drosera::getInst() { return hInst; } +void Drosera::setInst(HINSTANCE in) { hInst = in; } +void launchConsoleWindow(); + +extern "C" __declspec(dllimport) HANDLE* __pioinfo; + +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + MSG msg; + +#ifndef NDEBUG + launchConsoleWindow(); +#endif + + Drosera drosera; + + HRESULT ret = drosera.init(hInstance, nCmdShow); + if (FAILED(ret)) + return ret; + + HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DROSERA)); + + // Main message loop: + while (GetMessage(&msg, 0, 0, 0)) { + if (!drosera.serverConnected()) + drosera.attemptToCreateServerConnection(); + + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return static_cast<int>(msg.wParam); +} + +void launchConsoleWindow() +{ + if (AllocConsole()) { + // MSVCRT exports __pioinfo which is an array of ioinfo handles. the first three are stdout, stdin, and stderr + // the first pointer in the ioinfo object is the kernel handle for the console, so we can simplify the expression + // to just deref the exported symbol, setting it to the newly allocated console handle. + *__pioinfo = GetStdHandle(STD_OUTPUT_HANDLE); + // When an app is created without a console, stdout, stderr and stdin are all invalid handles (i.e. negative) + // Since we've introduced new handles, we can reset their file index - which is the index into the ioinfo array. + // This hooks up the standard cruntime APIS to the new console, allowing a functional output. As for input YMMV. + stdout->_file = 0; + stderr->_file = 0; + } +} + +////////////////// Setup Windows Specific Interface ////////////////// + +void registerDroseraClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = ::droseraWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = sizeof(Drosera*); + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DROSERA)); + wcex.hCursor = LoadCursor(0, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DROSERA); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + RegisterClassEx(&wcex); +} + +//Processes messages for the main window. +LRESULT CALLBACK droseraWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + HDC hdc; + + LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); + Drosera* drosera = reinterpret_cast<Drosera*>(longPtr); + + switch (message) { + case WM_COMMAND: + return drosera->handleCommand(hWnd, message, wParam, lParam); + break; + case WM_SIZE: + if (!drosera) + return 0; + return drosera->webViewLoaded() ? drosera->onSize(wParam, lParam) : 0; + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return 0; +} + +LRESULT CALLBACK Drosera::handleCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId = LOWORD(wParam); + switch (wmId) { + case ID_DEBUG_CONTINUE: + m_debuggerClient->resume(); + break; + case ID_DEBUG_PAUSE: + m_debuggerClient->pause(); + break; + case ID_DEBUG_STEPINTO: + m_debuggerClient->stepInto(); + break; + case ID_DEBUG_STEPOVER: + m_debuggerClient->stepOver(); + break; + case ID_DEBUG_STEPOUT: + m_debuggerClient->stepOut(); + break; + case ID_DEBUG_SHOWCONSOLE: + m_debuggerClient->showConsole(); + break; + case ID_HELP_ABOUT: + DialogBox(Drosera::getInst(), MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, ::aboutWndProc); + break; + case ID_FILE_EXIT: + DestroyWindow(hWnd); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return 0; +} + +// Message handler for about box. +INT_PTR CALLBACK aboutWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +////////////////// End Setup Windows Specific Interface ////////////////// + +Drosera::Drosera() + : m_hWnd(0) + , m_debuggerClient(new DebuggerClient()) +{ +} + +HRESULT Drosera::init(HINSTANCE hInstance, int nCmdShow) +{ + HRESULT ret = initUI(hInstance, nCmdShow); + if (FAILED(ret)) + return ret; + + ret = attach(); + return ret; +} + + +HRESULT Drosera::initUI(HINSTANCE hInstance, int nCmdShow) +{ + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, ARRAYSIZE(szTitle)); + LoadString(hInstance, IDC_DROSERA, szWindowClass, ARRAYSIZE(szWindowClass)); + registerDroseraClass(hInstance); + + Drosera::setInst(hInstance); // Store instance handle in our local variable + + m_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, 0); + + if (!m_hWnd) + return HRESULT_FROM_WIN32(GetLastError()); + + SetLastError(0); + SetWindowLongPtr(m_hWnd, 0, reinterpret_cast<LONG_PTR>(this)); + HRESULT ret = HRESULT_FROM_WIN32(GetLastError()); + if (FAILED(ret)) + return ret; + + CLSID clsid = CLSID_NULL; + ret = CLSIDFromProgID(PROGID(WebView), &clsid); + if (FAILED(ret)) + return ret; + + ret = CoCreateInstance(clsid, 0, CLSCTX_ALL, IID_IWebView, (void**)&m_webView); + if (FAILED(ret)) + return ret; + + m_webViewPrivate.query(m_webView.get()); + if (!m_webViewPrivate) + return E_FAIL; + + ret = m_webView->setHostWindow(reinterpret_cast<OLE_HANDLE>(m_hWnd)); + if (FAILED(ret)) + return ret; + + RECT clientRect = {0}; + ::GetClientRect(m_hWnd, &clientRect); + ret = m_webView->initWithFrame(clientRect, 0, 0); + if (FAILED(ret)) + return ret; + + HWND viewWindow; + ret = m_webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)); + if (FAILED(ret)) + return ret; + + SetProp(viewWindow, s_DroseraPointerProp, (HANDLE)this); + + // FIXME: Implement window size/position save/restore + ShowWindow(m_hWnd, nCmdShow); + UpdateWindow(m_hWnd); + + return ret; +} + +LRESULT Drosera::onSize(WPARAM, LPARAM) +{ + if (!m_webViewPrivate) + return 0; + + RECT clientRect = {0}; + ::GetClientRect(m_hWnd, &clientRect); + + HWND viewWindow; + if (SUCCEEDED(m_webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + // FIXME should this be the height-command bars height? + ::SetWindowPos(viewWindow, 0, clientRect.left, clientRect.top, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, SWP_NOZORDER); + + return 0; +} + +bool Drosera::webViewLoaded() const +{ + return m_debuggerClient->webViewLoaded(); +} + +// Server Detection Callbacks + +HRESULT Drosera::attach() +{ + // Get selected server + HRESULT ret = m_webView->setFrameLoadDelegate(m_debuggerClient.get()); + if (FAILED(ret)) + return ret; + + ret = m_webView->setUIDelegate(m_debuggerClient.get()); + if (FAILED(ret)) + return ret; + + CLSID clsid = CLSID_NULL; + ret = CLSIDFromProgID(PROGID(WebMutableURLRequest), &clsid); + if (FAILED(ret)) + return ret; + + COMPtr<IWebMutableURLRequest> request; + ret = CoCreateInstance(clsid, 0, CLSCTX_ALL, IID_IWebMutableURLRequest, (void**)&request); + if (FAILED(ret)) + return ret; + + RetainPtr<CFURLRef> htmlURLRef(AdoptCF, ::CFBundleCopyResourceURL(::CFBundleGetBundleWithIdentifier(CFSTR("org.webkit.drosera")), CFSTR("debugger"), CFSTR("html"), CFSTR("Drosera"))); + if (!htmlURLRef) + return E_FAIL; + + CFStringRef urlStringRef = ::CFURLGetString(htmlURLRef.get()); + BSTR tempStr = cfStringToBSTR(urlStringRef); // Both initWithRUL and SysFreeString can handle 0. + ret = request->initWithURL(tempStr, WebURLRequestUseProtocolCachePolicy, 60); + SysFreeString(tempStr); + if (FAILED(ret)) + return ret; + + COMPtr<IWebFrame> mainFrame; + ret = m_webView->mainFrame(&mainFrame); + if (FAILED(ret)) + return ret; + + ret = mainFrame->loadRequest(request.get()); + if (FAILED(ret)) + return ret; + + return ret; +} + +BSTR cfStringToBSTR(CFStringRef cfstr) +{ + if (!cfstr) + return 0; + + const UniChar* uniChars = CFStringGetCharactersPtr(cfstr); + if (uniChars) + return SysAllocStringLen((LPCTSTR)uniChars, CFStringGetLength(cfstr)); + + CFIndex length = CFStringGetLength(cfstr); + BSTR bstr = SysAllocStringLen(0, length); + CFStringGetCharacters(cfstr, CFRangeMake(0, length), (UniChar*)bstr); + bstr[length] = 0; + + return bstr; +} + +// Server Connection Functions + +bool Drosera::serverConnected() const +{ + return m_debuggerClient->serverConnected(); +} + +void Drosera::attemptToCreateServerConnection() +{ + m_debuggerClient->attemptToCreateServerConnection(); +} + diff --git a/WebKitTools/Drosera/win/Drosera.h b/WebKitTools/Drosera/win/Drosera.h new file mode 100644 index 0000000..a73c7f7 --- /dev/null +++ b/WebKitTools/Drosera/win/Drosera.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +#ifndef Drosera_H +#define Drosera_H + +#include "DebuggerDocument.h" + +#include <WebCore/COMPtr.h> +#include <wtf/OwnPtr.h> + +class DebuggerClient; +interface IWebView; +interface IWebViewPrivate; + +class Drosera { +public: + Drosera(); + + static HINSTANCE getInst(); + static void setInst(HINSTANCE); + + HRESULT init(HINSTANCE hInstance, int nCmdShow); + LRESULT onSize(WPARAM, LPARAM); + LRESULT CALLBACK handleCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + + bool webViewLoaded() const; + + // Server connection functions + bool serverConnected() const; + void attemptToCreateServerConnection(); + +private: + HRESULT initUI(HINSTANCE hInstance, int nCmdShow); + HRESULT attach(); + + HWND m_hWnd; + + COMPtr<IWebView> m_webView; + COMPtr<IWebViewPrivate> m_webViewPrivate; + + OwnPtr<DebuggerClient> m_debuggerClient; +}; + +#endif //Drosera_H diff --git a/WebKitTools/Drosera/win/Drosera.vcproj/Drosera.rc b/WebKitTools/Drosera/win/Drosera.vcproj/Drosera.rc new file mode 100755 index 0000000..6f8a8c8 --- /dev/null +++ b/WebKitTools/Drosera/win/Drosera.vcproj/Drosera.rc @@ -0,0 +1,196 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+#ifndef APSTUDIO_INVOKED
+#include "autoversion.h"
+#endif
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_DROSERA ICON "Drosera.ico"
+IDI_SMALL ICON "small.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDC_DROSERA MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "Close Current File", ID_FILE_CLOSECURRENTFILE
+ MENUITEM "Exit", ID_FILE_EXIT
+ END
+ POPUP "Edit"
+ BEGIN
+ MENUITEM "Undo", ID_EDIT_UNDO
+ MENUITEM "Redo", ID_EDIT_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cut", ID_EDIT_CUT
+ MENUITEM "Copy", ID_EDIT_COPY
+ MENUITEM "Paste", ID_EDIT_PASTE
+ MENUITEM "Select All", ID_EDIT_SELECTALL
+ MENUITEM SEPARATOR
+ POPUP "Find"
+ BEGIN
+ MENUITEM "Find", ID_FIND_FIND
+ MENUITEM "Find Next", ID_FIND_FINDNEXT
+ MENUITEM "Find Previous", ID_FIND_FINDPREVIOUS
+ MENUITEM "Use Selection for Find", ID_FIND_USESELECTIONFORFIND
+ MENUITEM "Jump to Selection", ID_FIND_JUMPTOSELECTION
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Special Characters", ID_EDIT_SPECIALCHARACTERS
+ END
+ POPUP "Debug"
+ BEGIN
+ MENUITEM "Show Console", ID_DEBUG_SHOWCONSOLE
+ MENUITEM SEPARATOR
+ MENUITEM "Continue", ID_DEBUG_CONTINUE
+ MENUITEM "Pause", ID_DEBUG_PAUSE
+ MENUITEM "Step Into", ID_DEBUG_STEPINTO
+ MENUITEM "Step Over", ID_DEBUG_STEPOVER
+ MENUITEM "Step Out", ID_DEBUG_STEPOUT
+ END
+ MENUITEM "Window", ID_WINDOW
+ POPUP "Help"
+ BEGIN
+ MENUITEM "About", ID_HELP_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 146, 62
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ ICON IDI_DROSERA,IDC_MYICON,64,10,20,20
+ CTEXT "Drosera Version 1.0",IDC_STATIC,0,37,146,8,SS_NOPREFIX
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __VERSION_MAJOR__,__BUILD_NUMBER_MAJOR__,__BUILD_NUMBER_MINOR__,__BUILD_NUMBER_VARIANT__
+ PRODUCTVERSION __VERSION_MAJOR__,__VERSION_MINOR__,__VERSION_TINY__,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "Drosera JavaScript Debugger"
+ VALUE "FileVersion", __VERSION_TEXT__
+ VALUE "CompanyName", "Apple Inc."
+ VALUE "InternalName", "Drosera"
+ VALUE "LegalCopyright", "Copyright Apple Inc. 2006-2008"
+ VALUE "OriginalFilename", "Drosera.exe"
+ VALUE "ProductName", "Drosera"
+ VALUE "ProductVersion", __VERSION_TEXT__
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_APP_TITLE "Drosera"
+ IDC_DROSERA "DROSERA"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/WebKitTools/Drosera/win/Drosera.vcproj/Drosera.vcproj b/WebKitTools/Drosera/win/Drosera.vcproj/Drosera.vcproj new file mode 100755 index 0000000..3f72dda --- /dev/null +++ b/WebKitTools/Drosera/win/Drosera.vcproj/Drosera.vcproj @@ -0,0 +1,449 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="Drosera"
+ ProjectGUID="{91671475-2114-4D8F-A051-9A1B270F6467}"
+ RootNamespace="Drosera"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)";"$(ProjectDir)\..";"$(ProjectDir)\..\..";"$(ProjectDir)\..\..\ForwardingHeaders";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\JavaScriptCore";"$(IntDir)\include""
+ PreprocessorDefinitions="STRICT;__APPLICATION_NAME__=\"$(ProjectName)\""
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="DroseraPrefix.h"
+ ForcedIncludeFiles="DroseraPrefix.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG;__APPLICATION_NAME__=\"$(ProjectName)\""
+ Culture="1033"
+ AdditionalIncludeDirectories=""$(IntDir)\include""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="false"
+ AdditionalDependencies="CoreFoundation$(LibraryConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib WebKitGUID$(WebKitConfigSuffix).lib WTF$(WebKitConfigSuffix).lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""$(WebKitOutputDir)\lib";"$(WebKitLibrariesDir)\lib""
+ IgnoreAllDefaultLibraries="false"
+ EmbedManagedResourceFile=""
+ DelayLoadDLLs=""
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ LinkTimeCodeGeneration="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin36$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin36$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc36$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc36$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

mkdir 2>NUL "$(OutDir)\$(ProjectName).resources"
xcopy /y /d "$(ProjectDir)..\Info.plist" "$(OutDir)\$(ProjectName).resources"

mkdir 2>NUL "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.css" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.html" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.js" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\Images\*" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/EHsc"
+ AdditionalIncludeDirectories=""$(ProjectDir)";"$(ProjectDir)\..";"$(ProjectDir)\..\..";"$(ProjectDir)\..\..\ForwardingHeaders";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\JavaScriptCore";"$(IntDir)\include""
+ PreprocessorDefinitions="STRICT;__APPLICATION_NAME__=\"$(ProjectName)\""
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="DroseraPrefix.h"
+ ForcedIncludeFiles="DroseraPrefix.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG;__APPLICATION_NAME__=\"$(ProjectName)\""
+ Culture="1033"
+ AdditionalIncludeDirectories=""$(IntDir)\include""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="false"
+ AdditionalDependencies="CoreFoundation$(LibraryConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib WebKitGUID$(WebKitConfigSuffix).lib WTF$(WebKitConfigSuffix).lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""$(WebKitOutputDir)\lib";"$(WebKitLibrariesDir)\lib""
+ DelayLoadDLLs=""
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="0"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin36$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin36$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc36$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc36$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

mkdir 2>NUL "$(OutDir)\$(ProjectName).resources"
xcopy /y /d "$(ProjectDir)..\Info.plist" "$(OutDir)\$(ProjectName).resources"

mkdir 2>NUL "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.css" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.html" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.js" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\Images\*" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_Internal|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)";"$(ProjectDir)\..";"$(ProjectDir)\..\..";"$(ProjectDir)\..\..\ForwardingHeaders";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\JavaScriptCore";"$(IntDir)\include""
+ PreprocessorDefinitions="STRICT;__APPLICATION_NAME__=\"$(ProjectName)\""
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderThrough="DroseraPrefix.h"
+ ForcedIncludeFiles="DroseraPrefix.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG;__APPLICATION_NAME__=\"$(ProjectName)\""
+ Culture="1033"
+ AdditionalIncludeDirectories=""$(IntDir)\include""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="false"
+ AdditionalDependencies="CoreFoundation$(LibraryConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib WebKitGUID$(WebKitConfigSuffix).lib WTF$(WebKitConfigSuffix).lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories=""$(WebKitOutputDir)\lib";"$(WebKitLibrariesDir)\lib""
+ IgnoreAllDefaultLibraries="false"
+ EmbedManagedResourceFile=""
+ DelayLoadDLLs=""
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ LinkTimeCodeGeneration="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin36$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin36$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc36$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc36$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
xcopy /y /d "$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb" "$(WebKitOutputDir)\bin"

mkdir 2>NUL "$(OutDir)\$(ProjectName).resources"
xcopy /y /d "$(ProjectDir)..\Info.plist" "$(OutDir)\$(ProjectName).resources"

mkdir 2>NUL "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.css" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.html" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\*.js" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
xcopy /y /d "$(ProjectDir)..\..\Images\*" "$(OutDir)\$(ProjectName).resources\$(ProjectName)"
"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\DebuggerClient.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\DebuggerDocument.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\DebuggerDocumentPlatform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Drosera.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\DroseraPrefix.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug_Internal|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\ServerConnection.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\BaseDelegate.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\DebuggerClient.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\DebuggerDocument.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Drosera.h"
+ >
+ </File>
+ <File
+ RelativePath="..\DroseraPrefix.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ServerConnection.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath="..\..\Images\Drosera.ico"
+ >
+ </File>
+ <File
+ RelativePath=".\Drosera.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""$(InputDir)\WTL75\include";"$(IntDir)\include";"$(ProjectDir)..";"$(ProjectDir)..\..\Images""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)..";"$(ProjectDir)..\..\Images""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug_Internal|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""$(InputDir)\WTL75\include";"$(IntDir)\include";"$(ProjectDir)..";"$(ProjectDir)..\..\Images""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\resource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\Images\small.ico"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="WebSource"
+ >
+ <File
+ RelativePath="..\..\breakpointEditor.html"
+ >
+ </File>
+ <File
+ RelativePath="..\..\console.css"
+ >
+ </File>
+ <File
+ RelativePath="..\..\console.html"
+ >
+ </File>
+ <File
+ RelativePath="..\..\console.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\debugger.css"
+ >
+ </File>
+ <File
+ RelativePath="..\..\debugger.html"
+ >
+ </File>
+ <File
+ RelativePath="..\..\debugger.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\viewer.css"
+ >
+ </File>
+ <File
+ RelativePath="..\..\viewer.html"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/Drosera/win/DroseraPrefix.cpp b/WebKitTools/Drosera/win/DroseraPrefix.cpp new file mode 100644 index 0000000..39d3f80 --- /dev/null +++ b/WebKitTools/Drosera/win/DroseraPrefix.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DroseraPrefix.h" diff --git a/WebKitTools/Drosera/win/DroseraPrefix.h b/WebKitTools/Drosera/win/DroseraPrefix.h new file mode 100644 index 0000000..fe608c7 --- /dev/null +++ b/WebKitTools/Drosera/win/DroseraPrefix.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef droseraPrefix_H +#define droseraPrefix_H + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#endif + +#ifndef WIN32 +#define WIN32 1 +#endif + +#endif //droseraPrefix_H diff --git a/WebKitTools/Drosera/win/Info.plist b/WebKitTools/Drosera/win/Info.plist new file mode 100644 index 0000000..ce4a0f7 --- /dev/null +++ b/WebKitTools/Drosera/win/Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>Drosera</string> + <key>CFBundleIconFile</key> + <string>Drosera</string> + <key>CFBundleIdentifier</key> + <string>org.webkit.drosera</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>21081</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/WebKitTools/Drosera/win/ServerConnection.cpp b/WebKitTools/Drosera/win/ServerConnection.cpp new file mode 100644 index 0000000..de2b416 --- /dev/null +++ b/WebKitTools/Drosera/win/ServerConnection.cpp @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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. + */ + +#include "config.h" +#include "ServerConnection.h" + +#include "DebuggerDocument.h" + +#include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/JSStringRefBSTR.h> +#include <JavaScriptCore/RetainPtr.h> +#include <WebKit/ForEachCoClass.h> +#include <WebKit/WebKit.h> + +#include <iostream> + +ServerConnection::ServerConnection() + : m_globalContext(0) + , m_serverConnected(false) +{ + OleInitialize(0); + attemptToCreateServerConnection(); +} + +ServerConnection::~ServerConnection() +{ + if (m_server) + m_server->removeListener(this); + + if (m_globalContext) + JSGlobalContextRelease(m_globalContext); +} + +void ServerConnection::attemptToCreateServerConnection(JSGlobalContextRef globalContextRef) +{ + COMPtr<IWebScriptDebugServer> tempServer; + + CLSID clsid = CLSID_NULL; + if (FAILED(CLSIDFromProgID(PROGID(WebScriptDebugServer), &clsid))) + return; + + if (FAILED(CoCreateInstance(clsid, 0, CLSCTX_LOCAL_SERVER, IID_IWebScriptDebugServer, (void**)&tempServer))) + return; + + if (FAILED(tempServer->sharedWebScriptDebugServer(&m_server))) + return; + + if (FAILED(m_server->addListener(this))) { + m_server = 0; + return; + } + + m_serverConnected = true; + + if (globalContextRef) + m_globalContext = JSGlobalContextRetain(globalContextRef); +} + +void ServerConnection::setGlobalContext(JSGlobalContextRef globalContextRef) +{ + m_globalContext = JSGlobalContextRetain(globalContextRef); +} + +// Pause & Step + +void ServerConnection::pause() +{ + if (m_server) + m_server->pause(); +} + +void ServerConnection::resume() +{ + if (m_server) + m_server->resume(); +} + +void ServerConnection::stepInto() +{ + if (m_server) + m_server->step(); +} + +// IUnknown -------------------------------------------------- +HRESULT STDMETHODCALLTYPE ServerConnection::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = this; + else if (IsEqualGUID(riid, IID_IWebScriptDebugListener)) + *ppvObject = static_cast<IWebScriptDebugListener*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE ServerConnection::AddRef(void) +{ + // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView. + return 1; +} + +ULONG STDMETHODCALLTYPE ServerConnection::Release(void) +{ + // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView. + return 1; +} +// IWebScriptDebugListener ----------------------------------- +HRESULT STDMETHODCALLTYPE ServerConnection::didLoadMainResourceForDataSource( + /* [in] */ IWebView*, + /* [in] */ IWebDataSource* dataSource) +{ + HRESULT ret = S_OK; + if (!m_globalContext || !dataSource) + return ret; + + // Get document source + COMPtr<IWebDocumentRepresentation> rep; + ret = dataSource->representation(&rep); + if (FAILED(ret)) + return ret; + + BOOL canProvideDocumentSource = FALSE; + ret = rep->canProvideDocumentSource(&canProvideDocumentSource); + if (FAILED(ret)) + return ret; + + BSTR documentSource = 0; + if (canProvideDocumentSource) + ret = rep->documentSource(&documentSource); + + if (FAILED(ret) || !documentSource) + return ret; + + JSRetainPtr<JSStringRef> documentSourceJS(Adopt, JSStringCreateWithBSTR(documentSource)); + SysFreeString(documentSource); + + // Get URL + COMPtr<IWebURLResponse> response; + ret = dataSource->response(&response); + if (FAILED(ret)) + return ret; + + BSTR url = 0; + ret = response->URL(&url); + if (FAILED(ret)) + return ret; + + JSRetainPtr<JSStringRef> urlJS(Adopt, JSStringCreateWithBSTR(url)); + SysFreeString(url); + + DebuggerDocument::updateFileSource(m_globalContext, documentSourceJS.get(), urlJS.get()); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ServerConnection::didParseSource( + /* [in] */ IWebView*, + /* [in] */ BSTR sourceCode, + /* [in] */ UINT baseLineNumber, + /* [in] */ BSTR url, + /* [in] */ int sourceID, + /* [in] */ IWebFrame* webFrame) +{ + HRESULT ret = S_OK; + if (!m_globalContext || !sourceCode) + return ret; + + COMPtr<IWebDataSource> dataSource; + ret = webFrame->dataSource(&dataSource); + if (FAILED(ret)) + return ret; + + COMPtr<IWebURLResponse> response; + ret = dataSource->response(&response); + if (FAILED(ret)) + return ret; + + BSTR responseURL; + ret = response->URL(&responseURL); + if (FAILED(ret)) + return ret; + + BSTR documentSource = 0; + if (!url || !wcscmp(responseURL, url)) { + COMPtr<IWebDocumentRepresentation> rep; + ret = dataSource->representation(&rep); + if (FAILED(ret)) + return ret; + + BOOL canProvideDocumentSource; + rep->canProvideDocumentSource(&canProvideDocumentSource); + if (FAILED(ret)) + return ret; + + if (canProvideDocumentSource) { + ret = rep->documentSource(&documentSource); + if (FAILED(ret)) + return ret; + } + + if (!url) { + ret = response->URL(&url); + if (FAILED(ret)) + return ret; + } + } + SysFreeString(responseURL); + + JSRetainPtr<JSStringRef> sourceJS(Adopt, JSStringCreateWithBSTR(sourceCode)); + JSRetainPtr<JSStringRef> documentSourceJS(Adopt, JSStringCreateWithBSTR(documentSource)); + SysFreeString(documentSource); + JSRetainPtr<JSStringRef> urlJS(Adopt, JSStringCreateWithBSTR(url)); + JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID); + JSValueRef baseLineJS = JSValueMakeNumber(m_globalContext, baseLineNumber); + + DebuggerDocument::didParseScript(m_globalContext, sourceJS.get(), documentSourceJS.get(), urlJS.get(), sidJS, baseLineJS); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ServerConnection::failedToParseSource( + /* [in] */ IWebView*, + /* [in] */ BSTR, + /* [in] */ UINT, + /* [in] */ BSTR, + /* [in] */ BSTR, + /* [in] */ IWebFrame*) +{ + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ServerConnection::didEnterCallFrame( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame* frame, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*) +{ + HRESULT ret = S_OK; + if (!m_globalContext) + return ret; + + m_currentFrame = frame; + + JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID); + JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber); + + DebuggerDocument::didEnterCallFrame(m_globalContext, sidJS, linenoJS); + + return ret; +} + +HRESULT STDMETHODCALLTYPE ServerConnection::willExecuteStatement( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame*, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*) +{ + HRESULT ret = S_OK; + if (!m_globalContext) + return ret; + + JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID); + JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber); + + DebuggerDocument::willExecuteStatement(m_globalContext, sidJS, linenoJS); + return ret; +} + +HRESULT STDMETHODCALLTYPE ServerConnection::willLeaveCallFrame( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame* frame, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*) +{ + HRESULT ret = S_OK; + if (!m_globalContext) + return ret; + + JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID); + JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber); + + DebuggerDocument::willLeaveCallFrame(m_globalContext, sidJS, linenoJS); + + m_currentFrame = frame; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ServerConnection::exceptionWasRaised( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame*, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*) +{ + HRESULT ret = S_OK; + if (!m_globalContext) + return ret; + + JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID); + JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber); + + DebuggerDocument::exceptionWasRaised(m_globalContext, sidJS, linenoJS); + + return ret; +} + +HRESULT STDMETHODCALLTYPE ServerConnection::serverDidDie() +{ + m_server = 0; + m_currentFrame = 0; + m_serverConnected = false; + return S_OK; +} + +// Stack & Variables + +IWebScriptCallFrame* ServerConnection::currentFrame() const +{ + return m_currentFrame.get(); +} + +COMPtr<IWebScriptCallFrame> ServerConnection::getCallerFrame(int callFrame) const +{ + COMPtr<IWebScriptCallFrame> cframe = currentFrame(); + for (int count = 0; count < callFrame; count++) { + COMPtr<IWebScriptCallFrame> callerFrame; + if (FAILED(cframe->caller(&callerFrame))) + return 0; + + cframe = callerFrame; + } + + return cframe; +} diff --git a/WebKitTools/Drosera/win/ServerConnection.h b/WebKitTools/Drosera/win/ServerConnection.h new file mode 100644 index 0000000..c0b64cf --- /dev/null +++ b/WebKitTools/Drosera/win/ServerConnection.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com) + * + * 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. + */ + +#ifndef ServerConnection_H +#define ServerConnection_H + +#include <string> +#include <WebCore/COMPtr.h> +#include <WebKit/WebKit.h> + +class DebuggerClient; +interface IWebScriptCallFrame; +interface IWebScriptDebugServer; + +typedef struct OpaqueJSContext* JSGlobalContextRef; + +class ServerConnection : public IWebScriptDebugListener { +public: + ServerConnection(); + ~ServerConnection(); + + bool serverConnected() const { return m_serverConnected; } + void attemptToCreateServerConnection(JSGlobalContextRef = 0); + void setGlobalContext(JSGlobalContextRef); + + // Pause & Step + void pause(); + void resume(); + void stepInto(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [retval][out] */ void** ppvObject); + + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + + // IWebScriptDebugListener + virtual HRESULT STDMETHODCALLTYPE didLoadMainResourceForDataSource( + /* [in] */ IWebView*, + /* [in] */ IWebDataSource* dataSource); + + virtual HRESULT STDMETHODCALLTYPE didParseSource( + /* [in] */ IWebView*, + /* [in] */ BSTR sourceCode, + /* [in] */ UINT baseLineNumber, + /* [in] */ BSTR url, + /* [in] */ int sourceID, + /* [in] */ IWebFrame* webFrame); + + virtual HRESULT STDMETHODCALLTYPE failedToParseSource( + /* [in] */ IWebView*, + /* [in] */ BSTR sourceCode, + /* [in] */ UINT baseLineNumber, + /* [in] */ BSTR url, + /* [in] */ BSTR error, + /* [in] */ IWebFrame*); + + virtual HRESULT STDMETHODCALLTYPE didEnterCallFrame( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame* frame, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*); + + virtual HRESULT STDMETHODCALLTYPE willExecuteStatement( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame*, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*); + + virtual HRESULT STDMETHODCALLTYPE willLeaveCallFrame( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame* frame, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*); + + virtual HRESULT STDMETHODCALLTYPE exceptionWasRaised( + /* [in] */ IWebView*, + /* [in] */ IWebScriptCallFrame*, + /* [in] */ int sourceID, + /* [in] */ int lineNumber, + /* [in] */ IWebFrame*); + + virtual HRESULT STDMETHODCALLTYPE serverDidDie(); + + // Stack & Variables + IWebScriptCallFrame* currentFrame() const; + COMPtr<IWebScriptCallFrame> getCallerFrame(int callFrame) const; + +private: + bool m_serverConnected; + + COMPtr<IWebScriptCallFrame> m_currentFrame; + COMPtr<IWebScriptDebugServer> m_server; + JSGlobalContextRef m_globalContext; +}; + +#endif //ServerConnection_H diff --git a/WebKitTools/Drosera/win/resource.h b/WebKitTools/Drosera/win/resource.h new file mode 100644 index 0000000..4ba014e --- /dev/null +++ b/WebKitTools/Drosera/win/resource.h @@ -0,0 +1,47 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Drosera.rc +// +#define IDC_MYICON 2 +#define IDS_APP_TITLE 103 +#define IDD_ABOUTBOX 103 +#define IDI_DROSERA 107 +#define IDI_SMALL 108 +#define IDC_DROSERA 109 +#define IDC_LIST1 1001 +#define ID_DEBUG_SHOWCONSOLE 32771 +#define ID_DEBUG_CONTINUE 32772 +#define ID_DEBUG_PAUSE 32773 +#define ID_DEBUG_STEPINTO 32774 +#define ID_DEBUG_STEPOVER 32775 +#define ID_DEBUG_STEPOUT 32776 +#define ID_EDIT_UNDO 32777 +#define ID_EDIT_REDO 32778 +#define ID_EDIT_CUT 32779 +#define ID_EDIT_COPY 32780 +#define ID_EDIT_PASTE 32781 +#define ID_EDIT_SELECTALL 32782 +#define ID_FIND_FIND 32784 +#define ID_FIND_FINDNEXT 32785 +#define ID_FIND_FINDPREVIOUS 32786 +#define ID_FIND_USESELECTIONFORFIND 32787 +#define ID_FIND_JUMPTOSELECTION 32788 +#define ID_EDIT_SPECIALCHARACTERS 32789 +#define ID_FILE_EXIT 32791 +#define ID_WINDOW 32793 +#define ID_HELP_ABOUT 32794 +#define ID_FILE_CLOSE_CURRENT_FILE 32795 +#define ID_FILE_CLOSECURRENTFILE 32798 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 131 +#define _APS_NEXT_COMMAND_VALUE 32799 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.h b/WebKitTools/DumpRenderTree/DumpRenderTree.h new file mode 100644 index 0000000..e74d4bc --- /dev/null +++ b/WebKitTools/DumpRenderTree/DumpRenderTree.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +#ifndef DumpRenderTree_h +#define DumpRenderTree_h + +#include <wtf/Platform.h> + +#if PLATFORM(MAC) +#include "DumpRenderTreeMac.h" +#elif PLATFORM(WIN) +#include "DumpRenderTreeWin.h" +#elif PLATFORM(GTK) +#include "DumpRenderTreeGtk.h" +#endif + +#if PLATFORM(CF) +#include <CoreFoundation/CoreFoundation.h> +extern CFRunLoopTimerRef waitToDumpWatchdog; +#endif + +#include <string> + +std::wstring urlSuitableForTestResult(const std::wstring& url); + +class LayoutTestController; + +extern volatile bool done; + +// FIXME: This is a bad abstraction. We should insted pass this to other controller objects which need access to it. +extern LayoutTestController* layoutTestController; + +void dump(); +void displayWebView(); + +#endif // DumpRenderTree_h diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.sln b/WebKitTools/DumpRenderTree/DumpRenderTree.sln new file mode 100644 index 0000000..5a6a35f --- /dev/null +++ b/WebKitTools/DumpRenderTree/DumpRenderTree.sln @@ -0,0 +1,47 @@ +
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DumpRenderTree", "win\DumpRenderTree.vcproj", "{6567DFD4-D6DE-4CD5-825D-17E353D160E1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestNetscapePlugin", "win\TestNetscapePlugin\TestNetscapePlugin.vcproj", "{C0737398-3565-439E-A2B8-AB2BE4D5430C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindSafari", "..\FindSafari\FindSafari.vcproj", "{DA31DA52-6675-48D4-89E0-333A7144397C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiff", "win\ImageDiff.vcproj", "{59CC0547-70AC-499C-9B19-EC01C6F61137}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug_Internal|Win32 = Debug_Internal|Win32
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_Internal|Win32.ActiveCfg = Debug_Internal|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_Internal|Win32.Build.0 = Debug_Internal|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug|Win32.Build.0 = Debug|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Release|Win32.ActiveCfg = Release|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Release|Win32.Build.0 = Release|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_Internal|Win32.ActiveCfg = Debug_Internal|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_Internal|Win32.Build.0 = Debug_Internal|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.Build.0 = Debug|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.ActiveCfg = Release|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.Build.0 = Release|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug_Internal|Win32.ActiveCfg = Debug|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug_Internal|Win32.Build.0 = Debug|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug|Win32.Build.0 = Debug|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Release|Win32.ActiveCfg = Release|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Release|Win32.Build.0 = Release|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_Internal|Win32.ActiveCfg = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_Internal|Win32.Build.0 = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.ActiveCfg = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.Build.0 = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.ActiveCfg = Release|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj b/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1a59f19 --- /dev/null +++ b/WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj @@ -0,0 +1,752 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXAggregateTarget section */ + A84F608D08B1370600E9745F /* All */ = { + isa = PBXAggregateTarget; + buildConfigurationList = A84F609208B1371400E9745F /* Build configuration list for PBXAggregateTarget "All" */; + buildPhases = ( + ); + dependencies = ( + A84F609108B1370E00E9745F /* PBXTargetDependency */, + A84F608F08B1370E00E9745F /* PBXTargetDependency */, + 141BF238096A451E00E0753C /* PBXTargetDependency */, + ); + name = All; + productName = All; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 141BF435096A455900E0753C /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9335435F03D75502008635CE /* WebKit.framework */; }; + 141BF436096A455900E0753C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A84F608908B136DA00E9745F /* Cocoa.framework */; }; + 141BF438096A455900E0753C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A817090308B164D300CCB9FB /* JavaScriptCore.framework */; }; + 141BF439096A455900E0753C /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AE8257EF08D22389000507AB /* Carbon.framework */; }; + 141BF44C096A45C800E0753C /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 141BF448096A45C800E0753C /* Info.plist */; }; + 141BF453096A45EB00E0753C /* PluginObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 141BF447096A45C800E0753C /* PluginObject.h */; }; + 14770FE20A22ADF7009342EE /* GCController.h in Headers */ = {isa = PBXBuildFile; fileRef = 14770FE00A22ADF7009342EE /* GCController.h */; }; + 1A8F02E80BB9B4EC008CFA34 /* TestObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8F024C0BB9B056008CFA34 /* TestObject.h */; }; + 1AC6C8490D07638600CD3161 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC6C77F0D07589B00CD3161 /* main.cpp */; }; + 1AC6C84A0D07638600CD3161 /* PluginObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC6C7800D07589B00CD3161 /* PluginObject.cpp */; }; + 1AC6C84B0D07638600CD3161 /* TestObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AC6C7810D07589B00CD3161 /* TestObject.cpp */; }; + 9340994C08540CAE007F3BC8 /* DumpRenderTreePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */; }; + 9340995108540CAE007F3BC8 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9335435F03D75502008635CE /* WebKit.framework */; }; + A817090008B163EF00CCB9FB /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A84F608908B136DA00E9745F /* Cocoa.framework */; }; + A817090408B164D300CCB9FB /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A817090308B164D300CCB9FB /* JavaScriptCore.framework */; }; + A84F608A08B136DA00E9745F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A84F608908B136DA00E9745F /* Cocoa.framework */; }; + A8B91ADA0CF3B32F008F91FF /* DumpRenderTreePasteboard.m in Sources */ = {isa = PBXBuildFile; fileRef = A8B91AD70CF3B32F008F91FF /* DumpRenderTreePasteboard.m */; }; + A8B91ADC0CF3B32F008F91FF /* DumpRenderTreeWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8B91AD90CF3B32F008F91FF /* DumpRenderTreeWindow.mm */; }; + A8B91AE00CF3B372008F91FF /* DumpRenderTreeWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91ADD0CF3B372008F91FF /* DumpRenderTreeWindow.h */; }; + A8B91AE20CF3B372008F91FF /* DumpRenderTreePasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91ADF0CF3B372008F91FF /* DumpRenderTreePasteboard.h */; }; + A8B91BFD0CF522B4008F91FF /* CheckedMalloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8B91BF70CF522B4008F91FF /* CheckedMalloc.cpp */; }; + A8B91BFF0CF522B4008F91FF /* CheckedMalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91BF90CF522B4008F91FF /* CheckedMalloc.h */; }; + AE8259F308D22463000507AB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AE8257EF08D22389000507AB /* Carbon.framework */; }; + AE8259F408D22463000507AB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AE8257EF08D22389000507AB /* Carbon.framework */; }; + B5A752A208AF5D1F00138E45 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A752A108AF5D1F00138E45 /* QuartzCore.framework */; }; + BC0131DA0C9772010087317D /* LayoutTestController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0131D80C9772010087317D /* LayoutTestController.cpp */; }; + BC0131DB0C9772010087317D /* LayoutTestController.h in Headers */ = {isa = PBXBuildFile; fileRef = BC0131D90C9772010087317D /* LayoutTestController.h */; }; + BC47412A0D038A4C0072B006 /* JavaScriptThreading.h in Headers */ = {isa = PBXBuildFile; fileRef = BC4741290D038A4C0072B006 /* JavaScriptThreading.h */; }; + BC4741410D038A570072B006 /* JavaScriptThreadingPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC4741400D038A570072B006 /* JavaScriptThreadingPthreads.cpp */; }; + BC9D90240C97472E0099A4A3 /* WorkQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC9D90210C97472D0099A4A3 /* WorkQueue.cpp */; }; + BC9D90250C97472E0099A4A3 /* WorkQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9D90220C97472E0099A4A3 /* WorkQueue.h */; }; + BC9D90260C97472E0099A4A3 /* WorkQueueItem.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9D90230C97472E0099A4A3 /* WorkQueueItem.h */; }; + BCA18B230C9B014B00114369 /* GCControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B210C9B014B00114369 /* GCControllerMac.mm */; }; + BCA18B240C9B014B00114369 /* LayoutTestControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B220C9B014B00114369 /* LayoutTestControllerMac.mm */; }; + BCA18B260C9B015C00114369 /* WorkQueueItemMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B250C9B015C00114369 /* WorkQueueItemMac.mm */; }; + BCA18B310C9B01B400114369 /* ObjCController.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B2F0C9B01B400114369 /* ObjCController.h */; }; + BCA18B320C9B01B400114369 /* ObjCController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B300C9B01B400114369 /* ObjCController.m */; }; + BCA18B380C9B021900114369 /* AppleScriptController.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B360C9B021900114369 /* AppleScriptController.h */; }; + BCA18B390C9B021900114369 /* AppleScriptController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B370C9B021900114369 /* AppleScriptController.m */; }; + BCA18B3C0C9B024900114369 /* TextInputController.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B3A0C9B024900114369 /* TextInputController.h */; }; + BCA18B490C9B02C400114369 /* TextInputController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B480C9B02C400114369 /* TextInputController.m */; }; + BCA18B610C9B08C200114369 /* EditingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B570C9B08C200114369 /* EditingDelegate.h */; }; + BCA18B620C9B08C200114369 /* EditingDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B580C9B08C200114369 /* EditingDelegate.mm */; }; + BCA18B630C9B08C200114369 /* FrameLoadDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B590C9B08C200114369 /* FrameLoadDelegate.h */; }; + BCA18B640C9B08C200114369 /* FrameLoadDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B5A0C9B08C200114369 /* FrameLoadDelegate.mm */; }; + BCA18B650C9B08C200114369 /* PolicyDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B5B0C9B08C200114369 /* PolicyDelegate.h */; }; + BCA18B660C9B08C200114369 /* PolicyDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B5C0C9B08C200114369 /* PolicyDelegate.mm */; }; + BCA18B670C9B08C200114369 /* ResourceLoadDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B5D0C9B08C200114369 /* ResourceLoadDelegate.h */; }; + BCA18B680C9B08C200114369 /* ResourceLoadDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B5E0C9B08C200114369 /* ResourceLoadDelegate.mm */; }; + BCA18B690C9B08C200114369 /* UIDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B5F0C9B08C200114369 /* UIDelegate.h */; }; + BCA18B6A0C9B08C200114369 /* UIDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B600C9B08C200114369 /* UIDelegate.mm */; }; + BCA18B6F0C9B08DB00114369 /* EventSendingController.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B6B0C9B08DB00114369 /* EventSendingController.h */; }; + BCA18B700C9B08DB00114369 /* EventSendingController.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B6C0C9B08DB00114369 /* EventSendingController.mm */; }; + BCA18B710C9B08DB00114369 /* NavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B6D0C9B08DB00114369 /* NavigationController.h */; }; + BCA18B720C9B08DB00114369 /* NavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B6E0C9B08DB00114369 /* NavigationController.m */; }; + BCA18B7A0C9B08F100114369 /* DumpRenderTreeDraggingInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B730C9B08F100114369 /* DumpRenderTreeDraggingInfo.h */; }; + BCA18B7B0C9B08F100114369 /* DumpRenderTreeDraggingInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B740C9B08F100114369 /* DumpRenderTreeDraggingInfo.mm */; }; + BCA18B7D0C9B08F100114369 /* ObjCPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B760C9B08F100114369 /* ObjCPlugin.h */; }; + BCA18B7E0C9B08F100114369 /* ObjCPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B770C9B08F100114369 /* ObjCPlugin.m */; }; + BCA18B7F0C9B08F100114369 /* ObjCPluginFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18B780C9B08F100114369 /* ObjCPluginFunction.h */; }; + BCA18B800C9B08F100114369 /* ObjCPluginFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA18B790C9B08F100114369 /* ObjCPluginFunction.m */; }; + BCA18C0B0C9B59EF00114369 /* DumpRenderTreeMac.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA18C0A0C9B59EF00114369 /* DumpRenderTreeMac.h */; }; + BCA18C470C9B5B9400114369 /* DumpRenderTree.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCA18C460C9B5B9400114369 /* DumpRenderTree.mm */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; }; + BCB284C70CFA83C4007E533E /* PixelDumpSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB2848A0CFA820F007E533E /* PixelDumpSupport.h */; }; + BCB284CD0CFA83C8007E533E /* PixelDumpSupportCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCB284880CFA8202007E533E /* PixelDumpSupportCG.cpp */; }; + BCB284D00CFA83CC007E533E /* PixelDumpSupportCG.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB284890CFA8202007E533E /* PixelDumpSupportCG.h */; }; + BCB284D60CFA83D1007E533E /* PixelDumpSupportMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCB2848C0CFA8221007E533E /* PixelDumpSupportMac.mm */; }; + BCB284F60CFA84F8007E533E /* ImageDiffCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCB284F30CFA84F2007E533E /* ImageDiffCG.cpp */; }; + BCF6C6500C98E9C000AC063E /* GCController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCF6C64F0C98E9C000AC063E /* GCController.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 141BF237096A451E00E0753C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 141BF21E096A441D00E0753C; + remoteInfo = TestNetscapePlugIn; + }; + A84F608E08B1370E00E9745F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B5A7525A08AF4A4A00138E45; + remoteInfo = ImageDiff; + }; + A84F609008B1370E00E9745F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9340994A08540CAE007F3BC8; + remoteInfo = DumpRenderTree; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 141BF233096A44CF00E0753C /* TestNetscapePlugIn.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestNetscapePlugIn.plugin; sourceTree = BUILT_PRODUCTS_DIR; }; + 141BF447096A45C800E0753C /* PluginObject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PluginObject.h; sourceTree = "<group>"; }; + 141BF448096A45C800E0753C /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; }; + 14770FE00A22ADF7009342EE /* GCController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCController.h; sourceTree = "<group>"; }; + 1A8F024C0BB9B056008CFA34 /* TestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObject.h; sourceTree = "<group>"; }; + 1AC6C77F0D07589B00CD3161 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; }; + 1AC6C7800D07589B00CD3161 /* PluginObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginObject.cpp; sourceTree = "<group>"; }; + 1AC6C7810D07589B00CD3161 /* TestObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestObject.cpp; sourceTree = "<group>"; }; + 32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DumpRenderTreePrefix.h; sourceTree = "<group>"; }; + 9335435F03D75502008635CE /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9340995408540CAF007F3BC8 /* DumpRenderTree */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = DumpRenderTree; sourceTree = BUILT_PRODUCTS_DIR; }; + A803FF7409CAAD08009B2A37 /* DumpRenderTree.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = DumpRenderTree.h; sourceTree = "<group>"; }; + A817090308B164D300CCB9FB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JavaScriptCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A84F608908B136DA00E9745F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; + A8B91AD70CF3B32F008F91FF /* DumpRenderTreePasteboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DumpRenderTreePasteboard.m; path = mac/DumpRenderTreePasteboard.m; sourceTree = "<group>"; }; + A8B91AD90CF3B32F008F91FF /* DumpRenderTreeWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = DumpRenderTreeWindow.mm; path = mac/DumpRenderTreeWindow.mm; sourceTree = "<group>"; }; + A8B91ADD0CF3B372008F91FF /* DumpRenderTreeWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DumpRenderTreeWindow.h; path = mac/DumpRenderTreeWindow.h; sourceTree = "<group>"; }; + A8B91ADF0CF3B372008F91FF /* DumpRenderTreePasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DumpRenderTreePasteboard.h; path = mac/DumpRenderTreePasteboard.h; sourceTree = "<group>"; }; + A8B91BF70CF522B4008F91FF /* CheckedMalloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckedMalloc.cpp; path = mac/CheckedMalloc.cpp; sourceTree = "<group>"; }; + A8B91BF90CF522B4008F91FF /* CheckedMalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CheckedMalloc.h; path = mac/CheckedMalloc.h; sourceTree = "<group>"; }; + AA7F10C20CB3C1030003BDC9 /* AHEM____.TTF */ = {isa = PBXFileReference; lastKnownFileType = file; name = "AHEM____.TTF"; path = "qt/fonts/AHEM____.TTF"; sourceTree = "<group>"; }; + AE8257EF08D22389000507AB /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; }; + B5A7526708AF4A4A00138E45 /* ImageDiff */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ImageDiff; sourceTree = BUILT_PRODUCTS_DIR; }; + B5A752A108AF5D1F00138E45 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = "<absolute>"; }; + BC0131D80C9772010087317D /* LayoutTestController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; path = LayoutTestController.cpp; sourceTree = "<group>"; }; + BC0131D90C9772010087317D /* LayoutTestController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LayoutTestController.h; sourceTree = "<group>"; }; + BC4741290D038A4C0072B006 /* JavaScriptThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptThreading.h; sourceTree = "<group>"; }; + BC4741400D038A570072B006 /* JavaScriptThreadingPthreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaScriptThreadingPthreads.cpp; path = pthreads/JavaScriptThreadingPthreads.cpp; sourceTree = "<group>"; }; + BC9D90210C97472D0099A4A3 /* WorkQueue.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; path = WorkQueue.cpp; sourceTree = "<group>"; }; + BC9D90220C97472E0099A4A3 /* WorkQueue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WorkQueue.h; sourceTree = "<group>"; }; + BC9D90230C97472E0099A4A3 /* WorkQueueItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WorkQueueItem.h; sourceTree = "<group>"; }; + BCA18B210C9B014B00114369 /* GCControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = GCControllerMac.mm; path = mac/GCControllerMac.mm; sourceTree = "<group>"; }; + BCA18B220C9B014B00114369 /* LayoutTestControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = LayoutTestControllerMac.mm; path = mac/LayoutTestControllerMac.mm; sourceTree = "<group>"; }; + BCA18B250C9B015C00114369 /* WorkQueueItemMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = WorkQueueItemMac.mm; path = mac/WorkQueueItemMac.mm; sourceTree = "<group>"; }; + BCA18B2F0C9B01B400114369 /* ObjCController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ObjCController.h; path = mac/ObjCController.h; sourceTree = "<group>"; }; + BCA18B300C9B01B400114369 /* ObjCController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ObjCController.m; path = mac/ObjCController.m; sourceTree = "<group>"; }; + BCA18B360C9B021900114369 /* AppleScriptController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AppleScriptController.h; path = mac/AppleScriptController.h; sourceTree = "<group>"; }; + BCA18B370C9B021900114369 /* AppleScriptController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = AppleScriptController.m; path = mac/AppleScriptController.m; sourceTree = "<group>"; }; + BCA18B3A0C9B024900114369 /* TextInputController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = TextInputController.h; path = mac/TextInputController.h; sourceTree = "<group>"; }; + BCA18B480C9B02C400114369 /* TextInputController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = TextInputController.m; path = mac/TextInputController.m; sourceTree = "<group>"; }; + BCA18B570C9B08C200114369 /* EditingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = EditingDelegate.h; path = mac/EditingDelegate.h; sourceTree = "<group>"; }; + BCA18B580C9B08C200114369 /* EditingDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = EditingDelegate.mm; path = mac/EditingDelegate.mm; sourceTree = "<group>"; }; + BCA18B590C9B08C200114369 /* FrameLoadDelegate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FrameLoadDelegate.h; path = mac/FrameLoadDelegate.h; sourceTree = "<group>"; }; + BCA18B5A0C9B08C200114369 /* FrameLoadDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = FrameLoadDelegate.mm; path = mac/FrameLoadDelegate.mm; sourceTree = "<group>"; }; + BCA18B5B0C9B08C200114369 /* PolicyDelegate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PolicyDelegate.h; path = mac/PolicyDelegate.h; sourceTree = "<group>"; }; + BCA18B5C0C9B08C200114369 /* PolicyDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = PolicyDelegate.mm; path = mac/PolicyDelegate.mm; sourceTree = "<group>"; }; + BCA18B5D0C9B08C200114369 /* ResourceLoadDelegate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ResourceLoadDelegate.h; path = mac/ResourceLoadDelegate.h; sourceTree = "<group>"; }; + BCA18B5E0C9B08C200114369 /* ResourceLoadDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = ResourceLoadDelegate.mm; path = mac/ResourceLoadDelegate.mm; sourceTree = "<group>"; }; + BCA18B5F0C9B08C200114369 /* UIDelegate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = UIDelegate.h; path = mac/UIDelegate.h; sourceTree = "<group>"; }; + BCA18B600C9B08C200114369 /* UIDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = UIDelegate.mm; path = mac/UIDelegate.mm; sourceTree = "<group>"; }; + BCA18B6B0C9B08DB00114369 /* EventSendingController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = EventSendingController.h; path = mac/EventSendingController.h; sourceTree = "<group>"; }; + BCA18B6C0C9B08DB00114369 /* EventSendingController.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = EventSendingController.mm; path = mac/EventSendingController.mm; sourceTree = "<group>"; }; + BCA18B6D0C9B08DB00114369 /* NavigationController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = NavigationController.h; path = mac/NavigationController.h; sourceTree = "<group>"; }; + BCA18B6E0C9B08DB00114369 /* NavigationController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = NavigationController.m; path = mac/NavigationController.m; sourceTree = "<group>"; }; + BCA18B730C9B08F100114369 /* DumpRenderTreeDraggingInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DumpRenderTreeDraggingInfo.h; path = mac/DumpRenderTreeDraggingInfo.h; sourceTree = "<group>"; }; + BCA18B740C9B08F100114369 /* DumpRenderTreeDraggingInfo.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = DumpRenderTreeDraggingInfo.mm; path = mac/DumpRenderTreeDraggingInfo.mm; sourceTree = "<group>"; }; + BCA18B760C9B08F100114369 /* ObjCPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ObjCPlugin.h; path = mac/ObjCPlugin.h; sourceTree = "<group>"; }; + BCA18B770C9B08F100114369 /* ObjCPlugin.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ObjCPlugin.m; path = mac/ObjCPlugin.m; sourceTree = "<group>"; }; + BCA18B780C9B08F100114369 /* ObjCPluginFunction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ObjCPluginFunction.h; path = mac/ObjCPluginFunction.h; sourceTree = "<group>"; }; + BCA18B790C9B08F100114369 /* ObjCPluginFunction.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = ObjCPluginFunction.m; path = mac/ObjCPluginFunction.m; sourceTree = "<group>"; }; + BCA18C0A0C9B59EF00114369 /* DumpRenderTreeMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DumpRenderTreeMac.h; path = mac/DumpRenderTreeMac.h; sourceTree = "<group>"; }; + BCA18C460C9B5B9400114369 /* DumpRenderTree.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = DumpRenderTree.mm; path = mac/DumpRenderTree.mm; sourceTree = "<group>"; }; + BCB281EE0CFA713D007E533E /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xcconfig; name = Base.xcconfig; path = mac/Configurations/Base.xcconfig; sourceTree = "<group>"; }; + BCB281F00CFA713D007E533E /* DumpRenderTree.xcconfig */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xcconfig; name = DumpRenderTree.xcconfig; path = mac/Configurations/DumpRenderTree.xcconfig; sourceTree = "<group>"; }; + BCB282F40CFA7450007E533E /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xcconfig; name = DebugRelease.xcconfig; path = mac/Configurations/DebugRelease.xcconfig; sourceTree = "<group>"; }; + BCB283D80CFA7AFD007E533E /* ImageDiff.xcconfig */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xcconfig; name = ImageDiff.xcconfig; path = mac/Configurations/ImageDiff.xcconfig; sourceTree = "<group>"; }; + BCB283DE0CFA7C20007E533E /* TestNetscapePlugIn.xcconfig */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xcconfig; name = TestNetscapePlugIn.xcconfig; path = mac/Configurations/TestNetscapePlugIn.xcconfig; sourceTree = "<group>"; }; + BCB284880CFA8202007E533E /* PixelDumpSupportCG.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; name = PixelDumpSupportCG.cpp; path = cg/PixelDumpSupportCG.cpp; sourceTree = "<group>"; }; + BCB284890CFA8202007E533E /* PixelDumpSupportCG.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PixelDumpSupportCG.h; path = cg/PixelDumpSupportCG.h; sourceTree = "<group>"; }; + BCB2848A0CFA820F007E533E /* PixelDumpSupport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PixelDumpSupport.h; sourceTree = "<group>"; }; + BCB2848C0CFA8221007E533E /* PixelDumpSupportMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = PixelDumpSupportMac.mm; path = mac/PixelDumpSupportMac.mm; sourceTree = "<group>"; }; + BCB284B20CFA82CB007E533E /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; }; + BCB284F30CFA84F2007E533E /* ImageDiffCG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ImageDiffCG.cpp; path = cg/ImageDiffCG.cpp; sourceTree = "<group>"; }; + BCF6C64F0C98E9C000AC063E /* GCController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 30; path = GCController.cpp; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 141BF21D096A441D00E0753C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 141BF439096A455900E0753C /* Carbon.framework in Frameworks */, + 141BF436096A455900E0753C /* Cocoa.framework in Frameworks */, + 141BF438096A455900E0753C /* JavaScriptCore.framework in Frameworks */, + 141BF435096A455900E0753C /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9340994F08540CAE007F3BC8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AE8259F308D22463000507AB /* Carbon.framework in Frameworks */, + A84F608A08B136DA00E9745F /* Cocoa.framework in Frameworks */, + A817090408B164D300CCB9FB /* JavaScriptCore.framework in Frameworks */, + 9340995108540CAE007F3BC8 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B5A7525F08AF4A4A00138E45 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AE8259F408D22463000507AB /* Carbon.framework in Frameworks */, + A817090008B163EF00CCB9FB /* Cocoa.framework in Frameworks */, + B5A752A208AF5D1F00138E45 /* QuartzCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* DumpRenderTree */ = { + isa = PBXGroup; + children = ( + 32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */, + 1422A2750AF6F4BD00E1A883 /* Delegates */, + 1422A2690AF6F45200E1A883 /* Controllers */, + BCB284870CFA81ED007E533E /* PixelDump */, + A803FF7409CAAD08009B2A37 /* DumpRenderTree.h */, + BCA18C460C9B5B9400114369 /* DumpRenderTree.mm */, + A8B91BF70CF522B4008F91FF /* CheckedMalloc.cpp */, + A8B91BF90CF522B4008F91FF /* CheckedMalloc.h */, + BC4741290D038A4C0072B006 /* JavaScriptThreading.h */, + BC4741400D038A570072B006 /* JavaScriptThreadingPthreads.cpp */, + BCA18C0A0C9B59EF00114369 /* DumpRenderTreeMac.h */, + BCA18B730C9B08F100114369 /* DumpRenderTreeDraggingInfo.h */, + BCA18B740C9B08F100114369 /* DumpRenderTreeDraggingInfo.mm */, + BC9D90210C97472D0099A4A3 /* WorkQueue.cpp */, + BC9D90220C97472E0099A4A3 /* WorkQueue.h */, + BC9D90230C97472E0099A4A3 /* WorkQueueItem.h */, + A8B91AD20CF3B305008F91FF /* AppKit Overrides */, + A8B91AC40CF3B170008F91FF /* ObjCPlugin */, + 141BF1F5096A439800E0753C /* TestNetscapePlugIn.subproj */, + 9345229B0BD12B2C0086EDA0 /* Resources */, + A803FF6409CAACC1009B2A37 /* Frameworks */, + 9340995508540CAF007F3BC8 /* Products */, + BCB281ED0CFA711D007E533E /* Configurations */, + ); + name = DumpRenderTree; + sourceTree = "<group>"; + }; + 141BF1F5096A439800E0753C /* TestNetscapePlugIn.subproj */ = { + isa = PBXGroup; + children = ( + 1AC6C77F0D07589B00CD3161 /* main.cpp */, + 1AC6C7800D07589B00CD3161 /* PluginObject.cpp */, + 141BF447096A45C800E0753C /* PluginObject.h */, + 1AC6C7810D07589B00CD3161 /* TestObject.cpp */, + 1A8F024C0BB9B056008CFA34 /* TestObject.h */, + 141BF448096A45C800E0753C /* Info.plist */, + ); + path = TestNetscapePlugIn.subproj; + sourceTree = "<group>"; + }; + 1422A2690AF6F45200E1A883 /* Controllers */ = { + isa = PBXGroup; + children = ( + BCA18B360C9B021900114369 /* AppleScriptController.h */, + BCA18B370C9B021900114369 /* AppleScriptController.m */, + BCA18B6B0C9B08DB00114369 /* EventSendingController.h */, + BCA18B6C0C9B08DB00114369 /* EventSendingController.mm */, + BCF6C64F0C98E9C000AC063E /* GCController.cpp */, + 14770FE00A22ADF7009342EE /* GCController.h */, + BCA18B210C9B014B00114369 /* GCControllerMac.mm */, + BC0131D80C9772010087317D /* LayoutTestController.cpp */, + BC0131D90C9772010087317D /* LayoutTestController.h */, + BCA18B220C9B014B00114369 /* LayoutTestControllerMac.mm */, + BCA18B6D0C9B08DB00114369 /* NavigationController.h */, + BCA18B6E0C9B08DB00114369 /* NavigationController.m */, + BCA18B2F0C9B01B400114369 /* ObjCController.h */, + BCA18B300C9B01B400114369 /* ObjCController.m */, + BCA18B3A0C9B024900114369 /* TextInputController.h */, + BCA18B480C9B02C400114369 /* TextInputController.m */, + ); + name = Controllers; + sourceTree = "<group>"; + }; + 1422A2750AF6F4BD00E1A883 /* Delegates */ = { + isa = PBXGroup; + children = ( + BCA18B570C9B08C200114369 /* EditingDelegate.h */, + BCA18B580C9B08C200114369 /* EditingDelegate.mm */, + BCA18B590C9B08C200114369 /* FrameLoadDelegate.h */, + BCA18B5A0C9B08C200114369 /* FrameLoadDelegate.mm */, + BCA18B5B0C9B08C200114369 /* PolicyDelegate.h */, + BCA18B5C0C9B08C200114369 /* PolicyDelegate.mm */, + BCA18B5D0C9B08C200114369 /* ResourceLoadDelegate.h */, + BCA18B5E0C9B08C200114369 /* ResourceLoadDelegate.mm */, + BCA18B5F0C9B08C200114369 /* UIDelegate.h */, + BCA18B600C9B08C200114369 /* UIDelegate.mm */, + ); + name = Delegates; + sourceTree = "<group>"; + }; + 9340995508540CAF007F3BC8 /* Products */ = { + isa = PBXGroup; + children = ( + 9340995408540CAF007F3BC8 /* DumpRenderTree */, + B5A7526708AF4A4A00138E45 /* ImageDiff */, + 141BF233096A44CF00E0753C /* TestNetscapePlugIn.plugin */, + ); + name = Products; + sourceTree = "<group>"; + }; + 9345229B0BD12B2C0086EDA0 /* Resources */ = { + isa = PBXGroup; + children = ( + AA7F10C20CB3C1030003BDC9 /* AHEM____.TTF */, + ); + name = Resources; + sourceTree = "<group>"; + }; + A803FF6409CAACC1009B2A37 /* Frameworks */ = { + isa = PBXGroup; + children = ( + BCB284B20CFA82CB007E533E /* ApplicationServices.framework */, + AE8257EF08D22389000507AB /* Carbon.framework */, + A84F608908B136DA00E9745F /* Cocoa.framework */, + A817090308B164D300CCB9FB /* JavaScriptCore.framework */, + B5A752A108AF5D1F00138E45 /* QuartzCore.framework */, + 9335435F03D75502008635CE /* WebKit.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + A8B91AC40CF3B170008F91FF /* ObjCPlugin */ = { + isa = PBXGroup; + children = ( + BCA18B250C9B015C00114369 /* WorkQueueItemMac.mm */, + BCA18B760C9B08F100114369 /* ObjCPlugin.h */, + BCA18B770C9B08F100114369 /* ObjCPlugin.m */, + BCA18B780C9B08F100114369 /* ObjCPluginFunction.h */, + BCA18B790C9B08F100114369 /* ObjCPluginFunction.m */, + ); + name = ObjCPlugin; + sourceTree = "<group>"; + }; + A8B91AD20CF3B305008F91FF /* AppKit Overrides */ = { + isa = PBXGroup; + children = ( + A8B91ADF0CF3B372008F91FF /* DumpRenderTreePasteboard.h */, + A8B91AD70CF3B32F008F91FF /* DumpRenderTreePasteboard.m */, + A8B91ADD0CF3B372008F91FF /* DumpRenderTreeWindow.h */, + A8B91AD90CF3B32F008F91FF /* DumpRenderTreeWindow.mm */, + ); + name = "AppKit Overrides"; + sourceTree = "<group>"; + }; + BCB281ED0CFA711D007E533E /* Configurations */ = { + isa = PBXGroup; + children = ( + BCB281EE0CFA713D007E533E /* Base.xcconfig */, + BCB282F40CFA7450007E533E /* DebugRelease.xcconfig */, + BCB281F00CFA713D007E533E /* DumpRenderTree.xcconfig */, + BCB283D80CFA7AFD007E533E /* ImageDiff.xcconfig */, + BCB283DE0CFA7C20007E533E /* TestNetscapePlugIn.xcconfig */, + ); + name = Configurations; + sourceTree = "<group>"; + }; + BCB284870CFA81ED007E533E /* PixelDump */ = { + isa = PBXGroup; + children = ( + BCB284F30CFA84F2007E533E /* ImageDiffCG.cpp */, + BCB2848A0CFA820F007E533E /* PixelDumpSupport.h */, + BCB284880CFA8202007E533E /* PixelDumpSupportCG.cpp */, + BCB284890CFA8202007E533E /* PixelDumpSupportCG.h */, + BCB2848C0CFA8221007E533E /* PixelDumpSupportMac.mm */, + ); + name = PixelDump; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 141BF44E096A45DD00E0753C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 141BF453096A45EB00E0753C /* PluginObject.h in Headers */, + 1A8F02E80BB9B4EC008CFA34 /* TestObject.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9340994B08540CAE007F3BC8 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + BCA18B380C9B021900114369 /* AppleScriptController.h in Headers */, + BCA18B7A0C9B08F100114369 /* DumpRenderTreeDraggingInfo.h in Headers */, + BCA18C0B0C9B59EF00114369 /* DumpRenderTreeMac.h in Headers */, + 9340994C08540CAE007F3BC8 /* DumpRenderTreePrefix.h in Headers */, + BCA18B610C9B08C200114369 /* EditingDelegate.h in Headers */, + BCA18B6F0C9B08DB00114369 /* EventSendingController.h in Headers */, + BCA18B630C9B08C200114369 /* FrameLoadDelegate.h in Headers */, + 14770FE20A22ADF7009342EE /* GCController.h in Headers */, + BC0131DB0C9772010087317D /* LayoutTestController.h in Headers */, + BCA18B710C9B08DB00114369 /* NavigationController.h in Headers */, + BCA18B310C9B01B400114369 /* ObjCController.h in Headers */, + BCA18B7D0C9B08F100114369 /* ObjCPlugin.h in Headers */, + BCA18B7F0C9B08F100114369 /* ObjCPluginFunction.h in Headers */, + BCA18B650C9B08C200114369 /* PolicyDelegate.h in Headers */, + BCA18B670C9B08C200114369 /* ResourceLoadDelegate.h in Headers */, + BCA18B3C0C9B024900114369 /* TextInputController.h in Headers */, + BCA18B690C9B08C200114369 /* UIDelegate.h in Headers */, + BC9D90250C97472E0099A4A3 /* WorkQueue.h in Headers */, + BC9D90260C97472E0099A4A3 /* WorkQueueItem.h in Headers */, + A8B91AE00CF3B372008F91FF /* DumpRenderTreeWindow.h in Headers */, + A8B91AE20CF3B372008F91FF /* DumpRenderTreePasteboard.h in Headers */, + A8B91BFF0CF522B4008F91FF /* CheckedMalloc.h in Headers */, + BCB284C70CFA83C4007E533E /* PixelDumpSupport.h in Headers */, + BCB284D00CFA83CC007E533E /* PixelDumpSupportCG.h in Headers */, + BC47412A0D038A4C0072B006 /* JavaScriptThreading.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B5A7525B08AF4A4A00138E45 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 141BF21E096A441D00E0753C /* TestNetscapePlugIn */ = { + isa = PBXNativeTarget; + buildConfigurationList = 141BF221096A441E00E0753C /* Build configuration list for PBXNativeTarget "TestNetscapePlugIn" */; + buildPhases = ( + 141BF21B096A441D00E0753C /* Resources */, + 141BF44E096A45DD00E0753C /* Headers */, + 141BF21C096A441D00E0753C /* Sources */, + 141BF21D096A441D00E0753C /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TestNetscapePlugIn; + productName = TestNetscapePlugIn.plugin; + productReference = 141BF233096A44CF00E0753C /* TestNetscapePlugIn.plugin */; + productType = "com.apple.product-type.bundle"; + }; + 9340994A08540CAE007F3BC8 /* DumpRenderTree */ = { + isa = PBXNativeTarget; + buildConfigurationList = 149C29BF08902C6D008A9EFC /* Build configuration list for PBXNativeTarget "DumpRenderTree" */; + buildPhases = ( + 9340994B08540CAE007F3BC8 /* Headers */, + 9340994D08540CAE007F3BC8 /* Sources */, + 9340994F08540CAE007F3BC8 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DumpRenderTree; + productInstallPath = "$(HOME)/bin"; + productName = DumpRenderTree; + productReference = 9340995408540CAF007F3BC8 /* DumpRenderTree */; + productType = "com.apple.product-type.tool"; + }; + B5A7525A08AF4A4A00138E45 /* ImageDiff */ = { + isa = PBXNativeTarget; + buildConfigurationList = B5A7526408AF4A4A00138E45 /* Build configuration list for PBXNativeTarget "ImageDiff" */; + buildPhases = ( + B5A7525B08AF4A4A00138E45 /* Headers */, + B5A7525D08AF4A4A00138E45 /* Sources */, + B5A7525F08AF4A4A00138E45 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ImageDiff; + productInstallPath = "$(HOME)/bin"; + productName = DumpRenderTree; + productReference = B5A7526708AF4A4A00138E45 /* ImageDiff */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 149C29C308902C6D008A9EFC /* Build configuration list for PBXProject "DumpRenderTree" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* DumpRenderTree */; + productRefGroup = 9340995508540CAF007F3BC8 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A84F608D08B1370600E9745F /* All */, + 9340994A08540CAE007F3BC8 /* DumpRenderTree */, + B5A7525A08AF4A4A00138E45 /* ImageDiff */, + 141BF21E096A441D00E0753C /* TestNetscapePlugIn */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 141BF21B096A441D00E0753C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 141BF44C096A45C800E0753C /* Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 141BF21C096A441D00E0753C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1AC6C8490D07638600CD3161 /* main.cpp in Sources */, + 1AC6C84A0D07638600CD3161 /* PluginObject.cpp in Sources */, + 1AC6C84B0D07638600CD3161 /* TestObject.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9340994D08540CAE007F3BC8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BCA18B390C9B021900114369 /* AppleScriptController.m in Sources */, + BCA18C470C9B5B9400114369 /* DumpRenderTree.mm in Sources */, + BCA18B7B0C9B08F100114369 /* DumpRenderTreeDraggingInfo.mm in Sources */, + BCA18B620C9B08C200114369 /* EditingDelegate.mm in Sources */, + BCA18B700C9B08DB00114369 /* EventSendingController.mm in Sources */, + BCA18B640C9B08C200114369 /* FrameLoadDelegate.mm in Sources */, + BCF6C6500C98E9C000AC063E /* GCController.cpp in Sources */, + BCA18B230C9B014B00114369 /* GCControllerMac.mm in Sources */, + BC0131DA0C9772010087317D /* LayoutTestController.cpp in Sources */, + BCA18B240C9B014B00114369 /* LayoutTestControllerMac.mm in Sources */, + BCA18B720C9B08DB00114369 /* NavigationController.m in Sources */, + BCA18B320C9B01B400114369 /* ObjCController.m in Sources */, + BCA18B7E0C9B08F100114369 /* ObjCPlugin.m in Sources */, + BCA18B800C9B08F100114369 /* ObjCPluginFunction.m in Sources */, + BCA18B660C9B08C200114369 /* PolicyDelegate.mm in Sources */, + BCA18B680C9B08C200114369 /* ResourceLoadDelegate.mm in Sources */, + BCA18B490C9B02C400114369 /* TextInputController.m in Sources */, + BCA18B6A0C9B08C200114369 /* UIDelegate.mm in Sources */, + BC9D90240C97472E0099A4A3 /* WorkQueue.cpp in Sources */, + BCA18B260C9B015C00114369 /* WorkQueueItemMac.mm in Sources */, + A8B91ADA0CF3B32F008F91FF /* DumpRenderTreePasteboard.m in Sources */, + A8B91ADC0CF3B32F008F91FF /* DumpRenderTreeWindow.mm in Sources */, + A8B91BFD0CF522B4008F91FF /* CheckedMalloc.cpp in Sources */, + BCB284CD0CFA83C8007E533E /* PixelDumpSupportCG.cpp in Sources */, + BCB284D60CFA83D1007E533E /* PixelDumpSupportMac.mm in Sources */, + BC4741410D038A570072B006 /* JavaScriptThreadingPthreads.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B5A7525D08AF4A4A00138E45 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BCB284F60CFA84F8007E533E /* ImageDiffCG.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 141BF238096A451E00E0753C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 141BF21E096A441D00E0753C /* TestNetscapePlugIn */; + targetProxy = 141BF237096A451E00E0753C /* PBXContainerItemProxy */; + }; + A84F608F08B1370E00E9745F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B5A7525A08AF4A4A00138E45 /* ImageDiff */; + targetProxy = A84F608E08B1370E00E9745F /* PBXContainerItemProxy */; + }; + A84F609108B1370E00E9745F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9340994A08540CAE007F3BC8 /* DumpRenderTree */; + targetProxy = A84F609008B1370E00E9745F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 141BF222096A441E00E0753C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB283DE0CFA7C20007E533E /* TestNetscapePlugIn.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 141BF223096A441E00E0753C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB283DE0CFA7C20007E533E /* TestNetscapePlugIn.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 149C29C008902C6D008A9EFC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB281F00CFA713D007E533E /* DumpRenderTree.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + 149C29C108902C6D008A9EFC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB281F00CFA713D007E533E /* DumpRenderTree.xcconfig */; + buildSettings = { + }; + name = Release; + }; + 149C29C408902C6D008A9EFC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB282F40CFA7450007E533E /* DebugRelease.xcconfig */; + buildSettings = { + GCC_OPTIMIZATION_LEVEL = 0; + }; + name = Debug; + }; + 149C29C508902C6D008A9EFC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB282F40CFA7450007E533E /* DebugRelease.xcconfig */; + buildSettings = { + }; + name = Release; + }; + A84F609308B1371400E9745F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + OPTIMIZATION_CFLAGS = "-O0"; + OTHER_CFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = All; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Debug; + }; + A84F609408B1371400E9745F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + OPTIMIZATION_CFLAGS = "-O0"; + OTHER_CFLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = All; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Release; + }; + B5A7526508AF4A4A00138E45 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB283D80CFA7AFD007E533E /* ImageDiff.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + B5A7526608AF4A4A00138E45 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCB283D80CFA7AFD007E533E /* ImageDiff.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 141BF221096A441E00E0753C /* Build configuration list for PBXNativeTarget "TestNetscapePlugIn" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 141BF222096A441E00E0753C /* Debug */, + 141BF223096A441E00E0753C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 149C29BF08902C6D008A9EFC /* Build configuration list for PBXNativeTarget "DumpRenderTree" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 149C29C008902C6D008A9EFC /* Debug */, + 149C29C108902C6D008A9EFC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 149C29C308902C6D008A9EFC /* Build configuration list for PBXProject "DumpRenderTree" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 149C29C408902C6D008A9EFC /* Debug */, + 149C29C508902C6D008A9EFC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A84F609208B1371400E9745F /* Build configuration list for PBXAggregateTarget "All" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A84F609308B1371400E9745F /* Debug */, + A84F609408B1371400E9745F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B5A7526408AF4A4A00138E45 /* Build configuration list for PBXNativeTarget "ImageDiff" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B5A7526508AF4A4A00138E45 /* Debug */, + B5A7526608AF4A4A00138E45 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/WebKitTools/DumpRenderTree/DumpRenderTreePrefix.h b/WebKitTools/DumpRenderTree/DumpRenderTreePrefix.h new file mode 100644 index 0000000..cb40968 --- /dev/null +++ b/WebKitTools/DumpRenderTree/DumpRenderTreePrefix.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + */ + +#ifdef __OBJC__ + +#import <Foundation/Foundation.h> + +#endif diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ASCIICType.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ASCIICType.h new file mode 100644 index 0000000..f2258d2 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ASCIICType.h @@ -0,0 +1 @@ +#include <JavaScriptCore/ASCIICType.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Assertions.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Assertions.h new file mode 100644 index 0000000..2144410 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Assertions.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Assertions.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashMap.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashMap.h new file mode 100644 index 0000000..9f262e2 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashMap.h @@ -0,0 +1 @@ +#include <JavaScriptCore/HashMap.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashSet.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashSet.h new file mode 100644 index 0000000..cfe2d80 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashSet.h @@ -0,0 +1 @@ +#include <JavaScriptCore/HashSet.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashTraits.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashTraits.h new file mode 100755 index 0000000..412fa98 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/HashTraits.h @@ -0,0 +1 @@ +#include <JavaScriptCore/HashTraits.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/MathExtras.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/MathExtras.h new file mode 100644 index 0000000..2955786 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/MathExtras.h @@ -0,0 +1 @@ +#include <JavaScriptCore/MathExtras.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Noncopyable.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Noncopyable.h new file mode 100644 index 0000000..f8484d2 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Noncopyable.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Noncopyable.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/OwnPtr.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/OwnPtr.h new file mode 100644 index 0000000..9211d38 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/OwnPtr.h @@ -0,0 +1 @@ +#include <JavaScriptCore/OwnPtr.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Platform.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Platform.h new file mode 100644 index 0000000..3b22955 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Platform.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Platform.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/RetainPtr.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/RetainPtr.h new file mode 100644 index 0000000..65fc27b --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/RetainPtr.h @@ -0,0 +1 @@ +#include <JavaScriptCore/RetainPtr.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/StringExtras.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/StringExtras.h new file mode 100644 index 0000000..063d500 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/StringExtras.h @@ -0,0 +1 @@ +#include <JavaScriptCore/StringExtras.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Vector.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Vector.h new file mode 100644 index 0000000..c6d15fd --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Vector.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Vector.h> diff --git a/WebKitTools/DumpRenderTree/GCController.cpp b/WebKitTools/DumpRenderTree/GCController.cpp new file mode 100644 index 0000000..38c45bf --- /dev/null +++ b/WebKitTools/DumpRenderTree/GCController.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "GCController.h" + +#include <JavaScriptCore/JSObjectRef.h> +#include <JavaScriptCore/JSRetainPtr.h> + +GCController::GCController() +{ +} + +GCController::~GCController() +{ +} + +// Static Functions + +static JSValueRef collectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + GCController* controller = reinterpret_cast<GCController*>(JSObjectGetPrivate(thisObject)); + controller->collect(); + return JSValueMakeUndefined(context); +} + +static JSValueRef collectOnAlternateThreadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + bool waitUntilDone = false; + if (argumentCount > 0) + waitUntilDone = JSValueToBoolean(context, arguments[0]); + + GCController* controller = reinterpret_cast<GCController*>(JSObjectGetPrivate(thisObject)); + controller->collectOnAlternateThread(waitUntilDone); + + return JSValueMakeUndefined(context); +} + +static JSValueRef getJSObjectCountCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + GCController* controller = reinterpret_cast<GCController*>(JSObjectGetPrivate(thisObject)); + size_t jsObjectCount = controller->getJSObjectCount(); + + return JSValueMakeNumber(context, jsObjectCount); +} + +// Object Creation + +void GCController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> gcControllerStr(Adopt, JSStringCreateWithUTF8CString("GCController")); + JSValueRef gcControllerObject = JSObjectMake(context, getJSClass(), this); + JSObjectSetProperty(context, windowObject, gcControllerStr.get(), gcControllerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); +} + +JSClassRef GCController::getJSClass() +{ + static JSClassRef gcControllerClass = 0; + + if (!gcControllerClass) { + JSStaticFunction* staticFunctions = GCController::staticFunctions(); + JSClassDefinition classDefinition = { + 0, kJSClassAttributeNone, "GCController", 0, 0, staticFunctions, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + gcControllerClass = JSClassCreate(&classDefinition); + } + + return gcControllerClass; +} + +JSStaticFunction* GCController::staticFunctions() +{ + static JSStaticFunction staticFunctions[] = { + { "collect", collectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "collectOnAlternateThread", collectOnAlternateThreadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "getJSObjectCount", getJSObjectCountCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { 0, 0, 0 } + }; + + return staticFunctions; +} diff --git a/WebKitTools/DumpRenderTree/GCController.h b/WebKitTools/DumpRenderTree/GCController.h new file mode 100644 index 0000000..4284275 --- /dev/null +++ b/WebKitTools/DumpRenderTree/GCController.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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. + */ + +#ifndef GCController_h +#define GCController_h + +#include <JavaScriptCore/JSObjectRef.h> + +class GCController { +public: + GCController(); + ~GCController(); + + void makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception); + + // Controller Methods - platfrom independant implementations + void collect() const; + void collectOnAlternateThread(bool waitUntilDone) const; + size_t getJSObjectCount() const; + +private: + static JSClassRef getJSClass(); + static JSStaticFunction* staticFunctions(); +}; + +#endif // GCController_h diff --git a/WebKitTools/DumpRenderTree/JavaScriptThreading.h b/WebKitTools/DumpRenderTree/JavaScriptThreading.h new file mode 100644 index 0000000..43795a1 --- /dev/null +++ b/WebKitTools/DumpRenderTree/JavaScriptThreading.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef JavaScriptThreading_h +#define JavaScriptThreading_h + +/* These functions start/stop threads used to abuse the JavaScript interpreter + and assure that our JS implementation remains threadsafe */ + +void startJavaScriptThreads(); +void stopJavaScriptThreads(); + +#endif // JavaScriptThreading_h diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp new file mode 100644 index 0000000..4920066 --- /dev/null +++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp @@ -0,0 +1,720 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "LayoutTestController.h" + +#include <JavaScriptCore/JSObjectRef.h> +#include <JavaScriptCore/JSRetainPtr.h> +#include <wtf/Assertions.h> +#include <wtf/MathExtras.h> + +LayoutTestController::LayoutTestController(bool testRepaintDefault, bool testRepaintSweepHorizontallyDefault) + : m_dumpAsText(false) + , m_dumpBackForwardList(false) + , m_dumpChildFrameScrollPositions(false) + , m_dumpChildFramesAsText(false) + , m_dumpDatabaseCallbacks(false) + , m_dumpDOMAsWebArchive(false) + , m_dumpSelectionRect(false) + , m_dumpSourceAsWebArchive(false) + , m_dumpStatusCallbacks(false) + , m_dumpTitleChanges(false) + , m_dumpEditingCallbacks(false) + , m_dumpResourceLoadCallbacks(false) + , m_dumpFrameLoadCallbacks(false) + , m_addFileToPasteboardOnDrag(false) + , m_callCloseOnWebViews(true) + , m_canOpenWindows(false) + , m_closeRemainingWindowsWhenComplete(true) + , m_testRepaint(testRepaintDefault) + , m_testRepaintSweepHorizontally(testRepaintSweepHorizontallyDefault) + , m_waitToDump(false) + , m_windowIsKey(true) + , m_globalFlag(false) +{ +} + +// Static Functions + +static JSValueRef dumpAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpAsText(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpBackForwardList(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpChildFramesAsTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpChildFramesAsText(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpChildFrameScrollPositionsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpChildFrameScrollPositions(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpDatabaseCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpDatabaseCallbacks(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpDOMAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpDOMAsWebArchive(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpEditingCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpEditingCallbacks(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpFrameLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpFrameLoadCallbacks(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpResourceLoadCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpResourceLoadCallbacks(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpSelectionRectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpSelectionRect(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpSourceAsWebArchiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpSourceAsWebArchive(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpStatusCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpStatusCallbacks(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef dumpTitleChangesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpTitleChanges(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef pathToLocalResourceCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + JSRetainPtr<JSStringRef> localPath(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + JSRetainPtr<JSStringRef> convertedPath(Adopt, controller->pathToLocalResource(context, localPath.get())); + if (!convertedPath) + return JSValueMakeUndefined(context); + + return JSValueMakeString(context, convertedPath.get()); +} + +static JSValueRef repaintSweepHorizontallyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setTestRepaintSweepHorizontally(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef setCallCloseOnWebViewsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setCallCloseOnWebViews(JSValueToBoolean(context, arguments[0])); + return JSValueMakeUndefined(context); +} + +static JSValueRef setCanOpenWindowsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setCanOpenWindows(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef setCloseRemainingWindowsWhenCompleteCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setCloseRemainingWindowsWhenComplete(JSValueToBoolean(context, arguments[0])); + return JSValueMakeUndefined(context); +} + +static JSValueRef testRepaintCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setTestRepaint(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef addFileToPasteboardOnDragCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setAddFileToPasteboardOnDrag(true); + return JSValueMakeUndefined(context); +} + +static JSValueRef addDisallowedURLCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->addDisallowedURL(url.get()); + + return JSValueMakeUndefined(context); +} + +static JSValueRef clearAllDatabasesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->clearAllDatabases(); + + return JSValueMakeUndefined(context); +} + +static JSValueRef clearBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->clearBackForwardList(); + + return JSValueMakeUndefined(context); +} + +static JSValueRef clearPersistentUserStyleSheetCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->clearPersistentUserStyleSheet(); + + return JSValueMakeUndefined(context); +} + +static JSValueRef decodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + JSRetainPtr<JSStringRef> decodedHostName(Adopt, controller->copyDecodedHostName(name.get())); + return JSValueMakeString(context, decodedHostName.get()); +} + +static JSValueRef displayCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->display(); + + return JSValueMakeUndefined(context); +} + +static JSValueRef encodeHostNameCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + JSRetainPtr<JSStringRef> encodedHostName(Adopt, controller->copyEncodedHostName(name.get())); + return JSValueMakeString(context, encodedHostName.get()); +} + +static JSValueRef execCommandCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has Mac & Windows implementations. + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> name(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + // Ignoring the second parameter (userInterface), as this command emulates a manual action. + + JSRetainPtr<JSStringRef> value; + if (argumentCount >= 3) { + value.adopt(JSValueToStringCopy(context, arguments[2], exception)); + ASSERT(!*exception); + } else + value.adopt(JSStringCreateWithUTF8CString("")); + + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->execCommand(name.get(), value.get()); + + return JSValueMakeUndefined(context); +} + +static JSValueRef keepWebHistoryCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->keepWebHistory(); + + return JSValueMakeUndefined(context); +} + +static JSValueRef notifyDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + // May be able to be made platform independant by using shared WorkQueue + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->notifyDone(); + + return JSValueMakeUndefined(context); +} + +static JSValueRef queueBackNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + // May be able to be made platform independant by using shared WorkQueue + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + double howFarBackDouble = JSValueToNumber(context, arguments[0], exception); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->queueBackNavigation(static_cast<int>(howFarBackDouble)); + + return JSValueMakeUndefined(context); +} + +static JSValueRef queueForwardNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + // May be able to be made platform independant by using shared WorkQueue + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + double howFarForwardDouble = JSValueToNumber(context, arguments[0], exception); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->queueForwardNavigation(static_cast<int>(howFarForwardDouble)); + + return JSValueMakeUndefined(context); +} + +static JSValueRef queueLoadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + // May be able to be made platform independant by using shared WorkQueue + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + JSRetainPtr<JSStringRef> target; + if (argumentCount >= 2) { + target.adopt(JSValueToStringCopy(context, arguments[1], exception)); + ASSERT(!*exception); + } else + target.adopt(JSStringCreateWithUTF8CString("")); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->queueLoad(url.get(), target.get()); + + return JSValueMakeUndefined(context); +} + +static JSValueRef queueReloadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + // May be able to be made platform independant by using shared WorkQueue + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->queueReload(); + + return JSValueMakeUndefined(context); +} + +static JSValueRef queueScriptCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + // May be able to be made platform independant by using shared WorkQueue + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->queueScript(script.get()); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setAcceptsEditingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setAcceptsEditing(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setAuthorAndUserStylesEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setAuthorAndUserStylesEnabled(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setCustomPolicyDelegateCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setCustomPolicyDelegate(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setDatabaseQuotaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + + double quota = JSValueToNumber(context, arguments[0], NULL); + if (!isnan(quota)) + controller->setDatabaseQuota(static_cast<unsigned long long>(quota)); + + return JSValueMakeUndefined(context); + +} + +static JSValueRef setMainFrameIsFirstResponderCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setMainFrameIsFirstResponder(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setPersistentUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setPersistentUserStyleSheetLocation(path.get()); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setPrivateBrowsingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setPrivateBrowsingEnabled(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setTabKeyCyclesThroughElementsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setTabKeyCyclesThroughElements(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setUseDashboardCompatibilityModeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setUseDashboardCompatibilityMode(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setUserStyleSheetEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setUserStyleSheetEnabled(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setUserStyleSheetLocationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> path(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setUserStyleSheetLocation(path.get()); + + return JSValueMakeUndefined(context); +} + +static JSValueRef setWindowIsKeyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setWindowIsKey(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + +static JSValueRef waitUntilDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setWaitToDump(true); + + return JSValueMakeUndefined(context); +} + +static JSValueRef windowCountCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + int windows = controller->windowCount(); + return JSValueMakeNumber(context, windows); +} + +static JSValueRef setPopupBlockingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setPopupBlockingEnabled(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + + +// Static Values + +static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + return JSValueMakeBoolean(context, controller->globalFlag()); +} + +static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) +{ + LayoutTestController* controller = reinterpret_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setGlobalFlag(JSValueToBoolean(context, value)); + return true; +} + +// Object Creation + +void LayoutTestController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> layoutTestContollerStr(Adopt, JSStringCreateWithUTF8CString("layoutTestController")); + JSValueRef layoutTestContollerObject = JSObjectMake(context, getJSClass(), this); + JSObjectSetProperty(context, windowObject, layoutTestContollerStr.get(), layoutTestContollerObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); +} + +JSClassRef LayoutTestController::getJSClass() +{ + static JSClassRef layoutTestControllerClass; + + if (!layoutTestControllerClass) { + JSStaticValue* staticValues = LayoutTestController::staticValues(); + JSStaticFunction* staticFunctions = LayoutTestController::staticFunctions(); + JSClassDefinition classDefinition = { + 0, kJSClassAttributeNone, "LayoutTestController", 0, staticValues, staticFunctions, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + layoutTestControllerClass = JSClassCreate(&classDefinition); + } + + return layoutTestControllerClass; +} + +JSStaticValue* LayoutTestController::staticValues() +{ + static JSStaticValue staticValues[] = { + { "globalFlag", getGlobalFlagCallback, setGlobalFlagCallback, kJSPropertyAttributeNone }, + { 0, 0, 0, 0 } + }; + return staticValues; + +} + +JSStaticFunction* LayoutTestController::staticFunctions() +{ + static JSStaticFunction staticFunctions[] = { + { "addDisallowedURL", addDisallowedURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "addFileToPasteboardOnDrag", addFileToPasteboardOnDragCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "decodeHostName", decodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "display", displayCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpAsText", dumpAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpBackForwardList", dumpBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpChildFramesAsText", dumpChildFramesAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpChildFrameScrollPositions", dumpChildFrameScrollPositionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpDatabaseCallbacks", dumpDatabaseCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpDOMAsWebArchive", dumpDOMAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpEditingCallbacks", dumpEditingCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpFrameLoadCallbacks", dumpFrameLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpResourceLoadCallbacks", dumpResourceLoadCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpSelectionRect", dumpSelectionRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpSourceAsWebArchive", dumpSourceAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpStatusCallbacks", dumpStatusCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpTitleChanges", dumpTitleChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "notifyDone", notifyDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "pathToLocalResource", pathToLocalResourceCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "queueBackNavigation", queueBackNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "queueForwardNavigation", queueForwardNavigationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "queueLoad", queueLoadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "queueReload", queueReloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "queueScript", queueScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "repaintSweepHorizontally", repaintSweepHorizontallyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setAuthorAndUserStylesEnabled", setAuthorAndUserStylesEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setCallCloseOnWebViews", setCallCloseOnWebViewsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setCanOpenWindows", setCanOpenWindowsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setCloseRemainingWindowsWhenComplete", setCloseRemainingWindowsWhenCompleteCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setCustomPolicyDelegate", setCustomPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setDatabaseQuota", setDatabaseQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setMainFrameIsFirstResponder", setMainFrameIsFirstResponderCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setPersistentUserStyleSheetLocation", setPersistentUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setPrivateBrowsingEnabled", setPrivateBrowsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setPopupBlockingEnabled", setPopupBlockingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setTabKeyCyclesThroughElements", setTabKeyCyclesThroughElementsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "testRepaint", testRepaintCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "waitUntilDone", waitUntilDoneCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "windowCount", windowCountCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { 0, 0, 0 } + }; + + return staticFunctions; +} + + diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h new file mode 100644 index 0000000..754d8ce --- /dev/null +++ b/WebKitTools/DumpRenderTree/LayoutTestController.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef LayoutTestController_h +#define LayoutTestController_h + +#include <JavaScriptCore/JSObjectRef.h> + +class LayoutTestController { +public: + LayoutTestController(bool testRepaintDefault, bool testRepaintSweepHorizontallyDefault); + ~LayoutTestController(); + + void makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception); + + // Controller Methods - platfrom independant implementations + void addDisallowedURL(JSStringRef url); + void clearAllDatabases(); + void clearBackForwardList(); + JSStringRef copyDecodedHostName(JSStringRef name); + JSStringRef copyEncodedHostName(JSStringRef name); + void execCommand(JSStringRef name, JSStringRef value); + void display(); + void keepWebHistory(); + void notifyDone(); + JSStringRef pathToLocalResource(JSContextRef, JSStringRef url); + void queueBackNavigation(int howFarBackward); + void queueForwardNavigation(int howFarForward); + void queueLoad(JSStringRef url, JSStringRef target); + void queueReload(); + void queueScript(JSStringRef url); + void setAcceptsEditing(bool acceptsEditing); + void setAuthorAndUserStylesEnabled(bool); + void setCustomPolicyDelegate(bool setDelegate); + void setDatabaseQuota(unsigned long long quota); + void setMainFrameIsFirstResponder(bool flag); + void setPrivateBrowsingEnabled(bool flag); + void setPopupBlockingEnabled(bool flag); + void setTabKeyCyclesThroughElements(bool cycles); + void setUseDashboardCompatibilityMode(bool flag); + void setUserStyleSheetEnabled(bool flag); + void setUserStyleSheetLocation(JSStringRef path); + void setPersistentUserStyleSheetLocation(JSStringRef path); + void clearPersistentUserStyleSheet(); + int windowCount(); + + bool dumpAsText() const { return m_dumpAsText; } + void setDumpAsText(bool dumpAsText) { m_dumpAsText = dumpAsText; } + + bool dumpBackForwardList() const { return m_dumpBackForwardList; } + void setDumpBackForwardList(bool dumpBackForwardList) { m_dumpBackForwardList = dumpBackForwardList; } + + bool dumpChildFrameScrollPositions() const { return m_dumpChildFrameScrollPositions; } + void setDumpChildFrameScrollPositions(bool dumpChildFrameScrollPositions) { m_dumpChildFrameScrollPositions = dumpChildFrameScrollPositions; } + + bool dumpChildFramesAsText() const { return m_dumpChildFramesAsText; } + void setDumpChildFramesAsText(bool dumpChildFramesAsText) { m_dumpChildFramesAsText = dumpChildFramesAsText; } + + bool dumpDatabaseCallbacks() const { return m_dumpDatabaseCallbacks; } + void setDumpDatabaseCallbacks(bool dumpDatabaseCallbacks) { m_dumpDatabaseCallbacks = dumpDatabaseCallbacks; } + + bool dumpStatusCallbacks() const { return m_dumpStatusCallbacks; } + void setDumpStatusCallbacks(bool dumpStatusCallbacks) { m_dumpStatusCallbacks = dumpStatusCallbacks; } + + bool dumpDOMAsWebArchive() const { return m_dumpDOMAsWebArchive; } + void setDumpDOMAsWebArchive(bool dumpDOMAsWebArchive) { m_dumpDOMAsWebArchive = dumpDOMAsWebArchive; } + + bool dumpSelectionRect() const { return m_dumpSelectionRect; } + void setDumpSelectionRect(bool dumpSelectionRect) { m_dumpSelectionRect = dumpSelectionRect; } + + bool dumpSourceAsWebArchive() const { return m_dumpSourceAsWebArchive; } + void setDumpSourceAsWebArchive(bool dumpSourceAsWebArchive) { m_dumpSourceAsWebArchive = dumpSourceAsWebArchive; } + + bool dumpTitleChanges() const { return m_dumpTitleChanges; } + void setDumpTitleChanges(bool dumpTitleChanges) { m_dumpTitleChanges = dumpTitleChanges; } + + bool dumpEditingCallbacks() const { return m_dumpEditingCallbacks; } + void setDumpEditingCallbacks(bool dumpEditingCallbacks) { m_dumpEditingCallbacks = dumpEditingCallbacks; } + + bool dumpResourceLoadCallbacks() const { return m_dumpResourceLoadCallbacks; } + void setDumpResourceLoadCallbacks(bool dumpResourceLoadCallbacks) { m_dumpResourceLoadCallbacks = dumpResourceLoadCallbacks; } + + bool dumpFrameLoadCallbacks() const { return m_dumpFrameLoadCallbacks; } + void setDumpFrameLoadCallbacks(bool dumpFrameLoadCallbacks) { m_dumpFrameLoadCallbacks = dumpFrameLoadCallbacks; } + + bool addFileToPasteboardOnDrag() const { return m_addFileToPasteboardOnDrag; } + void setAddFileToPasteboardOnDrag(bool addFileToPasteboardOnDrag) { m_addFileToPasteboardOnDrag = addFileToPasteboardOnDrag; } + + bool callCloseOnWebViews() const { return m_callCloseOnWebViews; } + void setCallCloseOnWebViews(bool callCloseOnWebViews) { m_callCloseOnWebViews = callCloseOnWebViews; } + + bool canOpenWindows() const { return m_canOpenWindows; } + void setCanOpenWindows(bool canOpenWindows) { m_canOpenWindows = canOpenWindows; } + + bool closeRemainingWindowsWhenComplete() const { return m_closeRemainingWindowsWhenComplete; } + void setCloseRemainingWindowsWhenComplete(bool closeRemainingWindowsWhenComplete) { m_closeRemainingWindowsWhenComplete = closeRemainingWindowsWhenComplete; } + + bool testRepaint() const { return m_testRepaint; } + void setTestRepaint(bool testRepaint) { m_testRepaint = testRepaint; } + + bool testRepaintSweepHorizontally() const { return m_testRepaintSweepHorizontally; } + void setTestRepaintSweepHorizontally(bool testRepaintSweepHorizontally) { m_testRepaintSweepHorizontally = testRepaintSweepHorizontally; } + + bool waitToDump() const { return m_waitToDump; } + void setWaitToDump(bool waitToDump); + + bool windowIsKey() const { return m_windowIsKey; } + void setWindowIsKey(bool windowIsKey); + + bool globalFlag() const { return m_globalFlag; } + void setGlobalFlag(bool globalFlag) { m_globalFlag = globalFlag; } + +private: + bool m_dumpAsText; + bool m_dumpBackForwardList; + bool m_dumpChildFrameScrollPositions; + bool m_dumpChildFramesAsText; + bool m_dumpDatabaseCallbacks; + bool m_dumpDOMAsWebArchive; + bool m_dumpSelectionRect; + bool m_dumpSourceAsWebArchive; + bool m_dumpStatusCallbacks; + bool m_dumpTitleChanges; + bool m_dumpEditingCallbacks; + bool m_dumpResourceLoadCallbacks; + bool m_dumpFrameLoadCallbacks; + bool m_addFileToPasteboardOnDrag; + bool m_callCloseOnWebViews; + bool m_canOpenWindows; + bool m_closeRemainingWindowsWhenComplete; + bool m_testRepaint; + bool m_testRepaintSweepHorizontally; + bool m_waitToDump; // True if waitUntilDone() has been called, but notifyDone() has not yet been called. + bool m_windowIsKey; + + bool m_globalFlag; + + static JSClassRef getJSClass(); + static JSStaticValue* staticValues(); + static JSStaticFunction* staticFunctions(); +}; + +#endif // LayoutTestController_h diff --git a/WebKitTools/DumpRenderTree/Makefile b/WebKitTools/DumpRenderTree/Makefile new file mode 100644 index 0000000..1f1dbbc --- /dev/null +++ b/WebKitTools/DumpRenderTree/Makefile @@ -0,0 +1,2 @@ +SCRIPTS_PATH = ../Scripts +include ../../Makefile.shared diff --git a/WebKitTools/DumpRenderTree/PixelDumpSupport.h b/WebKitTools/DumpRenderTree/PixelDumpSupport.h new file mode 100644 index 0000000..3214d04 --- /dev/null +++ b/WebKitTools/DumpRenderTree/PixelDumpSupport.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef PixelDumpSupport_h +#define PixelDumpSupport_h + +void dumpWebViewAsPixelsAndCompareWithExpected(const char* currentTest, bool forceAllTestsToDumpPixels); + +// Can be used as a signal handler +void restoreColorSpace(int ignored); + +// May change your color space, requiring a call to restoreColorSpace +void initializeColorSpaceAndScreeBufferForPixelTests(); + +#endif // PixelDumpSupport_h diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/Info.plist b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/Info.plist new file mode 100644 index 0000000..1f4cfe3 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/Info.plist @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>TestNetscapePlugIn</string> + <key>CFBundleGetInfoString</key> + <string>420+, Copyright 2006 Apple Computer, Inc.</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.apple.testnetscapeplugin</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>BRPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>CFPlugInDynamicRegisterFunction</key> + <string></string> + <key>CFPlugInDynamicRegistration</key> + <string>NO</string> + <key>CFPlugInFactories</key> + <dict> + <key>00000000-0000-0000-0000-000000000000</key> + <string>MyFactoryFunction</string> + </dict> + <key>CFPlugInTypes</key> + <dict> + <key>00000000-0000-0000-0000-000000000000</key> + <array> + <string>00000000-0000-0000-0000-000000000000</string> + </array> + </dict> + <key>CFPlugInUnloadFunction</key> + <string></string> + <key>WebPluginDescription</key> + <string>Simple Netscape plug-in that handles test content for WebKit</string> + <key>WebPluginMIMETypes</key> + <dict> + <key>application/x-webkit-test-netscape</key> + <dict> + <key>WebPluginExtensions</key> + <array> + <string>testnetscape</string> + </array> + <key>WebPluginTypeDescription</key> + <string>test netscape content</string> + </dict> + </dict> + <key>WebPluginName</key> + <string>WebKit Test PlugIn</string> +</dict> +</plist> diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp new file mode 100644 index 0000000..20c0e53 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#include "PluginObject.h" + +#include "TestObject.h" +#include <assert.h> +#include <stdio.h> + +static void pluginInvalidate(NPObject *obj); +static bool pluginHasProperty(NPObject *obj, NPIdentifier name); +static bool pluginHasMethod(NPObject *obj, NPIdentifier name); +static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant); +static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant); +static bool pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result); +static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result); +static NPObject *pluginAllocate(NPP npp, NPClass *theClass); +static void pluginDeallocate(NPObject *obj); + +NPNetscapeFuncs *browser; + +static NPClass pluginClass = { + NP_CLASS_STRUCT_VERSION, + pluginAllocate, + pluginDeallocate, + pluginInvalidate, + pluginHasMethod, + pluginInvoke, + pluginInvokeDefault, + pluginHasProperty, + pluginGetProperty, + pluginSetProperty, +}; + +NPClass *getPluginClass(void) +{ + return &pluginClass; +} + +static bool identifiersInitialized = false; + +#define ID_PROPERTY_PROPERTY 0 +#define ID_PROPERTY_EVENT_LOGGING 1 +#define ID_PROPERTY_HAS_STREAM 2 +#define ID_PROPERTY_TEST_OBJECT 3 +#define ID_PROPERTY_LOG_DESTROY 4 +#define NUM_PROPERTY_IDENTIFIERS 5 + +static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS]; +static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = { + "property", + "eventLoggingEnabled", + "hasStream", + "testObject", + "logDestroy", +}; + +#define ID_TEST_CALLBACK_METHOD 0 +#define ID_TEST_GETURL 1 +#define ID_REMOVE_DEFAULT_METHOD 2 +#define ID_TEST_DOM_ACCESS 3 +#define ID_TEST_GET_URL_NOTIFY 4 +#define ID_TEST_INVOKE_DEFAULT 5 +#define ID_DESTROY_STREAM 6 +#define ID_TEST_ENUMERATE 7 +#define ID_TEST_GETINTIDENTIFIER 8 +#define ID_TEST_GET_PROPERTY 9 +#define ID_TEST_EVALUATE 10 +#define ID_TEST_GET_PROPERTY_RETURN_VALUE 11 +#define NUM_METHOD_IDENTIFIERS 12 + +static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS]; +static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = { + "testCallback", + "getURL", + "removeDefaultMethod", + "testDOMAccess", + "getURLNotify", + "testInvokeDefault", + "destroyStream", + "testEnumerate", + "testGetIntIdentifier", + "testGetProperty", + "testEvaluate", + "testGetPropertyReturnValue", +}; + +static NPUTF8* createCStringFromNPVariant(const NPVariant *variant) +{ + size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length; + NPUTF8* result = (NPUTF8*)malloc(length + 1); + memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length); + result[length] = '\0'; + return result; +} + +static void initializeIdentifiers(void) +{ + browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers); + browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers); +} + +static bool pluginHasProperty(NPObject *obj, NPIdentifier name) +{ + for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) + if (name == pluginPropertyIdentifiers[i]) + return true; + return false; +} + +static bool pluginHasMethod(NPObject *obj, NPIdentifier name) +{ + for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) + if (name == pluginMethodIdentifiers[i]) + return true; + return false; +} + +static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant) +{ + if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) { + STRINGZ_TO_NPVARIANT("property", *variant); + return true; + } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { + BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->eventLogging, *variant); + return true; + } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { + BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->logDestroy, *variant); + return true; + } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) { + BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->stream != 0, *variant); + return true; + } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) { + NPObject *testObject = ((PluginObject *)obj)->testObject; + browser->retainobject(testObject); + OBJECT_TO_NPVARIANT(testObject, *variant); + return true; + } + return false; +} + +static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant) +{ + if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { + ((PluginObject *)obj)->eventLogging = NPVARIANT_TO_BOOLEAN(*variant); + return true; + } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { + ((PluginObject *)obj)->logDestroy = NPVARIANT_TO_BOOLEAN(*variant); + return true; + } + + return false; +} + +static void testDOMAccess(PluginObject *obj) +{ + // Get plug-in's DOM element + NPObject *elementObject; + if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) { + // Get style + NPVariant styleVariant; + NPIdentifier styleIdentifier = browser->getstringidentifier("style"); + if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) { + // Set style.border + NPIdentifier borderIdentifier = browser->getstringidentifier("border"); + NPVariant borderVariant; + STRINGZ_TO_NPVARIANT("3px solid red", borderVariant); + browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant); + browser->releasevariantvalue(&styleVariant); + } + + browser->releaseobject(elementObject); + } +} + +static bool pluginInvoke(NPObject *header, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) +{ + PluginObject *obj = (PluginObject *)header; + if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD]) { + // call whatever method name we're given + if (argCount > 0 && NPVARIANT_IS_STRING(args[0])) { + NPObject *windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPUTF8* callbackString = createCStringFromNPVariant(&args[0]); + NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString); + free(callbackString); + + NPVariant browserResult; + browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult); + browser->releasevariantvalue(&browserResult); + + VOID_TO_NPVARIANT(*result); + return true; + } + } else if (name == pluginMethodIdentifiers[ID_TEST_GETURL]) { + if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) { + NPUTF8* urlString = createCStringFromNPVariant(&args[0]); + NPUTF8* targetString = createCStringFromNPVariant(&args[1]); + browser->geturl(obj->npp, urlString, targetString); + free(urlString); + free(targetString); + + VOID_TO_NPVARIANT(*result); + return true; + } else if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) { + NPUTF8* urlString = createCStringFromNPVariant(&args[0]); + browser->geturl(obj->npp, urlString, 0); + free(urlString); + + VOID_TO_NPVARIANT(*result); + return true; + } + } else if (name == pluginMethodIdentifiers[ID_REMOVE_DEFAULT_METHOD]) { + pluginClass.invokeDefault = 0; + VOID_TO_NPVARIANT(*result); + return true; + } else if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS]) { + testDOMAccess(obj); + VOID_TO_NPVARIANT(*result); + return true; + } else if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY]) { + if (argCount == 3 + && NPVARIANT_IS_STRING(args[0]) + && (NPVARIANT_IS_STRING(args[1]) || NPVARIANT_IS_NULL(args[1])) + && NPVARIANT_IS_STRING(args[2])) { + NPUTF8* urlString = createCStringFromNPVariant(&args[0]); + NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : NULL); + NPUTF8* callbackString = createCStringFromNPVariant(&args[2]); + + NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString); + browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier); + + free(urlString); + free(targetString); + free(callbackString); + + VOID_TO_NPVARIANT(*result); + return true; + } + } else if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT] && NPVARIANT_IS_OBJECT(args[0])) { + NPObject *callback = NPVARIANT_TO_OBJECT(args[0]); + + NPVariant args[1]; + NPVariant browserResult; + + STRINGZ_TO_NPVARIANT("test", args[0]); + bool retval = browser->invokeDefault(obj->npp, callback, args, 1, &browserResult); + + if (retval) + browser->releasevariantvalue(&browserResult); + + BOOLEAN_TO_NPVARIANT(retval, *result); + return true; + } else if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE]) { + if (argCount == 2 && NPVARIANT_IS_OBJECT(args[0]) && NPVARIANT_IS_OBJECT(args[1])) { + uint32_t count; + NPIdentifier* identifiers; + + if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) { + NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]); + NPIdentifier pushIdentifier = browser->getstringidentifier("push"); + + for (uint32_t i = 0; i < count; i++) { + NPUTF8* string = browser->utf8fromidentifier(identifiers[i]); + + if (!string) + continue; + + NPVariant args[1]; + STRINGZ_TO_NPVARIANT(string, args[0]); + NPVariant browserResult; + browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult); + browser->releasevariantvalue(&browserResult); + browser->memfree(string); + } + + browser->memfree(identifiers); + } + + VOID_TO_NPVARIANT(*result); + return true; + } + } else if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM]) { + NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK); + INT32_TO_NPVARIANT(npError, *result); + return true; + } else if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER]) { + if (argCount == 1 && NPVARIANT_IS_DOUBLE(args[0])) { + NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0])); + INT32_TO_NPVARIANT((int32)identifier, *result); + return true; + } + } else if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE] && + argCount == 1 && NPVARIANT_IS_STRING(args[0])) { + NPObject *windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPString s = NPVARIANT_TO_STRING(args[0]); + + bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result); + browser->releaseobject(windowScriptObject); + return retval; + } else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY] && + argCount > 0) { + NPObject *object; + browser->getvalue(obj->npp, NPNVWindowNPObject, &object); + + for (uint32_t i = 0; i < argCount; i++) { + assert(NPVARIANT_IS_STRING(args[i])); + NPUTF8* propertyString = createCStringFromNPVariant(&args[i]); + NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString); + free(propertyString); + + NPVariant variant; + bool retval = browser->getproperty(obj->npp, object, propertyIdentifier, &variant); + browser->releaseobject(object); + + if (!retval) + break; + + if (i + 1 < argCount) { + assert(NPVARIANT_IS_OBJECT(variant)); + object = NPVARIANT_TO_OBJECT(variant); + } else { + *result = variant; + return true; + } + } + + VOID_TO_NPVARIANT(*result); + return false; + } else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE] && + argCount == 2 && NPVARIANT_IS_OBJECT(args[0]) && NPVARIANT_IS_STRING(args[1])) { + NPUTF8* propertyString = createCStringFromNPVariant(&args[1]); + NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString); + free(propertyString); + + NPVariant variant; + bool retval = browser->getproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier, &variant); + if (retval) + browser->releasevariantvalue(&variant); + + BOOLEAN_TO_NPVARIANT(retval, *result); + return true; + } + return false; +} + +static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result) +{ + INT32_TO_NPVARIANT(1, *result); + return true; +} + +static void pluginInvalidate(NPObject *obj) +{ +} + +static NPObject *pluginAllocate(NPP npp, NPClass *theClass) +{ + PluginObject *newInstance = (PluginObject*)malloc(sizeof(PluginObject)); + + if (!identifiersInitialized) { + identifiersInitialized = true; + initializeIdentifiers(); + } + + newInstance->npp = npp; + newInstance->testObject = browser->createobject(npp, getTestClass()); + newInstance->eventLogging = FALSE; + newInstance->logDestroy = FALSE; + newInstance->logSetWindow = FALSE; + newInstance->returnErrorFromNewStream = FALSE; + newInstance->stream = 0; + + newInstance->firstUrl = NULL; + newInstance->firstHeaders = NULL; + newInstance->lastUrl = NULL; + newInstance->lastHeaders = NULL; + + return (NPObject *)newInstance; +} + +static void pluginDeallocate(NPObject *header) +{ + PluginObject* obj = (PluginObject*)header; + + browser->releaseobject(obj->testObject); + + free(obj->firstUrl); + free(obj->firstHeaders); + free(obj->lastUrl); + free(obj->lastHeaders); + + free(obj); +} + +void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData) +{ + assert(object); + + NPVariant args[2]; + + NPObject *windowScriptObject; + browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject); + + NPIdentifier callbackIdentifier = notifyData; + + INT32_TO_NPVARIANT(reason, args[0]); + + char *strHdr = NULL; + if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) { + // Format expected by JavaScript validator: four fields separated by \n\n: + // First URL; first header block; last URL; last header block. + // Note that header blocks already end with \n due to how NPStream::headers works. + int len = strlen(object->firstUrl) + 2 + + strlen(object->firstHeaders) + 1 + + strlen(object->lastUrl) + 2 + + strlen(object->lastHeaders) + 1; + strHdr = (char*)malloc(len + 1); + snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n", + object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders); + STRINGN_TO_NPVARIANT(strHdr, len, args[1]); + } else + NULL_TO_NPVARIANT(args[1]); + + NPVariant browserResult; + browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult); + browser->releasevariantvalue(&browserResult); + + free(strHdr); +} + +void notifyStream(PluginObject* object, const char *url, const char *headers) +{ + if (object->firstUrl == NULL) { + if (url) + object->firstUrl = strdup(url); + if (headers) + object->firstHeaders = strdup(headers); + } else { + free(object->lastUrl); + free(object->lastHeaders); + object->lastUrl = (url ? strdup(url) : NULL); + object->lastHeaders = (headers ? strdup(headers) : NULL); + } +} diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h new file mode 100644 index 0000000..31dbb96 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#include <WebKit/npfunctions.h> + +extern NPNetscapeFuncs *browser; + +typedef struct { + NPObject header; + NPP npp; + NPBool eventLogging; + NPBool logSetWindow; + NPBool logDestroy; + NPBool returnErrorFromNewStream; + NPObject* testObject; + NPStream* stream; + char* onStreamLoad; + char* firstUrl; + char* firstHeaders; + char* lastUrl; + char* lastHeaders; +} PluginObject; + +extern NPClass *getPluginClass(void); +extern void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData); +extern void notifyStream(PluginObject* object, const char *url, const char *headers); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/TestObject.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/TestObject.cpp new file mode 100644 index 0000000..a62f6a7 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/TestObject.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#include "TestObject.h" +#include "PluginObject.h" + +static bool testEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count); +static bool testHasProperty(NPObject *obj, NPIdentifier name); +static NPObject *testAllocate(NPP npp, NPClass *theClass); +static void testDeallocate(NPObject *obj); + +static NPClass testClass = { + NP_CLASS_STRUCT_VERSION, + testAllocate, + testDeallocate, + 0, + 0, + 0, + 0, + testHasProperty, + 0, + 0, + 0, + testEnumerate +}; + +NPClass *getTestClass(void) +{ + return &testClass; +} + +static bool identifiersInitialized = false; + +#define NUM_TEST_IDENTIFIERS 2 + +static NPIdentifier testIdentifiers[NUM_TEST_IDENTIFIERS]; +static const NPUTF8 *testIdentifierNames[NUM_TEST_IDENTIFIERS] = { + "foo", + "bar" +}; + +static void initializeIdentifiers(void) +{ + browser->getstringidentifiers(testIdentifierNames, NUM_TEST_IDENTIFIERS, testIdentifiers); +} + +static NPObject *testAllocate(NPP npp, NPClass *theClass) +{ + NPObject *newInstance = (NPObject*)malloc(sizeof(NPObject)); + + if (!identifiersInitialized) { + identifiersInitialized = true; + initializeIdentifiers(); + } + + return newInstance; +} + +static void testDeallocate(NPObject *obj) +{ + free(obj); +} + +static bool testHasProperty(NPObject *obj, NPIdentifier name) +{ + for (unsigned i = 0; i < NUM_TEST_IDENTIFIERS; i++) { + if (testIdentifiers[i] == name) + return true; + } + + return false; +} + + +static bool testEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count) +{ + *count = NUM_TEST_IDENTIFIERS; + + *value = (NPIdentifier*)browser->memalloc(NUM_TEST_IDENTIFIERS * sizeof(NPIdentifier)); + memcpy(*value, testIdentifiers, sizeof(NPIdentifier) * NUM_TEST_IDENTIFIERS); + + return true; +} + + diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/TestObject.h b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/TestObject.h new file mode 100644 index 0000000..1295fb7 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/TestObject.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#include <WebKit/npapi.h> +#include <WebKit/npruntime.h> + +NPClass *getTestClass(void); diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp new file mode 100644 index 0000000..ebbc9e4 --- /dev/null +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "PluginObject.h" + +// Mach-o entry points +extern "C" { + NPError NP_Initialize(NPNetscapeFuncs *browserFuncs); + NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs); + void NP_Shutdown(void); +} + +// Mach-o entry points +NPError NP_Initialize(NPNetscapeFuncs *browserFuncs) +{ + browser = browserFuncs; + return NPERR_NO_ERROR; +} + +NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) +{ + pluginFuncs->version = 11; + pluginFuncs->size = sizeof(pluginFuncs); + pluginFuncs->newp = NPP_New; + pluginFuncs->destroy = NPP_Destroy; + pluginFuncs->setwindow = NPP_SetWindow; + pluginFuncs->newstream = NPP_NewStream; + pluginFuncs->destroystream = NPP_DestroyStream; + pluginFuncs->asfile = NPP_StreamAsFile; + pluginFuncs->writeready = NPP_WriteReady; + pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; + pluginFuncs->print = NPP_Print; + pluginFuncs->event = NPP_HandleEvent; + pluginFuncs->urlnotify = NPP_URLNotify; + pluginFuncs->getvalue = NPP_GetValue; + pluginFuncs->setvalue = NPP_SetValue; + + return NPERR_NO_ERROR; +} + +void NP_Shutdown(void) +{ +} + +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) +{ + if (browser->version >= 14) { + PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass()); + + obj->onStreamLoad = NULL; + + for (int i = 0; i < argc; i++) { + if (strcasecmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad) + obj->onStreamLoad = strdup(argv[i]); + else if (strcasecmp(argn[i], "src") == 0 && + strcasecmp(argv[i], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0) + obj->returnErrorFromNewStream = TRUE; + else if (strcasecmp(argn[i], "logfirstsetwindow") == 0) + obj->logSetWindow = TRUE; + } + + instance->pdata = obj; + } + + return NPERR_NO_ERROR; +} + +NPError NPP_Destroy(NPP instance, NPSavedData **save) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + if (obj) { + if (obj->onStreamLoad) + free(obj->onStreamLoad); + + if (obj->logDestroy) + printf("PLUGIN: NPP_Destroy\n"); + + browser->releaseobject(&obj->header); + } + return NPERR_NO_ERROR; +} + +NPError NPP_SetWindow(NPP instance, NPWindow *window) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + + if (obj) { + if (obj->logSetWindow) { + printf("PLUGIN: NPP_SetWindow: %d %d\n", (int)window->width, (int)window->height); + obj->logSetWindow = false; + } + } + + return NPERR_NO_ERROR; +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + obj->stream = stream; + *stype = NP_ASFILEONLY; + + if (obj->returnErrorFromNewStream) + return NPERR_GENERIC_ERROR; + + if (browser->version >= NPVERS_HAS_RESPONSE_HEADERS) + notifyStream(obj, stream->url, stream->headers); + + if (obj->onStreamLoad) { + NPObject *windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPString script; + script.UTF8Characters = obj->onStreamLoad; + script.UTF8Length = strlen(obj->onStreamLoad); + + NPVariant browserResult; + browser->evaluate(obj->npp, windowScriptObject, &script, &browserResult); + browser->releasevariantvalue(&browserResult); + } + + return NPERR_NO_ERROR; +} + +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) +{ + return NPERR_NO_ERROR; +} + +int32 NPP_WriteReady(NPP instance, NPStream *stream) +{ + return 0; +} + +int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) +{ + return 0; +} + +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) +{ +} + +void NPP_Print(NPP instance, NPPrint *platformPrint) +{ +} + +int16 NPP_HandleEvent(NPP instance, void *event) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + if (!obj->eventLogging) + return 0; + + EventRecord* evt = static_cast<EventRecord*>(event); + Point pt = { evt->where.v, evt->where.h }; + switch (evt->what) { + case nullEvent: + // these are delivered non-deterministically, don't log. + break; + case mouseDown: + GlobalToLocal(&pt); + printf("PLUGIN: mouseDown at (%d, %d)\n", pt.h, pt.v); + break; + case mouseUp: + GlobalToLocal(&pt); + printf("PLUGIN: mouseUp at (%d, %d)\n", pt.h, pt.v); + break; + case keyDown: + printf("PLUGIN: keyDown '%c'\n", (char)(evt->message & 0xFF)); + break; + case keyUp: + printf("PLUGIN: keyUp '%c'\n", (char)(evt->message & 0xFF)); + break; + case autoKey: + printf("PLUGIN: autoKey '%c'\n", (char)(evt->message & 0xFF)); + break; + case updateEvt: + printf("PLUGIN: updateEvt\n"); + break; + case diskEvt: + printf("PLUGIN: diskEvt\n"); + break; + case activateEvt: + printf("PLUGIN: activateEvt\n"); + break; + case osEvt: + printf("PLUGIN: osEvt - "); + switch ((evt->message & 0xFF000000) >> 24) { + case suspendResumeMessage: + printf("%s\n", (evt->message & 0x1) ? "resume" : "suspend"); + break; + case mouseMovedMessage: + printf("mouseMoved\n"); + break; + default: + printf("%08lX\n", evt->message); + } + break; + case kHighLevelEvent: + printf("PLUGIN: kHighLevelEvent\n"); + break; + // NPAPI events + case getFocusEvent: + printf("PLUGIN: getFocusEvent\n"); + break; + case loseFocusEvent: + printf("PLUGIN: loseFocusEvent\n"); + break; + case adjustCursorEvent: + printf("PLUGIN: adjustCursorEvent\n"); + break; + default: + printf("PLUGIN: event %d\n", evt->what); + } + + return 0; +} + +void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + + handleCallback(obj, url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) +{ + if (variable == NPPVpluginScriptableNPObject) { + void **v = (void **)value; + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + // Return value is expected to be retained + browser->retainobject((NPObject *)obj); + *v = obj; + return NPERR_NO_ERROR; + } + return NPERR_GENERIC_ERROR; +} + +NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) +{ + return NPERR_GENERIC_ERROR; +} diff --git a/WebKitTools/DumpRenderTree/WorkQueue.cpp b/WebKitTools/DumpRenderTree/WorkQueue.cpp new file mode 100644 index 0000000..87c7af5 --- /dev/null +++ b/WebKitTools/DumpRenderTree/WorkQueue.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "WorkQueue.h" + +#include "WorkQueueItem.h" +#include <wtf/Assertions.h> + +static const unsigned queueLength = 1024; + +static WorkQueueItem* theQueue[queueLength]; +static unsigned startOfQueue; +static unsigned endOfQueue; + +WorkQueue* WorkQueue::shared() +{ + static WorkQueue* sharedInstance = new WorkQueue; + return sharedInstance; +} + +WorkQueue::WorkQueue() + : m_frozen(false) +{ +} + +void WorkQueue::queue(WorkQueueItem* item) +{ + ASSERT(endOfQueue < queueLength); + ASSERT(endOfQueue >= startOfQueue); + + if (m_frozen) { + delete item; + return; + } + + theQueue[endOfQueue++] = item; +} + +WorkQueueItem* WorkQueue::dequeue() +{ + ASSERT(endOfQueue >= startOfQueue); + + if (startOfQueue == endOfQueue) + return 0; + + return theQueue[startOfQueue++]; +} + +unsigned WorkQueue::count() +{ + return endOfQueue - startOfQueue; +} + +void WorkQueue::clear() +{ + for (unsigned i = startOfQueue; i < endOfQueue; ++i) { + delete theQueue[i]; + theQueue[i] = 0; + } + + startOfQueue = 0; + endOfQueue = 0; +} diff --git a/WebKitTools/DumpRenderTree/WorkQueue.h b/WebKitTools/DumpRenderTree/WorkQueue.h new file mode 100644 index 0000000..c2850c5 --- /dev/null +++ b/WebKitTools/DumpRenderTree/WorkQueue.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef WorkQueue_h +#define WorkQueue_h + +class WorkQueueItem; + +class WorkQueue { +public: + static WorkQueue* shared(); + + void queue(WorkQueueItem*); + WorkQueueItem* dequeue(); + void clear(); + unsigned count(); + + void setFrozen(bool b) { m_frozen = b; } + +private: + WorkQueue(); + + bool m_frozen; +}; + +#endif // !defined(WorkQueue_h) diff --git a/WebKitTools/DumpRenderTree/WorkQueueItem.h b/WebKitTools/DumpRenderTree/WorkQueueItem.h new file mode 100644 index 0000000..fd15329 --- /dev/null +++ b/WebKitTools/DumpRenderTree/WorkQueueItem.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef WorkQueueItem_h +#define WorkQueueItem_h + +#include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/JSBase.h> + +class WorkQueueItem { +public: + virtual ~WorkQueueItem() { } + virtual void invoke() const = 0; +}; + +class LoadItem : public WorkQueueItem { +public: + LoadItem(const JSStringRef url, const JSStringRef target) + : m_url(url) + , m_target(target) + { + } + + const JSStringRef url() const { return m_url.get(); } + const JSStringRef target() const { return m_target.get(); } + + virtual void invoke() const; + +private: + JSRetainPtr<JSStringRef> m_url; + JSRetainPtr<JSStringRef> m_target; +}; + +class ReloadItem : public WorkQueueItem { +public: + virtual void invoke() const; +}; + +class ScriptItem : public WorkQueueItem { +public: + ScriptItem(const JSStringRef script) + : m_script(script) + { + } + + const JSStringRef script() const { return m_script.get(); } + + virtual void invoke() const; + +private: + JSRetainPtr<JSStringRef> m_script; +}; + +class BackForwardItem : public WorkQueueItem { +public: + virtual void invoke() const; + +protected: + BackForwardItem(int howFar) + : m_howFar(howFar) + { + } + + int m_howFar; +}; + +class BackItem : public BackForwardItem { +public: + BackItem(unsigned howFar) + : BackForwardItem(-howFar) + { + } +}; + +class ForwardItem : public BackForwardItem { +public: + ForwardItem(unsigned howFar) + : BackForwardItem(howFar) + { + } +}; + +#endif // !defined(WorkQueueItem_h) diff --git a/WebKitTools/DumpRenderTree/cg/ImageDiffCG.cpp b/WebKitTools/DumpRenderTree/cg/ImageDiffCG.cpp new file mode 100644 index 0000000..6a84b79 --- /dev/null +++ b/WebKitTools/DumpRenderTree/cg/ImageDiffCG.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2005, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2005 Ben La Monica <ben.lamonica@gmail.com>. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR + * 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. + */ + +#define min min + +#include <CoreGraphics/CGBitmapContext.h> +#include <CoreGraphics/CGImage.h> +#include <ImageIO/CGImageDestination.h> +#include <stdio.h> +#include <wtf/Platform.h> +#include <wtf/RetainPtr.h> + +#if PLATFORM(WIN) +#include <fcntl.h> +#include <io.h> +#endif + +#if PLATFORM(MAC) +#include <LaunchServices/UTCoreTypes.h> +#endif + +#ifndef CGFLOAT_DEFINED +#ifdef __LP64__ +typedef double CGFloat; +#else +typedef float CGFloat; +#endif +#define CGFLOAT_DEFINED 1 +#endif + +using namespace std; + +#if PLATFORM(WIN) +static const CFStringRef kUTTypePNG = CFSTR("public.png"); +#endif + +static RetainPtr<CGImageRef> createImageFromStdin(int bytesRemaining) +{ + unsigned char buffer[2048]; + RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(0, bytesRemaining)); + + while (bytesRemaining > 0) { + size_t bytesToRead = min(bytesRemaining, 2048); + size_t bytesRead = fread(buffer, 1, bytesToRead, stdin); + CFDataAppendBytes(data.get(), buffer, static_cast<CFIndex>(bytesRead)); + bytesRemaining -= static_cast<int>(bytesRead); + } + RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get())); + return RetainPtr<CGImageRef>(AdoptCF, CGImageCreateWithPNGDataProvider(dataProvider.get(), 0, false, kCGRenderingIntentDefault)); +} + +static RetainPtr<CGContextRef> getDifferenceBitmap(CGImageRef testBitmap, CGImageRef referenceBitmap) +{ + // we must have both images to take diff + if (!testBitmap || !referenceBitmap) + return 0; + + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); + static CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); + CFDataSetLength(data, CGImageGetHeight(testBitmap) * CGImageGetBytesPerRow(testBitmap)); + RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(CFDataGetMutableBytePtr(data), CGImageGetWidth(testBitmap), CGImageGetHeight(testBitmap), + CGImageGetBitsPerComponent(testBitmap), CGImageGetBytesPerRow(testBitmap), colorSpace.get(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst)); + + CGContextSetBlendMode(context.get(), kCGBlendModeNormal); + CGContextDrawImage(context.get(), CGRectMake(0, 0, static_cast<CGFloat>(CGImageGetWidth(testBitmap)), static_cast<CGFloat>(CGImageGetHeight(testBitmap))), testBitmap); + CGContextSetBlendMode(context.get(), kCGBlendModeDifference); + CGContextDrawImage(context.get(), CGRectMake(0, 0, static_cast<CGFloat>(CGImageGetWidth(referenceBitmap)), static_cast<CGFloat>(CGImageGetHeight(referenceBitmap))), referenceBitmap); + + return context; +} + +/** + * Counts the number of non-black pixels, and returns the percentage + * of non-black pixels to total pixels in the image. + */ +static float computePercentageDifferent(CGContextRef diffBitmap, unsigned threshold) +{ + // if diffBiatmap is nil, then there was an error, and it didn't match. + if (!diffBitmap) + return 100.0f; + + size_t pixelsHigh = CGBitmapContextGetHeight(diffBitmap); + size_t pixelsWide = CGBitmapContextGetWidth(diffBitmap); + size_t bytesPerRow = CGBitmapContextGetBytesPerRow(diffBitmap); + unsigned char* pixelRowData = static_cast<unsigned char*>(CGBitmapContextGetData(diffBitmap)); + unsigned differences = 0; + + // NOTE: This may not be safe when switching between ENDIAN types + for (unsigned row = 0; row < pixelsHigh; row++) { + for (unsigned col = 0; col < (pixelsWide * 4); col += 4) { + unsigned char* red = pixelRowData + col; + unsigned char* green = red + 1; + unsigned char* blue = red + 2; + unsigned distance = *red + *green + *blue; + if (distance > threshold) { + differences++; + // shift the pixels towards white to make them more visible + *red = static_cast<unsigned char>(min(UCHAR_MAX, *red + 100)); + *green = static_cast<unsigned char>(min(UCHAR_MAX, *green + 100)); + *blue = static_cast<unsigned char>(min(UCHAR_MAX, *blue + 100)); + } + } + pixelRowData += bytesPerRow; + } + + float totalPixels = static_cast<float>(pixelsHigh * pixelsWide); + return (differences * 100.f) / totalPixels; +} + +static void compareImages(CGImageRef actualBitmap, CGImageRef baselineBitmap, unsigned threshold) +{ + // prepare the difference blend to check for pixel variations + RetainPtr<CGContextRef> diffBitmap = getDifferenceBitmap(actualBitmap, baselineBitmap); + + float percentage = computePercentageDifferent(diffBitmap.get(), threshold); + + percentage = (float)((int)(percentage * 100.0f)) / 100.0f; // round to 2 decimal places + + // send message to let them know if an image was wrong + if (percentage > 0.0f) { + // since the diff might actually show something, send it to stdout + RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(diffBitmap.get())); + RetainPtr<CFMutableDataRef> imageData(AdoptCF, CFDataCreateMutable(0, 0)); + RetainPtr<CGImageDestinationRef> imageDest(AdoptCF, CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0)); + CGImageDestinationAddImage(imageDest.get(), image.get(), 0); + CGImageDestinationFinalize(imageDest.get()); + printf("Content-length: %lu\n", CFDataGetLength(imageData.get())); + fwrite(CFDataGetBytePtr(imageData.get()), 1, CFDataGetLength(imageData.get()), stdout); + fprintf(stdout, "diff: %01.2f%% failed\n", percentage); + } else + fprintf(stdout, "diff: %01.2f%% passed\n", percentage); +} + +int main(int argc, const char* argv[]) +{ +#if PLATFORM(WIN) + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); +#endif + + unsigned threshold = 0; + + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "--threshold")) { + if (i >= argc - 1) + exit(1); + threshold = strtol(argv[i + 1], 0, 0); + ++i; + continue; + } + } + + char buffer[2048]; + RetainPtr<CGImageRef> actualImage; + RetainPtr<CGImageRef> baselineImage; + + while (fgets(buffer, sizeof(buffer), stdin)) { + // remove the CR + char* newLineCharacter = strchr(buffer, '\n'); + if (newLineCharacter) + *newLineCharacter = '\0'; + + if (!strncmp("Content-length: ", buffer, 16)) { + strtok(buffer, " "); + int imageSize = strtol(strtok(0, " "), 0, 10); + + if (imageSize > 0 && !actualImage) + actualImage = createImageFromStdin(imageSize); + else if (imageSize > 0 && !baselineImage) + baselineImage = createImageFromStdin(imageSize); + else + fputs("error, image size must be specified.\n", stdout); + } + + if (actualImage && baselineImage) { + compareImages(actualImage.get(), baselineImage.get(), threshold); + actualImage = 0; + baselineImage = 0; + } + + fflush(stdout); + } + + return 0; +} diff --git a/WebKitTools/DumpRenderTree/cg/PixelDumpSupportCG.cpp b/WebKitTools/DumpRenderTree/cg/PixelDumpSupportCG.cpp new file mode 100644 index 0000000..e2e790c --- /dev/null +++ b/WebKitTools/DumpRenderTree/cg/PixelDumpSupportCG.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "DumpRenderTree.h" +#include "PixelDumpSupportCG.h" + +#include "LayoutTestController.h" +#include <ImageIO/CGImageDestination.h> +#include <wtf/Assertions.h> +#include <wtf/RetainPtr.h> +#include <wtf/StringExtras.h> + +#if PLATFORM(WIN) +#include "MD5.h" +#elif PLATFORM(MAC) +#include <LaunchServices/UTCoreTypes.h> +#define COMMON_DIGEST_FOR_OPENSSL +#include <CommonCrypto/CommonDigest.h> +#endif + +#if PLATFORM(WIN) +static const CFStringRef kUTTypePNG = CFSTR("public.png"); +#endif + +static void printPNG(CGImageRef image) +{ + RetainPtr<CFMutableDataRef> imageData(AdoptCF, CFDataCreateMutable(0, 0)); + RetainPtr<CGImageDestinationRef> imageDest(AdoptCF, CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0)); + CGImageDestinationAddImage(imageDest.get(), image, 0); + CGImageDestinationFinalize(imageDest.get()); + printf("Content-length: %lu\n", CFDataGetLength(imageData.get())); + fwrite(CFDataGetBytePtr(imageData.get()), 1, CFDataGetLength(imageData.get()), stdout); +} + +static void getMD5HashStringForBitmap(CGContextRef bitmap, char string[33]) +{ + MD5_CTX md5Context; + unsigned char hash[16]; + + size_t bitsPerPixel = CGBitmapContextGetBitsPerPixel(bitmap); + ASSERT(bitsPerPixel == 32); // ImageDiff assumes 32 bit RGBA, we must as well. + size_t bytesPerPixel = bitsPerPixel / 8; + size_t pixelsHigh = CGBitmapContextGetHeight(bitmap); + size_t pixelsWide = CGBitmapContextGetWidth(bitmap); + size_t bytesPerRow = CGBitmapContextGetBytesPerRow(bitmap); + ASSERT(bytesPerRow >= (pixelsWide * bytesPerPixel)); + + MD5_Init(&md5Context); + unsigned char* bitmapData = static_cast<unsigned char*>(CGBitmapContextGetData(bitmap)); + for (unsigned row = 0; row < pixelsHigh; row++) { + MD5_Update(&md5Context, bitmapData, static_cast<unsigned>(pixelsWide * bytesPerPixel)); + bitmapData += bytesPerRow; + } + MD5_Final(hash, &md5Context); + + string[0] = '\0'; + for (int i = 0; i < 16; i++) + snprintf(string, 33, "%s%02x", string, hash[i]); +} + +void drawSelectionRect(CGContextRef context, const CGRect& rect) +{ + CGContextSaveGState(context); + CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0); + CGContextStrokeRect(context, rect); + CGContextRestoreGState(context); +} + +void dumpWebViewAsPixelsAndCompareWithExpected(const char* /*currentTest*/, bool /*forceAllTestsToDumpPixels*/) +{ + RetainPtr<CGContextRef> context = getBitmapContextFromWebView(); + +#if PLATFORM(MAC) + if (layoutTestController->testRepaint()) + repaintWebView(context.get(), layoutTestController->testRepaintSweepHorizontally()); + else + paintWebView(context.get()); + + if (layoutTestController->dumpSelectionRect()) + drawSelectionRect(context.get(), getSelectionRect()); +#endif + + // Compute the actual hash to compare to the expected image's hash. + char actualHash[33]; + getMD5HashStringForBitmap(context.get(), actualHash); + printf("\nActualHash: %s\n", actualHash); + + // FIXME: We should compare the actualHash to the expected hash here and + // only set dumpImage to true if they don't match, but DRT doesn't have + // enough information currently to find the expected checksum file. + bool dumpImage = true; + + if (dumpImage) { + RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context.get())); + printPNG(image.get()); + } + + printf("#EOF\n"); +} diff --git a/WebKitTools/DumpRenderTree/cg/PixelDumpSupportCG.h b/WebKitTools/DumpRenderTree/cg/PixelDumpSupportCG.h new file mode 100644 index 0000000..0abdea6 --- /dev/null +++ b/WebKitTools/DumpRenderTree/cg/PixelDumpSupportCG.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef PixelDumpSupportCG_h +#define PixelDumpSupportCG_h + +#include <wtf/RetainPtr.h> + +#ifndef CGFLOAT_DEFINED +#ifdef __LP64__ +typedef double CGFloat; +#else +typedef float CGFloat; +#endif +#define CGFLOAT_DEFINED 1 +#endif + +typedef struct CGContext* CGContextRef; +struct CGRect; + +RetainPtr<CGContextRef> getBitmapContextFromWebView(); +CGRect getSelectionRect(); + +void paintWebView(CGContextRef); +void repaintWebView(CGContextRef context, bool horizontal); +void drawSelectionRect(CGContextRef, const CGRect&); + +#endif // PixelDumpSupportCG_h diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp new file mode 100644 index 0000000..271da15 --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "LayoutTestController.h" +#include "WorkQueue.h" +#include "WorkQueueItem.h" + +#include <gtk/gtk.h> +#include <webkit/webkit.h> + +#include <JavaScriptCore/JSBase.h> +#include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/JSObjectRef.h> +#include <JavaScriptCore/JSStringRef.h> +#include <JavaScriptCore/JSValueRef.h> + +#include <wtf/Assertions.h> + +#include <cassert> +#include <getopt.h> +#include <stdlib.h> +#include <string.h> + +extern "C" { +// This API is not yet public. +extern GSList* webkit_web_frame_get_children(WebKitWebFrame* frame); +extern gchar* webkit_web_frame_get_inner_text(WebKitWebFrame* frame); +} + +volatile bool done; +static bool printSeparators; +static int testRepaintDefault; +static int repaintSweepHorizontallyDefault; +static int dumpPixels; +static int dumpTree = 1; +static gchar* currentTest; + +LayoutTestController* layoutTestController = 0; +static WebKitWebView* webView; +WebKitWebFrame* mainFrame = 0; +WebKitWebFrame* topLoadingFrame = 0; +guint waitToDumpWatchdog = 0; + +const unsigned maxViewHeight = 600; +const unsigned maxViewWidth = 800; + +static gchar* autocorrectURL(const gchar* url) +{ + if (strncmp("http://", url, 7) != 0 && strncmp("https://", url, 8) != 0) { + GString* string = g_string_new("file://"); + g_string_append(string, url); + return g_string_free(string, FALSE); + } + + return g_strdup(url); +} + +static bool shouldLogFrameLoadDelegates(const char* pathOrURL) +{ + return strstr(pathOrURL, "loading/"); +} + +void dumpFrameScrollPosition(WebKitWebFrame* frame) +{ + +} + +void displayWebView() +{ + +} + +static void appendString(gchar*& target, gchar* string) +{ + gchar* oldString = target; + target = g_strconcat(target, string, NULL); + g_free(oldString); +} + +static gchar* dumpFramesAsText(WebKitWebFrame* frame) +{ + gchar* result = 0; + + // Add header for all but the main frame. + bool isMainFrame = (webkit_web_view_get_main_frame(webView) == frame); + + if (isMainFrame) { + gchar* innerText = webkit_web_frame_get_inner_text(frame); + result = g_strdup_printf("%s\n", innerText); + g_free(innerText); + } else { + const gchar* frameName = webkit_web_frame_get_name(frame); + gchar* innerText = webkit_web_frame_get_inner_text(frame); + + result = g_strdup_printf("\n--------\nFrame: '%s'\n--------\n%s\n", frameName, innerText); + + g_free(innerText); + } + + if (layoutTestController->dumpChildFramesAsText()) { + GSList* children = webkit_web_frame_get_children(frame); + for (;children; children = g_slist_next(children)) + appendString(result, dumpFramesAsText((WebKitWebFrame*)children->data)); + } + + return result; +} + +static gchar* dumpRenderTreeAsText(WebKitWebFrame* frame) +{ + // FIXME: this will require new WebKitGtk SPI + return strdup("foo"); +} + +static void invalidateAnyPreviousWaitToDumpWatchdog() +{ + if (waitToDumpWatchdog) { + g_source_remove(waitToDumpWatchdog); + waitToDumpWatchdog = 0; + } +} + +void dump() +{ + invalidateAnyPreviousWaitToDumpWatchdog(); + if (dumpTree) { + char* result = 0; + + bool dumpAsText = layoutTestController->dumpAsText(); + // FIXME: Also dump text resuls as text. + layoutTestController->setDumpAsText(dumpAsText); + if (layoutTestController->dumpAsText()) + result = dumpFramesAsText(mainFrame); + else { + bool isSVGW3CTest = (g_strrstr(currentTest, "svg/W3C-SVG-1.1")); + if (isSVGW3CTest) + gtk_widget_set_size_request(GTK_WIDGET(webView), 480, 360); + else + gtk_widget_set_size_request(GTK_WIDGET(webView), maxViewWidth, maxViewHeight); + result = dumpRenderTreeAsText(mainFrame); + } + + if (!result) { + const char* errorMessage; + if (layoutTestController->dumpAsText()) + errorMessage = "[documentElement innerText]"; + else if (layoutTestController->dumpDOMAsWebArchive()) + errorMessage = "[[mainFrame DOMDocument] webArchive]"; + else if (layoutTestController->dumpSourceAsWebArchive()) + errorMessage = "[[mainFrame dataSource] webArchive]"; + else + errorMessage = "[mainFrame renderTreeAsExternalRepresentation]"; + printf("ERROR: nil result from %s", errorMessage); + } else { + printf("%s", result); + g_free(result); + if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive()) + dumpFrameScrollPosition(mainFrame); + } + + if (layoutTestController->dumpBackForwardList()) { + // FIXME: not implemented + } + + if (printSeparators) + puts("#EOF"); + } + + if (dumpPixels) { + if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive()) { + // FIXME: Add support for dumping pixels + } + } + + fflush(stdout); + + // FIXME: call displayWebView here when we support --paint + + done = true; +} + +static void runTest(const char* pathOrURL) +{ + gchar* url = autocorrectURL(pathOrURL); + + layoutTestController = new LayoutTestController(testRepaintDefault, repaintSweepHorizontallyDefault); + + done = false; + topLoadingFrame = 0; + + if (shouldLogFrameLoadDelegates(pathOrURL)) + layoutTestController->setDumpFrameLoadCallbacks(true); + + if (currentTest) + g_free(currentTest); + currentTest = url; + + WorkQueue::shared()->clear(); + WorkQueue::shared()->setFrozen(false); + + webkit_web_view_open(webView, url); + + while (!done) + g_main_context_iteration(NULL, true); + + WorkQueue::shared()->clear(); + + delete layoutTestController; + layoutTestController = 0; +} + +void webViewLoadStarted(WebKitWebView* view, WebKitWebFrame* frame, void*) +{ + // Make sure we only set this once per test. If it gets cleared, and then set again, we might + // end up doing two dumps for one test. + if (!topLoadingFrame && !done) + topLoadingFrame = frame; +} + +static gboolean processWork(void* data) +{ + // quit doing work once a load is in progress + while (WorkQueue::shared()->count() > 0 && !topLoadingFrame) { + WorkQueueItem* item = WorkQueue::shared()->dequeue(); + ASSERT(item); + item->invoke(); + delete item; + } + + // if we didn't start a new load, then we finished all the commands, so we're ready to dump state + if (!topLoadingFrame && !layoutTestController->waitToDump()) + dump(); + + return FALSE; +} + +void webViewLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*) +{ + if (frame != topLoadingFrame) + return; + + topLoadingFrame = 0; + WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test + if (layoutTestController->waitToDump()) + return; + + if (WorkQueue::shared()->count()) + g_timeout_add(0, processWork, 0); + else + dump(); +} + +void webViewWindowObjectCleared(WebKitWebView* view, WebKitWebFrame* frame, JSGlobalContextRef context, JSObjectRef globalObject) +{ + JSValueRef exception = 0; + assert(layoutTestController); + layoutTestController->makeWindowObject(context, globalObject, &exception); + assert(!exception); +} + +gboolean webViewConsoleMessage(WebKitWebView* view, const gchar* message, unsigned int line, const gchar* sourceId) +{ + fprintf(stdout, "CONSOLE MESSAGE: line %d: %s\n", line, message); + return TRUE; +} + + +gboolean webViewScriptAlert(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message) +{ + fprintf(stdout, "ALERT: %s\n", message); + return TRUE; +} + +gboolean webViewScriptPrompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value) +{ + fprintf(stdout, "PROMPT: %s, default text: %s\n", message, defaultValue); + *value = g_strdup(defaultValue); + return TRUE; +} + +gboolean webViewScriptConfirm(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm) +{ + fprintf(stdout, "CONFIRM: %s\n", message); + *didConfirm = TRUE; + return TRUE; +} + + +int main(int argc, char* argv[]) +{ + struct option options[] = { + {"horizontal-sweep", no_argument, &repaintSweepHorizontallyDefault, true}, + {"notree", no_argument, &dumpTree, false}, + {"pixel-tests", no_argument, &dumpPixels, true}, + {"repaint", no_argument, &testRepaintDefault, true}, + {"tree", no_argument, &dumpTree, true}, + {NULL, 0, NULL, 0} + }; + + int option; + while ((option = getopt_long(argc, (char* const*)argv, "", options, NULL)) != -1) + switch (option) { + case '?': // unknown or ambiguous option + case ':': // missing argument + exit(1); + break; + } + + gtk_init(&argc, &argv); + + GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP); + GtkContainer* container = GTK_CONTAINER(gtk_fixed_new()); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(container)); + gtk_widget_realize(window); + + webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + gtk_container_add(container, GTK_WIDGET(webView)); + gtk_widget_realize(GTK_WIDGET(webView)); + mainFrame = webkit_web_view_get_main_frame(webView); + + g_signal_connect(G_OBJECT(webView), "load-started", G_CALLBACK(webViewLoadStarted), 0); + g_signal_connect(G_OBJECT(webView), "load-finished", G_CALLBACK(webViewLoadFinished), 0); + g_signal_connect(G_OBJECT(webView), "window-object-cleared", G_CALLBACK(webViewWindowObjectCleared), 0); + g_signal_connect(G_OBJECT(webView), "console-message", G_CALLBACK(webViewConsoleMessage), 0); + g_signal_connect(G_OBJECT(webView), "script-alert", G_CALLBACK(webViewScriptAlert), 0); + g_signal_connect(G_OBJECT(webView), "script-prompt", G_CALLBACK(webViewScriptPrompt), 0); + g_signal_connect(G_OBJECT(webView), "script-confirm", G_CALLBACK(webViewScriptConfirm), 0); + + if (argc == optind+1 && strcmp(argv[optind], "-") == 0) { + char filenameBuffer[2048]; + printSeparators = true; + while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { + char* newLineCharacter = strchr(filenameBuffer, '\n'); + if (newLineCharacter) + *newLineCharacter = '\0'; + + if (strlen(filenameBuffer) == 0) + continue; + + runTest(filenameBuffer); + } + } else { + printSeparators = (optind < argc-1 || (dumpPixels && dumpTree)); + for (int i = optind; i != argc; ++i) + runTest(argv[i]); + } + + return 0; +} diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.pro b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.pro new file mode 100644 index 0000000..51fdd65 --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.pro @@ -0,0 +1,19 @@ +TEMPLATE = app +SOURCES += DumpRenderTree.cpp \ + ../LayoutTestController.cpp \ + ../GCController.cpp \ + ../WorkQueue.cpp \ + GCControllerGtk.cpp \ + LayoutTestControllerGtk.cpp \ + WorkQueueItemGtk.cpp + +CONFIG -= app_bundle + +BASE_DIR = $$PWD/../../.. + +include(../../../WebKit.pri) + +INCLUDEPATH += \ + $$BASE_DIR/WebKitTools/DumpRenderTree + +QMAKE_RPATHDIR += $$OUTPUT_DIR/lib diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTreeGtk.h b/WebKitTools/DumpRenderTree/gtk/DumpRenderTreeGtk.h new file mode 100644 index 0000000..7be651a --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTreeGtk.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#ifndef DumpRenderTreeGtk_h +#define DumpRenderTreeGtk_h + +#include <webkit/webkitdefines.h> + +extern WebKitWebFrame* mainFrame; +extern WebKitWebFrame* topLoadingFrame; +extern guint waitToDumpWatchdog; + +#endif // DumpRenderTreeGtk_h diff --git a/WebKitTools/DumpRenderTree/gtk/GCControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/GCControllerGtk.cpp new file mode 100644 index 0000000..b3e6ad3 --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/GCControllerGtk.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "GCController.h" + +void GCController::collect() const +{ +} + +void GCController::collectOnAlternateThread(bool waitUntilDone) const +{ +} + +size_t GCController::getJSObjectCount() const +{ + return 0; +} diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp new file mode 100644 index 0000000..eae73db --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "LayoutTestController.h" + +#include "DumpRenderTree.h" +#include "WorkQueue.h" +#include "WorkQueueItem.h" +#include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/JSStringRef.h> + +#include <glib.h> + +LayoutTestController::~LayoutTestController() +{ + // FIXME: implement +} + +void LayoutTestController::addDisallowedURL(JSStringRef url) +{ + // FIXME: implement +} + +void LayoutTestController::clearBackForwardList() +{ + // FIXME: implement +} + +JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name) +{ + // FIXME: implement + return 0; +} + +JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name) +{ + // FIXME: implement + return 0; +} + +void LayoutTestController::display() +{ + displayWebView(); +} + +void LayoutTestController::keepWebHistory() +{ + // FIXME: implement +} + +void LayoutTestController::notifyDone() +{ + if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count()) + dump(); + m_waitToDump = false; +} + +JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url) +{ + // Function introduced in r28690. This may need special-casing on Windows. + return url; // Do nothing on Unix. +} + +void LayoutTestController::queueBackNavigation(int howFarBack) +{ + WorkQueue::shared()->queue(new BackItem(howFarBack)); +} + +void LayoutTestController::queueForwardNavigation(int howFarForward) +{ + WorkQueue::shared()->queue(new ForwardItem(howFarForward)); +} + +void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target) +{ + // FIXME: We need to resolve relative URLs here + WorkQueue::shared()->queue(new LoadItem(url, target)); +} + +void LayoutTestController::queueReload() +{ + WorkQueue::shared()->queue(new ReloadItem); +} + +void LayoutTestController::queueScript(JSStringRef script) +{ + WorkQueue::shared()->queue(new ScriptItem(script)); +} + +void LayoutTestController::setAcceptsEditing(bool newAcceptsEditing) +{ + // FIXME: implement +} + +void LayoutTestController::setCustomPolicyDelegate(bool setDelegate) +{ + // FIXME: implement +} + +void LayoutTestController::setMainFrameIsFirstResponder(bool flag) +{ + // FIXME: implement +} + +void LayoutTestController::setTabKeyCyclesThroughElements(bool cycles) +{ + // FIXME: implement +} + +void LayoutTestController::setUseDashboardCompatibilityMode(bool flag) +{ + // FIXME: implement +} + +void LayoutTestController::setUserStyleSheetEnabled(bool flag) +{ + // FIXME: implement +} + +void LayoutTestController::setUserStyleSheetLocation(JSStringRef path) +{ + // FIXME: implement +} + +void LayoutTestController::setWindowIsKey(bool windowIsKey) +{ + // FIXME: implement +} + +static gboolean waitToDumpWatchdogFired(void*) +{ + const char* message = "FAIL: Timed out waiting for notifyDone to be called\n"; + fprintf(stderr, "%s", message); + fprintf(stdout, "%s", message); + dump(); + return FALSE; +} + +void LayoutTestController::setWaitToDump(bool waitUntilDone) +{ + static const int timeoutSeconds = 10; + + m_waitToDump = waitUntilDone; + if (m_waitToDump && !waitToDumpWatchdog) +#if GLIB_CHECK_VERSION(2,14,0) + waitToDumpWatchdog = g_timeout_add_seconds(timeoutSeconds, waitToDumpWatchdogFired, 0); +#else + waitToDumpWatchdog = g_timeout_add(timeoutSeconds * 1000, waitToDumpWatchdogFired, 0); +#endif +} + +int LayoutTestController::windowCount() +{ + // FIXME: implement + return 0; +} + +void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled) +{ + // FIXME: implement +} + +void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag) +{ + // FIXME: implement +} + +void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled) +{ + // FIXME: implement +} + +void LayoutTestController::execCommand(JSStringRef name, JSStringRef value) +{ + // FIXME: implement +} + +void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL) +{ + // FIXME: implement +} + +void LayoutTestController::clearPersistentUserStyleSheet() +{ + // FIXME: implement +} + +void LayoutTestController::clearAllDatabases() +{ + // FIXME: implement +} + +void LayoutTestController::setDatabaseQuota(unsigned long long quota) +{ + // FIXME: implement +} + diff --git a/WebKitTools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp b/WebKitTools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp new file mode 100644 index 0000000..ee77683 --- /dev/null +++ b/WebKitTools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "WorkQueueItem.h" +#include "DumpRenderTree.h" + +#include <JavaScriptCore/JSStringRef.h> +#include <webkit/webkit.h> + +// Returns a newly allocated UTF-8 character buffer which must be freed with g_free() +static gchar* JSStringCopyUTF8CString(JSStringRef jsString) +{ + size_t dataSize = JSStringGetMaximumUTF8CStringSize(jsString); + gchar* utf8 = (gchar*)g_malloc(dataSize); + JSStringGetUTF8CString(jsString, utf8, dataSize); + + return utf8; +} + +void LoadItem::invoke() const +{ + gchar* targetString = JSStringCopyUTF8CString(target()); + + WebKitWebFrame* targetFrame; + if (!strlen(targetString)) + targetFrame = mainFrame; + else + targetFrame = webkit_web_frame_find_frame(mainFrame, targetString); + g_free(targetString); + + gchar* urlString = JSStringCopyUTF8CString(url()); + WebKitNetworkRequest* request = webkit_network_request_new(urlString); + g_free(urlString); + webkit_web_frame_load_request(targetFrame, request); + g_object_unref(request); +} + +void ReloadItem::invoke() const +{ + webkit_web_frame_reload(mainFrame); +} + +void ScriptItem::invoke() const +{ + WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); + gchar* scriptString = JSStringCopyUTF8CString(script()); + // TODO: does this return something we need to free? If not, why not? + webkit_web_view_execute_script(webView, scriptString); + g_free(scriptString); +} + +void BackForwardItem::invoke() const +{ + WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); + webkit_web_view_go_back_or_forward(webView, m_howFar); +} diff --git a/WebKitTools/DumpRenderTree/mac/AppleScriptController.h b/WebKitTools/DumpRenderTree/mac/AppleScriptController.h new file mode 100644 index 0000000..c29789c --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/AppleScriptController.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * + * 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 <Foundation/Foundation.h> + +@class WebView; + +@interface AppleScriptController : NSObject +{ + WebView *webView; +} +- (id)initWithWebView:(WebView *)view; +@end diff --git a/WebKitTools/DumpRenderTree/mac/AppleScriptController.m b/WebKitTools/DumpRenderTree/mac/AppleScriptController.m new file mode 100644 index 0000000..86d2881 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/AppleScriptController.m @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * + * 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 "AppleScriptController.h" + +#import <WebKit/WebView.h> +#import <WebKit/WebViewPrivate.h> // for aeDescByEvaluatingJavaScriptFromString, which is pending API review + +@implementation AppleScriptController + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(doJavaScript:)) + return NO; + return YES; +} + ++ (NSString *)webScriptNameForSelector:(SEL)aSelector +{ + if (aSelector == @selector(doJavaScript:)) + return @"doJavaScript"; + + return nil; +} + +- (id)initWithWebView:(WebView *)wv +{ + self = [super init]; + webView = wv; + return self; +} + +static id convertAEDescToObject(NSAppleEventDescriptor *aeDesc) +{ + id value = nil; + + DescType descType = [aeDesc descriptorType]; + switch (descType) { + case typeUnicodeText: + value = [NSString stringWithFormat:@"\"%@\"", [aeDesc stringValue]]; + break; + case typeLongDateTime: + if ([[aeDesc data] length] == sizeof(LongDateTime)) { + LongDateTime d; + [[aeDesc data] getBytes:&d]; + value = [NSString stringWithFormat:@"%016llX", (unsigned long long)d]; + } + break; + case typeAEList: + value = [NSMutableString stringWithString:@"("]; + int numItems = [aeDesc numberOfItems]; + for (int i = 0; i < numItems; ++i) { + if (i != 0) + [(NSMutableString*)value appendString:@", "]; + id obj = convertAEDescToObject([aeDesc descriptorAtIndex:(i + 1)]); + [(NSMutableString*)value appendString:[obj description]]; + } + [(NSMutableString*)value appendString:@")"]; + break; + case typeType: { + OSType type = [aeDesc typeCodeValue]; + + char typeStr[5]; + typeStr[0] = type >> 24; + typeStr[1] = type >> 16; + typeStr[2] = type >> 8; + typeStr[3] = type; + typeStr[4] = 0; + + value = [NSString stringWithFormat:@"'%s'", typeStr]; + break; + } + } + + if (!value) + value = [aeDesc stringValue]; + if (!value) + value = [aeDesc data]; + + return value; +} + +- (NSString *)doJavaScript:(NSString *)aString +{ + NSAppleEventDescriptor *aeDesc = [webView aeDescByEvaluatingJavaScriptFromString:aString]; + if (!aeDesc) + return @"(null)"; + + DescType descType = [aeDesc descriptorType]; + char descTypeStr[5]; + descTypeStr[0] = descType >> 24; + descTypeStr[1] = descType >> 16; + descTypeStr[2] = descType >> 8; + descTypeStr[3] = descType; + descTypeStr[4] = 0; + + return [NSString stringWithFormat:@"%@ ('%s')", convertAEDescToObject(aeDesc), descTypeStr]; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp new file mode 100644 index 0000000..467f1bb --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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 "CheckedMalloc.h" + +#import <malloc/malloc.h> + +static void* (*savedMalloc)(malloc_zone_t*, size_t); +static void* (*savedRealloc)(malloc_zone_t*, void*, size_t); + +static void* checkedMalloc(malloc_zone_t* zone, size_t size) +{ + if (size >= 0x10000000) + return 0; + return savedMalloc(zone, size); +} + +static void* checkedRealloc(malloc_zone_t* zone, void* ptr, size_t size) +{ + if (size >= 0x10000000) + return 0; + return savedRealloc(zone, ptr, size); +} + +void makeLargeMallocFailSilently() +{ + malloc_zone_t* zone = malloc_default_zone(); + savedMalloc = zone->malloc; + savedRealloc = zone->realloc; + zone->malloc = checkedMalloc; + zone->realloc = checkedRealloc; +} diff --git a/WebKitTools/DumpRenderTree/mac/CheckedMalloc.h b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.h new file mode 100644 index 0000000..c03bd20 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +void makeLargeMallocFailSilently(); diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig new file mode 100644 index 0000000..d2291a0 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig @@ -0,0 +1,16 @@ +HEADER_SEARCH_PATHS = ForwardingHeaders +FRAMEWORK_SEARCH_PATHS = $(FRAMEWORK_SEARCH_PATHS_$(MAC_OS_X_VERSION_MAJOR)); +FRAMEWORK_SEARCH_PATHS_ = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks +FRAMEWORK_SEARCH_PATHS_1040 = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks +FRAMEWORK_SEARCH_PATHS_1050 = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks +FRAMEWORK_SEARCH_PATHS_1060 = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks +DEBUG_INFORMATION_FORMAT = dwarf +PREBINDING = NO +GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_PRECOMPILE_PREFIX_HEADER = YES +GCC_TREAT_WARNINGS_AS_ERRORS = YES +GCC_WARN_UNUSED_FUNCTION = YES +GCC_WARN_UNUSED_VARIABLE = YES +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO +WARNING_CFLAGS = -Wall -W -Wno-unused-parameter +VALID_ARCHS = ppc7400 ppc970 i386 ppc diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig new file mode 100644 index 0000000..e17439e --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig @@ -0,0 +1,5 @@ +#include "Base.xcconfig" +MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(MAC_OS_X_VERSION_MAJOR)) +MACOSX_DEPLOYMENT_TARGET_ = 10.4 +MACOSX_DEPLOYMENT_TARGET_1040 = 10.4 +MACOSX_DEPLOYMENT_TARGET_1050 = 10.5 diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/DumpRenderTree.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/DumpRenderTree.xcconfig new file mode 100644 index 0000000..c8a7bdc --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/Configurations/DumpRenderTree.xcconfig @@ -0,0 +1,4 @@ +OTHER_LDFLAGS = -sectcreate __DATA Ahem qt/fonts/AHEM____.TTF +PRODUCT_NAME = DumpRenderTree +GCC_ENABLE_OBJC_EXCEPTIONS = YES +GCC_PREFIX_HEADER = DumpRenderTreePrefix.h diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/ImageDiff.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/ImageDiff.xcconfig new file mode 100644 index 0000000..fcd64c5 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/Configurations/ImageDiff.xcconfig @@ -0,0 +1 @@ +PRODUCT_NAME = ImageDiff diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/TestNetscapePlugIn.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/TestNetscapePlugIn.xcconfig new file mode 100644 index 0000000..ea17629 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/Configurations/TestNetscapePlugIn.xcconfig @@ -0,0 +1,6 @@ +PRODUCT_NAME = TestNetscapePlugIn +WRAPPER_EXTENSION = plugin +INFOPLIST_FILE = TestNetscapePlugIn.subproj/Info.plist +INSTALL_PATH = "$(USER_LIBRARY_DIR)/Plugins" +WARNING_CFLAGS = -Wmost -Wno-four-char-constants -Wno-unknown-pragmas +LIBRARY_STYLE = BUNDLE diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm new file mode 100644 index 0000000..4d5ea72 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm @@ -0,0 +1,931 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * + * 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 "DumpRenderTree.h" + +#import "CheckedMalloc.h" +#import "DumpRenderTreePasteboard.h" +#import "DumpRenderTreeWindow.h" +#import "EditingDelegate.h" +#import "EventSendingController.h" +#import "FrameLoadDelegate.h" +#import "JavaScriptThreading.h" +#import "LayoutTestController.h" +#import "NavigationController.h" +#import "ObjCPlugin.h" +#import "ObjCPluginFunction.h" +#import "PixelDumpSupport.h" +#import "PolicyDelegate.h" +#import "ResourceLoadDelegate.h" +#import "UIDelegate.h" +#import "WorkQueue.h" +#import "WorkQueueItem.h" +#import <CoreFoundation/CoreFoundation.h> +#import <WebKit/DOMElementPrivate.h> +#import <WebKit/DOMExtensions.h> +#import <WebKit/DOMRange.h> +#import <WebKit/WebBackForwardList.h> +#import <WebKit/WebCoreStatistics.h> +#import <WebKit/WebDatabaseManagerPrivate.h> +#import <WebKit/WebDataSourcePrivate.h> +#import <WebKit/WebDocumentPrivate.h> +#import <WebKit/WebEditingDelegate.h> +#import <WebKit/WebFrameView.h> +#import <WebKit/WebHistory.h> +#import <WebKit/WebHistoryItemPrivate.h> +#import <WebKit/WebPluginDatabase.h> +#import <WebKit/WebPreferences.h> +#import <WebKit/WebPreferencesPrivate.h> +#import <WebKit/WebResourceLoadDelegate.h> +#import <WebKit/WebViewPrivate.h> +#import <getopt.h> +#import <mach-o/getsect.h> +#import <objc/objc-runtime.h> +#import <wtf/Assertions.h> +#import <wtf/RetainPtr.h> + +@interface DumpRenderTreeEvent : NSEvent +@end + +static void runTest(const char *pathOrURL); + +// Deciding when it's OK to dump out the state is a bit tricky. All these must be true: +// - There is no load in progress +// - There is no work queued up (see workQueue var, below) +// - waitToDump==NO. This means either waitUntilDone was never called, or it was called +// and notifyDone was called subsequently. +// Note that the call to notifyDone and the end of the load can happen in either order. + +volatile bool done; + +NavigationController* navigationController = 0; +LayoutTestController* layoutTestController = 0; + +WebFrame *mainFrame = 0; +// This is the topmost frame that is loading, during a given load, or nil when no load is +// in progress. Usually this is the same as the main frame, but not always. In the case +// where a frameset is loaded, and then new content is loaded into one of the child frames, +// that child frame is the "topmost frame that is loading". +WebFrame *topLoadingFrame = nil; // !nil iff a load is in progress + + +CFMutableSetRef disallowedURLs = 0; +CFRunLoopTimerRef waitToDumpWatchdog = 0; + +// Delegates +static FrameLoadDelegate *frameLoadDelegate; +static UIDelegate *uiDelegate; +static EditingDelegate *editingDelegate; +static ResourceLoadDelegate *resourceLoadDelegate; +PolicyDelegate *policyDelegate; + +static int dumpPixels; +static int dumpAllPixels; +static int threaded; +static int testRepaintDefault; +static int repaintSweepHorizontallyDefault; +static int dumpTree = YES; +static BOOL printSeparators; +static NSString *currentTest = nil; +static RetainPtr<CFStringRef> persistentUserStyleSheetLocation; + +static WebHistoryItem *prevTestBFItem = nil; // current b/f item at the end of the previous test + +const unsigned maxViewHeight = 600; +const unsigned maxViewWidth = 800; + +void setPersistentUserStyleSheetLocation(CFStringRef url) +{ + persistentUserStyleSheetLocation = url; +} + +static BOOL shouldIgnoreWebCoreNodeLeaks(CFStringRef URLString) +{ + static CFStringRef const ignoreSet[] = { + // Keeping this infrastructure around in case we ever need it again. + }; + static const int ignoreSetCount = sizeof(ignoreSet) / sizeof(CFStringRef); + + for (int i = 0; i < ignoreSetCount; i++) { + CFStringRef ignoreString = ignoreSet[i]; + CFRange range = CFRangeMake(0, CFStringGetLength(URLString)); + CFOptionFlags flags = kCFCompareAnchored | kCFCompareBackwards | kCFCompareCaseInsensitive; + if (CFStringFindWithOptions(URLString, ignoreString, range, flags, NULL)) + return YES; + } + return NO; +} + +static void activateAhemFont() +{ + unsigned long fontDataLength; + char* fontData = getsectdata("__DATA", "Ahem", &fontDataLength); + if (!fontData) { + fprintf(stderr, "Failed to locate the Ahem font.\n"); + exit(1); + } + + ATSFontContainerRef fontContainer; + OSStatus status = ATSFontActivateFromMemory(fontData, fontDataLength, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &fontContainer); + + if (status != noErr) { + fprintf(stderr, "Failed to activate the Ahem font.\n"); + exit(1); + } +} + +WebView *createWebViewAndOffscreenWindow() +{ + NSRect rect = NSMakeRect(0, 0, maxViewWidth, maxViewHeight); + WebView *webView = [[WebView alloc] initWithFrame:rect frameName:nil groupName:@"org.webkit.DumpRenderTree"]; + + [webView setUIDelegate:uiDelegate]; + [webView setFrameLoadDelegate:frameLoadDelegate]; + [webView setEditingDelegate:editingDelegate]; + [webView setResourceLoadDelegate:resourceLoadDelegate]; + + // Register the same schemes that Safari does + [WebView registerURLSchemeAsLocal:@"feed"]; + [WebView registerURLSchemeAsLocal:@"feeds"]; + [WebView registerURLSchemeAsLocal:@"feedsearch"]; + + [webView setContinuousSpellCheckingEnabled:YES]; + + // To make things like certain NSViews, dragging, and plug-ins work, put the WebView a window, but put it off-screen so you don't see it. + // Put it at -10000, -10000 in "flipped coordinates", since WebCore and the DOM use flipped coordinates. + NSRect windowRect = NSOffsetRect(rect, -10000, [[[NSScreen screens] objectAtIndex:0] frame].size.height - rect.size.height + 10000); + DumpRenderTreeWindow *window = [[DumpRenderTreeWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; + [[window contentView] addSubview:webView]; + [window orderBack:nil]; + [window setAutodisplay:NO]; + + // For reasons that are not entirely clear, the following pair of calls makes WebView handle its + // dynamic scrollbars properly. Without it, every frame will always have scrollbars. + NSBitmapImageRep *imageRep = [webView bitmapImageRepForCachingDisplayInRect:[webView bounds]]; + [webView cacheDisplayInRect:[webView bounds] toBitmapImageRep:imageRep]; + + return webView; +} + +void testStringByEvaluatingJavaScriptFromString() +{ + // maps expected result <= JavaScript expression + NSDictionary *expressions = [NSDictionary dictionaryWithObjectsAndKeys: + @"0", @"0", + @"0", @"'0'", + @"", @"", + @"", @"''", + @"", @"new String()", + @"", @"new String('0')", + @"", @"throw 1", + @"", @"{ }", + @"", @"[ ]", + @"", @"//", + @"", @"a.b.c", + @"", @"(function() { throw 'error'; })()", + @"", @"null", + @"", @"undefined", + @"true", @"true", + @"false", @"false", + nil + ]; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + WebView *webView = [[WebView alloc] initWithFrame:NSZeroRect frameName:@"" groupName:@""]; + + NSEnumerator *enumerator = [expressions keyEnumerator]; + id expression; + while ((expression = [enumerator nextObject])) { + NSString *expectedResult = [expressions objectForKey:expression]; + NSString *result = [webView stringByEvaluatingJavaScriptFromString:expression]; + assert([result isEqualToString:expectedResult]); + } + + [webView close]; + [webView release]; + [pool release]; +} + +static void setDefaultsToConsistentValuesForTesting() +{ + // Give some clear to undocumented defaults values + static const int MediumFontSmoothing = 2; + static const int BlueTintedAppearance = 1; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; + [defaults setInteger:4 forKey:@"AppleAntiAliasingThreshold"]; // smallest font size to CG should perform antialiasing on + [defaults setInteger:MediumFontSmoothing forKey:@"AppleFontSmoothing"]; + [defaults setInteger:BlueTintedAppearance forKey:@"AppleAquaColorVariant"]; + [defaults setObject:@"0.709800 0.835300 1.000000" forKey:@"AppleHighlightColor"]; + [defaults setObject:@"0.500000 0.500000 0.500000" forKey:@"AppleOtherHighlightColor"]; + [defaults setObject:[NSArray arrayWithObject:@"en"] forKey:@"AppleLanguages"]; + + NSString *libraryPath = [@"~/Library/Application Support/DumpRenderTree" stringByExpandingTildeInPath]; + [defaults setObject:[libraryPath stringByAppendingPathComponent:@"Databases"] forKey:WebDatabaseDirectoryDefaultsKey]; + + WebPreferences *preferences = [WebPreferences standardPreferences]; + + [preferences setStandardFontFamily:@"Times"]; + [preferences setFixedFontFamily:@"Courier"]; + [preferences setSerifFontFamily:@"Times"]; + [preferences setSansSerifFontFamily:@"Helvetica"]; + [preferences setCursiveFontFamily:@"Apple Chancery"]; + [preferences setFantasyFontFamily:@"Papyrus"]; + [preferences setDefaultFontSize:16]; + [preferences setDefaultFixedFontSize:13]; + [preferences setMinimumFontSize:1]; + [preferences setJavaEnabled:NO]; + [preferences setEditableLinkBehavior:WebKitEditableLinkOnlyLiveWithShiftKey]; + [preferences setTabsToLinks:NO]; + [preferences setDOMPasteAllowed:YES]; + + // The back/forward cache is causing problems due to layouts during transition from one page to another. + // So, turn it off for now, but we might want to turn it back on some day. + [preferences setUsesPageCache:NO]; +} + +static void crashHandler(int sig) +{ + fprintf(stderr, "%s\n", strsignal(sig)); + restoreColorSpace(0); + exit(128 + sig); +} + +static void installSignalHandlers() +{ + signal(SIGILL, crashHandler); /* 4: illegal instruction (not reset when caught) */ + signal(SIGTRAP, crashHandler); /* 5: trace trap (not reset when caught) */ + signal(SIGEMT, crashHandler); /* 7: EMT instruction */ + signal(SIGFPE, crashHandler); /* 8: floating point exception */ + signal(SIGBUS, crashHandler); /* 10: bus error */ + signal(SIGSEGV, crashHandler); /* 11: segmentation violation */ + signal(SIGSYS, crashHandler); /* 12: bad argument to system call */ + signal(SIGPIPE, crashHandler); /* 13: write on a pipe with no reader */ + signal(SIGXCPU, crashHandler); /* 24: exceeded CPU time limit */ + signal(SIGXFSZ, crashHandler); /* 25: exceeded file size limit */ +} + +static void allocateGlobalControllers() +{ + // FIXME: We should remove these and move to the ObjC standard [Foo sharedInstance] model + navigationController = [[NavigationController alloc] init]; + frameLoadDelegate = [[FrameLoadDelegate alloc] init]; + uiDelegate = [[UIDelegate alloc] init]; + editingDelegate = [[EditingDelegate alloc] init]; + resourceLoadDelegate = [[ResourceLoadDelegate alloc] init]; + policyDelegate = [[PolicyDelegate alloc] init]; +} + +// ObjC++ doens't seem to let me pass NSObject*& sadly. +static inline void releaseAndZero(NSObject** object) +{ + [*object release]; + *object = nil; +} + +static void releaseGlobalControllers() +{ + releaseAndZero(&navigationController); + releaseAndZero(&frameLoadDelegate); + releaseAndZero(&editingDelegate); + releaseAndZero(&resourceLoadDelegate); + releaseAndZero(&uiDelegate); + releaseAndZero(&policyDelegate); +} + +static void initializeGlobalsFromCommandLineOptions(int argc, const char *argv[]) +{ + struct option options[] = { + {"dump-all-pixels", no_argument, &dumpAllPixels, YES}, + {"horizontal-sweep", no_argument, &repaintSweepHorizontallyDefault, YES}, + {"notree", no_argument, &dumpTree, NO}, + {"pixel-tests", no_argument, &dumpPixels, YES}, + {"repaint", no_argument, &testRepaintDefault, YES}, + {"tree", no_argument, &dumpTree, YES}, + {"threaded", no_argument, &threaded, YES}, + {NULL, 0, NULL, 0} + }; + + int option; + while ((option = getopt_long(argc, (char * const *)argv, "", options, NULL)) != -1) { + switch (option) { + case '?': // unknown or ambiguous option + case ':': // missing argument + exit(1); + break; + } + } +} + +static void addTestPluginsToPluginSearchPath(const char* executablePath) +{ + NSString *pwd = [[NSString stringWithUTF8String:executablePath] stringByDeletingLastPathComponent]; + [WebPluginDatabase setAdditionalWebPlugInPaths:[NSArray arrayWithObject:pwd]]; + [[WebPluginDatabase sharedDatabase] refresh]; +} + +static bool useLongRunningServerMode(int argc, const char *argv[]) +{ + // This assumes you've already called getopt_long + return (argc == optind+1 && strcmp(argv[optind], "-") == 0); +} + +static void runTestingServerLoop() +{ + // When DumpRenderTree run in server mode, we just wait around for file names + // to be passed to us and read each in turn, passing the results back to the client + char filenameBuffer[2048]; + while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { + char *newLineCharacter = strchr(filenameBuffer, '\n'); + if (newLineCharacter) + *newLineCharacter = '\0'; + + if (strlen(filenameBuffer) == 0) + continue; + + runTest(filenameBuffer); + } +} + +static void prepareConsistentTestingEnvironment() +{ + class_poseAs(objc_getClass("DumpRenderTreePasteboard"), objc_getClass("NSPasteboard")); + class_poseAs(objc_getClass("DumpRenderTreeEvent"), objc_getClass("NSEvent")); + + setDefaultsToConsistentValuesForTesting(); + activateAhemFont(); + + if (dumpPixels) + initializeColorSpaceAndScreeBufferForPixelTests(); + allocateGlobalControllers(); + + makeLargeMallocFailSilently(); +} + +void dumpRenderTree(int argc, const char *argv[]) +{ + initializeGlobalsFromCommandLineOptions(argc, argv); + prepareConsistentTestingEnvironment(); + addTestPluginsToPluginSearchPath(argv[0]); + if (dumpPixels) + installSignalHandlers(); + + WebView *webView = createWebViewAndOffscreenWindow(); + mainFrame = [webView mainFrame]; + + [[NSURLCache sharedURLCache] removeAllCachedResponses]; + + // <rdar://problem/5222911> + testStringByEvaluatingJavaScriptFromString(); + + if (threaded) + startJavaScriptThreads(); + + if (useLongRunningServerMode(argc, argv)) { + printSeparators = YES; + runTestingServerLoop(); + } else { + printSeparators = (optind < argc-1 || (dumpPixels && dumpTree)); + for (int i = optind; i != argc; ++i) + runTest(argv[i]); + } + + if (threaded) + stopJavaScriptThreads(); + + [WebCoreStatistics emptyCache]; // Otherwise SVGImages trigger false positives for Frame/Node counts + [webView close]; + mainFrame = nil; + + // Work around problem where registering drag types leaves an outstanding + // "perform selector" on the window, which retains the window. It's a bit + // inelegant and perhaps dangerous to just blow them all away, but in practice + // it probably won't cause any trouble (and this is just a test tool, after all). + NSWindow *window = [webView window]; + [NSObject cancelPreviousPerformRequestsWithTarget:window]; + + [window close]; // releases when closed + [webView release]; + + releaseGlobalControllers(); + + [DumpRenderTreePasteboard releaseLocalPasteboards]; + + // FIXME: This should be moved onto LayoutTestController and made into a HashSet + if (disallowedURLs) { + CFRelease(disallowedURLs); + disallowedURLs = 0; + } + + if (dumpPixels) + restoreColorSpace(0); +} + +int main(int argc, const char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSApplication sharedApplication]; // Force AppKit to init itself + dumpRenderTree(argc, argv); + [WebCoreStatistics garbageCollectJavaScriptObjects]; + [pool release]; + return 0; +} + +static int compareHistoryItems(id item1, id item2, void *context) +{ + return [[item1 target] caseInsensitiveCompare:[item2 target]]; +} + +static void dumpHistoryItem(WebHistoryItem *item, int indent, BOOL current) +{ + int start = 0; + if (current) { + printf("curr->"); + start = 6; + } + for (int i = start; i < indent; i++) + putchar(' '); + printf("%s", [[item URLString] UTF8String]); + NSString *target = [item target]; + if (target && [target length] > 0) + printf(" (in frame \"%s\")", [target UTF8String]); + if ([item isTargetItem]) + printf(" **nav target**"); + putchar('\n'); + NSArray *kids = [item children]; + if (kids) { + // must sort to eliminate arbitrary result ordering which defeats reproducible testing + kids = [kids sortedArrayUsingFunction:&compareHistoryItems context:nil]; + for (unsigned i = 0; i < [kids count]; i++) + dumpHistoryItem([kids objectAtIndex:i], indent+4, NO); + } +} + +static void dumpFrameScrollPosition(WebFrame *f) +{ + NSPoint scrollPosition = [[[[f frameView] documentView] superview] bounds].origin; + if (ABS(scrollPosition.x) > 0.00000001 || ABS(scrollPosition.y) > 0.00000001) { + if ([f parentFrame] != nil) + printf("frame '%s' ", [[f name] UTF8String]); + printf("scrolled to %.f,%.f\n", scrollPosition.x, scrollPosition.y); + } + + if (layoutTestController->dumpChildFrameScrollPositions()) { + NSArray *kids = [f childFrames]; + if (kids) + for (unsigned i = 0; i < [kids count]; i++) + dumpFrameScrollPosition([kids objectAtIndex:i]); + } +} + +static NSString *dumpFramesAsText(WebFrame *frame) +{ + DOMDocument *document = [frame DOMDocument]; + DOMElement *documentElement = [document documentElement]; + + if (!documentElement) + return @""; + + NSMutableString *result = [[[NSMutableString alloc] init] autorelease]; + + // Add header for all but the main frame. + if ([frame parentFrame]) + result = [NSMutableString stringWithFormat:@"\n--------\nFrame: '%@'\n--------\n", [frame name]]; + + [result appendFormat:@"%@\n", [documentElement innerText]]; + + if (layoutTestController->dumpChildFramesAsText()) { + NSArray *kids = [frame childFrames]; + if (kids) { + for (unsigned i = 0; i < [kids count]; i++) + [result appendString:dumpFramesAsText([kids objectAtIndex:i])]; + } + } + + return result; +} + +static void convertMIMEType(NSMutableString *mimeType) +{ + if ([mimeType isEqualToString:@"application/x-javascript"]) + [mimeType setString:@"text/javascript"]; +} + +static void convertWebResourceDataToString(NSMutableDictionary *resource) +{ + NSMutableString *mimeType = [resource objectForKey:@"WebResourceMIMEType"]; + convertMIMEType(mimeType); + + if ([mimeType hasPrefix:@"text/"]) { + NSData *data = [resource objectForKey:@"WebResourceData"]; + NSString *dataAsString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; + [resource setObject:dataAsString forKey:@"WebResourceData"]; + } +} + +static void normalizeWebResourceURL(NSMutableString *webResourceURL) +{ + static int fileUrlLength = [@"file://" length]; + NSRange layoutTestsWebArchivePathRange = [webResourceURL rangeOfString:@"/LayoutTests/" options:NSBackwardsSearch]; + if (layoutTestsWebArchivePathRange.location == NSNotFound) + return; + NSRange currentWorkingDirectoryRange = NSMakeRange(fileUrlLength, layoutTestsWebArchivePathRange.location - fileUrlLength); + [webResourceURL replaceCharactersInRange:currentWorkingDirectoryRange withString:@""]; +} + +static void convertWebResourceResponseToDictionary(NSMutableDictionary *propertyList) +{ + NSURLResponse *response = nil; + NSData *responseData = [propertyList objectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m + if ([responseData isKindOfClass:[NSData class]]) { + // Decode NSURLResponse + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:responseData]; + response = [unarchiver decodeObjectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m + [unarchiver finishDecoding]; + [unarchiver release]; + } + + NSMutableDictionary *responseDictionary = [[NSMutableDictionary alloc] init]; + + NSMutableString *urlString = [[[response URL] description] mutableCopy]; + normalizeWebResourceURL(urlString); + [responseDictionary setObject:urlString forKey:@"URL"]; + [urlString release]; + + NSMutableString *mimeTypeString = [[response MIMEType] mutableCopy]; + convertMIMEType(mimeTypeString); + [responseDictionary setObject:mimeTypeString forKey:@"MIMEType"]; + [mimeTypeString release]; + + NSString *textEncodingName = [response textEncodingName]; + if (textEncodingName) + [responseDictionary setObject:textEncodingName forKey:@"textEncodingName"]; + [responseDictionary setObject:[NSNumber numberWithLongLong:[response expectedContentLength]] forKey:@"expectedContentLength"]; + + if ([response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + + [responseDictionary setObject:[httpResponse allHeaderFields] forKey:@"allHeaderFields"]; + [responseDictionary setObject:[NSNumber numberWithInt:[httpResponse statusCode]] forKey:@"statusCode"]; + } + + [propertyList setObject:responseDictionary forKey:@"WebResourceResponse"]; + [responseDictionary release]; +} + +static NSString *serializeWebArchiveToXML(WebArchive *webArchive) +{ + NSString *errorString; + NSMutableDictionary *propertyList = [NSPropertyListSerialization propertyListFromData:[webArchive data] + mutabilityOption:NSPropertyListMutableContainersAndLeaves + format:NULL + errorDescription:&errorString]; + if (!propertyList) + return errorString; + + NSMutableArray *resources = [NSMutableArray arrayWithCapacity:1]; + [resources addObject:propertyList]; + + while ([resources count]) { + NSMutableDictionary *resourcePropertyList = [resources objectAtIndex:0]; + [resources removeObjectAtIndex:0]; + + NSMutableDictionary *mainResource = [resourcePropertyList objectForKey:@"WebMainResource"]; + normalizeWebResourceURL([mainResource objectForKey:@"WebResourceURL"]); + convertWebResourceDataToString(mainResource); + + // Add subframeArchives to list for processing + NSMutableArray *subframeArchives = [resourcePropertyList objectForKey:@"WebSubframeArchives"]; // WebSubframeArchivesKey in WebArchive.m + if (subframeArchives) + [resources addObjectsFromArray:subframeArchives]; + + NSMutableArray *subresources = [resourcePropertyList objectForKey:@"WebSubresources"]; // WebSubresourcesKey in WebArchive.m + NSEnumerator *enumerator = [subresources objectEnumerator]; + NSMutableDictionary *subresourcePropertyList; + while ((subresourcePropertyList = [enumerator nextObject])) { + normalizeWebResourceURL([subresourcePropertyList objectForKey:@"WebResourceURL"]); + convertWebResourceResponseToDictionary(subresourcePropertyList); + convertWebResourceDataToString(subresourcePropertyList); + } + } + + NSData *xmlData = [NSPropertyListSerialization dataFromPropertyList:propertyList + format:NSPropertyListXMLFormat_v1_0 + errorDescription:&errorString]; + if (!xmlData) + return errorString; + + NSMutableString *string = [[[NSMutableString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding] autorelease]; + + // Replace "Apple Computer" with "Apple" in the DTD declaration. + NSRange range = [string rangeOfString:@"-//Apple Computer//"]; + if (range.location != NSNotFound) + [string replaceCharactersInRange:range withString:@"-//Apple//"]; + + return string; +} + +static void dumpBackForwardListForWebView(WebView *view) +{ + printf("\n============== Back Forward List ==============\n"); + WebBackForwardList *bfList = [view backForwardList]; + + // Print out all items in the list after prevTestBFItem, which was from the previous test + // Gather items from the end of the list, the print them out from oldest to newest + NSMutableArray *itemsToPrint = [[NSMutableArray alloc] init]; + for (int i = [bfList forwardListCount]; i > 0; i--) { + WebHistoryItem *item = [bfList itemAtIndex:i]; + // something is wrong if the item from the last test is in the forward part of the b/f list + assert(item != prevTestBFItem); + [itemsToPrint addObject:item]; + } + + assert([bfList currentItem] != prevTestBFItem); + [itemsToPrint addObject:[bfList currentItem]]; + int currentItemIndex = [itemsToPrint count] - 1; + + for (int i = -1; i >= -[bfList backListCount]; i--) { + WebHistoryItem *item = [bfList itemAtIndex:i]; + if (item == prevTestBFItem) + break; + [itemsToPrint addObject:item]; + } + + for (int i = [itemsToPrint count]-1; i >= 0; i--) + dumpHistoryItem([itemsToPrint objectAtIndex:i], 8, i == currentItemIndex); + + [itemsToPrint release]; + printf("===============================================\n"); +} + +static void sizeWebViewForCurrentTest() +{ + // W3C SVG tests expect to be 480x360 + bool isSVGW3CTest = ([currentTest rangeOfString:@"svg/W3C-SVG-1.1"].length); + if (isSVGW3CTest) + [[mainFrame webView] setFrameSize:NSMakeSize(480, 360)]; + else + [[mainFrame webView] setFrameSize:NSMakeSize(maxViewWidth, maxViewHeight)]; +} + +static const char *methodNameStringForFailedTest() +{ + const char *errorMessage; + if (layoutTestController->dumpAsText()) + errorMessage = "[documentElement innerText]"; + else if (layoutTestController->dumpDOMAsWebArchive()) + errorMessage = "[[mainFrame DOMDocument] webArchive]"; + else if (layoutTestController->dumpSourceAsWebArchive()) + errorMessage = "[[mainFrame dataSource] webArchive]"; + else + errorMessage = "[mainFrame renderTreeAsExternalRepresentation]"; + + return errorMessage; +} + +static void dumpBackForwardListForAllWindows() +{ + CFArrayRef openWindows = (CFArrayRef)[DumpRenderTreeWindow openWindows]; + unsigned count = CFArrayGetCount(openWindows); + for (unsigned i = 0; i < count; i++) { + NSWindow *window = (NSWindow *)CFArrayGetValueAtIndex(openWindows, i); + WebView *webView = [[[window contentView] subviews] objectAtIndex:0]; + dumpBackForwardListForWebView(webView); + } +} + +static void invalidateAnyPreviousWaitToDumpWatchdog() +{ + if (waitToDumpWatchdog) { + CFRunLoopTimerInvalidate(waitToDumpWatchdog); + CFRelease(waitToDumpWatchdog); + waitToDumpWatchdog = 0; + } +} + +void dump() +{ + invalidateAnyPreviousWaitToDumpWatchdog(); + + if (dumpTree) { + NSString *resultString = nil; + NSData *resultData = nil; + + bool dumpAsText = layoutTestController->dumpAsText(); + dumpAsText |= [[[mainFrame dataSource] _responseMIMEType] isEqualToString:@"text/plain"]; + layoutTestController->setDumpAsText(dumpAsText); + if (layoutTestController->dumpAsText()) { + resultString = dumpFramesAsText(mainFrame); + } else if (layoutTestController->dumpDOMAsWebArchive()) { + WebArchive *webArchive = [[mainFrame DOMDocument] webArchive]; + resultString = serializeWebArchiveToXML(webArchive); + } else if (layoutTestController->dumpSourceAsWebArchive()) { + WebArchive *webArchive = [[mainFrame dataSource] webArchive]; + resultString = serializeWebArchiveToXML(webArchive); + } else { + sizeWebViewForCurrentTest(); + resultString = [mainFrame renderTreeAsExternalRepresentation]; + } + + if (resultString && !resultData) + resultData = [resultString dataUsingEncoding:NSUTF8StringEncoding]; + + if (resultData) { + fwrite([resultData bytes], 1, [resultData length], stdout); + + if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive()) + dumpFrameScrollPosition(mainFrame); + + if (layoutTestController->dumpBackForwardList()) + dumpBackForwardListForAllWindows(); + } else + printf("ERROR: nil result from %s", methodNameStringForFailedTest()); + + if (printSeparators) + puts("#EOF"); + } + + if (dumpPixels) + dumpWebViewAsPixelsAndCompareWithExpected([currentTest UTF8String], dumpAllPixels); + + fflush(stdout); + + done = YES; +} + +static bool shouldLogFrameLoadDelegates(const char *pathOrURL) +{ + return strstr(pathOrURL, "loading/"); +} + +static CFURLRef createCFURLFromPathOrURL(CFStringRef pathOrURLString) +{ + CFURLRef URL; + if (CFStringHasPrefix(pathOrURLString, CFSTR("http://")) || CFStringHasPrefix(pathOrURLString, CFSTR("https://"))) + URL = CFURLCreateWithString(NULL, pathOrURLString, NULL); + else + URL = CFURLCreateWithFileSystemPath(NULL, pathOrURLString, kCFURLPOSIXPathStyle, FALSE); + return URL; +} + +static void resetWebViewToConsistentStateBeforeTesting() +{ + WebView *webView = [mainFrame webView]; + [(EditingDelegate *)[webView editingDelegate] setAcceptsEditing:YES]; + [webView makeTextStandardSize:nil]; + [webView setTabKeyCyclesThroughElements: YES]; + [webView setPolicyDelegate:nil]; + [webView _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:NO]; + + WebPreferences *preferences = [webView preferences]; + [preferences setPrivateBrowsingEnabled:NO]; + [preferences setAuthorAndUserStylesEnabled:YES]; + [preferences setJavaScriptCanOpenWindowsAutomatically:YES]; + + if (persistentUserStyleSheetLocation) { + [preferences setUserStyleSheetLocation:[NSURL URLWithString:(NSString *)(persistentUserStyleSheetLocation.get())]]; + [preferences setUserStyleSheetEnabled:YES]; + } else + [preferences setUserStyleSheetEnabled:NO]; + + [WebView _setUsesTestModeFocusRingColor:YES]; +} + +static void runTest(const char *pathOrURL) +{ + CFStringRef pathOrURLString = CFStringCreateWithCString(NULL, pathOrURL, kCFStringEncodingUTF8); + if (!pathOrURLString) { + fprintf(stderr, "Failed to parse filename as UTF-8: %s\n", pathOrURL); + return; + } + + CFURLRef URL = createCFURLFromPathOrURL(pathOrURLString); + if (!URL) { + CFRelease(pathOrURLString); + fprintf(stderr, "Can't turn %s into a CFURL\n", pathOrURL); + return; + } + + resetWebViewToConsistentStateBeforeTesting(); + + layoutTestController = new LayoutTestController(testRepaintDefault, repaintSweepHorizontallyDefault); + topLoadingFrame = nil; + done = NO; + + if (disallowedURLs) + CFSetRemoveAllValues(disallowedURLs); + if (shouldLogFrameLoadDelegates(pathOrURL)) + layoutTestController->setDumpFrameLoadCallbacks(true); + + if ([WebHistory optionalSharedHistory]) + [WebHistory setOptionalSharedHistory:nil]; + lastMousePosition = NSZeroPoint; + lastClickPosition = NSZeroPoint; + + if (currentTest != nil) + CFRelease(currentTest); + currentTest = (NSString *)pathOrURLString; + [prevTestBFItem release]; + prevTestBFItem = [[[[mainFrame webView] backForwardList] currentItem] retain]; + + WorkQueue::shared()->clear(); + WorkQueue::shared()->setFrozen(false); + + BOOL _shouldIgnoreWebCoreNodeLeaks = shouldIgnoreWebCoreNodeLeaks(CFURLGetString(URL)); + if (_shouldIgnoreWebCoreNodeLeaks) + [WebCoreStatistics startIgnoringWebCoreNodeLeaks]; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [mainFrame loadRequest:[NSURLRequest requestWithURL:(NSURL *)URL]]; + CFRelease(URL); + [pool release]; + while (!done) { + pool = [[NSAutoreleasePool alloc] init]; + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]; + [pool release]; + } + pool = [[NSAutoreleasePool alloc] init]; + [EventSendingController clearSavedEvents]; + [[mainFrame webView] setSelectedDOMRange:nil affinity:NSSelectionAffinityDownstream]; + + WorkQueue::shared()->clear(); + + if (layoutTestController->closeRemainingWindowsWhenComplete()) { + NSArray* array = [DumpRenderTreeWindow openWindows]; + + unsigned count = [array count]; + for (unsigned i = 0; i < count; i++) { + NSWindow *window = [array objectAtIndex:i]; + + // Don't try to close the main window + if (window == [[mainFrame webView] window]) + continue; + + WebView *webView = [[[window contentView] subviews] objectAtIndex:0]; + + [webView close]; + [window close]; + } + } + + [mainFrame loadHTMLString:@"<html></html>" baseURL:[NSURL URLWithString:@"about:blank"]]; + [mainFrame stopLoading]; + + [pool release]; + + // We should only have our main window left open when we're done + ASSERT(CFArrayGetCount(openWindowsRef) == 1); + ASSERT(CFArrayGetValueAtIndex(openWindowsRef, 0) == [[mainFrame webView] window]); + + delete layoutTestController; + layoutTestController = 0; + + if (_shouldIgnoreWebCoreNodeLeaks) + [WebCoreStatistics stopIgnoringWebCoreNodeLeaks]; +} + +void displayWebView() +{ + NSView *webView = [mainFrame webView]; + [webView display]; + [webView lockFocus]; + [[[NSColor blackColor] colorWithAlphaComponent:0.66] set]; + NSRectFillUsingOperation([webView frame], NSCompositeSourceOver); + [webView unlockFocus]; +} + +@implementation DumpRenderTreeEvent + ++ (NSPoint)mouseLocation +{ + return [[[mainFrame webView] window] convertBaseToScreen:lastMousePosition]; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.h b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.h new file mode 100644 index 0000000..249809c --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. 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> + +@interface DumpRenderTreeDraggingInfo : NSObject <NSDraggingInfo> { +@private + NSSize offset; + NSImage *draggedImage; + NSPasteboard *draggingPasteboard; + id draggingSource; +} + +- (id)initWithImage:(NSImage *)image offset:(NSSize)offset pasteboard:(NSPasteboard *)pasteboard source:(id)source; + +- (NSWindow *)draggingDestinationWindow; +- (NSDragOperation)draggingSourceOperationMask; +- (NSPoint)draggingLocation; +- (NSPoint)draggedImageLocation; +- (NSImage *)draggedImage; +- (NSPasteboard *)draggingPasteboard; +- (id)draggingSource; +- (int)draggingSequenceNumber; + +- (void)slideDraggedImageTo:(NSPoint)screenPoint; +- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination; +@end + diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.mm new file mode 100644 index 0000000..41aa639 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeDraggingInfo.mm @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. 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 "DumpRenderTreeDraggingInfo.h" + +#import "DumpRenderTree.h" +#import "EventSendingController.h" +#import <WebKit/WebKit.h> + +@implementation DumpRenderTreeDraggingInfo + +- (id)initWithImage:(NSImage *)anImage offset:(NSSize)o pasteboard:(NSPasteboard *)pboard source:(id)source +{ + draggedImage = [anImage retain]; + draggingPasteboard = [pboard retain]; + draggingSource = [source retain]; + offset = o; + + return [super init]; +} + +- (void)dealloc +{ + [draggedImage release]; + [draggingPasteboard release]; + [draggingSource release]; + [super dealloc]; +} + +- (NSWindow *)draggingDestinationWindow +{ + return [[mainFrame webView] window]; +} + +- (NSDragOperation)draggingSourceOperationMask +{ + return [draggingSource draggingSourceOperationMaskForLocal:YES]; +} + +- (NSPoint)draggingLocation +{ + return lastMousePosition; +} + +- (NSPoint)draggedImageLocation +{ + return NSMakePoint(lastMousePosition.x + offset.width, lastMousePosition.y + offset.height); +} + +- (NSImage *)draggedImage +{ + return draggedImage; +} + +- (NSPasteboard *)draggingPasteboard +{ + return draggingPasteboard; +} + +- (id)draggingSource +{ + return draggingSource; +} + +- (int)draggingSequenceNumber +{ + NSLog(@"DumpRenderTree doesn't support draggingSequenceNumber"); + return 0; +} + +- (void)slideDraggedImageTo:(NSPoint)screenPoint +{ + NSLog(@"DumpRenderTree doesn't support slideDraggedImageTo:"); +} + +- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination +{ + NSLog(@"DumpRenderTree doesn't support namesOfPromisedFilesDroppedAtDestination:"); + return nil; +} + +@end + diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h new file mode 100644 index 0000000..c4c7573 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef DumpRenderTreeMac_h +#define DumpRenderTreeMac_h + +// FIXME: we should add a config.h file for DumpRenderTree. +#define WTF_PLATFORM_CF 1 + +@class DumpRenderTreeDraggingInfo; +@class NavigationController; +@class PolicyDelegate; +@class WebFrame; +@class WebView; + +typedef const struct __CFString* CFStringRef; + +extern CFMutableArrayRef openWindowsRef; +extern CFMutableSetRef disallowedURLs; +extern WebFrame* mainFrame; +extern WebFrame* topLoadingFrame; +extern DumpRenderTreeDraggingInfo *draggingInfo; +extern NavigationController* navigationController; +extern PolicyDelegate* policyDelegate; + +extern const unsigned maxViewHeight; +extern const unsigned maxViewWidth; + +WebView* createWebViewAndOffscreenWindow(); +void setPersistentUserStyleSheetLocation(CFStringRef); + +#endif // DumpRenderTreeMac_h diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h new file mode 100644 index 0000000..6a01a42 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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 <AppKit/AppKit.h> + +@interface DumpRenderTreePasteboard : NSPasteboard +- (int)declareType:(NSString *)type owner:(id)newOwner; ++ (void)releaseLocalPasteboards; +@end + diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m new file mode 100644 index 0000000..b5a9b7a --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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 "DumpRenderTreePasteboard.h" + +@interface LocalPasteboard : NSPasteboard +{ + NSMutableArray *typesArray; + NSMutableSet *typesSet; + NSMutableDictionary *dataByType; + int changeCount; +} +@end + +static NSMutableDictionary *localPasteboards; + +@implementation DumpRenderTreePasteboard + +// Return a local pasteboard so we don't disturb the real pasteboards when running tests. ++ (NSPasteboard *)_pasteboardWithName:(NSString *)name +{ + static int number = 0; + if (!name) + name = [NSString stringWithFormat:@"LocalPasteboard%d", ++number]; + if (!localPasteboards) + localPasteboards = [[NSMutableDictionary alloc] init]; + LocalPasteboard *pasteboard = [localPasteboards objectForKey:name]; + if (pasteboard) + return pasteboard; + pasteboard = [[LocalPasteboard alloc] init]; + [localPasteboards setObject:pasteboard forKey:name]; + [pasteboard release]; + return pasteboard; +} + ++ (void)releaseLocalPasteboards +{ + [localPasteboards release]; + localPasteboards = nil; +} + +// Convenience method for JS so that it doesn't have to try and create a NSArray on the objc side instead +// of the usual WebScriptObject that is passed around +- (int)declareType:(NSString *)type owner:(id)newOwner +{ + return [self declareTypes:[NSArray arrayWithObject:type] owner:newOwner]; +} + +@end + +@implementation LocalPasteboard + ++ (id)alloc +{ + return NSAllocateObject(self, 0, 0); +} + +- (id)init +{ + typesArray = [[NSMutableArray alloc] init]; + typesSet = [[NSMutableSet alloc] init]; + dataByType = [[NSMutableDictionary alloc] init]; + return self; +} + +- (void)dealloc +{ + [typesArray release]; + [typesSet release]; + [dataByType release]; + [super dealloc]; +} + +- (NSString *)name +{ + return nil; +} + +- (void)releaseGlobally +{ +} + +- (int)declareTypes:(NSArray *)newTypes owner:(id)newOwner +{ + [typesArray removeAllObjects]; + [typesSet removeAllObjects]; + [dataByType removeAllObjects]; + return [self addTypes:newTypes owner:newOwner]; +} + +- (int)addTypes:(NSArray *)newTypes owner:(id)newOwner +{ + unsigned count = [newTypes count]; + unsigned i; + for (i = 0; i < count; ++i) { + NSString *type = [newTypes objectAtIndex:i]; + NSString *setType = [typesSet member:type]; + if (!setType) { + setType = [type copy]; + [typesArray addObject:setType]; + [typesSet addObject:setType]; + [setType release]; + } + if (newOwner && [newOwner respondsToSelector:@selector(pasteboard:provideDataForType:)]) + [newOwner pasteboard:self provideDataForType:setType]; + } + return ++changeCount; +} + +- (int)changeCount +{ + return changeCount; +} + +- (NSArray *)types +{ + return typesArray; +} + +- (NSString *)availableTypeFromArray:(NSArray *)types +{ + unsigned count = [types count]; + unsigned i; + for (i = 0; i < count; ++i) { + NSString *type = [types objectAtIndex:i]; + NSString *setType = [typesSet member:type]; + if (setType) + return setType; + } + return nil; +} + +- (BOOL)setData:(NSData *)data forType:(NSString *)dataType +{ + if (data == nil) + data = [NSData data]; + if (![typesSet containsObject:dataType]) + return NO; + [dataByType setObject:data forKey:dataType]; + ++changeCount; + return YES; +} + +- (NSData *)dataForType:(NSString *)dataType +{ + return [dataByType objectForKey:dataType]; +} + +- (BOOL)setPropertyList:(id)propertyList forType:(NSString *)dataType; +{ + CFDataRef data = NULL; + if (propertyList) + data = CFPropertyListCreateXMLData(NULL, propertyList); + BOOL result = [self setData:(NSData *)data forType:dataType]; + if (data) + CFRelease(data); + return result; +} + +- (BOOL)setString:(NSString *)string forType:(NSString *)dataType +{ + CFDataRef data = NULL; + if (string) { + if ([string length] == 0) + data = CFDataCreate(NULL, NULL, 0); + else + data = CFStringCreateExternalRepresentation(NULL, (CFStringRef)string, kCFStringEncodingUTF8, 0); + } + BOOL result = [self setData:(NSData *)data forType:dataType]; + if (data) + CFRelease(data); + return result; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.h b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.h new file mode 100644 index 0000000..3ac3223 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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 <AppKit/AppKit.h> + +@interface DumpRenderTreeWindow : NSWindow +// I'm not sure why we can't just use [NSApp windows] ++ (NSArray *)openWindows; +@end diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm new file mode 100644 index 0000000..9e5e104 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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 "DumpRenderTreeWindow.h" + +#import "DumpRenderTree.h" + +// FIXME: This file is ObjC++ only because of this include. :( +#import "LayoutTestController.h" + +CFMutableArrayRef openWindowsRef = 0; + +static CFArrayCallBacks NonRetainingArrayCallbacks = { + 0, + NULL, + NULL, + CFCopyDescription, + CFEqual +}; + +@implementation DumpRenderTreeWindow + ++ (NSArray *)openWindows +{ + return [[(NSArray *)openWindowsRef copy] autorelease]; +} + +- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation +{ + if (!openWindowsRef) + openWindowsRef = CFArrayCreateMutable(NULL, 0, &NonRetainingArrayCallbacks); + + CFArrayAppendValue(openWindowsRef, self); + + return [super initWithContentRect:contentRect styleMask:styleMask backing:bufferingType defer:deferCreation]; +} + +- (void)close +{ + CFRange arrayRange = CFRangeMake(0, CFArrayGetCount(openWindowsRef)); + CFIndex i = CFArrayGetFirstIndexOfValue(openWindowsRef, arrayRange, self); + assert(i != -1); + CFArrayRemoveValueAtIndex(openWindowsRef, i); + [super close]; +} + +- (BOOL)isKeyWindow +{ + return layoutTestController ? layoutTestController->windowIsKey() : YES; +} + +- (void)keyDown:(id)sender +{ + // Do nothing, avoiding the beep we'd otherwise get from NSResponder, + // once we get to the end of the responder chain. +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/EditingDelegate.h b/WebKitTools/DumpRenderTree/mac/EditingDelegate.h new file mode 100644 index 0000000..b5563c8 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/EditingDelegate.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. 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> + +@interface EditingDelegate : NSObject +{ + BOOL acceptsEditing; +} + +- (void)setAcceptsEditing:(BOOL)newAcceptsEditing; + +@end diff --git a/WebKitTools/DumpRenderTree/mac/EditingDelegate.mm b/WebKitTools/DumpRenderTree/mac/EditingDelegate.mm new file mode 100644 index 0000000..a8f0815 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/EditingDelegate.mm @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. 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 "EditingDelegate.h" + +#import "DumpRenderTree.h" +#import "LayoutTestController.h" +#import <WebKit/WebKit.h> + +@interface DOMNode (dumpPath) +- (NSString *)dumpPath; +@end + +@implementation DOMNode (dumpPath) +- (NSString *)dumpPath +{ + DOMNode *parent = [self parentNode]; + NSString *str = [NSString stringWithFormat:@"%@", [self nodeName]]; + if (parent != nil) { + str = [str stringByAppendingString:@" > "]; + str = [str stringByAppendingString:[parent dumpPath]]; + } + return str; +} +@end + +@interface DOMRange (dump) +- (NSString *)dump; +@end + +@implementation DOMRange (dump) +- (NSString *)dump +{ + return [NSString stringWithFormat:@"range from %ld of %@ to %ld of %@", [self startOffset], [[self startContainer] dumpPath], [self endOffset], [[self endContainer] dumpPath]]; +} +@end + +@implementation EditingDelegate + +- (id)init +{ + self = [super init]; + if (!self) + return nil; + acceptsEditing = YES; + return self; +} + +- (BOOL)webView:(WebView *)webView shouldBeginEditingInDOMRange:(DOMRange *)range +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", [[range dump] UTF8String]); + return acceptsEditing; +} + +- (BOOL)webView:(WebView *)webView shouldEndEditingInDOMRange:(DOMRange *)range +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", [[range dump] UTF8String]); + return acceptsEditing; +} + +- (BOOL)webView:(WebView *)webView shouldInsertNode:(DOMNode *)node replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action +{ + static const char *insertactionstring[] = { + "WebViewInsertActionTyped", + "WebViewInsertActionPasted", + "WebViewInsertActionDropped", + }; + + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n", [[node dumpPath] UTF8String], [[range dump] UTF8String], insertactionstring[action]); + return acceptsEditing; +} + +- (BOOL)webView:(WebView *)webView shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action +{ + static const char *insertactionstring[] = { + "WebViewInsertActionTyped", + "WebViewInsertActionPasted", + "WebViewInsertActionDropped", + }; + + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n", [[text description] UTF8String], [[range dump] UTF8String], insertactionstring[action]); + return acceptsEditing; +} + +- (BOOL)webView:(WebView *)webView shouldDeleteDOMRange:(DOMRange *)range +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", [[range dump] UTF8String]); + return acceptsEditing; +} + +- (BOOL)webView:(WebView *)webView shouldShowDeleteInterfaceForElement:(DOMHTMLElement *)element +{ + return [[element className] isEqualToString:@"needsDeletionUI"]; +} + +- (BOOL)webView:(WebView *)webView shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag +{ + static const char *affinitystring[] = { + "NSSelectionAffinityUpstream", + "NSSelectionAffinityDownstream" + }; + static const char *boolstring[] = { + "FALSE", + "TRUE" + }; + + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n", [[currentRange dump] UTF8String], [[proposedRange dump] UTF8String], affinitystring[selectionAffinity], boolstring[flag]); + return acceptsEditing; +} + +- (BOOL)webView:(WebView *)webView shouldApplyStyle:(DOMCSSStyleDeclaration *)style toElementsInDOMRange:(DOMRange *)range +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n", [[style description] UTF8String], [[range dump] UTF8String]); + return acceptsEditing; +} + +- (BOOL)webView:(WebView *)webView shouldChangeTypingStyle:(DOMCSSStyleDeclaration *)currentStyle toStyle:(DOMCSSStyleDeclaration *)proposedStyle +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldChangeTypingStyle:%s toStyle:%s\n", [[currentStyle description] UTF8String], [[proposedStyle description] UTF8String]); + return acceptsEditing; +} + +- (void)webViewDidBeginEditing:(NSNotification *)notification +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidBeginEditing:%s\n", [[notification name] UTF8String]); +} + +- (void)webViewDidChange:(NSNotification *)notification +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidChange:%s\n", [[notification name] UTF8String]); +} + +- (void)webViewDidEndEditing:(NSNotification *)notification +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidEndEditing:%s\n", [[notification name] UTF8String]); +} + +- (void)webViewDidChangeTypingStyle:(NSNotification *)notification +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidChangeTypingStyle:%s\n", [[notification name] UTF8String]); +} + +- (void)webViewDidChangeSelection:(NSNotification *)notification +{ + if (!done && layoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidChangeSelection:%s\n", [[notification name] UTF8String]); +} + +- (void)setAcceptsEditing:(BOOL)newAcceptsEditing +{ + acceptsEditing = newAcceptsEditing; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.h b/WebKitTools/DumpRenderTree/mac/EventSendingController.h new file mode 100644 index 0000000..28d0385 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. 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> +#import <WebKit/WebKit.h> + +@interface EventSendingController : NSObject <DOMEventListener> +{ + BOOL down; + BOOL dragMode; + int clickCount; + NSTimeInterval lastClick; + int eventNumber; + double timeOffset; +} + ++ (void)saveEvent:(NSInvocation *)event; ++ (void)replaySavedEvents; ++ (void)clearSavedEvents; + +- (void)enableDOMUIEventLogging:(WebScriptObject *)node; + +- (void)handleEvent:(DOMEvent *)event; + +@end + +extern NSPoint lastMousePosition; +extern NSPoint lastClickPosition;
\ No newline at end of file diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm new file mode 100644 index 0000000..8e9be38 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Jonas Witt <jonas.witt@gmail.com> + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * + * 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 "EventSendingController.h" + +#import "DumpRenderTree.h" +#import "DumpRenderTreeDraggingInfo.h" + +#import <Carbon/Carbon.h> // for GetCurrentEventTime() +#import <WebKit/WebKit.h> +#import <WebKit/DOMPrivate.h> + +extern "C" void _NSNewKillRingSequence(); + +NSPoint lastMousePosition; +NSPoint lastClickPosition; +NSArray *webkitDomEventNames; +NSMutableArray *savedMouseEvents; // mouse events sent between mouseDown and mouseUp are stored here, and then executed at once. +BOOL replayingSavedEvents; + +@implementation EventSendingController + ++ (void)initialize +{ + webkitDomEventNames = [[NSArray alloc] initWithObjects: + @"abort", + @"beforecopy", + @"beforecut", + @"beforepaste", + @"blur", + @"change", + @"click", + @"contextmenu", + @"copy", + @"cut", + @"dblclick", + @"drag", + @"dragend", + @"dragenter", + @"dragleave", + @"dragover", + @"dragstart", + @"drop", + @"error", + @"focus", + @"input", + @"keydown", + @"keypress", + @"keyup", + @"load", + @"mousedown", + @"mousemove", + @"mouseout", + @"mouseover", + @"mouseup", + @"mousewheel", + @"beforeunload", + @"paste", + @"readystatechange", + @"reset", + @"resize", + @"scroll", + @"search", + @"select", + @"selectstart", + @"submit", + @"textInput", + @"textzoomin", + @"textzoomout", + @"unload", + @"zoom", + nil]; +} + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(mouseDown) + || aSelector == @selector(mouseUp) + || aSelector == @selector(contextClick) + || aSelector == @selector(mouseMoveToX:Y:) + || aSelector == @selector(leapForward:) + || aSelector == @selector(keyDown:withModifiers:) + || aSelector == @selector(enableDOMUIEventLogging:) + || aSelector == @selector(fireKeyboardEventsToElement:) + || aSelector == @selector(clearKillRing) + || aSelector == @selector(textZoomIn) + || aSelector == @selector(textZoomOut)) + return NO; + return YES; +} + ++ (BOOL)isKeyExcludedFromWebScript:(const char*)name +{ + if (strcmp(name, "dragMode") == 0) + return NO; + return YES; +} + ++ (NSString *)webScriptNameForSelector:(SEL)aSelector +{ + if (aSelector == @selector(mouseMoveToX:Y:)) + return @"mouseMoveTo"; + if (aSelector == @selector(leapForward:)) + return @"leapForward"; + if (aSelector == @selector(keyDown:withModifiers:)) + return @"keyDown"; + if (aSelector == @selector(enableDOMUIEventLogging:)) + return @"enableDOMUIEventLogging"; + if (aSelector == @selector(fireKeyboardEventsToElement:)) + return @"fireKeyboardEventsToElement"; + if (aSelector == @selector(setDragMode:)) + return @"setDragMode"; + return nil; +} + +- (id)init +{ + self = [super init]; + if (self) + dragMode = YES; + return self; +} + +- (void)dealloc +{ + [super dealloc]; +} + +- (double)currentEventTime +{ + return GetCurrentEventTime() + timeOffset; +} + +- (void)leapForward:(int)milliseconds +{ + if (dragMode && down && !replayingSavedEvents) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(leapForward:)]]; + [invocation setTarget:self]; + [invocation setSelector:@selector(leapForward:)]; + [invocation setArgument:&milliseconds atIndex:2]; + + [EventSendingController saveEvent:invocation]; + + return; + } + + timeOffset += milliseconds / 1000.0; +} + +- (void)clearKillRing +{ + _NSNewKillRingSequence(); +} + +- (void)mouseDown +{ + [[[mainFrame frameView] documentView] layout]; + if (([self currentEventTime] - lastClick >= 1) || + !NSEqualPoints(lastMousePosition, lastClickPosition)) + clickCount = 1; + else + clickCount++; + NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseDown + location:lastMousePosition + modifierFlags:0 + timestamp:[self currentEventTime] + windowNumber:[[[mainFrame webView] window] windowNumber] + context:[NSGraphicsContext currentContext] + eventNumber:++eventNumber + clickCount:clickCount + pressure:0.0]; + + NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; + if (subView) { + [subView mouseDown:event]; + down = YES; + } +} + +- (void)textZoomIn +{ + [[mainFrame webView] makeTextLarger:self]; +} + +- (void)textZoomOut +{ + [[mainFrame webView] makeTextSmaller:self]; +} + +- (void)mouseUp +{ + if (dragMode && !replayingSavedEvents) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp)]]; + [invocation setTarget:self]; + [invocation setSelector:@selector(mouseUp)]; + + [EventSendingController saveEvent:invocation]; + [EventSendingController replaySavedEvents]; + + return; + } + + [[[mainFrame frameView] documentView] layout]; + NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseUp + location:lastMousePosition + modifierFlags:0 + timestamp:[self currentEventTime] + windowNumber:[[[mainFrame webView] window] windowNumber] + context:[NSGraphicsContext currentContext] + eventNumber:++eventNumber + clickCount:clickCount + pressure:0.0]; + + NSView *targetView = [[mainFrame webView] hitTest:[event locationInWindow]]; + // FIXME: Silly hack to teach DRT to respect capturing mouse events outside the WebView. + // The right solution is just to use NSApplication's built-in event sending methods, + // instead of rolling our own algorithm for selecting an event target. + targetView = targetView ? targetView : [[mainFrame frameView] documentView]; + assert(targetView); + [targetView mouseUp:event]; + down = NO; + lastClick = [event timestamp]; + lastClickPosition = lastMousePosition; + if (draggingInfo) { + WebView *webView = [mainFrame webView]; + + NSDragOperation dragOperation = [webView draggingUpdated:draggingInfo]; + + if (dragOperation != NSDragOperationNone) + [webView performDragOperation:draggingInfo]; + else + [webView draggingExited:draggingInfo]; + [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] endedAt:lastMousePosition operation:dragOperation]; + [draggingInfo release]; + draggingInfo = nil; + } +} + +- (void)mouseMoveToX:(int)x Y:(int)y +{ + if (dragMode && down && !replayingSavedEvents) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseMoveToX:Y:)]]; + [invocation setTarget:self]; + [invocation setSelector:@selector(mouseMoveToX:Y:)]; + [invocation setArgument:&x atIndex:2]; + [invocation setArgument:&y atIndex:3]; + + [EventSendingController saveEvent:invocation]; + + return; + } + + NSView *view = [mainFrame webView]; + lastMousePosition = [view convertPoint:NSMakePoint(x, [view frame].size.height - y) toView:nil]; + NSEvent *event = [NSEvent mouseEventWithType:(down ? NSLeftMouseDragged : NSMouseMoved) + location:lastMousePosition + modifierFlags:0 + timestamp:[self currentEventTime] + windowNumber:[[view window] windowNumber] + context:[NSGraphicsContext currentContext] + eventNumber:++eventNumber + clickCount:(down ? clickCount : 0) + pressure:0.0]; + + NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; + if (subView) { + if (down) { + [subView mouseDragged:event]; + if (draggingInfo) { + [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition]; + [[mainFrame webView] draggingUpdated:draggingInfo]; + } + } else + [subView mouseMoved:event]; + } +} + +- (void)contextClick +{ + [[[mainFrame frameView] documentView] layout]; + if ([self currentEventTime] - lastClick >= 1) + clickCount = 1; + else + clickCount++; + NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseDown + location:lastMousePosition + modifierFlags:0 + timestamp:[self currentEventTime] + windowNumber:[[[mainFrame webView] window] windowNumber] + context:[NSGraphicsContext currentContext] + eventNumber:++eventNumber + clickCount:clickCount + pressure:0.0]; + + NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; + if (subView) + [subView menuForEvent:event]; +} + ++ (void)saveEvent:(NSInvocation *)event +{ + if (!savedMouseEvents) + savedMouseEvents = [[NSMutableArray alloc] init]; + [savedMouseEvents addObject:event]; +} + ++ (void)replaySavedEvents +{ + replayingSavedEvents = YES; + while ([savedMouseEvents count]) { + // if a drag is initiated, the remaining saved events will be dispatched from our dragging delegate + NSInvocation *invocation = [[[savedMouseEvents objectAtIndex:0] retain] autorelease]; + [savedMouseEvents removeObjectAtIndex:0]; + [invocation invoke]; + } + replayingSavedEvents = NO; +} + ++ (void)clearSavedEvents +{ + [savedMouseEvents release]; + savedMouseEvents = nil; +} + +- (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers +{ + NSString *eventCharacter = character; + if ([character isEqualToString:@"leftArrow"]) { + const unichar ch = NSLeftArrowFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"rightArrow"]) { + const unichar ch = NSRightArrowFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"upArrow"]) { + const unichar ch = NSUpArrowFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"downArrow"]) { + const unichar ch = NSDownArrowFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"pageUp"]) { + const unichar ch = NSPageUpFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"pageDown"]) { + const unichar ch = NSPageDownFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"home"]) { + const unichar ch = NSHomeFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"end"]) { + const unichar ch = NSEndFunctionKey; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } else if ([character isEqualToString:@"delete"]) { + const unichar ch = 0x7f; + eventCharacter = [NSString stringWithCharacters:&ch length:1]; + } + + NSString *charactersIgnoringModifiers = eventCharacter; + + int modifierFlags = 0; + + if ([character length] == 1 && [character characterAtIndex:0] >= 'A' && [character characterAtIndex:0] <= 'Z') { + modifierFlags |= NSShiftKeyMask; + charactersIgnoringModifiers = [character lowercaseString]; + } + + if ([modifiers isKindOfClass:[WebScriptObject class]]) + for (unsigned i = 0; [[modifiers webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) { + NSString *modifier = (NSString *)[modifiers webScriptValueAtIndex:i]; + if ([modifier isEqual:@"ctrlKey"]) + modifierFlags |= NSControlKeyMask; + else if ([modifier isEqual:@"shiftKey"]) + modifierFlags |= NSShiftKeyMask; + else if ([modifier isEqual:@"altKey"]) + modifierFlags |= NSAlternateKeyMask; + else if ([modifier isEqual:@"metaKey"]) + modifierFlags |= NSCommandKeyMask; + } + + [[[mainFrame frameView] documentView] layout]; + + NSEvent *event = [NSEvent keyEventWithType:NSKeyDown + location:NSMakePoint(5, 5) + modifierFlags:modifierFlags + timestamp:[self currentEventTime] + windowNumber:[[[mainFrame webView] window] windowNumber] + context:[NSGraphicsContext currentContext] + characters:eventCharacter + charactersIgnoringModifiers:charactersIgnoringModifiers + isARepeat:NO + keyCode:0]; + + [[[[mainFrame webView] window] firstResponder] keyDown:event]; + + event = [NSEvent keyEventWithType:NSKeyUp + location:NSMakePoint(5, 5) + modifierFlags:modifierFlags + timestamp:[self currentEventTime] + windowNumber:[[[mainFrame webView] window] windowNumber] + context:[NSGraphicsContext currentContext] + characters:eventCharacter + charactersIgnoringModifiers:charactersIgnoringModifiers + isARepeat:NO + keyCode:0]; + + [[[[mainFrame webView] window] firstResponder] keyUp:event]; +} + +- (void)enableDOMUIEventLogging:(WebScriptObject *)node +{ + NSEnumerator *eventEnumerator = [webkitDomEventNames objectEnumerator]; + id eventName; + while ((eventName = [eventEnumerator nextObject])) { + [(id<DOMEventTarget>)node addEventListener:eventName listener:self useCapture:NO]; + } +} + +- (void)handleEvent:(DOMEvent *)event +{ + DOMNode *target = [event target]; + + printf("event type: %s\n", [[event type] UTF8String]); + printf(" target: <%s>\n", [[[target nodeName] lowercaseString] UTF8String]); + + if ([event isKindOfClass:[DOMEvent class]]) { + printf(" eventPhase: %d\n", [event eventPhase]); + printf(" bubbles: %d\n", [event bubbles] ? 1 : 0); + printf(" cancelable: %d\n", [event cancelable] ? 1 : 0); + } + + if ([event isKindOfClass:[DOMUIEvent class]]) { + printf(" detail: %d\n", [(DOMUIEvent*)event detail]); + + DOMAbstractView *view = [(DOMUIEvent*)event view]; + if (view) { + printf(" view: OK"); + if ([view document]) + printf(" (document: OK)"); + printf("\n"); + } + } + + if ([event isKindOfClass:[DOMKeyboardEvent class]]) { + printf(" keyIdentifier: %s\n", [[(DOMKeyboardEvent*)event keyIdentifier] UTF8String]); + printf(" keyLocation: %d\n", [(DOMKeyboardEvent*)event keyLocation]); + printf(" modifier keys: c:%d s:%d a:%d m:%d\n", + [(DOMKeyboardEvent*)event ctrlKey] ? 1 : 0, + [(DOMKeyboardEvent*)event shiftKey] ? 1 : 0, + [(DOMKeyboardEvent*)event altKey] ? 1 : 0, + [(DOMKeyboardEvent*)event metaKey] ? 1 : 0); + printf(" keyCode: %d\n", [(DOMKeyboardEvent*)event keyCode]); + printf(" charCode: %d\n", [(DOMKeyboardEvent*)event charCode]); + } + + if ([event isKindOfClass:[DOMMouseEvent class]]) { + printf(" button: %d\n", [(DOMMouseEvent*)event button]); + printf(" clientX: %d\n", [(DOMMouseEvent*)event clientX]); + printf(" clientY: %d\n", [(DOMMouseEvent*)event clientY]); + printf(" screenX: %d\n", [(DOMMouseEvent*)event screenX]); + printf(" screenY: %d\n", [(DOMMouseEvent*)event screenY]); + printf(" modifier keys: c:%d s:%d a:%d m:%d\n", + [(DOMMouseEvent*)event ctrlKey] ? 1 : 0, + [(DOMMouseEvent*)event shiftKey] ? 1 : 0, + [(DOMMouseEvent*)event altKey] ? 1 : 0, + [(DOMMouseEvent*)event metaKey] ? 1 : 0); + id relatedTarget = [(DOMMouseEvent*)event relatedTarget]; + if (relatedTarget) { + printf(" relatedTarget: %s", [[[relatedTarget class] description] UTF8String]); + if ([relatedTarget isKindOfClass:[DOMNode class]]) + printf(" (nodeName: %s)", [[(DOMNode*)relatedTarget nodeName] UTF8String]); + printf("\n"); + } + } + + if ([event isKindOfClass:[DOMMutationEvent class]]) { + printf(" prevValue: %s\n", [[(DOMMutationEvent*)event prevValue] UTF8String]); + printf(" newValue: %s\n", [[(DOMMutationEvent*)event newValue] UTF8String]); + printf(" attrName: %s\n", [[(DOMMutationEvent*)event attrName] UTF8String]); + printf(" attrChange: %d\n", [(DOMMutationEvent*)event attrChange]); + DOMNode *relatedNode = [(DOMMutationEvent*)event relatedNode]; + if (relatedNode) { + printf(" relatedNode: %s (nodeName: %s)\n", + [[[relatedNode class] description] UTF8String], + [[relatedNode nodeName] UTF8String]); + } + } + + if ([event isKindOfClass:[DOMWheelEvent class]]) { + printf(" clientX: %d\n", [(DOMWheelEvent*)event clientX]); + printf(" clientY: %d\n", [(DOMWheelEvent*)event clientY]); + printf(" screenX: %d\n", [(DOMWheelEvent*)event screenX]); + printf(" screenY: %d\n", [(DOMWheelEvent*)event screenY]); + printf(" modifier keys: c:%d s:%d a:%d m:%d\n", + [(DOMWheelEvent*)event ctrlKey] ? 1 : 0, + [(DOMWheelEvent*)event shiftKey] ? 1 : 0, + [(DOMWheelEvent*)event altKey] ? 1 : 0, + [(DOMWheelEvent*)event metaKey] ? 1 : 0); + printf(" isHorizontal: %d\n", [(DOMWheelEvent*)event isHorizontal] ? 1 : 0); + printf(" wheelDelta: %d\n", [(DOMWheelEvent*)event wheelDelta]); + } +} + +// FIXME: It's not good to have a test hard-wired into this controller like this. +// Instead we need to get testing framework based on the Objective-C bindings +// to work well enough that we can test that way instead. +- (void)fireKeyboardEventsToElement:(WebScriptObject *)element { + + if (![element isKindOfClass:[DOMHTMLElement class]]) { + return; + } + + DOMHTMLElement *target = (DOMHTMLElement*)element; + DOMDocument *document = [target ownerDocument]; + + // Keyboard Event 1 + + DOMEvent *domEvent = [document createEvent:@"KeyboardEvent"]; + [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keydown" + canBubble:YES + cancelable:YES + view:[document defaultView] + keyIdentifier:@"U+000041" + keyLocation:0 + ctrlKey:YES + altKey:NO + shiftKey:NO + metaKey:NO]; + [target dispatchEvent:domEvent]; + + // Keyboard Event 2 + + domEvent = [document createEvent:@"KeyboardEvent"]; + [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keypress" + canBubble:YES + cancelable:YES + view:[document defaultView] + keyIdentifier:@"U+000045" + keyLocation:1 + ctrlKey:NO + altKey:YES + shiftKey:NO + metaKey:NO]; + [target dispatchEvent:domEvent]; + + // Keyboard Event 3 + + domEvent = [document createEvent:@"KeyboardEvent"]; + [(DOMKeyboardEvent*)domEvent initKeyboardEvent:@"keyup" + canBubble:YES + cancelable:YES + view:[document defaultView] + keyIdentifier:@"U+000056" + keyLocation:0 + ctrlKey:NO + altKey:NO + shiftKey:NO + metaKey:NO]; + [target dispatchEvent:domEvent]; + +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.h b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.h new file mode 100644 index 0000000..3b86fdf --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007 Apple Inc. 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 <Foundation/Foundation.h> + +class GCController; + +@interface FrameLoadDelegate : NSObject +{ + GCController* gcController; +} +@end diff --git a/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm new file mode 100644 index 0000000..98b6bac --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2007 Apple Inc. 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 "DumpRenderTree.h" +#import "FrameLoadDelegate.h" + +#import "AppleScriptController.h" +#import "EventSendingController.h" +#import "GCController.h" +#import "LayoutTestController.h" +#import "NavigationController.h" +#import "ObjCController.h" +#import "ObjCPlugin.h" +#import "ObjCPluginFunction.h" +#import "TextInputController.h" +#import "WorkQueue.h" +#import "WorkQueueItem.h" +#import <JavaScriptCore/JavaScriptCore.h> +#import <WebKit/WebFramePrivate.h> +#import <WebKit/WebHTMLViewPrivate.h> +#import <WebKit/WebKit.h> +#import <WebKit/WebNSURLExtras.h> +#import <wtf/Assertions.h> + +@interface NSURLRequest (PrivateThingsWeShouldntReallyUse) ++(void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString *)host; +@end + +@interface NSURL (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@interface NSError (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@interface NSURLResponse (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@interface NSURLRequest (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@interface WebFrame (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@implementation WebFrame (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult +{ + BOOL isMainFrame = (self == [[self webView] mainFrame]); + NSString *name = [self name]; + if (isMainFrame) { + if ([name length]) + return [NSString stringWithFormat:@"main frame \"%@\"", name]; + else + return @"main frame"; + } else { + if (name) + return [NSString stringWithFormat:@"frame \"%@\"", name]; + else + return @"frame (anonymous)"; + } +} +@end + +@implementation FrameLoadDelegate + +- (id)init +{ + if ((self = [super init])) + gcController = new GCController; + return self; +} + +- (void)dealloc +{ + delete gcController; + [super dealloc]; +} + +// Exec messages in the work queue until they're all done, or one of them starts a new load +- (void)processWork:(id)dummy +{ + // quit doing work once a load is in progress + while (WorkQueue::shared()->count() > 0 && !topLoadingFrame) { + WorkQueueItem* item = WorkQueue::shared()->dequeue(); + ASSERT(item); + item->invoke(); + delete item; + } + + // if we didn't start a new load, then we finished all the commands, so we're ready to dump state + if (!topLoadingFrame && !layoutTestController->waitToDump()) + dump(); +} + +- (void)webView:(WebView *)c locationChangeDone:(NSError *)error forDataSource:(WebDataSource *)dataSource +{ + if ([dataSource webFrame] == topLoadingFrame) { + topLoadingFrame = nil; + WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test + if (!layoutTestController->waitToDump()) { + if (WorkQueue::shared()->count()) + [self performSelector:@selector(processWork:) withObject:nil afterDelay:0]; + else + dump(); + } + } +} + +- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didStartProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } + + ASSERT([frame provisionalDataSource]); + // Make sure we only set this once per test. If it gets cleared, and then set again, we might + // end up doing two dumps for one test. + if (!topLoadingFrame && !done) + topLoadingFrame = frame; +} + +- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didCommitLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } + + ASSERT(![frame provisionalDataSource]); + ASSERT([frame dataSource]); + + layoutTestController->setWindowIsKey(true); + NSView *documentView = [[mainFrame frameView] documentView]; + [[[mainFrame webView] window] makeFirstResponder:documentView]; + if ([documentView isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)documentView _updateFocusedAndActiveState]; +} + +- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didFailProvisionalLoadWithError", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } + + if ([error domain] == NSURLErrorDomain && [error code] == NSURLErrorServerCertificateHasUnknownRoot) { + NSURL *failedURL = [[error userInfo] objectForKey:@"NSErrorFailingURLKey"]; + [NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[failedURL _web_hostString]]; + [frame loadRequest:[[[[frame provisionalDataSource] request] mutableCopy] autorelease]]; + return; + } + + ASSERT([frame provisionalDataSource]); + [self webView:sender locationChangeDone:error forDataSource:[frame provisionalDataSource]]; +} + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + ASSERT([frame dataSource]); + ASSERT(frame == [[frame dataSource] webFrame]); + + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } + + // FIXME: This call to displayIfNeeded can be removed when <rdar://problem/5092361> is fixed. + // After that is fixed, we will reenable painting after WebCore is done loading the document, + // and this call will no longer be needed. + if ([[sender mainFrame] isEqual:frame]) + [sender displayIfNeeded]; + [self webView:sender locationChangeDone:nil forDataSource:[frame dataSource]]; + [navigationController webView:sender didFinishLoadForFrame:frame]; +} + +- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame; +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadWithError", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } + + ASSERT(![frame provisionalDataSource]); + ASSERT([frame dataSource]); + + [self webView:sender locationChangeDone:error forDataSource:[frame dataSource]]; +} + +- (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject; +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"?? - windowScriptObjectAvailable"]; + printf ("%s\n", [string UTF8String]); + } + + ASSERT_NOT_REACHED(); +} + +- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)obj forFrame:(WebFrame *)frame +{ + ASSERT(obj == [frame windowObject]); + ASSERT([obj JSObject] == JSContextGetGlobalObject([frame globalContext])); + + // Make New-Style LayoutTestController + JSContextRef context = [frame globalContext]; + JSObjectRef globalObject = JSContextGetGlobalObject(context); + JSValueRef exception = 0; + + ASSERT(layoutTestController); + layoutTestController->makeWindowObject(context, globalObject, &exception); + ASSERT(!exception); + + gcController->makeWindowObject(context, globalObject, &exception); + ASSERT(!exception); + + // Make Old-Style controllers + EventSendingController *esc = [[EventSendingController alloc] init]; + [obj setValue:esc forKey:@"eventSender"]; + [esc release]; + + TextInputController *tic = [[TextInputController alloc] initWithWebView:sender]; + [obj setValue:tic forKey:@"textInputController"]; + [tic release]; + + AppleScriptController *asc = [[AppleScriptController alloc] initWithWebView:sender]; + [obj setValue:asc forKey:@"appleScriptController"]; + [asc release]; + + ObjCController *occ = [[ObjCController alloc] init]; + [obj setValue:occ forKey:@"objCController"]; + [occ release]; + + [obj setValue:navigationController forKey:@"navigationController"]; + + ObjCPlugin *plugin = [[ObjCPlugin alloc] init]; + [obj setValue:plugin forKey:@"objCPlugin"]; + [plugin release]; + + ObjCPluginFunction *pluginFunction = [[ObjCPluginFunction alloc] init]; + [obj setValue:pluginFunction forKey:@"objCPluginFunction"]; + [pluginFunction release]; +} + +- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didReceiveTitle: %@", [frame _drt_descriptionSuitableForTestResult], title]; + printf ("%s\n", [string UTF8String]); + } + + if (layoutTestController->dumpTitleChanges()) + printf("TITLE CHANGED: %s\n", [title UTF8String]); +} + +- (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didReceiveServerRedirectForProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +- (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didChangeLocationWithinPageForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +- (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - willPerformClientRedirectToURL: %@ ", [frame _drt_descriptionSuitableForTestResult], [URL _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +- (void)webView:(WebView *)sender didCancelClientRedirectForFrame:(WebFrame *)frame +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didCancelClientRedirectForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +- (void)webView:(WebView *)sender didFinishDocumentLoadForFrame:(WebFrame *)frame; +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didFinishDocumentLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +- (void)webView:(WebView *)sender didHandleOnloadEventsForFrame:(WebFrame *)frame; +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didHandleOnloadEventsForFrame", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/GCControllerMac.mm b/WebKitTools/DumpRenderTree/mac/GCControllerMac.mm new file mode 100644 index 0000000..4b845ba --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/GCControllerMac.mm @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * + * 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 "GCController.h" +#import <WebKit/WebCoreStatistics.h> + + +void GCController::collect() const +{ + [WebCoreStatistics garbageCollectJavaScriptObjects]; +} + +void GCController::collectOnAlternateThread(bool waitUntilDone) const +{ + [WebCoreStatistics garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging:waitUntilDone]; +} + +size_t GCController::getJSObjectCount() const +{ + return [WebCoreStatistics javaScriptObjectsCount]; +} diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm new file mode 100644 index 0000000..4774310 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2007 Apple Inc. 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 "DumpRenderTree.h" +#import "LayoutTestController.h" + +#import "EditingDelegate.h" +#import "WorkQueue.h" +#import "WorkQueueItem.h" +#import <Foundation/Foundation.h> +#import <JavaScriptCore/JSRetainPtr.h> +#import <JavaScriptCore/JSStringRef.h> +#import <JavaScriptCore/JSStringRefCF.h> +#import <WebKit/WebBackForwardList.h> +#import <WebKit/WebDatabaseManagerPrivate.h> +#import <WebKit/WebFrame.h> +#import <WebKit/WebHTMLViewPrivate.h> +#import <WebKit/WebHistory.h> +#import <WebKit/WebNSURLExtras.h> +#import <WebKit/WebPreferences.h> +#import <WebKit/WebPreferencesPrivate.h> +#import <WebKit/WebSecurityOriginPrivate.h> +#import <WebKit/WebView.h> +#import <WebKit/WebViewPrivate.h> +#import <wtf/RetainPtr.h> + +LayoutTestController::~LayoutTestController() +{ +} + +void LayoutTestController::addDisallowedURL(JSStringRef url) +{ + RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url)); + + if (!disallowedURLs) + disallowedURLs = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL); + + // Canonicalize the URL + NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:(NSString *)urlCF.get()]]; + request = [NSURLProtocol canonicalRequestForRequest:request]; + + CFSetAddValue(disallowedURLs, [request URL]); +} + +void LayoutTestController::clearAllDatabases() +{ + [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases]; +} + +void LayoutTestController::clearBackForwardList() +{ + WebBackForwardList *backForwardList = [[mainFrame webView] backForwardList]; + WebHistoryItem *item = [[backForwardList currentItem] retain]; + + // We clear the history by setting the back/forward list's capacity to 0 + // then restoring it back and adding back the current item. + int capacity = [backForwardList capacity]; + [backForwardList setCapacity:0]; + [backForwardList setCapacity:capacity]; + [backForwardList addItem:item]; + [backForwardList goToItem:item]; + [item release]; +} + +JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name) +{ + RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name)); + NSString *nameNS = (NSString *)nameCF.get(); + return JSStringCreateWithCFString((CFStringRef)[nameNS _web_decodeHostName]); +} + +JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name) +{ + RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name)); + NSString *nameNS = (NSString *)nameCF.get(); + return JSStringCreateWithCFString((CFStringRef)[nameNS _web_encodeHostName]); +} + +void LayoutTestController::display() +{ + displayWebView(); +} + +void LayoutTestController::keepWebHistory() +{ + if (![WebHistory optionalSharedHistory]) { + WebHistory *history = [[WebHistory alloc] init]; + [WebHistory setOptionalSharedHistory:history]; + [history release]; + } +} + +void LayoutTestController::notifyDone() +{ + if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count()) + dump(); + m_waitToDump = false; +} + +JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url) +{ + return JSStringRetain(url); // Do nothing on mac. +} + +void LayoutTestController::queueBackNavigation(int howFarBack) +{ + WorkQueue::shared()->queue(new BackItem(howFarBack)); +} + +void LayoutTestController::queueForwardNavigation(int howFarForward) +{ + WorkQueue::shared()->queue(new ForwardItem(howFarForward)); +} + +void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target) +{ + RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url)); + NSString *urlNS = (NSString *)urlCF.get(); + + NSURL *nsurl = [NSURL URLWithString:urlNS relativeToURL:[[[mainFrame dataSource] response] URL]]; + NSString* nsurlString = [nsurl absoluteString]; + + JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString([nsurlString UTF8String])); + WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target)); +} + +void LayoutTestController::queueReload() +{ + WorkQueue::shared()->queue(new ReloadItem); +} + +void LayoutTestController::queueScript(JSStringRef script) +{ + WorkQueue::shared()->queue(new ScriptItem(script)); +} + +void LayoutTestController::setAcceptsEditing(bool newAcceptsEditing) +{ + [(EditingDelegate *)[[mainFrame webView] editingDelegate] setAcceptsEditing:newAcceptsEditing]; +} + +void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag) +{ + [[[mainFrame webView] preferences] setAuthorAndUserStylesEnabled:flag]; +} + +void LayoutTestController::setCustomPolicyDelegate(bool setDelegate) +{ + if (setDelegate) + [[mainFrame webView] setPolicyDelegate:policyDelegate]; + else + [[mainFrame webView] setPolicyDelegate:nil]; +} + +void LayoutTestController::setDatabaseQuota(unsigned long long quota) +{ + WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithProtocol:@"file" domain:nil]; + [origin setQuota:quota]; + [origin release]; +} + +void LayoutTestController::setMainFrameIsFirstResponder(bool flag) +{ + NSView *documentView = [[mainFrame frameView] documentView]; + + NSResponder *firstResponder = flag ? documentView : nil; + [[[mainFrame webView] window] makeFirstResponder:firstResponder]; + + if ([documentView isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)documentView _updateFocusedAndActiveState]; +} + +void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled) +{ + [[[mainFrame webView] preferences] setPrivateBrowsingEnabled:privateBrowsingEnabled]; +} + +void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled) +{ + [[[mainFrame webView] preferences] setJavaScriptCanOpenWindowsAutomatically:!popupBlockingEnabled]; +} + +void LayoutTestController::setTabKeyCyclesThroughElements(bool cycles) +{ + [[mainFrame webView] setTabKeyCyclesThroughElements:cycles]; +} + +void LayoutTestController::setUseDashboardCompatibilityMode(bool flag) +{ + [[mainFrame webView] _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:flag]; +} + +void LayoutTestController::setUserStyleSheetEnabled(bool flag) +{ + [[WebPreferences standardPreferences] setUserStyleSheetEnabled:flag]; +} + +void LayoutTestController::setUserStyleSheetLocation(JSStringRef path) +{ + RetainPtr<CFStringRef> pathCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, path)); + NSURL *url = [NSURL URLWithString:(NSString *)pathCF.get()]; + [[WebPreferences standardPreferences] setUserStyleSheetLocation:url]; +} + +void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL) +{ + RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL)); + ::setPersistentUserStyleSheetLocation(urlString.get()); +} + +void LayoutTestController::clearPersistentUserStyleSheet() +{ + ::setPersistentUserStyleSheetLocation(0); +} + +void LayoutTestController::setWindowIsKey(bool windowIsKey) +{ + m_windowIsKey = windowIsKey; + NSView *documentView = [[mainFrame frameView] documentView]; + if ([documentView isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)documentView _updateFocusedAndActiveState]; +} + +static const CFTimeInterval waitToDumpWatchdogInterval = 10.0; + +static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info) +{ + const char* message = "FAIL: Timed out waiting for notifyDone to be called\n"; + fprintf(stderr, message); + fprintf(stdout, message); + dump(); +} + +void LayoutTestController::setWaitToDump(bool waitUntilDone) +{ + m_waitToDump = waitUntilDone; + if (m_waitToDump && !waitToDumpWatchdog) { + waitToDumpWatchdog = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + waitToDumpWatchdogInterval, 0, 0, 0, waitUntilDoneWatchdogFired, NULL); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), waitToDumpWatchdog, kCFRunLoopCommonModes); + } +} + +int LayoutTestController::windowCount() +{ + return CFArrayGetCount(openWindowsRef); +} + +void LayoutTestController::execCommand(JSStringRef name, JSStringRef value) +{ + RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name)); + NSString *nameNS = (NSString *)nameCF.get(); + + RetainPtr<CFStringRef> valueCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, value)); + NSString *valueNS = (NSString *)valueCF.get(); + + [[mainFrame webView] _executeCoreCommandByName:nameNS value:valueNS]; +} diff --git a/WebKitTools/DumpRenderTree/mac/NavigationController.h b/WebKitTools/DumpRenderTree/mac/NavigationController.h new file mode 100644 index 0000000..8ee3432 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/NavigationController.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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> +#import <WebKit/WebView.h> + +@interface NavigationController : NSObject +{ + enum { None, Load, GoBack, ExecuteScript } pendingAction; + NSString *pendingScript; + NSURLRequest *pendingRequest; +} +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame; +@end diff --git a/WebKitTools/DumpRenderTree/mac/NavigationController.m b/WebKitTools/DumpRenderTree/mac/NavigationController.m new file mode 100644 index 0000000..44aed8a --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/NavigationController.m @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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 <WebKit/WebFrame.h> +#import <WebKit/WebScriptObject.h> +#import "NavigationController.h" + +@implementation NavigationController ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector +{ + if (selector == @selector(evaluateWebScript:afterBackForwardNavigation:)) + return NO; + return YES; +} + ++ (NSString *)webScriptNameForSelector:(SEL)selector +{ + if (selector == @selector(evaluateWebScript:afterBackForwardNavigation:)) + return @"evalAfterBackForwardNavigation"; + return nil; +} + +- (void)setPendingScript:(NSString *)script +{ + if (script != pendingScript) { + [pendingScript release]; + pendingScript = [script copy]; + } +} + +- (void)setPendingRequest:(NSURLRequest *)request +{ + if (request != pendingRequest) { + [pendingRequest release]; + pendingRequest = [request copy]; + } +} + +- (void)evaluateWebScript:(NSString *)script afterBackForwardNavigation:(NSString *)navigation +{ + // Allow both arguments to be optional + if (![script isKindOfClass:[NSString class]]) + script = @""; + if (![navigation isKindOfClass:[NSString class]]) + navigation = @"about:blank"; + + [self setPendingScript:script]; + [self setPendingRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:navigation]]]; + pendingAction = Load; +} + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + if (frame == [[frame webView] mainFrame]) { + switch (pendingAction) { + case Load: + pendingAction = GoBack; + [frame loadRequest:pendingRequest]; + [self setPendingRequest:nil]; + break; + case GoBack: + pendingAction = ExecuteScript; + [[frame webView] goBack]; + break; + case ExecuteScript: + pendingAction = None; + [[[frame webView] windowScriptObject] evaluateWebScript:pendingScript]; + [self setPendingScript:nil]; + break; + case None: + default: + break; + } + } +} + +- (void)dealloc +{ + [self setPendingScript:nil]; + [self setPendingRequest:nil]; + [super dealloc]; +} +@end + diff --git a/WebKitTools/DumpRenderTree/mac/ObjCController.h b/WebKitTools/DumpRenderTree/mac/ObjCController.h new file mode 100644 index 0000000..d1d001c --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ObjCController.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007 Apple Inc. 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 <Foundation/Foundation.h> + +@class WebScriptObject; + +// This controller should be used to test Objective-C language features and the WebScriptObject. +@interface ObjCController : NSObject +{ + WebScriptObject *storedWebScriptObject; +} +@end diff --git a/WebKitTools/DumpRenderTree/mac/ObjCController.m b/WebKitTools/DumpRenderTree/mac/ObjCController.m new file mode 100644 index 0000000..9ca9299 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ObjCController.m @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2007 Apple Inc. 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 "ObjCController.h" + +#import <JavaScriptCore/JavaScriptCore.h> +#import <WebKit/DOMAbstractView.h> +#import <WebKit/WebScriptObject.h> +#import <WebKit/WebView.h> +#import <pthread.h> +#import <wtf/Assertions.h> + +static void* runJavaScriptThread(void* arg) +{ + JSGlobalContextRef ctx = JSGlobalContextCreate(0); + JSStringRef scriptRef = JSStringCreateWithUTF8CString("'Hello World!'"); + + JSValueRef exception = 0; + JSEvaluateScript(ctx, scriptRef, 0, 0, 0, &exception); + ASSERT(!exception); + + JSGlobalContextRelease(ctx); + JSStringRelease(scriptRef); + + return 0; +} + +@implementation ObjCController + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (0 + || aSelector == @selector(classNameOf:) + || aSelector == @selector(objectOfClass:) + || aSelector == @selector(identityIsEqual::) + || aSelector == @selector(longLongRoundTrip:) + || aSelector == @selector(unsignedLongLongRoundTrip:) + || aSelector == @selector(testWrapperRoundTripping:) + || aSelector == @selector(accessStoredWebScriptObject) + || aSelector == @selector(storeWebScriptObject:) + || aSelector == @selector(testValueForKey) + ) + return NO; + return YES; +} + ++ (NSString *)webScriptNameForSelector:(SEL)aSelector +{ + if (aSelector == @selector(classNameOf:)) + return @"className"; + if (aSelector == @selector(objectOfClass:)) + return @"objectOfClass"; + if (aSelector == @selector(identityIsEqual::)) + return @"identityIsEqual"; + if (aSelector == @selector(longLongRoundTrip:)) + return @"longLongRoundTrip"; + if (aSelector == @selector(unsignedLongLongRoundTrip:)) + return @"unsignedLongLongRoundTrip"; + if (aSelector == @selector(testWrapperRoundTripping:)) + return @"testWrapperRoundTripping"; + if (aSelector == @selector(storeWebScriptObject:)) + return @"storeWebScriptObject"; + if (aSelector == @selector(testValueForKey)) + return @"testValueForKey"; + + return nil; +} + +- (NSString *)classNameOf:(id)object +{ + if (!object) + return @"nil"; + return NSStringFromClass([object class]); +} + +- (id)objectOfClass:(NSString *)aClass +{ + if ([aClass isEqualToString:@"NSNull"]) + return [NSNull null]; + if ([aClass isEqualToString:@"WebUndefined"]) + return [WebUndefined undefined]; + if ([aClass isEqualToString:@"NSCFBoolean"]) + return [NSNumber numberWithBool:true]; + if ([aClass isEqualToString:@"NSCFNumber"]) + return [NSNumber numberWithInt:1]; + if ([aClass isEqualToString:@"NSCFString"]) + return @""; + if ([aClass isEqualToString:@"WebScriptObject"]) + return self; + if ([aClass isEqualToString:@"NSArray"]) + return [NSArray array]; + + return nil; +} + +- (BOOL)identityIsEqual:(WebScriptObject *)a :(WebScriptObject *)b +{ + if ([a isKindOfClass:[NSString class]] && [b isKindOfClass:[NSString class]]) + return [(NSString *)a isEqualToString:(NSString *)b]; + return a == b; +} + +- (long long)longLongRoundTrip:(long long)num +{ + return num; +} + +- (unsigned long long)unsignedLongLongRoundTrip:(unsigned long long)num +{ + return num; +} + +- (void)testValueForKey +{ + ASSERT(storedWebScriptObject); + + @try { + [storedWebScriptObject valueForKey:@"ThisKeyDoesNotExist"]; + } @catch (NSException *e) { + } + + pthread_t pthread; + pthread_create(&pthread, 0, &runJavaScriptThread, 0); + pthread_join(pthread, 0); +} + +- (BOOL)testWrapperRoundTripping:(WebScriptObject *)webScriptObject +{ + JSObjectRef jsObject = [webScriptObject JSObject]; + + if (!jsObject) + return false; + + if (!webScriptObject) + return false; + + if ([[webScriptObject evaluateWebScript:@"({ })"] class] != [webScriptObject class]) + return false; + + [webScriptObject setValue:[NSNumber numberWithInt:666] forKey:@"key"]; + if (![[webScriptObject valueForKey:@"key"] isKindOfClass:[NSNumber class]] || + ![[webScriptObject valueForKey:@"key"] isEqualToNumber:[NSNumber numberWithInt:666]]) + return false; + + [webScriptObject removeWebScriptKey:@"key"]; + @try { + if ([webScriptObject valueForKey:@"key"]) + return false; + } @catch(NSException *exception) { + // NSObject throws an exception if the key doesn't exist. + } + + [webScriptObject setWebScriptValueAtIndex:0 value:webScriptObject]; + if ([webScriptObject webScriptValueAtIndex:0] != webScriptObject) + return false; + + if ([[webScriptObject stringRepresentation] isEqualToString:@"[Object object]"]) + return false; + + if ([webScriptObject callWebScriptMethod:@"returnThis" withArguments:nil] != webScriptObject) + return false; + + return true; +} + +- (void)accessStoredWebScriptObject +{ +#if !ASSERT_DISABLED + BOOL isWindowObject = [storedWebScriptObject isKindOfClass:[DOMAbstractView class]]; +#endif + JSObjectRef jsObject = [storedWebScriptObject JSObject]; + ASSERT((jsObject && isWindowObject) || (!jsObject && !isWindowObject)); + + [storedWebScriptObject callWebScriptMethod:@"" withArguments:nil]; + [storedWebScriptObject evaluateWebScript:@""]; + [storedWebScriptObject setValue:[WebUndefined undefined] forKey:@"key"]; + [storedWebScriptObject valueForKey:@"key"]; + [storedWebScriptObject removeWebScriptKey:@"key"]; + [storedWebScriptObject stringRepresentation]; + [storedWebScriptObject webScriptValueAtIndex:0]; + [storedWebScriptObject setWebScriptValueAtIndex:0 value:[WebUndefined undefined]]; + [storedWebScriptObject setException:@"exception"]; +} + +- (void)storeWebScriptObject:(WebScriptObject *)webScriptObject +{ + if (webScriptObject == storedWebScriptObject) + return; + + [storedWebScriptObject release]; + storedWebScriptObject = [webScriptObject retain]; +} + +- (void)dealloc +{ + [storedWebScriptObject release]; + [super dealloc]; +} + +- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args +{ + // FIXME: Perhaps we should log that this has been called. + return nil; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/ObjCPlugin.h b/WebKitTools/DumpRenderTree/mac/ObjCPlugin.h new file mode 100644 index 0000000..a6d3e50 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ObjCPlugin.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR + * 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> + + +@interface ObjCPlugin : NSObject +{ + BOOL throwOnDealloc; +} + +- (void)removeBridgeRestrictions:(id)container; + +@end diff --git a/WebKitTools/DumpRenderTree/mac/ObjCPlugin.m b/WebKitTools/DumpRenderTree/mac/ObjCPlugin.m new file mode 100644 index 0000000..18b174c --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ObjCPlugin.m @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 James G. Speth (speth@end.com) + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR + * 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 "ObjCPlugin.h" +#import <objc/objc-runtime.h> +#import <WebKit/WebKit.h> + + +// === NSObject category to expose almost everything to JavaScript === + +// Warning: this class introduces huge security weaknesses, and should only be used +// for testing inside of DumpRenderTree, and only with trusted code. By default, it has +// the same restrictive behavior as the standard WebKit setup. However, scripts can use the +// plugin's removeBridgeRestrictions: method to open up almost total access to the Cocoa +// frameworks. + +static BOOL _allowsScriptsFullAccess = NO; + +@interface NSObject (ObjCScriptAccess) + ++ (void)setAllowsScriptsFullAccess:(BOOL)value; ++ (BOOL)allowsScriptsFullAccess; + +@end + +@implementation NSObject (ObjCScriptAccess) + ++ (void)setAllowsScriptsFullAccess:(BOOL)value +{ + _allowsScriptsFullAccess = value; +} + ++ (BOOL)allowsScriptsFullAccess +{ + return _allowsScriptsFullAccess; +} + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector +{ + return !_allowsScriptsFullAccess; +} + ++ (NSString *)webScriptNameForSelector:(SEL)selector +{ + return nil; +} + +@end + +@interface JSObjC : NSObject { +} + +// expose some useful objc functions to the scripting environment +- (id)lookUpClass:(NSString *)name; +- (void)log:(NSString *)message; +- (id)retainObject:(id)obj; +- (id)classOfObject:(id)obj; +- (NSString *)classNameOfObject:(id)obj; + +@end + +@implementation JSObjC + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (NSString *)webScriptNameForSelector:(SEL)selector +{ + return nil; +} + +- (id)invokeDefaultMethodWithArguments:(NSArray *)args +{ + // this is a useful shortcut for accessing objective-c classes from the scripting + // environment, e.g. 'var myObject = objc("NSObject").alloc().init();' + if ([args count] == 1) + return [self lookUpClass:[args objectAtIndex:0]]; + return nil; +} + +- (id)lookUpClass:(NSString *)name +{ + return NSClassFromString(name); +} + +- (void)log:(NSString *)message +{ + NSLog(message); +} + +- (id)retainObject:(id)obj +{ + return [obj retain]; +} + +- (id)classOfObject:(id)obj +{ + return (id)[obj class]; +} + +- (NSString *)classNameOfObject:(id)obj +{ + return [obj className]; +} + +@end + +@implementation ObjCPlugin + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(removeBridgeRestrictions:)) + return NO; + + if (aSelector == @selector(echo:)) + return NO; + + if (aSelector == @selector(throwIfArgumentIsNotHello:)) + return NO; + + return YES; +} + ++ (NSString *)webScriptNameForSelector:(SEL)aSelector +{ + if (aSelector == @selector(echo:)) + return @"echo"; + + if (aSelector == @selector(throwIfArgumentIsNotHello:)) + return @"throwIfArgumentIsNotHello"; + + return nil; +} + ++ (NSString *)webScriptNameForKey:(const char *)key +{ + if (strcmp(key, "throwOnDealloc") == 0) + return @"throwOnDealloc"; + + return nil; +} + ++ (BOOL)isKeyExcludedFromWebScript:(const char *)key +{ + if (strcmp(key, "throwOnDealloc") == 0) + return NO; + + return YES; +} + +- (void)removeBridgeRestrictions:(id)container +{ + // let scripts invoke any selector + [NSObject setAllowsScriptsFullAccess:YES]; + + // store a JSObjC instance into the provided container + JSObjC *objc = [[JSObjC alloc] init]; + [container setValue:objc forKey:@"objc"]; + [objc release]; +} + +- (id)echo:(id)obj +{ + return obj; +} + +- (void)throwIfArgumentIsNotHello:(NSString *)str +{ + if (![str isEqualToString:@"Hello"]) + [WebScriptObject throwException:[NSString stringWithFormat:@"%@ != Hello", str]]; +} + +- (void)dealloc +{ + if (throwOnDealloc) + [WebScriptObject throwException:@"Throwing exception on dealloc of ObjCPlugin"]; + + [super dealloc]; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/ObjCPluginFunction.h b/WebKitTools/DumpRenderTree/mac/ObjCPluginFunction.h new file mode 100644 index 0000000..1e81b21 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ObjCPluginFunction.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR + * 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> + + +@interface ObjCPluginFunction : NSObject +{ +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/ObjCPluginFunction.m b/WebKitTools/DumpRenderTree/mac/ObjCPluginFunction.m new file mode 100644 index 0000000..5cd16f8 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ObjCPluginFunction.m @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR OR + * 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 "ObjCPluginFunction.h" + + +@implementation ObjCPluginFunction + +- (id)invokeDefaultMethodWithArguments:(NSArray *)args +{ + return @"test"; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/PixelDumpSupportMac.mm b/WebKitTools/DumpRenderTree/mac/PixelDumpSupportMac.mm new file mode 100644 index 0000000..5a19164 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/PixelDumpSupportMac.mm @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "DumpRenderTree.h" +#include "PixelDumpSupport.h" +#include "PixelDumpSupportCG.h" + +#include "LayoutTestController.h" +#include <CoreGraphics/CGBitmapContext.h> +#include <wtf/Assertions.h> +#include <wtf/RetainPtr.h> + +#import <WebKit/WebDocumentPrivate.h> +#import <WebKit/WebKit.h> + +static unsigned char* screenCaptureBuffer; + +static CMProfileRef currentColorProfile = 0; +static CGColorSpaceRef sharedColorSpace; + +void restoreColorSpace(int ignored) +{ + // This is used as a signal handler, and thus the calls into ColorSync are unsafe + // But we might as well try to restore the user's color profile, we're going down anyway... + if (currentColorProfile) { + // This call is deprecated in Leopard, but there appears to be no replacement. + int error = CMSetDefaultProfileByUse(cmDisplayUse, currentColorProfile); + if (error) + fprintf(stderr, "Failed to retore previous color profile! You may need to open System Preferences : Displays : Color and manually restore your color settings. (Error: %i)", error); + currentColorProfile = 0; + } +} + +static void setDefaultColorProfileToRGB() +{ + CMProfileRef genericProfile = (CMProfileRef)[[NSColorSpace genericRGBColorSpace] colorSyncProfile]; + CMProfileRef previousProfile; + int error = CMGetDefaultProfileByUse(cmDisplayUse, &previousProfile); + if (error) { + fprintf(stderr, "Failed to get current color profile. I will not be able to restore your current profile, thus I'm not changing it. Many pixel tests may fail as a result. (Error: %i)\n", error); + return; + } + if (previousProfile == genericProfile) + return; + CFStringRef previousProfileName; + CFStringRef genericProfileName; + char previousProfileNameString[1024]; + char genericProfileNameString[1024]; + CMCopyProfileDescriptionString(previousProfile, &previousProfileName); + CMCopyProfileDescriptionString(genericProfile, &genericProfileName); + CFStringGetCString(previousProfileName, previousProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8); + CFStringGetCString(genericProfileName, genericProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8); + CFRelease(previousProfileName); + CFRelease(genericProfileName); + + fprintf(stderr, "\n\nWARNING: Temporarily changing your system color profile from \"%s\" to \"%s\".\n", previousProfileNameString, genericProfileNameString); + fprintf(stderr, "This allows the WebKit pixel-based regression tests to have consistent color values across all machines.\n"); + fprintf(stderr, "The colors on your screen will change for the duration of the testing.\n\n"); + + if ((error = CMSetDefaultProfileByUse(cmDisplayUse, genericProfile))) { + fprintf(stderr, "Failed to set color profile to \"%s\"! Many pixel tests will fail as a result. (Error: %i)", + genericProfileNameString, error); + } else { + currentColorProfile = previousProfile; + signal(SIGINT, restoreColorSpace); + signal(SIGHUP, restoreColorSpace); + signal(SIGTERM, restoreColorSpace); + } +} + +void initializeColorSpaceAndScreeBufferForPixelTests() +{ + setDefaultColorProfileToRGB(); + screenCaptureBuffer = (unsigned char *)malloc(maxViewHeight * maxViewWidth * 4); + sharedColorSpace = CGColorSpaceCreateDeviceRGB(); +} + +// Declared in PixelDumpSupportCG.h + +RetainPtr<CGContextRef> getBitmapContextFromWebView() +{ + NSSize webViewSize = [[mainFrame webView] frame].size; + return RetainPtr<CGContextRef>(AdoptCF, CGBitmapContextCreate(screenCaptureBuffer, static_cast<size_t>(webViewSize.width), static_cast<size_t>(webViewSize.height), 8, static_cast<size_t>(webViewSize.width) * 4, sharedColorSpace, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedLast)); +} + +void paintWebView(CGContextRef context) +{ + RetainPtr<NSGraphicsContext> savedContext = [NSGraphicsContext currentContext]; + + NSGraphicsContext* nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; + [NSGraphicsContext setCurrentContext:nsContext]; + + WebView* view = [mainFrame webView]; + [view displayIfNeeded]; + [view lockFocus]; + NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[view frame]]; + [view unlockFocus]; + [imageRep draw]; + [imageRep release]; + + [NSGraphicsContext setCurrentContext:savedContext.get()]; +} + +void repaintWebView(CGContextRef context, bool horizontal) +{ + RetainPtr<NSGraphicsContext> savedContext = [NSGraphicsContext currentContext]; + + NSGraphicsContext* nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; + [NSGraphicsContext setCurrentContext:nsContext]; + + WebView *view = [mainFrame webView]; + NSSize webViewSize = [view frame].size; + + if (horizontal) { + for (NSRect column = NSMakeRect(0, 0, 1, webViewSize.height); column.origin.x < webViewSize.width; column.origin.x++) + [view displayRectIgnoringOpacity:column inContext:nsContext]; + } else { + for (NSRect line = NSMakeRect(0, 0, webViewSize.width, 1); line.origin.y < webViewSize.height; line.origin.y++) + [view displayRectIgnoringOpacity:line inContext:nsContext]; + } + + [NSGraphicsContext setCurrentContext:savedContext.get()]; +} + +CGRect getSelectionRect() +{ + NSView *documentView = [[mainFrame frameView] documentView]; + if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) { + NSRect rect = [documentView convertRect:[(id <WebDocumentSelection>)documentView selectionRect] fromView:nil]; + return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); + } + + ASSERT_NOT_REACHED(); + return CGRectZero; +} diff --git a/WebKitTools/DumpRenderTree/mac/PolicyDelegate.h b/WebKitTools/DumpRenderTree/mac/PolicyDelegate.h new file mode 100644 index 0000000..f8bce68 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/PolicyDelegate.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2007 Apple Inc. 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> + + +@interface PolicyDelegate : NSObject { +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/PolicyDelegate.mm b/WebKitTools/DumpRenderTree/mac/PolicyDelegate.mm new file mode 100644 index 0000000..fc4ac74 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/PolicyDelegate.mm @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 Apple Inc. 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 "PolicyDelegate.h" + +#import "DumpRenderTree.h" +#import "DumpRenderTreeDraggingInfo.h" +#import <WebKit/WebPolicyDelegate.h> + +@implementation PolicyDelegate +- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation + request:(NSURLRequest *)request + frame:(WebFrame *)frame + decisionListener:(id<WebPolicyDecisionListener>)listener +{ + printf("Policy delegate: attempt to load %s\n", [[[request URL] absoluteString] UTF8String]); + [listener ignore]; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.h b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.h new file mode 100644 index 0000000..0c4618e --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2007 Apple Inc. 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> + + +@interface ResourceLoadDelegate : NSObject { +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm new file mode 100644 index 0000000..cc0eb4a --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2007, Apple Inc. 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 "ResourceLoadDelegate.h" + +#import "DumpRenderTree.h" +#import "LayoutTestController.h" +#import <WebKit/WebKit.h> +#import <wtf/Assertions.h> + +@interface NSURL (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@interface NSError (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@interface NSURLResponse (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@interface NSURLRequest (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult; +@end + +@implementation NSError (DRTExtras) +- (NSString *)_drt_descriptionSuitableForTestResult +{ + NSString *str = [NSString stringWithFormat:@"<NSError domain %@, code %d", [self domain], [self code]]; + NSURL *failingURL; + + if ((failingURL = [[self userInfo] objectForKey:@"NSErrorFailingURLKey"])) + str = [str stringByAppendingFormat:@", failing URL \"%@\"", [failingURL _drt_descriptionSuitableForTestResult]]; + + str = [str stringByAppendingFormat:@">"]; + + return str; +} + +@end + +@implementation NSURL (DRTExtras) + +- (NSString *)_drt_descriptionSuitableForTestResult +{ + if (![self isFileURL]) + return [self absoluteString]; + + WebDataSource *dataSource = [mainFrame dataSource]; + if (!dataSource) + dataSource = [mainFrame provisionalDataSource]; + + NSString *basePath = [[[[dataSource request] URL] path] stringByDeletingLastPathComponent]; + + return [[self path] substringFromIndex:[basePath length] + 1]; +} + +@end + +@implementation NSURLResponse (DRTExtras) + +- (NSString *)_drt_descriptionSuitableForTestResult +{ + return [NSString stringWithFormat:@"<NSURLResponse %@>", [[self URL] _drt_descriptionSuitableForTestResult]]; +} + +@end + +@implementation NSURLRequest (DRTExtras) + +- (NSString *)_drt_descriptionSuitableForTestResult +{ + return [NSString stringWithFormat:@"<NSURLRequest %@>", [[self URL] _drt_descriptionSuitableForTestResult]]; +} + +@end + +@implementation ResourceLoadDelegate + +- webView: (WebView *)wv identifierForInitialRequest: (NSURLRequest *)request fromDataSource: (WebDataSource *)dataSource +{ + ASSERT([[dataSource webFrame] dataSource] || [[dataSource webFrame] provisionalDataSource]); + + if (!done && layoutTestController->dumpResourceLoadCallbacks()) + return [[request URL] _drt_descriptionSuitableForTestResult]; + + return @"<unknown>"; +} + +-(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - willSendRequest %@ redirectResponse %@", identifier, [newRequest _drt_descriptionSuitableForTestResult], + [redirectResponse _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } + + if (disallowedURLs && CFSetContainsValue(disallowedURLs, [newRequest URL])) + return nil; + + return newRequest; +} + +- (void)webView:(WebView *)wv resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource +{ +} + +- (void)webView:(WebView *)wv resource:(id)identifier didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource +{ +} + +-(void)webView: (WebView *)wv resource:identifier didReceiveResponse: (NSURLResponse *)response fromDataSource:(WebDataSource *)dataSource +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didReceiveResponse %@", identifier, [response _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +-(void)webView: (WebView *)wv resource:identifier didReceiveContentLength: (unsigned)length fromDataSource:(WebDataSource *)dataSource +{ +} + +-(void)webView: (WebView *)wv resource:identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoading", identifier]; + printf ("%s\n", [string UTF8String]); + } +} + +-(void)webView: (WebView *)wv resource:identifier didFailLoadingWithError:(NSError *)error fromDataSource:(WebDataSource *)dataSource +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadingWithError: %@", identifier, [error _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + } +} + +- (void)webView: (WebView *)wv plugInFailedWithError:(NSError *)error dataSource:(WebDataSource *)dataSource +{ +} + +-(NSCachedURLResponse *) webView: (WebView *)wv resource:(id)identifier willCacheResponse:(NSCachedURLResponse *)response fromDataSource:(WebDataSource *)dataSource +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + NSString *string = [NSString stringWithFormat:@"%@ - willCacheResponse: called", identifier]; + printf ("%s\n", [string UTF8String]); + } + return response; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/TextInputController.h b/WebKitTools/DumpRenderTree/mac/TextInputController.h new file mode 100644 index 0000000..767e72f --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/TextInputController.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. 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 <Foundation/Foundation.h> + +@class WebView; +@class WebHTMLView; +@class WebScriptObject; + +@interface TextInputController : NSObject +{ + WebView *webView; + WebHTMLView *inputMethodView; + WebScriptObject *inputMethodHandler; +} +- (id)initWithWebView:(WebView *)view; +@end diff --git a/WebKitTools/DumpRenderTree/mac/TextInputController.m b/WebKitTools/DumpRenderTree/mac/TextInputController.m new file mode 100644 index 0000000..88b480b --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/TextInputController.m @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2005, 2007 Apple Inc. 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 "TextInputController.h" + +#import <AppKit/NSInputManager.h> +#import <WebKit/WebDocument.h> +#import <WebKit/WebFrame.h> +#import <WebKit/WebFrameView.h> +#import <WebKit/WebHTMLViewPrivate.h> +#import <WebKit/WebScriptObject.h> +#import <WebKit/WebView.h> + +@interface TextInputController (DumpRenderTreeInputMethodHandler) +- (BOOL)interpretKeyEvents:(NSArray *)eventArray withSender:(WebHTMLView *)sender; +@end + +@interface WebHTMLView (DumpRenderTreeInputMethodHandler) +- (void)interpretKeyEvents:(NSArray *)eventArray; +@end + +@interface WebHTMLView (WebKitSecretsTextInputControllerIsAwareOf) +- (WebFrame *)_frame; +@end + +@implementation WebHTMLView (DumpRenderTreeInputMethodHandler) +- (void)interpretKeyEvents:(NSArray *)eventArray +{ + WebScriptObject *obj = [[self _frame] windowObject]; + TextInputController *tic = [obj valueForKey:@"textInputController"]; + if (![tic interpretKeyEvents:eventArray withSender:self]) + [super interpretKeyEvents:eventArray]; +} +@end + +@implementation NSMutableAttributedString (TextInputController) + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(string) + || aSelector == @selector(getLength) + || aSelector == @selector(attributeNamesAtIndex:) + || aSelector == @selector(valueOfAttribute:atIndex:) + || aSelector == @selector(addAttribute:value:) + || aSelector == @selector(addAttribute:value:from:length:) + || aSelector == @selector(addColorAttribute:red:green:blue:alpha:) + || aSelector == @selector(addColorAttribute:red:green:blue:alpha:from:length:) + || aSelector == @selector(addFontAttribute:fontName:size:) + || aSelector == @selector(addFontAttribute:fontName:size:from:length:)) + return NO; + return YES; +} + ++ (NSString *)webScriptNameForSelector:(SEL)aSelector +{ + if (aSelector == @selector(getLength)) + return @"length"; + if (aSelector == @selector(attributeNamesAtIndex:)) + return @"getAttributeNamesAtIndex"; + if (aSelector == @selector(valueOfAttribute:atIndex:)) + return @"getAttributeValueAtIndex"; + if (aSelector == @selector(addAttribute:value:)) + return @"addAttribute"; + if (aSelector == @selector(addAttribute:value:from:length:)) + return @"addAttributeForRange"; + if (aSelector == @selector(addColorAttribute:red:green:blue:alpha:)) + return @"addColorAttribute"; + if (aSelector == @selector(addColorAttribute:red:green:blue:alpha:from:length:)) + return @"addColorAttributeForRange"; + if (aSelector == @selector(addFontAttribute:fontName:size:)) + return @"addFontAttribute"; + if (aSelector == @selector(addFontAttribute:fontName:size:from:length:)) + return @"addFontAttributeForRange"; + + return nil; +} + +- (int)getLength +{ + return (int)[self length]; +} + +- (NSArray *)attributeNamesAtIndex:(int)index +{ + NSDictionary *attributes = [self attributesAtIndex:(unsigned)index effectiveRange:nil]; + return [attributes allKeys]; +} + +- (id)valueOfAttribute:(NSString *)attrName atIndex:(int)index +{ + return [self attribute:attrName atIndex:(unsigned)index effectiveRange:nil]; +} + +- (void)addAttribute:(NSString *)attrName value:(id)value +{ + [self addAttribute:attrName value:value range:NSMakeRange(0, [self length])]; +} + +- (void)addAttribute:(NSString *)attrName value:(id)value from:(int)from length:(int)length +{ + [self addAttribute:attrName value:value range:NSMakeRange((unsigned)from, (unsigned)length)]; +} + +- (void)addColorAttribute:(NSString *)attrName red:(float)red green:(float)green blue:(float)blue alpha:(float)alpha +{ + [self addAttribute:attrName value:[NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha] range:NSMakeRange(0, [self length])]; +} + +- (void)addColorAttribute:(NSString *)attrName red:(float)red green:(float)green blue:(float)blue alpha:(float)alpha from:(int)from length:(int)length +{ + [self addAttribute:attrName value:[NSColor colorWithDeviceRed:red green:green blue:blue alpha:alpha] range:NSMakeRange((unsigned)from, (unsigned)length)]; +} + +- (void)addFontAttribute:(NSString *)attrName fontName:(NSString *)fontName size:(float)fontSize +{ + [self addAttribute:attrName value:[NSFont fontWithName:fontName size:fontSize] range:NSMakeRange(0, [self length])]; +} + +- (void)addFontAttribute:(NSString *)attrName fontName:(NSString *)fontName size:(float)fontSize from:(int)from length:(int)length +{ + [self addAttribute:attrName value:[NSFont fontWithName:fontName size:fontSize] range:NSMakeRange((unsigned)from, (unsigned)length)]; +} + +@end + +@implementation TextInputController + ++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector +{ + if (aSelector == @selector(insertText:) + || aSelector == @selector(doCommand:) + || aSelector == @selector(setMarkedText:selectedFrom:length:) + || aSelector == @selector(unmarkText) + || aSelector == @selector(hasMarkedText) + || aSelector == @selector(conversationIdentifier) + || aSelector == @selector(substringFrom:length:) + || aSelector == @selector(attributedSubstringFrom:length:) + || aSelector == @selector(markedRange) + || aSelector == @selector(selectedRange) + || aSelector == @selector(firstRectForCharactersFrom:length:) + || aSelector == @selector(characterIndexForPointX:Y:) + || aSelector == @selector(validAttributesForMarkedText) + || aSelector == @selector(attributedStringWithString:) + || aSelector == @selector(setInputMethodHandler:)) + return NO; + return YES; +} + ++ (NSString *)webScriptNameForSelector:(SEL)aSelector +{ + if (aSelector == @selector(insertText:)) + return @"insertText"; + else if (aSelector == @selector(doCommand:)) + return @"doCommand"; + else if (aSelector == @selector(setMarkedText:selectedFrom:length:)) + return @"setMarkedText"; + else if (aSelector == @selector(substringFrom:length:)) + return @"substringFromRange"; + else if (aSelector == @selector(attributedSubstringFrom:length:)) + return @"attributedSubstringFromRange"; + else if (aSelector == @selector(firstRectForCharactersFrom:length:)) + return @"firstRectForCharacterRange"; + else if (aSelector == @selector(characterIndexForPointX:Y:)) + return @"characterIndexForPoint"; + else if (aSelector == @selector(attributedStringWithString:)) + return @"makeAttributedString"; // just a factory method, doesn't call into NSTextInput + else if (aSelector == @selector(setInputMethodHandler:)) + return @"setInputMethodHandler"; + + return nil; +} + +- (id)initWithWebView:(WebView *)wv +{ + self = [super init]; + webView = wv; + inputMethodView = nil; + inputMethodHandler = nil; + return self; +} + +- (void)dealloc +{ + [inputMethodHandler release]; + inputMethodHandler = nil; + + [super dealloc]; +} + +- (NSObject <NSTextInput> *)textInput +{ + NSView <NSTextInput> *view = inputMethodView ? inputMethodView : (id)[[[webView mainFrame] frameView] documentView]; + return [view conformsToProtocol:@protocol(NSTextInput)] ? view : nil; +} + +- (void)insertText:(id)aString +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + [textInput insertText:aString]; +} + +- (void)doCommand:(NSString *)aCommand +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + [textInput doCommandBySelector:NSSelectorFromString(aCommand)]; +} + +- (void)setMarkedText:(NSString *)aString selectedFrom:(int)from length:(int)length +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + [textInput setMarkedText:aString selectedRange:NSMakeRange(from, length)]; +} + +- (void)unmarkText +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + [textInput unmarkText]; +} + +- (BOOL)hasMarkedText +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + return [textInput hasMarkedText]; + + return FALSE; +} + +- (long)conversationIdentifier +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + return [textInput conversationIdentifier]; + + return 0; +} + +- (NSString *)substringFrom:(int)from length:(int)length +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + return [[textInput attributedSubstringFromRange:NSMakeRange(from, length)] string]; + + return @""; +} + +- (NSMutableAttributedString *)attributedSubstringFrom:(int)from length:(int)length +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + NSMutableAttributedString *ret = [[[NSMutableAttributedString alloc] init] autorelease]; + + if (textInput) + [ret setAttributedString:[textInput attributedSubstringFromRange:NSMakeRange(from, length)]]; + + return ret; +} + +- (NSArray *)markedRange +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) { + NSRange range = [textInput markedRange]; + return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil]; + } + + return nil; +} + +- (NSArray *)selectedRange +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) { + NSRange range = [textInput selectedRange]; + return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil]; + } + + return nil; +} + + +- (NSArray *)firstRectForCharactersFrom:(int)from length:(int)length +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) { + NSRect rect = [textInput firstRectForCharacterRange:NSMakeRange(from, length)]; + if (rect.origin.x || rect.origin.y || rect.size.width || rect.size.height) { + rect.origin = [[webView window] convertScreenToBase:rect.origin]; + rect = [webView convertRect:rect fromView:nil]; + } + return [NSArray arrayWithObjects: + [NSNumber numberWithFloat:rect.origin.x], + [NSNumber numberWithFloat:rect.origin.y], + [NSNumber numberWithFloat:rect.size.width], + [NSNumber numberWithFloat:rect.size.height], + nil]; + } + + return nil; +} + +- (int)characterIndexForPointX:(float)x Y:(float)y +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) { + NSPoint point = NSMakePoint(x, y); + point = [webView convertPoint:point toView:nil]; + point = [[webView window] convertBaseToScreen:point]; + return [textInput characterIndexForPoint:point]; + } + + return 0; +} + +- (NSArray *)validAttributesForMarkedText +{ + NSObject <NSTextInput> *textInput = [self textInput]; + + if (textInput) + return [textInput validAttributesForMarkedText]; + + return nil; +} + +- (NSMutableAttributedString *)attributedStringWithString:(NSString *)aString +{ + return [[[NSMutableAttributedString alloc] initWithString:aString] autorelease]; +} + +- (void)setInputMethodHandler:(WebScriptObject *)handler +{ + if (inputMethodHandler == handler) + return; + [handler retain]; + [inputMethodHandler release]; + inputMethodHandler = handler; +} + +- (BOOL)interpretKeyEvents:(NSArray *)eventArray withSender:(WebHTMLView *)sender +{ + if (!inputMethodHandler) + return NO; + + inputMethodView = sender; + + NSEvent *event = [eventArray objectAtIndex:0]; + unsigned modifierFlags = [event modifierFlags]; + NSMutableArray *modifiers = [[NSMutableArray alloc] init]; + if (modifierFlags & NSAlphaShiftKeyMask) + [modifiers addObject:@"NSAlphaShiftKeyMask"]; + if (modifierFlags & NSShiftKeyMask) + [modifiers addObject:@"NSShiftKeyMask"]; + if (modifierFlags & NSControlKeyMask) + [modifiers addObject:@"NSControlKeyMask"]; + if (modifierFlags & NSAlternateKeyMask) + [modifiers addObject:@"NSAlternateKeyMask"]; + if (modifierFlags & NSCommandKeyMask) + [modifiers addObject:@"NSCommandKeyMask"]; + if (modifierFlags & NSNumericPadKeyMask) + [modifiers addObject:@"NSNumericPadKeyMask"]; + if (modifierFlags & NSHelpKeyMask) + [modifiers addObject:@"NSHelpKeyMask"]; + if (modifierFlags & NSFunctionKeyMask) + [modifiers addObject:@"NSFunctionKeyMask"]; + + WebScriptObject* eventParam = [inputMethodHandler evaluateWebScript:@"new Object();"]; + [eventParam setValue:[event characters] forKey:@"characters"]; + [eventParam setValue:[event charactersIgnoringModifiers] forKey:@"charactersIgnoringModifiers"]; + [eventParam setValue:[NSNumber numberWithBool:[event isARepeat]] forKey:@"isARepeat"]; + [eventParam setValue:[NSNumber numberWithUnsignedShort:[event keyCode]] forKey:@"keyCode"]; + [eventParam setValue:modifiers forKey:@"modifierFlags"]; + + [modifiers release]; + + id result = [inputMethodHandler callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:inputMethodHandler, eventParam, nil]]; + if (![result respondsToSelector:@selector(boolValue)] || ![result boolValue]) + [sender doCommandBySelector:@selector(noop:)]; // AppKit sends noop: if the ime does not handle an event + + inputMethodView = nil; + return YES; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/UIDelegate.h b/WebKitTools/DumpRenderTree/mac/UIDelegate.h new file mode 100644 index 0000000..da472d6 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/UIDelegate.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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> + +@interface UIDelegate : NSObject { + +@private + NSRect m_frame; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm new file mode 100644 index 0000000..9c440a7 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2006. 2007 Apple Inc. 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 "DumpRenderTree.h" +#import "UIDelegate.h" + +#import "DumpRenderTreeDraggingInfo.h" +#import "EventSendingController.h" +#import "LayoutTestController.h" +#import <WebKit/WebFramePrivate.h> +#import <WebKit/WebHTMLViewPrivate.h> +#import <WebKit/WebView.h> +#import <WebKit/WebSecurityOriginPrivate.h> +#import <wtf/Assertions.h> + +DumpRenderTreeDraggingInfo *draggingInfo = nil; + +@implementation UIDelegate + +- (void)webView:(WebView *)sender setFrame:(NSRect)frame +{ + m_frame = frame; +} + +- (NSRect)webViewFrame:(WebView *)sender; +{ + return m_frame; +} + +- (void)webView:(WebView *)sender addMessageToConsole:(NSDictionary *)dictionary +{ + NSString *message = [dictionary objectForKey:@"message"]; + NSNumber *lineNumber = [dictionary objectForKey:@"lineNumber"]; + + NSRange range = [message rangeOfString:@"file://"]; + if (range.location != NSNotFound) + message = [[message substringToIndex:range.location] stringByAppendingString:[[message substringFromIndex:NSMaxRange(range)] lastPathComponent]]; + + printf ("CONSOLE MESSAGE: line %d: %s\n", [lineNumber intValue], [message UTF8String]); +} + +- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + if (!done) + printf("ALERT: %s\n", [message UTF8String]); +} + +- (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + if (!done) + printf("CONFIRM: %s\n", [message UTF8String]); + return YES; +} + +- (NSString *)webView:(WebView *)sender runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WebFrame *)frame +{ + if (!done) + printf("PROMPT: %s, default text: %s\n", [prompt UTF8String], [defaultText UTF8String]); + return defaultText; +} + +- (void)webView:(WebView *)sender dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag forView:(NSView *)view +{ + assert(!draggingInfo); + if (layoutTestController->addFileToPasteboardOnDrag()) { + [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil]; + [pboard setPropertyList:[NSArray arrayWithObject:@"DRTFakeFile"] forType:NSFilenamesPboardType]; + } + draggingInfo = [[DumpRenderTreeDraggingInfo alloc] initWithImage:anImage offset:initialOffset pasteboard:pboard source:sourceObj]; + [EventSendingController replaySavedEvents]; +} + +- (void)webViewFocus:(WebView *)webView +{ + layoutTestController->setWindowIsKey(true); + NSView *documentView = [[mainFrame frameView] documentView]; + if ([documentView isKindOfClass:[WebHTMLView class]]) + [(WebHTMLView *)documentView _updateFocusedAndActiveState]; +} + +- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request +{ + if (!layoutTestController->canOpenWindows()) + return nil; + + // Make sure that waitUntilDone has been called. + ASSERT(layoutTestController->waitToDump()); + + WebView *webView = createWebViewAndOffscreenWindow(); + + return [webView autorelease]; +} + +- (void)webViewClose:(WebView *)sender +{ + NSWindow* window = [sender window]; + + if (layoutTestController->callCloseOnWebViews()) + [sender close]; + + [window close]; +} + +- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(WebSecurityOrigin *)origin database:(NSString *)databaseIdentifier +{ + if (!done && layoutTestController->dumpDatabaseCallbacks()) + printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n", [[origin protocol] UTF8String], [[origin domain] UTF8String], + [origin port], [databaseIdentifier UTF8String]); + + static const unsigned long long defaultQuota = 5 * 1024 * 1024; + [origin setQuota:defaultQuota]; +} + +- (void)webView:(WebView *)sender setStatusText:(NSString *)text +{ + if (layoutTestController->dumpStatusCallbacks()) + printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", [text UTF8String]); +} + +- (void)dealloc +{ + [draggingInfo release]; + draggingInfo = nil; + + [super dealloc]; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/WorkQueueItemMac.mm b/WebKitTools/DumpRenderTree/mac/WorkQueueItemMac.mm new file mode 100644 index 0000000..3a7b0e2 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/WorkQueueItemMac.mm @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007 Apple Inc. 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 "DumpRenderTree.h" +#import "WorkQueueItem.h" + +#import <JavaScriptCore/JSStringRef.h> +#import <JavaScriptCore/JSStringRefCF.h> +#import <WebKit/WebBackForwardList.h> +#import <WebKit/WebFrame.h> +#import <WebKit/WebScriptObject.h> +#import <WebKit/WebView.h> +#import <wtf/RetainPtr.h> + +void LoadItem::invoke() const +{ + RetainPtr<CFStringRef> urlCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, m_url.get())); + NSString *urlNS = (NSString *)urlCF.get(); + RetainPtr<CFStringRef> targetCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, m_target.get())); + NSString *targetNS = (NSString *)targetCF.get(); + + WebFrame *targetFrame; + if (targetNS && [targetNS length]) + targetFrame = [mainFrame findFrameNamed:targetNS]; + else + targetFrame = mainFrame; + [targetFrame loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlNS]]]; +} + +void ReloadItem::invoke() const +{ + [[mainFrame webView] reload:nil]; +} + +void ScriptItem::invoke() const +{ + RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, m_script.get())); + NSString *scriptNS = (NSString *)scriptCF.get(); + [[mainFrame webView] stringByEvaluatingJavaScriptFromString:scriptNS]; +} + +void BackForwardItem::invoke() const +{ + if (m_howFar == 1) + [[mainFrame webView] goForward]; + else if (m_howFar == -1) + [[mainFrame webView] goBack]; + else { + WebBackForwardList *bfList = [[mainFrame webView] backForwardList]; + [[mainFrame webView] goToBackForwardItem:[bfList itemAtIndex:m_howFar]]; + } +} diff --git a/WebKitTools/DumpRenderTree/pthreads/JavaScriptThreadingPthreads.cpp b/WebKitTools/DumpRenderTree/pthreads/JavaScriptThreadingPthreads.cpp new file mode 100644 index 0000000..19f6dc2 --- /dev/null +++ b/WebKitTools/DumpRenderTree/pthreads/JavaScriptThreadingPthreads.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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. + */ + +#include "JavaScriptThreading.h" + +#include <CoreFoundation/CoreFoundation.h> +#include <JavaScriptCore/JavaScriptCore.h> +#include <pthread.h> +#include <wtf/Assertions.h> +#include <wtf/HashSet.h> + +static pthread_mutex_t javaScriptThreadsMutex = PTHREAD_MUTEX_INITIALIZER; +static bool javaScriptThreadsShouldTerminate; + +static const int javaScriptThreadsCount = 4; + +typedef HashSet<pthread_t> ThreadSet; + +static ThreadSet* javaScriptThreads() +{ + ASSERT(pthread_mutex_trylock(&javaScriptThreadsMutex) == EBUSY); + static ThreadSet staticJavaScriptThreads; + return &staticJavaScriptThreads; +} + +// Loops forever, running a script and randomly respawning, until +// javaScriptThreadsShouldTerminate becomes true. +void* runJavaScriptThread(void* arg) +{ + const char* const script = + "var array = [];" + "for (var i = 0; i < 10; i++) {" + " array.push(String(i));" + "}"; + + while (1) { + JSGlobalContextRef ctx = JSGlobalContextCreate(0); + JSStringRef scriptRef = JSStringCreateWithUTF8CString(script); + + JSValueRef exception = 0; + JSEvaluateScript(ctx, scriptRef, 0, 0, 0, &exception); + ASSERT(!exception); + + JSGlobalContextRelease(ctx); + JSStringRelease(scriptRef); + + JSGarbageCollect(ctx); + + pthread_mutex_lock(&javaScriptThreadsMutex); + + // Check for cancellation. + if (javaScriptThreadsShouldTerminate) { + pthread_mutex_unlock(&javaScriptThreadsMutex); + return 0; + } + + // Respawn probabilistically. + if (random() % 5 == 0) { + pthread_t pthread; + pthread_create(&pthread, 0, &runJavaScriptThread, 0); + pthread_detach(pthread); + + javaScriptThreads()->remove(pthread_self()); + javaScriptThreads()->add(pthread); + + pthread_mutex_unlock(&javaScriptThreadsMutex); + return 0; + } + + pthread_mutex_unlock(&javaScriptThreadsMutex); + } +} + +void startJavaScriptThreads() +{ + pthread_mutex_lock(&javaScriptThreadsMutex); + + for (int i = 0; i < javaScriptThreadsCount; i++) { + pthread_t pthread; + pthread_create(&pthread, 0, &runJavaScriptThread, 0); + javaScriptThreads()->add(pthread); + } + + pthread_mutex_unlock(&javaScriptThreadsMutex); +} + +void stopJavaScriptThreads() +{ + pthread_mutex_lock(&javaScriptThreadsMutex); + + javaScriptThreadsShouldTerminate = true; + + ASSERT(javaScriptThreads()->size() == javaScriptThreadsCount); + + pthread_mutex_unlock(&javaScriptThreadsMutex); + + ThreadSet::iterator end = javaScriptThreads()->end(); + for (ThreadSet::iterator it = javaScriptThreads()->begin(); it != end; ++it) { + pthread_t pthread = *it; + pthread_join(pthread, 0); + } +} diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp new file mode 100644 index 0000000..5df8a38 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * + * 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. + */ + +#include "DumpRenderTree.h" +#include "jsobjects.h" + +#include <QDir> +#include <QFile> +#include <QTimer> +#include <QBoxLayout> +#include <QScrollArea> +#include <QApplication> +#include <QUrl> +#include <QFocusEvent> + +#include <qwebpage.h> +#include <qwebframe.h> +#include <qwebview.h> +#include <qwebsettings.h> + +#include <unistd.h> +#include <qdebug.h> +extern void qt_drt_run(bool b); +extern void qt_dump_set_accepts_editing(bool b); + + +namespace WebCore { + +// Choose some default values. +const unsigned int maxViewWidth = 800; +const unsigned int maxViewHeight = 600; + +class WebPage : public QWebPage { + Q_OBJECT +public: + WebPage(QWidget *parent, DumpRenderTree *drt); + + QWebPage *createWindow(); + + void javaScriptAlert(QWebFrame *frame, const QString& message); + void javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString& sourceID); + bool javaScriptConfirm(QWebFrame *frame, const QString& msg); + bool javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result); + +private slots: + void setViewGeometry(const QRect &r) + { + QWidget *v = view(); + if (v) + v->setGeometry(r); + } +private: + DumpRenderTree *m_drt; +}; + +WebPage::WebPage(QWidget *parent, DumpRenderTree *drt) + : QWebPage(parent), m_drt(drt) +{ + settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true); + settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true); + settings()->setAttribute(QWebSettings::LinksIncludedInFocusChain, false); + connect(this, SIGNAL(geometryChangeRequest(const QRect &)), + this, SLOT(setViewGeometry(const QRect & ))); +} + +QWebPage *WebPage::createWindow() +{ + return m_drt->createWindow(); +} + +void WebPage::javaScriptAlert(QWebFrame *frame, const QString& message) +{ + fprintf(stdout, "ALERT: %s\n", message.toUtf8().constData()); +} + +void WebPage::javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString&) +{ + fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.toUtf8().constData()); +} + +bool WebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) +{ + fprintf(stdout, "CONFIRM: %s\n", msg.toUtf8().constData()); + return true; +} + +bool WebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result) +{ + fprintf(stdout, "PROMPT: %s, default text: %s\n", msg.toUtf8().constData(), defaultValue.toUtf8().constData()); + *result = defaultValue; + return true; +} + +DumpRenderTree::DumpRenderTree() + : m_stdin(0) + , m_notifier(0) +{ + m_controller = new LayoutTestController(this); + connect(m_controller, SIGNAL(done()), this, SLOT(dump()), Qt::QueuedConnection); + + QWebView *view = new QWebView(0); + view->resize(QSize(maxViewWidth, maxViewHeight)); + m_page = new WebPage(view, this); + view->setPage(m_page); + connect(m_page, SIGNAL(frameCreated(QWebFrame *)), this, SLOT(connectFrame(QWebFrame *))); + connectFrame(m_page->mainFrame()); + + m_page->mainFrame()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_page->mainFrame()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + connect(m_page->mainFrame(), SIGNAL(titleChanged(const QString&)), + SLOT(titleChanged(const QString&))); + + m_eventSender = new EventSender(m_page); + m_textInputController = new TextInputController(m_page); + + QObject::connect(this, SIGNAL(quit()), qApp, SLOT(quit()), Qt::QueuedConnection); + qt_drt_run(true); + QFocusEvent event(QEvent::FocusIn, Qt::ActiveWindowFocusReason); + QApplication::sendEvent(view, &event); +} + +DumpRenderTree::~DumpRenderTree() +{ + delete m_page; + + delete m_stdin; + delete m_notifier; +} + +void DumpRenderTree::open() +{ + if (!m_stdin) { + m_stdin = new QFile; + m_stdin->open(stdin, QFile::ReadOnly); + } + + if (!m_notifier) { + m_notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read); + connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readStdin(int))); + } +} + +void DumpRenderTree::open(const QUrl& url) +{ + resetJSObjects(); + m_page->mainFrame()->load(url); +} + +void DumpRenderTree::readStdin(int /* socket */) +{ + // Read incoming data from stdin... + QByteArray line = m_stdin->readLine(); + if (line.endsWith('\n')) + line.truncate(line.size()-1); + //fprintf(stderr, "\n opening %s\n", line.constData()); + if (line.isEmpty()) + quit(); + QFileInfo fi(line); + open(QUrl::fromLocalFile(fi.absoluteFilePath())); + fflush(stdout); +} + +void DumpRenderTree::resetJSObjects() +{ + m_controller->reset(); + foreach(QWidget *widget, windows) + delete widget; + windows.clear(); +} + +void DumpRenderTree::initJSObjects() +{ + QWebFrame *frame = qobject_cast<QWebFrame*>(sender()); + Q_ASSERT(frame); + frame->addToJSWindowObject(QLatin1String("layoutTestController"), m_controller); + frame->addToJSWindowObject(QLatin1String("eventSender"), m_eventSender); + frame->addToJSWindowObject(QLatin1String("textInputController"), m_textInputController); +} + + +QString DumpRenderTree::dumpFramesAsText(QWebFrame* frame) +{ + if (!frame) + return QString(); + + QString result; + QWebFrame *parent = qobject_cast<QWebFrame *>(frame->parent()); + if (parent) { + result.append(QLatin1String("\n--------\nFrame: '")); + result.append(frame->name()); + result.append(QLatin1String("'\n--------\n")); + } + + result.append(frame->innerText()); + result.append(QLatin1String("\n")); + + if (m_controller->shouldDumpChildrenAsText()) { + QList<QWebFrame *> children = frame->childFrames(); + for (int i = 0; i < children.size(); ++i) + result += dumpFramesAsText(children.at(i)); + } + + return result; +} + +void DumpRenderTree::dump() +{ + QWebFrame *frame = m_page->mainFrame(); + + //fprintf(stderr, " Dumping\n"); + if (!m_notifier) { + // Dump markup in single file mode... + QString markup = frame->markup(); + fprintf(stdout, "Source:\n\n%s\n", markup.toUtf8().constData()); + } + + // Dump render text... + QString renderDump; + if (m_controller->shouldDumpAsText()) { + renderDump = dumpFramesAsText(frame); + } else { + renderDump = frame->renderTreeDump(); + } + if (renderDump.isEmpty()) { + printf("ERROR: nil result from %s", m_controller->shouldDumpAsText() ? "[documentElement innerText]" : "[frame renderTreeAsExternalRepresentation]"); + } else { + fprintf(stdout, "%s", renderDump.toUtf8().constData()); + } + + fprintf(stdout, "#EOF\n"); + + fflush(stdout); + + if (!m_notifier) { + // Exit now in single file mode... + quit(); + } +} + +void DumpRenderTree::titleChanged(const QString &s) +{ + if (m_controller->shouldDumpTitleChanges()) + printf("TITLE CHANGED: %s\n", s.toUtf8().data()); +} + +void DumpRenderTree::connectFrame(QWebFrame *frame) +{ + connect(frame, SIGNAL(cleared()), this, SLOT(initJSObjects())); + connect(frame, SIGNAL(provisionalLoad()), + layoutTestController(), SLOT(provisionalLoad())); + + if (frame == m_page->mainFrame()) { + connect(frame, SIGNAL(loadDone(bool)), + layoutTestController(), SLOT(maybeDump(bool))); + } +} + +QWebPage *DumpRenderTree::createWindow() +{ + if (!m_controller->canOpenWindows()) + return 0; + QWidget *container = new QWidget(0); + container->resize(0, 0); + container->move(-1, -1); + container->hide(); + QWebPage *page = new WebPage(container, this); + connect(m_page, SIGNAL(frameCreated(QWebFrame *)), this, SLOT(connectFrame(QWebFrame *))); + windows.append(container); + return page; +} + +int DumpRenderTree::windowCount() const +{ + int count = 0; + foreach(QWidget *w, windows) { + if (w->children().count()) + ++count; + } + return count + 1; +} + +} + +#include "DumpRenderTree.moc" diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.h b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.h new file mode 100644 index 0000000..b939fad --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * + * 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. + */ + +#ifndef DUMPRENDERTREE_H +#define DUMPRENDERTREE_H + +#include <QList> +#include <QObject> +#include <QTextStream> +#include <QSocketNotifier> +class QUrl; +class QFile; +class QWebPage; +class QWebFrame; + +class LayoutTestController; +class EventSender; +class TextInputController; + +namespace WebCore { + +class DumpRenderTree : public QObject { +Q_OBJECT + +public: + DumpRenderTree(); + virtual ~DumpRenderTree(); + + // Initialize in multi-file mode, used by run-webkit-tests. + void open(); + + // Initialize in single-file mode. + void open(const QUrl& url); + + void resetJSObjects(); + + LayoutTestController *layoutTestController() const { return m_controller; } + EventSender *eventSender() const { return m_eventSender; } + TextInputController *textInputController() const { return m_textInputController; } + + QWebPage *createWindow(); + int windowCount() const; + + QWebPage *webPage() const { return m_page; } + +public Q_SLOTS: + void initJSObjects(); + void readStdin(int); + void dump(); + void titleChanged(const QString &s); + void connectFrame(QWebFrame *frame); + +Q_SIGNALS: + void quit(); + +private: + QString dumpFramesAsText(QWebFrame* frame); + LayoutTestController *m_controller; + + QWebPage *m_page; + + EventSender *m_eventSender; + TextInputController *m_textInputController; + + QFile *m_stdin; + QSocketNotifier* m_notifier; + + QList<QWidget *> windows; +}; + +} + +#endif diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro new file mode 100644 index 0000000..8c3dbbf --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro @@ -0,0 +1,18 @@ +TARGET = DumpRenderTree +CONFIG -= app_bundle + +include(../../../WebKit.pri) +INCLUDEPATH += /usr/include/freetype2 +INCLUDEPATH += ../../../JavaScriptCore/kjs +DESTDIR = ../../../bin + + +QT = core gui +macx: QT += xml network + +HEADERS = DumpRenderTree.h jsobjects.h testplugin.h +SOURCES = DumpRenderTree.cpp main.cpp jsobjects.cpp testplugin.cpp + +unix:!mac { + QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR +} diff --git a/WebKitTools/DumpRenderTree/qt/fonts.conf b/WebKitTools/DumpRenderTree/qt/fonts.conf new file mode 100644 index 0000000..3540c47 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/fonts.conf @@ -0,0 +1,258 @@ +<?xml version="1.0"?> +<!DOCTYPE fontconfig SYSTEM "fonts.dtd"> +<fontconfig> + +<!-- + Accept deprecated 'mono' alias, replacing it with 'monospace' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>mono</string> + </test> + <edit name="family" mode="assign"> + <string>monospace</string> + </edit> + </match> + +<!-- + Accept alternate 'sans serif' spelling, replacing it with 'sans-serif' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans serif</string> + </test> + <edit name="family" mode="assign"> + <string>sans-serif</string> + </edit> + </match> + +<!-- + Accept deprecated 'sans' alias, replacing it with 'sans-serif' +--> + <match target="pattern"> + <test qual="any" name="family"> + <string>sans</string> + </test> + <edit name="family" mode="assign"> + <string>sans-serif</string> + </edit> + </match> + + + <config> +<!-- + These are the default Unicode chars that are expected to be blank + in fonts. All other blank chars are assumed to be broken and + won't appear in the resulting charsets + --> + <blank> + <int>0x0020</int> <!-- SPACE --> + <int>0x00A0</int> <!-- NO-BREAK SPACE --> + <int>0x00AD</int> <!-- SOFT HYPHEN --> + <int>0x034F</int> <!-- COMBINING GRAPHEME JOINER --> + <int>0x0600</int> <!-- ARABIC NUMBER SIGN --> + <int>0x0601</int> <!-- ARABIC SIGN SANAH --> + <int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER --> + <int>0x0603</int> <!-- ARABIC SIGN SAFHA --> + <int>0x06DD</int> <!-- ARABIC END OF AYAH --> + <int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK --> + <int>0x115F</int> <!-- HANGUL CHOSEONG FILLER --> + <int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER --> + <int>0x1680</int> <!-- OGHAM SPACE MARK --> + <int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ --> + <int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA --> + <int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR --> + <int>0x2000</int> <!-- EN QUAD --> + <int>0x2001</int> <!-- EM QUAD --> + <int>0x2002</int> <!-- EN SPACE --> + <int>0x2003</int> <!-- EM SPACE --> + <int>0x2004</int> <!-- THREE-PER-EM SPACE --> + <int>0x2005</int> <!-- FOUR-PER-EM SPACE --> + <int>0x2006</int> <!-- SIX-PER-EM SPACE --> + <int>0x2007</int> <!-- FIGURE SPACE --> + <int>0x2008</int> <!-- PUNCTUATION SPACE --> + <int>0x2009</int> <!-- THIN SPACE --> + <int>0x200A</int> <!-- HAIR SPACE --> + <int>0x200B</int> <!-- ZERO WIDTH SPACE --> + <int>0x200C</int> <!-- ZERO WIDTH NON-JOINER --> + <int>0x200D</int> <!-- ZERO WIDTH JOINER --> + <int>0x200E</int> <!-- LEFT-TO-RIGHT MARK --> + <int>0x200F</int> <!-- RIGHT-TO-LEFT MARK --> + <int>0x2028</int> <!-- LINE SEPARATOR --> + <int>0x2029</int> <!-- PARAGRAPH SEPARATOR --> + <int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING --> + <int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING --> + <int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING --> + <int>0x202D</int> <!-- LEFT-TO-RIGHT OVERRIDE --> + <int>0x202E</int> <!-- RIGHT-TO-LEFT OVERRIDE --> + <int>0x202F</int> <!-- NARROW NO-BREAK SPACE --> + <int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE --> + <int>0x2060</int> <!-- WORD JOINER --> + <int>0x2061</int> <!-- FUNCTION APPLICATION --> + <int>0x2062</int> <!-- INVISIBLE TIMES --> + <int>0x2063</int> <!-- INVISIBLE SEPARATOR --> + <int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING --> + <int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING --> + <int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING --> + <int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING --> + <int>0x206E</int> <!-- NATIONAL DIGIT SHAPES --> + <int>0x206F</int> <!-- NOMINAL DIGIT SHAPES --> + <int>0x3000</int> <!-- IDEOGRAPHIC SPACE --> + <int>0x3164</int> <!-- HANGUL FILLER --> + <int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE --> + <int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER --> + <int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR --> + <int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR --> + <int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR --> + </blank> +<!-- + Rescan configuration every 30 seconds when FcFontSetList is called + --> + <rescan> + <int>30</int> + </rescan> + </config> + +<!-- + URW provides metric and shape compatible fonts for these 10 Adobe families. + + However, these fonts are quite ugly and do not render well on-screen, + so we avoid matching them if the application said `anymetrics'; in that + case, a more generic font with different metrics but better appearance + will be used. + --> + <match target="pattern"> + <test name="family"> + <string>Avant Garde</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>URW Gothic L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Bookman</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>URW Bookman L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Courier</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>Nimbus Mono L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Helvetica</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>Nimbus Sans L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>New Century Schoolbook</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>Century Schoolbook L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Palatino</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>URW Palladio L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Times</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>Nimbus Roman No9 L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Zapf Chancery</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>URW Chancery L</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Zapf Dingbats</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append"> + <string>Dingbats</string> + </edit> + </match> + <match target="pattern"> + <test name="family"> + <string>Symbol</string> + </test> + <test name="anymetrics" qual="all" compare="not_eq"> + <bool>true</bool> + </test> + <edit name="family" mode="append" binding="same"> + <string>Standard Symbols L</string> + </edit> + </match> + +<!-- + Serif faces + --> + <alias> + <family>Nimbus Roman No9 L</family> + <default><family>serif</family></default> + </alias> +<!-- + Sans-serif faces + --> + <alias> + <family>Nimbus Sans L</family> + <default><family>sans-serif</family></default> + </alias> +<!-- + Monospace faces + --> + <alias> + <family>Nimbus Mono L</family> + <default><family>monospace</family></default> + </alias> + + +</fontconfig> diff --git a/WebKitTools/DumpRenderTree/qt/fonts/AHEM____.TTF b/WebKitTools/DumpRenderTree/qt/fonts/AHEM____.TTF Binary files differnew file mode 100644 index 0000000..ac81cb0 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/fonts/AHEM____.TTF diff --git a/WebKitTools/DumpRenderTree/qt/jsobjects.cpp b/WebKitTools/DumpRenderTree/qt/jsobjects.cpp new file mode 100644 index 0000000..78a93fe --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/jsobjects.cpp @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2006 Trolltech ASA + * + * 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. + */ +#include <jsobjects.h> +#include <qwebpage.h> +#include <qwebhistory.h> +#include <qwebframe.h> +#include <qevent.h> +#include <qapplication.h> +#include <qevent.h> + +#include "DumpRenderTree.h" +extern void qt_dump_editing_callbacks(bool b); + +LayoutTestController::LayoutTestController(WebCore::DumpRenderTree *drt) + : QObject() + , m_drt(drt) +{ + m_timeoutTimer = 0; + reset(); +} + +void LayoutTestController::reset() +{ + m_isLoading = true; + m_textDump = false; + m_dumpChildrenAsText = false; + m_canOpenWindows = false; + m_waitForDone = false; + m_dumpTitleChanges = false; + if (m_timeoutTimer) { + killTimer(m_timeoutTimer); + m_timeoutTimer = 0; + } + m_topLoadingFrame = 0; + qt_dump_editing_callbacks(false); +} + +void LayoutTestController::maybeDump(bool ok) +{ + QWebFrame *frame = qobject_cast<QWebFrame*>(sender()); + if (frame != m_topLoadingFrame) + return; + + m_topLoadingFrame = 0; + + if (!shouldWaitUntilDone()) { + emit done(); + m_isLoading = false; + } +} + +void LayoutTestController::waitUntilDone() +{ + //qDebug() << ">>>>waitForDone"; + m_waitForDone = true; + m_timeoutTimer = startTimer(11000); +} + +void LayoutTestController::notifyDone() +{ + //qDebug() << ">>>>notifyDone"; + if (!m_timeoutTimer) + return; + killTimer(m_timeoutTimer); + m_timeoutTimer = 0; + emit done(); + m_isLoading = false; +} + +int LayoutTestController::windowCount() +{ + return m_drt->windowCount(); +} + +void LayoutTestController::clearBackForwardList() +{ + m_drt->webPage()->history()->clear(); +} + + +void LayoutTestController::dumpEditingCallbacks() +{ + qDebug() << ">>>dumpEditingCallbacks"; + qt_dump_editing_callbacks(true); +} + +void LayoutTestController::queueReload() +{ + //qDebug() << ">>>queueReload"; +} + +void LayoutTestController::provisionalLoad() +{ + QWebFrame *frame = qobject_cast<QWebFrame*>(sender()); + if (!m_topLoadingFrame && m_isLoading) + m_topLoadingFrame = frame; +} + +void LayoutTestController::timerEvent(QTimerEvent *) +{ + qDebug() << ">>>>>>>>>>>>> timeout"; + notifyDone(); +} + +QString LayoutTestController::encodeHostName(const QString &host) +{ + QString encoded = QString::fromLatin1(QUrl::toAce(host + QLatin1String(".no"))); + encoded.truncate(encoded.length() - 3); // strip .no + return encoded; +} + +QString LayoutTestController::decodeHostName(const QString &host) +{ + QString decoded = QUrl::fromAce(host.toLatin1() + QByteArray(".no")); + decoded.truncate(decoded.length() - 3); + return decoded; +} + + +EventSender::EventSender(QWebPage *parent) + : QObject(parent) +{ + m_page = parent; +} + +void EventSender::mouseDown() +{ +// qDebug() << "EventSender::mouseDown" << frame; + QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QApplication::sendEvent(m_page, &event); +} + +void EventSender::mouseUp() +{ +// qDebug() << "EventSender::mouseUp" << frame; + QMouseEvent event(QEvent::MouseButtonRelease, m_mousePos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QApplication::sendEvent(m_page, &event); +} + +void EventSender::mouseMoveTo(int x, int y) +{ +// qDebug() << "EventSender::mouseMoveTo" << x << y; + m_mousePos = QPoint(x, y); + QMouseEvent event(QEvent::MouseMove, m_mousePos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); + QApplication::sendEvent(m_page, &event); +} + +void EventSender::leapForward(int ms) +{ + m_timeLeap += ms; + qDebug() << "EventSender::leapForward" << ms; +} + +void EventSender::keyDown(const QString &string, const QStringList &modifiers) +{ + QString s = string; + Qt::KeyboardModifiers modifs = 0; + for (int i = 0; i < modifiers.size(); ++i) { + const QString &m = modifiers.at(i); + if (m == "ctrlKey") + modifs |= Qt::ControlModifier; + else if (m == "shiftKey") + modifs |= Qt::ShiftModifier; + else if (m == "altKey") + modifs |= Qt::AltModifier; + else if (m == "metaKey") + modifs |= Qt::MetaModifier; + } + int code = 0; + if (string.length() == 1) { + code = string.unicode()->unicode(); + qDebug() << ">>>>>>>>> keyDown" << code << (char)code; + // map special keycodes used by the tests to something that works for Qt/X11 + if (code == '\t') { + code = Qt::Key_Tab; + if (modifs == Qt::ShiftModifier) + code = Qt::Key_Backtab; + s = QString(); + } else if (code == 127) { + code = Qt::Key_Backspace; + if (modifs == Qt::AltModifier) + modifs = Qt::ControlModifier; + s = QString(); + } else if (code == 'o' && modifs == Qt::ControlModifier) { + s = QLatin1String("\n"); + code = '\n'; + modifs = 0; + } else if (code == 'y' && modifs == Qt::ControlModifier) { + s = QLatin1String("c"); + code = 'c'; + } else if (code == 'k' && modifs == Qt::ControlModifier) { + s = QLatin1String("x"); + code = 'x'; + } else if (code == 'a' && modifs == Qt::ControlModifier) { + s = QString(); + code = Qt::Key_Home; + modifs = 0; + } else if (code == 0xf702) { + s = QString(); + code = Qt::Key_Left; + if (modifs & Qt::MetaModifier) { + code = Qt::Key_Home; + modifs &= ~Qt::MetaModifier; + } + } else if (code == 0xf703) { + s = QString(); + code = Qt::Key_Right; + if (modifs & Qt::MetaModifier) { + code = Qt::Key_End; + modifs &= ~Qt::MetaModifier; + } + } else if (code == 'a' && modifs == Qt::ControlModifier) { + s = QString(); + code = Qt::Key_Home; + modifs = 0; + } else { + code = string.unicode()->toUpper().unicode(); + } + } + QKeyEvent event(QEvent::KeyPress, code, modifs, s); + QApplication::sendEvent(m_page, &event); +} + +QWebFrame *EventSender::frameUnderMouse() const +{ + QWebFrame *frame = m_page->mainFrame(); + +redo: + QList<QWebFrame*> children = frame->childFrames(); + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->geometry().contains(m_mousePos)) { + frame = children.at(i); + goto redo; + } + } + if (frame->geometry().contains(m_mousePos)) + return frame; + return 0; +} + + +TextInputController::TextInputController(QWebPage *parent) + : QObject(parent) +{ +} + +void TextInputController::doCommand(const QString &command) +{ + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + int keycode = 0; + if (command == "moveBackwardAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + keycode = Qt::Key_Left; + } else if(command =="moveDown:") { + keycode = Qt::Key_Down; + } else if(command =="moveDownAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + keycode = Qt::Key_Down; + } else if(command =="moveForward:") { + keycode = Qt::Key_Right; + } else if(command =="moveForwardAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + keycode = Qt::Key_Right; + } else if(command =="moveLeft:") { + keycode = Qt::Key_Left; + } else if(command =="moveLeftAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + keycode = Qt::Key_Left; + } else if(command =="moveRight:") { + keycode = Qt::Key_Right; + } else if(command =="moveRightAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + keycode = Qt::Key_Right; + } else if(command =="moveToBeginningOfDocument:") { + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Home; + } else if(command =="moveToBeginningOfLine:") { + keycode = Qt::Key_Home; +// } else if(command =="moveToBeginningOfParagraph:") { + } else if(command =="moveToEndOfDocument:") { + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_End; + } else if(command =="moveToEndOfLine:") { + keycode = Qt::Key_End; +// } else if(command =="moveToEndOfParagraph:") { + } else if(command =="moveUp:") { + keycode = Qt::Key_Up; + } else if(command =="moveUpAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + keycode = Qt::Key_Up; + } else if(command =="moveWordBackward:") { + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Up; + } else if(command =="moveWordBackwardAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Left; + } else if(command =="moveWordForward:") { + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Right; + } else if(command =="moveWordForwardAndModifySelection:") { + modifiers |= Qt::ControlModifier; + modifiers |= Qt::ShiftModifier; + keycode = Qt::Key_Right; + } else if(command =="moveWordLeft:") { + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Left; + } else if(command =="moveWordRight:") { + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Left; + } else if(command =="moveWordRightAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Right; + } else if(command =="moveWordLeftAndModifySelection:") { + modifiers |= Qt::ShiftModifier; + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Left; + } else if(command =="pageDown:") { + keycode = Qt::Key_PageDown; + } else if(command =="pageUp:") { + keycode = Qt::Key_PageUp; + } else if(command == "deleteWordBackward:") { + modifiers |= Qt::ControlModifier; + keycode = Qt::Key_Backspace; + } else if(command == "deleteBackward:") { + keycode = Qt::Key_Backspace; + } else if(command == "deleteForward:") { + keycode = Qt::Key_Delete; + } + QKeyEvent event(QEvent::KeyPress, keycode, modifiers); + QApplication::sendEvent(parent(), &event); + QKeyEvent event2(QEvent::KeyRelease, keycode, modifiers); + QApplication::sendEvent(parent(), &event2); +} diff --git a/WebKitTools/DumpRenderTree/qt/jsobjects.h b/WebKitTools/DumpRenderTree/qt/jsobjects.h new file mode 100644 index 0000000..511e857 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/jsobjects.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2006 Trolltech ASA + * + * 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. + */ +#ifndef JSOBJECTS_H +#define JSOBJECTS_H + +#include <qobject.h> +#include <qdebug.h> +#include <qpoint.h> +#include <qstringlist.h> + +class QWebFrame; +namespace WebCore { + class DumpRenderTree; +} +class LayoutTestController : public QObject +{ + Q_OBJECT +public: + LayoutTestController(WebCore::DumpRenderTree *drt); + + bool isLoading() const { return m_isLoading; } + void setLoading(bool loading) { m_isLoading = loading; } + + bool shouldDumpAsText() const { return m_textDump; } + bool shouldDumpChildrenAsText() const { return m_dumpChildrenAsText; } + bool shouldWaitUntilDone() const { return m_waitForDone; } + bool canOpenWindows() const { return m_canOpenWindows; } + bool shouldDumpTitleChanges() const { return m_dumpTitleChanges; } + + void reset(); + +protected: + void timerEvent(QTimerEvent *); + +signals: + void done(); + +public slots: + void maybeDump(bool ok); + void dumpAsText() { m_textDump = true; } + void dumpChildFramesAsText() { m_dumpChildrenAsText = true; } + void setCanOpenWindows() { m_canOpenWindows = true; } + void waitUntilDone(); + void notifyDone(); + void dumpEditingCallbacks(); + void queueReload(); + void provisionalLoad(); + void setCloseRemainingWindowsWhenComplete(bool=false) {} + int windowCount(); + void display() {} + void clearBackForwardList(); + void dumpTitleChanges() { m_dumpTitleChanges = true; } + QString encodeHostName(const QString &host); + QString decodeHostName(const QString &host); + void dumpSelectionRect() const {} + +private: + bool m_isLoading; + bool m_textDump; + bool m_dumpChildrenAsText; + bool m_canOpenWindows; + bool m_waitForDone; + bool m_dumpTitleChanges; + int m_timeoutTimer; + QWebFrame *m_topLoadingFrame; + WebCore::DumpRenderTree *m_drt; +}; + +class QWebPage; +class QWebFrame; + +class EventSender : public QObject +{ + Q_OBJECT +public: + EventSender(QWebPage *parent); + +public slots: + void mouseDown(); + void mouseUp(); + void mouseMoveTo(int x, int y); + void leapForward(int ms); + void keyDown(const QString &string, const QStringList &modifiers=QStringList()); + void clearKillRing() {} + +private: + QPoint m_mousePos; + QWebPage *m_page; + int m_timeLeap; + QWebFrame *frameUnderMouse() const; +}; + +class TextInputController : public QObject +{ + Q_OBJECT +public: + TextInputController(QWebPage *parent); + +public slots: + void doCommand(const QString &command); +// void setMarkedText(const QString &str, int from, int length); +// bool hasMarkedText(); +// void unmarkText(); +// QList<int> markedRange(); +// QList<int> selectedRange(); +// void validAttributesForMarkedText(); +// void inserText(const QString &); +// void firstRectForCharacterRange(); +// void characterIndexForPoint(int, int); +// void substringFromRange(int, int); +// void conversationIdentifier(); +}; + +#endif diff --git a/WebKitTools/DumpRenderTree/qt/main.cpp b/WebKitTools/DumpRenderTree/qt/main.cpp new file mode 100644 index 0000000..dd4c0e9 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/main.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2007 Trolltech ASA + * + * 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. + */ + +#include "DumpRenderTree.h" +#include "testplugin.h" + +#include <qstringlist.h> +#include <qapplication.h> +#include <qurl.h> +#include <qdir.h> +#include <qdebug.h> +#include <qfont.h> + +#ifdef Q_WS_X11 +#include <qx11info_x11.h> +#include <fontconfig/fontconfig.h> +#endif + +#include <limits.h> +#include <signal.h> + +#if defined(__GLIBC__) +#include <execinfo.h> +#endif + +#if QT_VERSION < 0x040400 +Q_IMPORT_PLUGIN(testplugin) +#endif + +void messageHandler(QtMsgType type, const char *message) +{ + if (type == QtCriticalMsg) { + fprintf(stderr, "%s\n", message); + return; + } + // do nothing +} + +QString get_backtrace() { + QString s; + +#if defined(__GLIBC__) + void* array[256]; + size_t size; /* number of stack frames */ + + size = backtrace(array, 256); + + if (!size) + return s; + + char** strings = backtrace_symbols(array, size); + for (int i = 0; i < size; ++i) { + s += QString::number(i) + + QLatin1String(": ") + + QLatin1String(strings[i]) + QLatin1String("\n"); + } + + if (strings) + free (strings); +#endif + + return s; +} + +static void crashHandler(int sig) +{ + fprintf(stderr, "%s\n", strsignal(sig)); + fprintf(stderr, "%s\n", get_backtrace().toLatin1().constData()); + exit(128 + sig); +} + +int main(int argc, char* argv[]) +{ +#ifdef Q_WS_X11 + FcInit(); + FcConfig *config = FcConfigCreate(); + QByteArray fontDir = getenv("WEBKIT_TESTFONTS"); + if (fontDir.isEmpty() || !QDir(fontDir).exists()) { + fprintf(stderr, + "\n\n" + "--------------------------------------------------------------------\n" + "WEBKIT_TESTFONTS environment variable is not set correctly.\n" + "This variable has to point to the directory containing the fonts\n" + "you can checkout from svn://labs.trolltech.com/svn/webkit/testfonts\n" + "--------------------------------------------------------------------\n" +); + exit(1); + } + char currentPath[PATH_MAX+1]; + getcwd(currentPath, PATH_MAX); + QByteArray configFile = currentPath; + configFile += "/WebKitTools/DumpRenderTree/qt/fonts.conf"; + if (!FcConfigParseAndLoad (config, (FcChar8*) configFile.data(), true)) + qFatal("Couldn't load font configuration file"); + if (!FcConfigAppFontAddDir (config, (FcChar8*) fontDir.data())) + qFatal("Couldn't add font dir!"); + FcConfigSetCurrent(config); +#endif + QApplication app(argc, argv); +#ifdef Q_WS_X11 + QX11Info::setAppDpiY(0, 96); + QX11Info::setAppDpiX(0, 96); +#endif + + QFont f("Sans Serif"); + f.setPointSize(9); + f.setWeight(QFont::Normal); + f.setStyle(QFont::StyleNormal); + app.setFont(f); + app.setStyle(QLatin1String("Plastique")); + + + signal(SIGILL, crashHandler); /* 4: illegal instruction (not reset when caught) */ + signal(SIGTRAP, crashHandler); /* 5: trace trap (not reset when caught) */ + signal(SIGFPE, crashHandler); /* 8: floating point exception */ + signal(SIGBUS, crashHandler); /* 10: bus error */ + signal(SIGSEGV, crashHandler); /* 11: segmentation violation */ + signal(SIGSYS, crashHandler); /* 12: bad argument to system call */ + signal(SIGPIPE, crashHandler); /* 13: write on a pipe with no reader */ + signal(SIGXCPU, crashHandler); /* 24: exceeded CPU time limit */ + signal(SIGXFSZ, crashHandler); /* 25: exceeded file size limit */ + + QStringList args = app.arguments(); + if (args.count() < 2) { + qDebug() << "Usage: DumpRenderTree [-v] filename"; + exit(0); + } + + // supress debug output from Qt if not started with -v + if (!args.contains(QLatin1String("-v"))) + qInstallMsgHandler(messageHandler); + + WebCore::DumpRenderTree dumper; + + if (args.last() == QLatin1String("-")) { + dumper.open(); + } else { + if (!args.last().startsWith("/") + && !args.last().startsWith("file:")) { + QString path = QDir::currentPath(); + if (!path.endsWith('/')) + path.append('/'); + args.last().prepend(path); + } + dumper.open(QUrl(args.last())); + } + return app.exec(); +#ifdef Q_WS_X11 + FcConfigSetCurrent(0); +#endif +} diff --git a/WebKitTools/DumpRenderTree/qt/testplugin.cpp b/WebKitTools/DumpRenderTree/qt/testplugin.cpp new file mode 100644 index 0000000..27558c9 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/testplugin.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2007 Trolltech ASA + * + * 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. + */ +#include "testplugin.h" + +#if QT_VERSION < 0x040400 + +TestPlugin::TestPlugin(QObject *parent) + : QWebObjectPlugin(parent) +{ +} + +TestPlugin::~TestPlugin() +{ +} + +QStringList TestPlugin::keys() const +{ + return QStringList(QLatin1String("testplugin")); +} + +QString TestPlugin::descriptionForKey(const QString &) const +{ + return QLatin1String("testdescription"); +} + +QStringList TestPlugin::mimetypesForKey(const QString &) const +{ + return QStringList(QLatin1String("testtype")); +} + +QStringList TestPlugin::extensionsForMimetype(const QString &) const +{ + return QStringList(QLatin1String("testsuffixes")); +} + +QObject *TestPlugin::create(QWebObjectPluginConnector *, + const QUrl &, + const QString &, + const QStringList &, + const QStringList &) const +{ + return 0; +} + +Q_EXPORT_PLUGIN2(testplugin, TestPlugin) +#endif diff --git a/WebKitTools/DumpRenderTree/qt/testplugin.h b/WebKitTools/DumpRenderTree/qt/testplugin.h new file mode 100644 index 0000000..e305069 --- /dev/null +++ b/WebKitTools/DumpRenderTree/qt/testplugin.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007 Trolltech ASA + * + * 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. + */ +#include <qglobal.h> +#if QT_VERSION < 0x040400 +#define QT_STATICPLUGIN +#include <qwebobjectplugin.h> + + +class TestPlugin : public QWebObjectPlugin +{ +public: + explicit TestPlugin(QObject *parent = 0); + virtual ~TestPlugin(); + + virtual QStringList keys() const; + + virtual QString descriptionForKey(const QString &key) const; + virtual QStringList mimetypesForKey(const QString &key) const; + virtual QStringList extensionsForMimetype(const QString &mimeType) const; + virtual QObject *create(QWebObjectPluginConnector *connector, + const QUrl &url, + const QString &mimeType, + const QStringList &argumentNames, + const QStringList &argumentValues) const; +}; + +#endif diff --git a/WebKitTools/DumpRenderTree/win/DraggingInfo.h b/WebKitTools/DumpRenderTree/win/DraggingInfo.h new file mode 100644 index 0000000..2ead457 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/DraggingInfo.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef DraggingInfo_h +#define DraggingInfo_h + +#include <objidl.h> + +class DraggingInfo { +public: + DraggingInfo(IDataObject* object, IDropSource* source) + : m_object(object) + , m_source(source) + { + m_object->AddRef(); + m_source->AddRef(); + } + + ~DraggingInfo() + { + if (m_object) + m_object->Release(); + m_object = 0; + if (m_source) + m_source->Release(); + m_source = 0; + } + + IDataObject* dataObject() const { return m_object; } + IDropSource* dropSource() const { return m_source; } + +private: + IDataObject* m_object; + IDropSource* m_source; +}; + +#endif // !defined(DraggingInfo_h) diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp new file mode 100644 index 0000000..bf08ff2 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp @@ -0,0 +1,1103 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" + +#include "EditingDelegate.h" +#include "FrameLoadDelegate.h" +#include "LayoutTestController.h" +#include "PixelDumpSupport.h" +#include "PolicyDelegate.h" +#include "ResourceLoadDelegate.h" +#include "UIDelegate.h" +#include "WorkQueueItem.h" +#include "WorkQueue.h" +#include <wtf/RetainPtr.h> +#include <wtf/Vector.h> +#include <WebCore/COMPtr.h> +#include <CoreFoundation/CoreFoundation.h> +#include <CFNetwork/CFURLCachePriv.h> +#include <JavaScriptCore/JavaScriptCore.h> +#include <math.h> +#include <pthread.h> +#include <string> +#include <tchar.h> +#include <WebKit/WebKit.h> +#include <fcntl.h> +#include <io.h> +#include <windows.h> +#include <stdio.h> +#include <shlwapi.h> + +using std::wstring; + +#ifndef NDEBUG +const LPWSTR TestPluginDir = L"TestNetscapePlugin_Debug"; +#else +const LPWSTR TestPluginDir = L"TestNetscapePlugin"; +#endif + +static LPCWSTR fontsEnvironmentVariable = L"WEBKIT_TESTFONTS"; +#define USE_MAC_FONTS + +const LPCWSTR kDumpRenderTreeClassName = L"DumpRenderTreeWindow"; + +static bool dumpTree = true; +static bool dumpPixels; +static bool dumpAllPixels; +static bool printSeparators; +static bool leakChecking = false; +static bool timedOut = false; +static bool threaded = false; +static RetainPtr<CFStringRef> persistentUserStyleSheetLocation; + +static const char* currentTest; + +volatile bool done; +// This is the topmost frame that is loading, during a given load, or nil when no load is +// in progress. Usually this is the same as the main frame, but not always. In the case +// where a frameset is loaded, and then new content is loaded into one of the child frames, +// that child frame is the "topmost frame that is loading". +IWebFrame* topLoadingFrame; // !nil iff a load is in progress +static COMPtr<IWebHistoryItem> prevTestBFItem; // current b/f item at the end of the previous test +IWebPolicyDelegate* policyDelegate; +COMPtr<FrameLoadDelegate> sharedFrameLoadDelegate; +COMPtr<UIDelegate> sharedUIDelegate; +COMPtr<EditingDelegate> sharedEditingDelegate; +COMPtr<ResourceLoadDelegate> sharedResourceLoadDelegate; + +IWebFrame* frame; +HWND webViewWindow; + +LayoutTestController* layoutTestController = 0; +CFRunLoopTimerRef waitToDumpWatchdog = 0; + +static const unsigned timeoutValue = 60000; +static const unsigned timeoutId = 10; + +const unsigned maxViewWidth = 800; +const unsigned maxViewHeight = 600; + +void setPersistentUserStyleSheetLocation(CFStringRef url) +{ + persistentUserStyleSheetLocation = url; +} + +wstring urlSuitableForTestResult(const wstring& url) +{ + if (!url.c_str() || url.find(L"file://") == wstring::npos) + return url; + + return PathFindFileNameW(url.c_str()); +} + +static LRESULT CALLBACK DumpRenderTreeWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_TIMER: + // The test ran long enough to time out + timedOut = true; + PostQuitMessage(0); + return 0; + break; + case WM_DESTROY: + for (unsigned i = openWindows().size() - 1; i >= 0; --i) { + if (openWindows()[i] == hWnd) { + openWindows().remove(i); + windowToWebViewMap().remove(hWnd); + break; + } + } + return 0; + break; + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } +} + +static const wstring& exePath() +{ + static wstring path; + static bool initialized; + + if (initialized) + return path; + initialized = true; + + TCHAR buffer[MAX_PATH]; + GetModuleFileName(GetModuleHandle(0), buffer, ARRAYSIZE(buffer)); + path = buffer; + int lastSlash = path.rfind('\\'); + if (lastSlash != -1 && lastSlash + 1 < path.length()) + path = path.substr(0, lastSlash + 1); + + return path; +} + +static const wstring& fontsPath() +{ + static wstring path; + static bool initialized; + + if (initialized) + return path; + initialized = true; + + DWORD size = GetEnvironmentVariable(fontsEnvironmentVariable, 0, 0); + Vector<TCHAR> buffer(size); + if (GetEnvironmentVariable(fontsEnvironmentVariable, buffer.data(), buffer.size())) { + path = buffer.data(); + if (path[path.length() - 1] != '\\') + path.append(L"\\"); + return path; + } + + path = exePath() + TEXT("DumpRenderTree.resources\\"); + return path; +} + +#ifdef DEBUG_WEBKIT_HAS_SUFFIX +#define WEBKITDLL TEXT("WebKit_debug.dll") +#else +#define WEBKITDLL TEXT("WebKit.dll") +#endif + +static void initialize() +{ + if (HMODULE webKitModule = LoadLibrary(WEBKITDLL)) + if (FARPROC dllRegisterServer = GetProcAddress(webKitModule, "DllRegisterServer")) + dllRegisterServer(); + + // Init COM + OleInitialize(0); + + static LPCTSTR fontsToInstall[] = { + TEXT("AHEM____.ttf"), + TEXT("Apple Chancery.ttf"), + TEXT("Courier Bold.ttf"), + TEXT("Courier.ttf"), + TEXT("Helvetica Bold Oblique.ttf"), + TEXT("Helvetica Bold.ttf"), + TEXT("Helvetica Oblique.ttf"), + TEXT("Helvetica.ttf"), + TEXT("Helvetica Neue Bold Italic.ttf"), + TEXT("Helvetica Neue Bold.ttf"), + TEXT("Helvetica Neue Condensed Black.ttf"), + TEXT("Helvetica Neue Condensed Bold.ttf"), + TEXT("Helvetica Neue Italic.ttf"), + TEXT("Helvetica Neue Light Italic.ttf"), + TEXT("Helvetica Neue Light.ttf"), + TEXT("Helvetica Neue UltraLight Italic.ttf"), + TEXT("Helvetica Neue UltraLight.ttf"), + TEXT("Helvetica Neue.ttf"), + TEXT("Lucida Grande.ttf"), + TEXT("Lucida Grande Bold.ttf"), + TEXT("Monaco.ttf"), + TEXT("Papyrus.ttf"), + TEXT("Times Bold Italic.ttf"), + TEXT("Times Bold.ttf"), + TEXT("Times Italic.ttf"), + TEXT("Times Roman.ttf"), + TEXT("WebKit Layout Tests.ttf") + }; + + wstring resourcesPath = fontsPath(); + + COMPtr<IWebTextRenderer> textRenderer; + if (SUCCEEDED(CoCreateInstance(CLSID_WebTextRenderer, 0, CLSCTX_ALL, IID_IWebTextRenderer, (void**)&textRenderer))) + for (int i = 0; i < ARRAYSIZE(fontsToInstall); ++i) + textRenderer->registerPrivateFont(wstring(resourcesPath + fontsToInstall[i]).c_str()); + + // Register a host window + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = DumpRenderTreeWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(0); + wcex.hIcon = 0; + wcex.hCursor = LoadCursor(0, IDC_ARROW); + wcex.hbrBackground = 0; + wcex.lpszMenuName = 0; + wcex.lpszClassName = kDumpRenderTreeClassName; + wcex.hIconSm = 0; + + RegisterClassEx(&wcex); +} + +void displayWebView() +{ + ::InvalidateRect(webViewWindow, 0, TRUE); + ::UpdateWindow(webViewWindow); +} + +void dumpFrameScrollPosition(IWebFrame* frame) +{ + if (!frame) + return; + + COMPtr<IWebFramePrivate> framePrivate; + if (FAILED(frame->QueryInterface(&framePrivate))) + return; + + SIZE scrollPosition; + if (FAILED(framePrivate->scrollOffset(&scrollPosition))) + return; + + if (abs(scrollPosition.cx) > 0.00000001 || abs(scrollPosition.cy) > 0.00000001) { + COMPtr<IWebFrame> parent; + if (FAILED(frame->parentFrame(&parent))) + return; + if (parent) { + BSTR name; + if (FAILED(frame->name(&name))) + return; + printf("frame '%S' ", name ? name : L""); + SysFreeString(name); + } + printf("scrolled to %.f,%.f\n", (double)scrollPosition.cx, (double)scrollPosition.cy); + } + + if (::layoutTestController->dumpChildFrameScrollPositions()) { + COMPtr<IEnumVARIANT> enumKids; + if (FAILED(frame->childFrames(&enumKids))) + return; + VARIANT var; + VariantInit(&var); + while (enumKids->Next(1, &var, 0) == S_OK) { + ASSERT(V_VT(&var) == VT_UNKNOWN); + COMPtr<IWebFrame> framePtr; + V_UNKNOWN(&var)->QueryInterface(IID_IWebFrame, (void**)&framePtr); + dumpFrameScrollPosition(framePtr.get()); + VariantClear(&var); + } + } +} + +static wstring dumpFramesAsText(IWebFrame* frame) +{ + if (!frame) + return L""; + + COMPtr<IDOMDocument> document; + if (FAILED(frame->DOMDocument(&document))) + return L""; + + COMPtr<IDOMElement> documentElement; + if (FAILED(document->documentElement(&documentElement))) + return L""; + + wstring result; + + // Add header for all but the main frame. + COMPtr<IWebFrame> parent; + if (FAILED(frame->parentFrame(&parent))) + return L""; + if (parent) { + BSTR name = L""; + if (FAILED(frame->name(&name))) + return L""; + + result.append(L"\n--------\nFrame: '"); + result.append(name ? name : L"", SysStringLen(name)); + result.append(L"'\n--------\n"); + + SysFreeString(name); + } + + BSTR innerText = 0; + COMPtr<IDOMElementPrivate> docPrivate; + if (SUCCEEDED(documentElement->QueryInterface(&docPrivate))) + docPrivate->innerText(&innerText); + + result.append(innerText ? innerText : L"", SysStringLen(innerText)); + result.append(L"\n"); + + SysFreeString(innerText); + + if (::layoutTestController->dumpChildFramesAsText()) { + COMPtr<IEnumVARIANT> enumKids; + if (FAILED(frame->childFrames(&enumKids))) + return L""; + VARIANT var; + VariantInit(&var); + while (enumKids->Next(1, &var, 0) == S_OK) { + ASSERT(V_VT(&var) == VT_UNKNOWN); + COMPtr<IWebFrame> framePtr; + V_UNKNOWN(&var)->QueryInterface(IID_IWebFrame, (void**)&framePtr); + result.append(dumpFramesAsText(framePtr.get())); + VariantClear(&var); + } + } + + return result; +} + +static int compareHistoryItems(const void* item1, const void* item2) +{ + COMPtr<IWebHistoryItemPrivate> itemA; + if (FAILED((*(COMPtr<IUnknown>*)item1)->QueryInterface(&itemA))) + return 0; + + COMPtr<IWebHistoryItemPrivate> itemB; + if (FAILED((*(COMPtr<IUnknown>*)item2)->QueryInterface(&itemB))) + return 0; + + BSTR targetA; + if (FAILED(itemA->target(&targetA))) + return 0; + + BSTR targetB; + if (FAILED(itemB->target(&targetB))) { + SysFreeString(targetA); + return 0; + } + + int result = wcsicmp(wstring(targetA, SysStringLen(targetA)).c_str(), wstring(targetB, SysStringLen(targetB)).c_str()); + SysFreeString(targetA); + SysFreeString(targetB); + return result; +} + +static void dumpHistoryItem(IWebHistoryItem* item, int indent, bool current) +{ + assert(item); + + int start = 0; + if (current) { + printf("curr->"); + start = 6; + } + for (int i = start; i < indent; i++) + putchar(' '); + + BSTR url; + if (FAILED(item->URLString(&url))) + return; + printf("%S", url ? url : L""); + SysFreeString(url); + + COMPtr<IWebHistoryItemPrivate> itemPrivate; + if (FAILED(item->QueryInterface(&itemPrivate))) + return; + + BSTR target; + if (FAILED(itemPrivate->target(&target))) + return; + if (SysStringLen(target)) + printf(" (in frame \"%S\")", target); + SysFreeString(target); + BOOL isTargetItem = FALSE; + if (FAILED(itemPrivate->isTargetItem(&isTargetItem))) + return; + if (isTargetItem) + printf(" **nav target**"); + putchar('\n'); + + unsigned kidsCount; + SAFEARRAY* arrPtr; + if (FAILED(itemPrivate->children(&kidsCount, &arrPtr)) || !kidsCount) + return; + + Vector<COMPtr<IUnknown> > kidsVector; + + LONG lowerBound; + if (FAILED(::SafeArrayGetLBound(arrPtr, 1, &lowerBound))) + goto exit; + + LONG upperBound; + if (FAILED(::SafeArrayGetUBound(arrPtr, 1, &upperBound))) + goto exit; + + LONG length = upperBound - lowerBound + 1; + if (!length) + goto exit; + ASSERT(length == kidsCount); + + IUnknown** safeArrayData; + if (FAILED(::SafeArrayAccessData(arrPtr, (void**)&safeArrayData))) + goto exit; + + for (int i = 0; i < length; ++i) + kidsVector.append(safeArrayData[i]); + ::SafeArrayUnaccessData(arrPtr); + + // must sort to eliminate arbitrary result ordering which defeats reproducible testing + qsort(kidsVector.data(), kidsCount, sizeof(kidsVector[0]), compareHistoryItems); + + for (unsigned i = 0; i < kidsCount; ++i) { + COMPtr<IWebHistoryItem> item; + kidsVector[i]->QueryInterface(&item); + dumpHistoryItem(item.get(), indent + 4, false); + } + +exit: + if (arrPtr && SUCCEEDED(::SafeArrayUnlock(arrPtr))) + ::SafeArrayDestroy(arrPtr); +} + +static void dumpBackForwardList(IWebView* webView) +{ + ASSERT(webView); + + printf("\n============== Back Forward List ==============\n"); + + COMPtr<IWebBackForwardList> bfList; + if (FAILED(webView->backForwardList(&bfList))) + return; + + // Print out all items in the list after prevTestBFItem, which was from the previous test + // Gather items from the end of the list, the print them out from oldest to newest + + Vector<COMPtr<IUnknown> > itemsToPrint; + + int forwardListCount; + if (FAILED(bfList->forwardListCount(&forwardListCount))) + return; + + for (int i = forwardListCount; i > 0; --i) { + COMPtr<IWebHistoryItem> item; + if (FAILED(bfList->itemAtIndex(i, &item))) + return; + // something is wrong if the item from the last test is in the forward part of the b/f list + assert(item != prevTestBFItem); + COMPtr<IUnknown> itemUnknown; + item->QueryInterface(&itemUnknown); + itemsToPrint.append(itemUnknown); + } + + COMPtr<IWebHistoryItem> currentItem; + if (FAILED(bfList->currentItem(¤tItem))) + return; + + assert(currentItem != prevTestBFItem); + COMPtr<IUnknown> currentItemUnknown; + currentItem->QueryInterface(¤tItemUnknown); + itemsToPrint.append(currentItemUnknown); + int currentItemIndex = itemsToPrint.size() - 1; + + int backListCount; + if (FAILED(bfList->backListCount(&backListCount))) + return; + + for (int i = -1; i >= -backListCount; --i) { + COMPtr<IWebHistoryItem> item; + if (FAILED(bfList->itemAtIndex(i, &item))) + return; + if (item == prevTestBFItem) + break; + COMPtr<IUnknown> itemUnknown; + item->QueryInterface(&itemUnknown); + itemsToPrint.append(itemUnknown); + } + + for (int i = itemsToPrint.size() - 1; i >= 0; --i) { + COMPtr<IWebHistoryItem> historyItemToPrint; + itemsToPrint[i]->QueryInterface(&historyItemToPrint); + dumpHistoryItem(historyItemToPrint.get(), 8, i == currentItemIndex); + } + + printf("===============================================\n"); +} + +static void dumpBackForwardListForAllWindows() +{ + unsigned count = openWindows().size(); + for (unsigned i = 0; i < count; i++) { + HWND window = openWindows()[i]; + IWebView* webView = windowToWebViewMap().get(window); + dumpBackForwardList(webView); + } +} + +void dump() +{ + COMPtr<IWebDataSource> dataSource; + if (SUCCEEDED(frame->dataSource(&dataSource))) { + COMPtr<IWebURLResponse> response; + if (SUCCEEDED(dataSource->response(&response)) && response) { + BSTR mimeType; + if (SUCCEEDED(response->MIMEType(&mimeType))) + ::layoutTestController->setDumpAsText(::layoutTestController->dumpAsText() | !_tcscmp(mimeType, TEXT("text/plain"))); + SysFreeString(mimeType); + } + } + + BSTR resultString = 0; + + if (dumpTree) { + if (::layoutTestController->dumpAsText()) { + ::InvalidateRect(webViewWindow, 0, TRUE); + ::SendMessage(webViewWindow, WM_PAINT, 0, 0); + wstring result = dumpFramesAsText(frame); + resultString = SysAllocStringLen(result.data(), result.size()); + } else { + bool isSVGW3CTest = strstr(currentTest, "svg\\W3C-SVG-1.1"); + unsigned width; + unsigned height; + if (isSVGW3CTest) { + width = 480; + height = 360; + } else { + width = maxViewWidth; + height = maxViewHeight; + } + + ::SetWindowPos(webViewWindow, 0, 0, 0, width, height, SWP_NOMOVE); + ::InvalidateRect(webViewWindow, 0, TRUE); + ::SendMessage(webViewWindow, WM_PAINT, 0, 0); + + COMPtr<IWebFramePrivate> framePrivate; + if (FAILED(frame->QueryInterface(&framePrivate))) + goto fail; + framePrivate->renderTreeAsExternalRepresentation(&resultString); + } + + if (!resultString) + printf("ERROR: nil result from %s", ::layoutTestController->dumpAsText() ? "IDOMElement::innerText" : "IFrameViewPrivate::renderTreeAsExternalRepresentation"); + else { + unsigned stringLength = SysStringLen(resultString); + int bufferSize = ::WideCharToMultiByte(CP_UTF8, 0, resultString, stringLength, 0, 0, 0, 0); + char* buffer = (char*)malloc(bufferSize + 1); + ::WideCharToMultiByte(CP_UTF8, 0, resultString, stringLength, buffer, bufferSize + 1, 0, 0); + fwrite(buffer, 1, bufferSize, stdout); + free(buffer); + if (!::layoutTestController->dumpAsText()) + dumpFrameScrollPosition(frame); + } + if (::layoutTestController->dumpBackForwardList()) + dumpBackForwardListForAllWindows(); + } + + if (printSeparators) + puts("#EOF"); + + if (dumpPixels) { + if (layoutTestController->dumpAsText() || layoutTestController->dumpDOMAsWebArchive() || layoutTestController->dumpSourceAsWebArchive()) + printf("#EOF\n"); + else + dumpWebViewAsPixelsAndCompareWithExpected(currentTest, dumpAllPixels); + } + +fail: + SysFreeString(resultString); + // This will exit from our message loop + PostQuitMessage(0); + done = true; +} + +static bool shouldLogFrameLoadDelegates(const char* pathOrURL) +{ + return strstr(pathOrURL, "loading/"); +} + +static void resetWebViewToConsistentStateBeforeTesting() +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + webView->setPolicyDelegate(0); + + COMPtr<IWebIBActions> webIBActions(Query, webView); + if (webIBActions) + webIBActions->makeTextStandardSize(0); + + COMPtr<IWebPreferences> preferences; + if (SUCCEEDED(webView->preferences(&preferences))) { + preferences->setPrivateBrowsingEnabled(FALSE); + preferences->setJavaScriptCanOpenWindowsAutomatically(TRUE); + + if (persistentUserStyleSheetLocation) { + Vector<wchar_t> urlCharacters(CFStringGetLength(persistentUserStyleSheetLocation.get())); + CFStringGetCharacters(persistentUserStyleSheetLocation.get(), CFRangeMake(0, CFStringGetLength(persistentUserStyleSheetLocation.get())), (UniChar *)urlCharacters.data()); + BSTR url = SysAllocStringLen(urlCharacters.data(), urlCharacters.size()); + preferences->setUserStyleSheetLocation(url); + SysFreeString(url); + preferences->setUserStyleSheetEnabled(TRUE); + } else + preferences->setUserStyleSheetEnabled(FALSE); + + COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences); + if (prefsPrivate) + prefsPrivate->setAuthorAndUserStylesEnabled(TRUE); + } + + COMPtr<IWebViewPrivate> webViewPrivate(Query, webView); + if (!webViewPrivate) + return; + + HWND viewWindow; + if (SUCCEEDED(webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))) && viewWindow) + SetFocus(viewWindow); +} + +static void runTest(const char* pathOrURL) +{ + static BSTR methodBStr = SysAllocString(TEXT("GET")); + + BSTR urlBStr; + + CFStringRef str = CFStringCreateWithCString(0, pathOrURL, kCFStringEncodingWindowsLatin1); + CFURLRef url = CFURLCreateWithString(0, str, 0); + + if (!url) + url = CFURLCreateWithFileSystemPath(0, str, kCFURLWindowsPathStyle, false); + + CFRelease(str); + + str = CFURLGetString(url); + + CFIndex length = CFStringGetLength(str); + UniChar* buffer = new UniChar[length]; + + CFStringGetCharacters(str, CFRangeMake(0, length), buffer); + urlBStr = SysAllocStringLen((OLECHAR*)buffer, length); + delete[] buffer; + + CFRelease(url); + + currentTest = pathOrURL; + + ::layoutTestController = new LayoutTestController(false, false); + done = false; + topLoadingFrame = 0; + timedOut = false; + + if (shouldLogFrameLoadDelegates(pathOrURL)) + layoutTestController->setDumpFrameLoadCallbacks(true); + + COMPtr<IWebHistory> history(Create, CLSID_WebHistory); + if (history) + history->setOptionalSharedHistory(0); + + resetWebViewToConsistentStateBeforeTesting(); + sharedUIDelegate->resetUndoManager(); + + prevTestBFItem = 0; + COMPtr<IWebView> webView; + if (SUCCEEDED(frame->webView(&webView))) { + COMPtr<IWebBackForwardList> bfList; + if (SUCCEEDED(webView->backForwardList(&bfList))) + bfList->currentItem(&prevTestBFItem); + } + + WorkQueue::shared()->clear(); + WorkQueue::shared()->setFrozen(false); + + HWND hostWindow; + webView->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow)); + + // Set the test timeout timer + SetTimer(hostWindow, timeoutId, timeoutValue, 0); + + COMPtr<IWebMutableURLRequest> request; + HRESULT hr = CoCreateInstance(CLSID_WebMutableURLRequest, 0, CLSCTX_ALL, IID_IWebMutableURLRequest, (void**)&request); + if (FAILED(hr)) + goto exit; + + request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 60); + + request->setHTTPMethod(methodBStr); + frame->loadRequest(request.get()); + + MSG msg; + while (GetMessage(&msg, 0, 0, 0)) { + // We get spurious WM_MOUSELEAVE events which make event handling machinery think that mouse button + // is released during dragging (see e.g. fast\dynamic\layer-hit-test-crash.html). + // Mouse can never leave WebView during normal DumpRenderTree operation, so we just ignore all such events. + if (msg.message == WM_MOUSELEAVE) + continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + KillTimer(hostWindow, timeoutId); + + if (timedOut) { + fprintf(stderr, "ERROR: Timed out running %s\n", pathOrURL); + printf("ERROR: Timed out loading page\n"); + + if (printSeparators) + puts("#EOF"); + } + + frame->stopLoading(); + + if (::layoutTestController->closeRemainingWindowsWhenComplete()) { + Vector<HWND> windows = openWindows(); + unsigned size = windows.size(); + for (unsigned i = 0; i < size; i++) { + HWND window = windows[i]; + + // Don't try to close the main window + if (window == hostWindow) + continue; + + DestroyWindow(window); + } + } + +exit: + SysFreeString(urlBStr); + delete ::layoutTestController; + + return; +} + +static void initializePreferences(IWebPreferences* preferences) +{ +#ifdef USE_MAC_FONTS + BSTR standardFamily = SysAllocString(TEXT("Times")); + BSTR fixedFamily = SysAllocString(TEXT("Courier")); + BSTR sansSerifFamily = SysAllocString(TEXT("Helvetica")); + BSTR cursiveFamily = SysAllocString(TEXT("Apple Chancery")); + BSTR fantasyFamily = SysAllocString(TEXT("Papyrus")); +#else + BSTR standardFamily = SysAllocString(TEXT("Times New Roman")); + BSTR fixedFamily = SysAllocString(TEXT("Courier New")); + BSTR sansSerifFamily = SysAllocString(TEXT("Arial")); + BSTR cursiveFamily = SysAllocString(TEXT("Comic Sans MS")); // Not actually cursive, but it's what IE and Firefox use. + BSTR fantasyFamily = SysAllocString(TEXT("Times New Roman")); +#endif + + preferences->setStandardFontFamily(standardFamily); + preferences->setFixedFontFamily(fixedFamily); + preferences->setSerifFontFamily(standardFamily); + preferences->setSansSerifFontFamily(sansSerifFamily); + preferences->setCursiveFontFamily(cursiveFamily); + preferences->setFantasyFontFamily(fantasyFamily); + + preferences->setAutosaves(FALSE); + preferences->setJavaEnabled(FALSE); + preferences->setPlugInsEnabled(TRUE); + preferences->setDOMPasteAllowed(TRUE); + preferences->setEditableLinkBehavior(WebKitEditableLinkOnlyLiveWithShiftKey); + preferences->setFontSmoothing(FontSmoothingTypeStandard); + preferences->setUsesPageCache(FALSE); + + SysFreeString(standardFamily); + SysFreeString(fixedFamily); + SysFreeString(sansSerifFamily); + SysFreeString(cursiveFamily); + SysFreeString(fantasyFamily); +} + +static Boolean pthreadEqualCallback(const void* value1, const void* value2) +{ + return (Boolean)pthread_equal(*(pthread_t*)value1, *(pthread_t*)value2); +} + +static CFDictionaryKeyCallBacks pthreadKeyCallbacks = { 0, 0, 0, 0, pthreadEqualCallback, 0 }; + +static pthread_mutex_t javaScriptThreadsMutex = PTHREAD_MUTEX_INITIALIZER; +static bool javaScriptThreadsShouldTerminate; + +static const int javaScriptThreadsCount = 4; +static CFMutableDictionaryRef javaScriptThreads() +{ + assert(pthread_mutex_trylock(&javaScriptThreadsMutex) == EBUSY); + static CFMutableDictionaryRef staticJavaScriptThreads; + if (!staticJavaScriptThreads) + staticJavaScriptThreads = CFDictionaryCreateMutable(0, 0, &pthreadKeyCallbacks, 0); + return staticJavaScriptThreads; +} + +// Loops forever, running a script and randomly respawning, until +// javaScriptThreadsShouldTerminate becomes true. +void* runJavaScriptThread(void* arg) +{ + const char* const script = + " \ + var array = []; \ + for (var i = 0; i < 10; i++) { \ + array.push(String(i)); \ + } \ + "; + + while (true) { + JSGlobalContextRef ctx = JSGlobalContextCreate(0); + JSStringRef scriptRef = JSStringCreateWithUTF8CString(script); + + JSValueRef exception = 0; + JSEvaluateScript(ctx, scriptRef, 0, 0, 0, &exception); + assert(!exception); + + JSGlobalContextRelease(ctx); + JSStringRelease(scriptRef); + + JSGarbageCollect(ctx); + + pthread_mutex_lock(&javaScriptThreadsMutex); + + // Check for cancellation. + if (javaScriptThreadsShouldTerminate) { + pthread_mutex_unlock(&javaScriptThreadsMutex); + return 0; + } + + // Respawn probabilistically. + if (rand() % 5 == 0) { + pthread_t pthread; + pthread_create(&pthread, 0, &runJavaScriptThread, 0); + pthread_detach(pthread); + + pthread_t self = pthread_self(); + CFDictionaryRemoveValue(javaScriptThreads(), self.p); + CFDictionaryAddValue(javaScriptThreads(), pthread.p, 0); + + pthread_mutex_unlock(&javaScriptThreadsMutex); + return 0; + } + + pthread_mutex_unlock(&javaScriptThreadsMutex); + } +} + +static void startJavaScriptThreads(void) +{ + pthread_mutex_lock(&javaScriptThreadsMutex); + + for (int i = 0; i < javaScriptThreadsCount; i++) { + pthread_t pthread; + pthread_create(&pthread, 0, &runJavaScriptThread, 0); + pthread_detach(pthread); + CFDictionaryAddValue(javaScriptThreads(), pthread.p, 0); + } + + pthread_mutex_unlock(&javaScriptThreadsMutex); +} + +static void stopJavaScriptThreads(void) +{ + pthread_mutex_lock(&javaScriptThreadsMutex); + + javaScriptThreadsShouldTerminate = true; + + pthread_t* pthreads[javaScriptThreadsCount] = {0}; + int threadDictCount = CFDictionaryGetCount(javaScriptThreads()); + assert(threadDictCount == javaScriptThreadsCount); + CFDictionaryGetKeysAndValues(javaScriptThreads(), (const void**)pthreads, 0); + + pthread_mutex_unlock(&javaScriptThreadsMutex); + + for (int i = 0; i < javaScriptThreadsCount; i++) { + pthread_t* pthread = pthreads[i]; + pthread_join(*pthread, 0); + free(pthread); + } +} + +Vector<HWND>& openWindows() +{ + static Vector<HWND> vector; + return vector; +} + +HashMap<HWND, IWebView*>& windowToWebViewMap() +{ + static HashMap<HWND, IWebView*> map; + return map; +} + +IWebView* createWebViewAndOffscreenWindow(HWND* webViewWindow) +{ + HWND hostWindow = CreateWindowEx(WS_EX_TOOLWINDOW, kDumpRenderTreeClassName, TEXT("DumpRenderTree"), WS_POPUP, + -maxViewWidth, -maxViewHeight, maxViewWidth, maxViewHeight, 0, 0, GetModuleHandle(0), 0); + + IWebView* webView; + + HRESULT hr = CoCreateInstance(CLSID_WebView, 0, CLSCTX_ALL, IID_IWebView, (void**)&webView); + if (FAILED(hr)) { + fprintf(stderr, "Failed to create CLSID_WebView instance, error 0x%x\n", hr); + return 0; + } + + if (FAILED(webView->setHostWindow((OLE_HANDLE)(ULONG64)hostWindow))) + return 0; + + RECT clientRect; + clientRect.bottom = clientRect.left = clientRect.top = clientRect.right = 0; + BSTR groupName = SysAllocString(L"org.webkit.DumpRenderTree"); + bool failed = FAILED(webView->initWithFrame(clientRect, 0, groupName)); + SysFreeString(groupName); + if (failed) + return 0; + + COMPtr<IWebViewPrivate> viewPrivate; + if (FAILED(webView->QueryInterface(&viewPrivate))) + return 0; + + viewPrivate->setShouldApplyMacFontAscentHack(TRUE); + + BSTR pluginPath = SysAllocStringLen(0, exePath().length() + _tcslen(TestPluginDir)); + _tcscpy(pluginPath, exePath().c_str()); + _tcscat(pluginPath, TestPluginDir); + failed = FAILED(viewPrivate->addAdditionalPluginPath(pluginPath)); + SysFreeString(pluginPath); + if (failed) + return 0; + + HWND viewWindow; + if (FAILED(viewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + return 0; + if (webViewWindow) + *webViewWindow = viewWindow; + + SetWindowPos(viewWindow, 0, 0, 0, maxViewWidth, maxViewHeight, 0); + ShowWindow(hostWindow, SW_SHOW); + + if (FAILED(webView->setFrameLoadDelegate(sharedFrameLoadDelegate.get()))) + return 0; + + if (FAILED(viewPrivate->setFrameLoadDelegatePrivate(sharedFrameLoadDelegate.get()))) + return 0; + + if (FAILED(webView->setUIDelegate(sharedUIDelegate.get()))) + return 0; + + COMPtr<IWebViewEditing> viewEditing; + if (FAILED(webView->QueryInterface(&viewEditing))) + return 0; + + if (FAILED(viewEditing->setEditingDelegate(sharedEditingDelegate.get()))) + return 0; + + if (FAILED(webView->setResourceLoadDelegate(sharedResourceLoadDelegate.get()))) + return 0; + + COMPtr<IWebPreferences> preferences; + if (FAILED(webView->preferences(&preferences))) + return 0; + + initializePreferences(preferences.get()); + + openWindows().append(hostWindow); + windowToWebViewMap().set(hostWindow, webView); + return webView; +} + +int main(int argc, char* argv[]) +{ + leakChecking = false; + + _setmode(1, _O_BINARY); + + initialize(); + + Vector<const char*> tests; + + for (int i = 1; i < argc; ++i) { + if (!stricmp(argv[i], "--threaded")) { + threaded = true; + continue; + } + + if (!stricmp(argv[i], "--dump-all-pixels")) { + dumpAllPixels = true; + continue; + } + + if (!stricmp(argv[i], "--pixel-tests")) { + dumpPixels = true; + continue; + } + + tests.append(argv[i]); + } + + policyDelegate = new PolicyDelegate(); + sharedFrameLoadDelegate.adoptRef(new FrameLoadDelegate); + sharedUIDelegate.adoptRef(new UIDelegate); + sharedEditingDelegate.adoptRef(new EditingDelegate); + sharedResourceLoadDelegate.adoptRef(new ResourceLoadDelegate); + + COMPtr<IWebView> webView(AdoptCOM, createWebViewAndOffscreenWindow(&webViewWindow)); + if (!webView) + return -1; + + COMPtr<IWebIconDatabase> iconDatabase; + COMPtr<IWebIconDatabase> tmpIconDatabase; + if (FAILED(CoCreateInstance(CLSID_WebIconDatabase, 0, CLSCTX_ALL, IID_IWebIconDatabase, (void**)&tmpIconDatabase))) + return -1; + if (FAILED(tmpIconDatabase->sharedIconDatabase(&iconDatabase))) + return -1; + + if (FAILED(webView->mainFrame(&frame))) + return -1; + + CFURLCacheRemoveAllCachedResponses(CFURLCacheSharedURLCache()); + +#ifdef _DEBUG + _CrtMemState entryToMainMemCheckpoint; + if (leakChecking) + _CrtMemCheckpoint(&entryToMainMemCheckpoint); +#endif + + if (threaded) + startJavaScriptThreads(); + + if (tests.size() == 1 && !strcmp(tests[0], "-")) { + char filenameBuffer[2048]; + printSeparators = true; + while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { + char* newLineCharacter = strchr(filenameBuffer, '\n'); + if (newLineCharacter) + *newLineCharacter = '\0'; + + if (strlen(filenameBuffer) == 0) + continue; + + runTest(filenameBuffer); + fflush(stdout); + } + } else { + printSeparators = tests.size() > 1; + for (int i = 0; i < tests.size(); i++) + runTest(tests[i]); + } + + if (threaded) + stopJavaScriptThreads(); + + delete policyDelegate; + frame->Release(); + +#ifdef _DEBUG + if (leakChecking) { + // dump leaks to stderr + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtMemDumpAllObjectsSince(&entryToMainMemCheckpoint); + } +#endif + + return 0; +} diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj new file mode 100644 index 0000000..a357f29 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj @@ -0,0 +1,374 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="DumpRenderTree"
+ ProjectGUID="{6567DFD4-D6DE-4CD5-825D-17E353D160E1}"
+ RootNamespace="DumpRenderTree"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders""
+ PreprocessorDefinitions="_CONSOLE"
+ DisableSpecificWarnings="4146"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WebKitGUID$(WebKitConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib WTF$(WebKitConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib CFNetwork$(LibraryConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib gdi32.lib ole32.lib oleaut32.lib user32.lib shlwapi.lib"
+ AdditionalLibraryDirectories=""
+ DelayLoadDLLs=""
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="
"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders""
+ PreprocessorDefinitions="_CONSOLE"
+ DisableSpecificWarnings="4146"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WebKitGUID$(WebKitConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib WTF$(WebKitConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib CFNetwork$(LibraryConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib gdi32.lib ole32.lib oleaut32.lib user32.lib shlwapi.lib"
+ AdditionalLibraryDirectories=""
+ DelayLoadDLLs=""
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="
"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_Internal|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders"
mkdir 2>NUL "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"

xcopy /y /d "$(ProjectDir)\..\ForwardingHeaders\wtf\*.h" "$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf"
"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders""
+ PreprocessorDefinitions="_CONSOLE;DEBUG_WEBKIT_HAS_SUFFIX"
+ DisableSpecificWarnings="4146"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WebKitGUID$(WebKitConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib WTF$(WebKitConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib CFNetwork$(LibraryConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib gdi32.lib ole32.lib oleaut32.lib user32.lib shlwapi.lib"
+ AdditionalLibraryDirectories=""
+ DelayLoadDLLs=""
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="
"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Controllers"
+ >
+ <File
+ RelativePath=".\EventSender.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\EventSender.h"
+ >
+ </File>
+ <File
+ RelativePath="..\GCController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\GCController.h"
+ >
+ </File>
+ <File
+ RelativePath=".\GCControllerWin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\LayoutTestController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\LayoutTestController.h"
+ >
+ </File>
+ <File
+ RelativePath=".\LayoutTestControllerWin.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Delegates"
+ >
+ <File
+ RelativePath=".\EditingDelegate.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\EditingDelegate.h"
+ >
+ </File>
+ <File
+ RelativePath=".\FrameLoadDelegate.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\FrameLoadDelegate.h"
+ >
+ </File>
+ <File
+ RelativePath=".\PolicyDelegate.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\PolicyDelegate.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ResourceLoadDelegate.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ResourceLoadDelegate.h"
+ >
+ </File>
+ <File
+ RelativePath=".\UIDelegate.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\UIDelegate.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\DraggingInfo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\DumpRenderTree.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\DumpRenderTree.h"
+ >
+ </File>
+ <File
+ RelativePath=".\DumpRenderTreeWin.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MD5.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MD5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\PixelDumpSupport.h"
+ >
+ </File>
+ <File
+ RelativePath="..\cg\PixelDumpSupportCG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\cg\PixelDumpSupportCG.h"
+ >
+ </File>
+ <File
+ RelativePath=".\PixelDumpSupportWin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\WorkQueue.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\WorkQueue.h"
+ >
+ </File>
+ <File
+ RelativePath="..\WorkQueueItem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WorkQueueItemWin.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h b/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h new file mode 100644 index 0000000..54dc697 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +#ifndef DumpRenderTreeWin_h +#define DumpRenderTreeWin_h + +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 + +#undef WINVER +#define WINVER 0x0500 + +// If we don't define these, they get defined in windef.h. +// We want to use std::min and std::max +#undef max +#define max max +#undef min +#define min min + +#undef _WINSOCKAPI_ +#define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h + +// FIXME: we should add a config.h file for DumpRenderTree. +#define WTF_PLATFORM_CF 1 + +struct IWebFrame; +struct IWebPolicyDelegate; +struct IWebView; +typedef const struct __CFString* CFStringRef; +typedef struct HWND__* HWND; + +extern IWebFrame* topLoadingFrame; +extern IWebFrame* frame; +extern IWebPolicyDelegate* policyDelegate; + +extern HWND webViewWindow; + +#include <string> +#include <wtf/HashMap.h> +#include <wtf/Vector.h> + +std::wstring urlSuitableForTestResult(const std::wstring& url); +IWebView* createWebViewAndOffscreenWindow(HWND* webViewWindow = 0); +Vector<HWND>& openWindows(); +HashMap<HWND, IWebView*>& windowToWebViewMap(); + +void setPersistentUserStyleSheetLocation(CFStringRef); + +#endif // DumpRenderTreeWin_h diff --git a/WebKitTools/DumpRenderTree/win/EditingDelegate.cpp b/WebKitTools/DumpRenderTree/win/EditingDelegate.cpp new file mode 100644 index 0000000..7add64e --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/EditingDelegate.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "EditingDelegate.h" + +#include "LayoutTestController.h" +#include <WebCore/COMPtr.h> +#include <wtf/Platform.h> +#include <JavaScriptCore/Assertions.h> +#include <string> +#include <tchar.h> + +using std::wstring; + +EditingDelegate::EditingDelegate() + : m_refCount(1) + , m_acceptsEditing(true) +{ +} + +// IUnknown +HRESULT STDMETHODCALLTYPE EditingDelegate::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebEditingDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebEditingDelegate)) + *ppvObject = static_cast<IWebEditingDelegate*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE EditingDelegate::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE EditingDelegate::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete this; + + return newRef; +} + +static wstring dumpPath(IDOMNode* node) +{ + ASSERT(node); + + wstring result; + + BSTR name; + if (FAILED(node->nodeName(&name))) + return result; + result.assign(name, SysStringLen(name)); + SysFreeString(name); + + COMPtr<IDOMNode> parent; + if (SUCCEEDED(node->parentNode(&parent))) + result += TEXT(" > ") + dumpPath(parent.get()); + + return result; +} + +static wstring dump(IDOMRange* range) +{ + ASSERT(range); + + int startOffset; + if (FAILED(range->startOffset(&startOffset))) + return 0; + + int endOffset; + if (FAILED(range->endOffset(&endOffset))) + return 0; + + COMPtr<IDOMNode> startContainer; + if (FAILED(range->startContainer(&startContainer))) + return 0; + + COMPtr<IDOMNode> endContainer; + if (FAILED(range->endContainer(&endContainer))) + return 0; + + wchar_t buffer[1024]; + _snwprintf(buffer, ARRAYSIZE(buffer), L"range from %ld of %s to %ld of %s", startOffset, dumpPath(startContainer.get()), endOffset, dumpPath(endContainer.get())); + return buffer; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldBeginEditingInDOMRange( + /* [in] */ IWebView* webView, + /* [in] */ IDOMRange* range, + /* [retval][out] */ BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n"), dump(range)); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldEndEditingInDOMRange( + /* [in] */ IWebView* webView, + /* [in] */ IDOMRange* range, + /* [retval][out] */ BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n"), dump(range)); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldInsertNode( + /* [in] */ IWebView* webView, + /* [in] */ IDOMNode* node, + /* [in] */ IDOMRange* range, + /* [in] */ WebViewInsertAction action) +{ + static LPCTSTR insertactionstring[] = { + TEXT("WebViewInsertActionTyped"), + TEXT("WebViewInsertActionPasted"), + TEXT("WebViewInsertActionDropped"), + }; + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n"), dumpPath(node), dump(range), insertactionstring[action]); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldInsertText( + /* [in] */ IWebView* webView, + /* [in] */ BSTR text, + /* [in] */ IDOMRange* range, + /* [in] */ WebViewInsertAction action, + /* [retval][out] */ BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + static LPCTSTR insertactionstring[] = { + TEXT("WebViewInsertActionTyped"), + TEXT("WebViewInsertActionPasted"), + TEXT("WebViewInsertActionDropped"), + }; + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n"), text ? text : TEXT(""), dump(range), insertactionstring[action]); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldDeleteDOMRange( + /* [in] */ IWebView* webView, + /* [in] */ IDOMRange* range, + /* [retval][out] */ BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldDeleteDOMRange:%s\n"), dump(range)); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldChangeSelectedDOMRange( + /* [in] */ IWebView* webView, + /* [in] */ IDOMRange* currentRange, + /* [in] */ IDOMRange* proposedRange, + /* [in] */ WebSelectionAffinity selectionAffinity, + /* [in] */ BOOL stillSelecting, + /* [retval][out] */ BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + static LPCTSTR affinitystring[] = { + TEXT("NSSelectionAffinityUpstream"), + TEXT("NSSelectionAffinityDownstream") + }; + static LPCTSTR boolstring[] = { + TEXT("FALSE"), + TEXT("TRUE") + }; + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n"), dump(currentRange), dump(proposedRange), affinitystring[selectionAffinity], boolstring[stillSelecting]); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldApplyStyle( + /* [in] */ IWebView* webView, + /* [in] */ IDOMCSSStyleDeclaration* style, + /* [in] */ IDOMRange* range, + /* [retval][out] */ BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n"), TEXT("'style description'")/*[[style description] UTF8String]*/, dump(range)); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::shouldChangeTypingStyle( + /* [in] */ IWebView* webView, + /* [in] */ IDOMCSSStyleDeclaration* currentStyle, + /* [in] */ IDOMCSSStyleDeclaration* proposedStyle, + /* [retval][out] */ BOOL* result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: shouldChangeTypingStyle:%s toStyle:%s\n"), TEXT("'currentStyle description'"), TEXT("'proposedStyle description'")); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::doPlatformCommand( + /* [in] */ IWebView *webView, + /* [in] */ BSTR command, + /* [retval][out] */ BOOL *result) +{ + if (!result) { + ASSERT_NOT_REACHED(); + return E_POINTER; + } + + if (::layoutTestController->dumpEditingCallbacks() && !done) + _tprintf(TEXT("EDITING DELEGATE: doPlatformCommand:%s\n"), command ? command : TEXT("")); + + *result = m_acceptsEditing; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidBeginEditing( + /* [in] */ IWebNotification* notification) +{ + if (::layoutTestController->dumpEditingCallbacks() && !done) { + BSTR name; + notification->name(&name); + _tprintf(TEXT("EDITING DELEGATE: webViewDidBeginEditing:%s\n"), name ? name : TEXT("")); + SysFreeString(name); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidChange( + /* [in] */ IWebNotification *notification) +{ + if (::layoutTestController->dumpEditingCallbacks() && !done) { + BSTR name; + notification->name(&name); + _tprintf(TEXT("EDITING DELEGATE: webViewDidBeginEditing:%s\n"), name ? name : TEXT("")); + SysFreeString(name); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidEndEditing( + /* [in] */ IWebNotification *notification) +{ + if (::layoutTestController->dumpEditingCallbacks() && !done) { + BSTR name; + notification->name(&name); + _tprintf(TEXT("EDITING DELEGATE: webViewDidEndEditing:%s\n"), name ? name : TEXT("")); + SysFreeString(name); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidChangeTypingStyle( + /* [in] */ IWebNotification *notification) +{ + if (::layoutTestController->dumpEditingCallbacks() && !done) { + BSTR name; + notification->name(&name); + _tprintf(TEXT("EDITING DELEGATE: webViewDidChangeTypingStyle:%s\n"), name ? name : TEXT("")); + SysFreeString(name); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidChangeSelection( + /* [in] */ IWebNotification *notification) +{ + if (::layoutTestController->dumpEditingCallbacks() && !done) { + BSTR name; + notification->name(&name); + _tprintf(TEXT("EDITING DELEGATE: webViewDidChangeSelection:%s\n"), name ? name : TEXT("")); + SysFreeString(name); + } + return S_OK; +} diff --git a/WebKitTools/DumpRenderTree/win/EditingDelegate.h b/WebKitTools/DumpRenderTree/win/EditingDelegate.h new file mode 100644 index 0000000..6dba675 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/EditingDelegate.h @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef EditingDelegate_h +#define EditingDelegate_h + +#include <WebKit/WebKit.h> + +class __declspec(uuid("265DCD4B-79C3-44a2-84BC-511C3EDABD6F")) EditingDelegate : public IWebEditingDelegate { +public: + EditingDelegate(); + + void setAcceptsEditing(bool b) { m_acceptsEditing = b; } + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IWebEditingDelegate + virtual HRESULT STDMETHODCALLTYPE shouldBeginEditingInDOMRange( + /* [in] */ IWebView *webView, + /* [in] */ IDOMRange *range, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE shouldEndEditingInDOMRange( + /* [in] */ IWebView *webView, + /* [in] */ IDOMRange *range, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE shouldInsertNode( + /* [in] */ IWebView *webView, + /* [in] */ IDOMNode *node, + /* [in] */ IDOMRange *range, + /* [in] */ WebViewInsertAction action); + + virtual HRESULT STDMETHODCALLTYPE shouldInsertText( + /* [in] */ IWebView *webView, + /* [in] */ BSTR text, + /* [in] */ IDOMRange *range, + /* [in] */ WebViewInsertAction action, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE shouldDeleteDOMRange( + /* [in] */ IWebView *webView, + /* [in] */ IDOMRange *range, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE shouldChangeSelectedDOMRange( + /* [in] */ IWebView *webView, + /* [in] */ IDOMRange *currentRange, + /* [in] */ IDOMRange *proposedRange, + /* [in] */ WebSelectionAffinity selectionAffinity, + /* [in] */ BOOL stillSelecting, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE shouldApplyStyle( + /* [in] */ IWebView *webView, + /* [in] */ IDOMCSSStyleDeclaration *style, + /* [in] */ IDOMRange *range, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE shouldChangeTypingStyle( + /* [in] */ IWebView *webView, + /* [in] */ IDOMCSSStyleDeclaration *currentStyle, + /* [in] */ IDOMCSSStyleDeclaration *proposedStyle, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE doPlatformCommand( + /* [in] */ IWebView *webView, + /* [in] */ BSTR command, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE webViewDidBeginEditing( + /* [in] */ IWebNotification *notification); + + virtual HRESULT STDMETHODCALLTYPE webViewDidChange( + /* [in] */ IWebNotification *notification); + + virtual HRESULT STDMETHODCALLTYPE webViewDidEndEditing( + /* [in] */ IWebNotification *notification); + + virtual HRESULT STDMETHODCALLTYPE webViewDidChangeTypingStyle( + /* [in] */ IWebNotification *notification); + + virtual HRESULT STDMETHODCALLTYPE webViewDidChangeSelection( + /* [in] */ IWebNotification *notification); + + virtual HRESULT STDMETHODCALLTYPE undoManagerForWebView( + /* [in] */ IWebView *webView, + /* [retval][out] */ IWebUndoManager **undoManager) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE ignoreWordInSpellDocument( + /* [in] */ IWebView *view, + /* [in] */ BSTR word) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE learnWord( + /* [in] */ BSTR word) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE checkSpellingOfString( + /* [in] */ IWebView *view, + /* [in] */ LPCTSTR text, + /* [in] */ int length, + /* [out] */ int *misspellingLocation, + /* [out] */ int *misspellingLength) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE checkGrammarOfString( + /* [in] */ IWebView *view, + /* [in] */ LPCTSTR text, + /* [in] */ int length, + /* [out] */ IEnumWebGrammarDetails **grammarDetails, + /* [out] */ int *badGrammarLocation, + /* [out] */ int *badGrammarLength) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE updateSpellingUIWithGrammarString( + /* [in] */ BSTR string, + /* [in] */ int location, + /* [in] */ int length, + /* [in] */ BSTR userDescription, + /* [in] */ BSTR *guesses, + /* [in] */ int guessesCount) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE updateSpellingUIWithMisspelledWord( + /* [in] */ BSTR word) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE showSpellingUI( + /* [in] */ BOOL show) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE spellingUIIsShowing( + /* [retval][out] */ BOOL *result) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE guessesForWord( + /* [in] */ BSTR word, + /* [retval][out] */ IEnumSpellingGuesses **guesses) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE closeSpellDocument( + /* [in] */ IWebView *view) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE sharedSpellCheckerExists( + /* [retval][out] */ BOOL *exists) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE preflightChosenSpellServer( void) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE updateGrammar( void) { return E_NOTIMPL; } + +private: + bool m_acceptsEditing; + ULONG m_refCount; +}; + +#endif // !defined(EditingDelegate_h) diff --git a/WebKitTools/DumpRenderTree/win/EventSender.cpp b/WebKitTools/DumpRenderTree/win/EventSender.cpp new file mode 100644 index 0000000..ddff01c --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/EventSender.cpp @@ -0,0 +1,566 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "EventSender.h" + +#include "DraggingInfo.h" + +#include <WebCore/COMPtr.h> +#include <wtf/ASCIICType.h> +#include <wtf/Platform.h> +#include <JavaScriptCore/JavaScriptCore.h> +#include <JavaScriptCore/Assertions.h> +#include <WebKit/WebKit.h> +#include <windows.h> + +#define WM_DRT_SEND_QUEUED_EVENT (WM_APP+1) + +static bool down; +static bool dragMode = true; +static bool replayingSavedEvents; +static int timeOffset; +static POINT lastMousePosition; + +struct DelayedMessage { + MSG msg; + unsigned delay; +}; + +static DelayedMessage msgQueue[1024]; +static unsigned endOfQueue; +static unsigned startOfQueue; + +static bool didDragEnter; +DraggingInfo* draggingInfo = 0; + +static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) +{ + return JSValueMakeBoolean(context, dragMode); +} + +static bool setDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) +{ + dragMode = JSValueToBoolean(context, value); + return true; +} + +static JSValueRef getConstantCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) +{ + if (JSStringIsEqualToUTF8CString(propertyName, "WM_KEYDOWN")) + return JSValueMakeNumber(context, WM_KEYDOWN); + if (JSStringIsEqualToUTF8CString(propertyName, "WM_KEYUP")) + return JSValueMakeNumber(context, WM_KEYUP); + if (JSStringIsEqualToUTF8CString(propertyName, "WM_CHAR")) + return JSValueMakeNumber(context, WM_CHAR); + if (JSStringIsEqualToUTF8CString(propertyName, "WM_DEADCHAR")) + return JSValueMakeNumber(context, WM_DEADCHAR); + if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSKEYDOWN")) + return JSValueMakeNumber(context, WM_SYSKEYDOWN); + if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSKEYUP")) + return JSValueMakeNumber(context, WM_SYSKEYUP); + if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSCHAR")) + return JSValueMakeNumber(context, WM_SYSCHAR); + if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSDEADCHAR")) + return JSValueMakeNumber(context, WM_SYSDEADCHAR); + ASSERT_NOT_REACHED(); + return JSValueMakeUndefined(context); +} + +static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount > 0) { + msgQueue[endOfQueue].delay = JSValueToNumber(context, arguments[0], exception); + ASSERT(!exception || !*exception); + } + + return JSValueMakeUndefined(context); +} + +static DWORD currentEventTime() +{ + return ::GetTickCount() + timeOffset; +} + +static MSG makeMsg(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + MSG result = {0}; + result.hwnd = hwnd; + result.message = message; + result.wParam = wParam; + result.lParam = lParam; + result.time = currentEventTime(); + result.pt = lastMousePosition; + + return result; +} + +static LRESULT dispatchMessage(const MSG* msg) +{ + ASSERT(msg); + ::TranslateMessage(msg); + return ::DispatchMessage(msg); +} + +static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + COMPtr<IWebFramePrivate> framePrivate; + if (SUCCEEDED(frame->QueryInterface(&framePrivate))) + framePrivate->layout(); + + down = true; + MSG msg = makeMsg(webViewWindow, WM_RBUTTONDOWN, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); + dispatchMessage(&msg); + down = false; + msg = makeMsg(webViewWindow, WM_RBUTTONUP, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); + dispatchMessage(&msg); + + return JSValueMakeUndefined(context); +} + +static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + COMPtr<IWebFramePrivate> framePrivate; + if (SUCCEEDED(frame->QueryInterface(&framePrivate))) + framePrivate->layout(); + + down = true; + MSG msg = makeMsg(webViewWindow, WM_LBUTTONDOWN, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); + if (!msgQueue[endOfQueue].delay) + dispatchMessage(&msg); + else { + // replaySavedEvents has the required logic to make leapForward delays work + msgQueue[endOfQueue++].msg = msg; + replaySavedEvents(); + } + + return JSValueMakeUndefined(context); +} + +static inline POINTL pointl(const POINT& point) +{ + POINTL result; + result.x = point.x; + result.y = point.y; + return result; +} + +static void doMouseUp(MSG msg) +{ + COMPtr<IWebFramePrivate> framePrivate; + if (SUCCEEDED(frame->QueryInterface(&framePrivate))) + framePrivate->layout(); + + dispatchMessage(&msg); + down = false; + + if (draggingInfo) { + COMPtr<IWebView> webView; + COMPtr<IDropTarget> webViewDropTarget; + if (SUCCEEDED(frame->webView(&webView)) && SUCCEEDED(webView->QueryInterface(IID_IDropTarget, (void**)&webViewDropTarget))) { + POINT screenPoint = msg.pt; + DWORD effect = 0; + ::ClientToScreen(webViewWindow, &screenPoint); + if (!didDragEnter) { + webViewDropTarget->DragEnter(draggingInfo->dataObject(), 0, pointl(screenPoint), &effect); + didDragEnter = true; + } + HRESULT hr = draggingInfo->dropSource()->QueryContinueDrag(0, 0); + webViewDropTarget->DragOver(0, pointl(screenPoint), &effect); + if (hr == DRAGDROP_S_DROP && effect != DROPEFFECT_NONE) { + DWORD effect = 0; + webViewDropTarget->Drop(draggingInfo->dataObject(), 0, pointl(screenPoint), &effect); + } else + webViewDropTarget->DragLeave(); + + delete draggingInfo; + draggingInfo = 0; + } + } +} + +static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + MSG msg = makeMsg(webViewWindow, WM_LBUTTONUP, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); + + if ((dragMode && !replayingSavedEvents) || msgQueue[endOfQueue].delay) { + msgQueue[endOfQueue++].msg = msg; + replaySavedEvents(); + } else + doMouseUp(msg); + + return JSValueMakeUndefined(context); +} + +static void doMouseMove(MSG msg) +{ + COMPtr<IWebFramePrivate> framePrivate; + if (SUCCEEDED(frame->QueryInterface(&framePrivate))) + framePrivate->layout(); + + dispatchMessage(&msg); + + if (down && draggingInfo) { + POINT screenPoint = msg.pt; + ::ClientToScreen(webViewWindow, &screenPoint); + + IWebView* webView; + COMPtr<IDropTarget> webViewDropTarget; + if (SUCCEEDED(frame->webView(&webView)) && SUCCEEDED(webView->QueryInterface(IID_IDropTarget, (void**)&webViewDropTarget))) { + DWORD effect = 0; + if (didDragEnter) + webViewDropTarget->DragOver(MK_LBUTTON, pointl(screenPoint), &effect); + else { + webViewDropTarget->DragEnter(draggingInfo->dataObject(), 0, pointl(screenPoint), &effect); + didDragEnter = true; + } + draggingInfo->dropSource()->GiveFeedback(effect); + } + } +} + +static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 2) + return JSValueMakeUndefined(context); + + lastMousePosition.x = (int)JSValueToNumber(context, arguments[0], exception); + ASSERT(!exception || !*exception); + lastMousePosition.y = (int)JSValueToNumber(context, arguments[1], exception); + ASSERT(!exception || !*exception); + + MSG msg = makeMsg(webViewWindow, WM_MOUSEMOVE, down ? MK_LBUTTON : 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); + + if (dragMode && down && !replayingSavedEvents) { + msgQueue[endOfQueue++].msg = msg; + return JSValueMakeUndefined(context); + } + + doMouseMove(msg); + + return JSValueMakeUndefined(context); +} + +void replaySavedEvents() +{ + replayingSavedEvents = true; + + MSG msg = { 0 }; + + while (startOfQueue < endOfQueue && !msgQueue[startOfQueue].delay) { + msg = msgQueue[startOfQueue++].msg; + switch (msg.message) { + case WM_LBUTTONUP: + doMouseUp(msg); + break; + case WM_MOUSEMOVE: + doMouseMove(msg); + break; + case WM_LBUTTONDOWN: + dispatchMessage(&msg); + break; + default: + // Not reached + break; + } + } + + int numQueuedMessages = endOfQueue - startOfQueue; + if (!numQueuedMessages) { + startOfQueue = 0; + endOfQueue = 0; + replayingSavedEvents = false; + ASSERT(!down); + return; + } + + if (msgQueue[startOfQueue].delay) { + ::Sleep(msgQueue[startOfQueue].delay); + msgQueue[startOfQueue].delay = 0; + } + + ::PostMessage(webViewWindow, WM_DRT_SEND_QUEUED_EVENT, 0, 0); + while (::GetMessage(&msg, webViewWindow, 0, 0)) { + // FIXME: Why do we get a WM_MOUSELEAVE? it breaks tests + if (msg.message == WM_MOUSELEAVE) + continue; + if (msg.message != WM_DRT_SEND_QUEUED_EVENT) { + dispatchMessage(&msg); + continue; + } + msg = msgQueue[startOfQueue++].msg; + switch (msg.message) { + case WM_LBUTTONUP: + doMouseUp(msg); + break; + case WM_MOUSEMOVE: + doMouseMove(msg); + break; + case WM_LBUTTONDOWN: + dispatchMessage(&msg); + break; + default: + // Not reached + break; + } + if (startOfQueue >= endOfQueue) + break; + ::Sleep(msgQueue[startOfQueue].delay); + msgQueue[startOfQueue].delay = 0; + ::PostMessage(webViewWindow, WM_DRT_SEND_QUEUED_EVENT, 0, 0); + } + startOfQueue = 0; + endOfQueue = 0; + + replayingSavedEvents = false; +} + +static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + static const JSStringRef lengthProperty = JSStringCreateWithUTF8CString("length"); + + COMPtr<IWebFramePrivate> framePrivate; + if (SUCCEEDED(frame->QueryInterface(&framePrivate))) + framePrivate->layout(); + + JSStringRef character = JSValueToStringCopy(context, arguments[0], exception); + ASSERT(!*exception); + int virtualKeyCode; + int charCode = 0; + int keyData = 1; + bool needsShiftKeyModifier = false; + if (JSStringIsEqualToUTF8CString(character, "leftArrow")) { + virtualKeyCode = VK_LEFT; + keyData += KF_EXTENDED << 16; // In this case, extended means "not keypad". + } else if (JSStringIsEqualToUTF8CString(character, "rightArrow")) { + virtualKeyCode = VK_RIGHT; + keyData += KF_EXTENDED << 16; + } else if (JSStringIsEqualToUTF8CString(character, "upArrow")) { + virtualKeyCode = VK_UP; + keyData += KF_EXTENDED << 16; + } else if (JSStringIsEqualToUTF8CString(character, "downArrow")) { + virtualKeyCode = VK_DOWN; + keyData += KF_EXTENDED << 16; + } else if (JSStringIsEqualToUTF8CString(character, "pageUp")) + virtualKeyCode = VK_PRIOR; + else if (JSStringIsEqualToUTF8CString(character, "pageDown")) + virtualKeyCode = VK_NEXT; + else if (JSStringIsEqualToUTF8CString(character, "home")) + virtualKeyCode = VK_HOME; + else if (JSStringIsEqualToUTF8CString(character, "end")) + virtualKeyCode = VK_END; + else if (JSStringIsEqualToUTF8CString(character, "delete")) + virtualKeyCode = VK_BACK; + else { + charCode = JSStringGetCharactersPtr(character)[0]; + virtualKeyCode = LOBYTE(VkKeyScan(charCode)); + if (WTF::isASCIIUpper(charCode)) + needsShiftKeyModifier = true; + } + JSStringRelease(character); + + BYTE keyState[256]; + if (argumentCount > 1 || needsShiftKeyModifier) { + ::GetKeyboardState(keyState); + + BYTE newKeyState[256]; + memcpy(newKeyState, keyState, sizeof(keyState)); + + if (needsShiftKeyModifier) + newKeyState[VK_SHIFT] = 0x80; + + if (argumentCount > 1) { + JSObjectRef modifiersArray = JSValueToObject(context, arguments[1], exception); + if (modifiersArray) { + int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, lengthProperty, 0), 0); + for (int i = 0; i < modifiersCount; ++i) { + JSValueRef value = JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0); + JSStringRef string = JSValueToStringCopy(context, value, 0); + if (JSStringIsEqualToUTF8CString(string, "ctrlKey")) + newKeyState[VK_CONTROL] = 0x80; + else if (JSStringIsEqualToUTF8CString(string, "shiftKey")) + newKeyState[VK_SHIFT] = 0x80; + else if (JSStringIsEqualToUTF8CString(string, "altKey")) + newKeyState[VK_MENU] = 0x80; + + JSStringRelease(string); + } + } + } + + ::SetKeyboardState(newKeyState); + } + + MSG msg = makeMsg(webViewWindow, (::GetKeyState(VK_MENU) & 0x8000) ? WM_SYSKEYDOWN : WM_KEYDOWN, virtualKeyCode, keyData); + if (virtualKeyCode != 255) + dispatchMessage(&msg); + else { + // For characters that do not exist in the active keyboard layout, + // ::Translate will not work, so we post an WM_CHAR event ourselves. + ::PostMessage(webViewWindow, WM_CHAR, charCode, 0); + } + + // Tests expect that all messages are processed by the time keyDown() returns. + if (::PeekMessage(&msg, webViewWindow, WM_CHAR, WM_CHAR, PM_REMOVE) || ::PeekMessage(&msg, webViewWindow, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE)) + ::DispatchMessage(&msg); + + MSG msgUp = makeMsg(webViewWindow, (::GetKeyState(VK_MENU) & 0x8000) ? WM_SYSKEYUP : WM_KEYUP, virtualKeyCode, keyData); + ::DispatchMessage(&msgUp); + + if (argumentCount > 1 || needsShiftKeyModifier) + ::SetKeyboardState(keyState); + + return JSValueMakeUndefined(context); +} + +// eventSender.dispatchMessage(message, wParam, lParam, time = currentEventTime(), x = lastMousePosition.x, y = lastMousePosition.y) +static JSValueRef dispatchMessageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 3) + return JSValueMakeUndefined(context); + + COMPtr<IWebFramePrivate> framePrivate; + if (SUCCEEDED(frame->QueryInterface(&framePrivate))) + framePrivate->layout(); + + MSG msg = {}; + msg.hwnd = webViewWindow; + msg.message = JSValueToNumber(context, arguments[0], exception); + ASSERT(!*exception); + msg.wParam = JSValueToNumber(context, arguments[1], exception); + ASSERT(!*exception); + msg.lParam = static_cast<ULONG_PTR>(JSValueToNumber(context, arguments[2], exception)); + ASSERT(!*exception); + if (argumentCount >= 4) { + msg.time = JSValueToNumber(context, arguments[3], exception); + ASSERT(!*exception); + } + if (!msg.time) + msg.time = currentEventTime(); + if (argumentCount >= 6) { + msg.pt.x = JSValueToNumber(context, arguments[4], exception); + ASSERT(!*exception); + msg.pt.y = JSValueToNumber(context, arguments[5], exception); + ASSERT(!*exception); + } else + msg.pt = lastMousePosition; + + ::DispatchMessage(&msg); + + return JSValueMakeUndefined(context); +} + +static JSValueRef textZoomInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return JSValueMakeUndefined(context); + + COMPtr<IWebIBActions> webIBActions; + if (FAILED(webView->QueryInterface(IID_IWebIBActions, (void**)&webIBActions))) + return JSValueMakeUndefined(context); + + webIBActions->makeTextLarger(0); + return JSValueMakeUndefined(context); +} + +static JSValueRef textZoomOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return JSValueMakeUndefined(context); + + COMPtr<IWebIBActions> webIBActions; + if (FAILED(webView->QueryInterface(IID_IWebIBActions, (void**)&webIBActions))) + return JSValueMakeUndefined(context); + + webIBActions->makeTextSmaller(0); + return JSValueMakeUndefined(context); +} + +static JSStaticFunction staticFunctions[] = { + { "contextClick", contextClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "leapForward", leapForwardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dispatchMessage", dispatchMessageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "textZoomIn", textZoomInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "textZoomOut", textZoomOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { 0, 0, 0 } +}; + +static JSStaticValue staticValues[] = { + { "dragMode", getDragModeCallback, setDragModeCallback, kJSPropertyAttributeNone }, + { "WM_KEYDOWN", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { "WM_KEYUP", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { "WM_CHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { "WM_DEADCHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { "WM_SYSKEYDOWN", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { "WM_SYSKEYUP", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { "WM_SYSCHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { "WM_SYSDEADCHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone }, + { 0, 0, 0, 0 } +}; + +static JSClassRef getClass(JSContextRef context) +{ + static JSClassRef eventSenderClass = 0; + + if (!eventSenderClass) { + JSClassDefinition classDefinition = {0}; + classDefinition.staticFunctions = staticFunctions; + classDefinition.staticValues = staticValues; + + eventSenderClass = JSClassCreate(&classDefinition); + } + + return eventSenderClass; +} + +JSObjectRef makeEventSender(JSContextRef context) +{ + down = false; + dragMode = true; + replayingSavedEvents = false; + timeOffset = 0; + lastMousePosition.x = 0; + lastMousePosition.y = 0; + + endOfQueue = 0; + startOfQueue = 0; + + didDragEnter = false; + draggingInfo = 0; + + return JSObjectMake(context, getClass(context), 0); +} diff --git a/WebKitTools/DumpRenderTree/win/EventSender.h b/WebKitTools/DumpRenderTree/win/EventSender.h new file mode 100644 index 0000000..9ae0aec --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/EventSender.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef EventSender_h +#define EventSender_h + +class DraggingInfo; + +typedef const struct OpaqueJSContext* JSContextRef; +typedef struct OpaqueJSValue* JSObjectRef; + +JSObjectRef makeEventSender(JSContextRef context); +void replaySavedEvents(); + +extern DraggingInfo* draggingInfo; + +#endif diff --git a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp new file mode 100644 index 0000000..b21d34e --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "FrameLoadDelegate.h" + +#include "EventSender.h" +#include "GCController.h" +#include "LayoutTestController.h" +#include "WorkQueueItem.h" +#include "WorkQueue.h" +#include <WebCore/COMPtr.h> +#include <JavaScriptCore/Assertions.h> +#include <JavaScriptCore/JavaScriptCore.h> +#include <WebKit/WebKit.h> +#include <wtf/Vector.h> +#include <stdio.h> +#include <string> + +using std::string; + +static FrameLoadDelegate* g_delegateWaitingOnTimer; + +string BSTRtoString(BSTR bstr) +{ + int result = WideCharToMultiByte(CP_UTF8, 0, bstr, SysStringLen(bstr) + 1, 0, 0, 0, 0); + Vector<char> utf8Vector(result); + result = WideCharToMultiByte(CP_UTF8, 0, bstr, SysStringLen(bstr) + 1, utf8Vector.data(), result, 0, 0); + if (!result) + return string(); + + return string(utf8Vector.data(), utf8Vector.size() - 1); +} + +string descriptionSuitableForTestResult(IWebFrame* webFrame) +{ + COMPtr<IWebView> webView; + if (FAILED(webFrame->webView(&webView))) + return string(); + + COMPtr<IWebFrame> mainFrame; + if (FAILED(webView->mainFrame(&mainFrame))) + return string(); + + if (webFrame == mainFrame) + return "main frame"; + + BSTR frameNameBSTR; + if (FAILED(webFrame->name(&frameNameBSTR))) + return string(); + + string frameName = "frame \"" + BSTRtoString(frameNameBSTR) + "\""; + SysFreeString(frameNameBSTR); + + return frameName; +} + +FrameLoadDelegate::FrameLoadDelegate() + : m_refCount(1) + , m_gcController(new GCController) +{ +} + +FrameLoadDelegate::~FrameLoadDelegate() +{ +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate)) + *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate2)) + *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegatePrivate)) + *ppvObject = static_cast<IWebFrameLoadDelegatePrivate*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE FrameLoadDelegate::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE FrameLoadDelegate::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didStartProvisionalLoadForFrame( + /* [in] */ IWebView* webView, + /* [in] */ IWebFrame* frame) +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didStartProvisionalLoadForFrame\n", + descriptionSuitableForTestResult(frame).c_str()); + + // Make sure we only set this once per test. If it gets cleared, and then set again, we might + // end up doing two dumps for one test. + if (!topLoadingFrame && !done) + topLoadingFrame = frame; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didFailProvisionalLoadWithError( + /* [in] */ IWebView *webView, + /* [in] */ IWebError *error, + /* [in] */ IWebFrame *frame) +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didFailProvisionalLoadWithError\n", + descriptionSuitableForTestResult(frame).c_str()); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didCommitLoadForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) +{ + COMPtr<IWebViewPrivate> webViewPrivate; + HRESULT hr = webView->QueryInterface(&webViewPrivate); + if (FAILED(hr)) + return hr; + webViewPrivate->updateFocusedAndActiveState(); + + if (!done && layoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didCommitLoadForFrame\n", + descriptionSuitableForTestResult(frame).c_str()); + + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didReceiveTitle( + /* [in] */ IWebView *webView, + /* [in] */ BSTR title, + /* [in] */ IWebFrame *frame) +{ + if (::layoutTestController->dumpTitleChanges() && !done) + printf("TITLE CHANGED: %S\n", title ? title : L""); + return S_OK; +} + +void FrameLoadDelegate::processWork() +{ + // quit doing work once a load is in progress + while (!topLoadingFrame && WorkQueue::shared()->count()) { + WorkQueueItem* item = WorkQueue::shared()->dequeue(); + ASSERT(item); + item->invoke(); + } + + // if we didn't start a new load, then we finished all the commands, so we're ready to dump state + if (!topLoadingFrame && !::layoutTestController->waitToDump()) + dump(); +} + +static void CALLBACK processWorkTimer(HWND, UINT, UINT_PTR id, DWORD) +{ + ::KillTimer(0, id); + FrameLoadDelegate* d = g_delegateWaitingOnTimer; + g_delegateWaitingOnTimer = 0; + d->processWork(); +} + +void FrameLoadDelegate::locationChangeDone(IWebError*, IWebFrame* frame) +{ + if (frame != topLoadingFrame) + return; + + topLoadingFrame = 0; + WorkQueue::shared()->setFrozen(true); + + if (::layoutTestController->waitToDump()) + return; + + if (WorkQueue::shared()->count()) { + ASSERT(!g_delegateWaitingOnTimer); + g_delegateWaitingOnTimer = this; + ::SetTimer(0, 0, 0, processWorkTimer); + return; + } + + dump(); +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didFinishLoadForFrame( + /* [in] */ IWebView* webView, + /* [in] */ IWebFrame* frame) +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didFinishLoadForFrame\n", + descriptionSuitableForTestResult(frame).c_str()); + + locationChangeDone(0, frame); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didFailLoadWithError( + /* [in] */ IWebView* webView, + /* [in] */ IWebError* error, + /* [in] */ IWebFrame* forFrame) +{ + locationChangeDone(error, forFrame); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::willCloseFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didClearWindowObject( + /* [in] */ IWebView*webView, + /* [in] */ JSContextRef context, + /* [in] */ JSObjectRef windowObject, + /* [in] */ IWebFrame* frame) +{ + JSValueRef exception = 0; + + ::layoutTestController->makeWindowObject(context, windowObject, &exception); + ASSERT(!exception); + + m_gcController->makeWindowObject(context, windowObject, &exception); + ASSERT(!exception); + + JSStringRef eventSenderStr = JSStringCreateWithUTF8CString("eventSender"); + JSValueRef eventSender = makeEventSender(context); + JSObjectSetProperty(context, windowObject, eventSenderStr, eventSender, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0); + JSStringRelease(eventSenderStr); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didFinishDocumentLoadForFrame( + /* [in] */ IWebView *sender, + /* [in] */ IWebFrame *frame) +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didFinishDocumentLoadForFrame\n", + descriptionSuitableForTestResult(frame).c_str()); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didHandleOnloadEventsForFrame( + /* [in] */ IWebView *sender, + /* [in] */ IWebFrame *frame) +{ + if (!done && layoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didHandleOnloadEventsForFrame\n", + descriptionSuitableForTestResult(frame).c_str()); + + return S_OK; +} + diff --git a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h new file mode 100644 index 0000000..a2ba647 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. 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. + */ + +#ifndef FrameLoadDelegate_h +#define FrameLoadDelegate_h + +#include <WebKit/WebKit.h> +#include <wtf/OwnPtr.h> + +class GCController; + +class FrameLoadDelegate : public IWebFrameLoadDelegate2, public IWebFrameLoadDelegatePrivate { +public: + FrameLoadDelegate(); + virtual ~FrameLoadDelegate(); + + void processWork(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IWebFrameLoadDelegate + virtual HRESULT STDMETHODCALLTYPE didStartProvisionalLoadForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame); + + virtual HRESULT STDMETHODCALLTYPE didReceiveServerRedirectForProvisionalLoadForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didFailProvisionalLoadWithError( + /* [in] */ IWebView *webView, + /* [in] */ IWebError *error, + /* [in] */ IWebFrame *frame); + + virtual HRESULT STDMETHODCALLTYPE didCommitLoadForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame); + + virtual HRESULT STDMETHODCALLTYPE didReceiveTitle( + /* [in] */ IWebView *webView, + /* [in] */ BSTR title, + /* [in] */ IWebFrame *frame); + + virtual HRESULT STDMETHODCALLTYPE didReceiveIcon( + /* [in] */ IWebView *webView, + /* [in] */ OLE_HANDLE image, + /* [in] */ IWebFrame *frame) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didFinishLoadForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame); + + virtual HRESULT STDMETHODCALLTYPE didFailLoadWithError( + /* [in] */ IWebView *webView, + /* [in] */ IWebError *error, + /* [in] */ IWebFrame *forFrame); + + virtual HRESULT STDMETHODCALLTYPE didChangeLocationWithinPageForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformClientRedirectToURL( + /* [in] */ IWebView *webView, + /* [in] */ BSTR url, + /* [in] */ double delaySeconds, + /* [in] */ DATE fireDate, + /* [in] */ IWebFrame *frame) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didCancelClientRedirectForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willCloseFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame); + + virtual HRESULT STDMETHODCALLTYPE windowScriptObjectAvailable( + /* [in] */ IWebView *sender, + /* [in] */ JSContextRef context, + /* [in] */ JSObjectRef windowObject) { return E_NOTIMPL; } + + // IWebFrameLoadDelegatePrivate + virtual HRESULT STDMETHODCALLTYPE didFinishDocumentLoadForFrame( + /* [in] */ IWebView *sender, + /* [in] */ IWebFrame *frame); + + virtual HRESULT STDMETHODCALLTYPE didFirstLayoutInFrame( + /* [in] */ IWebView *sender, + /* [in] */ IWebFrame *frame) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didHandleOnloadEventsForFrame( + /* [in] */ IWebView *sender, + /* [in] */ IWebFrame *frame); + + // IWebFrameLoadDelegate2 + virtual /* [local] */ HRESULT STDMETHODCALLTYPE didClearWindowObject( + /* [in] */ IWebView* webView, + /* [in] */ JSContextRef context, + /* [in] */ JSObjectRef windowObject, + /* [in] */ IWebFrame* frame); + +protected: + void locationChangeDone(IWebError*, IWebFrame*); + + ULONG m_refCount; + OwnPtr<GCController> m_gcController; +}; + +#endif // FrameLoadDelegate_h diff --git a/WebKitTools/DumpRenderTree/win/GCControllerWin.cpp b/WebKitTools/DumpRenderTree/win/GCControllerWin.cpp new file mode 100644 index 0000000..24392af --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/GCControllerWin.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "GCController.h" + +#include <WebCore/COMPtr.h> +#include <WebKit/WebKit.h> + +void GCController::collect() const +{ + COMPtr<IWebJavaScriptCollector> collector; + if (FAILED(::CoCreateInstance(CLSID_WebJavaScriptCollector, 0, CLSCTX_ALL, IID_IWebJavaScriptCollector, (void**)&collector))) + return; + collector->collect(); +} + +void GCController::collectOnAlternateThread(bool waitUntilDone) const +{ + COMPtr<IWebJavaScriptCollector> collector; + if (FAILED(::CoCreateInstance(CLSID_WebJavaScriptCollector, 0, CLSCTX_ALL, IID_IWebJavaScriptCollector, (void**)&collector))) + return; + collector->collectOnAlternateThread(waitUntilDone ? TRUE : FALSE); +} + +size_t GCController::getJSObjectCount() const +{ + COMPtr<IWebJavaScriptCollector> collector; + if (FAILED(::CoCreateInstance(CLSID_WebJavaScriptCollector, 0, CLSCTX_ALL, IID_IWebJavaScriptCollector, (void**)&collector))) + return 0; + UINT objects = 0; + collector->objectCount(&objects); + return objects; +} diff --git a/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj new file mode 100644 index 0000000..2dc17c5 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="ImageDiff"
+ ProjectGUID="{59CC0547-70AC-499C-9B19-EC01C6F61137}"
+ RootNamespace="ImageDiff"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="CoreGraphics$(LibraryConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ AdditionalLibraryDirectories=""
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\release.vsprops;$(WebKitLibrariesDir)\tools\vsprops\common.vsprops"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include""
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="CoreGraphics$(LibraryConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ AdditionalLibraryDirectories=""
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\cg\ImageDiffCG.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp new file mode 100644 index 0000000..373091b --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp @@ -0,0 +1,563 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "LayoutTestController.h" + +#include "EditingDelegate.h" +#include "PolicyDelegate.h" +#include "WorkQueue.h" +#include "WorkQueueItem.h" +#include <WebCore/COMPtr.h> +#include <wtf/Platform.h> +#include <wtf/RetainPtr.h> +#include <wtf/Vector.h> +#include <JavaScriptCore/Assertions.h> +#include <JavaScriptCore/JavaScriptCore.h> +#include <JavaScriptCore/JSRetainPtr.h> +#include <WebKit/WebKit.h> +#include <string> +#include <CoreFoundation/CoreFoundation.h> +#include <shlwapi.h> +#include <shlguid.h> +#include <shobjidl.h> + +using std::string; +using std::wstring; + +static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath); + +LayoutTestController::~LayoutTestController() +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + // reset webview-related states back to default values in preparation for next test + + COMPtr<IWebViewPrivate> viewPrivate; + if (SUCCEEDED(webView->QueryInterface(&viewPrivate))) + viewPrivate->setTabKeyCyclesThroughElements(TRUE); + + COMPtr<IWebViewEditing> viewEditing; + if (FAILED(webView->QueryInterface(&viewEditing))) + return; + COMPtr<IWebEditingDelegate> delegate; + if (FAILED(viewEditing->editingDelegate(&delegate))) + return; + COMPtr<EditingDelegate> editingDelegate(Query, viewEditing.get()); + if (editingDelegate) + editingDelegate->setAcceptsEditing(TRUE); +} + +void LayoutTestController::addDisallowedURL(JSStringRef url) +{ + // FIXME: Implement! +} + +void LayoutTestController::clearBackForwardList() +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebBackForwardList> backForwardList; + if (FAILED(webView->backForwardList(&backForwardList))) + return; + + COMPtr<IWebHistoryItem> item; + if (FAILED(backForwardList->currentItem(&item))) + return; + + // We clear the history by setting the back/forward list's capacity to 0 + // then restoring it back and adding back the current item. + int capacity; + if (FAILED(backForwardList->capacity(&capacity))) + return; + + backForwardList->setCapacity(0); + backForwardList->setCapacity(capacity); + backForwardList->addItem(item.get()); + backForwardList->goToItem(item.get()); +} + +JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef name) +{ + // FIXME: Implement! + return 0; +} + +JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef name) +{ + // FIXME: Implement! + return 0; +} + +void LayoutTestController::display() +{ + displayWebView(); +} + +void LayoutTestController::keepWebHistory() +{ + COMPtr<IWebHistory> history(Create, CLSID_WebHistory); + if (!history) + return; + + COMPtr<IWebHistory> sharedHistory(Create, CLSID_WebHistory); + if (!sharedHistory) + return; + + history->setOptionalSharedHistory(sharedHistory.get()); +} + +void LayoutTestController::notifyDone() +{ + // Same as on mac. This can be shared. + if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count()) + dump(); + m_waitToDump = false; +} + +JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url) +{ + wstring input(JSStringGetCharactersPtr(url), JSStringGetLength(url)); + + wstring localPath; + if (!resolveCygwinPath(input, localPath)) { + printf("ERROR: Failed to resolve Cygwin path %S\n", input.c_str()); + return 0; + } + + return JSStringCreateWithCharacters(localPath.c_str(), localPath.length()); +} + +void LayoutTestController::queueBackNavigation(int howFarBack) +{ + // Same as on mac. This can be shared. + WorkQueue::shared()->queue(new BackItem(howFarBack)); +} + +void LayoutTestController::queueForwardNavigation(int howFarForward) +{ + // Same as on mac. This can be shared. + WorkQueue::shared()->queue(new ForwardItem(howFarForward)); +} + +static wstring jsStringRefToWString(JSStringRef jsStr) +{ + size_t length = JSStringGetLength(jsStr); + Vector<WCHAR> buffer(length + 1); + memcpy(buffer.data(), JSStringGetCharactersPtr(jsStr), length * sizeof(WCHAR)); + buffer[length] = '\0'; + + return buffer.data(); +} + +void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target) +{ + COMPtr<IWebDataSource> dataSource; + if (FAILED(frame->dataSource(&dataSource))) + return; + + COMPtr<IWebURLResponse> response; + if (FAILED(dataSource->response(&response)) || !response) + return; + + BSTR responseURLBSTR; + if (FAILED(response->URL(&responseURLBSTR))) + return; + wstring responseURL(responseURLBSTR, SysStringLen(responseURLBSTR)); + SysFreeString(responseURLBSTR); + + // FIXME: We should do real relative URL resolution here. + int lastSlash = responseURL.rfind('/'); + if (lastSlash != -1) + responseURL = responseURL.substr(0, lastSlash); + + wstring wURL = jsStringRefToWString(url); + wstring wAbsoluteURL = responseURL + TEXT("/") + wURL; + JSRetainPtr<JSStringRef> jsAbsoluteURL(Adopt, JSStringCreateWithCharacters(wAbsoluteURL.data(), wAbsoluteURL.length())); + + WorkQueue::shared()->queue(new LoadItem(jsAbsoluteURL.get(), target)); +} + +void LayoutTestController::queueReload() +{ + WorkQueue::shared()->queue(new ReloadItem); +} + +void LayoutTestController::queueScript(JSStringRef script) +{ + WorkQueue::shared()->queue(new ScriptItem(script)); +} + +void LayoutTestController::setAcceptsEditing(bool acceptsEditing) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebViewEditing> viewEditing; + if (FAILED(webView->QueryInterface(&viewEditing))) + return; + + COMPtr<IWebEditingDelegate> delegate; + if (FAILED(viewEditing->editingDelegate(&delegate))) + return; + + EditingDelegate* editingDelegate = (EditingDelegate*)(IWebEditingDelegate*)delegate.get(); + editingDelegate->setAcceptsEditing(acceptsEditing); +} + +void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebPreferences> preferences; + if (FAILED(webView->preferences(&preferences))) + return; + + COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences); + if (!prefsPrivate) + return; + + prefsPrivate->setAuthorAndUserStylesEnabled(flag); +} + +void LayoutTestController::setCustomPolicyDelegate(bool setDelegate) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + if (setDelegate) + webView->setPolicyDelegate(policyDelegate); + else + webView->setPolicyDelegate(NULL); +} + +void LayoutTestController::setMainFrameIsFirstResponder(bool flag) +{ + // FIXME: Implement! +} + +void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebPreferences> preferences; + if (FAILED(webView->preferences(&preferences))) + return; + + preferences->setPrivateBrowsingEnabled(privateBrowsingEnabled); +} + +void LayoutTestController::setPopupBlockingEnabled(bool privateBrowsingEnabled) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebPreferences> preferences; + if (FAILED(webView->preferences(&preferences))) + return; + + preferences->setJavaScriptCanOpenWindowsAutomatically(!privateBrowsingEnabled); +} + +void LayoutTestController::setTabKeyCyclesThroughElements(bool shouldCycle) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebViewPrivate> viewPrivate; + if (FAILED(webView->QueryInterface(&viewPrivate))) + return; + + viewPrivate->setTabKeyCyclesThroughElements(shouldCycle ? TRUE : FALSE); +} + +void LayoutTestController::setUseDashboardCompatibilityMode(bool flag) +{ + // FIXME: Implement! +} + +void LayoutTestController::setUserStyleSheetEnabled(bool flag) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebPreferences> preferences; + if (FAILED(webView->preferences(&preferences))) + return; + + preferences->setUserStyleSheetEnabled(flag); +} + +bool appendComponentToPath(wstring& path, const wstring& component) +{ + WCHAR buffer[MAX_PATH]; + + if (path.size() + 1 > MAX_PATH) + return false; + + memcpy(buffer, path.data(), path.size() * sizeof(WCHAR)); + buffer[path.size()] = '\0'; + + if (!PathAppendW(buffer, component.c_str())) + return false; + + path = wstring(buffer); + return true; +} + +static bool followShortcuts(wstring& path) +{ + if (PathFileExists(path.c_str())) + return true; + + // Do we have a shortcut? + path.append(TEXT(".lnk")); + if (!PathFileExists(path.c_str())) + return false; + + // We have a shortcut, find its target. + COMPtr<IShellLink> shortcut(Create, CLSID_ShellLink); + if (!shortcut) + return false; + COMPtr<IPersistFile> persistFile(Query, shortcut); + if (!shortcut) + return false; + if (FAILED(persistFile->Load(path.c_str(), STGM_READ))) + return false; + if (FAILED(shortcut->Resolve(0, 0))) + return false; + WCHAR targetPath[MAX_PATH]; + DWORD targetPathLen = _countof(targetPath); + if (FAILED(shortcut->GetPath(targetPath, targetPathLen, 0, 0))) + return false; + if (!PathFileExists(targetPath)) + return false; + // Use the target path as the result path instead. + path = wstring(targetPath); + + return true; +} + +static bool resolveCygwinPath(const wstring& cygwinPath, wstring& windowsPath) +{ + wstring fileProtocol = L"file://"; + bool isFileProtocol = cygwinPath.find(fileProtocol) != string::npos; + if (cygwinPath[isFileProtocol ? 7 : 0] != '/') // ensure path is absolute + return false; + + // Get the Root path. + WCHAR rootPath[MAX_PATH]; + DWORD rootPathSize = _countof(rootPath); + DWORD keyType; + DWORD result = ::SHGetValueW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/"), TEXT("native"), &keyType, &rootPath, &rootPathSize); + + if (result != ERROR_SUCCESS || keyType != REG_SZ) + return false; + + windowsPath = wstring(rootPath, rootPathSize); + + int oldPos = isFileProtocol ? 8 : 1; + while (1) { + int newPos = cygwinPath.find('/', oldPos); + + if (newPos == -1) { + wstring pathComponent = cygwinPath.substr(oldPos); + + if (!appendComponentToPath(windowsPath, pathComponent)) + return false; + + if (!followShortcuts(windowsPath)) + return false; + + break; + } + + wstring pathComponent = cygwinPath.substr(oldPos, newPos - oldPos); + if (!appendComponentToPath(windowsPath, pathComponent)) + return false; + + if (!followShortcuts(windowsPath)) + return false; + + oldPos = newPos + 1; + } + + if (isFileProtocol) + windowsPath = fileProtocol + windowsPath; + + return true; +} + +static wstring cfStringRefToWString(CFStringRef cfStr) +{ + Vector<wchar_t> v(CFStringGetLength(cfStr)); + CFStringGetCharacters(cfStr, CFRangeMake(0, CFStringGetLength(cfStr)), (UniChar *)v.data()); + + return wstring(v.data(), v.size()); +} + +void LayoutTestController::setUserStyleSheetLocation(JSStringRef jsURL) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebPreferences> preferences; + if (FAILED(webView->preferences(&preferences))) + return; + + RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL)); + RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateWithString(0, urlString.get(), 0)); + if (!url) + return; + + // Now copy the file system path, POSIX style. + RetainPtr<CFStringRef> pathCF(AdoptCF, CFURLCopyFileSystemPath(url.get(), kCFURLPOSIXPathStyle)); + if (!pathCF) + return; + + wstring path = cfStringRefToWString(pathCF.get()); + + wstring resultPath; + if (!resolveCygwinPath(path, resultPath)) + return; + + // The path has been resolved, now convert it back to a CFURL. + int result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, 0, 0, 0, 0); + Vector<char> utf8Vector(result); + result = WideCharToMultiByte(CP_UTF8, 0, resultPath.c_str(), resultPath.size() + 1, utf8Vector.data(), result, 0, 0); + if (!result) + return; + + url = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)utf8Vector.data(), utf8Vector.size() - 1, false); + if (!url) + return; + + resultPath = cfStringRefToWString(CFURLGetString(url.get())); + + BSTR resultPathBSTR = SysAllocStringLen(resultPath.data(), resultPath.size()); + preferences->setUserStyleSheetLocation(resultPathBSTR); + SysFreeString(resultPathBSTR); +} + +void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL) +{ + RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL)); + ::setPersistentUserStyleSheetLocation(urlString.get()); +} + +void LayoutTestController::clearPersistentUserStyleSheet() +{ + ::setPersistentUserStyleSheetLocation(0); +} + +void LayoutTestController::setWindowIsKey(bool flag) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebViewPrivate> viewPrivate; + if (FAILED(webView->QueryInterface(&viewPrivate))) + return; + + HWND webViewWindow; + if (FAILED(viewPrivate->viewWindow((OLE_HANDLE*)&webViewWindow))) + return; + + ::SendMessage(webViewWindow, flag ? WM_SETFOCUS : WM_KILLFOCUS, (WPARAM)::GetDesktopWindow(), 0); +} + +static const CFTimeInterval waitToDumpWatchdogInterval = 10.0; + +static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info) +{ + const char* message = "FAIL: Timed out waiting for notifyDone to be called\n"; + fprintf(stderr, message); + fprintf(stdout, message); + dump(); +} + +void LayoutTestController::setWaitToDump(bool waitUntilDone) +{ + // Same as on mac. This can be shared. + m_waitToDump = waitUntilDone; + if (m_waitToDump && !waitToDumpWatchdog) { + waitToDumpWatchdog = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + waitToDumpWatchdogInterval, 0, 0, 0, waitUntilDoneWatchdogFired, NULL); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), waitToDumpWatchdog, kCFRunLoopCommonModes); + } +} + +int LayoutTestController::windowCount() +{ + return openWindows().size(); +} + +void LayoutTestController::execCommand(JSStringRef name, JSStringRef value) +{ + wstring wName = jsStringRefToWString(name); + wstring wValue = jsStringRefToWString(value); + + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebViewPrivate> viewPrivate; + if (FAILED(webView->QueryInterface(&viewPrivate))) + return; + + BSTR nameBSTR = SysAllocStringLen((OLECHAR*)wName.c_str(), wName.length()); + BSTR valueBSTR = SysAllocStringLen((OLECHAR*)wValue.c_str(), wValue.length()); + viewPrivate->executeCoreCommandByName(nameBSTR, valueBSTR); + + SysFreeString(nameBSTR); + SysFreeString(valueBSTR); +} + +void LayoutTestController::clearAllDatabases() +{ + printf("ERROR: LayoutTestController::clearAllDatabases() not implemented\n"); +} + +void LayoutTestController::setDatabaseQuota(unsigned long long quota) +{ + printf("ERROR: LayoutTestController::setDatabaseQuota() not implemented\n"); +} diff --git a/WebKitTools/DumpRenderTree/win/MD5.cpp b/WebKitTools/DumpRenderTree/win/MD5.cpp new file mode 100644 index 0000000..4d4c848 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/MD5.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007 Apple, Inc. 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. + */ + +#include "MD5.h" + +#include <windows.h> + +typedef void (WINAPI*initPtr)(MD5_CTX*); +typedef void (WINAPI*updatePtr)(MD5_CTX*, unsigned char*, unsigned); +typedef void (WINAPI*finalPtr)(MD5_CTX*); + +static HMODULE cryptDLL() +{ + static HMODULE module = LoadLibraryW(L"Cryptdll.dll"); + return module; +} + +static initPtr init() +{ + static initPtr ptr = reinterpret_cast<initPtr>(GetProcAddress(cryptDLL(), "MD5Init")); + return ptr; +} + +static updatePtr update() +{ + static updatePtr ptr = reinterpret_cast<updatePtr>(GetProcAddress(cryptDLL(), "MD5Update")); + return ptr; +} + +static finalPtr final() +{ + static finalPtr ptr = reinterpret_cast<finalPtr>(GetProcAddress(cryptDLL(), "MD5Final")); + return ptr; +} + +void MD5_Init(MD5_CTX* context) +{ + init()(context); +} + +void MD5_Update(MD5_CTX* context, unsigned char* input, unsigned length) +{ + update()(context, input, length); +} + +void MD5_Final(unsigned char hash[16], MD5_CTX* context) +{ + final()(context); + + for (int i = 0; i < 16; ++i) + hash[i] = context->digest[i]; +} diff --git a/WebKitTools/DumpRenderTree/win/MD5.h b/WebKitTools/DumpRenderTree/win/MD5.h new file mode 100644 index 0000000..326e21d --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/MD5.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007 Apple, Inc. 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. + */ + +#ifndef MD5_h +#define MD5_h + +typedef unsigned long ULONG; + +struct MD5_CTX { + ULONG i[2]; + ULONG buf[4]; + unsigned char in[64]; + unsigned char digest[16]; +}; + +void MD5_Init(MD5_CTX*); +void MD5_Update(MD5_CTX*, unsigned char* input, unsigned length); +void MD5_Final(unsigned char hash[16], MD5_CTX*); + +#endif // MD5_h diff --git a/WebKitTools/DumpRenderTree/win/PixelDumpSupportWin.cpp b/WebKitTools/DumpRenderTree/win/PixelDumpSupportWin.cpp new file mode 100644 index 0000000..f6dd82d --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/PixelDumpSupportWin.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007 Apple, Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "PixelDumpSupportCG.h" + +#include <CoreGraphics/CGBitmapContext.h> +#include <wtf/Assertions.h> +#include <wtf/RetainPtr.h> + +RetainPtr<CGContextRef> getBitmapContextFromWebView() +{ + RECT frame; + if (!GetWindowRect(webViewWindow, &frame)) + return 0; + + BITMAPINFO bmp = {0}; + bmp.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp.bmiHeader.biWidth = frame.right - frame.left; + bmp.bmiHeader.biHeight = -(frame.bottom - frame.top); + bmp.bmiHeader.biPlanes = 1; + bmp.bmiHeader.biBitCount = 32; + bmp.bmiHeader.biCompression = BI_RGB; + + // FIXME: Currently we leak this HBITMAP because we don't have a good way + // to destroy it when the CGBitmapContext gets destroyed. + void* bits = 0; + HBITMAP bitmap = CreateDIBSection(0, &bmp, DIB_RGB_COLORS, &bits, 0, 0); + + HDC memoryDC = CreateCompatibleDC(0); + SelectObject(memoryDC, bitmap); + SendMessage(webViewWindow, WM_PRINTCLIENT, reinterpret_cast<WPARAM>(memoryDC), PRF_CLIENT | PRF_CHILDREN | PRF_OWNED); + DeleteDC(memoryDC); + + BITMAP info = {0}; + GetObject(bitmap, sizeof(info), &info); + ASSERT(info.bmBitsPixel == 32); + + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); + return RetainPtr<CGContextRef>(AdoptCF, CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8, + info.bmWidthBytes, colorSpace.get(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst)); +} diff --git a/WebKitTools/DumpRenderTree/win/PolicyDelegate.cpp b/WebKitTools/DumpRenderTree/win/PolicyDelegate.cpp new file mode 100644 index 0000000..c6a9fb0 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/PolicyDelegate.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "PolicyDelegate.h" + +#include <string> + +using std::wstring; + +PolicyDelegate::PolicyDelegate() + : m_refCount(1) +{ +} + +// IUnknown +HRESULT STDMETHODCALLTYPE PolicyDelegate::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebPolicyDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebPolicyDelegate)) + *ppvObject = static_cast<IWebPolicyDelegate*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE PolicyDelegate::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE PolicyDelegate::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete this; + + return newRef; +} + +HRESULT STDMETHODCALLTYPE PolicyDelegate::decidePolicyForNavigationAction( + /*[in]*/ IWebView* /*webView*/, + /*[in]*/ IPropertyBag* /*actionInformation*/, + /*[in]*/ IWebURLRequest* request, + /*[in]*/ IWebFrame* frame, + /*[in]*/ IWebPolicyDecisionListener* listener) +{ + BSTR url; + request->URL(&url); + + printf("Policy delegate: attempt to load %S\n", url ? url : TEXT("")); + SysFreeString(url); + listener->ignore(); + + return S_OK; +} diff --git a/WebKitTools/DumpRenderTree/win/PolicyDelegate.h b/WebKitTools/DumpRenderTree/win/PolicyDelegate.h new file mode 100644 index 0000000..b9844f4 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/PolicyDelegate.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef PolicyDelegate_h +#define PolicyDelegate_h + +#include <WebKit/WebKit.h> + +class PolicyDelegate : public IWebPolicyDelegate { +public: + PolicyDelegate(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IWebPolicyDelegate + virtual HRESULT STDMETHODCALLTYPE decidePolicyForNavigationAction( + /* [in] */ IWebView *webView, + /* [in] */ IPropertyBag *actionInformation, + /* [in] */ IWebURLRequest *request, + /* [in] */ IWebFrame *frame, + /* [in] */ IWebPolicyDecisionListener *listener); + + virtual HRESULT STDMETHODCALLTYPE decidePolicyForNewWindowAction( + /* [in] */ IWebView *webView, + /* [in] */ IPropertyBag *actionInformation, + /* [in] */ IWebURLRequest *request, + /* [in] */ BSTR frameName, + /* [in] */ IWebPolicyDecisionListener *listener){ return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE decidePolicyForMIMEType( + /* [in] */ IWebView *webView, + /* [in] */ BSTR type, + /* [in] */ IWebURLRequest *request, + /* [in] */ IWebFrame *frame, + /* [in] */ IWebPolicyDecisionListener *listener){ return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE unableToImplementPolicyWithError( + /* [in] */ IWebView *webView, + /* [in] */ IWebError *error, + /* [in] */ IWebFrame *frame){ return E_NOTIMPL; } + +private: + ULONG m_refCount; +}; + +#endif // PolicyDelegate_h diff --git a/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp b/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp new file mode 100644 index 0000000..0f15648 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "ResourceLoadDelegate.h" + +#include "LayoutTestController.h" +#include <wtf/HashMap.h> +#include <wtf/Vector.h> +#include <sstream> + +using std::wstring; +using std::wiostream; + +static inline wstring wstringFromBSTR(BSTR str) +{ + return wstring(str, ::SysStringLen(str)); +} + +wstring wstringFromInt(int i) +{ + std::wostringstream ss; + ss << i; + return ss.str(); +} + +typedef HashMap<unsigned long, wstring> IdentifierMap; + +IdentifierMap& urlMap() +{ + static IdentifierMap urlMap; + + return urlMap; +} + +static wstring descriptionSuitableForTestResult(unsigned long identifier) +{ + IdentifierMap::iterator it = urlMap().find(identifier); + + if (it == urlMap().end()) + return L"<unknown>"; + + return urlSuitableForTestResult(it->second); +} + +static wstring descriptionSuitableForTestResult(IWebURLRequest* request) +{ + if (!request) + return L"(null)"; + + BSTR urlBSTR; + if (FAILED(request->URL(&urlBSTR))) + return wstring(); + + wstring url = urlSuitableForTestResult(wstringFromBSTR(urlBSTR)); + ::SysFreeString(urlBSTR); + + return L"<NSURLRequest " + url + L">"; +} + +static wstring descriptionSuitableForTestResult(IWebURLResponse* response) +{ + if (!response) + return L"(null)"; + + BSTR urlBSTR; + if (FAILED(response->URL(&urlBSTR))) + return wstring(); + + wstring url = urlSuitableForTestResult(wstringFromBSTR(urlBSTR)); + ::SysFreeString(urlBSTR); + + return L"<NSURLResponse " + url + L">"; +} + +static wstring descriptionSuitableForTestResult(IWebError* error, unsigned long identifier) +{ + wstring result = L"<NSError "; + + BSTR domainSTR; + if (FAILED(error->domain(&domainSTR))) + return wstring(); + + wstring domain = wstringFromBSTR(domainSTR); + ::SysFreeString(domainSTR); + + int code; + if (FAILED(error->code(&code))) + return wstring(); + + if (domain == L"CFURLErrorDomain") { + domain = L"NSURLErrorDomain"; + + // Convert kCFURLErrorUnknown to NSURLErrorUnknown + if (code == -998) + code = -1; + } else if (domain == L"kCFErrorDomainWinSock") { + domain = L"NSURLErrorDomain"; + + // Convert the winsock error code to an NSURLError code. + if (code == WSAEADDRNOTAVAIL) + code = -1004; // NSURLErrorCannotConnectToHose; + } + + result += L"domain " + domain; + result += L", code " + wstringFromInt(code); + + BSTR failingURLSTR; + if (FAILED(error->failingURL(&failingURLSTR))) + return wstring(); + + wstring failingURL; + + // If the error doesn't have a failing URL, we fake one by using the URL the resource had + // at creation time. This seems to work fine for now. + // See <rdar://problem/5064234> CFErrors should have failingURL key. + if (failingURLSTR) + failingURL = wstringFromBSTR(failingURLSTR); + else + failingURL = descriptionSuitableForTestResult(identifier); + + ::SysFreeString(failingURLSTR); + + result += L", failing URL \"" + urlSuitableForTestResult(failingURL) + L"\">"; + + return result; +} + +ResourceLoadDelegate::ResourceLoadDelegate() + : m_refCount(1) +{ +} + +ResourceLoadDelegate::~ResourceLoadDelegate() +{ +} + +HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebResourceLoadDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebResourceLoadDelegate)) + *ppvObject = static_cast<IWebResourceLoadDelegate*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE ResourceLoadDelegate::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE ResourceLoadDelegate::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + +HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::identifierForInitialRequest( + /* [in] */ IWebView* webView, + /* [in] */ IWebURLRequest* request, + /* [in] */ IWebDataSource* dataSource, + /* [in] */ unsigned long identifier) +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + BSTR urlStr; + if (FAILED(request->URL(&urlStr))) + return E_FAIL; + + urlMap().set(identifier, wstringFromBSTR(urlStr)); + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::willSendRequest( + /* [in] */ IWebView* webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebURLRequest* request, + /* [in] */ IWebURLResponse* redirectResponse, + /* [in] */ IWebDataSource* dataSource, + /* [retval][out] */ IWebURLRequest **newRequest) +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + printf("%S - willSendRequest %S redirectResponse %S\n", + descriptionSuitableForTestResult(identifier).c_str(), + descriptionSuitableForTestResult(request).c_str(), + descriptionSuitableForTestResult(redirectResponse).c_str()); + } + + request->AddRef(); + *newRequest = request; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::didFinishLoadingFromDataSource( + /* [in] */ IWebView* webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebDataSource* dataSource) +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + printf("%S - didFinishLoading\n", + descriptionSuitableForTestResult(identifier).c_str()), + urlMap().remove(identifier); + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::didFailLoadingWithError( + /* [in] */ IWebView* webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebError* error, + /* [in] */ IWebDataSource* dataSource) +{ + if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + printf("%S - didFailLoadingWithError: %S\n", + descriptionSuitableForTestResult(identifier).c_str(), + descriptionSuitableForTestResult(error, identifier).c_str()); + urlMap().remove(identifier); + } + + return S_OK; +} diff --git a/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.h b/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.h new file mode 100644 index 0000000..e259adc --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#ifndef ResourceLoadDelegate_h +#define ResourceLoadDelegate_h + +#include <WebKit/WebKit.h> + +class ResourceLoadDelegate : public IWebResourceLoadDelegate { +public: + ResourceLoadDelegate(); + virtual ~ResourceLoadDelegate(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IWebResourceLoadDelegate + virtual HRESULT STDMETHODCALLTYPE identifierForInitialRequest( + /* [in] */ IWebView *webView, + /* [in] */ IWebURLRequest *request, + /* [in] */ IWebDataSource *dataSource, + /* [in] */ unsigned long identifier); + + virtual HRESULT STDMETHODCALLTYPE willSendRequest( + /* [in] */ IWebView *webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebURLRequest *request, + /* [in] */ IWebURLResponse *redirectResponse, + /* [in] */ IWebDataSource *dataSource, + /* [retval][out] */ IWebURLRequest **newRequest); + + virtual HRESULT STDMETHODCALLTYPE didReceiveAuthenticationChallenge( + /* [in] */ IWebView *webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebURLAuthenticationChallenge *challenge, + /* [in] */ IWebDataSource *dataSource) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didCancelAuthenticationChallenge( + /* [in] */ IWebView *webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebURLAuthenticationChallenge *challenge, + /* [in] */ IWebDataSource *dataSource) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didReceiveResponse( + /* [in] */ IWebView *webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebURLResponse *response, + /* [in] */ IWebDataSource *dataSource) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didReceiveContentLength( + /* [in] */ IWebView *webView, + /* [in] */ unsigned long identifier, + /* [in] */ UINT length, + /* [in] */ IWebDataSource *dataSource) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE didFinishLoadingFromDataSource( + /* [in] */ IWebView *webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebDataSource *dataSource); + + virtual HRESULT STDMETHODCALLTYPE didFailLoadingWithError( + /* [in] */ IWebView *webView, + /* [in] */ unsigned long identifier, + /* [in] */ IWebError *error, + /* [in] */ IWebDataSource *dataSource); + + virtual HRESULT STDMETHODCALLTYPE plugInFailedWithError( + /* [in] */ IWebView *webView, + /* [in] */ IWebError *error, + /* [in] */ IWebDataSource *dataSource) { return E_NOTIMPL; } + +protected: + ULONG m_refCount; +}; + +#endif // ResourceLoadDelegate_h diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.def b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.def new file mode 100644 index 0000000..92cdb12 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.def @@ -0,0 +1,6 @@ +LIBRARY "TestNetscapePlugin"
+
+EXPORTS
+ NP_GetEntryPoints @1
+ NP_Initialize @2
+ NP_Shutdown @3
diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc new file mode 100644 index 0000000..7801de9 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc @@ -0,0 +1,101 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Apple Inc."
+ VALUE "FileDescription", "TestNetscapePlugIn"
+ VALUE "FileOpenName", "test netscape content"
+ VALUE "LegalCopyright", "Copyright Apple Inc. 2007-2008"
+ VALUE "MIMEType", "application/x-webkit-test-netscape"
+ VALUE "OriginalFilename", "npTestNetscapePlugin.dll"
+ VALUE "ProductName", "TestNetscapePlugIn"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj new file mode 100644 index 0000000..0bc77f6 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj @@ -0,0 +1,257 @@ +<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="TestNetscapePlugin"
+ ProjectGUID="{C0737398-3565-439E-A2B8-AB2BE4D5430C}"
+ RootNamespace="TestNetscapePlugin"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj""
+ PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix)\np$(ProjectName)$(WebKitConfigSuffix).dll"
+ ModuleDefinitionFile="TestNetscapePlugin.def"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj""
+ PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix)\np$(ProjectName)$(WebKitConfigSuffix).dll"
+ ModuleDefinitionFile="TestNetscapePlugin.def"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_Internal|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj""
+ PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
+ RuntimeLibrary="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix)\np$(ProjectName)$(WebKitConfigSuffix).dll"
+ ModuleDefinitionFile="TestNetscapePlugin.def"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\main.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\TestNetscapePlugIn.subproj\PluginObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\TestNetscapePlugIn.subproj\PluginObject.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\TestNetscapePlugin.def"
+ >
+ </File>
+ <File
+ RelativePath=".\TestNetscapePlugin.rc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\TestNetscapePlugIn.subproj\TestObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\TestNetscapePlugIn.subproj\TestObject.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.c b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.c new file mode 100644 index 0000000..829a32c --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#include "PluginObject.h" + +#include <stdio.h> + +extern "C" +NPError __stdcall NP_Initialize(NPNetscapeFuncs* browserFuncs) +{ + browser = browserFuncs; + return NPERR_NO_ERROR; +} + +extern "C" +NPError __stdcall NP_GetEntryPoints(NPPluginFuncs* pluginFuncs) +{ + pluginFuncs->version = 11; + pluginFuncs->size = sizeof(pluginFuncs); + pluginFuncs->newp = NPP_New; + pluginFuncs->destroy = NPP_Destroy; + pluginFuncs->setwindow = NPP_SetWindow; + pluginFuncs->newstream = NPP_NewStream; + pluginFuncs->destroystream = NPP_DestroyStream; + pluginFuncs->asfile = NPP_StreamAsFile; + pluginFuncs->writeready = NPP_WriteReady; + pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; + pluginFuncs->print = NPP_Print; + pluginFuncs->event = NPP_HandleEvent; + pluginFuncs->urlnotify = NPP_URLNotify; + pluginFuncs->getvalue = NPP_GetValue; + pluginFuncs->setvalue = NPP_SetValue; + + return NPERR_NO_ERROR; +} + + +extern "C" +NPError __stdcall NP_Shutdown() +{ + return NPERR_NO_ERROR; +} + + +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) +{ + if (browser->version >= 14) { + PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass()); + + obj->onStreamLoad = NULL; + + for (int16 i = 0; i < argc; i++) { + if (_stricmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad) + obj->onStreamLoad = _strdup(argv[i]); + } + + instance->pdata = obj; + } + + return NPERR_NO_ERROR; +} + +NPError NPP_Destroy(NPP instance, NPSavedData **save) +{ + PluginObject *obj = (PluginObject*)instance->pdata; + if (obj) { + if (obj->onStreamLoad) + free(obj->onStreamLoad); + + if (obj->logDestroy) + printf("PLUGIN: NPP_Destroy\n"); + + browser->releaseobject(&obj->header); + } + return NPERR_NO_ERROR; +} + +NPError NPP_SetWindow(NPP instance, NPWindow *window) +{ + return NPERR_NO_ERROR; +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) +{ + PluginObject* obj = (PluginObject*)instance->pdata; + obj->stream = stream; + *stype = NP_ASFILEONLY; + + if (obj->onStreamLoad) { + NPObject *windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPString script; + script.UTF8Characters = obj->onStreamLoad; + script.UTF8Length = strlen(obj->onStreamLoad); + + NPVariant browserResult; + browser->evaluate(obj->npp, windowScriptObject, &script, &browserResult); + browser->releasevariantvalue(&browserResult); + } + + return NPERR_NO_ERROR; +} + +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) +{ + return NPERR_NO_ERROR; +} + +int32 NPP_WriteReady(NPP instance, NPStream *stream) +{ + return 0; +} + +int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) +{ + return 0; +} + +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) +{ +} + +void NPP_Print(NPP instance, NPPrint *platformPrint) +{ +} + +int16 NPP_HandleEvent(NPP instance, void *event) +{ + PluginObject *obj = (PluginObject*)instance->pdata; + if (!obj->eventLogging) + return 0; + + // FIXME: Implement this + return 0; +} + +void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData) +{ + PluginObject *obj = (PluginObject*)instance->pdata; + + handleCallback(obj, url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) +{ + if (variable == NPPVpluginScriptableNPObject) { + void **v = (void **)value; + PluginObject *obj = (PluginObject*)instance->pdata; + // Return value is expected to be retained + browser->retainobject((NPObject *)obj); + *v = obj; + return NPERR_NO_ERROR; + } + return NPERR_GENERIC_ERROR; +} + +NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) +{ + return NPERR_GENERIC_ERROR; +} diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp new file mode 100644 index 0000000..8c542ed --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp @@ -0,0 +1,191 @@ +/* + IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in + consideration of your agreement to the following terms, and your use, installation, + modification or redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject to these + terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in + this original Apple software (the "Apple Software"), to use, reproduce, modify and + redistribute the Apple Software, with or without modifications, in source and/or binary + forms; provided that if you redistribute the Apple Software in its entirety and without + modifications, you must retain this notice and the following text and disclaimers in all + such redistributions of the Apple Software. Neither the name, trademarks, service marks + or logos of Apple Computer, Inc. may be used to endorse or promote products derived from + the Apple Software without specific prior written permission from Apple. Except as expressly + stated in this notice, no other rights or licenses, express or implied, are granted by Apple + herein, including but not limited to any patent rights that may be infringed by your + derivative works or by other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, + EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS + USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, + REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND + WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR + OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginObject.h" + +#include <stdio.h> + +extern "C" +NPError __stdcall NP_Initialize(NPNetscapeFuncs* browserFuncs) +{ + browser = browserFuncs; + return NPERR_NO_ERROR; +} + +extern "C" +NPError __stdcall NP_GetEntryPoints(NPPluginFuncs* pluginFuncs) +{ + pluginFuncs->version = 11; + pluginFuncs->size = sizeof(pluginFuncs); + pluginFuncs->newp = NPP_New; + pluginFuncs->destroy = NPP_Destroy; + pluginFuncs->setwindow = NPP_SetWindow; + pluginFuncs->newstream = NPP_NewStream; + pluginFuncs->destroystream = NPP_DestroyStream; + pluginFuncs->asfile = NPP_StreamAsFile; + pluginFuncs->writeready = NPP_WriteReady; + pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; + pluginFuncs->print = NPP_Print; + pluginFuncs->event = NPP_HandleEvent; + pluginFuncs->urlnotify = NPP_URLNotify; + pluginFuncs->getvalue = NPP_GetValue; + pluginFuncs->setvalue = NPP_SetValue; + + return NPERR_NO_ERROR; +} + + +extern "C" +NPError __stdcall NP_Shutdown() +{ + return NPERR_NO_ERROR; +} + + +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) +{ + if (browser->version >= 14) { + PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass()); + + obj->onStreamLoad = NULL; + + for (int16 i = 0; i < argc; i++) { + if (_stricmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad) + obj->onStreamLoad = _strdup(argv[i]); + } + + instance->pdata = obj; + } + + return NPERR_NO_ERROR; +} + +NPError NPP_Destroy(NPP instance, NPSavedData **save) +{ + PluginObject *obj = (PluginObject*)instance->pdata; + if (obj) { + if (obj->onStreamLoad) + free(obj->onStreamLoad); + + if (obj->logDestroy) + printf("PLUGIN: NPP_Destroy\n"); + + browser->releaseobject(&obj->header); + } + return NPERR_NO_ERROR; +} + +NPError NPP_SetWindow(NPP instance, NPWindow *window) +{ + return NPERR_NO_ERROR; +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) +{ + PluginObject* obj = (PluginObject*)instance->pdata; + obj->stream = stream; + *stype = NP_ASFILEONLY; + + if (obj->onStreamLoad) { + NPObject *windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPString script; + script.UTF8Characters = obj->onStreamLoad; + script.UTF8Length = strlen(obj->onStreamLoad); + + NPVariant browserResult; + browser->evaluate(obj->npp, windowScriptObject, &script, &browserResult); + browser->releasevariantvalue(&browserResult); + } + + return NPERR_NO_ERROR; +} + +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) +{ + return NPERR_NO_ERROR; +} + +int32 NPP_WriteReady(NPP instance, NPStream *stream) +{ + return 0; +} + +int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) +{ + return 0; +} + +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) +{ +} + +void NPP_Print(NPP instance, NPPrint *platformPrint) +{ +} + +int16 NPP_HandleEvent(NPP instance, void *event) +{ + PluginObject *obj = (PluginObject*)instance->pdata; + if (!obj->eventLogging) + return 0; + + // FIXME: Implement this + return 0; +} + +void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData) +{ + PluginObject *obj = (PluginObject*)instance->pdata; + + handleCallback(obj, url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) +{ + if (variable == NPPVpluginScriptableNPObject) { + void **v = (void **)value; + PluginObject *obj = (PluginObject*)instance->pdata; + // Return value is expected to be retained + browser->retainobject((NPObject *)obj); + *v = obj; + return NPERR_NO_ERROR; + } + return NPERR_GENERIC_ERROR; +} + +NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) +{ + return NPERR_GENERIC_ERROR; +} diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/resource.h b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/resource.h new file mode 100644 index 0000000..b0ce340 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TestNetscapePlugin.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/WebKitTools/DumpRenderTree/win/UIDelegate.cpp b/WebKitTools/DumpRenderTree/win/UIDelegate.cpp new file mode 100755 index 0000000..a0362c3 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/UIDelegate.cpp @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "UIDelegate.h" + +#include "DraggingInfo.h" +#include "EventSender.h" +#include "LayoutTestController.h" + +#include <WebCore/COMPtr.h> +#include <wtf/Platform.h> +#include <wtf/Vector.h> +#include <JavaScriptCore/Assertions.h> +#include <JavaScriptCore/JavaScriptCore.h> +#include <WebKit/WebKit.h> +#include <stdio.h> + +using std::wstring; + +class DRTUndoObject { +public: + DRTUndoObject(IWebUndoTarget* target, BSTR actionName, IUnknown* obj) + : m_target(target) + , m_actionName(SysAllocString(actionName)) + , m_obj(obj) + { + } + + ~DRTUndoObject() + { + SysFreeString(m_actionName); + } + + void invoke() + { + m_target->invoke(m_actionName, m_obj.get()); + } + +private: + IWebUndoTarget* m_target; + BSTR m_actionName; + COMPtr<IUnknown> m_obj; +}; + +class DRTUndoStack { +public: + ~DRTUndoStack() { deleteAllValues(m_undoVector); } + + bool isEmpty() const { return m_undoVector.isEmpty(); } + void clear() { deleteAllValues(m_undoVector); m_undoVector.clear(); } + + void push(DRTUndoObject* undoObject) { m_undoVector.append(undoObject); } + DRTUndoObject* pop() { DRTUndoObject* top = m_undoVector.last(); m_undoVector.removeLast(); return top; } + +private: + Vector<DRTUndoObject*> m_undoVector; +}; + +class DRTUndoManager { +public: + DRTUndoManager(); + + void removeAllActions(); + void registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj); + void redo(); + void undo(); + bool canRedo() { return !m_redoStack->isEmpty(); } + bool canUndo() { return !m_undoStack->isEmpty(); } + +private: + OwnPtr<DRTUndoStack> m_redoStack; + OwnPtr<DRTUndoStack> m_undoStack; + bool m_isRedoing; + bool m_isUndoing; +}; + +DRTUndoManager::DRTUndoManager() + : m_redoStack(new DRTUndoStack) + , m_undoStack(new DRTUndoStack) + , m_isRedoing(false) + , m_isUndoing(false) +{ +} + +void DRTUndoManager::removeAllActions() +{ + m_redoStack->clear(); + m_undoStack->clear(); +} + +void DRTUndoManager::registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj) +{ + if (!m_isUndoing && !m_isRedoing) + m_redoStack->clear(); + + DRTUndoStack* stack = m_isUndoing ? m_redoStack.get() : m_undoStack.get(); + stack->push(new DRTUndoObject(target, actionName, obj)); +} + +void DRTUndoManager::redo() +{ + if (!canRedo()) + return; + + m_isRedoing = true; + + DRTUndoObject* redoObject = m_redoStack->pop(); + redoObject->invoke(); + delete redoObject; + + m_isRedoing = false; +} + +void DRTUndoManager::undo() +{ + if (!canUndo()) + return; + + m_isUndoing = true; + + DRTUndoObject* undoObject = m_undoStack->pop(); + undoObject->invoke(); + delete undoObject; + + m_isUndoing = false; +} + +UIDelegate::UIDelegate() + : m_refCount(1) + , m_undoManager(new DRTUndoManager) +{ + m_frame.bottom = 0; + m_frame.top = 0; + m_frame.left = 0; + m_frame.right = 0; +} + +void UIDelegate::resetUndoManager() +{ + m_undoManager.set(new DRTUndoManager); +} + +HRESULT STDMETHODCALLTYPE UIDelegate::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebUIDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebUIDelegate)) + *ppvObject = static_cast<IWebUIDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate)) + *ppvObject = static_cast<IWebUIDelegatePrivate*>(this); + else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate2)) + *ppvObject = static_cast<IWebUIDelegatePrivate2*>(this); + else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate3)) + *ppvObject = static_cast<IWebUIDelegatePrivate3*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE UIDelegate::AddRef() +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE UIDelegate::Release() +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::hasCustomMenuImplementation( + /* [retval][out] */ BOOL *hasCustomMenus) +{ + *hasCustomMenus = TRUE; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::trackCustomPopupMenu( + /* [in] */ IWebView *sender, + /* [in] */ OLE_HANDLE menu, + /* [in] */ LPPOINT point) +{ + // Do nothing + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::registerUndoWithTarget( + /* [in] */ IWebUndoTarget* target, + /* [in] */ BSTR actionName, + /* [in] */ IUnknown* actionArg) +{ + m_undoManager->registerUndoWithTarget(target, actionName, actionArg); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::removeAllActionsWithTarget( + /* [in] */ IWebUndoTarget*) +{ + m_undoManager->removeAllActions(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::setActionTitle( + /* [in] */ BSTR actionTitle) +{ + // It is not neccessary to implement this for DRT because there is + // menu to write out the title to. + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::undo() +{ + m_undoManager->undo(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::redo() +{ + m_undoManager->redo(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::canUndo( + /* [retval][out] */ BOOL* result) +{ + if (!result) + return E_POINTER; + + *result = m_undoManager->canUndo(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::canRedo( + /* [retval][out] */ BOOL* result) +{ + if (!result) + return E_POINTER; + + *result = m_undoManager->canRedo(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::setFrame( + /* [in] */ IWebView* /*sender*/, + /* [in] */ RECT* frame) +{ + m_frame = *frame; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::webViewFrame( + /* [in] */ IWebView* /*sender*/, + /* [retval][out] */ RECT* frame) +{ + *frame = m_frame; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptAlertPanelWithMessage( + /* [in] */ IWebView* /*sender*/, + /* [in] */ BSTR message) +{ + printf("ALERT: %S\n", message ? message : L""); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptConfirmPanelWithMessage( + /* [in] */ IWebView* sender, + /* [in] */ BSTR message, + /* [retval][out] */ BOOL* result) +{ + printf("CONFIRM: %S\n", message ? message : L""); + *result = TRUE; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptTextInputPanelWithPrompt( + /* [in] */ IWebView *sender, + /* [in] */ BSTR message, + /* [in] */ BSTR defaultText, + /* [retval][out] */ BSTR *result) +{ + printf("PROMPT: %S, default text: %S\n", message ? message : L"", defaultText ? defaultText : L""); + *result = SysAllocString(defaultText); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::webViewAddMessageToConsole( + /* [in] */ IWebView* sender, + /* [in] */ BSTR message, + /* [in] */ int lineNumber, + /* [in] */ BSTR url, + /* [in] */ BOOL isError) +{ + wstring newMessage; + if (message) { + newMessage = message; + size_t fileProtocol = newMessage.find(L"file://"); + if (fileProtocol != wstring::npos) + newMessage = newMessage.substr(0, fileProtocol) + urlSuitableForTestResult(newMessage.substr(fileProtocol)); + } + + printf("CONSOLE MESSAGE: line %d: %S\n", lineNumber, newMessage.c_str()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::doDragDrop( + /* [in] */ IWebView* sender, + /* [in] */ IDataObject* object, + /* [in] */ IDropSource* source, + /* [in] */ DWORD okEffect, + /* [retval][out] */ DWORD* performedEffect) +{ + if (!performedEffect) + return E_POINTER; + + *performedEffect = 0; + + draggingInfo = new DraggingInfo(object, source); + replaySavedEvents(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::webViewGetDlgCode( + /* [in] */ IWebView* /*sender*/, + /* [in] */ UINT /*keyCode*/, + /* [retval][out] */ LONG_PTR *code) +{ + if (!code) + return E_POINTER; + *code = 0; + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest( + /* [in] */ IWebView *sender, + /* [in] */ IWebURLRequest *request, + /* [retval][out] */ IWebView **newWebView) +{ + if (!::layoutTestController->canOpenWindows()) + return E_FAIL; + *newWebView = createWebViewAndOffscreenWindow(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::webViewClose( + /* [in] */ IWebView *sender) +{ + HWND hostWindow; + sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow)); + DestroyWindow(hostWindow); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::webViewPainted( + /* [in] */ IWebView *sender) +{ + return S_OK; +} + +HRESULT STDMETHODCALLTYPE UIDelegate::exceededDatabaseQuota( + /* [in] */ IWebView *sender, + /* [in] */ IWebFrame *frame, + /* [in] */ IWebSecurityOrigin *origin, + /* [in] */ BSTR databaseIdentifier) +{ + static const unsigned long long defaultQuota = 5 * 1024 * 1024; + origin->setQuota(defaultQuota); + + return S_OK; +} + + +HRESULT STDMETHODCALLTYPE UIDelegate::setStatusText(IWebView*, BSTR text) +{ + if (layoutTestController->dumpStatusCallbacks()) + printf("UI DELEGATE STATUS CALLBACK: setStatusText:%S\n", text ? text : L""); + return S_OK; +} diff --git a/WebKitTools/DumpRenderTree/win/UIDelegate.h b/WebKitTools/DumpRenderTree/win/UIDelegate.h new file mode 100755 index 0000000..0acab81 --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/UIDelegate.h @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. 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. + */ + +#ifndef UIDelegate_h +#define UIDelegate_h + +#include <WebKit/WebKit.h> +#include <wtf/OwnPtr.h> +#include <windef.h> + +class DRTUndoManager; + +class UIDelegate : public IWebUIDelegate, IWebUIDelegatePrivate3 { +public: + UIDelegate(); + + void resetUndoManager(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IWebUIDelegate + virtual HRESULT STDMETHODCALLTYPE createWebViewWithRequest( + /* [in] */ IWebView *sender, + /* [in] */ IWebURLRequest *request, + /* [retval][out] */ IWebView **newWebView); + + virtual HRESULT STDMETHODCALLTYPE webViewShow( + /* [in] */ IWebView *sender) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewClose( + /* [in] */ IWebView *sender); + + virtual HRESULT STDMETHODCALLTYPE webViewFocus( + /* [in] */ IWebView *sender) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewUnfocus( + /* [in] */ IWebView *sender) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewFirstResponder( + /* [in] */ IWebView *sender, + /* [retval][out] */ OLE_HANDLE *responder) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE makeFirstResponder( + /* [in] */ IWebView *sender, + /* [in] */ OLE_HANDLE responder) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setStatusText( + /* [in] */ IWebView *sender, + /* [in] */ BSTR text); + + virtual HRESULT STDMETHODCALLTYPE webViewStatusText( + /* [in] */ IWebView *sender, + /* [retval][out] */ BSTR *text) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewAreToolbarsVisible( + /* [in] */ IWebView *sender, + /* [retval][out] */ BOOL *visible) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setToolbarsVisible( + /* [in] */ IWebView *sender, + /* [in] */ BOOL visible) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewIsStatusBarVisible( + /* [in] */ IWebView *sender, + /* [retval][out] */ BOOL *visible) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setStatusBarVisible( + /* [in] */ IWebView *sender, + /* [in] */ BOOL visible) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewIsResizable( + /* [in] */ IWebView *sender, + /* [retval][out] */ BOOL *resizable) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setResizable( + /* [in] */ IWebView *sender, + /* [in] */ BOOL resizable) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setFrame( + /* [in] */ IWebView *sender, + /* [in] */ RECT *frame); + + virtual HRESULT STDMETHODCALLTYPE webViewFrame( + /* [in] */ IWebView *sender, + /* [retval][out] */ RECT *frame); + + virtual HRESULT STDMETHODCALLTYPE setContentRect( + /* [in] */ IWebView *sender, + /* [in] */ RECT *contentRect) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewContentRect( + /* [in] */ IWebView *sender, + /* [retval][out] */ RECT *contentRect) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptAlertPanelWithMessage( + /* [in] */ IWebView *sender, + /* [in] */ BSTR message); + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptConfirmPanelWithMessage( + /* [in] */ IWebView *sender, + /* [in] */ BSTR message, + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptTextInputPanelWithPrompt( + /* [in] */ IWebView *sender, + /* [in] */ BSTR message, + /* [in] */ BSTR defaultText, + /* [retval][out] */ BSTR *result); + + virtual HRESULT STDMETHODCALLTYPE runBeforeUnloadConfirmPanelWithMessage( + /* [in] */ IWebView *sender, + /* [in] */ BSTR message, + /* [in] */ IWebFrame *initiatedByFrame, + /* [retval][out] */ BOOL *result) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runOpenPanelForFileButtonWithResultListener( + /* [in] */ IWebView *sender, + /* [in] */ IWebOpenPanelResultListener *resultListener) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE mouseDidMoveOverElement( + /* [in] */ IWebView *sender, + /* [in] */ IPropertyBag *elementInformation, + /* [in] */ UINT modifierFlags) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE contextMenuItemsForElement( + /* [in] */ IWebView *sender, + /* [in] */ IPropertyBag *element, + /* [in] */ OLE_HANDLE defaultItems, + /* [retval][out] */ OLE_HANDLE *resultMenu) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE validateUserInterfaceItem( + /* [in] */ IWebView *webView, + /* [in] */ UINT itemCommandID, + /* [in] */ BOOL defaultValidation, + /* [retval][out] */ BOOL *isValid) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE shouldPerformAction( + /* [in] */ IWebView *webView, + /* [in] */ UINT itemCommandID, + /* [in] */ UINT sender) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE dragDestinationActionMaskForDraggingInfo( + /* [in] */ IWebView *webView, + /* [in] */ IDataObject *draggingInfo, + /* [retval][out] */ WebDragDestinationAction *action) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformDragDestinationAction( + /* [in] */ IWebView *webView, + /* [in] */ WebDragDestinationAction action, + /* [in] */ IDataObject *draggingInfo) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE dragSourceActionMaskForPoint( + /* [in] */ IWebView *webView, + /* [in] */ LPPOINT point, + /* [retval][out] */ WebDragSourceAction *action) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformDragSourceAction( + /* [in] */ IWebView *webView, + /* [in] */ WebDragSourceAction action, + /* [in] */ LPPOINT point, + /* [in] */ IDataObject *pasteboard) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE contextMenuItemSelected( + /* [in] */ IWebView *sender, + /* [in] */ void *item, + /* [in] */ IPropertyBag *element) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE hasCustomMenuImplementation( + /* [retval][out] */ BOOL *hasCustomMenus); + + virtual HRESULT STDMETHODCALLTYPE trackCustomPopupMenu( + /* [in] */ IWebView *sender, + /* [in] */ OLE_HANDLE menu, + /* [in] */ LPPOINT point); + + virtual HRESULT STDMETHODCALLTYPE measureCustomMenuItem( + /* [in] */ IWebView *sender, + /* [in] */ void *measureItem) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE drawCustomMenuItem( + /* [in] */ IWebView *sender, + /* [in] */ void *drawItem) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE addCustomMenuDrawingData( + /* [in] */ IWebView *sender, + /* [in] */ OLE_HANDLE menu) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE cleanUpCustomMenuDrawingData( + /* [in] */ IWebView *sender, + /* [in] */ OLE_HANDLE menu) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE canTakeFocus( + /* [in] */ IWebView *sender, + /* [in] */ BOOL forward, + /* [out] */ BOOL *result) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE takeFocus( + /* [in] */ IWebView *sender, + /* [in] */ BOOL forward) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE registerUndoWithTarget( + /* [in] */ IWebUndoTarget *target, + /* [in] */ BSTR actionName, + /* [in] */ IUnknown *actionArg); + + virtual HRESULT STDMETHODCALLTYPE removeAllActionsWithTarget( + /* [in] */ IWebUndoTarget *target); + + virtual HRESULT STDMETHODCALLTYPE setActionTitle( + /* [in] */ BSTR actionTitle); + + virtual HRESULT STDMETHODCALLTYPE undo(); + + virtual HRESULT STDMETHODCALLTYPE redo(); + + virtual HRESULT STDMETHODCALLTYPE canUndo( + /* [retval][out] */ BOOL *result); + + virtual HRESULT STDMETHODCALLTYPE canRedo( + /* [retval][out] */ BOOL *result); + +protected: + // IWebUIDelegatePrivate + + virtual HRESULT STDMETHODCALLTYPE webViewResizerRect( + /* [in] */ IWebView *sender, + /* [retval][out] */ RECT *rect) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewDrawResizer( + /* [in] */ IWebView *sender, + /* [in] */ HDC dc, + /* [in] */ BOOL overlapsContent, + /* [in] */ RECT *rect) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewScrolled( + /* [in] */ IWebView *sender) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewAddMessageToConsole( + /* [in] */ IWebView *sender, + /* [in] */ BSTR message, + /* [in] */ int lineNumber, + /* [in] */ BSTR url, + /* [in] */ BOOL isError); + + virtual HRESULT STDMETHODCALLTYPE webViewShouldInterruptJavaScript( + /* [in] */ IWebView *sender, + /* [retval][out] */ BOOL *result) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewReceivedFocus( + /* [in] */ IWebView *sender) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewLostFocus( + /* [in] */ IWebView *sender, + /* [in] */ OLE_HANDLE loseFocusTo) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE doDragDrop( + /* [in] */ IWebView *sender, + /* [in] */ IDataObject *dataObject, + /* [in] */ IDropSource *dropSource, + /* [in] */ DWORD okEffect, + /* [retval][out] */ DWORD *performedEffect); + + virtual HRESULT STDMETHODCALLTYPE webViewGetDlgCode( + /* [in] */ IWebView *sender, + /* [in] */ UINT keyCode, + /* [retval][out] */ LONG_PTR *code); + + // IWebUIDelegatePrivate2 + + virtual HRESULT STDMETHODCALLTYPE webViewPainted( + /* [in] */ IWebView *sender); + + // IWebUIDelegatePrivate3 + + virtual HRESULT STDMETHODCALLTYPE exceededDatabaseQuota( + /* [in] */ IWebView *sender, + /* [in] */ IWebFrame *frame, + /* [in] */ IWebSecurityOrigin *origin, + /* [in] */ BSTR databaseIdentifier); + + ULONG m_refCount; + +private: + RECT m_frame; + OwnPtr<DRTUndoManager> m_undoManager; +}; + +#endif diff --git a/WebKitTools/DumpRenderTree/win/WorkQueueItemWin.cpp b/WebKitTools/DumpRenderTree/win/WorkQueueItemWin.cpp new file mode 100644 index 0000000..4113c9e --- /dev/null +++ b/WebKitTools/DumpRenderTree/win/WorkQueueItemWin.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include "DumpRenderTree.h" +#include "WorkQueueItem.h" + +#include <WebCore/COMPtr.h> +#include <WebKit/WebKit.h> +#include <JavaScriptCore/JSStringRef.h> +#include <JavaScriptCore/JSStringRefCF.h> +#include <JavaScriptCore/RetainPtr.h> +#include <wtf/Vector.h> +#include <string> + +using std::wstring; + +static wstring jsStringRefToWString(JSStringRef jsStr) +{ + size_t length = JSStringGetLength(jsStr); + Vector<WCHAR> buffer(length + 1); + memcpy(buffer.data(), JSStringGetCharactersPtr(jsStr), length * sizeof(WCHAR)); + buffer[length] = '\0'; + + return buffer.data(); +} + +void LoadItem::invoke() const +{ + wstring targetString = jsStringRefToWString(target()); + + COMPtr<IWebFrame> targetFrame; + if (targetString.empty()) + targetFrame = frame; + else { + BSTR targetBSTR = SysAllocString(targetString.c_str()); + bool failed = FAILED(frame->findFrameNamed(targetBSTR, &targetFrame)); + SysFreeString(targetBSTR); + if (failed) + return; + } + + COMPtr<IWebURLRequest> request; + if (FAILED(CoCreateInstance(CLSID_WebURLRequest, 0, CLSCTX_ALL, IID_IWebURLRequest, (void**)&request))) + return; + + wstring urlString = jsStringRefToWString(url()); + BSTR urlBSTR = SysAllocString(urlString.c_str()); + bool failed = FAILED(request->initWithURL(urlBSTR, WebURLRequestUseProtocolCachePolicy, 60)); + SysFreeString(urlBSTR); + if (failed) + return; + + targetFrame->loadRequest(request.get()); +} + +void ReloadItem::invoke() const +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebIBActions> webActions; + if (SUCCEEDED(webView->QueryInterface(&webActions))) + webActions->reload(0); +} + +void ScriptItem::invoke() const +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + wstring scriptString = jsStringRefToWString(script()); + + BSTR result; + BSTR scriptBSTR = SysAllocString(scriptString.c_str()); + webView->stringByEvaluatingJavaScriptFromString(scriptBSTR, &result); + SysFreeString(result); + SysFreeString(scriptBSTR); +} + +void BackForwardItem::invoke() const +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + BOOL result; + if (m_howFar == 1) { + webView->goForward(&result); + return; + } + + if (m_howFar == -1) { + webView->goBack(&result); + return; + } + + COMPtr<IWebBackForwardList> bfList; + if (FAILED(webView->backForwardList(&bfList))) + return; + + COMPtr<IWebHistoryItem> item; + if (FAILED(bfList->itemAtIndex(m_howFar, &item))) + return; + + webView->goToBackForwardItem(item.get(), &result); +} diff --git a/WebKitTools/FindSafari/FindSafari.cpp b/WebKitTools/FindSafari/FindSafari.cpp new file mode 100644 index 0000000..83626bb --- /dev/null +++ b/WebKitTools/FindSafari/FindSafari.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2007 Apple Inc. 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. + */ + +#include <shlwapi.h> +#include <stdio.h> +#include <tchar.h> +#include <windows.h> + +#define LOG(header, ...) \ + do { \ + _ftprintf(stderr, header); \ + _ftprintf(stderr, __VA_ARGS__); \ + } while (0) +#define LOG_WARNING(...) LOG(TEXT("WARNING: "), __VA_ARGS__) +#define LOG_ERROR(...) LOG(TEXT("ERROR: "), __VA_ARGS__) + +static TCHAR* getStringValue(HKEY key, LPCTSTR valueName) +{ + DWORD type = 0; + DWORD bufferSize = 0; + if (RegQueryValueEx(key, valueName, 0, &type, 0, &bufferSize) != ERROR_SUCCESS || type != REG_SZ) + return 0; + + TCHAR* buffer = (TCHAR*)malloc(bufferSize); + if (RegQueryValueEx(key, 0, 0, &type, reinterpret_cast<LPBYTE>(buffer), &bufferSize) != ERROR_SUCCESS) { + free(buffer); + return 0; + } + + return buffer; +} + +static LPOLESTR getWebViewCLSID() +{ + LPCTSTR webViewProgID = TEXT("WebKit.WebView"); + + CLSID clsid = CLSID_NULL; + HRESULT hr = CLSIDFromProgID(webViewProgID, &clsid); + if (FAILED(hr)) { + LOG_WARNING(TEXT("Failed to get CLSID for %s\n"), webViewProgID); + return 0; + } + + LPOLESTR clsidString = 0; + if (FAILED(StringFromCLSID(clsid, &clsidString))) { + LOG_WARNING(TEXT("Failed to get string representation of CLSID for WebView\n")); + return 0; + } + + return clsidString; +} + +static TCHAR* getInstalledWebKitDirectory() +{ + LPCTSTR keyPrefix = TEXT("SOFTWARE\\Classes\\CLSID\\"); + LPCTSTR keySuffix = TEXT("\\InprocServer32"); + + LPOLESTR clsid = getWebViewCLSID(); + if (!clsid) + return 0; + + size_t keyBufferLength = _tcslen(keyPrefix) + _tcslen(clsid) + _tcslen(keySuffix) + 1; + TCHAR* keyString = (TCHAR*)malloc(keyBufferLength * sizeof(TCHAR)); + + int ret = _sntprintf_s(keyString, keyBufferLength, keyBufferLength - 1, TEXT("%s%s%s"), keyPrefix, clsid, keySuffix); + CoTaskMemFree(clsid); + if (ret == -1) { + LOG_WARNING(TEXT("Failed to construct InprocServer32 key\n")); + return 0; + } + + HKEY serverKey = 0; + LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyString, 0, KEY_READ, &serverKey); + free(keyString); + if (error != ERROR_SUCCESS) { + LOG_WARNING(TEXT("Failed to open registry key %s\n"), keyString); + return 0; + } + + TCHAR* webKitPath = getStringValue(serverKey, 0); + RegCloseKey(serverKey); + if (!webKitPath) { + LOG_WARNING(TEXT("Couldn't retrieve value for registry key %s\n"), keyString); + return 0; + } + + TCHAR* startOfFileName = PathFindFileName(webKitPath); + if (startOfFileName == webKitPath) { + LOG_WARNING(TEXT("Couldn't find filename from path %s\n"), webKitPath); + free(webKitPath); + return 0; + } + + *startOfFileName = '\0'; + return webKitPath; +} + +int _tmain(int argc, TCHAR* argv[]) +{ + TCHAR* path = getInstalledWebKitDirectory(); + if (!path) { + LOG_ERROR(TEXT("Couldn't determine installed Safari path\n")); + return 1; + } + + bool printLauncher = false; + bool printEnvironment = false; + bool debugger = false; + + for (int i = 1; i < argc; ++i) { + if (!_tcscmp(argv[i], TEXT("/printSafariLauncher"))) { + printLauncher = true; + continue; + } + if (!_tcscmp(argv[i], TEXT("/printSafariEnvironment"))) { + printEnvironment = true; + continue; + } + if (!_tcscmp(argv[i], TEXT("/debugger"))) { + debugger = true; + continue; + } + } + + // printLauncher is inclusive of printEnvironment, so do not + // leave both enabled: + if (printLauncher && printEnvironment) + printEnvironment = false; + + if (!printLauncher && !printEnvironment) { + _tprintf(TEXT("%s\n"), path); + free(path); + return 0; + } + + LPCTSTR lines[] = { + TEXT("@echo off"), + TEXT("mkdir 2>NUL \"%%TMP%%\\WebKitNightly\\Safari.resources\""), + TEXT("xcopy /y /i /d \"%sSafari.exe\" \"%%TMP%%\\WebKitNightly\""), + TEXT("xcopy /y /i /d /e \"%sSafari.resources\" \"%%TMP%%\\WebKitNightly\\Safari.resources\""), + TEXT("xcopy /y /i /d /e \"%splugins\" \"%%TMP%%\\WebKitNightly\\plugins\""), + TEXT("set PATH=%%CD%%;%s;%%PATH%%"), + }; + + LPCTSTR command = TEXT("\"%TMP%\\WebKitNightly\\Safari.exe\" /customWebKit"); + + LPCTSTR launchLines[] = { + TEXT("%s"), + }; + + LPCTSTR debuggerLines[] = { + TEXT("if exist \"%%DevEnvDir%%\\VCExpress.exe\" ("), + TEXT("\"%%DevEnvDir%%\\VCExpress.exe\" /debugExe %s"), + TEXT(") else ("), + TEXT("\"%%DevEnvDir%%\\devenv.exe\" /debugExe %s"), + TEXT(")"), + }; + + for (int i = 0; i < ARRAYSIZE(lines); ++i) { + _tprintf(lines[i], path); + _tprintf(TEXT("\n")); + } + + LPCTSTR* endLines = debugger ? debuggerLines : launchLines; + + // Don't print launch command if we just want the environment set up... + if (!printEnvironment) { + for (unsigned i = 0; i < (debugger ? ARRAYSIZE(debuggerLines) : ARRAYSIZE(launchLines)); ++i) { + _tprintf(endLines[i], command); + _tprintf(TEXT("\n")); + } + } + + free(path); + return 0; +} diff --git a/WebKitTools/FindSafari/FindSafari.vcproj b/WebKitTools/FindSafari/FindSafari.vcproj new file mode 100644 index 0000000..93f8647 --- /dev/null +++ b/WebKitTools/FindSafari/FindSafari.vcproj @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="FindSafari"
+ ProjectGUID="{DA31DA52-6675-48D4-89E0-333A7144397C}"
+ RootNamespace="FindSafari"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib advapi32.lib ole32.lib"
+ OutputFile="$(OutDir)\$(ProjectName).exe"
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\FindSafari.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/GNUmakefile.am b/WebKitTools/GNUmakefile.am new file mode 100644 index 0000000..26758b5 --- /dev/null +++ b/WebKitTools/GNUmakefile.am @@ -0,0 +1,48 @@ +noinst_PROGRAMS += \ + Programs/GtkLauncher \ + Programs/DumpRenderTree + +# GtkLauncher +Programs_GtkLauncher_CPPFLAGS = \ + -I$(srcdir)/WebKit/gtk \ + $(global_cppflags) + +Programs_GtkLauncher_SOURCES = \ + WebKitTools/GtkLauncher/main.c + +Programs_GtkLauncher_CFLAGS = \ + $(GLOBALDEPS_CFLAGS) \ + $(WEBKITDEPS_CFLAGS) \ + $(global_cflags) + +Programs_GtkLauncher_LDADD = \ + libwebkit-1.0.la + +Programs_GtkLauncher_LDFLAGS = -rpath $(CURDIR)/.libs + +# DumpRenderTree +Programs_DumpRenderTree_CPPFLAGS = \ + -I$(srcdir)/WebKitTools/DumpRenderTree \ + -I$(srcdir)/WebKitTools/DumpRenderTree/gtk \ + -I$(srcdir)/WebKit/gtk \ + $(global_cppflags) + +Programs_DumpRenderTree_SOURCES = \ + WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp \ + WebKitTools/DumpRenderTree/LayoutTestController.cpp \ + WebKitTools/DumpRenderTree/GCController.cpp \ + WebKitTools/DumpRenderTree/WorkQueue.cpp \ + WebKitTools/DumpRenderTree/gtk/GCControllerGtk.cpp \ + WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp \ + WebKitTools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp + +Programs_DumpRenderTree_CXXFLAGS = \ + $(GLOBALDEPS_CFLAGS) \ + $(WEBKITDEPS_CFLAGS) \ + $(global_cxxflags) \ + $(global_cflags) + +Programs_DumpRenderTree_LDADD = \ + libwebkit-1.0.la + +Programs_DumpRenderTree_LDFLAGS = -rpath $(CURDIR)/.libs diff --git a/WebKitTools/GtkLauncher/GtkLauncher.pro b/WebKitTools/GtkLauncher/GtkLauncher.pro new file mode 100644 index 0000000..b8c4aa8 --- /dev/null +++ b/WebKitTools/GtkLauncher/GtkLauncher.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +SOURCES += main.c +CONFIG -= app_bundle + +BASE_DIR = $$PWD/../.. + +include(../../WebKit.pri) + + +QMAKE_RPATHDIR += $$OUTPUT_DIR/lib diff --git a/WebKitTools/GtkLauncher/main.c b/WebKitTools/GtkLauncher/main.c new file mode 100644 index 0000000..8ed2690 --- /dev/null +++ b/WebKitTools/GtkLauncher/main.c @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#include <gtk/gtk.h> +#include <webkit/webkit.h> + +static GtkWidget* main_window; +static GtkWidget* uri_entry; +static GtkStatusbar* main_statusbar; +static WebKitWebView* web_view; +static gchar* main_title; +static gint load_progress; +static guint status_context_id; + +static void +activate_uri_entry_cb (GtkWidget* entry, gpointer data) +{ + const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry)); + g_assert (uri); + webkit_web_view_open (web_view, uri); +} + +static void +update_title (GtkWindow* window) +{ + GString* string = g_string_new (main_title); + g_string_append (string, " - WebKit Launcher"); + if (load_progress < 100) + g_string_append_printf (string, " (%d%%)", load_progress); + gchar* title = g_string_free (string, FALSE); + gtk_window_set_title (window, title); + g_free (title); +} + +static void +link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data) +{ + /* underflow is allowed */ + gtk_statusbar_pop (main_statusbar, status_context_id); + if (link) + gtk_statusbar_push (main_statusbar, status_context_id, link); +} + +static void +title_change_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data) +{ + if (main_title) + g_free (main_title); + main_title = g_strdup (title); + update_title (GTK_WINDOW (main_window)); +} + +static void +progress_change_cb (WebKitWebView* page, gint progress, gpointer data) +{ + load_progress = progress; + update_title (GTK_WINDOW (main_window)); +} + +static void +load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data) +{ + const gchar* uri = webkit_web_frame_get_uri(frame); + if (uri) + gtk_entry_set_text (GTK_ENTRY (uri_entry), uri); +} + +static void +destroy_cb (GtkWidget* widget, gpointer data) +{ + gtk_main_quit (); +} + +static void +go_back_cb (GtkWidget* widget, gpointer data) +{ + webkit_web_view_go_back (web_view); +} + +static void +go_forward_cb (GtkWidget* widget, gpointer data) +{ + webkit_web_view_go_forward (web_view); +} + +static GtkWidget* +create_browser () +{ + GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ()); + gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view)); + + g_signal_connect (G_OBJECT (web_view), "title-changed", G_CALLBACK (title_change_cb), web_view); + g_signal_connect (G_OBJECT (web_view), "load-progress-changed", G_CALLBACK (progress_change_cb), web_view); + g_signal_connect (G_OBJECT (web_view), "load-committed", G_CALLBACK (load_commit_cb), web_view); + g_signal_connect (G_OBJECT (web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), web_view); + + return scrolled_window; +} + +static GtkWidget* +create_statusbar () +{ + main_statusbar = GTK_STATUSBAR (gtk_statusbar_new ()); + status_context_id = gtk_statusbar_get_context_id (main_statusbar, "Link Hover"); + + return (GtkWidget*)main_statusbar; +} + +static GtkWidget* +create_toolbar () +{ + GtkWidget* toolbar = gtk_toolbar_new (); + + gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); + + GtkToolItem* item; + + /* the back button */ + item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); + g_signal_connect (G_OBJECT (item), "clicked", G_CALLBACK (go_back_cb), NULL); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); + + /* The forward button */ + item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD); + g_signal_connect (G_OBJECT (item), "clicked", G_CALLBACK (go_forward_cb), NULL); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); + + /* The URL entry */ + item = gtk_tool_item_new (); + gtk_tool_item_set_expand (item, TRUE); + uri_entry = gtk_entry_new (); + gtk_container_add (GTK_CONTAINER (item), uri_entry); + g_signal_connect (G_OBJECT (uri_entry), "activate", G_CALLBACK (activate_uri_entry_cb), NULL); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); + + /* The go button */ + item = gtk_tool_button_new_from_stock (GTK_STOCK_OK); + g_signal_connect_swapped (G_OBJECT (item), "clicked", G_CALLBACK (activate_uri_entry_cb), (gpointer)uri_entry); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); + + return toolbar; +} + +static GtkWidget* +create_window () +{ + GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); + gtk_widget_set_name (window, "GtkLauncher"); + g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL); + + return window; +} + +int +main (int argc, char* argv[]) +{ + gtk_init (&argc, &argv); + + GtkWidget* vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), create_toolbar (), FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), create_browser (), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), create_statusbar (), FALSE, FALSE, 0); + + main_window = create_window (); + gtk_container_add (GTK_CONTAINER (main_window), vbox); + + gchar* uri = (gchar*) (argc > 1 ? argv[1] : "http://www.google.com/"); + webkit_web_view_open (web_view, uri); + + gtk_widget_grab_focus (GTK_WIDGET (web_view)); + gtk_widget_show_all (main_window); + gtk_main (); + + return 0; +} diff --git a/WebKitTools/GtkLauncher/simple.svg b/WebKitTools/GtkLauncher/simple.svg new file mode 100644 index 0000000..30b13ac --- /dev/null +++ b/WebKitTools/GtkLauncher/simple.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" +"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> +<svg width="5cm" height="4cm" +xmlns="http://www.w3.org/2000/svg"> +<desc>Four separate rectangles +</desc> +<rect x="0.5cm" y="0.5cm" width="2cm" height="1cm"/> +<rect x="0.5cm" y="2cm" width="1cm" height="1.5cm"/> +<rect x="3cm" y="0.5cm" width="1.5cm" height="2cm"/> +<rect x="3.5cm" y="3cm" width="1cm" height="0.5cm"/> +<!-- Show outline of canvas using 'rect' element --> +<rect x=".01cm" y=".01cm" width="4.98cm" height="3.98cm" +fill="none" stroke="blue" stroke-width=".02cm" /> +</svg> diff --git a/WebKitTools/GtkLauncher/text.html b/WebKitTools/GtkLauncher/text.html new file mode 100644 index 0000000..607df72 --- /dev/null +++ b/WebKitTools/GtkLauncher/text.html @@ -0,0 +1,9 @@ +<html> +<head> +<title>Hello World</title> +<body bgcolor=#00ffff text=#000000> +<p> +Hello world +</p> +</body> +</html> diff --git a/WebKitTools/MIDLWrapper/MIDLWrapper.cpp b/WebKitTools/MIDLWrapper/MIDLWrapper.cpp new file mode 100644 index 0000000..2132af8 --- /dev/null +++ b/WebKitTools/MIDLWrapper/MIDLWrapper.cpp @@ -0,0 +1,86 @@ +// MIDLWrapper.cpp : Just calls the built-in midl.exe with the given arguments. + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include <process.h> +#include <stdio.h> +#include <string> +#include <windows.h> + +using namespace std; + +int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) +{ +#ifndef NDEBUG + fwprintf(stderr, L"######### im in ur IDE, compiling ur c0des ########\n"); +#endif + + int pathIndex = -1; + for (int i = 0; envp[i]; ++i) + if (!wcsncmp(envp[i], L"PATH=", 5)) { + pathIndex = i; + break; + } + + if (pathIndex == -1) { + fwprintf(stderr, L"Couldn't find PATH environment variable!\n"); + return -1; + } + + wchar_t* vcbin = wcsstr(envp[pathIndex], L"WebKitTools\\vcbin"); + if (!vcbin) { + fwprintf(stderr, L"Couldn't find WebKitTools\\vcbin in PATH!\n"); + return -1; + } + + wchar_t saved = *vcbin; + *vcbin = 0; + + wchar_t* afterLeadingSemiColon = wcsrchr(envp[pathIndex], ';'); + if (!afterLeadingSemiColon) + afterLeadingSemiColon = envp[pathIndex] + 5; // +5 for the length of "PATH=" + else + afterLeadingSemiColon++; + + *vcbin = saved; + + size_t pathLength = wcslen(envp[pathIndex]); + + wchar_t* trailingSemiColon = wcschr(vcbin, ';'); + if (!trailingSemiColon) + trailingSemiColon = envp[pathIndex] + pathLength; + + int vcbinLength = trailingSemiColon - afterLeadingSemiColon; + + size_t newPathLength = pathLength - vcbinLength; + + wchar_t* newPath = new wchar_t[newPathLength + 1]; + + // Copy everything before the vcbin path... + wchar_t* d = newPath; + wchar_t* s = envp[pathIndex]; + while (s < afterLeadingSemiColon) + *d++ = *s++; + + // Copy everything after the vcbin path... + s = trailingSemiColon; + while (*d++ = *s++); + + envp[pathIndex] = newPath; + +#ifndef NDEBUG + fwprintf(stderr, L"New path: %s\n", envp[pathIndex]); +#endif + + wchar_t** newArgv = new wchar_t*[argc + 1]; + for (int i = 0; i < argc; ++i) { + size_t length = wcslen(argv[i]); + newArgv[i] = new wchar_t[length + 3]; + *newArgv[i] = '\"'; + wcscpy_s(newArgv[i] + 1, length + 2, argv[i]); + *(newArgv[i] + 1 + length) = '\"'; + *(newArgv[i] + 2 + length) = 0; + } + newArgv[argc] = 0; + + return _wspawnvpe(_P_WAIT, L"midl", newArgv, envp); +} diff --git a/WebKitTools/MIDLWrapper/MIDLWrapper.sln b/WebKitTools/MIDLWrapper/MIDLWrapper.sln new file mode 100644 index 0000000..b066df5 --- /dev/null +++ b/WebKitTools/MIDLWrapper/MIDLWrapper.sln @@ -0,0 +1,20 @@ +
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MIDLWrapper", "MIDLWrapper.vcproj", "{CBE6BA0B-1A76-4936-BF54-7EB84E1B0F21}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CBE6BA0B-1A76-4936-BF54-7EB84E1B0F21}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CBE6BA0B-1A76-4936-BF54-7EB84E1B0F21}.Debug|Win32.Build.0 = Debug|Win32
+ {CBE6BA0B-1A76-4936-BF54-7EB84E1B0F21}.Release|Win32.ActiveCfg = Release|Win32
+ {CBE6BA0B-1A76-4936-BF54-7EB84E1B0F21}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/WebKitTools/MIDLWrapper/MIDLWrapper.vcproj b/WebKitTools/MIDLWrapper/MIDLWrapper.vcproj new file mode 100644 index 0000000..471813d --- /dev/null +++ b/WebKitTools/MIDLWrapper/MIDLWrapper.vcproj @@ -0,0 +1,199 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MIDLWrapper"
+ ProjectGUID="{CBE6BA0B-1A76-4936-BF54-7EB84E1B0F21}"
+ RootNamespace="MIDLWrapper"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\vcbin"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\midl.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="..\vcbin"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\midl.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\MIDLWrapper.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/WebKitTools/Makefile b/WebKitTools/Makefile new file mode 100644 index 0000000..364eadb --- /dev/null +++ b/WebKitTools/Makefile @@ -0,0 +1,30 @@ +MODULES = Drosera DumpRenderTree + +all: + @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ + if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done + +debug d development dev develop: + @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ + if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done + +release r deployment dep deploy: + @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ + if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done + +universal u: + @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ + if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done + +64: + @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ + if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done + +64u: + @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ + if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done + +clean: + @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ + if [ $$exit_status -ne 0 ]; then exit $$exit_status; fi; done + diff --git a/WebKitTools/Scripts/SpacingHeuristics.pm b/WebKitTools/Scripts/SpacingHeuristics.pm new file mode 100644 index 0000000..7de0172 --- /dev/null +++ b/WebKitTools/Scripts/SpacingHeuristics.pm @@ -0,0 +1,101 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. 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. + +# Used for helping remove extra blank lines from files when processing. +# see split-class for an example usage (or other scripts in bugzilla) + +BEGIN { + use Exporter (); + our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); + $VERSION = 1.00; + @ISA = qw(Exporter); + @EXPORT = qw(&resetSpacingHeuristics &isOnlyWhiteSpace &applySpacingHeuristicsAndPrint &setPreviousAllowedLine &setPreviousAllowedLine &printPendingEmptyLines &ignoringLine); + %EXPORT_TAGS = (); + @EXPORT_OK = (); +} + +our @EXPORT_OK; + +my $justFoundEmptyLine = 0; +my $previousLineWasDisallowed = 0; +my $previousAllowedLine = ""; +my $pendingEmptyLines = ""; + +sub resetSpacingHeuristics +{ + $justFoundEmptyLine = 0; + $previousLineWasDisallowed = 0; + $previousAllowedLine = ""; + $pendingEmptyLines = ""; +} + +sub isOnlyWhiteSpace +{ + my $line = shift; + my $isOnlyWhiteSpace = ($line =~ m/^\s+$/); + $pendingEmptyLines .= $line if ($isOnlyWhiteSpace); + return $isOnlyWhiteSpace; +} + +sub applySpacingHeuristicsAndPrint +{ + my ($out, $line) = @_; + + printPendingEmptyLines($out, $line); + $previousLineWasDisallowed = 0; + print $out $line; +} + +sub setPreviousAllowedLine +{ + my $line = shift; + $previousAllowedLine = $line; +} + +sub printPendingEmptyLines +{ + my $out = shift; + my $line = shift; + if ($previousLineWasDisallowed) { + if (!($pendingEmptyLines eq "") && !($previousAllowedLine =~ m/{\s*$/) && !($line =~ m/^\s*}/)) { + $pendingEmptyLines = "\n"; + } else { + $pendingEmptyLines = ""; + } + } + print $out $pendingEmptyLines; + $pendingEmptyLines = ""; +} + +sub ignoringLine +{ + # my $line = shift; # ignoring input argument + $previousLineWasDisallowed = 1; +} + +1;
\ No newline at end of file diff --git a/WebKitTools/Scripts/VCSUtils.pm b/WebKitTools/Scripts/VCSUtils.pm new file mode 100644 index 0000000..26401f4 --- /dev/null +++ b/WebKitTools/Scripts/VCSUtils.pm @@ -0,0 +1,121 @@ +# Copyright (C) 2007 Apple Inc. 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. + +# Module to share code to work with various version control systems. + +use strict; +use warnings; +use File::Spec; +use webkitdirs; + +BEGIN { + use Exporter (); + our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); + $VERSION = 1.00; + @ISA = qw(Exporter); + @EXPORT = qw(&isGitDirectory &isGit &isSVNDirectory &isSVN &makeFilePathRelative); + %EXPORT_TAGS = ( ); + @EXPORT_OK = (); +} + +our @EXPORT_OK; + +my $isGit; +my $isSVN; +my $gitBranch; +my $isGitBranchBuild; + +sub isGitDirectory($) +{ + my ($dir) = @_; + return system("cd $dir && git rev-parse > /dev/null 2>&1") == 0; +} + +sub isGit() +{ + return $isGit if defined $isGit; + + $isGit = isGitDirectory("."); + return $isGit; +} + +sub gitBranch() +{ + unless (defined $gitBranch) { + chomp($gitBranch = `git symbolic-ref -q HEAD`); + $gitBranch = "" if exitStatus($?); + $gitBranch =~ s#^refs/heads/##; + $gitBranch = "" if $gitBranch eq "master"; + } + + return $gitBranch; +} + +sub isGitBranchBuild() +{ + my $branch = gitBranch(); + chomp(my $override = `git config --bool branch.$branch.webKitBranchBuild`); + return 1 if $override eq "true"; + return 0 if $override eq "false"; + + unless (defined $isGitBranchBuild) { + chomp(my $gitBranchBuild = `git config --bool core.webKitBranchBuild`); + $isGitBranchBuild = $gitBranchBuild eq "true"; + } + + return $isGitBranchBuild; +} + +sub isSVNDirectory($) +{ + my ($dir) = @_; + + return -d File::Spec->catdir($dir, ".svn"); +} + +sub isSVN() +{ + return $isSVN if defined $isSVN; + + $isSVN = isSVNDirectory("."); + return $isSVN; +} + +my $gitRoot; +sub makeFilePathRelative($) +{ + my ($path) = @_; + return $path unless isGit(); + + unless (defined $gitRoot) { + chomp($gitRoot = `git rev-parse --git-dir`); + $gitRoot =~ s/\.git$//; + } + my $result = File::Spec->abs2rel(File::Spec->rel2abs($path, $gitRoot)); + return $result; +} + +1; diff --git a/WebKitTools/Scripts/bisect-builds b/WebKitTools/Scripts/bisect-builds new file mode 100755 index 0000000..43e3889 --- /dev/null +++ b/WebKitTools/Scripts/bisect-builds @@ -0,0 +1,417 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Inc. 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. + +# This script attempts to find the point at which a regression (or progression) +# of behavior occurred by searching WebKit nightly builds. + +# To override the location where the nightly builds are downloaded or the path +# to the Safari web browser, create a ~/.bisect-buildsrc file with one or more of +# the following lines (use "~/" to specify a path from your home directory): +# +# $branch = "branch-name"; +# $nightlyDownloadDirectory = "~/path/to/nightly/downloads"; +# $safariPath = "/path/to/Safari.app"; + +use strict; + +use File::Basename; +use File::Path; +use File::Spec; +use File::Temp; +use Getopt::Long; +use Time::HiRes qw(usleep); + +sub createTempFile($); +sub downloadNightly($$$); +sub findMacOSXVersion(); +sub findNearestNightlyIndex(\@$$); +sub findSafariVersion($); +sub loadSettings(); +sub makeNightlyList($$$$); +sub mountAndRunNightly($$$$); +sub parseRevisions($$;$); +sub printStatus($$$); +sub promptForTest($); + +loadSettings(); + +my %validBranches = map { $_ => 1 } qw(feature-branch trunk); +my $branch = $Settings::branch; +my $nightlyDownloadDirectory = $Settings::nightlyDownloadDirectory; +my $safariPath = $Settings::safariPath; + +my @nightlies; + +my $isProgression; +my $localOnly; +my @revisions; +my $sanityCheck; +my $showHelp; +my $testURL; + +# Fix up -r switches in @ARGV +@ARGV = map { /^(-r)(.+)$/ ? ($1, $2) : $_ } @ARGV; + +my $result = GetOptions( + "b|branch=s" => \$branch, + "d|download-directory=s" => \$nightlyDownloadDirectory, + "h|help" => \$showHelp, + "l|local!" => \$localOnly, + "p|progression!" => \$isProgression, + "r|revisions=s" => \&parseRevisions, + "safari-path=s" => \$safariPath, + "s|sanity-check!" => \$sanityCheck, +); +$testURL = shift @ARGV; + +$branch = "feature-branch" if $branch eq "feature"; +if (!exists $validBranches{$branch}) { + print STDERR "ERROR: Invalid branch '$branch'\n"; + $showHelp = 1; +} + +if (!$result || $showHelp || scalar(@ARGV) > 0) { + print STDERR "Search WebKit nightly builds for changes in behavior.\n"; + print STDERR "Usage: " . basename($0) . " [options] [url]\n"; + print STDERR <<END; + [-b|--branch name] name of the nightly build branch (default: trunk) + [-d|--download-directory dir] nightly build download directory (default: ~/Library/Caches/WebKit-Nightlies) + [-h|--help] show this help message + [-l|--local] only use local (already downloaded) nightlies + [-p|--progression] searching for a progression, not a regression + [-r|--revision M[:N]] specify starting (and optional ending) revisions to search + [--safari-path path] path to Safari application bundle (default: /Applications/Safari.app) + [-s|--sanity-check] verify both starting and ending revisions before bisecting +END + exit 1; +} + +my $nightlyWebSite = "http://nightly.webkit.org"; +my $nightlyBuildsURLBase = $nightlyWebSite . File::Spec->catdir("/builds", $branch, "mac"); +my $nightlyFilesURLBase = $nightlyWebSite . File::Spec->catdir("/files", $branch, "mac"); + +$nightlyDownloadDirectory = glob($nightlyDownloadDirectory) if $nightlyDownloadDirectory =~ /^~/; +$safariPath = glob($safariPath) if $safariPath =~ /^~/; +$safariPath = File::Spec->catdir($safariPath, "Contents/MacOS/Safari") if $safariPath =~ m#\.app/*#; + +$nightlyDownloadDirectory = File::Spec->catdir($nightlyDownloadDirectory, $branch); +if (! -d $nightlyDownloadDirectory) { + mkpath($nightlyDownloadDirectory, 0, 0755) || die "Could not create $nightlyDownloadDirectory: $!"; +} + +@nightlies = makeNightlyList($localOnly, $nightlyDownloadDirectory, findMacOSXVersion(), findSafariVersion($safariPath)); + +my $startIndex = $revisions[0] ? findNearestNightlyIndex(@nightlies, $revisions[0], 'ceil') : 0; +my $endIndex = $revisions[1] ? findNearestNightlyIndex(@nightlies, $revisions[1], 'floor') : $#nightlies; + +my $tempFile = createTempFile($testURL); + +if ($sanityCheck) { + my $didReproduceBug; + + do { + printf "\nChecking starting revision (r%s)...\n", + $nightlies[$startIndex]->{rev}; + downloadNightly($nightlies[$startIndex]->{file}, $nightlyFilesURLBase, $nightlyDownloadDirectory); + mountAndRunNightly($nightlies[$startIndex]->{file}, $nightlyDownloadDirectory, $safariPath, $tempFile); + $didReproduceBug = promptForTest($nightlies[$startIndex]->{rev}); + $startIndex-- if $didReproduceBug < 0; + } while ($didReproduceBug < 0); + die "ERROR: Bug reproduced in starting revision! Do you need to test an earlier revision or for a progression?" + if $didReproduceBug && !$isProgression; + die "ERROR: Bug not reproduced in starting revision! Do you need to test an earlier revision or for a regression?" + if !$didReproduceBug && $isProgression; + + do { + printf "\nChecking ending revision (r%s)...\n", + $nightlies[$endIndex]->{rev}; + downloadNightly($nightlies[$endIndex]->{file}, $nightlyFilesURLBase, $nightlyDownloadDirectory); + mountAndRunNightly($nightlies[$endIndex]->{file}, $nightlyDownloadDirectory, $safariPath, $tempFile); + $didReproduceBug = promptForTest($nightlies[$endIndex]->{rev}); + $endIndex++ if $didReproduceBug < 0; + } while ($didReproduceBug < 0); + die "ERROR: Bug NOT reproduced in ending revision! Do you need to test a later revision or for a progression?" + if !$didReproduceBug && !$isProgression; + die "ERROR: Bug reproduced in ending revision! Do you need to test a later revision or for a regression?" + if $didReproduceBug && $isProgression; +} + +printStatus($nightlies[$startIndex]->{rev}, $nightlies[$endIndex]->{rev}, $isProgression); + +my %brokenRevisions = (); +while (abs($endIndex - $startIndex) > 1) { + my $index = $startIndex + int(($endIndex - $startIndex) / 2); + + my $didReproduceBug; + do { + if (exists $nightlies[$index]) { + printf "\nChecking revision (r%s)...\n", $nightlies[$index]->{rev}; + downloadNightly($nightlies[$index]->{file}, $nightlyFilesURLBase, $nightlyDownloadDirectory); + mountAndRunNightly($nightlies[$index]->{file}, $nightlyDownloadDirectory, $safariPath, $tempFile); + $didReproduceBug = promptForTest($nightlies[$index]->{rev}); + } + if ($didReproduceBug < 0) { + $brokenRevisions{$nightlies[$index]->{rev}} = $nightlies[$index]->{file}; + delete $nightlies[$index]; + $endIndex--; + $index = $startIndex + int(($endIndex - $startIndex) / 2); + } + } while ($didReproduceBug < 0); + + if ($didReproduceBug && !$isProgression || !$didReproduceBug && $isProgression) { + $endIndex = $index; + } else { + $startIndex = $index; + } + + print "\nBroken revisions skipped: r" . join(", r", keys %brokenRevisions) . "\n" + if scalar keys %brokenRevisions > 0; + printStatus($nightlies[$startIndex]->{rev}, $nightlies[$endIndex]->{rev}, $isProgression); +} + +unlink $tempFile if $tempFile; + +exit 0; + +sub createTempFile($) +{ + my ($url) = @_; + + return undef if !$url; + + my $fh = new File::Temp( + DIR => ($ENV{'TMPDIR'} || "/tmp"), + SUFFIX => ".html", + TEMPLATE => basename($0) . "-XXXXXXXX", + UNLINK => 0, + ); + my $tempFile = $fh->filename(); + print $fh "<meta http-equiv=\"refresh\" content=\"0; $url\">\n"; + close($fh); + + return $tempFile; +} + +sub downloadNightly($$$) +{ + my ($filename, $urlBase, $directory) = @_; + my $path = File::Spec->catfile($directory, $filename); + if (! -f $path) { + print "Downloading $filename to $directory...\n"; + `curl -# -o '$path' '$urlBase/$filename'`; + } +} + +sub findMacOSXVersion() +{ + my $version; + open(SW_VERS, "-|", "/usr/bin/sw_vers") || die; + while (<SW_VERS>) { + $version = $1 if /^ProductVersion:\s+([^\s]+)/; + } + close(SW_VERS); + return $version; +} + +sub findNearestNightlyIndex(\@$$) +{ + my ($nightlies, $revision, $round) = @_; + + my $lowIndex = 0; + my $highIndex = $#{$nightlies}; + + return $highIndex if uc($revision) eq 'HEAD' || $revision >= $nightlies->[$highIndex]->{rev}; + return $lowIndex if $revision <= $nightlies->[$lowIndex]->{rev}; + + while (abs($highIndex - $lowIndex) > 1) { + my $index = $lowIndex + int(($highIndex - $lowIndex) / 2); + if ($revision < $nightlies->[$index]->{rev}) { + $highIndex = $index; + } elsif ($revision > $nightlies->[$index]->{rev}) { + $lowIndex = $index; + } else { + return $index; + } + } + + return ($round eq "floor") ? $lowIndex : $highIndex; +} + +sub findSafariVersion($) +{ + my ($path) = @_; + my $versionPlist = File::Spec->catdir(dirname(dirname($path)), "version.plist"); + my $version; + open(PLIST, "< $versionPlist") || die; + while (<PLIST>) { + if (m#^\s*<key>CFBundleShortVersionString</key>#) { + $version = <PLIST>; + $version =~ s#^\s*<string>(.+)</string>\s*[\r\n]*#$1#; + } + } + close(PLIST); + return $version; +} + +sub loadSettings() +{ + package Settings; + + our $branch = "trunk"; + our $nightlyDownloadDirectory = File::Spec->catdir($ENV{HOME}, "Library/Caches/WebKit-Nightlies"); + our $safariPath = "/Applications/Safari.app"; + + my $rcfile = File::Spec->catdir($ENV{HOME}, ".bisect-buildsrc"); + return if !-f $rcfile; + + my $result = do $rcfile; + die "Could not parse $rcfile: $@" if $@; +} + +sub makeNightlyList($$$$) +{ + my ($useLocalFiles, $localDirectory, $macOSXVersion, $safariVersion) = @_; + my @files; + + if ($useLocalFiles) { + opendir(DIR, $localDirectory) || die "$!"; + foreach my $file (readdir(DIR)) { + if ($file =~ /^WebKit-SVN-r([0-9]+)\.dmg$/) { + push(@files, +{ rev => $1, file => $file }); + } + } + closedir(DIR); + } else { + open(NIGHTLIES, "curl -s $nightlyBuildsURLBase/all |") || die; + + while (my $line = <NIGHTLIES>) { + chomp $line; + my ($revision, $timestamp, $url) = split(/,/, $line); + my $nightly = basename($url); + push(@files, +{ rev => $revision, file => $nightly }); + } + close(NIGHTLIES); + } + + if (eval "v$macOSXVersion" ge v10.5) { + if (eval "v$safariVersion" ge v3.0) { + @files = grep { $_->{rev} >= 25124 } @files; + } elsif (eval "v$safariVersion" ge v2.0) { + @files = grep { $_->{rev} >= 19594 } @files; + } else { + die "Requires Safari 2.0 or newer"; + } + } elsif (eval "v$macOSXVersion" ge v10.4) { + if (eval "v$safariVersion" ge v3.0) { + @files = grep { $_->{rev} >= 19992 } @files; + } elsif (eval "v$safariVersion" ge v2.0) { + @files = grep { $_->{rev} >= 11976 } @files; + } else { + die "Requires Safari 2.0 or newer"; + } + } else { + die "Requires Mac OS X 10.4 (Tiger) or 10.5 (Leopard)"; + } + + my $nightlycmp = sub { return $a->{rev} <=> $b->{rev}; }; + + return sort $nightlycmp @files; +} + +sub mountAndRunNightly($$$$) +{ + my ($filename, $directory, $safari, $tempFile) = @_; + my $mountPath = "/Volumes/WebKit"; + my $webkitApp = File::Spec->catfile($mountPath, "WebKit.app"); + my $diskImage = File::Spec->catfile($directory, $filename); + + my $i = 0; + while (-e $mountPath) { + $i++; + usleep 100 if $i > 1; + `hdiutil detach '$mountPath' 2> /dev/null`; + die "Could not unmount $diskImage at $mountPath" if $i > 100; + } + die "Can't mount $diskImage: $mountPath already exists!" if -e $mountPath; + + print "Mounting disk image and running WebKit...\n"; + `hdiutil attach '$diskImage'`; + $i = 0; + while (! -e $webkitApp) { + usleep 100; + $i++; + die "Could not mount $diskImage at $mountPath" if $i > 100; + } + + my $frameworkPath; + if (-d "/Volumes/WebKit/WebKit.app/Contents/Frameworks") { + my $osXVersion = join('.', (split(/\./, findMacOSXVersion()))[0..1]); + $frameworkPath = "/Volumes/WebKit/WebKit.app/Contents/Frameworks/$osXVersion"; + } else { + $frameworkPath = "/Volumes/WebKit/WebKit.app/Contents/Resources"; + } + + $tempFile ||= ""; + `DYLD_FRAMEWORK_PATH=$frameworkPath WEBKIT_UNSET_DYLD_FRAMEWORK_PATH=YES $safari $tempFile`; + + `hdiutil detach '$mountPath' 2> /dev/null`; +} + +sub parseRevisions($$;$) +{ + my ($optionName, $value, $ignored) = @_; + + if ($value =~ /^r?([0-9]+|HEAD):?$/i) { + push(@revisions, $1); + die "Too many revision arguments specified" if scalar @revisions > 2; + } elsif ($value =~ /^r?([0-9]+):?r?([0-9]+|HEAD)$/i) { + $revisions[0] = $1; + $revisions[1] = $2; + } else { + die "Unknown revision '$value': expected 'M' or 'M:N'"; + } +} + +sub printStatus($$$) +{ + my ($startRevision, $endRevision, $isProgression) = @_; + printf "\n%s: r%s %s: r%s\n", + $isProgression ? "Fails" : "Works", $startRevision, + $isProgression ? "Works" : "Fails", $endRevision; +} + +sub promptForTest($) +{ + my ($revision) = @_; + print "Did the bug reproduce in r$revision (yes/no/broken)? "; + my $answer = <STDIN>; + return 1 if $answer =~ /^(1|y.*)$/i; + return -1 if $answer =~ /^(-1|b.*)$/i; # Broken + return 0; +} + diff --git a/WebKitTools/Scripts/build-drawtest b/WebKitTools/Scripts/build-drawtest new file mode 100755 index 0000000..fa9b7c2 --- /dev/null +++ b/WebKitTools/Scripts/build-drawtest @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006 Apple Computer, Inc. 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. + +# Simplified build script for WebKit Open Source Project. +# Modified copy of build-dumprendertree. Perhaps these could share code. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +checkRequiredSystemConfig(); +setConfiguration(); +chdirWebKit(); +my @options = XcodeOptions(); + +# Check to see that all the frameworks are built (w/ SVG support). +checkFrameworks(); +checkWebCoreSVGSupport(1); + +# Build +chdir "WebKitTools/DrawTest" or die; +exit system "xcodebuild", "-project", "DrawTest.xcodeproj", @options; diff --git a/WebKitTools/Scripts/build-drosera b/WebKitTools/Scripts/build-drosera new file mode 100755 index 0000000..f3b1144 --- /dev/null +++ b/WebKitTools/Scripts/build-drosera @@ -0,0 +1,53 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. 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. + +# Simplified build script for Web Kit Open Source Project. +# Modified copy of build-webkit. Perhaps these could share code. +# Currently only works for the Deployment build style. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +checkRequiredSystemConfig(); +setConfiguration(); +chdirWebKit(); +my @options = XcodeOptions(); + +# Build +chdir "WebKitTools/Drosera/mac" or die; +my $result; +if (isOSX()) { + print "xcodebuild -project Drosera.xcodeproj ", join(" ", @options), "\n"; + $result = system "xcodebuild", "-project", "Drosera.xcodeproj", @options; +} else { + die "Building not defined for this platform!\n"; +} +exit exitStatus($result); diff --git a/WebKitTools/Scripts/build-dumprendertree b/WebKitTools/Scripts/build-dumprendertree new file mode 100755 index 0000000..7f48a59 --- /dev/null +++ b/WebKitTools/Scripts/build-dumprendertree @@ -0,0 +1,54 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. 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. + + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +checkRequiredSystemConfig(); +setConfiguration(); +chdirWebKit(); +my @options = XcodeOptions(); + +# Build +chdir "WebKitTools/DumpRenderTree" or die; +my $result; +if (isOSX()) { + $result = system "xcodebuild", "-project", "DumpRenderTree.xcodeproj", @options; +} elsif (isCygwin()) { + $result = buildVisualStudioProject("DumpRenderTree.sln"); +} elsif (isQt() || isGtk()) { + # Qt and Gtk build everything in one shot. No need to build anything here. + $result = 0; +} else { + die "Building not defined for this platform!\n"; +} +exit exitStatus($result); diff --git a/WebKitTools/Scripts/build-testkjs b/WebKitTools/Scripts/build-testkjs new file mode 100755 index 0000000..5dc28ad --- /dev/null +++ b/WebKitTools/Scripts/build-testkjs @@ -0,0 +1,54 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2007 Eric Seidel <eric@webkit.org> +# +# 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. + + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +checkRequiredSystemConfig(); +setConfiguration(); +chdirWebKit(); +my @options = XcodeOptions(); + +chdir "JavaScriptCore" or die "Can't find JavaScriptCore directory to build from"; +my $result; +if (isOSX()) { + $result = system "sh", "-c", 'xcodebuild -project JavaScriptCore.xcodeproj -target testkjs "$@" | grep -v setenv && exit ${PIPESTATUS[0]}', "xcodebuild", @options, @ARGV; +} elsif (isCygwin()) { + $result = buildVisualStudioProject("JavaScriptCore.vcproj/JavaScriptCore.sln"); +} elsif (isQt() or isGtk() or isWx()) { + # Qt and Gtk build everything in one-shot. No need to build anything here. + $result = 0; +} else { + die "Building not defined for this platform!\n"; +} +exit exitStatus($result); diff --git a/WebKitTools/Scripts/build-webkit b/WebKitTools/Scripts/build-webkit new file mode 100755 index 0000000..f4c99e6 --- /dev/null +++ b/WebKitTools/Scripts/build-webkit @@ -0,0 +1,351 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006 Apple Computer, Inc. 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. + +# Simplified build script for Web Kit Open Source Project. + +use strict; +use File::Basename; +use File::Spec; +use FindBin; +use Getopt::Long qw(:config pass_through); +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +my $originalWorkingDirectory = getcwd(); + +my $crossDocumentMessagingSupport = 1; +my $databaseSupport = 1; +my $iconDatabaseSupport = 1; +my $svgSupport = 1; +my $svgExperimentalSupport = 0; +my $svgAnimationSupport = $svgExperimentalSupport; +my $svgFiltersSupport = $svgExperimentalSupport; +my $svgForeignObjectSupport = 1; +my $svgUseSupport = 1; +my $svgFontsSupport = 1; +my $svgAsImageSupport = 1; +my $xpathSupport = 1; +my $xsltSupport = 1; +my $coverageSupport = 0; +my $videoSupport = isOSX() || isCygwin(); # Enable by default on OSX and Windows +my $showHelp = 0; +my $clean = 0; +my $buildUniversal = 0; +my $buildSixtyFourBit = 0; + +my $programName = basename($0); +my $usage = <<EOF; +Usage: $programName [options] [options to pass to build system] + --help Show this help message + --clean Perform a clean build + --universal Build 2-way universal (PPC and Intel 32-bit) + --64-bit Build 64-bit, combine with --universal to build 4-way universal + --[no-]cross-document-messaging Toggle cross-document messaging support (default: $crossDocumentMessagingSupport) + --[no-]database Toggle Database Support (default: $databaseSupport) + --[no-]icon-database Toggle Icon database support (default: $iconDatabaseSupport) + --[no-]svg Toggle SVG support (default: $svgSupport) + --[no-]svg-experimental Toggle SVG experimental features support (default: $svgExperimentalSupport, + implies SVG Support) + --[no-]svg-animation Toggle SVG animation support (default: $svgAnimationSupport, implies SVG Support) + --[no-]svg-filters Toggle SVG filters support (default: $svgFiltersSupport, implies SVG Support) + --[no-]svg-foreign-object Toggle SVG forgeing object support (default: $svgForeignObjectSupport, implies SVG Support) + --[no-]svg-fonts Toggle SVG fonts support (default: $svgFontsSupport, implies SVG Support) + --[no-]svg-as-image Toggle SVG as Image support (default: $svgAsImageSupport, implies SVG Support) + --[no-]svg-use Toggle SVG use element support (default: $svgUseSupport, implies SVG Support) + --[no-]xpath Toggle XPath support (default: $xpathSupport) + --[no-]xslt Toggle XSLT support (default: $xsltSupport) + --[no-]video Toggle Video support (default: $videoSupport) + --[no-]coverage Toggle code coverage support (default: $coverageSupport) +EOF + +GetOptions('cross-document-messaging!' => \$crossDocumentMessagingSupport, + 'database!' => \$databaseSupport, + 'icon-database!' => \$iconDatabaseSupport, + 'svg!' => \$svgSupport, + 'svg-experimental!' => \$svgExperimentalSupport, + 'svg-animation!' => \$svgAnimationSupport, + 'svg-filters!' => \$svgFiltersSupport, + 'svg-foreign-object!' => \$svgForeignObjectSupport, + 'svg-fonts!' => \$svgFontsSupport, + 'svg-as-image!' => \$svgAsImageSupport, + 'svg-use!' => \$svgUseSupport, + 'xpath!' => \$xpathSupport, + 'xslt!' => \$xsltSupport, + 'video!' => \$videoSupport, + 'coverage!' => \$coverageSupport, + 'help' => \$showHelp, + 'universal' => \$buildUniversal, + '64-bit' => \$buildSixtyFourBit, + 'clean' => \$clean); + +if ($showHelp) { + print STDERR $usage; + exit 1; +} + +$svgExperimentalSupport = 0 unless $svgSupport; +$svgAnimationSupport = 0 unless $svgSupport; +$svgFiltersSupport = 0 unless $svgSupport; +$svgForeignObjectSupport = 0 unless $svgSupport; +$svgFontsSupport = 0 unless $svgSupport; +$svgAsImageSupport = 0 unless $svgSupport; +$svgUseSupport = 0 unless $svgSupport; + +if ($svgExperimentalSupport) { + $svgAnimationSupport = 1; + $svgFiltersSupport = 1; + $svgForeignObjectSupport = 1; + $svgFontsSupport = 1; + $svgAsImageSupport = 1; + $svgUseSupport = 1; +} + +checkRequiredSystemConfig(); +setConfiguration(); +chdirWebKit(); + +# FIXME: Migrate build-wxwebkit commands into build-webkit. +if (isWx()) { + my @opts = (); + $ENV{"WEBKITOUTPUTDIR"} = productDir(); + foreach (@ARGV) { + if ($_ eq "wxgc" || $_ eq "wxpython") { + push(@opts, $_); + } + } + if ($clean) { + push(@opts, "clean"); + } + system "WebKitTools/wx/build-wxwebkit @opts"; + exit exitStatus($?); +} + + +my $productDir = productDir(); +my @overrideFeatureDefinesOption = (); + +push @overrideFeatureDefinesOption, "ENABLE_CROSS_DOCUMENT_MESSAGING" if $crossDocumentMessagingSupport; +push @overrideFeatureDefinesOption, "ENABLE_DATABASE" if $databaseSupport; +push @overrideFeatureDefinesOption, "ENABLE_ICONDATABASE" if $iconDatabaseSupport; +push @overrideFeatureDefinesOption, "ENABLE_SVG" if $svgSupport; +push @overrideFeatureDefinesOption, "ENABLE_SVG_ANIMATION" if $svgAnimationSupport; +push @overrideFeatureDefinesOption, "ENABLE_SVG_FILTERS" if $svgFiltersSupport; +push @overrideFeatureDefinesOption, "ENABLE_SVG_FOREIGN_OBJECT" if $svgForeignObjectSupport; +push @overrideFeatureDefinesOption, "ENABLE_SVG_FONTS" if $svgFontsSupport; +push @overrideFeatureDefinesOption, "ENABLE_SVG_AS_IMAGE" if $svgAsImageSupport; +push @overrideFeatureDefinesOption, "ENABLE_SVG_USE" if $svgUseSupport; +push @overrideFeatureDefinesOption, "ENABLE_XPATH" if $xpathSupport; +push @overrideFeatureDefinesOption, "ENABLE_XSLT" if $xsltSupport; +push @overrideFeatureDefinesOption, "ENABLE_VIDEO" if $videoSupport; +my $overrideFeatureDefinesString = "FEATURE_DEFINES=" . join(" ", @overrideFeatureDefinesOption); + +my @coverageSupportOption = (); +if ($coverageSupport) { + push @coverageSupportOption, "GCC_GENERATE_TEST_COVERAGE_FILES=YES"; + push @coverageSupportOption, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES"; + push @coverageSupportOption, "EXTRA_LINK= -ftest-coverage -fprofile-arcs"; + push @coverageSupportOption, "OTHER_CFLAGS= -MD"; + push @coverageSupportOption, "OTHER_LDFLAGS=\$(OTHER_LDFLAGS) -ftest-coverage -fprofile-arcs -framework AppKit"; +} + +# Check that all the project directories are there. +my @projects = ("JavaScriptCore", "JavaScriptGlue", "WebCore", "WebKit"); +my @otherDirs = ("WebKitLibraries"); +for my $dir (@projects, @otherDirs) { + if (! -d $dir) { + die "Error: No $dir directory found. Please do a fresh checkout.\n"; + } +} + +my @options = (); + +if ($clean && isOSX()) { + push(@options, "-alltargets"); + push(@options, "clean"); +} + +if ($buildSixtyFourBit && isOSX()) { + my $cpuVendor = `sysctl -n machdep.cpu.vendor`; + chomp $cpuVendor; + + if ($buildUniversal) { + push(@options, "ARCHS=ppc ppc64 i386 x86_64"); + } elsif ($cpuVendor eq "GenuineIntel") { + push(@options, "ARCHS=i386 x86_64"); + } else { + push(@options, "ARCHS=ppc ppc64"); + } +} elsif ($buildUniversal && isOSX()) { + push(@options, "ARCHS=ppc i386"); +} + +# enable autotool options accordingly +if ($ENV{WEBKITAUTOTOOLS}) { + push @options, autotoolsFlag($crossDocumentMessagingSupport, "cross-document-messaging"); + push @options, autotoolsFlag($databaseSupport, "database"); + push @options, autotoolsFlag($iconDatabaseSupport, "icon-database"); + push @options, autotoolsFlag($svgSupport, "svg"); + push @options, autotoolsFlag($svgAnimationSupport, "svg-animation"); + push @options, autotoolsFlag($svgFiltersSupport, "svg-filters"); + push @options, autotoolsFlag($svgForeignObjectSupport, "svg-foreign-object"); + push @options, autotoolsFlag($svgFontsSupport, "svg-fonts"); + push @options, autotoolsFlag($svgAsImageSupport, "svg-as-image"); + push @options, autotoolsFlag($svgUseSupport, "svg-use-element"); + push @options, autotoolsFlag($xpathSupport, "xpath"); + push @options, autotoolsFlag($xsltSupport, "xslt"); + push @options, autotoolsFlag($videoSupport, "video"); + push @options, autotoolsFlag($coverageSupport, "coverage"); +} + +if (isOSX()) { + + push(@options, XcodeOptions()); + + # Copy library and header from WebKitLibraries to a findable place in the product directory. + my $srcLib = "WebKitLibraries/libWebKitSystemInterfaceTiger.a"; + my $lib = "$productDir/libWebKitSystemInterfaceTiger.a"; + if (!-e $lib || -M $lib > -M $srcLib) { + print "Updating $lib\n"; + system "ditto", $srcLib, $lib; + system "ranlib", $lib; + } + + $srcLib = "WebKitLibraries/libWebKitSystemInterfaceLeopard.a"; + $lib = "$productDir/libWebKitSystemInterfaceLeopard.a"; + if (!-e $lib || -M $lib > -M $srcLib) { + print "Updating $lib\n"; + system "ditto", $srcLib, $lib; + system "ranlib", $lib; + } + + my $srcHeader = "WebKitLibraries/WebKitSystemInterface.h"; + my $header = "$productDir/usr/local/include/WebKitSystemInterface.h"; + if (!-e $header || -M $header > -M $srcHeader) { + print "Updating $header\n"; + system "mkdir", "-p", "$productDir/usr/local/include"; + system "ditto", $srcHeader, $header; + } + + $srcLib = "WebKitLibraries/libWebCoreSQLite3.a"; + $lib = "$productDir/libWebCoreSQLite3.a"; + if (!-e $lib || -M $lib > -M $srcLib) { + print "Updating $lib\n"; + system "ditto", $srcLib, $lib; + system "ranlib", $lib; + } + + my $srcHeaderDir = "WebKitLibraries/WebCoreSQLite3"; + my $headerDir = "$productDir/WebCoreSQLite3"; + if (!-e $headerDir || -M $headerDir > -M $srcHeaderDir) { + print "Updating $headerDir\n"; + system "ditto", $srcHeaderDir, $headerDir; + } +} + +if (isGtk() && isDarwin() && !$ENV{WEBKITAUTOTOOLS} && !$ENV{QMAKESPEC}) { + # The qmake from Trolltech's binary "QT for Mac" distribution tries to + # create xcode projects, not Makefiles + $ENV{QMAKESPEC} = "macx-g++"; +} + +if (isCygwin()) { + # Copy WebKitSupportLibrary to the correct location in WebKitLibraries so it can be found. + # Will fail if WebKitSupportLibrary.zip is not in source root. + (system("perl WebKitTools/Scripts/update-webkit-support-libs") == 0) or die; +} + +# Force re-link of existing libraries if different than expected +removeLibraryDependingOnSVG("WebCore", $svgSupport); + +# Build, and abort if the build fails. +for my $dir (@projects) { + chdir $dir or die; + my $result = 0; + + if (isGtk()) { + if ($dir ne "WebKit") { + chdir ".." or die; + next; + } + + $result = buildGtkProject($dir, $clean, @options); + } elsif (isQt()) { + if ($dir ne "WebKit") { + chdir ".." or die; + next; + } + $result = buildQMakeQtProject($dir, $clean); + } elsif (isOSX()) { + $result = system "xcodebuild", "-project", "$dir.xcodeproj", @options, $overrideFeatureDefinesString, @coverageSupportOption, @ARGV; + } elsif (isCygwin()) { + if ($dir eq "WebKit") { + $result = buildVisualStudioProject("win/WebKit.vcproj/WebKit.sln", $clean); + } + } + + if (exitStatus($result)) { + if (isCygwin()) { + print "\n\n===== BUILD FAILED ======\n\n"; + my $scriptDir = relativeScriptsDir(); + print "Please ensure you have run $scriptDir/update-webkit to install depenedencies.\n\n"; + my $baseProductDir = baseProductDir(); + print "You can view build errors by checking the BuildLog.htm files located at:\n$baseProductDir/obj/<project>/<config>.\n"; + } + exit exitStatus($result); + } + chdir ".." or die; +} + +# Don't report the "WebKit is now built" message after a clean operation. +exit if $clean; + +# Write out congratulations message. + +my $launcherPath = launcherPath(); +my $launcherName = launcherName(); + +print "\n"; +print "===========================================================\n"; +print " WebKit is now built. To run $launcherName with this newly-built\n"; +print " code, use the \"$launcherPath\" script.\n"; +if ($svgSupport) { + print "\n NOTE: WebKit has been built with SVG support enabled.\n"; + print " $launcherName will have SVG viewing capabilities.\n"; +} +if ($svgAnimationSupport or $svgFiltersSupport or $svgForeignObjectSupport or $svgFontsSupport or $svgAsImageSupport or $svgUseSupport) { + print "\n NOTE: WebKit has been built with experimental SVG features enabled.\n"; + print " Your build supports: \n"; + print " * Basic SVG animation.\n" if $svgAnimationSupport; + print " * SVG filters.\n" if $svgFiltersSupport; + print " * SVG foreign object.\n" if $svgForeignObjectSupport; + print " * SVG fonts.\n" if $svgFontsSupport; + print " * SVG as image.\n" if $svgAsImageSupport; + print " * SVG <use> support.\n" if $svgUseSupport; +} +print "===========================================================\n"; diff --git a/WebKitTools/Scripts/check-dom-results b/WebKitTools/Scripts/check-dom-results new file mode 100755 index 0000000..0b32406 --- /dev/null +++ b/WebKitTools/Scripts/check-dom-results @@ -0,0 +1,141 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. 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 to check status of W3C DOM tests that are part of the WebKit tests. + +use strict; +use FindBin; +use Cwd; +use lib $FindBin::Bin; +use webkitdirs; + +chdirWebKit(); + +my $verbose = $ARGV[0] && $ARGV[0] eq "-v"; + +my $workingDir = getcwd(); +my $testDirectory = "$workingDir/LayoutTests"; + +my @suites = ( {"name" => "DOM Level 1 Core (html)", "directory" => "dom/html/level1/core"}, + {"name" => "DOM Level 2 Core (html)", "directory" => "dom/html/level2/core"}, + {"name" => "DOM Level 2 Events (html)", "directory" => "dom/html/level2/events"}, + {"name" => "DOM Level 2 HTML (html)", "directory" => "dom/html/level2/html"}, + {"name" => "DOM Level 1 Core (xhtml)", "directory" => "dom/xhtml/level1/core"}, + {"name" => "DOM Level 2 Core (xhtml)", "directory" => "dom/xhtml/level2/core"}, + {"name" => "DOM Level 2 Events (xhtml)", "directory" => "dom/xhtml/level2/events"}, + {"name" => "DOM Level 2 HTML (xhtml)", "directory" => "dom/xhtml/level2/html"}, + {"name" => "DOM Level 3 Core (xhtml)", "directory" => "dom/xhtml/level3/core"}, + {"name" => "DOM Level 3 XPath (svg)", "directory" => "dom/svg/level3/xpath"}); + +my $totalCount = 0; +my $totalSuccesses = 0; +my $totalDisabled = 0; +my $totalFailed = 0; + +foreach my $suite (@suites) { + + my %suite = %$suite; + my $directory = $suite{"directory"}; + my $name = $suite{"name"}; + my @results = `find "${testDirectory}/${directory}" -name "*-expected.txt"`; + my @disabled = `find "${testDirectory}/${directory}" -name "*-disabled"`; + + my @failures = (); + my $count = 0; + + foreach my $result (@results) { + $count++; + my $success = 0; + open RESULT, "<$result"; + while (<RESULT>) { + if (/Success/) { + $success = 1; + last; + } + } + close RESULT; + if (!$success) { + push @failures, $result; + } + } + + my $disabledCount = (scalar @disabled); + my $failureCount = (scalar @failures); + + $count += $disabledCount; + + my $successCount = $count - $failureCount - $disabledCount; + my $percentage = (sprintf "%.1f", ($successCount * 100.0 / $count)); + + if ($percentage == 100) { + print "${name}: all ${count} tests succeeded"; + } else { + print "${name}: ${successCount} out of ${count} tests succeeded (${percentage}%)"; + } + print " ($disabledCount disabled)" if $disabledCount; + print "\n"; + if ($verbose) { + print "\n"; + if (@disabled) { + print " Disabled:\n"; + + foreach my $failure (sort @disabled) { + $failure =~ s|.*/||; + $failure =~ s|-disabled||; + print " ${directory}/${failure}"; + } + } + if (@failures) { + print " Failed:\n"; + + foreach my $failure (sort @failures) { + $directory =~ m|^dom/(\w+)|; + my $extension = $1; + $failure =~ s|.*/||; + $failure =~ s|-expected\.txt|.${extension}|; + print " ${directory}/${failure}"; + } + } + + print "\n"; + } + + $totalCount += $count; + $totalSuccesses += $successCount; + $totalDisabled += $disabledCount; + $totalFailed += $failureCount; +} + + +my $totalPercentage = (sprintf "%.1f", ($totalSuccesses * 100.0 / $totalCount)); +my $totalDisabledPercentage = (sprintf "%.1f", ($totalDisabled * 100.0 / $totalCount)); +my $totalFailedPercentage = (sprintf "%.1f", ($totalFailed * 100.0 / $totalCount)); + +print "Total: ${totalSuccesses} out of ${totalCount} tests succeeded (${totalPercentage}%)\n"; +print " ${totalDisabled} tests disabled (${totalDisabledPercentage}%)\n"; +print " ${totalFailed} tests failed (${totalFailedPercentage}%)\n"; diff --git a/WebKitTools/Scripts/check-for-global-initializers b/WebKitTools/Scripts/check-for-global-initializers new file mode 100755 index 0000000..c73b8cc --- /dev/null +++ b/WebKitTools/Scripts/check-for-global-initializers @@ -0,0 +1,131 @@ +#!/usr/bin/perl + +# Copyright (C) 2006, 2007, 2008 Apple Inc. 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. + +# "check-for-global-initializers" script for Web Kit Open Source Project + +# Intended to be invoked from an Xcode build step to check if there are +# any global initializers in a target. + +use warnings; +use strict; + +use File::Basename; + +sub touch($); + +my $arch = $ENV{'CURRENT_ARCH'}; +my $configuration = $ENV{'CONFIGURATION'}; +my $target = $ENV{'TARGET_NAME'}; +my $variant = $ENV{'CURRENT_VARIANT'}; +my $coverageBuild = $ENV{'WEBKIT_COVERAGE_BUILD'}; +my $debugRoot = $ENV{'WEBKIT_DEBUG_ROOT'}; + +$arch = $ENV{'NATIVE_ARCH'} if !$arch; # for Xcode 2.1, which does not have CURRENT_ARCH +$variant = "normal" if !$variant; # for Xcode 2.1, which does not have CURRENT_VARIANT + +my $executablePath = "$ENV{'TARGET_BUILD_DIR'}/$ENV{'EXECUTABLE_PATH'}"; + +my $buildTimestampPath = $ENV{'TARGET_TEMP_DIR'} . "/" . basename($0) . ".timestamp"; +my $buildTimestampAge = -M $buildTimestampPath; + +touch($buildTimestampPath); + +my $list = $ENV{"LINK_FILE_LIST_${variant}_${arch}"}; + +if (!open LIST, $list) { + print "Could not open $list\n"; + exit 1; +} + +my @files = <LIST>; +chomp @files; +close LIST; + +my $sawError = 0; + +for my $file (sort @files) { + if (defined $buildTimestampAge) { + my $fileAge = -M $file; + next if defined $fileAge && $fileAge > $buildTimestampAge; + } + if (!open NM, "(nm '$file' | sed 's/^/STDOUT:/') 2>&1 |") { + print "Could not open $file\n"; + $sawError = 1; + next; + } + my $sawGlobal = 0; + while (<NM>) { + if (/^STDOUT:/) { + $sawGlobal = 1 if /__GLOBAL__I/; + } else { + print STDERR if $_ ne "nm: no name list\n"; + } + } + close NM; + if ($sawGlobal) { + my $shortName = $file; + $shortName =~ s/.*\///; + + # Special cases for files that have initializers in debug builds. + if ($configuration eq "Debug" or $debugRoot ) { + if ($target eq "JavaScriptCore") { + next if $shortName eq "nodes.o"; + next if $shortName eq "AllInOneFile.o"; + } + if ($target eq "WebCore") { + next if $shortName eq "CachedPage.o"; + next if $shortName eq "Frame.o"; + next if $shortName eq "JSCustomSQLTransactionCallback.o"; + next if $shortName eq "Node.o"; + next if $shortName eq "Page.o"; + next if $shortName eq "Range.o"; + next if $shortName eq "RenderObject.o"; + next if $shortName eq "SubresourceLoader.o"; + next if $shortName eq "bidi.o"; + next if $shortName eq "kjs_events.o"; + } + } + + print "$shortName has a global initializer in it! ($file)\n"; + $sawError = 1; + } +} + +if ($sawError and !$coverageBuild) { + unlink $executablePath; + exit 1; +} + +exit 0; + +sub touch($) +{ + my ($path) = @_; + open(TOUCH, ">", $path) or die "$!"; + close(TOUCH); +} diff --git a/WebKitTools/Scripts/clean-header-guards b/WebKitTools/Scripts/clean-header-guards new file mode 100755 index 0000000..2bad046 --- /dev/null +++ b/WebKitTools/Scripts/clean-header-guards @@ -0,0 +1,53 @@ +#!/usr/bin/ruby + +require 'find' +require 'optparse' + +options = {} +OptionParser.new do |opts| + opts.banner = "Usage: clean-header-guards [options]" + + opts.on("--prefix [PREFIX]", "Append a header prefix to all guards") do |prefix| + options[:prefix] = prefix + end +end.parse! + +IgnoredFilenamePatterns = [ + # ignore headers which are known not to have guard + /WebCorePrefix/, + /ForwardingHeaders/, + %r|bindings/objc|, + /vcproj/, # anything inside a vcproj is in the windows wasteland + + # we don't own any of these headers + %r|icu/unicode|, + %r|platform/graphics/cairo|, + %r|platform/image-decoders|, + + /config.h/ # changing this one sounds scary +].freeze + +IgnoreFileNamesPattern = Regexp.union(*IgnoredFilenamePatterns).freeze + +Find::find(".") do |filename| + next unless filename =~ /\.h$/ + next if filename.match(IgnoreFileNamesPattern) + + File.open(filename, "r+") do |file| + contents = file.read + match_results = contents.match(/#ifndef (\S+)\n#define \1/s) + if match_results + current_guard = match_results[1] + new_guard = File.basename(filename).sub('.', '_') + new_guard = options[:prefix] + '_' + new_guard if options[:prefix] + contents.gsub!(/#{current_guard}\b/, new_guard) + else + puts "Ignoring #{filename}, failed to find existing header guards." + end + tmp_filename = filename + ".tmp" + File.open(tmp_filename, "w+") do |new_file| + new_file.write(contents) + end + File.rename tmp_filename, filename + end +end diff --git a/WebKitTools/Scripts/commit-log-editor b/WebKitTools/Scripts/commit-log-editor new file mode 100755 index 0000000..e7ee5155 --- /dev/null +++ b/WebKitTools/Scripts/commit-log-editor @@ -0,0 +1,189 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006, 2007 Apple Inc. 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 to put change log comments in as default check-in comment. + +use strict; +use File::Basename; +use File::Spec; +use FindBin; +use lib $FindBin::Bin; +use VCSUtils; +use webkitdirs; + +my $log = $ARGV[0]; + +my $baseDir = baseProductDir(); + +my $editor = $ENV{SVN_LOG_EDITOR}; +if (!$editor) { + $editor = $ENV{CVS_LOG_EDITOR}; +} +if (!$editor) { + my $builtEditorApplication = "$baseDir/Release/Commit Log Editor.app/Contents/MacOS/Commit Log Editor"; + $editor = $builtEditorApplication if -x $builtEditorApplication; +} +if (!$editor) { + my $builtEditorApplication = "$baseDir/Debug/Commit Log Editor.app/Contents/MacOS/Commit Log Editor"; + $editor = $builtEditorApplication if -x $builtEditorApplication; +} +if (!$editor) { + my $installedEditorApplication = "$ENV{HOME}/Applications/Commit Log Editor.app/Contents/MacOS/Commit Log Editor"; + $editor = $installedEditorApplication if -x $installedEditorApplication; +} +if (!$editor) { + $editor = $ENV{EDITOR} || "/usr/bin/vi"; +} + +my $inChangesToBeCommitted = !isGit(); +my @changeLogs = (); +my $logContents = ""; +my $existingLog = 0; +open LOG, $log or die; +while (<LOG>) { + if (isGit()) { + if (/^# Changes to be committed:$/) { + $inChangesToBeCommitted = 1; + } elsif ($inChangesToBeCommitted && /^# \S/) { + $inChangesToBeCommitted = 0; + } + } + + $logContents .= $_; + $existingLog = isGit() && !(/^#/ || /^\s*$/) unless $existingLog; + + push @changeLogs, makeFilePathRelative($1) if $inChangesToBeCommitted && (/^M....(.*ChangeLog)$/ || /^#\tmodified: (.*ChangeLog)/) && !/-ChangeLog/; +} +close LOG; + +# Don't change anything if there's already a log message +# (as can happen with git-commit --amend) +exec $editor, @ARGV if $existingLog; + +my $topLevel = topLevelSourceDirectory(); + +my %changeLogSort; +my %changeLogContents; +for my $changeLog (@changeLogs) { + open CHANGELOG, $changeLog or die "Can't open $changeLog"; + my $contents = ""; + my $blankLines = ""; + while (<CHANGELOG>) { + if (/^\S/) { + last if $contents; + next; + } elsif (/\S/) { + $contents .= $blankLines if $contents; + $blankLines = ""; + $contents .= $_; + } else { + $blankLines .= $_; + } + } + close CHANGELOG; + + $changeLog = File::Spec->abs2rel(File::Spec->rel2abs($changeLog), $topLevel); + + my $label = dirname($changeLog); + $label = "top level" unless length $label; + + my $sortKey = lc $label; + if ($label eq "top level") { + $sortKey = ""; + } elsif ($label eq "Tools") { + $sortKey = "-, just after top level"; + } elsif ($label eq "WebBrowser") { + $sortKey = lc "WebKit, WebBrowser after"; + } elsif ($label eq "WebCore") { + $sortKey = lc "WebFoundation, WebCore after"; + } elsif ($label eq "LayoutTests") { + $sortKey = lc "~, LayoutTests last"; + } + + $changeLogSort{$sortKey} = $label; + $changeLogContents{$label} = $contents; +} + +my $first = 1; +open NEWLOG, ">$log.edit" or die; +for my $sortKey (sort keys %changeLogSort) { + my $label = $changeLogSort{$sortKey}; + if (keys %changeLogSort > 1) { + print NEWLOG "\n" if !$first; + $first = 0; + print NEWLOG "$label:\n\n"; + } + print NEWLOG $changeLogContents{$label}; +} +print NEWLOG $logContents; +close NEWLOG; + +system $editor, "$log.edit"; + +open NEWLOG, "$log.edit" or exit; +my $foundComment = 0; +while (<NEWLOG>) { + $foundComment = 1 if (/\S/ && !/^CVS:/); +} +close NEWLOG; + +if ($foundComment) { + open NEWLOG, "$log.edit" or die; + open LOG, ">$log" or die; + while (<NEWLOG>) { + print LOG; + } + close LOG; + close NEWLOG; +} + +unlink "$log.edit"; + +sub topLevelSourceDirectory +{ + if (isGit()) { + chomp(my $gitDir = `git rev-parse --git-dir`); + return dirname($gitDir); + } elsif (isSVN()) { + open(INFO, "-|", qw(svn info)) or die; + my ($root, $url); + while (my $line = <INFO>) { + if ($line =~ /^Repository Root: (.*)$/) { + $root = $1; + } elsif ($line =~ /^URL: (.*)$/) { + $url = $1; + } + } + close(INFO); + + my $path = $url; + $path =~ s/^\Q$root\E//; + $path =~ s/^\/?(branches\/[^\/]*|trunk)\/?//; + return File::Spec->rel2abs(File::Spec->catdir(map { ".." } File::Spec->splitdir($path))); + } +} diff --git a/WebKitTools/Scripts/compare-timing-files b/WebKitTools/Scripts/compare-timing-files new file mode 100755 index 0000000..11b470b --- /dev/null +++ b/WebKitTools/Scripts/compare-timing-files @@ -0,0 +1,88 @@ +#!/usr/bin/perl + +# Copyright (C) 2006 Apple Computer, Inc. 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. + +# This script takes two files that are lists of timings and compares them. + +use warnings; +use strict; +use Getopt::Long; + +my $usage = "compare-timing-files [-c|--count results] oldFile newFile"; + +my $count = 1; +GetOptions("c|count=i" => \$count); + +my ($file1, $file2) = @ARGV; +die "$usage\n" unless ($file1 && $file2 && @ARGV == 2); + +my ($oldAverage, $oldRange, $oldRangePercent) = parseResults($file1); +my ($newAverage, $newRange, $newRangePercent) = parseResults($file2); + +print "\n===== $file1 =====\n"; +if ($count == 1) { + print("fastest run: $oldAverage\n"); +} else { + print("average of fastest $count runs: $oldAverage\n"); + printf("range of fastest $count runs: %.2f%% (%d)\n", $oldRangePercent, $oldRange); +} + +print "\n===== $file2 =====\n"; +if ($count == 1) { + print("fastest run: $newAverage\n"); +} else { + print("average of fastest $count runs: $newAverage\n"); + printf("range of fastest $count runs: %.2f%% (%d)\n", $newRangePercent, $newRange); +} + +my $gainOrLoss = $newAverage <= $oldAverage ? "GAIN" : "LOSS"; +my $difference = abs($newAverage - $oldAverage); +my $differencePercent = $difference / $oldAverage * 100; +printf("\nperformance %s of %.2f%% (%.1f / %.1f)\n", $gainOrLoss, $differencePercent, $difference, $oldAverage); +print "\n"; + +sub parseResults +{ + my ($file) = @_; + + open(FILE, $file) or die "Couldn't open file: $file"; + my @results = <FILE>; + close(FILE); + + @results = sort(@results); + my $total = 0; + for (my $i = 0; $i < $count; $i++) { + $results[$i] =~ s/\D*//; # cut out non-digits + $total += $results[$i]; + } + my $average = $total / $count; + my $range = $results[$count - 1] - $results[0]; + my $rangePercent = $range / $results[$count - 1] * 100; + + return ($average, $range, $rangePercent); +} + diff --git a/WebKitTools/Scripts/debug-safari b/WebKitTools/Scripts/debug-safari new file mode 100755 index 0000000..52e97fe --- /dev/null +++ b/WebKitTools/Scripts/debug-safari @@ -0,0 +1,38 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Inc. 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 to run Safari in the platform's debugger for the WebKit Open Source Project. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); + +exit exitStatus(runSafari(1)); diff --git a/WebKitTools/Scripts/do-file-rename b/WebKitTools/Scripts/do-file-rename new file mode 100755 index 0000000..23a460c --- /dev/null +++ b/WebKitTools/Scripts/do-file-rename @@ -0,0 +1,110 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. 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 to do file renaming. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; +use File::Find; + +setConfiguration(); +chdirWebKit(); + +my %words; + +# find all files we want to process + +my @paths; +find(\&wanted, "WebCore"); + +sub wanted +{ + my $file = $_; + + if ($file eq "icu") { + $File::Find::prune = 1; + return; + } + + if ($file =~ /^\../) { + $File::Find::prune = 1; + return; + } + + return if $file =~ /^ChangeLog/; + return if -d $file; + + push @paths, $File::Find::name; +} + +my %renames = ( + "xxx.mm" => "yyy.mm", +); + +# rename files + +my %newFile; +for my $file (sort @paths) { + my $f = $file; + $f = "$1$renames{$2}" if $f =~ /^(.*\/)(\w+\.\w+)$/ && $renames{$2}; + $newFile{$file} = $f if $f ne $file; +} + +for my $file (sort @paths) { + if ($newFile{$file}) { + my $newFile = $newFile{$file}; + print "Renaming $file to $newFile\n"; + system "svn move $file $newFile"; + } +} + +# change all file contents + +for my $file (sort @paths) { + $file = $newFile{$file} if $newFile{$file}; + my $contents; + { + local $/; + open FILE, $file or die; + $contents = <FILE>; + close FILE; + } + my $newContents = $contents; + + for my $from (keys %renames) { + $newContents =~ s/\b\Q$from\E(?!["\w])/$renames{$from}/g; # this " unconfuses Xcode syntax highlighting + } + + if ($newContents ne $contents) { + open FILE, ">", $file or die; + print FILE $newContents; + close FILE; + } +} diff --git a/WebKitTools/Scripts/do-webcore-rename b/WebKitTools/Scripts/do-webcore-rename new file mode 100755 index 0000000..36f894a --- /dev/null +++ b/WebKitTools/Scripts/do-webcore-rename @@ -0,0 +1,345 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006, 2007, 2008 Apple Inc. 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 to do a rename in JavaScriptCore, WebCore, and WebKit. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; +use File::Find; + +setConfiguration(); +chdirWebKit(); + +my %words; + +# find all files we want to process + +my @paths; +find(\&wanted, "JavaScriptCore"); +find(\&wanted, "JavaScriptGlue"); +find(\&wanted, "WebCore"); +find(\&wanted, "WebKit"); + +sub wanted +{ + my $file = $_; + + if ($file eq "icu") { + $File::Find::prune = 1; + return; + } + + if ($file =~ /^\../) { + $File::Find::prune = 1; + return; + } + + return if $file =~ /^ChangeLog/; + return if -d $file; + + push @paths, $File::Find::name; +} + +my %renames = ( + "XSLTProcessorPrototypeTable" => "JSXSLTProcessorPrototypeTable", + "ActivationImp" => "Activation", + "ActivationImpData" => "ActivationData", + "ArrayInstance" => "JSArray", + "ArrayObjectImp" => "ArrayConstructor", + "ArrayProtoFuncConcat" => "ArrayFunctionConcat", + "ArrayProtoFuncEvery" => "ArrayFunctionEvery", + "ArrayProtoFuncFilter" => "ArrayFunctionFilter", + "ArrayProtoFuncForEach" => "ArrayFunctionForEach", + "ArrayProtoFuncIndexOf" => "ArrayFunctionIndexOf", + "ArrayProtoFuncJoin" => "ArrayFunctionJoin", + "ArrayProtoFuncLastIndexOf" => "ArrayFunctionLastIndexOf", + "ArrayProtoFuncMap" => "ArrayFunctionMap", + "ArrayProtoFuncPop" => "ArrayFunctionPop", + "ArrayProtoFuncPush" => "ArrayFunctionPush", + "ArrayProtoFuncReverse" => "ArrayFunctionReverse", + "ArrayProtoFuncShift" => "ArrayFunctionShift", + "ArrayProtoFuncSlice" => "ArrayFunctionSlice", + "ArrayProtoFuncSome" => "ArrayFunctionSome", + "ArrayProtoFuncSort" => "ArrayFunctionSort", + "ArrayProtoFuncSplice" => "ArrayFunctionSplice", + "ArrayProtoFuncToLocaleString" => "ArrayFunctionToLocaleString", + "ArrayProtoFuncToString" => "ArrayFunctionToString", + "ArrayProtoFuncUnShift" => "ArrayFunctionUnshift", + "BooleanInstance" => "BooleanObject", + "BooleanObjectImp" => "BooleanConstructor", + "BooleanProtoFunc" => "BooleanFunction", + "DateObjectFuncImp" => "DateFunction", + "DateObjectImp" => "DateConstructor", + "DateProtoFuncGetDate" => "DateFunctionGetDate", + "DateProtoFuncGetDay" => "DateFunctionGetDay", + "DateProtoFuncGetFullYear" => "DateFunctionGetFullYear", + "DateProtoFuncGetHours" => "DateFunctionGetHours", + "DateProtoFuncGetMilliSeconds" => "DateFunctionGetMilliSeconds", + "DateProtoFuncGetMinutes" => "DateFunctionGetMinutes", + "DateProtoFuncGetMonth" => "DateFunctionGetMonth", + "DateProtoFuncGetSeconds" => "DateFunctionGetSeconds", + "DateProtoFuncGetTime" => "DateFunctionGetTime", + "DateProtoFuncGetTimezoneOffset" => "DateFunctionGetTimezoneOffset", + "DateProtoFuncGetUTCDate" => "DateFunctionGetUTCDate", + "DateProtoFuncGetUTCDay" => "DateFunctionGetUTCDay", + "DateProtoFuncGetUTCFullYear" => "DateFunctionGetUTCFullYear", + "DateProtoFuncGetUTCHours" => "DateFunctionGetUTCHours", + "DateProtoFuncGetUTCMilliseconds" => "DateFunctionGetUTCMilliseconds", + "DateProtoFuncGetUTCMinutes" => "DateFunctionGetUTCMinutes", + "DateProtoFuncGetUTCMonth" => "DateFunctionGetUTCMonth", + "DateProtoFuncGetUTCSeconds" => "DateFunctionGetUTCSeconds", + "DateProtoFuncGetYear" => "DateFunctionGetYear", + "DateProtoFuncSetDate" => "DateFunctionSetDate", + "DateProtoFuncSetFullYear" => "DateFunctionSetFullYear", + "DateProtoFuncSetHours" => "DateFunctionSetHours", + "DateProtoFuncSetMilliSeconds" => "DateFunctionSetMilliSeconds", + "DateProtoFuncSetMinutes" => "DateFunctionSetMinutes", + "DateProtoFuncSetMonth" => "DateFunctionSetMonth", + "DateProtoFuncSetSeconds" => "DateFunctionSetSeconds", + "DateProtoFuncSetTime" => "DateFunctionSetTime", + "DateProtoFuncSetUTCDate" => "DateFunctionSetUTCDate", + "DateProtoFuncSetUTCFullYear" => "DateFunctionSetUTCFullYear", + "DateProtoFuncSetUTCHours" => "DateFunctionSetUTCHours", + "DateProtoFuncSetUTCMilliseconds" => "DateFunctionSetUTCMilliseconds", + "DateProtoFuncSetUTCMinutes" => "DateFunctionSetUTCMinutes", + "DateProtoFuncSetUTCMonth" => "DateFunctionSetUTCMonth", + "DateProtoFuncSetUTCSeconds" => "DateFunctionSetUTCSeconds", + "DateProtoFuncSetYear" => "DateFunctionSetYear", + "DateProtoFuncToDateString" => "DateFunctionToDateString", + "DateProtoFuncToGMTString" => "DateFunctionToGMTString", + "DateProtoFuncToLocaleDateString" => "DateFunctionToLocaleDateString", + "DateProtoFuncToLocaleString" => "DateFunctionToLocaleString", + "DateProtoFuncToLocaleTimeString" => "DateFunctionToLocaleTimeString", + "DateProtoFuncToString" => "DateFunctionToString", + "DateProtoFuncToTimeString" => "DateFunctionToTimeString", + "DateProtoFuncToUTCString" => "DateFunctionToUTCString", + "DateProtoFuncValueOf" => "DateFunctionValueOf", + "DebuggerImp" => "DebuggerData", + "ErrorObjectImp" => "ErrorConstructor", + "ErrorProtoFuncToString" => "ErrorFunction", + "FRAMES_ON_STACK" => "numFramesOnStack", + "FTPDirectoryTokenizer" => "FTPDirectoryDocumentBuilder", + "FunctionImp" => "JSFunction", + "FunctionObjectImp" => "FunctionConstructor", + "FunctionProtoFunc" => "FunctionFunction", + "GetterSetterImp" => "JSGetterSetter", + "GlobalFuncImp" => "GlobalFunction", + "GlobalImp" => "TestGlobalObject", + "HTMLGenericFormElement" => "HTMLFormControlElement", + "HTMLGenericFormElement_h" => "HTMLFormControlElement_h", + "HTMLTokenizer" => "HTMLDocumentBuilder", + "ImageConstructorImp" => "JSImageConstructor", + "ImageTokenizer" => "ImageDocumentBuilder", + "InternalFunctionImp" => "InternalFunction", + "JSXMLHttpRequestConstructorImp" => "JSXMLHttpRequestConstructor", + "KURL" => "URL", + "KURLCFNet" => "URLCF", + "KURLMac" => "URLMac", + "KURL_H_" => "URL_h", + "List" => "JSArgumentList", + "MathObjectImp" => "MathObject", + "MathProtoFuncACos" => "MathFunctionACos", + "MathProtoFuncASin" => "MathFunctionASin", + "MathProtoFuncATan" => "MathFunctionATan", + "MathProtoFuncATan2" => "MathFunctionATan2", + "MathProtoFuncAbs" => "MathFunctionAbs", + "MathProtoFuncCeil" => "MathFunctionCeil", + "MathProtoFuncCos" => "MathFunctionCos", + "MathProtoFuncExp" => "MathFunctionExp", + "MathProtoFuncFloor" => "MathFunctionFloor", + "MathProtoFuncLog" => "MathFunctionLog", + "MathProtoFuncMax" => "MathFunctionMax", + "MathProtoFuncMin" => "MathFunctionMin", + "MathProtoFuncPow" => "MathFunctionPow", + "MathProtoFuncRandom" => "MathFunctionRandom", + "MathProtoFuncRound" => "MathFunctionRound", + "MathProtoFuncSin" => "MathFunctionSin", + "MathProtoFuncSqrt" => "MathFunctionSqrt", + "MathProtoFuncTan" => "MathFunctionTan", + "NativeErrorImp" => "NativeErrorConstructor", + "Navigator" => "JSNavigator", + "NumberImp" => "JSNumberCell", + "NumberInstance" => "NumberObject", + "NumberObjectImp" => "NumberConstructor", + "NumberProtoFunc" => "NumberFunction", + "ObjcFallbackObjectImp" => "ObjCFallbackObject", + "ObjectObjectImp" => "ObjectConstructor", + "ObjectProtoFunc" => "ObjectFunction", + "PluginTokenizer" => "PluginDocumetBuilder", + "RECURSIVE_MATCH_STARTNG_NEW_GROUP" => "RECURSIVE_MATCH_NEW_GROUP", + "RegExpImp" => "RegExpObject", + "RegExpObjectImp" => "RegExpConstructor", + "RegExpObjectImpPrivate" => "RegExpConstructorPrivate", + "RegExpProtoFunc" => "RegExpFunction", + "RuntimeObjectImp" => "ForeignObject", + "StringImp" => "JSString", + "StringImpl" => "SharedString", + "StringInstance" => "StringObject", + "StringInstanceThatMasqueradesAsUndefined" => "StringObjectThatMasqueradesAsUndefined", + "StringObjectFuncImp" => "StringConstructorFunction", + "StringObjectImp" => "StringConstructor", + "StringProtoFuncAnchor" => "StringFunctionAnchor", + "StringProtoFuncBig" => "StringFunctionBig", + "StringProtoFuncBlink" => "StringFunctionBlink", + "StringProtoFuncBold" => "StringFunctionBold", + "StringProtoFuncCharAt" => "StringFunctionCharAt", + "StringProtoFuncCharCodeAt" => "StringFunctionCharCodeAt", + "StringProtoFuncConcat" => "StringFunctionConcat", + "StringProtoFuncFixed" => "StringFunctionFixed", + "StringProtoFuncFontcolor" => "StringFunctionFontcolor", + "StringProtoFuncFontsize" => "StringFunctionFontsize", + "StringProtoFuncIndexOf" => "StringFunctionIndexOf", + "StringProtoFuncItalics" => "StringFunctionItalics", + "StringProtoFuncLastIndexOf" => "StringFunctionLastIndexOf", + "StringProtoFuncLink" => "StringFunctionLink", + "StringProtoFuncLocaleCompare" => "StringFunctionLocaleCompare", + "StringProtoFuncMatch" => "StringFunctionMatch", + "StringProtoFuncReplace" => "StringFunctionReplace", + "StringProtoFuncSearch" => "StringFunctionSearch", + "StringProtoFuncSlice" => "StringFunctionSlice", + "StringProtoFuncSmall" => "StringFunctionSmall", + "StringProtoFuncSplit" => "StringFunctionSplit", + "StringProtoFuncStrike" => "StringFunctionStrike", + "StringProtoFuncSub" => "StringFunctionSub", + "StringProtoFuncSubstr" => "StringFunctionSubstr", + "StringProtoFuncSubstring" => "StringFunctionSubstring", + "StringProtoFuncSup" => "StringFunctionSup", + "StringProtoFuncToLocaleLowerCase" => "StringFunctionToLocaleLowerCase", + "StringProtoFuncToLocaleUpperCase" => "StringFunctionToLocaleUpperCase", + "StringProtoFuncToLowerCase" => "StringFunctionToLowerCase", + "StringProtoFuncToString" => "StringFunctionToString", + "StringProtoFuncToUpperCase" => "StringFunctionToUpperCase", + "StringProtoFuncValueOf" => "StringFunctionValueOf", + "TestFunctionImp" => "TestFunction", + "TextTokenizer" => "TextDocumentBuilder", + "ThreadSafeShared" => "ThreadSafeRefCounted", + "Tokenizer" => "DocumentBuilder", + "Tokenizer_h" => "DocumentBuilder_h", + "XMLTokenizer" => "XMLDocumentBuilder", + "XSLTProcessorConstructorImp" => "JSXSLTProcessorConstructor", + "XSLTProcessorPrototype" => "JSXSLTProcessorPrototype", + "animationController" => "animation", + "branchfirstbyte" => "branchFirstByte", + "branchreqbyte" => "branchReqByte", + "class_charcount" => "classCharCount", + "class_lastchar" => "classLastChar", + "codeptr" => "codePtr", + "createTokenizer" => "createBuilder", + "domString" => "string", + "equalIgnoringCase" => "equalFoldingCase", + "errorcodeptr" => "errorCodePtr", + "errorptr" => "errorPtr", + "first_byte" => "firstByte", + "first_byte_caseless" => "firstByteIsCaseless", + "first_char" => "firstChar", + "firstbyte" => "firstByte", + "groupsetfirstbyte" => "didGroupSetFirstByte", + "isHTMLTokenizer" => "isHTMLDocumentBuilder", + "is_quantifier" => "isQuantifier", + "isclass" => "isClass", + "kjs_binding" => "JSDOMBinding", + "kjs_binding_h" => "JSDOMBinding_h", + "kjs_css" => "JSRGBColor", + "kjs_css_h" => "JSRGBColor_h", + "kjs_proxy" => "ScriptController", + "kjs_proxy_h" => "ScriptController_h", + "last_branch" => "lastBranch", + "m_tokenizer" => "m_builder", + "mclength" => "mcLength", + "negate_class" => "negateClass", + "offsetcount" => "offsetCount", + "op_type" => "opType", + "prev_length" => "prevLength", + "ptrptr" => "ptrPtr", + "repeat_min" => "repeatMin", + "repeat_type" => "repeatType", + "req_byte" => "reqByte", + "req_byte2" => "reqByte2", + "req_byte_caseless" => "reqByteIsCaseless", + "req_caseopt" => "reqCaseOpt", + "req_varyopt" => "reqVaryOpt", + "reqbyte" => "reqByte", + "resetcount" => "resetCount", + "scriptProxy" => "script", + "selectionController" => "selection", + "should_flip_negation" => "shouldFlipNegation", + "skipbytes" => "skipBytes", + "subfirstbyte" => "subFirstByte", + "subreqbyte" => "subReqByte", + "tokenizerProcessedData" => "documentBuilderProcessedData", + "top_backref" => "topBackref", + "top_bracket" => "topBracket", + "using_temporary_offsets" => "usingTemporaryOffsets", + "zerofirstbyte" => "zeroFirstByte", + "zeroreqbyte" => "zeroReqByte", +); + +# rename files + +my %newFile; +for my $file (sort @paths) { + my $f = $file; + $f = "$1$renames{$2}$3" if $f =~ /^(.*\/)(\w+)(\.\w+)$/ && $renames{$2}; + if ($f ne $file) { + $newFile{$file} = $f; + } +} + +for my $file (sort @paths) { + if ($newFile{$file}) { + my $newFile = $newFile{$file}; + print "Renaming $file to $newFile\n"; + system "svn move $file $newFile"; + } +} + +# change all file contents + +for my $file (sort @paths) { + $file = $newFile{$file} if $newFile{$file}; + my $contents; + { + local $/; + open FILE, $file or die; + $contents = <FILE>; + close FILE; + } + my $newContents = $contents; + + for my $from (keys %renames) { + $newContents =~ s/\b$from(?!["\w])/$renames{$from}/g; # this " unconfuses Xcode syntax highlighting + } + + if ($newContents ne $contents) { + open FILE, ">", $file or die; + print FILE $newContents; + close FILE; + } +} diff --git a/WebKitTools/Scripts/extract-localizable-strings b/WebKitTools/Scripts/extract-localizable-strings new file mode 100755 index 0000000..15d6782 --- /dev/null +++ b/WebKitTools/Scripts/extract-localizable-strings @@ -0,0 +1,359 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006, 2007 Apple Inc. 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. + +# This script is like the genstrings tool (minus most of the options) with these differences. +# +# 1) It uses the names UI_STRING and UI_STRING_WITH_KEY for the macros, rather than the macros +# from NSBundle.h, and doesn't support tables (although they would be easy to add). +# 2) It supports UTF-8 in key strings (and hence uses "" strings rather than @"" strings; +# @"" strings only reliably support ASCII since they are decoded based on the system encoding +# at runtime, so give different results on US and Japanese systems for example). +# 3) It looks for strings that are not marked for localization, using both macro names that are +# known to be used for debugging in Intrigue source code and an exceptions file. +# 4) It finds the files to work on rather than taking them as parameters, and also uses a +# hardcoded location for both the output file and the exceptions file. +# It would have been nice to use the project to find the source files, but it's too hard to +# locate source files after parsing a .pbxproj file. + +# The exceptions file has a list of strings in quotes, filenames, and filename/string pairs separated by :. + +use strict; + +my $stringsFile = "English.lproj/Localizable.strings"; +my %isDebugMacro = ( ASSERT_WITH_MESSAGE => 1, LOG_ERROR => 1, ERROR => 1, NSURL_ERROR => 1, FATAL => 1, LOG => 1, dprintf => 1, NSException => 1, NSLog => 1, printf => 1 ); + +@ARGV >= 1 or die "Usage: extract-localizable-strings <exceptions file> [ directory... ]\nDid you mean to run extract-webkit-localizable-strings instead?\n"; + +my $exceptionsFile = shift @ARGV; +-f $exceptionsFile or die "Couldn't find exceptions file $exceptionsFile\n"; + +my @directories = (); +my @directoriesToSkip = (); +if (@ARGV < 1) { + push(@directories, "."); +} else { + for my $dir (@ARGV) { + if ($dir =~ /^-(.*)$/) { + push @directoriesToSkip, $1; + } else { + push @directories, $dir; + } + } +} + +my $sawError = 0; + +my $localizedCount = 0; +my $keyCollisionCount = 0; +my $notLocalizedCount = 0; +my $NSLocalizeCount = 0; + +my %exception; +my %usedException; + +if (open EXCEPTIONS, $exceptionsFile) { + while (<EXCEPTIONS>) { + chomp; + if (/^"([^\\"]|\\.)*"$/ or /^[-_\/\w.]+.(h|m|mm|c|cpp)$/ or /^[-_\/\w.]+.(h|m|mm|c|cpp):"([^\\"]|\\.)*"$/) { + if ($exception{$_}) { + print "$exceptionsFile:$.:exception for $_ appears twice\n"; + print "$exceptionsFile:$exception{$_}:first appearance\n"; + } else { + $exception{$_} = $.; + } + } else { + print "$exceptionsFile:$.:syntax error\n"; + } + } + close EXCEPTIONS; +} + +my $quotedDirectoriesString = '"' . join('" "', @directories) . '"'; +for my $dir (@directoriesToSkip) { + $quotedDirectoriesString .= ' -path "' . $dir . '" -prune'; +} + +my @files = ( split "\n", `find $quotedDirectoriesString -name "*.h" -o -name "*.m" -o -name "*.mm" -o -name "*.c" -o -name "*.cpp"` ); + +for my $file (sort @files) { + next if $file =~ /\/WebLocalizableStrings\.h$/; + next if $file =~ /\/icu\//; + + $file =~ s-^./--; + + open SOURCE, $file or die "can't open $file\n"; + + my $inComment = 0; + + my $expected = ""; + my $macroLine; + my $macro; + my $UIString; + my $key; + my $comment; + + my $string; + my $stringLine; + my $nestingLevel; + + my $previousToken = ""; + + while (<SOURCE>) { + chomp; + + # Handle continued multi-line comment. + if ($inComment) { + next unless s-.*\*/--; + $inComment = 0; + } + + # Handle all the tokens in the line. + while (s-^\s*([#\w]+|/\*|//|[^#\w/'"()\[\],]+|.)--) { + my $token = $1; + + if ($token eq "\"") { + if ($expected and $expected ne "a quoted string") { + print "$file:$.:ERROR:found a quoted string but expected $expected\n"; + $sawError = 1; + $expected = ""; + } + if (s-^(([^\\$token]|\\.)*?)$token--) { + if (!defined $string) { + $stringLine = $.; + $string = $1; + } else { + $string .= $1; + } + } else { + print "$file:$.:ERROR:mismatched quotes\n"; + $sawError = 1; + $_ = ""; + } + next; + } + + if (defined $string) { +handleString: + if ($expected) { + if (!defined $UIString) { + # FIXME: Validate UTF-8 here? + $UIString = $string; + $expected = ","; + } elsif (($macro eq "UI_STRING_KEY" or $macro eq "LPCTSTR_UI_STRING_KEY") and !defined $key) { + # FIXME: Validate UTF-8 here? + $key = $string; + $expected = ","; + } elsif (!defined $comment) { + # FIXME: Validate UTF-8 here? + $comment = $string; + $expected = ")"; + } + } else { + if (defined $nestingLevel) { + # In a debug macro, no need to localize. + } elsif ($previousToken eq "#include" or $previousToken eq "#import") { + # File name, no need to localize. + } elsif ($previousToken eq "extern" and $string eq "C") { + # extern "C", no need to localize. + } elsif ($string eq "") { + # Empty string can sometimes be localized, but we need not complain if not. + } elsif ($exception{$file}) { + $usedException{$file} = 1; + } elsif ($exception{"\"$string\""}) { + $usedException{"\"$string\""} = 1; + } elsif ($exception{"$file:\"$string\""}) { + $usedException{"$file:\"$string\""} = 1; + } else { + print "$file:$stringLine:\"$string\" is not marked for localization\n"; + $notLocalizedCount++; + } + } + $string = undef; + last if !defined $token; + } + + $previousToken = $token; + + if ($token =~ /^NSLocalized/ && $token !~ /NSLocalizedDescriptionKey/ && $token !~ /NSLocalizedStringFromTableInBundle/) { + print "$file:$.:ERROR:found a use of an NSLocalized macro; not supported\n"; + $nestingLevel = 0 if !defined $nestingLevel; + $sawError = 1; + $NSLocalizeCount++; + } elsif ($token eq "/*") { + if (!s-^.*?\*/--) { + $_ = ""; # If the comment doesn't end, discard the result of the line and set flag + $inComment = 1; + } + } elsif ($token eq "//") { + $_ = ""; # Discard the rest of the line + } elsif ($token eq "'") { + if (!s-([^\\]|\\.)'--) { #' <-- that single quote makes the Project Builder editor less confused + print "$file:$.:ERROR:mismatched single quote\n"; + $sawError = 1; + $_ = ""; + } + } else { + if ($expected and $expected ne $token) { + print "$file:$.:ERROR:found $token but expected $expected\n"; + $sawError = 1; + $expected = ""; + } + if ($token eq "UI_STRING" or $token eq "UI_STRING_KEY" or $token eq "LPCTSTR_UI_STRING" or $token eq "LPCTSTR_UI_STRING_KEY") { + $expected = "("; + $macro = $token; + $UIString = undef; + $key = undef; + $comment = undef; + $macroLine = $.; + } elsif ($token eq "(" or $token eq "[") { + ++$nestingLevel if defined $nestingLevel; + $expected = "a quoted string" if $expected; + } elsif ($token eq ",") { + $expected = "a quoted string" if $expected; + } elsif ($token eq ")" or $token eq "]") { + $nestingLevel = undef if defined $nestingLevel && !--$nestingLevel; + if ($expected) { + $key = $UIString if !defined $key; + HandleUIString($UIString, $key, $comment, $file, $macroLine); + $macro = ""; + $expected = ""; + $localizedCount++; + } + } elsif ($isDebugMacro{$token}) { + $nestingLevel = 0 if !defined $nestingLevel; + } + } + } + + } + + goto handleString if defined $string; + + if ($expected) { + print "$file:ERROR:reached end of file but expected $expected\n"; + $sawError = 1; + } + + close SOURCE; +} + +my %stringByKey; +my %commentByKey; +my %fileByKey; +my %lineByKey; + +sub HandleUIString +{ + my ($string, $key, $comment, $file, $line) = @_; + + my $bad = 0; + if (grep { $_ == 0xFFFD } unpack "U*", $string) { + print "$file:$line:ERROR:string for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n"; + $bad = 1; + } + if ($string ne $key && grep { $_ == 0xFFFD } unpack "U*", $key) { + print "$file:$line:ERROR:key has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n"; + $bad = 1; + } + if (grep { $_ == 0xFFFD } unpack "U*", $comment) { + print "$file:$line:ERROR:comment for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n"; + $bad = 1; + } + if ($bad) { + $sawError = 1; + return; + } + + if ($stringByKey{$key} && $stringByKey{$key} ne $string) { + print "$file:$line:encountered the same key, \"$key\", twice, with different strings\n"; + print "$fileByKey{$key}:$lineByKey{$key}:previous occurrence\n"; + $keyCollisionCount++; + return; + } + if ($commentByKey{$key} && $commentByKey{$key} ne $comment) { + print "$file:$line:encountered the same key, \"$key\", twice, with different comments\n"; + print "$fileByKey{$key}:$lineByKey{$key}:previous occurrence\n"; + $keyCollisionCount++; + return; + } + + $fileByKey{$key} = $file; + $lineByKey{$key} = $line; + $stringByKey{$key} = $string; + $commentByKey{$key} = $comment; +} + +print "\n" if $sawError || $notLocalizedCount || $NSLocalizeCount; + +my @unusedExceptions = sort grep { !$usedException{$_} } keys %exception; +if (@unusedExceptions) { + for my $unused (@unusedExceptions) { + print "$exceptionsFile:$exception{$unused}:exception $unused not used\n"; + } + print "\n"; +} + +print "$localizedCount localizable strings\n" if $localizedCount; +print "$keyCollisionCount key collisions\n" if $keyCollisionCount; +print "$notLocalizedCount strings not marked for localization\n" if $notLocalizedCount; +print "$NSLocalizeCount uses of NSLocalize\n" if $NSLocalizeCount; +print scalar(@unusedExceptions), " unused exceptions\n" if @unusedExceptions; + +if ($sawError) { + print "\nErrors encountered. Exiting without writing a $stringsFile file.\n"; + exit 1; +} + +my $localizedStrings = ""; + +for my $key (sort keys %commentByKey) { + $localizedStrings .= "/* $commentByKey{$key} */\n\"$key\" = \"$stringByKey{$key}\";\n\n"; +} + +# Write out the strings file in UTF-16 with a BOM. +utf8::decode($localizedStrings) if $^V ge chr(5).chr(8); +my $output = pack "n*", (0xFEFF, unpack "U*", $localizedStrings); +foreach my $directory (@directories) { + if (-e "$directory/mac/$stringsFile") { + open STRINGS, ">", "$directory/mac/$stringsFile" or die; + print STRINGS $output; + close STRINGS; + } + + if (-e "$directory/win/$stringsFile") { + open STRINGS, ">", "$directory/win/$stringsFile" or die; + print STRINGS $output; + close STRINGS; + } + + if (-e "$directory/$stringsFile") { + open STRINGS, ">", "$directory/$stringsFile" or die; + print STRINGS $output; + close STRINGS; + } +} diff --git a/WebKitTools/Scripts/find-extra-includes b/WebKitTools/Scripts/find-extra-includes new file mode 100755 index 0000000..1286cd5 --- /dev/null +++ b/WebKitTools/Scripts/find-extra-includes @@ -0,0 +1,102 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. 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. + +# "find-extra-includes" script for Web Kit Open Source Project + +use strict; +use File::Find; + +find(\&wanted, @ARGV ? @ARGV : "."); + +my %paths; +my %includes; + +sub wanted +{ + my $file = $_; + + if ($file eq "icu") { + $File::Find::prune = 1; + return; + } + + if ($file !~ /^\./ && $file =~ /\.(h|cpp|c|mm|m)$/) { + $paths{$file} = $File::Find::name; + open FILE, $file or die; + while (<FILE>) { + if (m-^\s*#\s*(include|import)\s+["<]((\S+/)*)(\S+)[">]-) { + my $include = ($2 eq "sys/" ? $2 : "") . $4; + $includes{$file}{$include}++; + } + } + close FILE; + } +} + +my %totalIncludes; + +sub fillOut +{ + my ($file) = @_; + + return if defined $totalIncludes{$file}; + + for my $include (keys %{ $includes{$file} }) { + $totalIncludes{$file}{$include} = 1; + fillOut($include); + for my $i (keys %{ $totalIncludes{$include} }) { + $totalIncludes{$file}{$i} = 1; + } + } +} + +sub check +{ + my ($file) = @_; + + for my $include (keys %{ $includes{$file} }) { + fillOut($include); + } + for my $i1 (sort keys %{ $includes{$file} }) { + for my $i2 (keys %{ $includes{$file} }) { + next if $i1 eq $i2; + if ($totalIncludes{$i2}{$i1}) { + my $b1 = $i1; + my $b2 = $file; + $b1 =~ s/\..+$//; + $b2 =~ s/\..+$//; + print "$paths{$file} does not need to include $i1, because $i2 does\n" if $b1 ne $b2; + last; + } + } + } +} + +for my $file (sort keys %includes) { + check($file); +} diff --git a/WebKitTools/Scripts/find-included-framework-headers b/WebKitTools/Scripts/find-included-framework-headers new file mode 100755 index 0000000..3e7aaf6 --- /dev/null +++ b/WebKitTools/Scripts/find-included-framework-headers @@ -0,0 +1,10 @@ +#!/bin/sh + +FILE_EXTENSIONS_TO_SEARCH="cpp h m mm" + +for framework in $*; do + echo -e "\n$framework\n==================" + for ext in ${FILE_EXTENSIONS_TO_SEARCH}; do + find . -name "*.$ext" -exec grep $framework {} ';' | grep '\(include\|import\)' | sed -e 's|.*/\(.*\.h\).*|\1|' + done | sort | uniq +done diff --git a/WebKitTools/Scripts/gdb-drosera b/WebKitTools/Scripts/gdb-drosera new file mode 100644 index 0000000..fcde476 --- /dev/null +++ b/WebKitTools/Scripts/gdb-drosera @@ -0,0 +1,59 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Computer, Inc. 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. + +# Simplified "run under gdb" script for Web Kit Open Source Project. + +use strict; +use Getopt::Long; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; +use File::Temp qw/:mktemp/; + +setConfiguration(); +my $productDir = productDir(); +my $droseraPath = "$productDir/Drosera.app/Contents/MacOS/Drosera"; + +# Check to see that gdb is in the usual place. +my $gdbPath = "/usr/bin/gdb"; +die "Can't find gdb executable. Is gdb installed?\n" unless -x $gdbPath; + +# Check to see that all the frameworks are built. +checkFrameworks(); + +# Put a command to set DYLD_FRAMEWORK_PATH in a temp file. +my ($fh, $path) = mkstemp("/tmp/gdb-drosera-XXXX"); +print $fh "set env DYLD_FRAMEWORK_PATH $productDir\n"; + +# Start up Drosera. +print "Start Drosera under gdb with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; +exec $gdbPath, "-x", $path, $droseraPath or die; + +# Delete the temporary file. +unlink0($fh, $path) or die "Error unlinking file $path safely"; + diff --git a/WebKitTools/Scripts/gdb-safari b/WebKitTools/Scripts/gdb-safari new file mode 100755 index 0000000..b94dc12 --- /dev/null +++ b/WebKitTools/Scripts/gdb-safari @@ -0,0 +1,61 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. 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. + +# Simplified "run under gdb" script for Web Kit Open Source Project. + +use strict; +use Getopt::Long; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; +use File::Temp qw/:mktemp/; + +setConfiguration(); +my $productDir = productDir(); +my $safariPath = safariPath(); + +# Check to see that gdb is in the usual place. +my $gdbPath = "/usr/bin/gdb"; +die "Can't find gdb executable. Is gdb installed?\n" unless -x $gdbPath; + +# Check to see that all the frameworks are built. +checkFrameworks(); + +# Put a command to set DYLD_FRAMEWORK_PATH in a temp file. +# Also set WEBKIT_UNSET_DYLD_FRAMEWORK_PATH to YES in this environment, so that +# executables launched by Safari don't inherit using the new frameworks. +my ($fh, $path) = mkstemp("/tmp/gdb-safari-XXXX"); +print $fh "set env DYLD_FRAMEWORK_PATH $productDir\n"; +print $fh "set env WEBKIT_UNSET_DYLD_FRAMEWORK_PATH YES\n"; + +# Start up Safari. +print "Start Safari under gdb with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; +exec $gdbPath, "-x", $path, $safariPath or die; + +# Delete the temporary file. +unlink0($fh, $path) or die "Error unlinking file $path safely"; diff --git a/WebKitTools/Scripts/generate-coverage-data b/WebKitTools/Scripts/generate-coverage-data new file mode 100755 index 0000000..7ed36aa --- /dev/null +++ b/WebKitTools/Scripts/generate-coverage-data @@ -0,0 +1,71 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2007 Holger Hans Peter Freyther. 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. + +# Simple script to build, run and visualize coverage information + +use strict; +use File::Basename; +use File::Spec; +use FindBin; +use Getopt::Long qw(:config pass_through); +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +# Generate a name for our results +my $svnVersion = determineCurrentSVNRevision(); +my @timeData = localtime(time); +my $resultName = $svnVersion . "-" . join('_', @timeData); +my @otherOptions = (); + +# Move to the source directory +# Delete old gcov files +# Compile WebKit and run the tests +# Generate the coverage graph... +# Upload + +$ENV{'WEBKIT_COVERAGE_BUILD'} = 1; +chdirWebKit(); + +# Clean-up old files +print "Cleaning up\n"; +system("if [ -d WebKitBuild ]; then find WebKitBuild -name '*.gcda' -delete; fi;") == 0 or die; + + +print "Building and testing\n"; +system("WebKitTools/Scripts/build-webkit", "--coverage", @ARGV) == 0 or die; +system "WebKitTools/Scripts/run-webkit-tests", "--no-launch-safari"; +system "WebKitTools/Scripts/run-javascriptcore-tests", "--coverage", @ARGV; + +# Collect the data and generate a report +print "Collecting coverage data\n"; +system("WebKitTools/CodeCoverage/run-generate-coverage-data", $resultName, "WebKitBuild/Coverage") == 0 or die; +system("WebKitTools/CodeCoverage/regenerate-coverage-display", "WebKitBuild/Coverage", "WebKitBuild/Coverage/html") == 0 or die; + +print "Done\n"; diff --git a/WebKitTools/Scripts/make-js-test-wrappers b/WebKitTools/Scripts/make-js-test-wrappers new file mode 100755 index 0000000..b58978f --- /dev/null +++ b/WebKitTools/Scripts/make-js-test-wrappers @@ -0,0 +1,103 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. 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 to generate HTML wrappers for JavaScript tests from templates + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); +my $productDir = productDir(); + +use strict; + +chdirWebKit(); + +my @templates = `find LayoutTests -name "TEMPLATE.html"`; + +for my $tfile (@templates) { + + chomp $tfile; + + my $tpath = $tfile; + $tpath =~ s:/resources/TEMPLATE.html$::; + + print "${tpath}\n"; + + chdirWebKit(); + chdir($tpath); + + my @files = `find resources -name "*.js"`; + + open TEMPLATE, "<resources/TEMPLATE.html"; + my $template = do { local $/; <TEMPLATE> }; + close TEMPLATE; + + my $templateNegative = $template; + if (-e "resources/TEMPLATE-n.html") { + open TEMPLATE, "<resources/TEMPLATE-n.html"; + $templateNegative = do { local $/; <TEMPLATE> }; + close TEMPLATE; + } + + for my $file (@files) { + chomp $file; + next if $file =~ /js-test-.*\.js$/; + next if $file =~ /SVGTestCase\.js/; + next if $file =~ m:resources/attr-case-sensitivity\.js$:; + next if $file =~ m:resources/frame-loading-via-document-write\.js$:; + next if $file =~ m:resources/intersectsNode\.js$:; + next if $file =~ m:resources/script-element-gc\.js$:; + next if $file =~ m:resources/script-element-gc\.js$:; + next if $file =~ m:resources/script3\.js$:; + next if $file =~ m:resources/script4\.js$:; + next if $file =~ m:resources/script5\.js$:; + next if $file =~ m:resources/select-options-remove\.js$:; + next if $file =~ m:resources/wrapper-identity-base\.js$:; + + my $html = $file; + $html =~ s:resources/(.*)\.js:$1.html:; + next if -f "$html-disabled"; + + system("grep -q 'successfullyParsed =' $file"); + if ($? != 0) { + `echo "" >> "${file}"`; + `echo "var successfullyParsed = true;" >> "${file}"`; + } + + print " ${html}\n"; + open HTML, ">$html"; + my $output = ($file =~ /-n\.js/) ? $templateNegative : $template; + $output =~ s:YOUR_JS_FILE_HERE:$file:; + print HTML $output; + + close HTML; + } +} diff --git a/WebKitTools/Scripts/num-cpus b/WebKitTools/Scripts/num-cpus new file mode 100755 index 0000000..c5f28a1 --- /dev/null +++ b/WebKitTools/Scripts/num-cpus @@ -0,0 +1,16 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Win32API::Registry 0.21 qw( :ALL ); + + +my $key; +my $i = 0; +while (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\$i", 0, KEY_READ, $key)) { + $i++; + RegCloseKey($key); +} + +print "$i\n"; diff --git a/WebKitTools/Scripts/parallelcl b/WebKitTools/Scripts/parallelcl new file mode 100755 index 0000000..532079f --- /dev/null +++ b/WebKitTools/Scripts/parallelcl @@ -0,0 +1,224 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use File::Basename; +use File::Spec; +use File::Temp; +use POSIX; + +sub makeJob(\@$); +sub forkAndCompileFiles(\@$); +sub Exec($); +sub waitForChild(\@); +sub cleanup(\@); + +my $debug = 0; + +chomp(my $clexe = `cygpath -u '$ENV{'VS80COMNTOOLS'}/../../VC/bin/cl.exe'`); + +if ($debug) { + print STDERR "Received " . @ARGV . " arguments:\n"; + foreach my $arg (@ARGV) { + print STDERR "$arg\n"; + } +} + +my $commandFile; +foreach my $arg (@ARGV) { + if ($arg =~ /^[\/-](E|EP|P)$/) { + print STDERR "The invoking process wants preprocessed source, so let's hand off this whole command to the real cl.exe\n" if $debug; + Exec("\"$clexe\" \"" . join('" "', @ARGV) . "\""); + } elsif ($arg =~ /^@(.*)$/) { + chomp($commandFile = `cygpath -u '$1'`); + } +} + +die "No command file specified!" unless $commandFile; +die "Couldn't find $commandFile!" unless -f $commandFile; + +my @sources; + +open(COMMAND, '<:raw:encoding(UTF16-LE):crlf:utf8', $commandFile) or die "Couldn't open $commandFile!"; + +# The first line of the command file contains all the options to cl.exe plus the first (possibly quoted) filename +my $firstLine = <COMMAND>; +$firstLine =~ s/\r?\n$//; + +# To find the start of the first filename, look for either the last space on the line. +# If the filename is quoted, the last character on the line will be a quote, so look for the quote before that. +my $firstFileIndex; +print STDERR "Last character of first line = '" . substr($firstLine, -1, 1) . "'\n" if $debug; +if (substr($firstLine, -1, 1) eq '"') { + print STDERR "First file is quoted\n" if $debug; + $firstFileIndex = rindex($firstLine, '"', length($firstLine) - 2); +} else { + print STDERR "First file is NOT quoted\n" if $debug; + $firstFileIndex = rindex($firstLine, ' ') + 1; +} + +my $options = substr($firstLine, 0, $firstFileIndex) . join(' ', @ARGV[1 .. $#ARGV]); +my $possibleFirstFile = substr($firstLine, $firstFileIndex); +if ($possibleFirstFile =~ /\.(cpp|c)/) { + push(@sources, $possibleFirstFile); +} else { + $options .= " $possibleFirstFile"; +} + +print STDERR "######## Found options $options ##########\n" if $debug; +print STDERR "####### Found first source file $sources[0] ########\n" if @sources && $debug; + +# The rest of the lines of the command file just contain source files, one per line +while (my $source = <COMMAND>) { + chomp($source); + $source =~ s/^\s+//; + $source =~ s/\s+$//; + push(@sources, $source) if length($source); +} +close(COMMAND); + +my $numSources = @sources; +exit unless $numSources > 0; + +my $numJobs; +if ($options =~ s/-j\s*([0-9]+)//) { + $numJobs = $1; +} else { + chomp($numJobs = `num-cpus`); +} + +print STDERR "\n\n####### RUNNING AT MOST $numJobs PARALLEL INSTANCES OF cl.exe ###########\n\n";# if $debug; + +# Magic determination of job size +# The hope is that by splitting the source files up into 2*$numJobs pieces, we +# won't suffer too much if one job finishes much more quickly than another. +# However, we don't want to split it up too much due to cl.exe overhead, so set +# the minimum job size to 5. +my $jobSize = POSIX::ceil($numSources / (2 * $numJobs)); +$jobSize = $jobSize < 5 ? 5 : $jobSize; + +print STDERR "######## jobSize = $jobSize ##########\n" if $debug; + +# Sort the source files randomly so that we don't end up with big clumps of large files (aka SVG) +sub fisher_yates_shuffle(\@) +{ + my ($array) = @_; + for (my $i = @{$array}; --$i; ) { + my $j = int(rand($i+1)); + next if $i == $j; + @{$array}[$i,$j] = @{$array}[$j,$i]; + } +} + +fisher_yates_shuffle(@sources); # permutes @array in place + +my @children; +my @tmpFiles; +my $status = 0; +while (@sources) { + while (@sources && @children < $numJobs) { + my $pid; + my $tmpFile; + my $job = makeJob(@sources, $jobSize); + ($pid, $tmpFile) = forkAndCompileFiles(@{$job}, $options); + + print STDERR "####### Spawned child with PID $pid and tmpFile $tmpFile ##########\n" if $debug; + push(@children, $pid); + push(@tmpFiles, $tmpFile); + } + + $status |= waitForChild(@children); +} + +while (@children) { + $status |= waitForChild(@children); +} +cleanup(@tmpFiles); + +exit WEXITSTATUS($status); + + +sub makeJob(\@$) +{ + my ($files, $jobSize) = @_; + + my @job; + if (@{$files} > ($jobSize * 1.5)) { + @job = splice(@{$files}, -$jobSize); + } else { + # Compile all the remaining files in this job to avoid having a small job later + @job = splice(@{$files}); + } + + return \@job; +} + +sub forkAndCompileFiles(\@$) +{ + print STDERR "######## forkAndCompileFiles()\n" if $debug; + my ($files, $options) = @_; + + if ($debug) { + foreach my $file (@{$files}) { + print STDERR "######## $file\n"; + } + } + + my (undef, $tmpFile) = File::Temp::tempfile('clcommandXXXXX', DIR => File::Spec->tmpdir, OPEN => 0); + + my $pid = fork(); + die "Fork failed" unless defined($pid); + + unless ($pid) { + # Child process + open(TMP, '>:raw:encoding(UTF16-LE):crlf:utf8', $tmpFile) or die "Couldn't open $tmpFile"; + print TMP "$options\n"; + foreach my $file (@{$files}) { + print TMP "$file\n"; + } + close(TMP); + + chomp(my $winTmpFile = `cygpath -m $tmpFile`); + Exec "\"$clexe\" \@\"$winTmpFile\""; + } else { + return ($pid, $tmpFile); + } +} + +sub Exec($) +{ + my ($command) = @_; + + print STDERR "Exec($command)\n" if $debug; + + exec($command); +} + +sub waitForChild(\@) +{ + my ($children) = @_; + + return unless @{$children}; + + my $deceased = wait(); + my $status = $?; + print STDERR "######## Child with PID $deceased finished ###########\n" if $debug; + for (my $i = 0; $i < @{$children}; $i++) { + if ($children->[$i] == $deceased) { + splice(@{$children}, $i, 1); + last; + } + } + + return $status; +} + +sub cleanup(\@) +{ + my ($tmpFiles) = @_; + + foreach my $file (@{$tmpFiles}) { + unlink $file; + } +} diff --git a/WebKitTools/Scripts/parse-malloc-history b/WebKitTools/Scripts/parse-malloc-history new file mode 100755 index 0000000..76ca74b --- /dev/null +++ b/WebKitTools/Scripts/parse-malloc-history @@ -0,0 +1,154 @@ +#!/usr/bin/perl + +# Copyright (C) 2007 Apple Inc. 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. + +# Parses the callstacks in a file with malloc_history formatted content, sorting +# based on total number of bytes allocated, and filtering based on command-line +# parameters. + +use Getopt::Long; +use File::Basename; + +use strict; +use warnings; + +sub commify($); + +sub main() +{ + my $usage = + "Usage: " . basename($0) . " [options] malloc_history.txt\n" . + " --grep-regexp Include only call stacks that match this regular expression.\n" . + " --byte-minimum Include only call stacks with allocation sizes >= this value.\n" . + " --merge-regexp Merge all call stacks that match this regular expression.\n" . + " --merge-depth Merge all call stacks that match at this stack depth and above.\n"; + + my $grepRegexp = ""; + my $byteMinimum = ""; + my @mergeRegexps = (); + my $mergeDepth = ""; + my $getOptionsResult = GetOptions( + "grep-regexp:s" => \$grepRegexp, + "byte-minimum:i" => \$byteMinimum, + "merge-regexp:s" => \@mergeRegexps, + "merge-depth:i" => \$mergeDepth + ); + my $fileName = $ARGV[0]; + die $usage if (!$getOptionsResult || !$fileName); + + open FILE, "<$fileName" or die "bad file: $fileName"; + my @file = <FILE>; + close FILE; + + my %callstacks = (); + my $byteCountTotal = 0; + + for (my $i = 0; $i < @file; $i++) { + my $line = $file[$i]; + my ($callCount, $byteCount); + + next if $line =~ /^\-/; + + # First try malloc_history format + # 6 calls for 664 bytes thread_ffffffff |0x0 | start + ($callCount, $byteCount) = ($line =~ /(\d+) calls for (\d+) bytes/); + + # Then try leaks format + # Leak: 0x0ac3ca40 size=48 + # 0x00020001 0x00000001 0x00000000 0x00000000 ................ + # Call stack: [thread ffffffff]: | 0x0 | start + if (!$callCount || !$byteCount) { + $callCount = 1; + ($byteCount) = ($line =~ /Leak: [x[:xdigit:]]* size=(\d+)/); + + if ($byteCount) { + while (!($line =~ "Call stack: ")) { + $i++; + $line = $file[$i]; + } + } + } + + # Then give up + next if (!$callCount || !$byteCount); + + $byteCountTotal += $byteCount; + + next if ($grepRegexp && !($line =~ $grepRegexp)); + + my $callstackBegin = 0; + if ($mergeDepth) { + # count stack frames backwards from end of callstack + $callstackBegin = length($line); + for (my $pipeCount = 0; $pipeCount < $mergeDepth; $pipeCount++) { + my $rindexResult = rindex($line, "|", $callstackBegin - 1); + last if $rindexResult == -1; + $callstackBegin = $rindexResult; + } + } else { + # start at beginning of callstack + $callstackBegin = index($line, "|"); + } + + my $callstack = substr($line, $callstackBegin + 2); # + 2 skips "| " + for my $regexp (@mergeRegexps) { + if ($callstack =~ $regexp) { + $callstack = $regexp . "\n"; + last; + } + } + + if (!$callstacks{$callstack}) { + $callstacks{$callstack} = {"callCount" => 0, "byteCount" => 0}; + } + + $callstacks{$callstack}{"callCount"} += $callCount; + $callstacks{$callstack}{"byteCount"} += $byteCount; + } + + my $byteCountTotalReported = 0; + for my $callstack (sort { $callstacks{$b}{"byteCount"} <=> $callstacks{$a}{"byteCount"} } keys %callstacks) { + my $callCount = $callstacks{$callstack}{"callCount"}; + my $byteCount = $callstacks{$callstack}{"byteCount"}; + last if ($byteMinimum && $byteCount < $byteMinimum); + + $byteCountTotalReported += $byteCount; + print commify($callCount) . " calls for " . commify($byteCount) . " bytes: $callstack\n"; + } + + print "total: " . commify($byteCountTotalReported) . " bytes (" . commify($byteCountTotal - $byteCountTotalReported) . " bytes excluded).\n"; +} + +exit(main()); + +# Copied from perldoc -- please excuse the style +sub commify($) +{ + local $_ = shift; + 1 while s/^([-+]?\d+)(\d{3})/$1,$2/; + return $_; +} diff --git a/WebKitTools/Scripts/pdevenv b/WebKitTools/Scripts/pdevenv new file mode 100755 index 0000000..8072adf --- /dev/null +++ b/WebKitTools/Scripts/pdevenv @@ -0,0 +1,24 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; + +use File::Temp qw/tempfile/; +use FindBin; + +my ($fh, $path) = tempfile(UNLINK => 0, SUFFIX => '.cmd') or die; + +chomp(my $vcBin = `cygpath -w "$FindBin::Bin/../vcbin"`); + +print $fh "\@echo off\n\n"; +print $fh "call \"\%VS80COMNTOOLS\%\\vsvars32.bat\"\n\n"; +print $fh "set PATH=$vcBin;\%PATH\%\n\n"; +print $fh "devenv.com /useenv " . join(" ", @ARGV) . "\n"; + +close $fh; + +chmod 0755, $path; + +chomp($path = `cygpath -w -s '$path'`); + +exec("cmd /c \"call $path\""); diff --git a/WebKitTools/Scripts/prepare-ChangeLog b/WebKitTools/Scripts/prepare-ChangeLog new file mode 100755 index 0000000..913eea5 --- /dev/null +++ b/WebKitTools/Scripts/prepare-ChangeLog @@ -0,0 +1,1256 @@ +#!/usr/bin/perl -w +# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 2 -*- + +# +# Copyright (C) 2000, 2001 Eazel, Inc. +# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. +# +# prepare-ChangeLog is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# prepare-ChangeLog is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + + +# Perl script to create a ChangeLog entry with names of files +# and functions from a diff. +# +# Darin Adler <darin@bentspoon.com>, started 20 April 2000 +# Java support added by Maciej Stachowiak <mjs@eazel.com> +# Objective-C, C++ and Objective-C++ support added by Maciej Stachowiak <mjs@apple.com> +# Git support added by Adam Roben <aroben@apple.com> + + +# +# TODO: +# List functions that have been removed too. +# Decide what a good logical order is for the changed files +# other than a normal text "sort" (top level first?) +# (group directories?) (.h before .c?) +# Handle yacc source files too (other languages?). +# Help merge when there are ChangeLog conflicts or if there's +# already a partly written ChangeLog entry. +# Add command line option to put the ChangeLog into a separate +# file or just spew it out stdout. +# Add SVN version numbers for commit (can't do that until +# the changes are checked in, though). +# Work around diff stupidity where deleting a function that starts +# with a comment makes diff think that the following function +# has been changed (if the following function starts with a comment +# with the same first line, such as /**) +# Work around diff stupidity where deleting an entire function and +# the blank lines before it makes diff think you've changed the +# previous function. + +use strict; +use warnings; + +use File::Basename; +use File::Spec; +use FindBin; +use Getopt::Long; +use lib $FindBin::Bin; +use POSIX qw(strftime); +use VCSUtils; + +sub changeLogDate($); +sub firstDirectoryOrCwd(); +sub diffFromToString(); +sub diffCommand(@); +sub statusCommand(@); +sub createPatchCommand($); +sub diffHeaderFormat(); +sub findOriginalFileFromSvn($); +sub generateFileList(\@\@\%); +sub gitConfig($); +sub isModifiedStatus($); +sub isAddedStatus($); +sub isConflictStatus($); +sub statusDescription($$); +sub extractLineRange($); +sub canonicalizePath($); +sub testListForChangeLog(@); +sub get_function_line_ranges($$); +sub get_function_line_ranges_for_c($$); +sub get_function_line_ranges_for_java($$); +sub method_decl_to_selector($); +sub processPaths(\@); +sub reviewerAndDescriptionForGitCommit($); + +# Project time zone for Cupertino, CA, US +my $changeLogTimeZone = "PST8PDT"; + +my $gitCommit = 0; +my $gitReviewer = ""; +my $openChangeLogs = 0; +my $showHelp = 0; +my $spewDiff = $ENV{"PREPARE_CHANGELOG_DIFF"}; +my $updateChangeLogs = 1; +my $parseOptionsResult = + GetOptions("diff|d!" => \$spewDiff, + "git-commit:s" => \$gitCommit, + "git-reviewer:s" => \$gitReviewer, + "help|h!" => \$showHelp, + "open|o!" => \$openChangeLogs, + "update!" => \$updateChangeLogs); +if (!$parseOptionsResult || $showHelp) { + print STDERR basename($0) . " [-d|--diff] [-h|--help] [-o|--open] [--git-commit=<committish>] [--git-reviewer=<name>] [svndir1 [svndir2 ...]]\n"; + print STDERR " -d|--diff Spew diff to stdout when running\n"; + print STDERR " --git-commit Populate the ChangeLogs from the specified git commit\n"; + print STDERR " --git-reviewer When populating the ChangeLogs from a git commit claim that the spcified name reviewed the change.\n"; + print STDERR " This option is useful when the git commit lacks a Signed-Off-By: line\n"; + print STDERR " -h|--help Show this help message\n"; + print STDERR " -o|--open Open ChangeLogs in an editor when done\n"; + print STDERR " --[no-]update Update ChangeLogs from svn before adding entry (default: update)\n"; + exit 1; +} + +my %paths = processPaths(@ARGV); + +my $isGit = isGitDirectory(firstDirectoryOrCwd()); +my $isSVN = isSVNDirectory(firstDirectoryOrCwd()); + +$isSVN || $isGit || die "Couldn't determine your version control system."; + +# Find the list of modified files +my @changed_files; +my $changed_files_string; +my %changed_line_ranges; +my %function_lists; +my @conflict_files; + +my $SVN = "svn"; +my $GIT = "git"; + +my %supportedTestExtensions = map { $_ => 1 } qw(html shtml svg xml xhtml pl php); +my @addedRegressionTests = (); +my $didChangeRegressionTests = 0; + +generateFileList(@changed_files, @conflict_files, %function_lists); + +if (!@changed_files && !@conflict_files && !keys %function_lists) { + print STDERR " No changes found.\n"; + exit 1; +} + +if (@conflict_files) { + print STDERR " The following files have conflicts. Run prepare-ChangeLog again after fixing the conflicts:\n"; + print STDERR join("\n", @conflict_files), "\n"; + exit 1; +} + +if (@changed_files) { + $changed_files_string = "'" . join ("' '", @changed_files) . "'"; + + # For each file, build a list of modified lines. + # Use line numbers from the "after" side of each diff. + print STDERR " Reviewing diff to determine which lines changed.\n"; + my $file; + open DIFF, "-|", diffCommand(@changed_files) or die "The diff failed: $!.\n"; + while (<DIFF>) { + $file = makeFilePathRelative($1) if $_ =~ diffHeaderFormat(); + if (defined $file) { + my ($start, $end) = extractLineRange($_); + if ($start >= 0 && $end >= 0) { + push @{$changed_line_ranges{$file}}, [ $start, $end ]; + } elsif (/DO_NOT_COMMIT/) { + print STDERR "WARNING: file $file contains the string DO_NOT_COMMIT, line $.\n"; + } + } + } + close DIFF; +} + +# For each source file, convert line range to function list. +if (%changed_line_ranges) { + print STDERR " Extracting affected function names from source files.\n"; + foreach my $file (keys %changed_line_ranges) { + # Only look for function names in .c files. + next unless $file =~ /\.(c|cpp|m|mm|h|java)/; + + # Find all the functions in the file. + open SOURCE, $file or next; + my @function_ranges = get_function_line_ranges(\*SOURCE, $file); + close SOURCE; + + # Find all the modified functions. + my @functions; + my %saw_function; + my @change_ranges = (@{$changed_line_ranges{$file}}, []); + my @change_range = (0, 0); + FUNCTION: foreach my $function_range_ref (@function_ranges) { + my @function_range = @$function_range_ref; + + # Advance to successive change ranges. + for (;; @change_range = @{shift @change_ranges}) { + last FUNCTION unless @change_range; + + # If past this function, move on to the next one. + next FUNCTION if $change_range[0] > $function_range[1]; + + # If an overlap with this function range, record the function name. + if ($change_range[1] >= $function_range[0] + and $change_range[0] <= $function_range[1]) { + if (!$saw_function{$function_range[2]}) { + $saw_function{$function_range[2]} = 1; + push @functions, $function_range[2]; + } + next FUNCTION; + } + } + } + + # Format the list of functions now. + + if (@functions) { + $function_lists{$file} = "" if !defined $function_lists{$file}; + $function_lists{$file} .= "\n (" . join("):\n (", @functions) . "):"; + } + } +} + +# Get some parameters for the ChangeLog we are about to write. +my $date = changeLogDate($changeLogTimeZone); +my $name = $ENV{CHANGE_LOG_NAME} + || $ENV{REAL_NAME} + || gitConfig("user.name") + || (split /\s*,\s*/, (getpwuid $<)[6])[0] + || "set REAL_NAME environment variable"; +my $email_address = $ENV{CHANGE_LOG_EMAIL_ADDRESS} + || $ENV{EMAIL_ADDRESS} + || gitConfig("user.email") + || "set EMAIL_ADDRESS environment variable"; + +if ($gitCommit) { + $name = `$GIT log --max-count=1 --pretty=\"format:%an\" \"$gitCommit\"`; + $email_address = `$GIT log --max-count=1 --pretty=\"format:%ae\" \"$gitCommit\"`; +} + +# Remove trailing parenthesized notes from user name (bit of hack). +$name =~ s/\(.*?\)\s*$//g; + +# Find the change logs. +my %has_log; +my %files; +foreach my $file (sort keys %function_lists) { + my $prefix = $file; + my $has_log = 0; + while ($prefix) { + $prefix =~ s-/[^/]+/?$-/- or $prefix = ""; + $has_log = $has_log{$prefix}; + if (!defined $has_log) { + $has_log = -f "${prefix}ChangeLog"; + $has_log{$prefix} = $has_log; + } + last if $has_log; + } + if (!$has_log) { + print STDERR "No ChangeLog found for $file.\n"; + } else { + push @{$files{$prefix}}, $file; + } +} + +# Get the latest ChangeLog files from svn. +my @logs = (); +foreach my $prefix (sort keys %files) { + push @logs, File::Spec->catfile($prefix || ".", "ChangeLog"); +} + +if (@logs && $updateChangeLogs && $isSVN) { + print STDERR " Running 'svn update' to update ChangeLog files.\n"; + open ERRORS, "-|", $SVN, "update", @logs + or die "The svn update of ChangeLog files failed: $!.\n"; + my @conflictedChangeLogs; + while (my $line = <ERRORS>) { + print STDERR " ", $line; + push @conflictedChangeLogs, $1 if $line =~ m/^C\s+(.+)\s*$/; + } + close ERRORS; + + if (@conflictedChangeLogs) { + print STDERR " Attempting to merge conflicted ChangeLogs.\n"; + my $resolveChangeLogsPath = File::Spec->catfile(dirname($0), "resolve-ChangeLogs"); + open RESOLVE, "-|", $resolveChangeLogsPath, "--no-warnings", @conflictedChangeLogs + or die "Could not open resolve-ChangeLogs script: $!.\n"; + print STDERR " $_" while <RESOLVE>; + close RESOLVE; + } +} + +# Write out a new ChangeLog file. +foreach my $prefix (sort keys %files) { + my $changeLogPath = File::Spec->catfile($prefix || ".", "ChangeLog"); + print STDERR " Editing the ${changeLogPath} file.\n"; + open OLD_CHANGE_LOG, ${changeLogPath} or die "Could not open ${changeLogPath} file: $!.\n"; + # It's less efficient to read the whole thing into memory than it would be + # to read it while we prepend to it later, but I like doing this part first. + my @old_change_log = <OLD_CHANGE_LOG>; + close OLD_CHANGE_LOG; + open CHANGE_LOG, "> ${changeLogPath}" or die "Could not write ${changeLogPath}\n."; + print CHANGE_LOG "$date $name <$email_address>\n\n"; + + my ($reviewer, $description) = reviewerAndDescriptionForGitCommit($gitCommit) if $gitCommit; + $reviewer = "NOBODY (OO" . "PS!)" if !$reviewer; + + print CHANGE_LOG " Reviewed by $reviewer.\n\n"; + print CHANGE_LOG $description . "\n" if $description; + + if ($prefix =~ m/WebCore/ || `pwd` =~ m/WebCore/) { + if ($didChangeRegressionTests) { + print CHANGE_LOG testListForChangeLog(sort @addedRegressionTests); + } else { + print CHANGE_LOG " WARNING: NO TEST CASES ADDED OR CHANGED\n\n"; + } + } + + foreach my $file (sort @{$files{$prefix}}) { + my $file_stem = substr $file, length $prefix; + print CHANGE_LOG " * $file_stem:$function_lists{$file}\n"; + } + print CHANGE_LOG "\n", @old_change_log; + close CHANGE_LOG; +} + +# Write out another diff. +if ($spewDiff && @changed_files) { + print STDERR " Running diff to help you write the ChangeLog entries.\n"; + local $/ = undef; # local slurp mode + open DIFF, "-|", createPatchCommand($changed_files_string) or die "The diff failed: $!.\n"; + print <DIFF>; + close DIFF; +} + +# Open ChangeLogs. +if ($openChangeLogs && @logs) { + print STDERR " Opening the edited ChangeLog files.\n"; + my $editor = $ENV{"CHANGE_LOG_EDIT_APPLICATION"}; + if ($editor) { + system "open", "-a", $editor, @logs; + } else { + system "open", "-e", @logs; + } +} + +# Done. +exit; + +sub canonicalizePath($) +{ + my ($file) = @_; + + # Remove extra slashes and '.' directories in path + $file = File::Spec->canonpath($file); + + # Remove '..' directories in path + my @dirs = (); + foreach my $dir (File::Spec->splitdir($file)) { + if ($dir eq '..' && $#dirs >= 0 && $dirs[$#dirs] ne '..') { + pop(@dirs); + } else { + push(@dirs, $dir); + } + } + return ($#dirs >= 0) ? File::Spec->catdir(@dirs) : "."; +} + +sub changeLogDate($) +{ + my ($timeZone) = @_; + my $savedTimeZone = $ENV{'TZ'}; + # Set TZ temporarily so that localtime() is in that time zone + $ENV{'TZ'} = $timeZone; + my $date = strftime("%Y-%m-%d", localtime()); + if (defined $savedTimeZone) { + $ENV{'TZ'} = $savedTimeZone; + } else { + delete $ENV{'TZ'}; + } + return $date; +} + +sub get_function_line_ranges($$) +{ + my ($file_handle, $file_name) = @_; + + if ($file_name =~ /\.(c|cpp|m|mm|h)$/) { + return get_function_line_ranges_for_c ($file_handle, $file_name); + } elsif ($file_name =~ /\.java$/) { + return get_function_line_ranges_for_java ($file_handle, $file_name); + } + return (); +} + + +sub method_decl_to_selector($) +{ + (my $method_decl) = @_; + + $_ = $method_decl; + + if ((my $comment_stripped) = m-([^/]*)(//|/*).*-) { + $_ = $comment_stripped; + } + + s/,\s*...//; + + if (/:/) { + my @components = split /:/; + pop @components if (scalar @components > 1); + $_ = (join ':', map {s/.*[^[:word:]]//; scalar $_;} @components) . ':'; + } else { + s/\s*$//; + s/.*[^[:word:]]//; + } + + return $_; +} + + + +# Read a file and get all the line ranges of the things that look like C functions. +# A function name is the last word before an open parenthesis before the outer +# level open brace. A function starts at the first character after the last close +# brace or semicolon before the function name and ends at the close brace. +# Comment handling is simple-minded but will work for all but pathological cases. +# +# Result is a list of triples: [ start_line, end_line, function_name ]. + +sub get_function_line_ranges_for_c($$) +{ + my ($file_handle, $file_name) = @_; + + my @ranges; + + my $in_comment = 0; + my $in_macro = 0; + my $in_method_declaration = 0; + my $in_parentheses = 0; + my $in_braces = 0; + my $brace_start = 0; + my $brace_end = 0; + my $skip_til_brace_or_semicolon = 0; + + my $word = ""; + my $interface_name = ""; + + my $potential_method_char = ""; + my $potential_method_spec = ""; + + my $potential_start = 0; + my $potential_name = ""; + + my $start = 0; + my $name = ""; + + my $next_word_could_be_namespace = 0; + my $potential_namespace = ""; + my @namespaces; + + while (<$file_handle>) { + # Handle continued multi-line comment. + if ($in_comment) { + next unless s-.*\*/--; + $in_comment = 0; + } + + # Handle continued macro. + if ($in_macro) { + $in_macro = 0 unless /\\$/; + next; + } + + # Handle start of macro (or any preprocessor directive). + if (/^\s*\#/) { + $in_macro = 1 if /^([^\\]|\\.)*\\$/; + next; + } + + # Handle comments and quoted text. + while (m-(/\*|//|\'|\")-) { # \' and \" keep emacs perl mode happy + my $match = $1; + if ($match eq "/*") { + if (!s-/\*.*?\*/--) { + s-/\*.*--; + $in_comment = 1; + } + } elsif ($match eq "//") { + s-//.*--; + } else { # ' or " + if (!s-$match([^\\]|\\.)*?$match--) { + warn "mismatched quotes at line $. in $file_name\n"; + s-$match.*--; + } + } + } + + + # continued method declaration + if ($in_method_declaration) { + my $original = $_; + my $method_cont = $_; + + chomp $method_cont; + $method_cont =~ s/[;\{].*//; + $potential_method_spec = "${potential_method_spec} ${method_cont}"; + + $_ = $original; + if (/;/) { + $potential_start = 0; + $potential_method_spec = ""; + $potential_method_char = ""; + $in_method_declaration = 0; + s/^[^;\{]*//; + } elsif (/{/) { + my $selector = method_decl_to_selector ($potential_method_spec); + $potential_name = "${potential_method_char}\[${interface_name} ${selector}\]"; + + $potential_method_spec = ""; + $potential_method_char = ""; + $in_method_declaration = 0; + + $_ = $original; + s/^[^;{]*//; + } elsif (/\@end/) { + $in_method_declaration = 0; + $interface_name = ""; + $_ = $original; + } else { + next; + } + } + + + # start of method declaration + if ((my $method_char, my $method_spec) = m&^([-+])([^0-9;][^;]*);?$&) { + my $original = $_; + + if ($interface_name) { + chomp $method_spec; + $method_spec =~ s/\{.*//; + + $potential_method_char = $method_char; + $potential_method_spec = $method_spec; + $potential_start = $.; + $in_method_declaration = 1; + } else { + warn "declaring a method but don't have interface on line $. in $file_name\n"; + } + $_ = $original; + if (/\{/) { + my $selector = method_decl_to_selector ($potential_method_spec); + $potential_name = "${potential_method_char}\[${interface_name} ${selector}\]"; + + $potential_method_spec = ""; + $potential_method_char = ""; + $in_method_declaration = 0; + $_ = $original; + s/^[^{]*//; + } elsif (/\@end/) { + $in_method_declaration = 0; + $interface_name = ""; + $_ = $original; + } else { + next; + } + } + + + # Find function, interface and method names. + while (m&((?:[[:word:]]+::)*operator(?:[ \t]*\(\)|[^()]*)|[[:word:]:~]+|[(){}:;])|\@(?:implementation|interface|protocol)\s+(\w+)[^{]*&g) { + # interface name + if ($2) { + $interface_name = $2; + next; + } + + # Open parenthesis. + if ($1 eq "(") { + $potential_name = $word unless $in_parentheses || $skip_til_brace_or_semicolon; + $in_parentheses++; + next; + } + + # Close parenthesis. + if ($1 eq ")") { + $in_parentheses--; + next; + } + + # C++ constructor initializers + if ($1 eq ":") { + $skip_til_brace_or_semicolon = 1 unless ($in_parentheses || $in_braces); + } + + # Open brace. + if ($1 eq "{") { + $skip_til_brace_or_semicolon = 0; + + if ($potential_namespace) { + push @namespaces, $potential_namespace; + $potential_namespace = ""; + next; + } + + # Promote potential name to real function name at the + # start of the outer level set of braces (function body?). + if (!$in_braces and $potential_start) { + $start = $potential_start; + $name = $potential_name; + if (@namespaces && (length($name) < 2 || substr($name,1,1) ne "[")) { + $name = join ('::', @namespaces, $name); + } + } + + $in_method_declaration = 0; + + $brace_start = $. if (!$in_braces); + $in_braces++; + next; + } + + # Close brace. + if ($1 eq "}") { + if (!$in_braces && @namespaces) { + pop @namespaces; + next; + } + + $in_braces--; + $brace_end = $. if (!$in_braces); + + # End of an outer level set of braces. + # This could be a function body. + if (!$in_braces and $name) { + push @ranges, [ $start, $., $name ]; + $name = ""; + } + + $potential_start = 0; + $potential_name = ""; + next; + } + + # Semicolon. + if ($1 eq ";") { + $skip_til_brace_or_semicolon = 0; + $potential_start = 0; + $potential_name = ""; + $in_method_declaration = 0; + next; + } + + # Ignore "const" method qualifier. + if ($1 eq "const") { + next; + } + + if ($1 eq "namespace" || $1 eq "class" || $1 eq "struct") { + $next_word_could_be_namespace = 1; + next; + } + + # Word. + $word = $1; + if (!$skip_til_brace_or_semicolon) { + if ($next_word_could_be_namespace) { + $potential_namespace = $word; + $next_word_could_be_namespace = 0; + } elsif ($potential_namespace) { + $potential_namespace = ""; + } + + if (!$in_parentheses) { + $potential_start = 0; + $potential_name = ""; + } + if (!$potential_start) { + $potential_start = $.; + $potential_name = ""; + } + } + } + } + + warn "missing close braces in $file_name (probable start at $brace_start)\n" if ($in_braces > 0); + warn "too many close braces in $file_name (probable start at $brace_end)\n" if ($in_braces < 0); + + warn "mismatched parentheses in $file_name\n" if $in_parentheses; + + return @ranges; +} + + + +# Read a file and get all the line ranges of the things that look like Java +# classes, interfaces and methods. +# +# A class or interface name is the word that immediately follows +# `class' or `interface' when followed by an open curly brace and not +# a semicolon. It can appear at the top level, or inside another class +# or interface block, but not inside a function block +# +# A class or interface starts at the first character after the first close +# brace or after the function name and ends at the close brace. +# +# A function name is the last word before an open parenthesis before +# an open brace rather than a semicolon. It can appear at top level or +# inside a class or interface block, but not inside a function block. +# +# A function starts at the first character after the first close +# brace or after the function name and ends at the close brace. +# +# Comment handling is simple-minded but will work for all but pathological cases. +# +# Result is a list of triples: [ start_line, end_line, function_name ]. + +sub get_function_line_ranges_for_java($$) +{ + my ($file_handle, $file_name) = @_; + + my @current_scopes; + + my @ranges; + + my $in_comment = 0; + my $in_macro = 0; + my $in_parentheses = 0; + my $in_braces = 0; + my $in_non_block_braces = 0; + my $class_or_interface_just_seen = 0; + + my $word = ""; + + my $potential_start = 0; + my $potential_name = ""; + my $potential_name_is_class_or_interface = 0; + + my $start = 0; + my $name = ""; + my $current_name_is_class_or_interface = 0; + + while (<$file_handle>) { + # Handle continued multi-line comment. + if ($in_comment) { + next unless s-.*\*/--; + $in_comment = 0; + } + + # Handle continued macro. + if ($in_macro) { + $in_macro = 0 unless /\\$/; + next; + } + + # Handle start of macro (or any preprocessor directive). + if (/^\s*\#/) { + $in_macro = 1 if /^([^\\]|\\.)*\\$/; + next; + } + + # Handle comments and quoted text. + while (m-(/\*|//|\'|\")-) { # \' and \" keep emacs perl mode happy + my $match = $1; + if ($match eq "/*") { + if (!s-/\*.*?\*/--) { + s-/\*.*--; + $in_comment = 1; + } + } elsif ($match eq "//") { + s-//.*--; + } else { # ' or " + if (!s-$match([^\\]|\\.)*?$match--) { + warn "mismatched quotes at line $. in $file_name\n"; + s-$match.*--; + } + } + } + + # Find function names. + while (m-(\w+|[(){};])-g) { + # Open parenthesis. + if ($1 eq "(") { + if (!$in_parentheses) { + $potential_name = $word; + $potential_name_is_class_or_interface = 0; + } + $in_parentheses++; + next; + } + + # Close parenthesis. + if ($1 eq ")") { + $in_parentheses--; + next; + } + + # Open brace. + if ($1 eq "{") { + # Promote potential name to real function name at the + # start of the outer level set of braces (function/class/interface body?). + if (!$in_non_block_braces + and (!$in_braces or $current_name_is_class_or_interface) + and $potential_start) { + if ($name) { + push @ranges, [ $start, ($. - 1), + join ('.', @current_scopes) ]; + } + + + $current_name_is_class_or_interface = $potential_name_is_class_or_interface; + + $start = $potential_start; + $name = $potential_name; + + push (@current_scopes, $name); + } else { + $in_non_block_braces++; + } + + $potential_name = ""; + $potential_start = 0; + + $in_braces++; + next; + } + + # Close brace. + if ($1 eq "}") { + $in_braces--; + + # End of an outer level set of braces. + # This could be a function body. + if (!$in_non_block_braces) { + if ($name) { + push @ranges, [ $start, $., + join ('.', @current_scopes) ]; + + pop (@current_scopes); + + if (@current_scopes) { + $current_name_is_class_or_interface = 1; + + $start = $. + 1; + $name = $current_scopes[$#current_scopes-1]; + } else { + $current_name_is_class_or_interface = 0; + $start = 0; + $name = ""; + } + } + } else { + $in_non_block_braces-- if $in_non_block_braces; + } + + $potential_start = 0; + $potential_name = ""; + next; + } + + # Semicolon. + if ($1 eq ";") { + $potential_start = 0; + $potential_name = ""; + next; + } + + if ($1 eq "class" or $1 eq "interface") { + $class_or_interface_just_seen = 1; + next; + } + + # Word. + $word = $1; + if (!$in_parentheses) { + if ($class_or_interface_just_seen) { + $potential_name = $word; + $potential_start = $.; + $class_or_interface_just_seen = 0; + $potential_name_is_class_or_interface = 1; + next; + } + } + if (!$potential_start) { + $potential_start = $.; + $potential_name = ""; + } + $class_or_interface_just_seen = 0; + } + } + + warn "mismatched braces in $file_name\n" if $in_braces; + warn "mismatched parentheses in $file_name\n" if $in_parentheses; + + return @ranges; +} + +sub processPaths(\@) +{ + my ($paths) = @_; + return ("." => 1) if (!@{$paths}); + + my %result = (); + + for my $file (@{$paths}) { + die "can't handle absolute paths like \"$file\"\n" if File::Spec->file_name_is_absolute($file); + die "can't handle empty string path\n" if $file eq ""; + die "can't handle path with single quote in the name like \"$file\"\n" if $file =~ /'/; # ' (keep Xcode syntax highlighting happy) + + my $untouchedFile = $file; + + $file = canonicalizePath($file); + + die "can't handle paths with .. like \"$untouchedFile\"\n" if $file =~ m|/\.\./|; + + $result{$file} = 1; + } + + return ("." => 1) if ($result{"."}); + + # Remove any paths that also have a parent listed. + for my $path (keys %result) { + for (my $parent = dirname($path); $parent ne '.'; $parent = dirname($parent)) { + if ($result{$parent}) { + delete $result{$path}; + last; + } + } + } + + return %result; +} + +sub diffFromToString() +{ + return "" if $isSVN; + return $gitCommit if $gitCommit =~ m/.+\.\..+/; + return "\"$gitCommit^\" \"$gitCommit\"" if $gitCommit; + return "HEAD" if $isGit; +} + +sub diffCommand(@) +{ + my @paths = @_; + + my $pathsString = "'" . join("' '", @paths) . "'"; + + my $command; + if ($isSVN) { + $command = "$SVN diff --diff-cmd diff -x -N $pathsString"; + } elsif ($isGit) { + $command = "$GIT diff " . diffFromToString(); + $command .= " -- $pathsString" unless $gitCommit; + } + + return $command; +} + +sub statusCommand(@) +{ + my @files = @_; + + my $filesString = "'" . join ("' '", @files) . "'"; + my $command; + if ($isSVN) { + $command = "$SVN stat $filesString"; + } elsif ($isGit) { + $command = "$GIT diff -r --name-status -C -C -M " . diffFromToString(); + $command .= " -- $filesString" unless $gitCommit; + } + + return "$command 2>&1"; +} + +sub createPatchCommand($) +{ + my ($changedFilesString) = @_; + + my $command; + if ($isSVN) { + $command = "'$FindBin::Bin/svn-create-patch' $changedFilesString"; + } elsif ($isGit) { + $command = "$GIT diff -C -C -M " . diffFromToString(); + $command .= " -- $changedFilesString" unless $gitCommit; + } + + return $command; +} + +sub diffHeaderFormat() +{ + return qr/^Index: (\S+)$/ if $isSVN; + return qr/^diff --git a\/.+ b\/(.+)$/ if $isGit; +} + +sub findOriginalFileFromSvn($) +{ + my ($file) = @_; + my $baseUrl; + open INFO, "$SVN info . |" or die; + while (<INFO>) { + if (/^URL: (.+)/) { + $baseUrl = $1; + last; + } + } + close INFO; + my $sourceFile; + open INFO, "$SVN info '$file' |" or die; + while (<INFO>) { + if (/^Copied From URL: (.+)/) { + $sourceFile = File::Spec->abs2rel($1, $baseUrl); + last; + } + } + close INFO; + return $sourceFile; +} + +sub generateFileList(\@\@\%) +{ + my ($changedFiles, $conflictFiles, $functionLists) = @_; + print STDERR " Running status to find changed, added, or removed files.\n"; + open STAT, "-|", statusCommand(keys %paths) or die "The status failed: $!.\n"; + my $inGitCommitSection = 0; + while (<STAT>) { + my $status; + my $original; + my $file; + + if ($isSVN) { + if (/^([ACDMR]).{5} (.+)$/) { + $status = $1; + $file = $2; + $original = findOriginalFileFromSvn($file) if substr($_, 3, 1) eq "+"; + } else { + print; # error output from svn stat + } + } elsif ($isGit) { + if (/^([ADM])\t(.+)$/) { + $status = $1; + $file = $2; + } elsif (/^([CR])[0-9]{1,3}\t([^\t]+)\t([^\t\n]+)$/) { # for example: R90% newfile oldfile + $status = $1; + $original = $2; + $file = $3; + } else { + print; # error output from git diff + } + } + + next unless $status; + + $file = makeFilePathRelative($file); + + if (isModifiedStatus($status) || isAddedStatus($status)) { + my @components = File::Spec->splitdir($file); + if ($components[0] eq "LayoutTests") { + $didChangeRegressionTests = 1; + push @addedRegressionTests, $file + if isAddedStatus($status) + && $file =~ /\.([a-zA-Z]+)$/ + && $supportedTestExtensions{lc($1)} + && !scalar(grep(/^resources$/i, @components)); + } + push @{$changedFiles}, $file if $components[$#components] ne "ChangeLog"; + } elsif (isConflictStatus($status)) { + push @{$conflictFiles}, $file; + } + my $description = statusDescription($status, $original); + $functionLists->{$file} = $description if defined $description; + } + close STAT; +} + +sub gitConfig($) +{ + return unless $isGit; + + my ($config) = @_; + + my $result = `$GIT config $config`; + if (($? >> 8) != 0) { + $result = `$GIT repo-config $config`; + } + chomp $result; + return $result; +} + +sub isModifiedStatus($) +{ + my ($status) = @_; + + my %statusCodes = ( + "M" => 1, + ); + + return $statusCodes{$status}; +} + +sub isAddedStatus($) +{ + my ($status) = @_; + + my %statusCodes = ( + "A" => 1, + "C" => $isGit, + "R" => 1, + ); + + return $statusCodes{$status}; +} + +sub isConflictStatus($) +{ + my ($status) = @_; + + my %svn = ( + "C" => 1, + ); + + my %git = ( + "U" => 1, + ); + + return 0 if $gitCommit; # an existing commit cannot have conflicts + return $svn{$status} if $isSVN; + return $git{$status} if $isGit; +} + +sub statusDescription($$) +{ + my ($status, $original) = @_; + + my %svn = ( + "A" => defined $original ? " Copied from \%s." : " Added.", + "D" => " Removed.", + "M" => "", + "R" => defined $original ? " Replaced with \%s." : " Replaced.", + ); + + my %git = %svn; + $git{"A"} = " Added."; + $git{"C"} = " Copied from \%s."; + $git{"R"} = " Renamed from \%s."; + + return sprintf($svn{$status}, $original) if $isSVN && exists $svn{$status}; + return sprintf($git{$status}, $original) if $isGit && exists $git{$status}; + return undef; +} + +sub extractLineRange($) +{ + my ($string) = @_; + + my ($start, $end) = (-1, -1); + + if ($isSVN && $string =~ /^\d+(,\d+)?[acd](\d+)(,(\d+))?/) { + $start = $2; + $end = $4 || $2; + } elsif ($isGit && $string =~ /^@@ -\d+,\d+ \+(\d+),(\d+) @@/) { + $start = $1; + $end = $1 + $2 - 1; + + # git-diff shows 3 lines of context above and below the actual changes, + # so we need to subtract that context to find the actual changed range. + + # FIXME: This won't work if there's a change at the very beginning or + # very end of a file. + + $start += 3; + $end -= 6; + } + + return ($start, $end); +} + +sub firstDirectoryOrCwd() +{ + my $dir = "."; + my @dirs = keys(%paths); + + $dir = -d $dirs[0] ? $dirs[0] : dirname($dirs[0]) if @dirs; + + return $dir; +} + +sub testListForChangeLog(@) +{ + my (@tests) = @_; + + return "" unless @tests; + + my $leadString = " Test" . (@tests == 1 ? "" : "s") . ": "; + my $list = $leadString; + foreach my $i (0..$#tests) { + $list .= " " x length($leadString) if $i; + my $test = $tests[$i]; + $test =~ s/^LayoutTests\///; + $list .= "$test\n"; + } + $list .= "\n"; + + return $list; +} + +sub reviewerAndDescriptionForGitCommit($) +{ + my ($commit) = @_; + + my $description = ''; + my $reviewer; + + my @args = qw(rev-list --pretty); + push @args, '-1' if $commit !~ m/.+\.\..+/; + my $gitLog; + { + local $/ = undef; + open(GIT, "-|", $GIT, @args, $commit) || die; + $gitLog = <GIT>; + close(GIT); + } + + my @commitLogs = split(/^[Cc]ommit [a-f0-9]{40}/m, $gitLog); + shift @commitLogs; # Remove initial blank commit log + my $commitLogCount = 0; + foreach my $commitLog (@commitLogs) { + $description .= "\n" if $commitLogCount; + $commitLogCount++; + my $inHeader = 1; + my @lines = split(/\n/, $commitLog); + shift @lines; # Remove initial blank line + foreach my $line (@lines) { + if ($inHeader) { + if (!$line) { + $inHeader = 0; + } + next; + } elsif ($line =~ /[Ss]igned-[Oo]ff-[Bb]y: (.+)/) { + if (!$reviewer) { + $reviewer = $1; + } else { + $reviewer .= ", " . $1; + } + } elsif (length $line == 0) { + $description = $description . "\n"; + } else { + $line =~ s/^\s*//; + $description = $description . " " . $line . "\n"; + } + } + } + if (!$reviewer) { + $reviewer = $gitReviewer; + } + + return ($reviewer, $description); +} diff --git a/WebKitTools/Scripts/report-include-statistics b/WebKitTools/Scripts/report-include-statistics new file mode 100755 index 0000000..f81c3c3 --- /dev/null +++ b/WebKitTools/Scripts/report-include-statistics @@ -0,0 +1,114 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006 Apple Computer, Inc. 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. + +# "report-include-statistics" script for Web Kit Open Source Project + +use strict; +use File::Find; + +find(\&wanted, @ARGV ? @ARGV : "."); + +my %paths; +my %sources; +my %includes; + +sub wanted +{ + my $file = $_; + + if ($file eq "icu") { + $File::Find::prune = 1; + return; + } + + if ($file !~ /^\./ && $file =~ /\.(h|cpp|c|mm|m)$/) { + $paths{$file} = $File::Find::name; + $sources{$file} = $File::Find::name if $file !~ /\.h/; + open FILE, $file or die; + while (<FILE>) { + if (m-^\s*#\s*(include|import)\s+["<]((\S+/)*)(\S+)[">]-) { + my $include = ($2 eq "sys/" ? $2 : "") . $4; + $includes{$file}{$include}++; + } + } + close FILE; + } +} + +my %totalIncludes; + +sub fillOut +{ + my ($file) = @_; + + return if defined $totalIncludes{$file}; + + for my $include (keys %{ $includes{$file} }) { + $totalIncludes{$file}{$include} = 1; + fillOut($include); + for my $i (keys %{ $totalIncludes{$include} }) { + $totalIncludes{$file}{$i} = 1; + } + } +} + +my %inclusionCounts; +for my $file (keys %includes) { + $inclusionCounts{$file} = 0; + fillOut($file); +} + +for my $file (keys %sources) { + for my $include (keys %{ $totalIncludes{$file} }) { + $inclusionCounts{$include}++; + } +} + +for my $file (sort mostincludedcmp keys %includes) { + next if !$paths{$file}; + my $count = $inclusionCounts{$file}; + my $numIncludes = keys %{ $includes{$file} }; + my $numTotalIncludes = keys %{ $totalIncludes{$file} }; + print "$file is included $count times, includes $numIncludes files directly, $numTotalIncludes files total.\n" +} + +# Sort most-included files first. +sub mostincludedcmp($$) +{ + my ($filea, $fileb) = @_; + + my $counta = $inclusionCounts{$filea} || 0; + my $countb = $inclusionCounts{$fileb} || 0; + return $countb <=> $counta if $counta != $countb; + + my $ta = keys %{ $totalIncludes{$filea} }; + my $tb = keys %{ $totalIncludes{$fileb} }; + return $ta <=> $tb if $ta != $tb; + + return $filea cmp $fileb; +} diff --git a/WebKitTools/Scripts/resolve-ChangeLogs b/WebKitTools/Scripts/resolve-ChangeLogs new file mode 100755 index 0000000..fa01243 --- /dev/null +++ b/WebKitTools/Scripts/resolve-ChangeLogs @@ -0,0 +1,305 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Inc. 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. + +# Merge and resolve ChangeLog conflicts for svn and git repositories + +use strict; + +use FindBin; +use lib $FindBin::Bin; + +use File::Basename; +use File::Spec; +use Getopt::Long; +use VCSUtils; + +sub conflictFiles($); +sub fixChangeLogPatch($); +sub mergeChanges($$$); +sub resolveConflict($); +sub showStatus($;$); + +my $SVN = "svn"; +my $GIT = "git"; + +my $printWarnings = 1; +my $showHelp; + +my $getOptionsResult = GetOptions( + 'h|help' => \$showHelp, + 'w|warnings!' => \$printWarnings, +); + +sub findChangeLog { + return $_ if basename($_) eq "ChangeLog"; + + my $file = File::Spec->catfile($_, "ChangeLog"); + return $file if -d $_ and -e $file; + + return undef; +} + +my @changeLogFiles = grep { defined $_ } map { findChangeLog($_) } @ARGV; + +if (scalar(@changeLogFiles) != scalar(@ARGV)) { + print STDERR "ERROR: Files listed on command-line that are not ChangeLogs.\n"; + undef $getOptionsResult; +} elsif (scalar(@changeLogFiles) == 0) { + print STDERR "ERROR: No ChangeLog files listed on command-line.\n"; + undef $getOptionsResult; +} + +if (!$getOptionsResult || $showHelp) { + print STDERR <<__END__; +Usage: @{[ basename($0) ]} [options] path/to/ChangeLog [path/to/another/ChangeLog ...] + -h|--help show this help message + -w|--[no-]warnings show or suppress warnings (default: show warnings) +__END__ + exit 1; +} + +for my $file (@changeLogFiles) { + my ($fileMine, $fileOlder, $fileNewer) = conflictFiles($file); + if (!$fileMine || !$fileOlder || !$fileNewer) { + next; + } + if (mergeChanges($fileMine, $fileOlder, $fileNewer)) { + if ($file ne $fileNewer) { + unlink($file); + rename($fileNewer, $file) || die; + } + unlink($fileMine, $fileOlder); + resolveConflict($file); + showStatus($file, 1); + } else { + showStatus($file); + print STDERR "WARNING: ${file} could not be merged using fuzz level 3.\n" if $printWarnings; + unlink($fileMine, $fileOlder, $fileNewer) if isGit(); + } +} + +exit 0; + +sub conflictFiles($) +{ + my ($file) = @_; + my $fileMine; + my $fileOlder; + my $fileNewer; + + if (-e $file && -e "$file.orig" && -e "$file.rej") { + return ("$file.rej", "$file.orig", $file); + } + + if (isSVN()) { + open STAT, "-|", $SVN, "status", $file || die; + my $status = <STAT>; + close STAT; + if (!$status || $status !~ m/^C\s+/) { + print STDERR "WARNING: ${file} is not in a conflicted state.\n" if $printWarnings; + return (); + } + + $fileMine = "${file}.mine" if -e "${file}.mine"; + + my $currentRevision; + open INFO, "-|", $SVN, "info", $file || die; + while (my $line = <INFO>) { + $currentRevision = $1 if $line =~ m/^Revision: ([0-9]+)/; + } + close INFO; + $fileNewer = "${file}.r${currentRevision}" if -e "${file}.r${currentRevision}"; + + my @matchingFiles = grep { $_ ne $fileNewer } glob("${file}.r[0-9][0-9]*"); + if (scalar(@matchingFiles) > 1) { + print STDERR "WARNING: Too many conflict files exist for ${file}!\n" if $printWarnings; + } else { + $fileOlder = shift @matchingFiles; + } + } elsif (isGit()) { + my $gitPrefix = `$GIT rev-parse --show-prefix`; + chomp $gitPrefix; + open GIT, "-|", $GIT, "ls-files", "--unmerged", $file || die; + while (my $line = <GIT>) { + my ($mode, $hash, $stage, $fileName) = split(' ', $line); + my $outputFile; + if ($stage == 1) { + $fileOlder = "${file}.BASE.$$"; + $outputFile = $fileOlder; + } elsif ($stage == 2) { + $fileNewer = "${file}.LOCAL.$$"; + $outputFile = $fileNewer; + } elsif ($stage == 3) { + $fileMine = "${file}.REMOTE.$$"; + $outputFile = $fileMine; + } else { + die "Unknown file stage: $stage"; + } + system("$GIT cat-file blob :${stage}:${gitPrefix}${file} > $outputFile"); + } + close GIT; + } else { + die "Unknown version control system"; + } + + if (!$fileMine && !$fileOlder && !$fileNewer) { + print STDERR "WARNING: ${file} does not need merging.\n" if $printWarnings; + } elsif (!$fileMine || !$fileOlder || !$fileNewer) { + print STDERR "WARNING: ${file} is missing some conflict files.\n" if $printWarnings; + } + + return ($fileMine, $fileOlder, $fileNewer); +} + +sub fixChangeLogPatch($) +{ + my $patch = shift; + my $contextLineCount = 3; + + return $patch if $patch !~ /\n@@ -1,(\d+) \+1,(\d+) @@\n( .*\n)+(\+.*\n)+( .*\n){$contextLineCount}$/m; + my ($oldLineCount, $newLineCount) = ($1, $2); + return $patch if $oldLineCount <= $contextLineCount; + + # The diff(1) command is greedy when matching lines, so a new ChangeLog entry will + # have lines of context at the top of a patch when the existing entry has the same + # date and author as the new entry. This nifty loop alters a ChangeLog patch so + # that the added lines ("+") in the patch always start at the beginning of the + # patch and there are no initial lines of context. + my $newPatch; + my $lineCountInState = 0; + my $oldContentLineCountReduction = $oldLineCount - $contextLineCount; + my $newContentLineCountWithoutContext = $newLineCount - $oldLineCount - $oldContentLineCountReduction; + my ($stateHeader, $statePreContext, $stateNewChanges, $statePostContext) = (1..4); + my $state = $stateHeader; + foreach my $line (split(/\n/, $patch)) { + $lineCountInState++; + if ($state == $stateHeader && $line =~ /^@@ -1,$oldLineCount \+1,$newLineCount @\@$/) { + $line = "@@ -1,$contextLineCount +1," . ($newLineCount - $oldContentLineCountReduction) . " @@"; + $lineCountInState = 0; + $state = $statePreContext; + } elsif ($state == $statePreContext && substr($line, 0, 1) eq " ") { + $line = "+" . substr($line, 1); + if ($lineCountInState == $oldContentLineCountReduction) { + $lineCountInState = 0; + $state = $stateNewChanges; + } + } elsif ($state == $stateNewChanges && substr($line, 0, 1) eq "+") { + # No changes to these lines + if ($lineCountInState == $newContentLineCountWithoutContext) { + $lineCountInState = 0; + $state = $statePostContext; + } + } elsif ($state == $statePostContext) { + if (substr($line, 0, 1) eq "+" && $lineCountInState <= $oldContentLineCountReduction) { + $line = " " . substr($line, 1); + } elsif ($lineCountInState > $contextLineCount && substr($line, 0, 1) eq " ") { + next; # Discard + } + } + $newPatch .= $line . "\n"; + } + + return $newPatch; +} + +sub mergeChanges($$$) +{ + my ($fileMine, $fileOlder, $fileNewer) = @_; + + my $traditionalReject = $fileMine =~ /\.rej$/ ? 1 : 0; + + local $/ = undef; + + my $patch; + if ($traditionalReject) { + open(DIFF, "<", $fileMine); + $patch = <DIFF>; + close(DIFF); + rename($fileMine, "$fileMine.save"); + rename($fileOlder, "$fileOlder.save"); + } else { + open(DIFF, "-|", qw(diff -u), $fileOlder, $fileMine) || die; + $patch = <DIFF>; + close(DIFF); + } + + unlink("${fileNewer}.orig"); + unlink("${fileNewer}.rej"); + + open(PATCH, "| patch --fuzz=3 $fileNewer > /dev/null") || die; + print PATCH fixChangeLogPatch($patch); + close(PATCH); + + my $result; + + # Refuse to merge the patch if it did not apply cleanly + if (-e "${fileNewer}.rej") { + unlink("${fileNewer}.rej"); + unlink($fileNewer); + rename("${fileNewer}.orig", $fileNewer); + $result = 0; + } else { + unlink("${fileNewer}.orig"); + $result = 1; + } + + if ($traditionalReject) { + rename("$fileMine.save", $fileMine); + rename("$fileOlder.save", $fileOlder); + } + + return $result; +} + +sub resolveConflict($) +{ + my ($file) = @_; + + if (isSVN()) { + system($SVN, "resolved", $file); + } elsif (isGit()) { + system($GIT, "add", $file); + } else { + die "Unknown version control system"; + } +} + +sub showStatus($;$) +{ + my ($file, $isConflictResolved) = @_; + + if (isSVN()) { + system($SVN, "status", $file); + } elsif (isGit()) { + my @args = qw(--name-status); + unshift @args, qw(--cached) if $isConflictResolved; + system($GIT, "diff", @args, $file); + } else { + die "Unknown version control system"; + } +} diff --git a/WebKitTools/Scripts/run-drawtest b/WebKitTools/Scripts/run-drawtest new file mode 100755 index 0000000..2cd61de --- /dev/null +++ b/WebKitTools/Scripts/run-drawtest @@ -0,0 +1,47 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. 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. + +# Simplified "run" script for WebKit Open Source Project. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); +my $productDir = productDir(); + +# Check to see that all the frameworks are built (w/ SVG support). +checkFrameworks(); +checkWebCoreSVGSupport(1); + +# Set up DYLD_FRAMEWORK_PATH to point to the product directory. +print "Start DrawTest with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; +$ENV{DYLD_FRAMEWORK_PATH} = $productDir; +my $drawtestPath = "$productDir/DrawTest.app/Contents/MacOS/DrawTest"; +exec $drawtestPath or die; diff --git a/WebKitTools/Scripts/run-drosera b/WebKitTools/Scripts/run-drosera new file mode 100644 index 0000000..925293c --- /dev/null +++ b/WebKitTools/Scripts/run-drosera @@ -0,0 +1,41 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2007 Apple Inc. 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. + +# Simplified "run" script for Web Kit Open Source Project. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); + +# Check to see that all the frameworks are built. +checkFrameworks(); + +exit exitStatus(runDrosera()); diff --git a/WebKitTools/Scripts/run-drosera-nightly.cmd b/WebKitTools/Scripts/run-drosera-nightly.cmd new file mode 100644 index 0000000..4f547fb --- /dev/null +++ b/WebKitTools/Scripts/run-drosera-nightly.cmd @@ -0,0 +1,12 @@ +@echo off +set script="%TMP%\run-drosera-nightly2.cmd" +set vsvars="%VS80COMNTOOLS%\vsvars32.bat" +if exist %vsvars% ( + copy %vsvars% "%script%" +) else ( + del "%script%" +) + +FindSafari.exe %1 /printSafariEnvironment >> "%script%" +echo Drosera.exe >> "%script%" +call %script% diff --git a/WebKitTools/Scripts/run-drosera.cmd b/WebKitTools/Scripts/run-drosera.cmd new file mode 100755 index 0000000..3b6e1f0 --- /dev/null +++ b/WebKitTools/Scripts/run-drosera.cmd @@ -0,0 +1,5 @@ +@echo off +set script="%TMP%\run-drosera2.cmd" +FindSafari.exe %1 /printSafariEnvironment > "%script%" +call %script% +Drosera.exe diff --git a/WebKitTools/Scripts/run-iexploder-tests b/WebKitTools/Scripts/run-iexploder-tests new file mode 100755 index 0000000..6acff18 --- /dev/null +++ b/WebKitTools/Scripts/run-iexploder-tests @@ -0,0 +1,170 @@ +#!/usr/bin/perl + +# Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) +# +# 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. + +# A script to semi-automatically run iExploder tests. + +use strict; +use warnings; + +use Cwd; +use FindBin; +use Getopt::Long; +use IPC::Open2; + +use lib $FindBin::Bin; +use webkitdirs; + +sub openHTTPDIfNeeded(); +sub closeHTTPD(); +sub runSafari(); + +# Argument handling +my $guardMalloc = ''; +my $httpdPort = 8000; +my $downloadTest; + +GetOptions( + 'guard-malloc|g' => \$guardMalloc, + 'get=s' => \$downloadTest, + 'port=i' => \$httpdPort +); + + +setConfiguration(); +my $productDir = productDir(); + +chdirWebKit(); + +checkFrameworks(); + +my $httpdOpen = 0; +openHTTPDIfNeeded(); + +if ($downloadTest) { + system "/usr/bin/curl -o ~/Desktop/iexploder$downloadTest.html \"http://127.0.0.1:$httpdPort/iexploder.cgi?lookup=1&test=$downloadTest\""; + print "Saved the test as iexploder$downloadTest.html on the desktop\n"; +} else { + runSafari(); + print "Last generated tests:\n"; + system "grep 'iexploder.cgi' /tmp/WebKit/access_log.txt | tail -n -5 | awk -F'[ =&\\?]' '{if (\$8 == \"lookup\") print \$11; else print \$9}'"; +} + +closeHTTPD(); + + +sub runSafari() +{ + my $redirectTo; + if (@ARGV) { + $redirectTo = "http://127.0.0.1:$httpdPort/iexploder.cgi?lookup=1&test=$ARGV[0]"; + } else { + $redirectTo = "http://127.0.0.1:$httpdPort/index.html"; + } + + open REDIRECT_HTML, ">", "/tmp/WebKit/redirect.html" or die; + print REDIRECT_HTML "<html>\n"; + print REDIRECT_HTML " <head>\n"; + print REDIRECT_HTML " <meta http-equiv=\"refresh\" content=\"1;URL=$redirectTo\" />\n"; + print REDIRECT_HTML " <script type=\"text/javascript\">\n"; + print REDIRECT_HTML " document.location = \"$redirectTo\";\n"; + print REDIRECT_HTML " </script>\n"; + print REDIRECT_HTML " </head>\n"; + print REDIRECT_HTML " <body>\n"; + print REDIRECT_HTML " </body>\n"; + print REDIRECT_HTML "</html>\n"; + close REDIRECT_HTML; + + local %ENV; + $ENV{DYLD_INSERT_LIBRARIES} = "/usr/lib/libgmalloc.dylib" if $guardMalloc; + system "WebKitTools/Scripts/run-safari", "-NSOpen", "/tmp/WebKit/redirect.html"; +} + +sub openHTTPDIfNeeded() +{ + return if $httpdOpen; + + mkdir "/tmp/WebKit"; + + if (-f "/tmp/WebKit/httpd.pid") { + my $oldPid = `cat /tmp/WebKit/httpd.pid`; + chomp $oldPid; + if (0 != kill 0, $oldPid) { + print "\nhttpd is already running: pid $oldPid, killing...\n"; + kill 15, $oldPid; + + my $retryCount = 20; + while ((0 != kill 0, $oldPid) && $retryCount) { + sleep 1; + --$retryCount; + } + + die "Timed out waiting for httpd to quit" unless $retryCount; + } + } + + my $testDirectory = getcwd() . "/LayoutTests"; + my $iExploderDirectory = getcwd() . "/WebKitTools/iExploder"; + my $httpdPath = "/usr/sbin/httpd"; + my $httpdConfig = "$testDirectory/http/conf/httpd.conf"; + $httpdConfig = "$testDirectory/http/conf/apache2-httpd.conf" if `$httpdPath -v` =~ m|Apache/2|; + my $documentRoot = "$iExploderDirectory/htdocs"; + my $typesConfig = "$testDirectory/http/conf/mime.types"; + my $listen = "127.0.0.1:$httpdPort"; + + open2(\*HTTPDIN, \*HTTPDOUT, $httpdPath, + "-f", "$httpdConfig", + "-C", "DocumentRoot \"$documentRoot\"", + "-C", "Listen $listen", + "-c", "TypesConfig \"$typesConfig\"", + "-c", "CustomLog \"/tmp/WebKit/access_log.txt\" common", + "-c", "ErrorLog \"/tmp/WebKit/error_log.txt\"", + # Apache wouldn't run CGIs with permissions==700 otherwise + "-c", "User \"#$<\""); + + my $retryCount = 20; + while (system("/usr/bin/curl -q --silent --stderr - --output /dev/null $listen") && $retryCount) { + sleep 1; + --$retryCount; + } + + die "Timed out waiting for httpd to start" unless $retryCount; + + $httpdOpen = 1; +} + +sub closeHTTPD() +{ + return if !$httpdOpen; + + close HTTPDIN; + close HTTPDOUT; + + kill 15, `cat /tmp/WebKit/httpd.pid` if -f "/tmp/WebKit/httpd.pid"; + + $httpdOpen = 0; +} diff --git a/WebKitTools/Scripts/run-javascriptcore-tests b/WebKitTools/Scripts/run-javascriptcore-tests new file mode 100755 index 0000000..16522ca --- /dev/null +++ b/WebKitTools/Scripts/run-javascriptcore-tests @@ -0,0 +1,173 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2007 Eric Seidel <eric@webkit.org> +# +# 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 to run the Web Kit Open Source Project JavaScriptCore tests (adapted from Mozilla). + +use strict; +use FindBin; +use Getopt::Long qw(:config pass_through); +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +my $coverageSupport = 0; +GetOptions('coverage!' => \$coverageSupport); + +my @coverageSupportOption = (); +if ($coverageSupport) { + push @coverageSupportOption, "GCC_GENERATE_TEST_COVERAGE_FILES=YES"; + push @coverageSupportOption, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES"; + push @coverageSupportOption, "EXTRA_LINK= -ftest-coverage -fprofile-arcs"; + push @coverageSupportOption, "OTHER_CFLAGS= -MD"; + push @coverageSupportOption, "OTHER_LDFLAGS= -ftest-coverage -fprofile-arcs -framework AppKit"; +} + +# determine configuration +my $configuration; +setConfiguration(); +$configuration = configuration(); + +my @jsArgs; +my @xcodeArgs; +my $root; + +# pre-evaluate arguments. jsDriver args have - preceding, xcode args do not. +# special arguments +# --root=<path to webkit root> use pre-built root +# --gtk build gtk +foreach my $arg(@ARGV) { + print $arg."\n"; + if( $arg =~ /root=(.*)/ ){ + $root = $1; + } elsif( $arg =~ /^--gtk$/i || $arg =~ /^--qt$/i || $arg =~ /^--wx$/i ){ + } elsif( $arg =~ /^-/ or !($arg =~/=/)){ + push( @jsArgs, $arg ); + } else { + push( @xcodeArgs, $arg ); + } +} + +setConfigurationProductDir(Cwd::abs_path($root)) if (defined($root)); + +if(!defined($root)){ + chdirWebKit(); + push(@xcodeArgs, "--" . $configuration); + + # FIXME: These should be stored per-config and ignored here + push(@xcodeArgs, "--qt") if isQt(); + push(@xcodeArgs, "--gtk") if isGtk(); + push(@xcodeArgs, "--wx") if isWx(); + + my $buildResult = system "perl", "WebKitTools/Scripts/build-testkjs", @xcodeArgs; + if ($buildResult) { + print STDERR "Compiling testkjs failed!\n"; + exit exitStatus($buildResult); + } +} + +# Find JavaScriptCore directory +chdirWebKit(); +chdir("JavaScriptCore"); + +my $productDir = productDir(); +chdir "tests/mozilla" or die; + +$productDir .= "/JavaScriptCore" if (isQt() or isGtk()); +$ENV{DYLD_FRAMEWORK_PATH} = $productDir; +setPathForRunningWebKitApp(\%ENV) if isCygwin(); + +sub testKJSPath($) +{ + my ($productDir) = @_; + my $testkjsName = "testkjs"; + $testkjsName .= "_debug" if (isCygwin() && ($configuration eq "Debug")); + return "$productDir/$testkjsName"; +} + +my $result = system "perl", "jsDriver.pl", "-e", "kjs", "-s", testKJSPath($productDir), "-f", "actual.html", @jsArgs; +exit exitStatus($result) if $result; + +my %failures; + +open EXPECTED, "expected.html" or die; +while (<EXPECTED>) { + last if /failures reported\.$/; +} +while (<EXPECTED>) { + chomp; + $failures{$_} = 1; +} +close EXPECTED; + +my %newFailures; + +open ACTUAL, "actual.html" or die; +while (<ACTUAL>) { + last if /failures reported\.$/; +} +while (<ACTUAL>) { + chomp; + if ($failures{$_}) { + delete $failures{$_}; + } else { + $newFailures{$_} = 1; + } +} +close ACTUAL; + +my $numNewFailures = keys %newFailures; +if ($numNewFailures) { + print "\n** Danger, Will Robinson! Danger! The following failures have been introduced:\n"; + foreach my $failure (sort keys %newFailures) { + print "\t$failure\n"; + } +} + +my $numOldFailures = keys %failures; +if ($numOldFailures) { + print "\nYou fixed the following test"; + print "s" if $numOldFailures != 1; + print ":\n"; + foreach my $failure (sort keys %failures) { + print "\t$failure\n"; + } +} + +print "\n"; + +print "$numNewFailures regression"; +print "s" if $numNewFailures != 1; +print " found.\n"; + +print "$numOldFailures test"; +print "s" if $numOldFailures != 1; +print " fixed.\n"; + +print "OK.\n" if $numNewFailures == 0; +exit(1) if $numNewFailures; diff --git a/WebKitTools/Scripts/run-launcher b/WebKitTools/Scripts/run-launcher new file mode 100755 index 0000000..60f3c86 --- /dev/null +++ b/WebKitTools/Scripts/run-launcher @@ -0,0 +1,75 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Computer, Inc. All rights reserved. +# Copyright (C) 2007 Staikos Computing Services, Inc. <info@staikos.net> +# +# 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. + +# Simplified "run" script for Web Kit Open Source Project. + +use strict; +use File::Spec::Functions qw/catdir/; +use File::Temp qw/tempfile/; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); +my $productDir = productDir(); +my $launcherPath = productDir(); +my @args = @ARGV; + +# Check to see that all the frameworks are built. +checkFrameworks(); + +# Set paths according to the build system used +if (!$ENV{WEBKITAUTOTOOLS}) { + my $libDir = catdir(productDir(), 'lib'); + + if (isGtk()) { + $launcherPath = catdir($launcherPath, "WebKitTools", "GtkLauncher", "GtkLauncher"); + # Strip --gtk from the arg-list, since otherwise GtkLauncher will try to + # interpret it as a URL. + @args = grep(!/^(--gtk)$/, @args); + } elsif (isQt()) { + $launcherPath = catdir($launcherPath, "bin", "QtLauncher"); + } + + # Set up LD_LIBRARY_PATH to point to the product directory. + print "Starting webkit launcher with LD_LIBRARY_PATH set to point to built WebKit in $libDir.\n"; + + $ENV{LD_LIBRARY_PATH} = $ENV{LD_LIBRARY_PATH} ? "$libDir:$ENV{LD_LIBRARY_PATH}" : $libDir; +} else { + + if (isGtk()) { + $launcherPath = catdir($launcherPath, "Programs", "GtkLauncher"); + @args = grep(!/^(--gtk)$/, @args); + } + + print "Starting webkit launcher.\n"; +} + +exec $launcherPath, @args or die; + diff --git a/WebKitTools/Scripts/run-leaks b/WebKitTools/Scripts/run-leaks new file mode 100755 index 0000000..d8f89d3 --- /dev/null +++ b/WebKitTools/Scripts/run-leaks @@ -0,0 +1,212 @@ +#!/usr/bin/perl + +# Copyright (C) 2007 Apple Inc. 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 to run the Mac OS X leaks tool with more expressive '-exclude' lists. + +use strict; +use warnings; + +use File::Basename; +use Getopt::Long; + +sub runLeaks($); +sub parseLeaksOutput(\@); +sub removeMatchingRecords(\@$\@); +sub reportError($); + +sub main() +{ + # Read options. + my $usage = + "Usage: " . basename($0) . " [options] pid | executable name\n" . + " --exclude-callstack regexp Exclude leaks whose call stacks match the regular expression 'regexp'.\n" . + " --exclude-type regexp Exclude leaks whose data types match the regular expression 'regexp'.\n" . + " --help Show this help message.\n"; + + my @callStacksToExclude = (); + my @typesToExclude = (); + my $help = 0; + + my $getOptionsResult = GetOptions( + 'exclude-callstack:s' => \@callStacksToExclude, + 'exclude-type:s' => \@typesToExclude, + 'help' => \$help + ); + my $pidOrExecutableName = $ARGV[0]; + + if (!$getOptionsResult || $help) { + print STDERR $usage; + return 1; + } + + if (!$pidOrExecutableName) { + reportError("Missing argument: pid | executable."); + print STDERR $usage; + return 1; + } + + # Run leaks tool. + my $leaksOutput = runLeaks($pidOrExecutableName); + if (!$leaksOutput) { + return 1; + } + + my $leakList = parseLeaksOutput(@$leaksOutput); + if (!$leakList) { + return 1; + } + + # Filter output. + my $leakCount = @$leakList; + removeMatchingRecords(@$leakList, "callStack", @callStacksToExclude); + removeMatchingRecords(@$leakList, "type", @typesToExclude); + my $excludeCount = $leakCount - @$leakList; + + # Dump results. + print $leaksOutput->[0]; + print $leaksOutput->[1]; + foreach my $leak (@$leakList) { + print $leak->{"leaksOutput"}; + } + + if ($excludeCount) { + print "$excludeCount leaks excluded (not printed)\n"; + } + + return 0; +} + +exit(main()); + +# Returns the output of the leaks tool in list form. +sub runLeaks($) +{ + my ($pidOrExecutableName) = @_; + + my @leaksOutput = `leaks $pidOrExecutableName`; + if (!@leaksOutput) { + reportError("Error running leaks tool."); + return; + } + + return \@leaksOutput; +} + +# Returns a list of hash references with the keys { address, size, type, callStack, leaksOutput } +sub parseLeaksOutput(\@) +{ + my ($leaksOutput) = @_; + + # Format: + # Process 00000: 1234 nodes malloced for 1234 KB + # Process 00000: XX leaks for XXX total leaked bytes. + # Leak: 0x00000000 size=1234 [instance of 'blah'] + # 0x00000000 0x00000000 0x00000000 0x00000000 a..d.e.e + # ... + # Call stack: leak_caller() | leak() | malloc + # + # We treat every line except for Process 00000: and Leak: as optional + + my ($leakCount) = ($leaksOutput->[1] =~ /[[:blank:]]+([0-9]+)[[:blank:]]+leaks?/); + if (!defined($leakCount)) { + reportError("Could not parse leak count reported by leaks tool."); + return; + } + + my @leakList = (); + for my $line (@$leaksOutput) { + next if $line =~ /^Process/; + next if $line =~ /^node buffer added/; + + if ($line =~ /^Leak: /) { + my ($address) = ($line =~ /Leak: ([[:xdigit:]x]+)/); + if (!defined($address)) { + reportError("Could not parse Leak address."); + return; + } + + my ($size) = ($line =~ /size=([[:digit:]]+)/); + if (!defined($size)) { + reportError("Could not parse Leak size."); + return; + } + + my ($type) = ($line =~ /'([^']+)'/); #' + if (!defined($type)) { + $type = ""; # The leaks tool sometimes omits the type. + } + + my %leak = ( + "address" => $address, + "size" => $size, + "type" => $type, + "callStack" => "", # The leaks tool sometimes omits the call stack. + "leaksOutput" => $line + ); + push(@leakList, \%leak); + } else { + $leakList[$#leakList]->{"leaksOutput"} .= $line; + if ($line =~ /Call stack:/) { + $leakList[$#leakList]->{"callStack"} = $line; + } + } + } + + if (@leakList != $leakCount) { + my $parsedLeakCount = @leakList; + reportError("Parsed leak count($parsedLeakCount) does not match leak count reported by leaks tool($leakCount)."); + return; + } + + return \@leakList; +} + +sub removeMatchingRecords(\@$\@) +{ + my ($recordList, $key, $regexpList) = @_; + + RECORD: for (my $i = 0; $i < @$recordList;) { + my $record = $recordList->[$i]; + + foreach my $regexp (@$regexpList) { + if ($record->{$key} =~ $regexp) { + splice(@$recordList, $i, 1); + next RECORD; + } + } + + $i++; + } +} + +sub reportError($) +{ + my ($errorMessage) = @_; + + print STDERR basename($0) . ": $errorMessage\n"; +} diff --git a/WebKitTools/Scripts/run-mangleme-tests b/WebKitTools/Scripts/run-mangleme-tests new file mode 100755 index 0000000..78b5d14 --- /dev/null +++ b/WebKitTools/Scripts/run-mangleme-tests @@ -0,0 +1,173 @@ +#!/usr/bin/perl + +# Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) +# +# 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. + +# A script to semi-automatically run mangleme tests. + +use strict; +use warnings; + +use Cwd; +use FindBin; +use Getopt::Long; +use IPC::Open2; + +use lib $FindBin::Bin; +use webkitdirs; + +sub openHTTPDIfNeeded(); +sub closeHTTPD(); +sub runSafari(); + +# Argument handling +my $guardMalloc = ''; +my $httpdPort = 8000; +my $downloadTest; + +GetOptions( + 'guard-malloc|g' => \$guardMalloc, + 'get=s' => \$downloadTest, + 'port=i' => \$httpdPort +); + + +setConfiguration(); +my $productDir = productDir(); + +chdirWebKit(); + +checkFrameworks(); + +mkdir "WebKitBuild/mangleme"; +(system "/usr/bin/make", "-C", "WebKitTools/mangleme") == 0 or die; + +my $httpdOpen = 0; +openHTTPDIfNeeded(); + +if ($downloadTest) { + system "/usr/bin/curl -o ~/Desktop/mangleme$downloadTest.html http://127.0.0.1:$httpdPort/remangle.cgi?$downloadTest"; + print "Saved the test as mangleme$downloadTest.html on the desktop\n"; +} else { + runSafari(); + print "Last generated tests:\n"; + system "grep 'Mangle attempt' /tmp/WebKit/error_log.txt | tail -n -5 | awk ' {print \$4}'"; +} + +closeHTTPD(); + + +sub runSafari() +{ + my $redirectTo; + if (@ARGV) { + $redirectTo = "http://127.0.0.1:$httpdPort/remangle.cgi?$ARGV[0]"; + } else { + $redirectTo = "http://127.0.0.1:$httpdPort/mangle.cgi"; + } + + open REDIRECT_HTML, ">", "/tmp/WebKit/redirect.html" or die; + print REDIRECT_HTML "<html>\n"; + print REDIRECT_HTML " <head>\n"; + print REDIRECT_HTML " <meta http-equiv=\"refresh\" content=\"1;URL=$redirectTo\" />\n"; + print REDIRECT_HTML " <script type=\"text/javascript\">\n"; + print REDIRECT_HTML " document.location = \"$redirectTo\";\n"; + print REDIRECT_HTML " </script>\n"; + print REDIRECT_HTML " </head>\n"; + print REDIRECT_HTML " <body>\n"; + print REDIRECT_HTML " </body>\n"; + print REDIRECT_HTML "</html>\n"; + close REDIRECT_HTML; + + local %ENV; + $ENV{DYLD_INSERT_LIBRARIES} = "/usr/lib/libgmalloc.dylib" if $guardMalloc; + system "WebKitTools/Scripts/run-safari", "-NSOpen", "/tmp/WebKit/redirect.html"; +} + +sub openHTTPDIfNeeded() +{ + return if $httpdOpen; + + mkdir "/tmp/WebKit"; + + if (-f "/tmp/WebKit/httpd.pid") { + my $oldPid = `cat /tmp/WebKit/httpd.pid`; + chomp $oldPid; + if (0 != kill 0, $oldPid) { + print "\nhttpd is already running: pid $oldPid, killing...\n"; + kill 15, $oldPid; + + my $retryCount = 20; + while ((0 != kill 0, $oldPid) && $retryCount) { + sleep 1; + --$retryCount; + } + + die "Timed out waiting for httpd to quit" unless $retryCount; + } + } + + my $testDirectory = getcwd() . "/LayoutTests"; + my $manglemeDirectory = getcwd() . "/WebKitBuild/mangleme"; + my $httpdPath = "/usr/sbin/httpd"; + my $httpdConfig = "$testDirectory/http/conf/httpd.conf"; + $httpdConfig = "$testDirectory/http/conf/apache2-httpd.conf" if `$httpdPath -v` =~ m|Apache/2|; + my $documentRoot = "$manglemeDirectory"; + my $typesConfig = "$testDirectory/http/conf/mime.types"; + my $listen = "127.0.0.1:$httpdPort"; + + open2(\*HTTPDIN, \*HTTPDOUT, $httpdPath, + "-f", "$httpdConfig", + "-C", "DocumentRoot \"$documentRoot\"", + "-C", "Listen $listen", + "-c", "TypesConfig \"$typesConfig\"", + "-c", "CustomLog \"/tmp/WebKit/access_log.txt\" common", + "-c", "ErrorLog \"/tmp/WebKit/error_log.txt\"", + # Apache wouldn't run CGIs with permissions==700 otherwise + "-c", "User \"#$<\""); + + my $retryCount = 20; + while (system("/usr/bin/curl -q --silent --stderr - --output /dev/null $listen") && $retryCount) { + sleep 1; + --$retryCount; + } + + die "Timed out waiting for httpd to start" unless $retryCount; + + $httpdOpen = 1; +} + +sub closeHTTPD() +{ + return if !$httpdOpen; + + close HTTPDIN; + close HTTPDOUT; + + kill 15, `cat /tmp/WebKit/httpd.pid` if -f "/tmp/WebKit/httpd.pid"; + + $httpdOpen = 0; +} diff --git a/WebKitTools/Scripts/run-pageloadtest b/WebKitTools/Scripts/run-pageloadtest new file mode 100755 index 0000000..ad6daa1 --- /dev/null +++ b/WebKitTools/Scripts/run-pageloadtest @@ -0,0 +1,92 @@ +#!/usr/bin/perl + +# Copyright (C) 2006 Eric Seidel (eric@webkit.org) +# +# 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 to run the WebKit Open Source Project page load tests (PLTs). + +# Run all the tests passed in on the command line. + +use strict; +use warnings; + +use File::Basename; +use File::Spec; +use FindBin; +use Getopt::Long; + +use lib $FindBin::Bin; +use webkitdirs; + +# Argument handling +my $testName = 'svg'; +my $showHelp = 0; + +my $usage = + "Usage: " . basename($0) . "[options] testName\n" . + " --help Show this help message\n"; + +my $getOptionsResult = GetOptions('help' => \$showHelp); + +if (!$getOptionsResult || $showHelp) { + print STDERR $usage; + exit 1; +} + +$testName = shift @ARGV if (@ARGV); + +my $safariExecutablePath = safariPath(); +my $safariResourcePath = File::Spec->catdir(dirname(dirname($safariExecutablePath)), "Resources"); + +# Check to see that all the frameworks are built. +checkFrameworks(); + +chdirWebKit(); + +if ($testName eq 'svg') { + my $suiteFile = "PageLoadTests/$testName/$testName.pltsuite"; + my $webkitPath = sourceDir(); + `cat "$suiteFile" | perl -pe 's|WEBKIT_PATH|$webkitPath|' > $safariResourcePath/$testName.pltsuite` +} + +die "Please copy ${testName}.pltsuite to ${safariResourcePath}/${testName}.pltsuite" + if (! -f "${safariResourcePath}/${testName}.pltsuite"); + +setConfiguration(); + +my $productDir = productDir(); + +# Set up DYLD_FRAMEWORK_PATH to point to the product directory. +print "Starting Safari with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; +$ENV{DYLD_FRAMEWORK_PATH} = $productDir; +$ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; + +my @testCommands = ('activate'); +# Autovicki would clear history, we skip that here as this is likely an active user account +@testCommands = (@testCommands, ("run $testName", 'emptyCache', 'wait 30')); +@testCommands = (@testCommands, (("run $testName", 'wait 10') x 3)); +my $testCommandsString = join('; ', @testCommands); +exec $safariExecutablePath, '--test-commands', $testCommandsString or die; diff --git a/WebKitTools/Scripts/run-safari b/WebKitTools/Scripts/run-safari new file mode 100755 index 0000000..4474b69 --- /dev/null +++ b/WebKitTools/Scripts/run-safari @@ -0,0 +1,41 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2007 Apple Inc. 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. + +# Simplified "run" script for Web Kit Open Source Project. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); + +# Check to see that all the frameworks are built. +checkFrameworks(); + +exit exitStatus(runSafari()); diff --git a/WebKitTools/Scripts/run-sunspider b/WebKitTools/Scripts/run-sunspider new file mode 100755 index 0000000..8dfeabb --- /dev/null +++ b/WebKitTools/Scripts/run-sunspider @@ -0,0 +1,123 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Inc. All rights reserved. +# Copyright (C) 2007 Eric Seidel <eric@webkit.org> +# +# 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. +# +# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR +# 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. + +use strict; +use FindBin; +use Getopt::Long qw(:config pass_through); +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +# determine configuration, but default to "Release" instead of last-used configuration +setConfiguration("Release"); +setConfiguration(); +my $configuration = configuration(); + +my $root; +my $testRuns = 10; # This number may be different from what sunspider defaults to (that's OK) +my $runShark = 0; +my $runShark20 = 0; +my $runSharkCache = 0; +my $setBaseline = 0; +my $showHelp = 0; +my $testsPattern; + +my $programName = basename($0); +my $usage = <<EOF; +Usage: $programName [options] [options to pass to build system] + --help Show this help message + --set-baseline Set baseline for future comparisons + --root Path to root tools build + --runs Number of times to run tests (default: $testRuns) + --tests Only run tests matching provided pattern + --shark Sample with the Mac OS X "Shark" performance testing tool (implies --runs=1) + --shark20 Like --shark, but with a 20 microsecond sampling interval + --shark-cache Like --shark, but performs a L2 cache-miss sample instead of time sample +EOF + +GetOptions('root=s' => sub { my ($value) = @_; $root = $value; setConfigurationProductDir(Cwd::abs_path($root)); }, + 'runs=i' => \$testRuns, + 'set-baseline' => \$setBaseline, + 'shark' => \$runShark, + 'shark20' => \$runShark20, + 'shark-cache' => \$runSharkCache, + 'tests=s' => \$testsPattern, + 'help' => \$showHelp); + +if ($showHelp) { + print STDERR $usage; + exit 1; +} + +sub buildTestKJS +{ + if (!defined($root)){ + push(@ARGV, "--" . $configuration); + + chdirWebKit(); + my $buildResult = system "WebKitTools/Scripts/build-testkjs", @ARGV; + if ($buildResult) { + print STDERR "Compiling testkjs failed!\n"; + exit exitStatus($buildResult); + } + } +} + +sub setupEnvironmentForExecution($) +{ + my ($productDir) = @_; + print "Starting sunspider with DYLD_FRAMEWORK_PATH set to point to built JavaScriptCore in $productDir.\n"; + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + # FIXME: Other platforms may wish to augment this method to use LD_LIBRARY_PATH, etc. +} + +sub testKJSPath($) +{ + my ($productDir) = @_; + my $testkjsName = "testkjs"; + $testkjsName .= "_debug" if (isCygwin() && ($configuration eq "Debug")); + return "$productDir/$testkjsName"; +} + +buildTestKJS(); + +chdirWebKit(); +chdir("SunSpider"); + +my $productDir = productDir(); +# FIXME: This hack should be pushed down into productDir() +$productDir .= "/JavaScriptCore" if (isQt() or isGtk()); + +setupEnvironmentForExecution($productDir); +my @args = ("--shell", testKJSPath($productDir), "--runs", $testRuns); +# This code could be removed if we chose to pass extra args to sunspider instead of Xcode +push @args, "--set-baseline" if $setBaseline; +push @args, "--shark" if $runShark; +push @args, "--shark20" if $runShark20; +push @args, "--shark-cache" if $runSharkCache; +push @args, "--tests", $testsPattern if $testsPattern; + +exec "./sunspider", @args; diff --git a/WebKitTools/Scripts/run-testkjs b/WebKitTools/Scripts/run-testkjs new file mode 100755 index 0000000..5610bad --- /dev/null +++ b/WebKitTools/Scripts/run-testkjs @@ -0,0 +1,58 @@ +#!/usr/bin/perl + +# Copyright (C) 2006 Apple Computer, Inc. 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. + +# This script runs a list of scripts through testkjs a specified number of times. + +use strict; +use warnings; +use FindBin; +use lib $FindBin::Bin; +use Getopt::Long; +use webkitdirs; + +my $usage = "Usage: run-testkjs [--count run_count] [--verbose] shell_file [file2...]"; + +my $count = 1; +my $verbose = 0; +GetOptions("count|c=i" => \$count, + "verbose|v" => \$verbose); +die "$usage\n" if (@ARGV < 1); + +my $testkjs = productDir() . "/testkjs @ARGV"; +$testkjs .= " 2> /dev/null" unless $verbose; + +my $dyld = productDir(); + +$ENV{"DYLD_FRAMEWORK_PATH"} = $dyld; +print STDERR "Running $count time(s): DYLD_FRAMEWORK_PATH=$dyld $testkjs\n"; +while ($count--) { + if (system("$testkjs") != 0) { + last; + } +} + diff --git a/WebKitTools/Scripts/run-webkit-app b/WebKitTools/Scripts/run-webkit-app new file mode 100755 index 0000000..36b9a58 --- /dev/null +++ b/WebKitTools/Scripts/run-webkit-app @@ -0,0 +1,50 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. 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. + +# Simplified "run" script for Web Kit Open Source Project. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +setConfiguration(); +my $productDir = productDir(); + +die "Did not specify an application to open (e.g. run-webkit-app AppName).\n" unless length($ARGV[0]) > 0; + +# Check to see that all the frameworks are built. +checkFrameworks(); + +# Set up DYLD_FRAMEWORK_PATH to point to the product directory. +print "Start $ARGV[0] with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; +$ENV{DYLD_FRAMEWORK_PATH} = $productDir; +$ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; + +unshift(@ARGV, "-a"); +exec "open", @ARGV; diff --git a/WebKitTools/Scripts/run-webkit-httpd b/WebKitTools/Scripts/run-webkit-httpd new file mode 100755 index 0000000..a64eef6 --- /dev/null +++ b/WebKitTools/Scripts/run-webkit-httpd @@ -0,0 +1,127 @@ +#!/usr/bin/perl + +# Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. +# Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) +# +# 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 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 to run Apache with the same configuration as used in http layout tests. + +use strict; +use warnings; + +use Cwd; +use File::Basename; +use Getopt::Long; +use FindBin; + +use lib $FindBin::Bin; +use webkitdirs; + +# Argument handling +my $httpdPort = 8000; +my $allInterfaces = 0; +my $showHelp; + +my $result = GetOptions( + 'all-interfaces|a' => \$allInterfaces, + 'help|h' => \$showHelp, + 'port=i' => \$httpdPort, +); + +if (!$result || @ARGV || $showHelp) { + print "Usage: " . basename($0) . " [options]\n"; + print " -a|--all-interfaces Bind to all interfaces\n"; + print " -h|--help Show this help message\n"; + print " -p|--port NNNN Bind to port NNNN\n"; + exit 1; +} + +setConfiguration(); +my $productDir = productDir(); +chdirWebKit(); + +mkdir "/tmp/WebKit"; + +if (-f "/tmp/WebKit/httpd.pid") { + my $oldPid = `cat /tmp/WebKit/httpd.pid`; + chomp $oldPid; + if (0 != kill 0, $oldPid) { + print "\nhttpd is already running: pid $oldPid, killing...\n"; + kill 15, $oldPid; + + my $retryCount = 20; + while ((0 != kill 0, $oldPid) && $retryCount) { + sleep 1; + --$retryCount; + } + + die "Timed out waiting for httpd to quit" unless $retryCount; + } +} + +my $testDirectory = getcwd() . "/LayoutTests"; +my $httpdPath = "/usr/sbin/httpd"; +$httpdPath = "/usr/sbin/apache2" if isDebianBased(); +my $httpdConfig = "$testDirectory/http/conf/httpd.conf"; +$httpdConfig = "$testDirectory/http/conf/cygwin-httpd.conf" if isCygwin(); +$httpdConfig = "$testDirectory/http/conf/apache2-httpd.conf" if `$httpdPath -v` =~ m|Apache/2|; +$httpdConfig = "$testDirectory/http/conf/apache2-debian-httpd.conf" if isDebianBased(); +my $documentRoot = "$testDirectory/http/tests"; +my $typesConfig = "$testDirectory/http/conf/mime.types"; +my $sslCertificate = "$testDirectory/http/conf/webkit-httpd.pem"; + +my $listen = "127.0.0.1:$httpdPort"; +$listen = "$httpdPort" if ($allInterfaces); + +if ($allInterfaces) { + print "Starting httpd on port $httpdPort (all interfaces)...\n"; +} else { + print "Starting httpd on <http://$listen/>...\n"; +} +print "Press Ctrl+C to stop it.\n\n"; + +my @args = ( + "-f", "$httpdConfig", + "-C", "DocumentRoot \"$documentRoot\"", + "-C", "Listen $listen", + "-c", "TypesConfig \"$typesConfig\"", + "-c", "CustomLog |/usr/bin/tee common", + "-c", "ErrorLog |/usr/bin/tee", + # Apache wouldn't run CGIs with permissions==700 otherwise. + "-c", "User \"#$<\"", + # Run in single-process mode, do not detach from the controlling terminal. + "-X", + # Disable Keep-Alive support. Makes testing in multiple browsers easier (no need to wait + # for another browser's connection to expire). + "-c", "KeepAlive 0" +); + +# FIXME: Enable this on Windows once <rdar://problem/5345985> is fixed +push(@args, "-c", "SSLCertificateFile \"$sslCertificate\"") unless isCygwin(); + +system($httpdPath, @args); + +unlink "/tmp/WebKit/httpd.pid"; diff --git a/WebKitTools/Scripts/run-webkit-nightly.cmd b/WebKitTools/Scripts/run-webkit-nightly.cmd new file mode 100755 index 0000000..93037ab --- /dev/null +++ b/WebKitTools/Scripts/run-webkit-nightly.cmd @@ -0,0 +1,10 @@ +@echo off +set script="%TMP%\run-webkit-nightly2.cmd" +set vsvars="%VS80COMNTOOLS%\vsvars32.bat" +if exist %vsvars% ( + copy %vsvars% "%script%" +) else ( + del "%script%" +) +FindSafari.exe %1 /printSafariLauncher >> "%script%" +call %script% diff --git a/WebKitTools/Scripts/run-webkit-tests b/WebKitTools/Scripts/run-webkit-tests new file mode 100755 index 0000000..3b6bbb3 --- /dev/null +++ b/WebKitTools/Scripts/run-webkit-tests @@ -0,0 +1,1627 @@ +#!/usr/bin/perl + +# Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. +# Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) +# Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com) +# Copyright (C) 2007 Eric Seidel <eric@webkit.org> +# +# 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 to run the Web Kit Open Source Project layout tests. + +# Run all the tests passed in on the command line. +# If no tests are passed, find all the .html, .shtml, .xml, .xhtml, .pl, .php (and svg) files in the test directory. + +# Run each text. +# Compare against the existing file xxx-expected.txt. +# If there is a mismatch, generate xxx-actual.txt and xxx-diffs.txt. + +# At the end, report: +# the number of tests that got the expected results +# the number of tests that ran, but did not get the expected results +# the number of tests that failed to run +# the number of tests that were run but had no expected results to compare against + +use strict; +use warnings; + +use Cwd; +use File::Basename; +use File::Copy; +use File::Find; +use File::Path; +use File::Spec; +use File::Spec::Functions; +use FindBin; +use Getopt::Long; +use IPC::Open2; +use IPC::Open3; +use Time::HiRes qw(time); + +use List::Util 'shuffle'; + +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +sub openDumpTool(); +sub closeDumpTool(); +sub dumpToolDidCrash(); +sub closeHTTPD(); +sub countAndPrintLeaks($$$); +sub fileNameWithNumber($$); +sub numericcmp($$); +sub openHTTPDIfNeeded(); +sub pathcmp($$); +sub processIgnoreTests($); +sub slowestcmp($$); +sub splitpath($); +sub stripExtension($); +sub isTextOnlyTest($); +sub expectedDirectoryForTest($;$;$); +sub printFailureMessageForTest($$); +sub toURL($); +sub toWindowsPath($); +sub closeCygpaths(); +sub validateSkippedArg($$;$); +sub htmlForExpectedAndActualResults($); +sub deleteExpectedAndActualResults($); +sub recordActualResultsAndDiff($$); +sub buildPlatformHierarchy(); +sub epiloguesAndPrologues($$); +sub parseLeaksandPrintUniqueLeaks(); + +# Argument handling +my $addPlatformExceptions = 0; +my $configuration = configuration(); +my $guardMalloc = ''; +my $httpdPort = 8000; +my $httpdSSLPort = 8443; +my $ignoreTests = ''; +my $launchSafari = 1; +my $platform; +my $pixelTests = ''; +my $quiet = ''; +my $repaintSweepHorizontally = ''; +my $repaintTests = ''; +my $report10Slowest = 0; +my $resetResults = 0; +my $shouldCheckLeaks = 0; +my $showHelp = 0; +my $testsPerDumpTool = 1000; +my $testHTTP = 1; +my $testMedia = 1; +my $testResultsDirectory = "/tmp/layout-test-results"; +my $threaded = 0; +my $threshold = 0; +my $treatSkipped = "default"; +my $verbose = 0; +my $useValgrind = 0; +my $strictTesting = 0; +my $generateNewResults = 1; +my $stripEditingCallbacks = isCygwin(); +my $root; +my $reverseTests = 0; +my $randomizeTests = 0; +my $mergeDepth; +my @leaksFilenames; + +# Default to --no-http for Qt, Gtk and wx for now. +$testHTTP = 0 if (isQt() || isGtk() || isWx()); + +my $expectedTag = "expected"; +my $actualTag = "actual"; +my $diffsTag = "diffs"; +my $errorTag = "stderr"; + +if (isTiger()) { + $platform = "mac-tiger"; +} elsif (isLeopard()) { + $platform = "mac-leopard"; +} elsif (isOSX()) { + $platform = "mac"; +} elsif (isQt()) { + $platform = "qt"; +} elsif (isGtk()) { + $platform = "gtk"; +} elsif (isCygwin()) { + $platform = "win"; +} + +if (!defined($platform)) { + print "WARNING: Your platform is not recognized. Any platform-specific results will be generated in platform/undefined.\n"; + $platform = "undefined"; +} + +my $programName = basename($0); +my $launchSafariDefault = $launchSafari ? "launch" : "do not launch"; +my $httpDefault = $testHTTP ? "run" : "do not run"; + +# FIXME: "--strict" should be renamed to qt-mac-comparison, or something along those lines. +my $usage = <<EOF; +Usage: $programName [options] [testdir|testpath ...] + --add-platform-exceptions Put new results for non-platform-specific failing tests into the platform-specific results directory + -c|--configuration config Set DumpRenderTree build configuration + -g|--guard-malloc Enable malloc guard + --help Show this help message + -h|--horizontal-sweep Change repaint to sweep horizontally instead of vertically (implies --repaint-tests) + --[no-]http Run (or do not run) http tests (default: $httpDefault) + -i|--ignore-tests Comma-separated list of directories or tests to ignore + --[no-]launch-safari Launch (or do not launch) Safari to display test results (default: $launchSafariDefault) + -l|--leaks Enable leaks checking + --[no-]new-test-results Generate results for new tests + -p|--pixel-tests Enable pixel tests + --platform Override the detected platform to use for tests and results (default: $platform) + --port Web server port to use with http tests + -q|--quiet Less verbose output + -r|--repaint-tests Run repaint tests (implies --pixel-tests) + --reset-results Reset ALL results (including pixel tests if --pixel-tests is set) + -o|--results-directory Output results directory (default: $testResultsDirectory) + --random Run the tests in a random order + --reverse Run the tests in reverse alphabetical order + --root Path to root tools build + -1|--singly Isolate each test case run (implies --verbose) + --skipped=[default|ignore|only] Specifies how to treat the Skipped file + default: Tests/directories listed in the Skipped file are not tested + ignore: The Skipped file is ignored + only: Only those tests/directories listed in the Skipped file will be run + --slowest Report the 10 slowest tests + --strict Do a comparison with the output on Mac (Qt only) + --[no-]strip-editing-callbacks Remove editing callbacks from expected results + -t|--threaded Run a concurrent JavaScript thead with each test + --threshold t Ignore pixel value deviations less than or equal to t + --valgrind Run DumpRenderTree inside valgrind (Qt/Linux only) + -v|--verbose More verbose output (overrides --quiet) + -m|--merge-leak-depth arg Merges leak callStacks and prints the number of unique leaks beneath a callstack depth of arg. Defaults to 5. +EOF + +my $getOptionsResult = GetOptions( + 'c|configuration=s' => \$configuration, + 'debug|devel' => sub { $configuration = "Debug" }, + 'guard-malloc|g' => \$guardMalloc, + 'help' => \$showHelp, + 'horizontal-sweep|h' => \$repaintSweepHorizontally, + 'http!' => \$testHTTP, + 'ignore-tests|i=s' => \$ignoreTests, + 'launch-safari!' => \$launchSafari, + 'leaks|l' => \$shouldCheckLeaks, + 'pixel-tests|p' => \$pixelTests, + 'platform=s' => \$platform, + 'port=i' => \$httpdPort, + 'quiet|q' => \$quiet, + 'release|deploy' => sub { $configuration = "Release" }, + 'repaint-tests|r' => \$repaintTests, + 'reset-results' => \$resetResults, + 'new-test-results!' => \$generateNewResults, + 'results-directory|o=s' => \$testResultsDirectory, + 'singly|1' => sub { $testsPerDumpTool = 1; }, + 'nthly=i' => \$testsPerDumpTool, + 'skipped=s' => \&validateSkippedArg, + 'slowest' => \$report10Slowest, + 'threaded|t' => \$threaded, + 'threshold=i' => \$threshold, + 'verbose|v' => \$verbose, + 'valgrind' => \$useValgrind, + 'strict' => \$strictTesting, + 'strip-editing-callbacks!' => \$stripEditingCallbacks, + 'random' => \$randomizeTests, + 'reverse' => \$reverseTests, + 'root=s' => \$root, + 'add-platform-exceptions' => \$addPlatformExceptions, + 'merge-leak-depth|m:5' => \$mergeDepth, +); + +if (!$getOptionsResult || $showHelp) { + print STDERR $usage; + exit 1; +} + +my $ignoreSkipped = $treatSkipped eq "ignore"; +my $skippedOnly = $treatSkipped eq "only"; + +!$skippedOnly || @ARGV == 0 or die "--skipped=only cannot be used when tests are specified on the command line."; + +setConfiguration($configuration); + +my $configurationOption = "--" . lc($configuration); + +$repaintTests = 1 if $repaintSweepHorizontally; + +$pixelTests = 1 if $repaintTests; +$pixelTests = 1 if $threshold > 0; + +$verbose = 1 if $testsPerDumpTool == 1; + +if ($shouldCheckLeaks && $testsPerDumpTool > 1000) { + print STDERR "\nWARNING: Running more than 1000 tests at a time with MallocStackLogging enabled may cause a crash.\n\n"; +} + +# Stack logging does not play well with QuickTime on Tiger (rdar://problem/5537157) +$testMedia = 0 if $shouldCheckLeaks && isTiger(); + +setConfigurationProductDir(Cwd::abs_path($root)) if (defined($root)); +my $productDir = productDir(); +$productDir .= "/bin" if (isQt()); + +if (isGtk()) { + if ($ENV{WEBKITAUTOTOOLS}) { + $productDir .= "/Programs"; + } else { + $productDir .= "/WebKitTools/DumpRenderTree/gtk"; + } +} + +chdirWebKit(); + +if(!defined($root)){ + # Push the parameters to build-dumprendertree as an array + my @args; + push(@args, "--" . $configuration); + push(@args, "--qt") if isQt(); + push(@args, "--gtk") if isGtk(); + + my $buildResult = system "WebKitTools/Scripts/build-dumprendertree", @args; + if ($buildResult) { + print STDERR "Compiling DumpRenderTree failed!\n"; + exit exitStatus($buildResult); + } +} + +my $dumpToolName = "DumpRenderTree"; +$dumpToolName .= "_debug" if isCygwin() && $configuration ne "Release"; +my $dumpTool = "$productDir/$dumpToolName"; +die "can't find executable $dumpToolName (looked in $productDir)\n" unless -x $dumpTool; + +my $imageDiffTool = "$productDir/ImageDiff"; +die "can't find executable $imageDiffTool (looked in $productDir)\n" if $pixelTests && !-x $imageDiffTool; + +checkFrameworks() unless isCygwin(); + +my $layoutTestsName = "LayoutTests"; +my $testDirectory = File::Spec->rel2abs($layoutTestsName); +my $expectedDirectory = $testDirectory; +my $platformBaseDirectory = catdir($testDirectory, "platform"); +my $platformTestDirectory = catdir($platformBaseDirectory, $platform); +my @platformHierarchy = buildPlatformHierarchy(); + +$expectedDirectory = $ENV{"WebKitExpectedTestResultsDirectory"} if $ENV{"WebKitExpectedTestResultsDirectory"}; + +my $testResults = catfile($testResultsDirectory, "results.html"); + +print "Running tests from $testDirectory\n"; + +my @tests = (); +my %testType = (); + +system "ln", "-s", $testDirectory, "/tmp/LayoutTests" unless -x "/tmp/LayoutTests"; + +my %ignoredFiles = (); +my %ignoredDirectories = map { $_ => 1 } qw(platform); +my %ignoredLocalDirectories = map { $_ => 1 } qw(.svn _svn resources); +my %supportedFileExtensions = map { $_ => 1 } qw(html shtml xml xhtml pl php); +if (checkWebCoreSVGSupport(0)) { + $supportedFileExtensions{'svg'} = 1; +} elsif (isCygwin()) { + # FIXME: We should fix webkitdirs.pm:hasSVGSupport() to do the correct + # check for Windows instead of forcing this here. + $supportedFileExtensions{'svg'} = 1; +} else { + $ignoredLocalDirectories{'svg'} = 1; +} +if (!$testHTTP) { + $ignoredDirectories{'http'} = 1; +} + +if (!$testMedia) { + $ignoredDirectories{'media'} = 1; + $ignoredDirectories{'http/tests/media'} = 1; +} + +if ($ignoreTests) { + processIgnoreTests($ignoreTests); +} + +if (!$ignoreSkipped) { + foreach my $level (@platformHierarchy) { + if (open SKIPPED, "<", "$level/Skipped") { + if ($verbose && !$skippedOnly) { + my ($dir, $name) = splitpath($level); + print "Skipped tests in $name:\n"; + } + + while (<SKIPPED>) { + my $skipped = $_; + chomp $skipped; + $skipped =~ s/^[ \n\r]+//; + $skipped =~ s/[ \n\r]+$//; + if ($skipped && $skipped !~ /^#/) { + if ($skippedOnly) { + push(@ARGV, $skipped); + } else { + if ($verbose) { + print " $skipped\n"; + } + processIgnoreTests($skipped); + } + } + } + close SKIPPED; + } + } +} + + +my $directoryFilter = sub { + return () if exists $ignoredLocalDirectories{basename($File::Find::dir)}; + return () if exists $ignoredDirectories{File::Spec->abs2rel($File::Find::dir, $testDirectory)}; + return @_; +}; + +my $fileFilter = sub { + my $filename = $_; + if ($filename =~ /\.([^.]+)$/) { + if (exists $supportedFileExtensions{$1}) { + my $path = File::Spec->abs2rel(catfile($File::Find::dir, $filename), $testDirectory); + push @tests, $path if !exists $ignoredFiles{$path}; + } + } +}; + +for my $test (@ARGV) { + $test =~ s/^($layoutTestsName|$testDirectory)\///; + my $fullPath = catfile($testDirectory, $test); + if (file_name_is_absolute($test)) { + print "can't run test $test outside $testDirectory\n"; + } elsif (-f $fullPath) { + my ($filename, $pathname, $fileExtension) = fileparse($test, qr{\.[^.]+$}); + if (!exists $supportedFileExtensions{substr($fileExtension, 1)}) { + print "test $test does not have a supported extension\n"; + } elsif ($testHTTP || $pathname !~ /^http\//) { + push @tests, $test; + } + } elsif (-d $fullPath) { + find({ preprocess => $directoryFilter, wanted => $fileFilter }, $fullPath); + + for my $level (@platformHierarchy) { + my $platformPath = catfile($level, $test); + find({ preprocess => $directoryFilter, wanted => $fileFilter }, $platformPath) if (-d $platformPath); + } + } else { + print "test $test not found\n"; + } +} +if (!scalar @ARGV) { + find({ preprocess => $directoryFilter, wanted => $fileFilter }, $testDirectory); + + for my $level (@platformHierarchy) { + find({ preprocess => $directoryFilter, wanted => $fileFilter }, $level); + } +} + +die "no tests to run\n" if !@tests; + +@tests = sort pathcmp @tests; + +my %counts; +my %tests; +my %imagesPresent; +my %imageDifferences; +my %durations; +my $count = 0; +my $leaksOutputFileNumber = 1; +my $totalLeaks = 0; + +my @toolArgs = (); +push @toolArgs, "--dump-all-pixels" if $pixelTests && $resetResults; +push @toolArgs, "--pixel-tests" if $pixelTests; +push @toolArgs, "--repaint" if $repaintTests; +push @toolArgs, "--horizontal-sweep" if $repaintSweepHorizontally; +push @toolArgs, "--threaded" if $threaded; +push @toolArgs, "-"; + +my @diffToolArgs = (); +push @diffToolArgs, "--threshold", $threshold; + +$| = 1; + +my $imageDiffToolPID; +if ($pixelTests) { + local %ENV; + $ENV{MallocStackLogging} = 1 if $shouldCheckLeaks; + $imageDiffToolPID = open2(\*DIFFIN, \*DIFFOUT, $imageDiffTool, @diffToolArgs) or die "unable to open $imageDiffTool\n"; +} + +my $dumpToolPID; +my $isDumpToolOpen = 0; +my $dumpToolCrashed = 0; + +my $atLineStart = 1; +my $lastDirectory = ""; + +my $isHttpdOpen = 0; + +sub catch_pipe { $dumpToolCrashed = 1; } +$SIG{"PIPE"} = "catch_pipe"; + +print "Testing ", scalar @tests, " test cases.\n"; +my $overallStartTime = time; + +my %expectedResultDirectory; + +# Reverse the tests +@tests = reverse @tests if $reverseTests; + +# Shuffle the array +@tests = shuffle(@tests) if $randomizeTests; + +for my $test (@tests) { + next if $test eq 'results.html'; + + my $newDumpTool = not $isDumpToolOpen; + openDumpTool(); + + my $base = stripExtension($test); + + my $dir = $base; + $dir =~ s|/[^/]+$||; + + if ($newDumpTool || $dir ne $lastDirectory) { + foreach my $logue (epiloguesAndPrologues($newDumpTool ? "" : $lastDirectory, $dir)) { + if (isCygwin()) { + $logue = toWindowsPath($logue); + } else { + $logue = canonpath($logue); + } + if ($verbose) { + print "running epilogue or prologue $logue\n"; + } + print OUT "$logue\n"; + # Discard the output. + while (<IN>) { + last if /#EOF/; + } + } + } + + if ($verbose) { + print "running $test -> "; + $atLineStart = 0; + } elsif (!$quiet) { + if ($dir ne $lastDirectory) { + print "\n" unless $atLineStart; + print "$dir "; + } + print "."; + $atLineStart = 0; + } + + $lastDirectory = $dir; + + my $result; + + my $startTime = time if $report10Slowest; + + if ($test !~ /^http\//) { + my $testPath = "$testDirectory/$test"; + if (isCygwin()) { + $testPath = toWindowsPath($testPath); + } else { + $testPath = canonpath($testPath); + } + print OUT "$testPath\n"; + } else { + openHTTPDIfNeeded(); + if ($test !~ /^http\/tests\/local\// && $test !~ /^http\/tests\/ssl\// && $test !~ /^http\/tests\/media\//) { + my $path = canonpath($test); + $path =~ s/^http\/tests\///; + print OUT "http://127.0.0.1:$httpdPort/$path\n"; + } elsif ($test =~ /^http\/tests\/ssl\//) { + my $path = canonpath($test); + $path =~ s/^http\/tests\///; + print OUT "https://127.0.0.1:$httpdSSLPort/$path\n"; + } else { + my $testPath = "$testDirectory/$test"; + if (isCygwin()) { + $testPath = toWindowsPath($testPath); + } else { + $testPath = canonpath($testPath); + } + print OUT "$testPath\n"; + } + } + + my $actual = ""; + while (<IN>) { + last if /#EOF/; + $actual .= $_; + } + + my $isText = isTextOnlyTest($actual); + + $durations{$test} = time - $startTime if $report10Slowest; + + my $expected; + my $expectedDir = expectedDirectoryForTest($base, $isText, 0); + $expectedResultDirectory{$base} = $expectedDir; + + if (!$resetResults && open EXPECTED, "<", "$expectedDir/$base-$expectedTag.txt") { + $expected = ""; + while (<EXPECTED>) { + next if $stripEditingCallbacks && $_ =~ /^EDITING DELEGATE:/; + $expected .= $_; + } + close EXPECTED; + } + my $expectedMac; + if (!isOSX() && $strictTesting && !$isText) { + if (!$resetResults && open EXPECTED, "<", "$testDirectory/platform/mac/$base-$expectedTag.txt") { + $expectedMac = ""; + while (<EXPECTED>) { + $expectedMac .= $_; + } + close EXPECTED; + } + } + + if ($shouldCheckLeaks && $testsPerDumpTool == 1) { + print " $test -> "; + } + + my $actualPNG = ""; + my $diffPNG = ""; + my $diffPercentage = ""; + my $diffResult = "passed"; + + if ($pixelTests) { + my $expectedPixelDir = expectedDirectoryForTest($base, $isText, 1); + + my $actualHash = ""; + my $expectedHash = ""; + my $actualPNGSize = 0; + + while (<IN>) { + last if /#EOF/; + if (/ActualHash: ([a-f0-9]{32})/) { + $actualHash = $1; + } elsif (/BaselineHash: ([a-f0-9]{32})/) { + $expectedHash = $1; + } elsif (/Content-length: (\d+)\s*/) { + $actualPNGSize = $1; + read(IN, $actualPNG, $actualPNGSize); + } + } + + if ($expectedHash ne $actualHash && -f "$expectedPixelDir/$base-$expectedTag.png") { + my $expectedPNGSize = -s "$expectedPixelDir/$base-$expectedTag.png"; + my $expectedPNG = ""; + open EXPECTEDPNG, "$expectedPixelDir/$base-$expectedTag.png"; + read(EXPECTEDPNG, $expectedPNG, $expectedPNGSize); + + print DIFFOUT "Content-length: $actualPNGSize\n"; + print DIFFOUT $actualPNG; + + print DIFFOUT "Content-length: $expectedPNGSize\n"; + print DIFFOUT $expectedPNG; + + while (<DIFFIN>) { + last if /^error/ || /^diff:/; + if (/Content-length: (\d+)\s*/) { + read(DIFFIN, $diffPNG, $1); + } + } + + if (/^diff: (.+)% (passed|failed)/) { + $diffPercentage = $1; + $imageDifferences{$base} = $diffPercentage; + $diffResult = $2; + } + } + + if ($actualPNGSize && ($resetResults || !-f "$expectedPixelDir/$base-$expectedTag.png")) { + mkpath catfile($expectedPixelDir, dirname($base)) if $testDirectory ne $expectedPixelDir; + open EXPECTED, ">", "$expectedPixelDir/$base-expected.png" or die "could not create $expectedPixelDir/$base-expected.png\n"; + print EXPECTED $actualPNG; + close EXPECTED; + } + + # update the expected hash if the image diff said that there was no difference + if ($actualHash ne "" && ($resetResults || !-f "$expectedPixelDir/$base-$expectedTag.checksum")) { + open EXPECTED, ">", "$expectedPixelDir/$base-$expectedTag.checksum" or die "could not create $expectedPixelDir/$base-$expectedTag.checksum\n"; + print EXPECTED $actualHash; + close EXPECTED; + } + } + + if (!isOSX() && $strictTesting && !$isText) { + if (defined $expectedMac) { + my $simplified_actual; + $simplified_actual = $actual; + $simplified_actual =~ s/at \(-?[0-9]+,-?[0-9]+\) *//g; + $simplified_actual =~ s/size -?[0-9]+x-?[0-9]+ *//g; + $simplified_actual =~ s/text run width -?[0-9]+: //g; + $simplified_actual =~ s/text run width -?[0-9]+ [a-zA-Z ]+: //g; + $simplified_actual =~ s/RenderButton {BUTTON} .*/RenderButton {BUTTON}/g; + $simplified_actual =~ s/RenderImage {INPUT} .*/RenderImage {INPUT}/g; + $simplified_actual =~ s/RenderBlock {INPUT} .*/RenderBlock {INPUT}/g; + $simplified_actual =~ s/RenderTextControl {INPUT} .*/RenderTextControl {INPUT}/g; + $simplified_actual =~ s/\([0-9]+px/px/g; + $simplified_actual =~ s/ *" *\n +" */ /g; + $simplified_actual =~ s/" +$/"/g; + + $simplified_actual =~ s/- /-/g; + $simplified_actual =~ s/\n( *)"\s+/\n$1"/g; + $simplified_actual =~ s/\s+"\n/"\n/g; + + $expectedMac =~ s/at \(-?[0-9]+,-?[0-9]+\) *//g; + $expectedMac =~ s/size -?[0-9]+x-?[0-9]+ *//g; + $expectedMac =~ s/text run width -?[0-9]+: //g; + $expectedMac =~ s/text run width -?[0-9]+ [a-zA-Z ]+: //g; + $expectedMac =~ s/RenderButton {BUTTON} .*/RenderButton {BUTTON}/g; + $expectedMac =~ s/RenderImage {INPUT} .*/RenderImage {INPUT}/g; + $expectedMac =~ s/RenderBlock {INPUT} .*/RenderBlock {INPUT}/g; + $expectedMac =~ s/RenderTextControl {INPUT} .*/RenderTextControl {INPUT}/g; + $expectedMac =~ s/\([0-9]+px/px/g; + $expectedMac =~ s/ *" *\n +" */ /g; + $expectedMac =~ s/" +$/"/g; + + $expectedMac =~ s/- /-/g; + $expectedMac =~ s/\n( *)"\s+/\n$1"/g; + $expectedMac =~ s/\s+"\n/"\n/g; + + if ($simplified_actual ne $expectedMac) { + open ACTUAL, ">", "/tmp/actual.txt" or die; + print ACTUAL $simplified_actual; + close ACTUAL; + open ACTUAL, ">", "/tmp/expected.txt" or die; + print ACTUAL $expectedMac; + close ACTUAL; + system "diff -u \"/tmp/expected.txt\" \"/tmp/actual.txt\" > \"/tmp/simplified.diff\""; + + $diffResult = "failed"; + if($verbose) { + print "\n"; + system "cat /tmp/simplified.diff"; + print "failed!!!!!"; + } + } + } + } + + if (dumpToolDidCrash()) { + $result = "crash"; + + printFailureMessageForTest($test, "crashed"); + + my $dir = "$testResultsDirectory/$base"; + $dir =~ s|/([^/]+)$|| or die "Failed to find test name from base\n"; + mkpath $dir; + + deleteExpectedAndActualResults($base); + + open CRASH, ">", "$testResultsDirectory/$base-$errorTag.txt" or die; + print CRASH <ERROR>; + close CRASH; + + recordActualResultsAndDiff($base, $actual); + + closeDumpTool(); + } elsif (!defined $expected) { + if ($verbose) { + print "new " . ($resetResults ? "result" : "test") ."\n"; + $atLineStart = 1; + } + $result = "new"; + + if ($generateNewResults || $resetResults) { + mkpath catfile($expectedDir, dirname($base)) if $testDirectory ne $expectedDir; + open EXPECTED, ">", "$expectedDir/$base-$expectedTag.txt" or die "could not create $expectedDir/$base-$expectedTag.txt\n"; + print EXPECTED $actual; + close EXPECTED; + } + deleteExpectedAndActualResults($base); + unless ($resetResults) { + # Always print the file name for new tests, as they will probably need some manual inspection. + # in verbose mode we already printed the test case, so no need to do it again. + unless ($verbose) { + print "\n" unless $atLineStart; + print "$test -> "; + } + my $resultsDir = catdir($expectedDir, dirname($base)); + print "new (results generated in $resultsDir)\n"; + $atLineStart = 1; + } + } elsif ($actual eq $expected && $diffResult eq "passed") { + if ($verbose) { + print "succeeded\n"; + $atLineStart = 1; + } + $result = "match"; + deleteExpectedAndActualResults($base); + } else { + $result = "mismatch"; + + my $message = $actual eq $expected ? "pixel test failed" : "failed"; + + if ($actual ne $expected && $addPlatformExceptions) { + my $testBase = catfile($testDirectory, $base); + my $expectedBase = catfile($expectedDir, $base); + my $testIsMaximallyPlatformSpecific = $testBase =~ m|^\Q$platformTestDirectory\E/|; + my $expectedResultIsMaximallyPlatformSpecific = $expectedBase =~ m|^\Q$platformTestDirectory\E/|; + if (!$testIsMaximallyPlatformSpecific && !$expectedResultIsMaximallyPlatformSpecific) { + mkpath catfile($platformTestDirectory, dirname($base)); + my $expectedFile = catfile($platformTestDirectory, "$base-$expectedTag.txt"); + open EXPECTED, ">", $expectedFile or die "could not create $expectedFile\n"; + print EXPECTED $actual; + close EXPECTED; + $message .= " (results generated in $platformTestDirectory)"; + } + } + + printFailureMessageForTest($test, $message); + + my $dir = "$testResultsDirectory/$base"; + $dir =~ s|/([^/]+)$|| or die "Failed to find test name from base\n"; + my $testName = $1; + mkpath $dir; + + deleteExpectedAndActualResults($base); + recordActualResultsAndDiff($base, $actual); + + if ($pixelTests && $diffPNG && $diffPNG ne "") { + $imagesPresent{$base} = 1; + + open ACTUAL, ">", "$testResultsDirectory/$base-$actualTag.png" or die; + print ACTUAL $actualPNG; + close ACTUAL; + + open DIFF, ">", "$testResultsDirectory/$base-$diffsTag.png" or die; + print DIFF $diffPNG; + close DIFF; + + copy("$expectedDir/$base-$expectedTag.png", "$testResultsDirectory/$base-$expectedTag.png"); + + open DIFFHTML, ">$testResultsDirectory/$base-$diffsTag.html" or die; + print DIFFHTML "<html>\n"; + print DIFFHTML "<head>\n"; + print DIFFHTML "<title>$base Image Compare</title>\n"; + print DIFFHTML "<script language=\"Javascript\" type=\"text/javascript\">\n"; + print DIFFHTML "var currentImage = 0;\n"; + print DIFFHTML "var imageNames = new Array(\"Actual\", \"Expected\");\n"; + print DIFFHTML "var imagePaths = new Array(\"$testName-$actualTag.png\", \"$testName-$expectedTag.png\");\n"; + if (-f "$testDirectory/$base-w3c.png") { + copy("$testDirectory/$base-w3c.png", "$testResultsDirectory/$base-w3c.png"); + print DIFFHTML "imageNames.push(\"W3C\");\n"; + print DIFFHTML "imagePaths.push(\"$testName-w3c.png\");\n"; + } + print DIFFHTML "function animateImage() {\n"; + print DIFFHTML " var image = document.getElementById(\"animatedImage\");\n"; + print DIFFHTML " var imageText = document.getElementById(\"imageText\");\n"; + print DIFFHTML " image.src = imagePaths[currentImage];\n"; + print DIFFHTML " imageText.innerHTML = imageNames[currentImage] + \" Image\";\n"; + print DIFFHTML " currentImage = (currentImage + 1) % imageNames.length;\n"; + print DIFFHTML " setTimeout('animateImage()',2000);\n"; + print DIFFHTML "}\n"; + print DIFFHTML "</script>\n"; + print DIFFHTML "</head>\n"; + print DIFFHTML "<body onLoad=\"animateImage();\">\n"; + print DIFFHTML "<table>\n"; + if ($diffPercentage) { + print DIFFHTML "<tr>\n"; + print DIFFHTML "<td>Difference between images: <a href=\"$testName-$diffsTag.png\">$diffPercentage%</a></td>\n"; + print DIFFHTML "</tr>\n"; + } + print DIFFHTML "<tr>\n"; + print DIFFHTML "<td><a href=\"" . toURL("$testDirectory/$test") . "\">test file</a></td>\n"; + print DIFFHTML "</tr>\n"; + print DIFFHTML "<tr>\n"; + print DIFFHTML "<td id=\"imageText\" style=\"text-weight: bold;\">Actual Image</td>\n"; + print DIFFHTML "</tr>\n"; + print DIFFHTML "<tr>\n"; + print DIFFHTML "<td><img src=\"$testName-$actualTag.png\" id=\"animatedImage\"></td>\n"; + print DIFFHTML "</tr>\n"; + print DIFFHTML "</table>\n"; + print DIFFHTML "</body>\n"; + print DIFFHTML "</html>\n"; + } + } + + if (($count + 1) % $testsPerDumpTool == 0 || $count == $#tests) { + if ($shouldCheckLeaks) { + my $fileName; + if ($testsPerDumpTool == 1) { + $fileName = "$testResultsDirectory/$base-leaks.txt"; + } else { + $fileName = "$testResultsDirectory/" . fileNameWithNumber($dumpToolName, $leaksOutputFileNumber) . "-leaks.txt"; + } + my $leakCount = countAndPrintLeaks($dumpToolName, $dumpToolPID, $fileName); + $totalLeaks += $leakCount; + $leaksOutputFileNumber++ if ($leakCount); + } + + closeDumpTool(); + } + + $count++; + $counts{$result}++; + push @{$tests{$result}}, $test; + $testType{$test} = $isText; +} +printf "\n%0.2fs total testing time\n", (time - $overallStartTime) . ""; + +!$isDumpToolOpen || die "Failed to close $dumpToolName.\n"; + +closeHTTPD(); + +# Because multiple instances of this script are running concurrently we cannot +# safely delete this symlink. +# system "rm /tmp/LayoutTests"; + +# FIXME: Do we really want to check the image-comparison tool for leaks every time? +if ($shouldCheckLeaks && $pixelTests) { + $totalLeaks += countAndPrintLeaks("ImageDiff", $imageDiffToolPID, "$testResultsDirectory/ImageDiff-leaks.txt"); +} + +if ($totalLeaks) { + if ($mergeDepth) { + parseLeaksandPrintUniqueLeaks(); + } + else { + print "\nWARNING: $totalLeaks total leaks found!\n"; + print "See above for individual leaks results.\n" if ($leaksOutputFileNumber > 2); + } +} + +close IN; +close OUT; +close ERROR; + +if ($report10Slowest) { + print "\n\nThe 10 slowest tests:\n\n"; + my $count = 0; + for my $test (sort slowestcmp keys %durations) { + printf "%0.2f secs: %s\n", $durations{$test}, $test; + last if ++$count == 10; + } +} + +print "\n"; + +if ($skippedOnly && $counts{"match"}) { + print "The following tests are in the Skipped file (" . File::Spec->abs2rel("$platformTestDirectory/Skipped", $testDirectory) . "), but succeeded:\n"; + foreach my $test (@{$tests{"match"}}) { + print " $test\n"; + } +} + +if ($resetResults || ($counts{match} && $counts{match} == $count)) { + print "all $count test cases succeeded\n"; + unlink $testResults; + exit; +} + + +my %text = ( + match => "succeeded", + mismatch => "had incorrect layout", + new => "were new", + crash => "crashed", +); + +for my $type ("match", "mismatch", "new", "crash") { + my $c = $counts{$type}; + if ($c) { + my $t = $text{$type}; + my $message; + if ($c == 1) { + $t =~ s/were/was/; + $message = sprintf "1 test case (%d%%) %s\n", 1 * 100 / $count, $t; + } else { + $message = sprintf "%d test cases (%d%%) %s\n", $c, $c * 100 / $count, $t; + } + $message =~ s-\(0%\)-(<1%)-; + print $message; + } +} + +mkpath $testResultsDirectory; + +open HTML, ">", $testResults or die; +print HTML "<html>\n"; +print HTML "<head>\n"; +print HTML "<title>Layout Test Results</title>\n"; +print HTML "</head>\n"; +print HTML "<body>\n"; + +if ($counts{mismatch}) { + print HTML "<p>Tests where results did not match expected results:</p>\n"; + print HTML "<table>\n"; + for my $test (@{$tests{mismatch}}) { + my $base = stripExtension($test); + print HTML "<tr>\n"; + print HTML "<td><a href=\"" . toURL("$testDirectory/$test") . "\">$test</a></td>\n"; + print HTML htmlForExpectedAndActualResults($base); + if ($pixelTests) { + if ($imagesPresent{$base}) { + print HTML "<td><a href=\"$base-$expectedTag.png\">expected image</a></td>\n"; + print HTML "<td><a href=\"$base-$diffsTag.html\">image diffs</a>\n"; + print HTML "<a href=\"$base-$diffsTag.png\">$imageDifferences{$base}%</a></td>\n"; + } else { + print HTML "<td></td><td></td>\n"; + } + } + print HTML "</tr>\n"; + } + print HTML "</table>\n"; +} + +if ($counts{crash}) { + print HTML "<p>Tests that caused the DumpRenderTree tool to crash:</p>\n"; + print HTML "<table>\n"; + for my $test (@{$tests{crash}}) { + my $base = stripExtension($test); + my $expectedDir = $expectedResultDirectory{$base}; + print HTML "<tr>\n"; + print HTML "<td><a href=\"" . toURL("$testDirectory/$test") . "\">$base</a></td>\n"; + print HTML htmlForExpectedAndActualResults($base); + print HTML "<td><a href=\"$base-$errorTag.txt\">stderr</a></td>\n"; + print HTML "</tr>\n"; + } + print HTML "</table>\n"; +} + +if ($counts{new}) { + print HTML "<p>Tests that had no expected results (probably new):</p>\n"; + print HTML "<table>\n"; + for my $test (@{$tests{new}}) { + my $base = stripExtension($test); + my $expectedDir = $expectedResultDirectory{$base}; + print HTML "<tr>\n"; + print HTML "<td><a href=\"" . toURL("$testDirectory/$test") . "\">$base</a></td>\n"; + print HTML "<td><a href=\"" . toURL("$expectedDir/$base-$expectedTag.txt") . "\">results</a></td>\n"; + if ($pixelTests && -f "$expectedDir/$base-$expectedTag.png") { + print HTML "<td><a href=\"" . toURL("$expectedDir/$base-$expectedTag.png") . "\">image</a></td>\n"; + } + print HTML "</tr>\n"; + } + print HTML "</table>\n"; +} + +print HTML "</body>\n"; +print HTML "</html>\n"; +close HTML; + +if (isQt()) { + system "konqueror", $testResults if $launchSafari; +} elsif (isGtk()) { + system "WebKitTools/Scripts/run-launcher", "--gtk", $configurationOption, $testResults if $launchSafari; +} elsif (isCygwin()) { + system "cygstart", $testResults if $launchSafari; +} else { + system "WebKitTools/Scripts/run-safari", $configurationOption, "-NSOpen", $testResults if $launchSafari; +} + +closeCygpaths() if isCygwin(); + +exit 1; + +sub countAndPrintLeaks($$$) +{ + my ($dumpToolName, $dumpToolPID, $leaksFilePath) = @_; + + print "\n" unless $atLineStart; + $atLineStart = 1; + + # We are excluding the following reported leaks so they don't get in our way when looking for WebKit leaks: + # This allows us ignore known leaks and only be alerted when new leaks occur. Some leaks are in the old + # versions of the system frameworks that are being used by the leaks bots. Even though a leak has been + # fixed, it will be listed here until the bot has been updated with the newer frameworks. + + my @typesToExclude = ( + ); + + my @callStacksToExclude = ( + "Flash_EnforceLocalSecurity" # leaks in Flash plug-in code, rdar://problem/4449747 + ); + + if (isTiger()) { + # Leak list for the version of Tiger used on the build bot. + push @callStacksToExclude, ( + "CFRunLoopRunSpecific \\| malloc_zone_malloc", "CFRunLoopRunSpecific \\| CFAllocatorAllocate ", # leak in CFRunLoopRunSpecific, rdar://problem/4670839 + "CGImageSourceGetPropertiesAtIndex", # leak in ImageIO, rdar://problem/4628809 + "FOGetCoveredUnicodeChars", # leak in ATS, rdar://problem/3943604 + "GetLineDirectionPreference", "InitUnicodeUtilities", # leaks tool falsely reporting leak in CFNotificationCenterAddObserver, rdar://problem/4964790 + "ICCFPrefWrapper::GetPrefDictionary", # leaks in Internet Config. code, rdar://problem/4449794 + "NSHTTPURLProtocol setResponseHeader:", # leak in multipart/mixed-replace handling in Foundation, no Radar, but fixed in Leopard + "NSURLCache cachedResponseForRequest", # leak in CFURL cache, rdar://problem/4768430 + "PCFragPrepareClosureFromFile", # leak in Code Fragment Manager, rdar://problem/3426998 + "WebCore::Selection::toRange", # bug in 'leaks', rdar://problem/4967949 + "WebCore::SubresourceLoader::create", # bug in 'leaks', rdar://problem/4985806 + "_CFPreferencesDomainDeepCopyDictionary", # leak in CFPreferences, rdar://problem/4220786 + "_objc_msgForward", # leak in NSSpellChecker, rdar://problem/4965278 + "gldGetString", # leak in OpenGL, rdar://problem/5013699 + "_setDefaultUserInfoFromURL", # leak in NSHTTPAuthenticator, rdar://problem/5546453 + "SSLHandshake", # leak in SSL, rdar://problem/5546440 + "SecCertificateCreateFromData", # leak in SSL code, rdar://problem/4464397 + ); + push @typesToExclude, ( + "THRD", # bug in 'leaks', rdar://problem/3387783 + "DRHT", # ditto (endian little hate i) + ); + } + + if (isLeopard()) { + # Leak list for the version of Leopard used on the build bot. + push @callStacksToExclude, ( + "CFHTTPMessageAppendBytes", # leak in CFNetwork, rdar://problem/5435912 + "sendDidReceiveDataCallback", # leak in CFNetwork, rdar://problem/5441619 + "_CFHTTPReadStreamReadMark", # leak in CFNetwork, rdar://problem/5441468 + "httpProtocolStart", # leak in CFNetwork, rdar://problem/5468837 + "_CFURLConnectionSendCallbacks", # leak in CFNetwork, rdar://problem/5441600 + "DispatchQTMsg", # leak in Quicktime, PPC only, <rdar://problem/5667132> + "QTMovieContentView createVisualContext", # leak in Quicktime, PPC only, <rdar://problem/5667132> + ); + } + + my $leaksTool = sourceDir() . "/WebKitTools/Scripts/run-leaks"; + my $excludeString = "--exclude-callstack '" . (join "' --exclude-callstack '", @callStacksToExclude) . "'"; + $excludeString .= " --exclude-type '" . (join "' --exclude-type '", @typesToExclude) . "'" if @typesToExclude; + + print " ? checking for leaks in $dumpToolName\n"; + my $leaksOutput = `$leaksTool $excludeString $dumpToolPID`; + my ($count, $bytes) = $leaksOutput =~ /Process $dumpToolPID: (\d+) leaks? for (\d+) total/; + my ($excluded) = $leaksOutput =~ /(\d+) leaks? excluded/; + + my $adjustedCount = $count; + $adjustedCount -= $excluded if $excluded; + + if (!$adjustedCount) { + print " - no leaks found\n"; + unlink $leaksFilePath; + return 0; + } else { + my $dir = $leaksFilePath; + $dir =~ s|/[^/]+$|| or die; + mkpath $dir; + + if ($excluded) { + print " + $adjustedCount leaks ($bytes bytes including $excluded excluded leaks) were found, details in $leaksFilePath\n"; + } else { + print " + $count leaks ($bytes bytes) were found, details in $leaksFilePath\n"; + } + + open LEAKS, ">", $leaksFilePath or die; + print LEAKS $leaksOutput; + close LEAKS; + + push( @leaksFilenames, $leaksFilePath ); + } + + return $adjustedCount; +} + +# Break up a path into the directory (with slash) and base name. +sub splitpath($) +{ + my ($path) = @_; + + my $pathSeparator = "/"; + my $dirname = dirname($path) . $pathSeparator; + $dirname = "" if $dirname eq "." . $pathSeparator; + + return ($dirname, basename($path)); +} + +# Sort first by directory, then by file, so all paths in one directory are grouped +# rather than being interspersed with items from subdirectories. +# Use numericcmp to sort directory and filenames to make order logical. +sub pathcmp($$) +{ + my ($patha, $pathb) = @_; + + my ($dira, $namea) = splitpath($patha); + my ($dirb, $nameb) = splitpath($pathb); + + return numericcmp($dira, $dirb) if $dira ne $dirb; + return numericcmp($namea, $nameb); +} + +# Sort numeric parts of strings as numbers, other parts as strings. +# Makes 1.33 come after 1.3, which is cool. +sub numericcmp($$) +{ + my ($aa, $bb) = @_; + + my @a = split /(\d+)/, $aa; + my @b = split /(\d+)/, $bb; + + # Compare one chunk at a time. + # Each chunk is either all numeric digits, or all not numeric digits. + while (@a && @b) { + my $a = shift @a; + my $b = shift @b; + + # Use numeric comparison if chunks are non-equal numbers. + return $a <=> $b if $a =~ /^\d/ && $b =~ /^\d/ && $a != $b; + + # Use string comparison if chunks are any other kind of non-equal string. + return $a cmp $b if $a ne $b; + } + + # One of the two is now empty; compare lengths for result in this case. + return @a <=> @b; +} + +# Sort slowest tests first. +sub slowestcmp($$) +{ + my ($testa, $testb) = @_; + + my $dura = $durations{$testa}; + my $durb = $durations{$testb}; + return $durb <=> $dura if $dura != $durb; + return pathcmp($testa, $testb); +} + +sub openDumpTool() +{ + return if $isDumpToolOpen; + + # Save some requires variables for the linux environment... + my $homeDir = $ENV{'HOME'}; + my $libraryPath = $ENV{'LD_LIBRARY_PATH'}; + my $dyldLibraryPath = $ENV{'DYLD_LIBRARY_PATH'}; + my $dbusAddress = $ENV{'DBUS_SESSION_BUS_ADDRESS'}; + my $display = $ENV{'DISPLAY'}; + my $testfonts = $ENV{'WEBKIT_TESTFONTS'}; + + my $homeDrive = $ENV{'HOMEDRIVE'}; + my $homePath = $ENV{'HOMEPATH'}; + + local %ENV; + if (isQt() || isGtk()) { + if (defined $display) { + $ENV{DISPLAY} = $display; + } else { + $ENV{DISPLAY} = ":1"; + } + $ENV{'WEBKIT_TESTFONTS'} = $testfonts if defined($testfonts); + $ENV{HOME} = $homeDir; + if (defined $libraryPath) { + $ENV{LD_LIBRARY_PATH} = $libraryPath; + } + if (defined $dyldLibraryPath) { + $ENV{DYLD_LIBRARY_PATH} = $dyldLibraryPath; + } + if (defined $dbusAddress) { + $ENV{DBUS_SESSION_BUS_ADDRESS} = $dbusAddress; + } + } + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + $ENV{XML_CATALOG_FILES} = ""; # work around missing /etc/catalog <rdar://problem/4292995> + $ENV{MallocStackLogging} = 1 if $shouldCheckLeaks; + $ENV{DYLD_INSERT_LIBRARIES} = "/usr/lib/libgmalloc.dylib" if $guardMalloc; + + if (isCygwin()) { + $ENV{HOMEDRIVE} = $homeDrive; + $ENV{HOMEPATH} = $homePath; + if ($testfonts) { + $ENV{WEBKIT_TESTFONTS} = $testfonts; + } + setPathForRunningWebKitApp(\%ENV) if isCygwin(); + } + + my @args = (); + if ($useValgrind) { + push @args, $dumpTool; + } + push @args, @toolArgs; + if ($useValgrind) { + $dumpTool = "valgrind"; + } + $dumpToolPID = open3(\*OUT, \*IN, \*ERROR, $dumpTool, @args) or die "Failed to start tool: $dumpTool\n"; + $isDumpToolOpen = 1; + $dumpToolCrashed = 0; +} + +sub closeDumpTool() +{ + return if !$isDumpToolOpen; + + close IN; + close OUT; + close ERROR; + waitpid $dumpToolPID, 0; + $isDumpToolOpen = 0; +} + +sub dumpToolDidCrash() +{ + return 1 if $dumpToolCrashed; + return 0 unless $isDumpToolOpen; + + my $pid = waitpid(-1, WNOHANG); + return $pid == $dumpToolPID; +} + +sub openHTTPDIfNeeded() +{ + return if $isHttpdOpen; + + mkdir "/tmp/WebKit"; + + if (-f "/tmp/WebKit/httpd.pid") { + my $oldPid = `cat /tmp/WebKit/httpd.pid`; + chomp $oldPid; + if (0 != kill 0, $oldPid) { + print "\nhttpd is already running: pid $oldPid, killing...\n"; + kill 15, $oldPid; + + my $retryCount = 20; + while ((0 != kill 0, $oldPid) && $retryCount) { + sleep 1; + --$retryCount; + } + + die "Timed out waiting for httpd to quit" unless $retryCount; + } + } + + my $httpdPath = "/usr/sbin/httpd"; + my $httpdConfig; + if (isCygwin()) { + my $windowsConfDirectory = "$testDirectory/http/conf/"; + unless (-x "/usr/lib/apache/libphp4.dll") { + copy("$windowsConfDirectory/libphp4.dll", "/usr/lib/apache/libphp4.dll"); + chmod(0755, "/usr/lib/apache/libphp4.dll"); + } + $httpdConfig = "$windowsConfDirectory/cygwin-httpd.conf"; + } elsif (isDebianBased()) { + $httpdPath = "/usr/sbin/apache2"; + $httpdConfig = "$testDirectory/http/conf/apache2-debian-httpd.conf"; + } else { + $httpdConfig = "$testDirectory/http/conf/httpd.conf"; + $httpdConfig = "$testDirectory/http/conf/apache2-httpd.conf" if `$httpdPath -v` =~ m|Apache/2|; + } + my $documentRoot = "$testDirectory/http/tests"; + my $typesConfig = "$testDirectory/http/conf/mime.types"; + my $listen = "127.0.0.1:$httpdPort"; + my $absTestResultsDirectory = File::Spec->rel2abs(glob $testResultsDirectory); + my $sslCertificate = "$testDirectory/http/conf/webkit-httpd.pem"; + + mkpath $absTestResultsDirectory; + + my @args = ( + "-f", "$httpdConfig", + "-C", "DocumentRoot \"$documentRoot\"", + "-C", "Listen $listen", + "-c", "TypesConfig \"$typesConfig\"", + "-c", "CustomLog \"$absTestResultsDirectory/access_log.txt\" common", + "-c", "ErrorLog \"$absTestResultsDirectory/error_log.txt\"", + # Apache wouldn't run CGIs with permissions==700 otherwise + "-c", "User \"#$<\"" + ); + + # FIXME: Enable this on Windows once <rdar://problem/5345985> is fixed + push(@args, "-c", "SSLCertificateFile \"$sslCertificate\"") unless isCygwin(); + + open2(\*HTTPDIN, \*HTTPDOUT, $httpdPath, @args); + + my $retryCount = 20; + while (system("/usr/bin/curl -q --silent --stderr - --output /dev/null $listen") && $retryCount) { + sleep 1; + --$retryCount; + } + + die "Timed out waiting for httpd to start" unless $retryCount; + + $isHttpdOpen = 1; +} + +sub closeHTTPD() +{ + return if !$isHttpdOpen; + + close HTTPDIN; + close HTTPDOUT; + + kill 15, `cat /tmp/WebKit/httpd.pid` if -f "/tmp/WebKit/httpd.pid"; + + $isHttpdOpen = 0; +} + +sub fileNameWithNumber($$) +{ + my ($base, $number) = @_; + return "$base$number" if ($number > 1); + return $base; +} + +sub processIgnoreTests($) { + my @ignoreList = split(/\s*,\s*/, shift); + my $addIgnoredDirectories = sub { + return () if exists $ignoredLocalDirectories{basename($File::Find::dir)}; + $ignoredDirectories{File::Spec->abs2rel($File::Find::dir, $testDirectory)} = 1; + return @_; + }; + foreach my $item (@ignoreList) { + my $path = catfile($testDirectory, $item); + if (-d $path) { + $ignoredDirectories{$item} = 1; + find({ preprocess => $addIgnoredDirectories, wanted => sub {} }, $path); + } + elsif (-f $path) { + $ignoredFiles{$item} = 1; + } + else { + print "ignoring '$item' on ignore-tests list\n"; + } + } +} + +sub stripExtension($) +{ + my ($test) = @_; + + $test =~ s/\.[a-zA-Z]+$//; + return $test; +} + +sub isTextOnlyTest($) +{ + my ($actual) = @_; + my $isText; + if ($actual =~ /^layer at/ms) { + $isText = 0; + } else { + $isText = 1; + } + return $isText; +} + +sub expectedDirectoryForTest($;$;$) +{ + my ($base, $isText, $isPixelTest) = @_; + + my @directories = @platformHierarchy; + push @directories, map { catdir($platformBaseDirectory, $_) } qw(mac-leopard mac) if isCygwin(); + push @directories, $expectedDirectory; + + # If we already have expected results, just return their location. + if ($isPixelTest) { + foreach my $directory (@directories) { + return $directory if (-f "$directory/$base-$expectedTag.png"); + } + } else { + foreach my $directory (@directories) { + return $directory if (-f "$directory/$base-$expectedTag.txt"); + } + } + + # For platform-specific tests, the results should go right next to the test itself. + # Note: The return value of this subroutine will be concatenated with $base + # to determine the location of the new results, so returning $expectedDirectory + # will put the results right next to the test. + # FIXME: We want to allow platform/mac tests with platform/mac-leopard results, + # so this needs to be enhanced. + return $expectedDirectory if $base =~ /^platform/; + + # For cross-platform tests, text-only results should go in the cross-platform directory, + # while render tree dumps should go in the least-specific platform directory. + return $isText ? $expectedDirectory : $platformHierarchy[$#platformHierarchy]; +} + +sub printFailureMessageForTest($$) +{ + my ($test, $description) = @_; + + unless ($verbose) { + print "\n" unless $atLineStart; + print "$test -> "; + } + print "$description\n"; + $atLineStart = 1; +} + +my %cygpaths = (); + +sub openCygpathIfNeeded($) +{ + my ($options) = @_; + + return unless isCygwin(); + return $cygpaths{$options} if $cygpaths{$options} && $cygpaths{$options}->{"open"}; + + local (*CYGPATHIN, *CYGPATHOUT); + my $pid = open2(\*CYGPATHIN, \*CYGPATHOUT, "cygpath -f - $options"); + my $cygpath = { + "pid" => $pid, + "in" => *CYGPATHIN, + "out" => *CYGPATHOUT, + "open" => 1 + }; + + $cygpaths{$options} = $cygpath; + + return $cygpath; +} + +sub closeCygpaths() +{ + return unless isCygwin(); + + foreach my $cygpath (values(%cygpaths)) { + close $cygpath->{"in"}; + close $cygpath->{"out"}; + waitpid($cygpath->{"pid"}, 0); + $cygpath->{"open"} = 0; + + } +} + +sub convertPathUsingCygpath($$) +{ + my ($path, $options) = @_; + + my $cygpath = openCygpathIfNeeded($options); + local *inFH = $cygpath->{"in"}; + local *outFH = $cygpath->{"out"}; + print outFH $path . "\n"; + chomp(my $convertedPath = <inFH>); + return $convertedPath; +} + +sub toWindowsPath($) +{ + my ($path) = @_; + return unless isCygwin(); + + return convertPathUsingCygpath($path, "-w"); +} + +sub toURL($) +{ + my ($path) = @_; + return $path unless isCygwin(); + + return "file:///" . convertPathUsingCygpath($path, "-m"); +} + +sub validateSkippedArg($$;$) +{ + my ($option, $value, $value2) = @_; + my %validSkippedValues = map { $_ => 1 } qw(default ignore only); + $value = lc($value); + die "Invalid argument '" . $value . "' for option $option" unless $validSkippedValues{$value}; + $treatSkipped = $value; +} + +sub htmlForExpectedAndActualResults($) +{ + my ($base) = @_; + + return "<td></td><td></td><td></td>\n" unless -s "$testResultsDirectory/$base-$diffsTag.txt"; + + return "<td><a href=\"$base-$expectedTag.txt\">expected</a></td>\n" + . "<td><a href=\"$base-$actualTag.txt\">actual</a></td>\n" + . "<td><a href=\"$base-$diffsTag.txt\">diffs</a></td>\n"; +} + +sub deleteExpectedAndActualResults($) +{ + my ($base) = @_; + + unlink "$testResultsDirectory/$base-$actualTag.txt"; + unlink "$testResultsDirectory/$base-$diffsTag.txt"; + unlink "$testResultsDirectory/$base-$errorTag.txt"; +} + +sub recordActualResultsAndDiff($$) +{ + my ($base, $actual) = @_; + + return unless length($actual); + + open ACTUAL, ">", "$testResultsDirectory/$base-$actualTag.txt" or die "Couldn't open actual results file for $base"; + print ACTUAL $actual; + close ACTUAL; + + my $expectedDir = $expectedResultDirectory{$base}; + copy("$expectedDir/$base-$expectedTag.txt", "$testResultsDirectory/$base-$expectedTag.txt"); + + system "diff -u \"$testResultsDirectory/$base-$expectedTag.txt\" \"$testResultsDirectory/$base-$actualTag.txt\" > \"$testResultsDirectory/$base-$diffsTag.txt\""; +} + +sub buildPlatformHierarchy() +{ + mkpath($platformTestDirectory) if ($platform eq "undefined" && !-d "$platformTestDirectory"); + + my @platforms = split('-', $platform); + my @hierarchy; + for (my $i=0; $i < @platforms; $i++) { + my $scoped = catdir($platformBaseDirectory, join('-', @platforms[0..($#platforms - $i)])); + push(@hierarchy, $scoped) if (-d $scoped); + } + + return @hierarchy; +} + +sub epiloguesAndPrologues($$) { + my ($lastDirectory, $directory) = @_; + my @lastComponents = split('/', $lastDirectory); + my @components = split('/', $directory); + + while (@lastComponents) { + if ($lastComponents[0] ne $components[0]) { + last; + } + shift @components; + shift @lastComponents; + } + + my @result; + my $leaving = $lastDirectory; + foreach (@lastComponents) { + my $epilogue = $leaving . "/resources/run-webkit-tests-epilogue.html"; + foreach (@platformHierarchy) { + push @result, catdir($_, $epilogue) if (stat(catdir($_, $epilogue))); + } + push @result, catdir($testDirectory, $epilogue) if (stat(catdir($testDirectory, $epilogue))); + $leaving =~ s|(^\|/)[^/]+$||; + } + + my $entering = $leaving; + foreach (@components) { + $entering .= '/' . $_; + my $prologue = $entering . "/resources/run-webkit-tests-prologue.html"; + push @result, catdir($testDirectory, $prologue) if (stat(catdir($testDirectory, $prologue))); + foreach (reverse @platformHierarchy) { + push @result, catdir($_, $prologue) if (stat(catdir($_, $prologue))); + } + } + return @result; +} + +sub parseLeaksandPrintUniqueLeaks() { + return unless @leaksFilenames; + + my $mergedFilenames = join " ", @leaksFilenames; + my $parseMallocHistoryTool = sourceDir() . "/WebKitTools/Scripts/parse-malloc-history"; + + open MERGED_LEAKS, "cat $mergedFilenames | $parseMallocHistoryTool --merge-depth $mergeDepth - |" ; + my @leakLines = <MERGED_LEAKS>; + close MERGED_LEAKS; + + my $uniqueLeakCount = 0; + my $totalBytes; + foreach my $line (@leakLines) { + ++$uniqueLeakCount if ($line =~ /^(\d*)\scalls/); + $totalBytes = $1 if $line =~ /^total\:\s(.*)\s\(/; + } + + print "\nWARNING: $totalLeaks total leaks found for a total of $totalBytes!\n"; + print "WARNING: $uniqueLeakCount unique leaks found!\n"; + print "See above for individual leaks results.\n" if ($leaksOutputFileNumber > 2); + +} diff --git a/WebKitTools/Scripts/set-webkit-configuration b/WebKitTools/Scripts/set-webkit-configuration new file mode 100755 index 0000000..8735140 --- /dev/null +++ b/WebKitTools/Scripts/set-webkit-configuration @@ -0,0 +1,41 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005 Apple Computer, Inc. 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. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +my $configuration = passedConfiguration(); +die "Please specify either --debug or --release.\n" if !$configuration; + +my $baseProductDir = baseProductDir(); +system "mkdir", "-p", "$baseProductDir"; +open CONFIGURATION, ">", "$baseProductDir/Configuration" or die; +print CONFIGURATION $configuration; +close CONFIGURATION; diff --git a/WebKitTools/Scripts/sort-Xcode-project-file b/WebKitTools/Scripts/sort-Xcode-project-file new file mode 100755 index 0000000..e9b7a56 --- /dev/null +++ b/WebKitTools/Scripts/sort-Xcode-project-file @@ -0,0 +1,115 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Inc. 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 to sort "files=(...);" sections in Xcode project.pbxproj files + +use strict; + +use File::Basename; +use File::Temp; +use Getopt::Long; + +sub sortByFileName($$); + +my $printWarnings = 1; +my $showHelp; + +my $getOptionsResult = GetOptions( + 'h|help' => \$showHelp, + 'w|warnings!' => \$printWarnings, +); + +if (scalar(@ARGV) == 0) { + print STDERR "ERROR: No Xcode project files (project.pbxproj) listed on command-line.\n"; + undef $getOptionsResult; +} + +if (!$getOptionsResult || $showHelp) { + print STDERR <<__END__; +Usage: @{[ basename($0) ]} [options] path/to/project.pbxproj [path/to/project.pbxproj ...] + -h|--help show this help message + -w|--[no-]warnings show or suppress warnings (default: show warnings) +__END__ + exit 1; +} + +for my $projectFile (@ARGV) { + if (basename($projectFile) ne "project.pbxproj") { + print STDERR "WARNING: Not an Xcode project file: $projectFile\n" if $printWarnings; + next; + } + + my $OUT = new File::Temp( + DIR => dirname($projectFile), + TEMPLATE => basename($projectFile) . "-XXXXXXXX", + UNLINK => 0, + ); + my $tempFileName = $OUT->filename(); + + # Clean up temp file in case of die() + $SIG{__DIE__} = sub { + close(IN); + close($OUT); + unlink($tempFileName); + }; + + open(IN, "< $projectFile") || die "Could not open $projectFile: $!"; + while (my $line = <IN>) { + if ($line =~ /^(\s*)files = \(\s*$/) { + print $OUT $line; + my $endMarker = $1 . ");"; + my @files; + while (my $fileLine = <IN>) { + if ($fileLine =~ /^\Q$endMarker\E\s*$/) { + $endMarker = $fileLine; + last; + } + push @files, $fileLine; + } + print $OUT sort sortByFileName @files; + print $OUT $endMarker; + } else { + print $OUT $line; + } + } + close(IN); + close($OUT); + + unlink($projectFile) || die "Could not delete $projectFile: $!"; + rename($tempFileName, $projectFile) || die "Could not rename $tempFileName to $projectFile: $!"; +} + +exit 0; + +sub sortByFileName($$) +{ + my ($a, $b) = @_; + my $aFileName = $1 if $a =~ /^\s*[A-Z0-9]{24} \/\* (.+) in /; + my $bFileName = $1 if $b =~ /^\s*[A-Z0-9]{24} \/\* (.+) in /; + return $aFileName cmp $bFileName; +} diff --git a/WebKitTools/Scripts/split-file-by-class b/WebKitTools/Scripts/split-file-by-class new file mode 100755 index 0000000..b6aeb68 --- /dev/null +++ b/WebKitTools/Scripts/split-file-by-class @@ -0,0 +1,159 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006 Apple Computer, Inc. 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. + +# Used for splitting a single file into multiple class files +# Usage: split-class <header file> + +use strict; +use File::Copy; +use FindBin; +use lib $FindBin::Bin; +use SpacingHeuristics; + + +for my $filename (@ARGV) { + + $filename =~ m/^(\w+)\.h$/ or die "Command line args must be .h files.\n"; + my $basename = $1; + + open(OLDFILE, "<", $filename) or die "File does not exist: $filename\n"; + print "Splitting class $filename.{h,cpp}:\n"; + + my $currentClassName = ""; + my $classIndent = ""; + my $fileContent = ""; + my %classDefs = (); + while (my $line = <OLDFILE>) { + if ($currentClassName) { + $classDefs{$currentClassName} .= $line; + if ($line =~ /^$classIndent};\s*$/) { + $currentClassName = ""; + } + } else { + if ($line =~ /^(\s*)class\s+(\w+)\s+[^;]*$/) { + $classIndent = $1; + $currentClassName = $2; + $classDefs{$currentClassName} .= $line; + $fileContent .= "###CLASS###$currentClassName\n"; + } else { + $fileContent .= $line; + } + } + } + close(OLDFILE); + + if (scalar(keys(%classDefs)) == 1) { # degenerate case + my ($classname) = keys(%classDefs); + if (!($classname eq $basename)) { + print "Skipping $filename, already correctly named.\n"; + } else { + print "$filename only includes one class, renaming to $classname.h\n"; + system("svn rm --force $classname.h") if (-r "$classname.h"); + system "svn mv $basename.h $classname.h"; + } + } else { + while (my ($classname, $classDef) = each(%classDefs)) { + if (($classname eq $basename)) { + print "Skipping $filename, already correctly named.\n"; + } else { + print "Using SVN to copy $basename.{h,cpp} to $classname.{h,cpp}\n"; + + system("svn rm --force $classname.h") if (-r "$classname.h"); + system "svn cp $basename.h $classname.h"; + + system("svn rm --force $classname.cpp") if (-r "$classname.cpp"); + system "svn cp $basename.cpp $classname.cpp"; + } + + print "Fixing $classname.h as much as possible.\n"; + open(NEWHEADER, ">", "$classname.h") or die "File does not exist: $filename\n"; + my @lines = split("\n", $fileContent); + foreach my $line (@lines) { + if ($line =~ /^###CLASS###(\w+)/) { + if ($1 eq $classname) { + print NEWHEADER $classDef . "\n"; + } + } else { + print NEWHEADER $line . "\n"; + } + } + close(NEWHEADER); + + print "Fixing $classname.cpp as much as possible.\n"; + copy("$classname.cpp", "$classname.cpp.original"); + open(OLDCPP, "<", "$classname.cpp.original") or die "Failed to copy file for reading: $filename\n"; + open(NEWCPP, ">", "$classname.cpp") or die "File does not exist: $filename\n"; + my $insideMemberFunction = 0; + my $shouldPrintMemberFunction = 0; + resetSpacingHeuristics(); + while (my $line = <OLDCPP>) { + if ($insideMemberFunction) { + if ($shouldPrintMemberFunction) { + print NEWCPP $line; + #setPreviousAllowedLine($line); + } else { + ignoringLine($line); + } + if ($line =~ /^}\s*$/) { + $insideMemberFunction = 0; + } + } elsif ($line =~ /$filename/) { + print NEWCPP "#include \"config.h\"\n"; + print NEWCPP "#include \"$classname.h\"\n"; + } elsif ($line =~ /#include/ || $line =~ /#import/) { + next; # skip includes, they're generally wrong or unecessary anyway. + } else { + $line =~ s/DOM:://; + $line =~ s/khtml:://; + $line =~ s/namespace DOM/namespace WebCore/; + $line =~ s/namespace khtml/namespace WebCore/; + + if ($line =~ /^(.*?\s+)?(\*|&)?(\w+)::(~)?\w+\s*\(/) { + $insideMemberFunction = 1; + $shouldPrintMemberFunction = ($classname eq $3); + if ($shouldPrintMemberFunction) { + printPendingEmptyLines(*NEWCPP, $line); + print NEWCPP $line; + } + } else { + next if isOnlyWhiteSpace($line); + next if ($line =~ m/------------/); + printPendingEmptyLines(*NEWCPP, $line); + applySpacingHeuristicsAndPrint(*NEWCPP, $line); + } + } + } + close(NEWCPP); + close(OLDCPP); + unlink("$classname.cpp.original"); + } + } + + print "Opening new files...\n"; + system("open " . join(".* ", keys(%classDefs)) . ".*"); +}
\ No newline at end of file diff --git a/WebKitTools/Scripts/sunspider-compare-results b/WebKitTools/Scripts/sunspider-compare-results new file mode 100755 index 0000000..cf18aae --- /dev/null +++ b/WebKitTools/Scripts/sunspider-compare-results @@ -0,0 +1,101 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2007 Apple Inc. All rights reserved. +# Copyright (C) 2007 Eric Seidel <eric@webkit.org> +# +# 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. +# +# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR +# 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. + +use strict; +use File::Spec; +use FindBin; +use Getopt::Long qw(:config pass_through); +use lib $FindBin::Bin; +use webkitdirs; +use POSIX; + +# determine configuration, but default to "Release" instead of last-used configuration to match run-sunspider +setConfiguration("Release"); +setConfiguration(); +my $configuration = configuration(); + +my $root; +my $showHelp = 0; + +my $programName = basename($0); +my $usage = <<EOF; +Usage: $programName [options] FILE FILE + --help Show this help message + --root Path to root tools build +EOF + +GetOptions('root=s' => sub { my ($argName, $value); setConfigurationProductDir(Cwd::abs_path($value)); }, + 'help' => \$showHelp); + +if ($showHelp) { + print STDERR $usage; + exit 1; +} + +@ARGV = map { File::Spec->rel2abs($_) } @ARGV; + +sub buildTestKJS +{ + if (!defined($root)){ + chdirWebKit(); + my $buildResult = system "WebKitTools/Scripts/build-testkjs", "--" . $configuration; + if ($buildResult) { + print STDERR "Compiling testkjs failed!\n"; + exit WEXITSTATUS($buildResult); + } + } +} + +sub setupEnvironmentForExecution($) +{ + my ($productDir) = @_; + print "Starting sunspider-compare-results with DYLD_FRAMEWORK_PATH set to point to built JavaScriptCore in $productDir.\n"; + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + # FIXME: Other platforms may wish to augment this method to use LD_LIBRARY_PATH, etc. +} + +sub testKJSPath($) +{ + my ($productDir) = @_; + my $testkjsName = "testkjs"; + $testkjsName .= "_debug" if (isCygwin() && ($configuration eq "Debug")); + return "$productDir/$testkjsName"; +} + +buildTestKJS(); + +chdirWebKit(); +chdir("SunSpider"); + +my $productDir = productDir(); +# FIXME: This hack should be pushed down into productDir() +$productDir .= "/JavaScriptCore" if (isQt() or isGtk()); + +setupEnvironmentForExecution($productDir); +my @args = ("--shell", testKJSPath($productDir)); +# This code could be removed if we chose to pass extra args to sunspider instead of Xcode + +exec "./sunspider-compare-results", @args, @ARGV; diff --git a/WebKitTools/Scripts/svn-apply b/WebKitTools/Scripts/svn-apply new file mode 100755 index 0000000..5845917 --- /dev/null +++ b/WebKitTools/Scripts/svn-apply @@ -0,0 +1,438 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006, 2007 Apple Inc. 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. + +# "patch" script for WebKit Open Source Project, used to apply patches. + +# Differences from invoking "patch -p0": +# +# Handles added files (does a svn add with logic to handle local changes). +# Handles added directories (does a svn add). +# Handles removed files (does a svn rm with logic to handle local changes). +# Handles removed directories--those with no more files or directories left in them +# (does a svn rm). +# Has mode where it will roll back to svn version numbers in the patch file so svn +# can do a 3-way merge. +# Paths from Index: lines are used rather than the paths on the patch lines, which +# makes patches generated by "cvs diff" work (increasingly unimportant since we +# use Subversion now). +# ChangeLog patches use --fuzz=3 to prevent rejects, and the entry date is set in +# the patch to today's date using $changeLogTimeZone. +# Handles binary files (requires patches made by svn-create-patch). +# Handles copied and moved files (requires patches made by svn-create-patch). +# Handles git-diff patches (without binary changes) created at the top-level directory +# +# Missing features: +# +# Handle property changes. +# Handle copied and moved directories (would require patches made by svn-create-patch). +# When doing a removal, check that old file matches what's being removed. +# Notice a patch that's being applied at the "wrong level" and make it work anyway. +# Do a dry run on the whole patch and don't do anything if part of the patch is +# going to fail (probably too strict unless we exclude ChangeLog). +# Handle git-diff patches with binary changes + +use strict; +use warnings; + +use Cwd; +use Digest::MD5; +use File::Basename; +use File::Spec; +use Getopt::Long; +use MIME::Base64; +use POSIX qw(strftime); + +sub addDirectoriesIfNeeded($); +sub applyPatch($$;$); +sub checksum($); +sub fixChangeLogPatch($); +sub gitdiff2svndiff($); +sub handleBinaryChange($$); +sub isDirectoryEmptyForRemoval($); +sub patch($); +sub removeDirectoriesIfNeeded(); +sub setChangeLogDate($); +sub svnStatus($); + +# Project time zone for Cupertino, CA, US +my $changeLogTimeZone = "PST8PDT"; + +my $merge = 0; +my $showHelp = 0; +if (!GetOptions("merge!" => \$merge, "help!" => \$showHelp) || $showHelp) { + print STDERR basename($0) . " [-h|--help] [-m|--merge] patch1 [patch2 ...]\n"; + exit 1; +} + +my %removeDirectoryIgnoreList = ( + '.' => 1, + '..' => 1, + '.svn' => 1, + '_svn' => 1, +); + +my %checkedDirectories; +my %copiedFiles; +my @patches; +my %versions; + +my $copiedFromPath; +my $filter; +my $indexPath; +my $patch; +while (<>) { + s/\r//g; + chomp; + if (!defined($indexPath) && m#^diff --git a/#) { + $filter = \&gitdiff2svndiff; + } + $_ = &$filter($_) if $filter; + if (/^Index: (.+)/) { + $indexPath = $1; + if ($patch) { + if (!$copiedFromPath) { + push @patches, $patch; + } + $copiedFromPath = ""; + $patch = ""; + } + } + if ($indexPath) { + # Fix paths on diff, ---, and +++ lines to match preceding Index: line. + s/\S+$/$indexPath/ if /^diff/; + s/^--- \S+/--- $indexPath/; + if (/^--- .+\(from (\S+):(\d+)\)$/) { + $copiedFromPath = $1; + $copiedFiles{$indexPath} = $copiedFromPath; + $versions{$copiedFromPath} = $2 if ($2 != 0); + } + elsif (/^--- .+\(revision (\d+)\)$/) { + $versions{$indexPath} = $1 if ($1 != 0); + } + if (s/^\+\+\+ \S+/+++ $indexPath/) { + $indexPath = ""; + } + } + $patch .= $_; + $patch .= "\n"; +} + +if ($patch && !$copiedFromPath) { + push @patches, $patch; +} + +if ($merge) { + for my $file (sort keys %versions) { + print "Getting version $versions{$file} of $file\n"; + system "svn", "update", "-r", $versions{$file}, $file; + } +} + +# Handle copied and moved files first since moved files may have their source deleted before the move. +for my $file (keys %copiedFiles) { + addDirectoriesIfNeeded(dirname($file)); + system "svn", "copy", $copiedFiles{$file}, $file; +} + +for $patch (@patches) { + patch($patch); +} + +removeDirectoriesIfNeeded(); + +exit 0; + +sub addDirectoriesIfNeeded($) +{ + my ($path) = @_; + my @dirs = File::Spec->splitdir($path); + my $dir = "."; + while (scalar @dirs) { + $dir = File::Spec->catdir($dir, shift @dirs); + next if exists $checkedDirectories{$dir}; + if (! -e $dir) { + mkdir $dir or die "Failed to create required directory '$dir' for path '$path'\n"; + system "svn", "add", $dir; + $checkedDirectories{$dir} = 1; + } + elsif (-d $dir) { + my $svnOutput = svnStatus($dir); + if ($svnOutput && $svnOutput =~ m#\?\s+$dir\n#) { + system "svn", "add", $dir; + } + $checkedDirectories{$dir} = 1; + } + else { + die "'$dir' is not a directory"; + } + } +} + +sub applyPatch($$;$) +{ + my ($patch, $fullPath, $options) = @_; + $options = [] if (! $options); + my $command = "patch " . join(" ", "-p0", @{$options}); + open PATCH, "| $command" or die "Failed to patch $fullPath\n"; + print PATCH $patch; + close PATCH; +} + +sub checksum($) +{ + my $file = shift; + open(FILE, $file) or die "Can't open '$file': $!"; + binmode(FILE); + my $checksum = Digest::MD5->new->addfile(*FILE)->hexdigest(); + close(FILE); + return $checksum; +} + +sub fixChangeLogPatch($) +{ + my $patch = shift; + my $contextLineCount = 3; + + return $patch if $patch !~ /\n@@ -1,(\d+) \+1,(\d+) @@\n( .*\n)+(\+.*\n)+( .*\n){$contextLineCount}$/m; + my ($oldLineCount, $newLineCount) = ($1, $2); + return $patch if $oldLineCount <= $contextLineCount; + + # The diff(1) command is greedy when matching lines, so a new ChangeLog entry will + # have lines of context at the top of a patch when the existing entry has the same + # date and author as the new entry. This nifty loop alters a ChangeLog patch so + # that the added lines ("+") in the patch always start at the beginning of the + # patch and there are no initial lines of context. + my $newPatch; + my $lineCountInState = 0; + my $oldContentLineCountReduction = $oldLineCount - $contextLineCount; + my $newContentLineCountWithoutContext = $newLineCount - $oldLineCount - $oldContentLineCountReduction; + my ($stateHeader, $statePreContext, $stateNewChanges, $statePostContext) = (1..4); + my $state = $stateHeader; + foreach my $line (split(/\n/, $patch)) { + $lineCountInState++; + if ($state == $stateHeader && $line =~ /^@@ -1,$oldLineCount \+1,$newLineCount @\@$/) { + $line = "@@ -1,$contextLineCount +1," . ($newLineCount - $oldContentLineCountReduction) . " @@"; + $lineCountInState = 0; + $state = $statePreContext; + } elsif ($state == $statePreContext && substr($line, 0, 1) eq " ") { + $line = "+" . substr($line, 1); + if ($lineCountInState == $oldContentLineCountReduction) { + $lineCountInState = 0; + $state = $stateNewChanges; + } + } elsif ($state == $stateNewChanges && substr($line, 0, 1) eq "+") { + # No changes to these lines + if ($lineCountInState == $newContentLineCountWithoutContext) { + $lineCountInState = 0; + $state = $statePostContext; + } + } elsif ($state == $statePostContext) { + if (substr($line, 0, 1) eq "+" && $lineCountInState <= $oldContentLineCountReduction) { + $line = " " . substr($line, 1); + } elsif ($lineCountInState > $contextLineCount && substr($line, 0, 1) eq " ") { + next; # Discard + } + } + $newPatch .= $line . "\n"; + } + + return $newPatch; +} + +sub gitdiff2svndiff($) +{ + $_ = shift @_; + if (m#^diff --git a/(.+) b/(.+)#) { + return "Index: $1"; + } elsif (m/^new file.*/) { + return ""; + } elsif (m#^index [0-9a-f]{7}\.\.[0-9a-f]{7} [0-9]{6}#) { + return "==================================================================="; + } elsif (m#^--- a/(.+)#) { + return "--- $1"; + } elsif (m#^\+\+\+ b/(.+)#) { + return "+++ $1"; + } + return $_; +} + +sub handleBinaryChange($$) +{ + my ($fullPath, $contents) = @_; + if ($contents =~ m#((\n[A-Za-z0-9+/]{76})+\n[A-Za-z0-9+/=]{4,76}\n)#) { + # Addition or Modification + open FILE, ">", $fullPath or die; + print FILE decode_base64($1); + close FILE; + my $svnOutput = svnStatus($fullPath); + if ($svnOutput && substr($svnOutput, 0, 1) eq "?") { + # Addition + system "svn", "add", $fullPath; + } else { + # Modification + print $svnOutput if $svnOutput; + } + } else { + # Deletion + system "svn", "rm", $fullPath; + } +} + +sub isDirectoryEmptyForRemoval($) +{ + my ($dir) = @_; + my $directoryIsEmpty = 1; + opendir DIR, $dir or die "Could not open '$dir' to list files: $?"; + for (my $item = readdir DIR; $item && $directoryIsEmpty; $item = readdir DIR) { + next if exists $removeDirectoryIgnoreList{$item}; + if (! -d File::Spec->catdir($dir, $item)) { + $directoryIsEmpty = 0; + } else { + my $svnOutput = svnStatus(File::Spec->catdir($dir, $item)); + next if $svnOutput && substr($svnOutput, 0, 1) eq "D"; + $directoryIsEmpty = 0; + } + } + closedir DIR; + return $directoryIsEmpty; +} + +sub patch($) +{ + my ($patch) = @_; + return if !$patch; + + unless ($patch =~ m|^Index: ([^\n]+)|) { + my $separator = '-' x 67; + warn "Failed to find 'Index:' in:\n$separator\n$patch\n$separator\n"; + return; + } + my $fullPath = $1; + + my $deletion = 0; + my $addition = 0; + my $isBinary = 0; + + $addition = 1 if $patch =~ /\n--- .+\(revision 0\)\n/; + $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/; + $isBinary = 1 if $patch =~ /\nCannot display: file marked as a binary type\./; + + if (!$addition && !$deletion && !$isBinary) { + # Standard patch, patch tool can handle this. + if (basename($fullPath) eq "ChangeLog") { + my $changeLogDotOrigExisted = -f "${fullPath}.orig"; + applyPatch(setChangeLogDate(fixChangeLogPatch($patch)), $fullPath, ["--fuzz=3"]); + unlink("${fullPath}.orig") if (! $changeLogDotOrigExisted); + } else { + applyPatch($patch, $fullPath); + } + } else { + # Either a deletion, an addition or a binary change. + + addDirectoriesIfNeeded(dirname($fullPath)); + + if ($isBinary) { + # Binary change + handleBinaryChange($fullPath, $patch); + } elsif ($deletion) { + # Deletion + applyPatch($patch, $fullPath, ["--force"]); + system "svn", "rm", "--force", $fullPath; + } else { + # Addition + rename($fullPath, "$fullPath.orig") if -e $fullPath; + applyPatch($patch, $fullPath); + unlink("$fullPath.orig") if -e "$fullPath.orig" && checksum($fullPath) eq checksum("$fullPath.orig"); + system "svn", "add", $fullPath; + system "svn", "stat", "$fullPath.orig" if -e "$fullPath.orig"; + } + } +} + +sub removeDirectoriesIfNeeded() +{ + foreach my $dir (reverse sort keys %checkedDirectories) { + if (isDirectoryEmptyForRemoval($dir)) { + my $svnOutput; + open SVN, "svn rm '$dir' |" or die; + # Only save the last line since Subversion lists all changed statuses below $dir + while (<SVN>) { + $svnOutput = $_; + } + close SVN; + print $svnOutput if $svnOutput; + } + } +} + +sub setChangeLogDate($) +{ + my $patch = shift; + my $savedTimeZone = $ENV{'TZ'}; + # Set TZ temporarily so that localtime() is in that time zone + $ENV{'TZ'} = $changeLogTimeZone; + my $newDate = strftime("%Y-%m-%d", localtime()); + if (defined $savedTimeZone) { + $ENV{'TZ'} = $savedTimeZone; + } else { + delete $ENV{'TZ'}; + } + $patch =~ s/(\n\+)\d{4}-[^-]{2}-[^-]{2}( )/$1$newDate$2/; + return $patch; +} + +sub svnStatus($) +{ + my ($fullPath) = @_; + my $svnStatus; + open SVN, "svn status --non-interactive --non-recursive '$fullPath' |" or die; + if (-d $fullPath) { + # When running "svn stat" on a directory, we can't assume that only one + # status will be returned (since any files with a status below the + # directory will be returned), and we can't assume that the directory will + # be first (since any files with unknown status will be listed first). + my $normalizedFullPath = File::Spec->catdir(File::Spec->splitdir($fullPath)); + while (<SVN>) { + chomp; + my $normalizedStatPath = File::Spec->catdir(File::Spec->splitdir(substr($_, 7))); + if ($normalizedFullPath eq $normalizedStatPath) { + $svnStatus = $_; + last; + } + } + # Read the rest of the svn command output to avoid a broken pipe warning. + local $/ = undef; + <SVN>; + } + else { + # Files will have only one status returned. + $svnStatus = <SVN>; + } + close SVN; + return $svnStatus; +} diff --git a/WebKitTools/Scripts/svn-create-patch b/WebKitTools/Scripts/svn-create-patch new file mode 100755 index 0000000..365737a --- /dev/null +++ b/WebKitTools/Scripts/svn-create-patch @@ -0,0 +1,442 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006 Apple Computer, Inc. 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. + +# Extended "svn diff" script for WebKit Open Source Project, used to make patches. + +# Differences from standard "svn diff": +# +# Uses the real diff, not svn's built-in diff. +# Always passes "-p" to diff so it will try to include function names. +# Handles binary files (encoded as a base64 chunk of text). +# Sorts the diffs alphabetically by text files, then binary files. +# Handles copied and moved files. +# +# Missing features: +# +# Handle copied and moved directories. + +use strict; +use warnings; + +use Config; +use Cwd; +use File::Basename; +use File::Spec; +use File::stat; +use Getopt::Long; +use MIME::Base64; +use POSIX qw(:errno_h); +use Time::gmtime; + +sub binarycmp($$); +sub canonicalizePath($); +sub findBaseUrl($); +sub findMimeType($;$); +sub findModificationType($); +sub findSourceFileAndRevision($); +sub fixChangeLogPatch($); +sub generateDiff($); +sub generateFileList($\%); +sub isBinaryMimeType($); +sub manufacturePatchForAdditionWithHistory($); +sub numericcmp($$); +sub outputBinaryContent($); +sub patchpathcmp($$); +sub pathcmp($$); +sub processPaths(\@); +sub splitpath($); +sub testfilecmp($$); + +$ENV{'LC_ALL'} = 'C'; + +my $showHelp; + +my $result = GetOptions( + "help" => \$showHelp, +); +if (!$result || $showHelp) { + print STDERR basename($0) . " [-h|--help] [svndir1 [svndir2 ...]]\n"; + exit 1; +} + +# Sort the diffs for easier reviewing. +my %paths = processPaths(@ARGV); + +# Generate a list of files requiring diffs. +my %diffFiles; +for my $path (keys %paths) { + generateFileList($path, %diffFiles); +} + +# Generate the diffs, in a order chosen for easy reviewing. +for my $path (sort patchpathcmp values %diffFiles) { + generateDiff($path); +} + +exit 0; + +# Overall sort, considering multiple criteria. +sub patchpathcmp($$) +{ + my ($a, $b) = @_; + + # All binary files come after all non-binary files. + my $result = binarycmp($a, $b); + return $result if $result; + + # All test files come after all non-test files. + $result = testfilecmp($a, $b); + return $result if $result; + + # Final sort is a "smart" sort by directory and file name. + return pathcmp($a, $b); +} + +# Sort so text files appear before binary files. +sub binarycmp($$) +{ + my ($fileDataA, $fileDataB) = @_; + return $fileDataA->{isBinary} <=> $fileDataB->{isBinary}; +} + +sub canonicalizePath($) +{ + my ($file) = @_; + + # Remove extra slashes and '.' directories in path + $file = File::Spec->canonpath($file); + + # Remove '..' directories in path + my @dirs = (); + foreach my $dir (File::Spec->splitdir($file)) { + if ($dir eq '..' && $#dirs >= 0 && $dirs[$#dirs] ne '..') { + pop(@dirs); + } else { + push(@dirs, $dir); + } + } + return ($#dirs >= 0) ? File::Spec->catdir(@dirs) : "."; +} + +sub findBaseUrl($) +{ + my ($infoPath) = @_; + my $baseUrl; + open INFO, "svn info '$infoPath' |" or die; + while (<INFO>) { + if (/^URL: (.+)/) { + $baseUrl = $1; + last; + } + } + close INFO; + return $baseUrl; +} + +sub findMimeType($;$) +{ + my ($file, $revision) = @_; + my $args = $revision ? "--revision $revision" : ""; + open PROPGET, "svn propget svn:mime-type $args '$file' |" or die; + my $mimeType = <PROPGET>; + close PROPGET; + chomp $mimeType if $mimeType; + return $mimeType; +} + +sub findModificationType($) +{ + my ($stat) = @_; + my $fileStat = substr($stat, 0, 1); + my $propertyStat = substr($stat, 1, 1); + if ($fileStat eq "A") { + my $additionWithHistory = substr($stat, 3, 1); + return $additionWithHistory eq "+" ? "additionWithHistory" : "addition"; + } + return "modification" if ($fileStat eq "M" || $propertyStat eq "M"); + return "deletion" if ($fileStat eq "D"); + return undef; +} + +sub findSourceFileAndRevision($) +{ + my ($file) = @_; + my $baseUrl = findBaseUrl("."); + my $sourceFile; + my $sourceRevision; + open INFO, "svn info '$file' |" or die; + while (<INFO>) { + if (/^Copied From URL: (.+)/) { + $sourceFile = File::Spec->abs2rel($1, $baseUrl); + } elsif (/^Copied From Rev: ([0-9]+)/) { + $sourceRevision = $1; + } + } + close INFO; + return ($sourceFile, $sourceRevision); +} + +sub fixChangeLogPatch($) +{ + my $patch = shift; + my $contextLineCount = 3; + + return $patch if $patch !~ /\n@@ -1,(\d+) \+1,(\d+) @@\n( .*\n)+(\+.*\n)+( .*\n){$contextLineCount}$/m; + my ($oldLineCount, $newLineCount) = ($1, $2); + return $patch if $oldLineCount <= $contextLineCount; + + # The diff(1) command is greedy when matching lines, so a new ChangeLog entry will + # have lines of context at the top of a patch when the existing entry has the same + # date and author as the new entry. This nifty loop alters a ChangeLog patch so + # that the added lines ("+") in the patch always start at the beginning of the + # patch and there are no initial lines of context. + my $newPatch; + my $lineCountInState = 0; + my $oldContentLineCountReduction = $oldLineCount - $contextLineCount; + my $newContentLineCountWithoutContext = $newLineCount - $oldLineCount - $oldContentLineCountReduction; + my ($stateHeader, $statePreContext, $stateNewChanges, $statePostContext) = (1..4); + my $state = $stateHeader; + foreach my $line (split(/\n/, $patch)) { + $lineCountInState++; + if ($state == $stateHeader && $line =~ /^@@ -1,$oldLineCount \+1,$newLineCount @\@$/) { + $line = "@@ -1,$contextLineCount +1," . ($newLineCount - $oldContentLineCountReduction) . " @@"; + $lineCountInState = 0; + $state = $statePreContext; + } elsif ($state == $statePreContext && substr($line, 0, 1) eq " ") { + $line = "+" . substr($line, 1); + if ($lineCountInState == $oldContentLineCountReduction) { + $lineCountInState = 0; + $state = $stateNewChanges; + } + } elsif ($state == $stateNewChanges && substr($line, 0, 1) eq "+") { + # No changes to these lines + if ($lineCountInState == $newContentLineCountWithoutContext) { + $lineCountInState = 0; + $state = $statePostContext; + } + } elsif ($state == $statePostContext) { + if (substr($line, 0, 1) eq "+" && $lineCountInState <= $oldContentLineCountReduction) { + $line = " " . substr($line, 1); + } elsif ($lineCountInState > $contextLineCount && substr($line, 0, 1) eq " ") { + next; # Discard + } + } + $newPatch .= $line . "\n"; + } + + return $newPatch; +} + +sub generateDiff($) +{ + my ($fileData) = @_; + my $file = $fileData->{path}; + my $patch; + if ($fileData->{modificationType} eq "additionWithHistory") { + manufacturePatchForAdditionWithHistory($fileData); + } + open DIFF, "svn diff --diff-cmd diff -x -uaNp '$file' |" or die; + while (<DIFF>) { + $patch .= $_; + } + close DIFF; + $patch = fixChangeLogPatch($patch) if basename($file) eq "ChangeLog"; + print $patch if $patch; + if ($fileData->{isBinary}) { + print "\n" if ($patch && $patch =~ m/\n\S+$/m); + outputBinaryContent($file); + } +} + +sub generateFileList($\%) +{ + my ($statPath, $diffFiles) = @_; + my %testDirectories = map { $_ => 1 } qw(LayoutTests); + open STAT, "svn stat '$statPath' |" or die; + while (my $line = <STAT>) { + chomp $line; + my $stat = substr($line, 0, 7); + my $path = substr($line, 7); + next if -d $path; + my $modificationType = findModificationType($stat); + if ($modificationType) { + $diffFiles->{$path}->{path} = $path; + $diffFiles->{$path}->{modificationType} = $modificationType; + $diffFiles->{$path}->{isBinary} = isBinaryMimeType($path); + $diffFiles->{$path}->{isTestFile} = exists $testDirectories{(File::Spec->splitdir($path))[0]} ? 1 : 0; + if ($modificationType eq "additionWithHistory") { + my ($sourceFile, $sourceRevision) = findSourceFileAndRevision($path); + $diffFiles->{$path}->{sourceFile} = $sourceFile; + $diffFiles->{$path}->{sourceRevision} = $sourceRevision; + } + } else { + print STDERR $line, "\n"; + } + } + close STAT; +} + +sub isBinaryMimeType($) +{ + my ($file) = @_; + my $mimeType = findMimeType($file); + return 0 if (!$mimeType || substr($mimeType, 0, 5) eq "text/"); + return 1; +} + +sub manufacturePatchForAdditionWithHistory($) +{ + my ($fileData) = @_; + my $file = $fileData->{path}; + print "Index: ${file}\n"; + print "=" x 67, "\n"; + my $sourceFile = $fileData->{sourceFile}; + my $sourceRevision = $fileData->{sourceRevision}; + print "--- ${file}\t(revision ${sourceRevision})\t(from ${sourceFile}:${sourceRevision})\n"; + print "+++ ${file}\t(working copy)\n"; + if ($fileData->{isBinary}) { + print "\nCannot display: file marked as a binary type.\n"; + my $mimeType = findMimeType($file, $sourceRevision); + print "svn:mime-type = ${mimeType}\n\n"; + } else { + print `svn cat ${sourceFile} | diff -u /dev/null - | tail -n +3`; + } +} + +# Sort numeric parts of strings as numbers, other parts as strings. +# Makes 1.33 come after 1.3, which is cool. +sub numericcmp($$) +{ + my ($aa, $bb) = @_; + + my @a = split /(\d+)/, $aa; + my @b = split /(\d+)/, $bb; + + # Compare one chunk at a time. + # Each chunk is either all numeric digits, or all not numeric digits. + while (@a && @b) { + my $a = shift @a; + my $b = shift @b; + + # Use numeric comparison if chunks are non-equal numbers. + return $a <=> $b if $a =~ /^\d/ && $b =~ /^\d/ && $a != $b; + + # Use string comparison if chunks are any other kind of non-equal string. + return $a cmp $b if $a ne $b; + } + + # One of the two is now empty; compare lengths for result in this case. + return @a <=> @b; +} + +sub outputBinaryContent($) +{ + my ($path) = @_; + # Deletion + return if (! -e $path); + # Addition or Modification + my $buffer; + open BINARY, $path or die; + while (read(BINARY, $buffer, 60*57)) { + print encode_base64($buffer); + } + close BINARY; + print "\n"; +} + +# Sort first by directory, then by file, so all paths in one directory are grouped +# rather than being interspersed with items from subdirectories. +# Use numericcmp to sort directory and filenames to make order logical. +# Also include a special case for ChangeLog, which comes first in any directory. +sub pathcmp($$) +{ + my ($fileDataA, $fileDataB) = @_; + + my ($dira, $namea) = splitpath($fileDataA->{path}); + my ($dirb, $nameb) = splitpath($fileDataB->{path}); + + return numericcmp($dira, $dirb) if $dira ne $dirb; + return -1 if $namea eq "ChangeLog" && $nameb ne "ChangeLog"; + return +1 if $namea ne "ChangeLog" && $nameb eq "ChangeLog"; + return numericcmp($namea, $nameb); +} + +sub processPaths(\@) +{ + my ($paths) = @_; + return ("." => 1) if (!@{$paths}); + + my %result = (); + + for my $file (@{$paths}) { + die "can't handle absolute paths like \"$file\"\n" if File::Spec->file_name_is_absolute($file); + die "can't handle empty string path\n" if $file eq ""; + die "can't handle path with single quote in the name like \"$file\"\n" if $file =~ /'/; # ' (keep Xcode syntax highlighting happy) + + my $untouchedFile = $file; + + $file = canonicalizePath($file); + + die "can't handle paths with .. like \"$untouchedFile\"\n" if $file =~ m|/\.\./|; + + $result{$file} = 1; + } + + return ("." => 1) if ($result{"."}); + + # Remove any paths that also have a parent listed. + for my $path (keys %result) { + for (my $parent = dirname($path); $parent ne '.'; $parent = dirname($parent)) { + if ($result{$parent}) { + delete $result{$path}; + last; + } + } + } + + return %result; +} + +# Break up a path into the directory (with slash) and base name. +sub splitpath($) +{ + my ($path) = @_; + + my $pathSeparator = "/"; + my $dirname = dirname($path) . $pathSeparator; + $dirname = "" if $dirname eq "." . $pathSeparator; + + return ($dirname, basename($path)); +} + +# Sort so source code files appear before test files. +sub testfilecmp($$) +{ + my ($fileDataA, $fileDataB) = @_; + return $fileDataA->{isTestFile} <=> $fileDataB->{isTestFile}; +} diff --git a/WebKitTools/Scripts/svn-unapply b/WebKitTools/Scripts/svn-unapply new file mode 100755 index 0000000..05910ad --- /dev/null +++ b/WebKitTools/Scripts/svn-unapply @@ -0,0 +1,374 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006, 2007 Apple Inc. 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. + +# "unpatch" script for Web Kit Open Source Project, used to remove patches. + +# Differences from invoking "patch -p0 -R": +# +# Handles added files (does a svn revert with additional logic to handle local changes). +# Handles added directories (does a svn revert and a rmdir). +# Handles removed files (does a svn revert with additional logic to handle local changes). +# Handles removed directories (does a svn revert). +# Paths from Index: lines are used rather than the paths on the patch lines, which +# makes patches generated by "cvs diff" work (increasingly unimportant since we +# use Subversion now). +# ChangeLog patches use --fuzz=3 to prevent rejects, and the entry date is reset in +# the patch before it is applied (svn-apply sets it when applying a patch). +# Handles binary files (requires patches made by svn-create-patch). +# Handles copied and moved files (requires patches made by svn-create-patch). +# Handles git-diff patches (without binary changes) created at the top-level directory +# +# Missing features: +# +# Handle property changes. +# Handle copied and moved directories (would require patches made by svn-create-patch). +# Use version numbers in the patch file and do a 3-way merge. +# When reversing an addition, check that the file matches what's being removed. +# Notice a patch that's being unapplied at the "wrong level" and make it work anyway. +# Do a dry run on the whole patch and don't do anything if part of the patch is +# going to fail (probably too strict unless we exclude ChangeLog). +# Handle git-diff patches with binary changes + +use strict; +use warnings; + +use Cwd; +use Digest::MD5; +use Fcntl qw(:DEFAULT :seek); +use File::Basename; +use File::Spec; +use File::Temp qw(tempfile); +use Getopt::Long; + +sub checksum($); +sub fixChangeLogPatch($); +sub gitdiff2svndiff($); +sub patch($); +sub revertDirectories(); +sub svnStatus($); +sub unapplyPatch($$;$); +sub unsetChangeLogDate($$); + +my $showHelp = 0; +if (!GetOptions("help!" => \$showHelp) || $showHelp) { + print STDERR basename($0) . " [-h|--help] patch1 [patch2 ...]\n"; + exit 1; +} + +my @copiedFiles; +my %directoriesToCheck; + +my $copiedFromPath; +my $filter; +my $indexPath; +my $patch; +while (<>) { + s/\r//g; + chomp; + if (!defined($indexPath) && m#^diff --git a/#) { + $filter = \&gitdiff2svndiff; + } + $_ = &$filter($_) if $filter; + if (/^Index: (.*)/) { + $indexPath = $1; + if ($patch) { + if ($copiedFromPath) { + push @copiedFiles, $patch; + } else { + patch($patch); + } + $copiedFromPath = ""; + $patch = ""; + } + } + if ($indexPath) { + # Fix paths on diff, ---, and +++ lines to match preceding Index: line. + s/^--- \S+/--- $indexPath/; + if (/^--- .+\(from (\S+):\d+\)$/) { + $copiedFromPath = $1; + } + if (s/^\+\+\+ \S+/+++ $indexPath/) { + $indexPath = ""; + } + } + $patch .= $_; + $patch .= "\n"; +} + +if ($patch) { + if ($copiedFromPath) { + push @copiedFiles, $patch; + } else { + patch($patch); + } +} + +# Handle copied and moved files last since they may have had post-copy changes that have now been unapplied +for $patch (@copiedFiles) { + patch($patch); +} + +revertDirectories(); + +exit 0; + +sub checksum($) +{ + my $file = shift; + open(FILE, $file) or die "Can't open '$file': $!"; + binmode(FILE); + my $checksum = Digest::MD5->new->addfile(*FILE)->hexdigest(); + close(FILE); + return $checksum; +} + +sub fixChangeLogPatch($) +{ + my $patch = shift; + my $contextLineCount = 3; + + return $patch if $patch !~ /\n@@ -1,(\d+) \+1,(\d+) @@\n( .*\n)+(\+.*\n)+( .*\n){$contextLineCount}$/m; + my ($oldLineCount, $newLineCount) = ($1, $2); + return $patch if $oldLineCount <= $contextLineCount; + + # The diff(1) command is greedy when matching lines, so a new ChangeLog entry will + # have lines of context at the top of a patch when the existing entry has the same + # date and author as the new entry. This nifty loop alters a ChangeLog patch so + # that the added lines ("+") in the patch always start at the beginning of the + # patch and there are no initial lines of context. + my $newPatch; + my $lineCountInState = 0; + my $oldContentLineCountReduction = $oldLineCount - $contextLineCount; + my $newContentLineCountWithoutContext = $newLineCount - $oldLineCount - $oldContentLineCountReduction; + my ($stateHeader, $statePreContext, $stateNewChanges, $statePostContext) = (1..4); + my $state = $stateHeader; + foreach my $line (split(/\n/, $patch)) { + $lineCountInState++; + if ($state == $stateHeader && $line =~ /^@@ -1,$oldLineCount \+1,$newLineCount @\@$/) { + $line = "@@ -1,$contextLineCount +1," . ($newLineCount - $oldContentLineCountReduction) . " @@"; + $lineCountInState = 0; + $state = $statePreContext; + } elsif ($state == $statePreContext && substr($line, 0, 1) eq " ") { + $line = "+" . substr($line, 1); + if ($lineCountInState == $oldContentLineCountReduction) { + $lineCountInState = 0; + $state = $stateNewChanges; + } + } elsif ($state == $stateNewChanges && substr($line, 0, 1) eq "+") { + # No changes to these lines + if ($lineCountInState == $newContentLineCountWithoutContext) { + $lineCountInState = 0; + $state = $statePostContext; + } + } elsif ($state == $statePostContext) { + if (substr($line, 0, 1) eq "+" && $lineCountInState <= $oldContentLineCountReduction) { + $line = " " . substr($line, 1); + } elsif ($lineCountInState > $contextLineCount && substr($line, 0, 1) eq " ") { + next; # Discard + } + } + $newPatch .= $line . "\n"; + } + + return $newPatch; +} + +sub gitdiff2svndiff($) +{ + $_ = shift @_; + if (m#^diff --git a/(.+) b/(.+)#) { + return "Index: $1"; + } elsif (m/^new file.*/) { + return ""; + } elsif (m#^index [0-9a-f]{7}\.\.[0-9a-f]{7} [0-9]{6}#) { + return "==================================================================="; + } elsif (m#^--- a/(.+)#) { + return "--- $1"; + } elsif (m#^\+\+\+ b/(.+)#) { + return "+++ $1"; + } + return $_; +} + +sub patch($) +{ + my ($patch) = @_; + return if !$patch; + + unless ($patch =~ m|^Index: ([^\n]+)|) { + my $separator = '-' x 67; + warn "Failed to find 'Index:' in:\n$separator\n$patch\n$separator\n"; + return; + } + my $fullPath = $1; + $directoriesToCheck{dirname($fullPath)} = 1; + + my $deletion = 0; + my $addition = 0; + my $isBinary = 0; + + $addition = 1 if ($patch =~ /\n--- .+\(revision 0\)\n/ || $patch =~ /\n@@ -0,0 .* @@/); + $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/; + $isBinary = 1 if $patch =~ /\nCannot display: file marked as a binary type\./; + + if (!$addition && !$deletion && !$isBinary) { + # Standard patch, patch tool can handle this. + if (basename($fullPath) eq "ChangeLog") { + my $changeLogDotOrigExisted = -f "${fullPath}.orig"; + unapplyPatch(unsetChangeLogDate($fullPath, fixChangeLogPatch($patch)), $fullPath, ["--fuzz=3"]); + unlink("${fullPath}.orig") if (! $changeLogDotOrigExisted); + } else { + unapplyPatch($patch, $fullPath); + } + } else { + # Either a deletion, an addition or a binary change. + + if ($isBinary) { + # Reverse binary change + unlink($fullPath) if (-e $fullPath); + system "svn", "revert", $fullPath; + } elsif ($deletion) { + # Reverse deletion + rename($fullPath, "$fullPath.orig") if -e $fullPath; + + unapplyPatch($patch, $fullPath); + + # If we don't ask for the filehandle here, we always get a warning. + my ($fh, $tempPath) = tempfile(basename($fullPath) . "-XXXXXXXX", + DIR => dirname($fullPath), UNLINK => 1); + close($fh); + + # Keep the version from the patch in case it's different from svn. + rename($fullPath, $tempPath); + system "svn", "revert", $fullPath; + rename($tempPath, $fullPath); + + # This works around a bug in the svn client. + # [Issue 1960] file modifications get lost due to FAT 2s time resolution + # http://subversion.tigris.org/issues/show_bug.cgi?id=1960 + system "touch", $fullPath; + + # Remove $fullPath.orig if it is the same as $fullPath + unlink("$fullPath.orig") if -e "$fullPath.orig" && checksum($fullPath) eq checksum("$fullPath.orig"); + + # Show status if the file is modifed + system "svn", "stat", $fullPath; + } else { + # Reverse addition + unapplyPatch($patch, $fullPath, ["--force"]); + unlink($fullPath) if -z $fullPath; + system "svn", "revert", $fullPath; + } + } +} + +sub revertDirectories() +{ + my %checkedDirectories; + foreach my $path (reverse sort keys %directoriesToCheck) { + my @dirs = File::Spec->splitdir($path); + while (scalar @dirs) { + my $dir = File::Spec->catdir(@dirs); + pop(@dirs); + next if (exists $checkedDirectories{$dir}); + if (-d $dir) { + my $svnOutput = svnStatus($dir); + if ($svnOutput && $svnOutput =~ m#A\s+$dir\n#) { + system "svn", "revert", $dir; + rmdir $dir; + } + elsif ($svnOutput && $svnOutput =~ m#D\s+$dir\n#) { + system "svn", "revert", $dir; + } + else { + # Modification + print $svnOutput if $svnOutput; + } + $checkedDirectories{$dir} = 1; + } + else { + die "'$dir' is not a directory"; + } + } + } +} + +sub svnStatus($) +{ + my ($fullPath) = @_; + my $svnStatus; + open SVN, "svn status --non-interactive --non-recursive '$fullPath' |" or die; + if (-d $fullPath) { + # When running "svn stat" on a directory, we can't assume that only one + # status will be returned (since any files with a status below the + # directory will be returned), and we can't assume that the directory will + # be first (since any files with unknown status will be listed first). + my $normalizedFullPath = File::Spec->catdir(File::Spec->splitdir($fullPath)); + while (<SVN>) { + chomp; + my $normalizedStatPath = File::Spec->catdir(File::Spec->splitdir(substr($_, 7))); + if ($normalizedFullPath eq $normalizedStatPath) { + $svnStatus = $_; + last; + } + } + # Read the rest of the svn command output to avoid a broken pipe warning. + local $/ = undef; + <SVN>; + } + else { + # Files will have only one status returned. + $svnStatus = <SVN>; + } + close SVN; + return $svnStatus; +} + +sub unapplyPatch($$;$) +{ + my ($patch, $fullPath, $options) = @_; + $options = [] if (! $options); + my $command = "patch " . join(" ", "-p0", "-R", @{$options}); + open PATCH, "| $command" or die "Failed to patch $fullPath: $!"; + print PATCH $patch; + close PATCH; +} + +sub unsetChangeLogDate($$) +{ + my $fullPath = shift; + my $patch = shift; + my $newDate; + sysopen(CHANGELOG, $fullPath, O_RDONLY) or die "Failed to open $fullPath: $!"; + sysseek(CHANGELOG, 0, SEEK_SET); + my $byteCount = sysread(CHANGELOG, $newDate, 10); + die "Failed reading $fullPath: $!" if !$byteCount || $byteCount != 10; + close(CHANGELOG); + $patch =~ s/(\n\+)\d{4}-[^-]{2}-[^-]{2}( )/$1$newDate$2/; + return $patch; +} diff --git a/WebKitTools/Scripts/update-iexploder-cssproperties b/WebKitTools/Scripts/update-iexploder-cssproperties new file mode 100755 index 0000000..b7ae6cb --- /dev/null +++ b/WebKitTools/Scripts/update-iexploder-cssproperties @@ -0,0 +1,112 @@ +#!/usr/bin/perl + +# Copyright (C) 2007 Apple Inc. 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 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. + +# This script updates WebKitTools/iExploder/htdocs/cssproperties.in based on +# WebCore/css/CSSPropertyNames.in. + +use warnings; +use strict; + +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +use File::Spec; + +sub generateSectionFromCSSPropertyNamesFile(); +sub readiExploderFile(); +sub svnRevision($); +sub writeiExploderFile(); + +my $iExploderFile = File::Spec->catfile(sourceDir(), split("/", "WebKitTools/iExploder/htdocs/cssproperties.in")); +my $cssPropertyNamesFile = File::Spec->catfile(sourceDir(), split("/", "WebCore/css/CSSPropertyNames.in")); + +my @sections = readiExploderFile(); +$sections[0] = generateSectionFromCSSPropertyNamesFile(); +writeiExploderFile(); + +print `svn stat $iExploderFile`; +print "Successfully updated!\n"; + +exit 0; + +sub generateSectionFromCSSPropertyNamesFile() +{ + my $revision = svnRevision($cssPropertyNamesFile); + my $path = File::Spec->abs2rel($cssPropertyNamesFile, sourceDir()); + my $result = "# From WebKit svn r" . $revision . " (" . $path . ")\n"; + + my @properties = (); + + open(IN, $cssPropertyNamesFile) || die "$!"; + while (my $l = <IN>) { + chomp $l; + next if $l =~ m/^\s*#/ || $l =~ m/^\s*$/; + push(@properties, $l); + } + close(IN); + + $result .= join("\n", sort { $a cmp $b } @properties) . "\n\n"; + + return $result; +} + +sub readiExploderFile() +{ + my @sections = (); + local $/ = "\n\n"; + + open(IN, $iExploderFile) || die "$!"; + @sections = <IN>; + close(IN); + + return @sections; +} + +sub svnRevision($) +{ + my ($file) = @_; + my $revision = ""; + + open INFO, "svn info '$file' |" or die; + while (<INFO>) { + if (/^Revision: (.+)/) { + $revision = $1; + } + } + close INFO; + + return $revision ? $revision : "UNKNOWN"; +} + +sub writeiExploderFile() +{ + open(OUT, "> $iExploderFile") || die "$!"; + print OUT join("", @sections); + close(OUT); +} diff --git a/WebKitTools/Scripts/update-javascriptcore-test-results b/WebKitTools/Scripts/update-javascriptcore-test-results new file mode 100755 index 0000000..dd8b9b6 --- /dev/null +++ b/WebKitTools/Scripts/update-javascriptcore-test-results @@ -0,0 +1,73 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2007 Apple Inc. 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. + +use strict; +use FindBin; +use Getopt::Long; +use lib $FindBin::Bin; +use webkitdirs; + +chdirWebKit(); +chdir "JavaScriptCore/tests/mozilla" or die; + +my $force = 0; +GetOptions('force' => \$force); + +open EXPECTED, "expected.html" or die; +while (<EXPECTED>) { + last if /failures reported\.$/; +} +my %expected; +while (<EXPECTED>) { + chomp; + $expected{$_} = 1; +} +close EXPECTED; + +open ACTUAL, "actual.html" or die; +my $actual; +while (<ACTUAL>) { + $actual .= $_; + last if /failures reported\.$/; +} +my $failed = 0; +while (<ACTUAL>) { + $actual .= $_; + chomp; + if (!$expected{$_}) { + $failed = 1; + print "failure not expected: $_\n"; + } +} +close ACTUAL; + +die "won't update, failures introduced\n" if $failed && !$force; + +open EXPECTED, ">expected.html"; +print EXPECTED $actual; +close EXPECTED; diff --git a/WebKitTools/Scripts/update-webkit b/WebKitTools/Scripts/update-webkit new file mode 100755 index 0000000..6d974b1 --- /dev/null +++ b/WebKitTools/Scripts/update-webkit @@ -0,0 +1,92 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. 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. + +# Update script for Web Kit Open Source Project. + +use strict; +use FindBin; +use lib $FindBin::Bin; +use File::Basename; +use File::Spec; +use Getopt::Long; +use webkitdirs; + +sub runSvnUpdate(); + +# Handle options +my $quiet = ''; +my $showHelp; + +my $getOptionsResult = GetOptions( + 'h|help' => \$showHelp, + 'q|quiet' => \$quiet, +); + +if (!$getOptionsResult || $showHelp) { + print STDERR <<__END__; +Usage: @{[ basename($0) ]} [options] + -h|--help show the help message + -q|--quiet pass -q to svn update for quiet updates +__END__ + exit 1; +} + +my @svnOptions = (); +push @svnOptions, '-q' if $quiet; + +chdirWebKit(); +print "Updating OpenSource\n" unless $quiet; +runSvnUpdate(); + +if (-d "../Internal") { + chdir("../Internal"); + print "Updating Internal\n" unless $quiet; + runSvnUpdate(); +} elsif (isCygwin()) { + system("perl", "WebKitTools/Scripts/update-webkit-auxiliary-libs") == 0 or die; +} + +exit 0; + +sub runSvnUpdate() +{ + open UPDATE, "-|", "svn", "update", @svnOptions or die; + my @conflictedChangeLogs; + while (my $line = <UPDATE>) { + print $line; + push @conflictedChangeLogs, $1 if $line =~ m/^C\s+(.+)\s*$/ && basename($1) eq "ChangeLog"; + } + close UPDATE; + + if (@conflictedChangeLogs) { + print "Attempting to merge conflicted ChangeLogs.\n"; + my $resolveChangeLogsPath = File::Spec->catfile(dirname($0), "resolve-ChangeLogs"); + (system($resolveChangeLogsPath, "--no-warnings", @conflictedChangeLogs) == 0) + or die "Could not open resolve-ChangeLogs script: $!.\n"; + } +} diff --git a/WebKitTools/Scripts/update-webkit-auxiliary-libs b/WebKitTools/Scripts/update-webkit-auxiliary-libs new file mode 100755 index 0000000..1d6943c --- /dev/null +++ b/WebKitTools/Scripts/update-webkit-auxiliary-libs @@ -0,0 +1,121 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006, 2007 Apple Computer, Inc. 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. + +# Updates a development environment to the new WebKitAuxiliaryLibrary + +use strict; +use warnings; + +use HTTP::Date qw(str2time); +use File::Find; +use File::Temp; +use File::Spec; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +sub lastModifiedToUnixTime($); + +# Time in seconds that the new zip file must be newer than the old for us to +# consider them to be different. If the difference in modification time is less +# than this threshold, we assume that the files are the same. We need this +# because the zip file is served from a set of mirrors with slightly different +# Last-Modified times. +my $newnessThreshold = 30; + +my $sourceDir = sourceDir(); +my $file = "WebKitAuxiliaryLibrary"; +my $zipFile = "$file.zip"; +my $auxiliaryLibsURL = "http://developer.apple.com/opensource/internet/$zipFile"; +my $webkitLibrariesDir = toUnixPath($ENV{'WEBKITLIBRARIESDIR'}) || "$sourceDir/WebKitLibraries/win"; +my $tmpDir = File::Spec->rel2abs(File::Temp::tempdir("webkitlibsXXXXXXX", TMPDIR => 1, CLEANUP => 1)); + +print "Checking Last-Modified date of $zipFile...\n"; + +my $result = system "curl -s -I $auxiliaryLibsURL | grep Last-Modified > \"$tmpDir/$file.headers\""; +print STDERR "Couldn't check Last-Modified date of new $zipFile.\n" if $result; + +if (!$result && open NEW, "$tmpDir/$file.headers") { + my $new = lastModifiedToUnixTime(<NEW>); + close NEW; + + if (defined $new && open OLD, "$webkitLibrariesDir/$file.headers") { + my $old = lastModifiedToUnixTime(<OLD>); + close OLD; + if (defined $old && abs($new - $old) < $newnessThreshold) { + print "Current $file is up to date\n"; + exit 0; + } + } +} + +print "Downloading $zipFile...\n\n"; +$result = system "curl -o \"$tmpDir/$zipFile\" $auxiliaryLibsURL"; +die "Couldn't download $zipFile!" if $result; + +$result = system "unzip", "-q", "-d", $tmpDir, "$tmpDir/$zipFile"; +die "Couldn't unzip $zipFile." if $result; + +print "\nInstalling $file...\n"; + +sub wanted +{ + my $relativeName = File::Spec->abs2rel($File::Find::name, "$tmpDir/$file/win"); + my $destination = "$webkitLibrariesDir/$relativeName"; + + if (-d $_) { + mkdir $destination; + return; + } + + system "cp", $_, $destination; +} + +File::Find::find(\&wanted, "$tmpDir/$file"); + +$result = system "mv", "$tmpDir/$file.headers", $webkitLibrariesDir; +print STDERR "Couldn't move $file.headers to $webkitLibrariesDir" . ".\n" if $result; + +print "The $file has been sucessfully installed in\n $webkitLibrariesDir\n"; +exit; + +sub toUnixPath +{ + my $path = shift; + return unless $path; + chomp($path = `cygpath -u '$path'`); + return $path; +} + +sub lastModifiedToUnixTime($) +{ + my ($str) = @_; + + $str =~ /^Last-Modified: (.*)$/ or return; + return str2time($1); +} diff --git a/WebKitTools/Scripts/update-webkit-localizable-strings b/WebKitTools/Scripts/update-webkit-localizable-strings new file mode 100755 index 0000000..53037a6 --- /dev/null +++ b/WebKitTools/Scripts/update-webkit-localizable-strings @@ -0,0 +1,45 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2006, 2007 Apple Inc. 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. + +use strict; +use warnings; + +use File::Basename; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +my @directoriesToScan = ("WebKit/mac", "WebKit/win"); +my $exceptionsFile = "WebKit/StringsNotToBeLocalized.txt"; + +@ARGV == 0 or die "Usage: " . basename($0) . "\n"; + +chdirWebKit(); + +system "sort -u $exceptionsFile -o $exceptionsFile"; +exec "extract-localizable-strings", $exceptionsFile, @directoriesToScan; diff --git a/WebKitTools/Scripts/update-webkit-support-libs b/WebKitTools/Scripts/update-webkit-support-libs new file mode 100755 index 0000000..e9c302b --- /dev/null +++ b/WebKitTools/Scripts/update-webkit-support-libs @@ -0,0 +1,105 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2005, 2006, 2007 Apple Computer, Inc. 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. + +# Updates a development environment to the new WebKitSupportLibrary + +use strict; +use warnings; + +use File::Find; +use File::Temp; +use File::Spec; +use FindBin; +use lib $FindBin::Bin; +use webkitdirs; + +my $sourceDir = sourceDir(); +my $file = "WebKitSupportLibrary"; +my $zipFile = "$file.zip"; +my $zipDirectory = toUnixPath($ENV{'WEBKITSUPPORTLIBRARIESZIPDIR'}) || $sourceDir; +my $pathToZip = File::Spec->catfile($zipDirectory, $zipFile); +my $webkitLibrariesDir = toUnixPath($ENV{'WEBKITLIBRARIESDIR'}) || "$sourceDir/WebKitLibraries/win"; +my $tmpDir = File::Spec->rel2abs(File::Temp::tempdir("webkitlibsXXXXXXX", TMPDIR => 1, CLEANUP => 1)); + +# Make sure the file zipfile exists before doing anything. +die "$zipFile could not be found in your root source directory. Please\n" . + "download it from http://developer.apple.com/opensource/internet/webkit_sptlib_agree.html and place it in \n" . + "$sourceDir\n and then run update-webkit again.\n" unless (-f "$pathToZip"); + +print "Checking mod-date of $zipFile...\n"; +open MOD, ">$tmpDir/$file.modified" or die "Couldn't open $tmpDir/$file.modified for writing"; +print MOD (stat $pathToZip)[9] . "\n"; +close MOD; + +if (open NEW, "$tmpDir/$file.modified") { + my $new = <NEW>; + close NEW; + + if (open OLD, "$webkitLibrariesDir/$file.modified") { + my $old = <OLD>; + close OLD; + if ($old eq $new) { + print "Current $file is up to date\n"; + exit 0; + } + } +} + +my $result = system "unzip", "-q", "-d", $tmpDir, $pathToZip; +die "Couldn't unzip $zipFile." if $result; + +print "\nInstalling $file...\n"; + +sub wanted +{ + my $relativeName = File::Spec->abs2rel($File::Find::name, "$tmpDir/$file/win"); + my $destination = "$webkitLibrariesDir/$relativeName"; + + if (-d $_) { + mkdir $destination; + return; + } + + system "cp", $_, $destination; +} + +File::Find::find(\&wanted, "$tmpDir/$file"); + +$result = system "mv", "$tmpDir/$file.modified", $webkitLibrariesDir; +print STDERR "Couldn't move $file.modified to $webkitLibrariesDir" . ".\n" if $result; + +print "The $file has been sucessfully installed in\n $webkitLibrariesDir\n"; +exit; + +sub toUnixPath +{ + my $path = shift; + return unless $path; + chomp($path = `cygpath -u '$path'`); + return $path; +} diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm new file mode 100644 index 0000000..478da8a --- /dev/null +++ b/WebKitTools/Scripts/webkitdirs.pm @@ -0,0 +1,947 @@ +# Copyright (C) 2005, 2006, 2007 Apple Inc. 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. + +# Module to share code to get to WebKit directories. + +use strict; +use warnings; +use FindBin; +use File::Basename; +use POSIX; +use VCSUtils; + +BEGIN { + use Exporter (); + 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 ¤tSVNRevision); + %EXPORT_TAGS = ( ); + @EXPORT_OK = (); +} + +our @EXPORT_OK; + +my $baseProductDir; +my @baseProductDirOption; +my $configuration; +my $configurationForVisualStudio; +my $configurationProductDir; +my $sourceDir; +my $currentSVNRevision; +my $osXVersion; +my $isQt; +my $isGtk; +my $isWx; + +# Variables for Win32 support +my $vcBuildPath; +my $windowsTmpPath; + +sub determineSourceDir +{ + return if $sourceDir; + $sourceDir = $FindBin::Bin; + + # walks up path checking each directory to see if it is the main WebKit project dir, + # defined by containing JavaScriptCore, WebCore, and WebKit + until ((-d "$sourceDir/JavaScriptCore" && -d "$sourceDir/WebCore" && -d "$sourceDir/WebKit") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource")) + { + if ($sourceDir !~ s|/[^/]+$||) { + die "Could not find top level webkit directory above source directory using FindBin.\n"; + } + } + + $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource"; +} + +# used for scripts which are stored in a non-standard location +sub setSourceDir($) +{ + ($sourceDir) = @_; +} + +sub determineBaseProductDir +{ + return if defined $baseProductDir; + determineSourceDir(); + if (isOSX()) { + open PRODUCT, "defaults read com.apple.Xcode PBXApplicationwideBuildSettings 2> /dev/null |" or die; + $baseProductDir = join '', <PRODUCT>; + close PRODUCT; + + $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s; + undef $baseProductDir unless $baseProductDir =~ /^\//; + + if (!defined($baseProductDir)) { + open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null |" or die; + $baseProductDir = <PRODUCT>; + close PRODUCT; + if ($baseProductDir) { + chomp $baseProductDir; + undef $baseProductDir unless $baseProductDir =~ /^\//; + } + } + } else { + $baseProductDir = $ENV{"WEBKITOUTPUTDIR"}; + if (isCygwin() && $baseProductDir) { + my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`; + chomp $unixBuildPath; + $baseProductDir = $unixBuildPath; + } + } + + if ($baseProductDir && isOSX()) { + $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|; + $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|; + $baseProductDir =~ s|^~/|$ENV{HOME}/|; + die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/; + die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/; + @baseProductDirOption = (); + } + + if (!defined($baseProductDir)) { + $baseProductDir = "$sourceDir/WebKitBuild"; + + if (isGit() && isGitBranchBuild()) { + my $branch = gitBranch(); + $baseProductDir = "$baseProductDir/$branch"; + } + + @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir") if (isOSX()); + if (isCygwin()) { + my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`; + chomp $dosBuildPath; + $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath; + } + } +} + +sub setBaseProductDir($) +{ + ($baseProductDir) = @_; +} + +sub determineConfiguration +{ + return if defined $configuration; + determineBaseProductDir(); + if (open CONFIGURATION, "$baseProductDir/Configuration") { + $configuration = <CONFIGURATION>; + close CONFIGURATION; + } + if ($configuration) { + chomp $configuration; + # compatibility for people who have old Configuration files + $configuration = "Release" if $configuration eq "Deployment"; + $configuration = "Debug" if $configuration eq "Development"; + } else { + $configuration = "Release"; + } +} + +sub determineConfigurationForVisualStudio +{ + return if defined $configurationForVisualStudio; + determineConfiguration(); + $configurationForVisualStudio = $configuration; + return unless $configuration eq "Debug"; + setupCygwinEnv(); + chomp(my $dir = `cygpath -ua '$ENV{WEBKITLIBRARIESDIR}'`); + $configurationForVisualStudio = "Debug_Internal" if -f "$dir/bin/CoreFoundation_debug.dll"; +} + +sub determineConfigurationProductDir +{ + return if defined $configurationProductDir; + determineBaseProductDir(); + if(isCygwin() && !isWx()) { + $configurationProductDir = "$baseProductDir/bin"; + } else { + determineConfiguration(); + $configurationProductDir = "$baseProductDir/$configuration"; + } +} + +sub setConfigurationProductDir($) +{ + ($configurationProductDir) = @_; +} + +sub determineCurrentSVNRevision +{ + return if defined $currentSVNRevision; + determineSourceDir(); + my $svnInfo = `LC_ALL=C 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(); + chdir $sourceDir or die; +} + +sub baseProductDir +{ + determineBaseProductDir(); + return $baseProductDir; +} + +sub sourceDir +{ + determineSourceDir(); + return $sourceDir; +} + +sub productDir +{ + determineConfigurationProductDir(); + return $configurationProductDir; +} + +sub configuration() +{ + determineConfiguration(); + return $configuration; +} + +sub configurationForVisualStudio() +{ + determineConfigurationForVisualStudio(); + return $configurationForVisualStudio; +} + +sub currentSVNRevision +{ + determineCurrentSVNRevision(); + return $currentSVNRevision; +} + +sub XcodeOptions +{ + determineBaseProductDir(); + determineConfiguration(); + return (@baseProductDirOption, "-configuration", $configuration); +} + +sub XcodeOptionString +{ + return join " ", XcodeOptions(); +} + +sub XcodeOptionStringNoConfig +{ + return join " ", @baseProductDirOption; +} + +my $passedConfiguration; +my $searchedForPassedConfiguration; +sub determinePassedConfiguration +{ + return if $searchedForPassedConfiguration; + $searchedForPassedConfiguration = 1; + for my $i (0 .. $#ARGV) { + my $opt = $ARGV[$i]; + if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) { + splice(@ARGV, $i, 1); + $passedConfiguration = "Debug"; + return; + } + if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) { + splice(@ARGV, $i, 1); + $passedConfiguration = "Release"; + return; + } + } + $passedConfiguration = undef; +} + +sub passedConfiguration +{ + determinePassedConfiguration(); + return $passedConfiguration; +} + +sub setConfiguration +{ + if (my $config = shift @_) { + $configuration = $config; + return; + } + + determinePassedConfiguration(); + $configuration = $passedConfiguration if $passedConfiguration; +} + +sub safariPathFromSafariBundle +{ + my ($safariBundle) = @_; + + return "$safariBundle/Contents/MacOS/Safari" if isOSX(); + return $safariBundle if isCygwin(); +} + +sub installedSafariPath +{ + my $safariBundle; + + if (isOSX()) { + $safariBundle = "/Applications/Safari.app"; + } elsif (isCygwin()) { + $safariBundle = `"$configurationProductDir/FindSafari.exe"`; + $safariBundle =~ s/[\r\n]+$//; + $safariBundle = `cygpath -u '$safariBundle'`; + $safariBundle =~ s/[\r\n]+$//; + $safariBundle .= "Safari.exe"; + } + + return safariPathFromSafariBundle($safariBundle); +} + +# Locate Safari. +sub safariPath +{ + # Use WEBKIT_SAFARI environment variable if present. + my $safariBundle = $ENV{WEBKIT_SAFARI}; + if (!$safariBundle) { + determineConfigurationProductDir(); + # Use Safari.app in product directory if present (good for Safari development team). + if (isOSX() && -d "$configurationProductDir/Safari.app") { + $safariBundle = "$configurationProductDir/Safari.app"; + } elsif (isCygwin() && -x "$configurationProductDir/bin/Safari.exe") { + $safariBundle = "$configurationProductDir/bin/Safari.exe"; + } else { + return installedSafariPath(); + } + } + my $safariPath = safariPathFromSafariBundle($safariBundle); + die "Can't find executable at $safariPath.\n" if isOSX() && !-x $safariPath; + return $safariPath; +} + +sub builtDylibPathForName +{ + my $framework = shift; + determineConfigurationProductDir(); + if (isQt() or isGtk()) { + return "$configurationProductDir/$framework"; + } + if (isOSX()) { + return "$configurationProductDir/$framework.framework/Versions/A/$framework"; + } + if (isCygwin()) { + if ($framework eq "JavaScriptCore") { + return "$baseProductDir/lib/$framework.lib"; + } else { + return "$baseProductDir/$framework.intermediate/$configuration/$framework.intermediate/$framework.lib"; + } + } + + die "Unsupported platform, can't determine built library locations."; +} + +# Check to see that all the frameworks are built. +sub checkFrameworks +{ + return if isCygwin(); + my @frameworks = ("JavaScriptCore", "WebCore"); + push(@frameworks, "WebKit") if isOSX(); + for my $framework (@frameworks) { + my $path = builtDylibPathForName($framework); + die "Can't find built framework at \"$path\".\n" unless -x $path; + } +} + +sub hasSVGSupport +{ + return 0 if isCygwin(); + + my $path = shift; + + if (isQt()) { + return 1; + } + + if (isGtk() and $path =~ /WebCore/) { + $path .= "/../lib/libWebKitGtk.so" if !$ENV{WEBKITAUTOTOOLS}; + $path .= "/../.libs/libWebKitGtk.so" if $ENV{WEBKITAUTOTOOLS}; + } + + my $hasSVGSupport = 0; + if (-e $path) { + open NM, "-|", "nm", $path or die; + while (<NM>) { + $hasSVGSupport = 1 if /SVGElement/; + } + close NM; + } + return $hasSVGSupport; +} + +sub removeLibraryDependingOnSVG +{ + my $frameworkName = shift; + my $shouldHaveSVG = shift; + + my $path = builtDylibPathForName($frameworkName); + return unless -x $path; + + my $hasSVG = hasSVGSupport($path); + system "rm -f $path" if ($shouldHaveSVG xor $hasSVG); +} + +sub checkWebCoreSVGSupport +{ + my $required = shift; + my $framework = "WebCore"; + my $path = builtDylibPathForName($framework); + my $hasSVG = hasSVGSupport($path); + if ($required && !$hasSVG) { + die "$framework at \"$path\" does not include SVG Support, please run build-webkit --svg\n"; + } + return $hasSVG; +} + +sub isQt() +{ + determineIsQt(); + return $isQt; +} + +sub checkArgv($) +{ + my $argToCheck = shift; + foreach my $opt (@ARGV) { + if ($opt =~ /^$argToCheck/i ) { + @ARGV = grep(!/^$argToCheck/i, @ARGV); + return 1; + } + } + return 0; +} + +sub determineIsQt() +{ + return if defined($isQt); + + # Allow override in case QTDIR is not set. + if (checkArgv("--qt")) { + $isQt = 1; + return; + } + + # The presence of QTDIR only means Qt if --gtk is not on the command-line + if (isGtk()) { + $isQt = 0; + return; + } + + $isQt = defined($ENV{'QTDIR'}); +} + +sub isGtk() +{ + determineIsGtk(); + return $isGtk; +} + +sub determineIsGtk() +{ + return if defined($isGtk); + + if (checkArgv("--gtk")) { + $isGtk = 1; + } else { + $isGtk = 0; + } +} + +sub isWx() +{ + determineIsWx(); + return $isWx; +} + +sub determineIsWx() +{ + return if defined($isWx); + + if (checkArgv("--wx")) { + $isWx = 1; + } else { + $isWx = 0; + } +} + +# Determine if this is debian, ubuntu, linspire, or something similar. +sub isDebianBased() +{ + return -e "/etc/debian_version"; +} + +sub isCygwin() +{ + return ($^O eq "cygwin"); +} + +sub isDarwin() +{ + return ($^O eq "darwin"); +} + +sub isOSX() +{ + return isDarwin() unless (isQt() or isGtk() or isWx()); + return 0; +} + +sub determineOSXVersion() +{ + return if $osXVersion; + + if (!isOSX()) { + $osXVersion = -1; + return; + } + + my $version = `sw_vers -productVersion`; + my @splitVersion = split(/\./, $version); + @splitVersion >= 2 or die "Invalid version $version"; + $osXVersion = { + "major" => $splitVersion[0], + "minor" => $splitVersion[1], + "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0), + }; +} + +sub osXVersion() +{ + determineOSXVersion(); + return $osXVersion; +} + +sub isTiger() +{ + return isOSX() && osXVersion()->{"minor"} == 4; +} + +sub isLeopard() +{ + return isOSX() && osXVersion()->{"minor"} == 5; +} + +sub relativeScriptsDir() +{ + my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel(dirname($0), getcwd()), ""); + if ($scriptDir eq "") { + $scriptDir = "."; + } + return $scriptDir; +} + +sub launcherPath() +{ + my $relativeScriptsPath = relativeScriptsDir(); + if (isGtk() || isQt()) { + return "$relativeScriptsPath/run-launcher"; + } elsif (isOSX() || isCygwin()) { + return "$relativeScriptsPath/run-safari"; + } +} + +sub launcherName() +{ + if (isGtk()) { + return "GtkLauncher"; + } elsif (isQt()) { + return "QtLauncher"; + } elsif (isOSX() || isCygwin()) { + return "Safari"; + } +} + +sub checkRequiredSystemConfig +{ + if (isOSX()) { + chomp(my $productVersion = `sw_vers -productVersion`); + if ($productVersion lt "10.4") { + print "*************************************************************\n"; + print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n"; + print "You have " . $productVersion . ", thus the build will most likely fail.\n"; + print "*************************************************************\n"; + } + my $xcodeVersion = `xcodebuild -version`; + if ($xcodeVersion !~ /DevToolsCore-(\d+)/ || $1 < 747) { + print "*************************************************************\n"; + print "Xcode Version 2.3 or later is required to build WebKit.\n"; + print "You have an earlier version of Xcode, thus the build will\n"; + print "most likely fail. The latest Xcode is available from the web:\n"; + print "http://developer.apple.com/tools/xcode\n"; + print "*************************************************************\n"; + } + } elsif (isGtk() or isQt() or isWx()) { + my @cmds = qw(flex bison gperf); + my @missing = (); + foreach my $cmd (@cmds) { + if (not `$cmd --version`) { + push @missing, $cmd; + } + } + if (@missing) { + my $list = join ", ", @missing; + die "ERROR: $list missing but required to build WebKit.\n"; + } + } + # Win32 and other platforms may want to check for minimum config +} + +sub setupCygwinEnv() +{ + return if !isCygwin(); + return if $vcBuildPath; + + my $programFilesPath = `cygpath "$ENV{'PROGRAMFILES'}"`; + chomp $programFilesPath; + $vcBuildPath = "$programFilesPath/Microsoft Visual Studio 8/Common7/IDE/devenv.com"; + if (! -e $vcBuildPath) { + # VC++ not found, try VC++ Express + my $vsInstallDir; + if ($ENV{'VSINSTALLDIR'}) { + $vsInstallDir = $ENV{'VSINSTALLDIR'}; + } else { + $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files"; + $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8"; + } + $vsInstallDir = `cygpath "$vsInstallDir"`; + chomp $vsInstallDir; + $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe"; + if (! -e $vcBuildPath) { + print "*************************************************************\n"; + print "Cannot find '$vcBuildPath'\n"; + print "Please execute the file 'vcvars32.bat' from\n"; + print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n"; + print "to setup the necessary environment variables.\n"; + print "*************************************************************\n"; + die; + } + } + + my $qtSDKPath = "$programFilesPath/QuickTime SDK"; + if (0 && ! -e $qtSDKPath) { + print "*************************************************************\n"; + print "Cannot find '$qtSDKPath'\n"; + print "Please download the QuickTime SDK for Windows from\n"; + print "http://developer.apple.com/quicktime/download/\n"; + print "*************************************************************\n"; + die; + } + + chomp($ENV{'WEBKITLIBRARIESDIR'} = `cygpath -wa "$sourceDir/WebKitLibraries/win"`) unless $ENV{'WEBKITLIBRARIESDIR'}; + + $windowsTmpPath = `cygpath -w /tmp`; + chomp $windowsTmpPath; + print "Building results into: ", baseProductDir(), "\n"; + print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n"; + print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n"; +} + +sub buildVisualStudioProject +{ + my ($project, $clean) = @_; + setupCygwinEnv(); + + my $config = configurationForVisualStudio(); + + chomp(my $winProjectPath = `cygpath -w "$project"`); + + my $command = "/build"; + if ($clean) { + $command = "/clean"; + } + + print "$vcBuildPath $winProjectPath /build $config\n"; + return system $vcBuildPath, $winProjectPath, $command, $config; +} + +sub qtMakeCommand($) +{ + my ($qmakebin) = @_; + chomp(my $mkspec = `$qmakebin -query QMAKE_MKSPECS`); + $mkspec .= "/default"; + + my $compiler = ""; + open SPEC, "<$mkspec/qmake.conf" or return "make"; + while (<SPEC>) { + if ($_ =~ /QMAKE_CC\s*=\s*([^\s]+)/) { + $compiler = $1; + } + } + close SPEC; + + #print "default spec: " . $mkspec . "\n"; + #print "compiler found: " . $compiler . "\n"; + + if ($compiler eq "cl") { + return "nmake"; + } + + return "make"; +} + +sub autotoolsFlag($$) +{ + my ($flag, $feature) = @_; + my $prefix = $flag ? "--enable" : "--disable"; + + return $prefix . '-' . $feature; +} + +sub buildAutotoolsProject($@) +{ + my ($clean, @buildArgs) = @_; + + my $make = 'make'; + my $dir = productDir(); + my $config = passedConfiguration() || configuration(); + my $prefix = $ENV{"WebKitInstallationPrefix"}; + + # check if configuration is Debug + if ($config =~ m/debug/i) { + push @buildArgs, "--enable-debug"; + } else { + push @buildArgs, "--disable-debug"; + } + + if (! -d $dir) { + system "mkdir", "-p", "$dir"; + if (! -d $dir) { + die "Failed to create build directory " . $dir; + } + } + + chdir $dir or die "Failed to cd into " . $dir . "\n"; + + my $result; + if ($clean) { + $result = system $make, "distclean"; + return $result; + } + + print "Calling configure in " . $dir . "\n\n"; + print "Installation directory: $prefix\n" if(defined($prefix)); + + $result = system "$sourceDir/autogen.sh", @buildArgs; + if ($result ne 0) { + die "Failed to setup build environment using 'autotools'!\n"; + } + + $result = system $make; + if ($result ne 0) { + die "\nFailed to build WebKit using '$make'!\n"; + } + + chdir ".." or die; + return $result; +} + +sub buildQMakeProject($@) +{ + my ($clean, @buildArgs) = @_; + + push @buildArgs, "-r"; + + my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH + for my $i (0 .. $#ARGV) { + my $opt = $ARGV[$i]; + if ($opt =~ /^--qmake=(.*)/i ) { + $qmakebin = $1; + } elsif ($opt =~ /^--qmakearg=(.*)/i ) { + push @buildArgs, $1; + } + } + + my $make = qtMakeCommand($qmakebin); + my $config = configuration(); + my $prefix = $ENV{"WebKitInstallationPrefix"}; + + push @buildArgs, "OUTPUT_DIR=" . baseProductDir() . "/$config"; + push @buildArgs, sourceDir() . "/WebKit.pro"; + if ($config =~ m/debug/i) { + push @buildArgs, "CONFIG-=release"; + push @buildArgs, "CONFIG+=debug"; + } else { + push @buildArgs, "CONFIG+=release"; + push @buildArgs, "CONFIG-=debug"; + } + + my $dir = baseProductDir(); + if (! -d $dir) { + system "mkdir", "-p", "$dir"; + if (! -d $dir) { + die "Failed to create product directory " . $dir; + } + } + $dir = $dir . "/$config"; + if (! -d $dir) { + system "mkdir", "-p", "$dir"; + if (! -d $dir) { + die "Failed to create build directory " . $dir; + } + } + + chdir $dir or die "Failed to cd into " . $dir . "\n"; + + print "Calling '$qmakebin @buildArgs' in " . $dir . "\n\n"; + print "Installation directory: $prefix\n" if(defined($prefix)); + + my $result = system $qmakebin, @buildArgs; + if ($result ne 0) { + die "Failed to setup build environment using $qmakebin!\n"; + } + + if ($clean) { + $result = system "$make distclean"; + } else { + $result = system "$make"; + } + + chdir ".." or die; + return $result; +} + +sub buildQMakeQtProject($$) +{ + my ($project, $clean) = @_; + + my @buildArgs = ("CONFIG+=qt-port"); + return buildQMakeProject($clean, @buildArgs); +} + +sub buildGtkProject($$@) +{ + my ($project, $clean, @buildArgs) = @_; + + if ($project ne "WebKit") { + die "The Gtk port builds JavaScriptCore, WebCore and WebKit in one shot! Only call it for 'WebKit'.\n"; + } + + if ($ENV{WEBKITAUTOTOOLS}) { + return buildAutotoolsProject($clean, @buildArgs); + } else { + my @buildArgs = ("CONFIG+=gtk-port", "CONFIG-=qt"); + return buildQMakeProject($clean, @buildArgs); + } +} + +sub setPathForRunningWebKitApp +{ + my ($env) = @_; + + return unless isCygwin(); + + $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), $env->{PATH} || ""); +} + +sub exitStatus($) +{ + my ($returnvalue) = @_; + if ($^O eq "MSWin32") { + return $returnvalue >> 8; + } + return WEXITSTATUS($returnvalue); +} + +sub runSafari +{ + my ($debugger) = @_; + + if (isOSX()) { + return system "$FindBin::Bin/gdb-safari", @ARGV if $debugger; + + my $productDir = productDir(); + print "Starting Safari with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; + return system safariPath(), @ARGV; + } + + if (isCygwin()) { + my $script = "run-webkit-nightly.cmd"; + my $result = system "cp", "$FindBin::Bin/$script", productDir(); + return $result if $result; + + my $cwd = getcwd(); + chdir productDir(); + + my $debuggerFlag = $debugger ? "/debugger" : ""; + $result = system "cmd", "/c", "call $script $debuggerFlag"; + chdir $cwd; + return $result; + } + + return 1; +} + +sub runDrosera +{ + my ($debugger) = @_; + + if (isOSX()) { + return system "$FindBin::Bin/gdb-drosera", @ARGV if $debugger; + + my $productDir = productDir(); + print "Starting Drosera with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n"; + $ENV{DYLD_FRAMEWORK_PATH} = $productDir; + $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; + + my $droseraPath = "$productDir/Drosera.app/Contents/MacOS/Drosera"; + return system $droseraPath, @ARGV; + } + + if (isCygwin()) { + print "Running Drosera\n"; + my $script = "run-drosera-nightly.cmd"; + my $prodDir = productDir(); + my $result = system "cp", "$FindBin::Bin/$script", $prodDir; + return $result if $result; + + my $cwd = getcwd(); + chdir $prodDir; + + my $debuggerFlag = $debugger ? "/debugger" : ""; + $result = system "cmd", "/c", "call $script $debuggerFlag"; + chdir $cwd; + return $result; + } + + return 1; +} + +1; diff --git a/WebKitTools/Scripts/wkstyle b/WebKitTools/Scripts/wkstyle new file mode 100755 index 0000000..690b5fa --- /dev/null +++ b/WebKitTools/Scripts/wkstyle @@ -0,0 +1,66 @@ + +# Copyright (C) 2006 Michael Emmel<mike.emmel@gmail.com> 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. + +astyle \ +--style=linux \ +--indent=spaces=4 \ +--convert-tabs \ +$@ + +#astyle does not support unpadding so we use sed +for i in $@ +do +echo $i +#first print the changes we are making +sed -n -e ' +/( .*/p +s/( /(/gp +/*. )/p +s/ )/)/gp +#supress printing this +#/^namespace WebCore/{ +#N +#s/\n{/ {/p +#} +' $i + +#do it for real +sed -e ' +#unpad leading spaces +s/( /(/g +#unpad traling spaces +s/ )/)/g +#fixup the namspec decl +/^namespace WebCore/{ +N +s/\n{/ {/ +} +' $i > $i.sed +mv $i.sed $i +done + + diff --git a/WebKitTools/WebKitLauncher/Info.plist b/WebKitTools/WebKitLauncher/Info.plist new file mode 100644 index 0000000..9317bd4 --- /dev/null +++ b/WebKitTools/WebKitLauncher/Info.plist @@ -0,0 +1,476 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>css</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>text/css</string> + </array> + <key>CFBundleTypeName</key> + <string>CSS style sheet</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>pdf</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/pdf</string> + </array> + <key>CFBundleTypeName</key> + <string>PDF document</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>webarchive</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>webarchive.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/x-webarchive</string> + </array> + <key>CFBundleTypeName</key> + <string>Web archive</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>syndarticle</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeName</key> + <string>RSS article</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>webbookmark</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeName</key> + <string>Safari bookmark</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>webloc</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeName</key> + <string>Web internet location</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>ilht</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>download</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>download10.icns</string> + <key>CFBundleTypeName</key> + <string>Safari download</string> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSTypeIsPackage</key> + <true/> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>gif</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/gif</string> + </array> + <key>CFBundleTypeName</key> + <string>GIF image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>GIFf</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>html</string> + <string>htm</string> + <string>shtml</string> + <string>jhtml</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>text/html</string> + </array> + <key>CFBundleTypeName</key> + <string>HTML document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>HTML</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>js</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/x-javascript</string> + </array> + <key>CFBundleTypeName</key> + <string>JavaScript script</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>jpg</string> + <string>jpeg</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/jpeg</string> + </array> + <key>CFBundleTypeName</key> + <string>JPEG image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>JPEG</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>jp2</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/jp2</string> + </array> + <key>CFBundleTypeName</key> + <string>JPEG 2000 image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>jp2 </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>txt</string> + <string>text</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>text/plain</string> + </array> + <key>CFBundleTypeName</key> + <string>Plain text document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>TEXT</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>png</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/png</string> + </array> + <key>CFBundleTypeName</key> + <string>PNG image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>PNGf</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>rtf</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/rtf</string> + </array> + <key>CFBundleTypeName</key> + <string>Rich Text Format (RTF) document</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>RTF </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>tiff</string> + <string>tif</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/tiff</string> + </array> + <key>CFBundleTypeName</key> + <string>TIFF image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>TIFF</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>url</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeName</key> + <string>Web site location</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>LINK</string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>ico</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>image/x-icon</string> + </array> + <key>CFBundleTypeName</key> + <string>Windows icon image</string> + <key>CFBundleTypeOSTypes</key> + <array> + <string>ICO </string> + </array> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>xhtml</string> + <string>xhtm</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/xhtml+xml</string> + </array> + <key>CFBundleTypeName</key> + <string>XHTML document</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>xml</string> + <string>xbl</string> + <string>xsl</string> + <string>xslt</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeMIMETypes</key> + <array> + <string>application/xml</string> + <string>text/xml</string> + </array> + <key>CFBundleTypeName</key> + <string>XML document</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>NSDocumentClass</key> + <string>BrowserDocument</string> + </dict> + </array> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleGetInfoString</key> + <string>rVERSION, Copyright 2005, 2006, 2007 Apple Inc.</string> + <key>CFBundleIconFile</key> + <string>webkit.icns</string> + <key>CFBundleIdentifier</key> + <string>org.webkit.nightly.WebKit</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>wbkt</string> + <key>CFBundleVersion</key> + <string>VERSION</string> + <key>CFBundleShortVersionString</key> + <string>rVERSION</string> + <key>NSPrincipalClass</key> + <string>BrowserApplication</string> + + <key>CFBundleHelpBookFolder</key> + <string>SafariHelp</string> + <key>CFBundleHelpBookName</key> + <string>Safari Help</string> + <key>CFBundleURLTypes</key> + <array> + <dict> + <key>CFBundleURLName</key> + <string>Web site URL</string> + <key>CFBundleURLSchemes</key> + <array> + <string>http</string> + <string>https</string> + </array> + </dict> + <dict> + <key>CFBundleURLName</key> + <string>local file URL</string> + <key>CFBundleURLSchemes</key> + <array> + <string>file</string> + </array> + </dict> + </array> + <key>NSAppleScriptEnabled</key> + <string>Yes</string> + <key>UTExportedTypeDeclarations</key> + <array> + <dict> + <key>UTTypeConformsTo</key> + <string>public.data</string> + <key>UTTypeDescription</key> + <string>Safari bookmark</string> + <key>UTTypeIdentifier</key> + <string>com.apple.safari.bookmark</string> + <key>UTTypeTagSpecification</key> + <dict> + <key>public.filename-extension</key> + <array> + <string>webbookmark</string> + </array> + </dict> + </dict> + </array> + +</dict> +</plist> diff --git a/WebKitTools/WebKitLauncher/VERSION b/WebKitTools/WebKitLauncher/VERSION new file mode 100644 index 0000000..fd85e30 --- /dev/null +++ b/WebKitTools/WebKitLauncher/VERSION @@ -0,0 +1 @@ +VERSION diff --git a/WebKitTools/WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj b/WebKitTools/WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fda0581 --- /dev/null +++ b/WebKitTools/WebKitLauncher/WebKitLauncher.xcodeproj/project.pbxproj @@ -0,0 +1,359 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 5D41141C0A50A9DE00C84CF0 /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 5D41141B0A50A9DE00C84CF0 /* VERSION */; }; + 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 */; }; + 5D877FCD0A5795F200D0C67B /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.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 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 = "<absolute>"; }; + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; + 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; + 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; + 5D41141B0A50A9DE00C84CF0 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; }; + 5D4DF981097F89FB0083D5E5 /* start.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html; path = start.html; sourceTree = "<group>"; }; + 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 = "<group>"; }; + 5D650F7509DB8CB40075E9A8 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; }; + 5DB70524097B94CD009875EC /* webkit.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = webkit.icns; sourceTree = "<group>"; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; + 8D1107320486CEB800E47090 /* WebKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WebKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5D650F3209DB8B280075E9A8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D877FCD0A5795F200D0C67B /* Cocoa.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 = "<group>"; + }; + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = "<group>"; + }; + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 5D650F7509DB8CB40075E9A8 /* CoreFoundation.framework */, + 29B97324FDCFA39411CA2CEA /* AppKit.framework */, + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, + 29B97325FDCFA39411CA2CEA /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = "<group>"; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D1107320486CEB800E47090 /* WebKit.app */, + 5D650F3409DB8B280075E9A8 /* WebKitNightlyEnabler.dylib */, + ); + name = Products; + sourceTree = "<group>"; + }; + 29B97314FDCFA39411CA2CEA /* WebKit */ = { + isa = PBXGroup; + children = ( + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = WebKit; + sourceTree = "<group>"; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 5D650F3509DB8B370075E9A8 /* WebKitNightlyEnabler.m */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = "<group>"; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 5D4DF981097F89FB0083D5E5 /* start.html */, + 5DB70524097B94CD009875EC /* webkit.icns */, + 8D1107310486CEB800E47090 /* Info.plist */, + 5D41141B0A50A9DE00C84CF0 /* VERSION */, + ); + name = Resources; + sourceTree = "<group>"; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; +/* 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 = ( + ); + 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 = ( + ); + 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 "WebKitLauncher" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* WebKit */; + projectDirPath = ""; + projectRoot = ""; + shouldCheckCompatibility = 1; + targets = ( + 8D1107260486CEB800E47090 /* WebKit */, + 5D650F3309DB8B280075E9A8 /* WebKitNightlyEnabler */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D1107290486CEB800E47090 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5D41141C0A50A9DE00C84CF0 /* VERSION in Resources */, + 5D650F3A09DB8B410075E9A8 /* WebKitNightlyEnabler.dylib in Resources */, + 5D4DF982097F89FB0083D5E5 /* start.html in Resources */, + 5DB70525097B94CD009875EC /* webkit.icns 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 = { + DEBUG_INFORMATION_FORMAT = dwarf; + 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 = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + 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 = /Developer/SDKs/MacOSX10.4u.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 "WebKitLauncher" */ = { + 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 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]; +} diff --git a/WebKitTools/WebKitLauncher/main.m b/WebKitTools/WebKitLauncher/main.m new file mode 100644 index 0000000..7c9b9a5 --- /dev/null +++ b/WebKitTools/WebKitLauncher/main.m @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. 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> +#import <CoreFoundation/CoreFoundation.h> + +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); +} + +NSBundle *locateSafariBundle() +{ + NSArray *applicationDirectories = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSAllDomainsMask, YES); + NSEnumerator *e = [applicationDirectories objectEnumerator]; + NSString *applicationDirectory; + while (applicationDirectory = [e nextObject]) { + NSString *possibleSafariPath = [applicationDirectory stringByAppendingPathComponent:@"Safari.app"]; + NSBundle *possibleSafariBundle = [NSBundle bundleWithPath:possibleSafariPath]; + if ([[possibleSafariBundle bundleIdentifier] isEqualToString:@"com.apple.Safari"]) + return possibleSafariBundle; + } + + 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."); + + NSBundle *safariBundle = [NSBundle bundleWithPath:[(NSURL *)safariURL path]]; + CFRelease(safariURL); + return safariBundle; +} + +NSString *currentSystemVersion() +{ + long version; + if (Gestalt(gestaltSystemVersion, &version) != noErr) + return @"10.4"; + + return [NSString stringWithFormat:@"%x.%x", (version & 0xFF00) >> 8, (version & 0x00F0) >> 4]; +} + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + checkMacOSXVersion(); + + NSBundle *safariBundle = locateSafariBundle(); + NSString *executablePath = [safariBundle executablePath]; + NSString *frameworkPath = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:currentSystemVersion()]; + NSString *pathToEnablerLib = [[NSBundle mainBundle] pathForResource:@"WebKitNightlyEnabler" ofType:@"dylib"]; + + NSLog(@"Using framework path of %@", frameworkPath); + + if ([frameworkPath rangeOfString:@":"].location != NSNotFound || + [pathToEnablerLib rangeOfString:@":"].location != NSNotFound) + displayErrorAndQuit(@"Unable to launch Safari", + @"WebKit is located at a path containing an unsupported character. Please move WebKit to a different location and try again."); + + NSMutableArray *arguments = [NSMutableArray arrayWithObjects:executablePath, @"-WebKitDeveloperExtras", @"YES", @"-WebKitScriptDebuggerEnabled", @"YES", nil]; + NSMutableDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys:frameworkPath, @"DYLD_FRAMEWORK_PATH", @"YES", @"WEBKIT_UNSET_DYLD_FRAMEWORK_PATH", + pathToEnablerLib, @"DYLD_INSERT_LIBRARIES", [[NSBundle mainBundle] executablePath], @"WebKitAppPath", nil]; + addStartPageToArgumentsIfNeeded(arguments); + + while (*++argv) + [arguments addObject:[NSString stringWithUTF8String:*argv]]; + + myExecve(executablePath, arguments, environment); + + char *error = strerror(errno); + NSString *errorMessage = [NSString stringWithFormat:@"Launching Safari at %@ failed with the error '%s' (%d)", [safariBundle bundlePath], error, errno]; + displayErrorAndQuit(@"Unable to launch Safari", errorMessage); + + [pool release]; + return 0; +} diff --git a/WebKitTools/WebKitLauncher/start.html b/WebKitTools/WebKitLauncher/start.html new file mode 100644 index 0000000..2c94e79 --- /dev/null +++ b/WebKitTools/WebKitLauncher/start.html @@ -0,0 +1,33 @@ +<html> + <head> + <title>Loading WebKit...</title> + <meta http-equiv="refresh" content="1;URL=http://nightly.webkit.org/start/" /> + <script type="text/javascript"> + function getWebKitRevision() + { + var request = new XMLHttpRequest(); + request.open("GET", "VERSION", false); + request.send(); + var revision = parseInt(request.responseText); + if (isNaN(revision)) + return ""; + + return revision; + } + + function getWebKitBranch() + { + var request = new XMLHttpRequest(); + request.open("GET", "BRANCH", false); + request.send(); + return (request.responseText || "trunk").replace(/\s/g, '') + } + + var revision = getWebKitRevision(); + var branch = getWebKitBranch(); + document.location = "http://nightly.webkit.org/start/" + branch + "/" + revision; + </script> + </head> + <body> + </body> +</html> diff --git a/WebKitTools/WebKitLauncher/webkit.icns b/WebKitTools/WebKitLauncher/webkit.icns Binary files differnew file mode 100644 index 0000000..bf629bf --- /dev/null +++ b/WebKitTools/WebKitLauncher/webkit.icns diff --git a/WebKitTools/WinLauncher/WinLauncher.cpp b/WebKitTools/WinLauncher/WinLauncher.cpp new file mode 100644 index 0000000..4d60115 --- /dev/null +++ b/WebKitTools/WinLauncher/WinLauncher.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2006, 2008 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#include "stdafx.h" +#include "WinLauncher.h" +#include "WebKit.h" + +#include <commctrl.h> +#include <objbase.h> +#include <shlwapi.h> +#include <wininet.h> + +#define MAX_LOADSTRING 100 +#define URLBAR_HEIGHT 24 + +// Global Variables: +HINSTANCE hInst; // current instance +HWND hMainWnd; +HWND hURLBarWnd; +long DefEditProc; +IWebView* gWebView = 0; +HWND gViewWindow = 0; +WinLauncherWebHost* gWebHost = 0; +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name + +// Forward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK MyEditProc(HWND, UINT, WPARAM, LPARAM); + +static void loadURL(BSTR urlBStr); + +HRESULT WinLauncherWebHost::updateAddressBar(IWebView* webView) +{ + IWebFrame* mainFrame = 0; + IWebDataSource* dataSource = 0; + IWebMutableURLRequest* request = 0; + BSTR frameURL = 0; + + HRESULT hr = S_OK; + + hr = webView->mainFrame(&mainFrame); + if (FAILED(hr)) + goto exit; + + hr = mainFrame->dataSource(&dataSource); + if (FAILED(hr) || !dataSource) + hr = mainFrame->provisionalDataSource(&dataSource); + if (FAILED(hr) || !dataSource) + goto exit; + + hr = dataSource->request(&request); + if (FAILED(hr) || !request) + goto exit; + + hr = request->mainDocumentURL(&frameURL); + if (FAILED(hr)) + goto exit; + + SendMessage(hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL); + +exit: + if (mainFrame) + mainFrame->Release(); + if (dataSource) + dataSource->Release(); + if (request) + request->Release(); + SysFreeString(frameURL); + return 0; +} + +HRESULT STDMETHODCALLTYPE WinLauncherWebHost::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); + else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate)) + *ppvObject = static_cast<IWebFrameLoadDelegate*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE WinLauncherWebHost::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE WinLauncherWebHost::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + +static void resizeSubViews() +{ + RECT rcClient; + GetClientRect(hMainWnd, &rcClient); + MoveWindow(hURLBarWnd, 0, 0, rcClient.right, URLBAR_HEIGHT, TRUE); + MoveWindow(gViewWindow, 0, URLBAR_HEIGHT, rcClient.right, rcClient.bottom - URLBAR_HEIGHT, TRUE); +} + +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); +#endif + + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + // TODO: Place code here. + MSG msg; + HACCEL hAccelTable; + + INITCOMMONCONTROLSEX InitCtrlEx; + + InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCtrlEx.dwICC = 0x00004000; //ICC_STANDARD_CLASSES; + InitCommonControlsEx(&InitCtrlEx); + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_WINLAUNCHER, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + return FALSE; + + // Init COM + OleInitialize(NULL); + + hURLBarWnd = CreateWindow(L"EDIT", 0, + WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, + 0, 0, 0, 0, + hMainWnd, + 0, + hInstance, 0); + + DefEditProc = GetWindowLong(hURLBarWnd, GWL_WNDPROC); + SetWindowLong(hURLBarWnd, GWL_WNDPROC,(long)MyEditProc); + SetFocus(hURLBarWnd); + + HRESULT hr = CoCreateInstance(CLSID_WebView, 0, CLSCTX_ALL, IID_IWebView, (void**)&gWebView); + if (FAILED(hr)) + goto exit; + + gWebHost = new WinLauncherWebHost(); + gWebHost->AddRef(); + hr = gWebView->setFrameLoadDelegate(gWebHost); + if (FAILED(hr)) + goto exit; + + hr = gWebView->setHostWindow((OLE_HANDLE) hMainWnd); + if (FAILED(hr)) + goto exit; + + RECT clientRect; + GetClientRect(hMainWnd, &clientRect); + hr = gWebView->initWithFrame(clientRect, 0, 0); + if (FAILED(hr)) + goto exit; + + IWebFrame* frame; + hr = gWebView->mainFrame(&frame); + if (FAILED(hr)) + goto exit; + static BSTR defaultHTML = 0; + if (!defaultHTML) + defaultHTML = SysAllocString(TEXT("<p style=\"background-color: #00FF00\">Testing</p><img src=\"http://webkit.org/images/icon-gold.png\" alt=\"Face\"><div style=\"border: solid blue\" contenteditable=\"true\">div with blue border</div><ul><li>foo<li>bar<li>baz</ul>")); + frame->loadHTMLString(defaultHTML, 0); + frame->Release(); + + IWebViewPrivate* viewExt; + hr = gWebView->QueryInterface(IID_IWebViewPrivate, (void**)&viewExt); + if (FAILED(hr)) + goto exit; + hr = viewExt->viewWindow((OLE_HANDLE*) &gViewWindow); + viewExt->Release(); + if (FAILED(hr) || !gViewWindow) + goto exit; + + resizeSubViews(); + + ShowWindow(gViewWindow, nCmdShow); + UpdateWindow(gViewWindow); + + hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINLAUNCHER)); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + +exit: + delete gWebView; +#ifdef _CRTDBG_MAP_ALLOC + _CrtDumpMemoryLeaks(); +#endif + + // Shut down COM. + OleUninitialize(); + + return (int) msg.wParam; +} + +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINLAUNCHER)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = 0; + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINLAUNCHER); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassEx(&wcex); +} + +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + hInst = hInstance; // Store instance handle in our global variable + + hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + + if (!hMainWnd) + return FALSE; + + ShowWindow(hMainWnd, nCmdShow); + UpdateWindow(hMainWnd); + + return TRUE; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + PAINTSTRUCT ps; + HDC hdc; + + switch (message) { + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) { + case IDM_ABOUT: + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); + break; + case IDM_EXIT: + DestroyWindow(hWnd); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + case WM_SIZE: + if (!gWebView) + break; + resizeSubViews(); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + + +#define MAX_URL_LENGTH 1024 + +LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_CHAR: + if( wParam == 13 ) { // Enter Key + wchar_t strPtr[MAX_URL_LENGTH]; + *((LPWORD)strPtr) = MAX_URL_LENGTH; + int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr); + + BSTR bstr = SysAllocStringLen(strPtr, strLen); + loadURL(bstr); + SysFreeString(bstr); + + return 0; + } else + return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam); + break; + default: + return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam); + break; + } + return 0; +} + + +// Message handler for about box. +INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +static void loadURL(BSTR urlBStr) +{ + IWebFrame* frame = 0; + IWebMutableURLRequest* request = 0; + static BSTR methodBStr = 0; + + if (!methodBStr) + methodBStr = SysAllocString(TEXT("GET")); + + if (urlBStr && urlBStr[0] && (PathFileExists(urlBStr) || PathIsUNC(urlBStr))) { + TCHAR fileURL[INTERNET_MAX_URL_LENGTH]; + DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]); + if (SUCCEEDED(UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0))) + urlBStr = fileURL; + } + + HRESULT hr = gWebView->mainFrame(&frame); + if (FAILED(hr)) + goto exit; + + hr = CoCreateInstance(CLSID_WebMutableURLRequest, 0, CLSCTX_ALL, IID_IWebMutableURLRequest, (void**)&request); + if (FAILED(hr)) + goto exit; + + hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0); + if (FAILED(hr)) + goto exit; + + hr = request->setHTTPMethod(methodBStr); + if (FAILED(hr)) + goto exit; + + hr = frame->loadRequest(request); + if (FAILED(hr)) + goto exit; + + SetFocus(gViewWindow); + +exit: + if (frame) + frame->Release(); + if (request) + request->Release(); +} diff --git a/WebKitTools/WinLauncher/WinLauncher.h b/WebKitTools/WinLauncher/WinLauncher.h new file mode 100644 index 0000000..1f57bff --- /dev/null +++ b/WebKitTools/WinLauncher/WinLauncher.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#pragma once + +#include "resource.h" +#include "WebKit.h" + +class WinLauncherWebHost : public IWebFrameLoadDelegate +{ +public: + WinLauncherWebHost() : m_refCount(1) {} + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IWebFrameLoadDelegate + virtual HRESULT STDMETHODCALLTYPE didStartProvisionalLoadForFrame( + /* [in] */ IWebView* webView, + /* [in] */ IWebFrame* /*frame*/) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didReceiveServerRedirectForProvisionalLoadForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didFailProvisionalLoadWithError( + /* [in] */ IWebView *webView, + /* [in] */ IWebError *error, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didCommitLoadForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return updateAddressBar(webView); } + + virtual HRESULT STDMETHODCALLTYPE didReceiveTitle( + /* [in] */ IWebView *webView, + /* [in] */ BSTR title, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didReceiveIcon( + /* [in] */ IWebView *webView, + /* [in] */ OLE_HANDLE hBitmap, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didFinishLoadForFrame( + /* [in] */ IWebView* webView, + /* [in] */ IWebFrame* /*frame*/) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didFailLoadWithError( + /* [in] */ IWebView *webView, + /* [in] */ IWebError *error, + /* [in] */ IWebFrame *forFrame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didChangeLocationWithinPageForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE willPerformClientRedirectToURL( + /* [in] */ IWebView *webView, + /* [in] */ BSTR url, + /* [in] */ double delaySeconds, + /* [in] */ DATE fireDate, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE didCancelClientRedirectForFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE willCloseFrame( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return S_OK; } + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE windowScriptObjectAvailable( + /* [in] */ IWebView *webView, + /* [in] */ JSContextRef context, + /* [in] */ JSObjectRef windowScriptObject) { return S_OK; } + + // WinLauncherWebHost + +protected: + HRESULT updateAddressBar(IWebView* webView); + +protected: + ULONG m_refCount; +}; diff --git a/WebKitTools/WinLauncher/WinLauncher.ico b/WebKitTools/WinLauncher/WinLauncher.ico Binary files differnew file mode 100644 index 0000000..d551aa3 --- /dev/null +++ b/WebKitTools/WinLauncher/WinLauncher.ico diff --git a/WebKitTools/WinLauncher/WinLauncher.rc b/WebKitTools/WinLauncher/WinLauncher.rc new file mode 100644 index 0000000..f4b2cd4 --- /dev/null +++ b/WebKitTools/WinLauncher/WinLauncher.rc @@ -0,0 +1,136 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_WINLAUNCHER ICON "WinLauncher.ico" +IDI_SMALL ICON "small.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_WINLAUNCHER MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_WINLAUNCHER ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System", 0, 0, 0x0 +BEGIN + ICON IDI_WINLAUNCHER,IDC_MYICON,14,9,20,20 + LTEXT "WinLauncher Version 1.1",IDC_STATIC,49,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2008",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "WinLauncher" + IDC_WINLAUNCHER "WINLAUNCHER" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/WebKitTools/WinLauncher/WinLauncher.vcproj b/WebKitTools/WinLauncher/WinLauncher.vcproj new file mode 100644 index 0000000..234df33 --- /dev/null +++ b/WebKitTools/WinLauncher/WinLauncher.vcproj @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="WinLauncher" + ProjectGUID="{114FCA11-216B-4C8C-957E-30A75AE80443}" + RootNamespace="WinLauncher" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(WebKitOutputDir)\bin" + IntermediateDirectory="$(WebKitOutputDir)\obj\$(ProjectName)\$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories=""$(WebKitOutputDir)\include\WebKit";"$(WebKitOutputDir)\Include";"$(WebKitLibrariesDir)\Include";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include\WebCore\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include\JavaScriptCore";"$(ProjectDir)\..";"$(ProjectDir)";"$(IntDir)\Include";"$(WebKitOutputDir)\obj\WebKit\DerivedSources"" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE" + MinimalRebuild="true" + ExceptionHandling="0" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + RuntimeTypeInfo="false" + UsePrecompiledHeader="2" + WarningLevel="1" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkLibraryDependencies="false" + AdditionalDependencies="comctl32.lib shlwapi.lib WebKitGUID$(WebKitConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib" + LinkIncremental="2" + AdditionalLibraryDirectories=""$(WebKitOutputDir)\lib";"$(ProjectDir)\..\..\..\"" + GenerateDebugInformation="true" + SubSystem="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(WebKitOutputDir)\bin" + IntermediateDirectory="$(WebKitOutputDir)\obj\$(ProjectName)\$(ConfigurationName)" + ConfigurationType="1" + InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(WebKitOutputDir)\include\WebKit";"$(WebKitOutputDir)\Include";"$(WebKitLibrariesDir)\Include";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\Include\WebCore\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitLibrariesDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\icu";"$(WebKitLibrariesDir)\Include\icu";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitOutputDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility";"$(ProjectDir)\..";"$(ProjectDir)";"$(IntDir)\include";"$(WebKitOutputDir)\obj\WebKit\DerivedSources"" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINNT=0x501" + ExceptionHandling="0" + RuntimeLibrary="2" + RuntimeTypeInfo="false" + UsePrecompiledHeader="2" + WarningLevel="1" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkLibraryDependencies="false" + AdditionalOptions="
" + AdditionalDependencies="comctl32.lib shlwapi.lib WebKitGUID$(WebKitConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib" + LinkIncremental="1" + AdditionalLibraryDirectories=""$(WebKitOutputDir)\lib";"$(ProjectDir)\..\..\..\"" + GenerateDebugInformation="true" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\stdafx.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\WinLauncher.cpp" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\Resource.h" + > + </File> + <File + RelativePath=".\stdafx.h" + > + </File> + <File + RelativePath=".\WinLauncher.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + <File + RelativePath=".\small.ico" + > + </File> + <File + RelativePath=".\WinLauncher.ico" + > + </File> + <File + RelativePath=".\WinLauncher.rc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/WebKitTools/WinLauncher/resource.h b/WebKitTools/WinLauncher/resource.h new file mode 100644 index 0000000..6a21684 --- /dev/null +++ b/WebKitTools/WinLauncher/resource.h @@ -0,0 +1,27 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by WinLauncher.rc +// +#define IDC_MYICON 2 +#define IDD_WINLAUNCHER_DIALOG 102 +#define IDS_APP_TITLE 103 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_WINLAUNCHER 107 +#define IDI_SMALL 108 +#define IDC_WINLAUNCHER 109 +#define IDR_MAINFRAME 128 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/WebKitTools/WinLauncher/small.ico b/WebKitTools/WinLauncher/small.ico Binary files differnew file mode 100644 index 0000000..d551aa3 --- /dev/null +++ b/WebKitTools/WinLauncher/small.ico diff --git a/WebKitTools/WinLauncher/stdafx.cpp b/WebKitTools/WinLauncher/stdafx.cpp new file mode 100644 index 0000000..541dcb1 --- /dev/null +++ b/WebKitTools/WinLauncher/stdafx.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +// stdafx.cpp : source file that includes just the standard includes +// Spinneret.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/WebKitTools/WinLauncher/stdafx.h b/WebKitTools/WinLauncher/stdafx.h new file mode 100644 index 0000000..86f76cc --- /dev/null +++ b/WebKitTools/WinLauncher/stdafx.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include <windows.h> + +// C RunTime Header Files +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <tchar.h> + +#if 0 +// Visual Studio Leak Detection +// <http://msdn2.microsoft.com/en-US/library/e5ewb1h3.aspx> +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include <stdlib.h> +#include <crtdbg.h> +#endif +#endif diff --git a/WebKitTools/iExploder/CHANGELOG.txt b/WebKitTools/iExploder/CHANGELOG.txt new file mode 100644 index 0000000..a9d5060 --- /dev/null +++ b/WebKitTools/iExploder/CHANGELOG.txt @@ -0,0 +1,328 @@ +------------------------------------------------------------------------ +r618 | thomas | 2006-04-21 09:55:51 -0400 (Fri, 21 Apr 2006) | 1 line +Changed paths: + M /iexploder/README.txt + M /iexploder/htdocs/iexploder.cgi + M /iexploder/htdocs/iexploder.rb + M /iexploder/htdocs/webserver.rb + +1.3.2.. minor adjustment to title and where gets set +------------------------------------------------------------------------ +r617 | thomas | 2006-04-19 17:14:26 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + A /iexploder/testcases/safari/2500_163-Safari-2.0.3_Mac_OS_X-Crash.html + +Add h4+pre+cite+nolayer+code crash for Safari 2.0.3 +------------------------------------------------------------------------ +r616 | thomas | 2006-04-19 17:01:48 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + A /iexploder/tools/showtest.rb + +showtest.rb: easily download a testcase +------------------------------------------------------------------------ +r615 | thomas | 2006-04-19 16:07:13 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + M /iexploder/htdocs/iexploder.rb + +Remove stopping debug message +------------------------------------------------------------------------ +r614 | thomas | 2006-04-19 16:02:48 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + M /iexploder/README.txt + M /iexploder/htdocs/iexploder.rb + +New subtest algorithm: double the tag count each iteration +------------------------------------------------------------------------ +r613 | thomas | 2006-04-19 15:05:30 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + M /iexploder/htdocs/cssproperties.in + +remove IE dupes: text-overflow and word-wrap +------------------------------------------------------------------------ +r612 | thomas | 2006-04-19 12:48:07 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + M /iexploder/README.txt + M /iexploder/htdocs/config.rb + M /iexploder/htdocs/iexploder.rb + +Add some benchmark/performance info.. set MAX_TAGS default to 96 +------------------------------------------------------------------------ +r611 | thomas | 2006-04-19 10:22:33 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + M /iexploder/htdocs/iexploder.cgi + M /iexploder/htdocs/iexploder.rb + M /iexploder/htdocs/webserver.rb + +Add stop parameter, fix port assignment issue, fix indentation +------------------------------------------------------------------------ +r610 | thomas | 2006-04-19 10:22:06 -0400 (Wed, 19 Apr 2006) | 1 line +Changed paths: + M /iexploder/README.txt + +1.3.0 +------------------------------------------------------------------------ +r609 | thomas | 2006-04-18 22:46:35 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + A /iexploder/testcases/safari/16170_44-Safari-Nightly-420+-2006-r13911-2006-04-18.html + +applet+param Hashmap crash in Safari +------------------------------------------------------------------------ +r608 | thomas | 2006-04-18 22:07:45 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + M /iexploder/htdocs/iexploder.cgi + M /iexploder/htdocs/webserver.rb + +1.3.0 +------------------------------------------------------------------------ +r607 | thomas | 2006-04-18 22:05:47 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + M /iexploder/README.txt + M /iexploder/htdocs/webserver.rb + M /iexploder/tools/osx_last_crash.rb + +commit osx_last_crash minutes->days change, document that you can pass a new port number to the webserver.rb program +------------------------------------------------------------------------ +r606 | thomas | 2006-04-18 22:02:16 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + A /iexploder/testcases/safari/2969_421-Safari-2.0.3_Mac_OS_X-Crash.html + A /iexploder/testcases/safari/5763_181-Safari-Nightly-420+-2006-r13911-2006-04-18.html + +Add more Safari crashes to the testcases list +------------------------------------------------------------------------ +r605 | thomas | 2006-04-18 19:05:46 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + M /iexploder/README.txt + M /iexploder/htdocs/config.rb + M /iexploder/htdocs/iexploder.cgi + M /iexploder/htdocs/iexploder.rb + M /iexploder/htdocs/webserver.rb + +Greatly improve subtests. Not only do we iterate around each tag, but we steadily increase the amount of tags we input as well +------------------------------------------------------------------------ +r604 | thomas | 2006-04-18 17:04:17 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + M /iexploder/README.txt + M /iexploder/htdocs/config.rb + +1.3b1.. also, raise max tags to 48 now that we have fixed subtest bugs +------------------------------------------------------------------------ +r603 | thomas | 2006-04-18 16:59:20 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + M /iexploder/htdocs/iexploder.cgi + M /iexploder/htdocs/iexploder.rb + A /iexploder/htdocs/webserver.rb + +New Webrick based option for standalone hosting +------------------------------------------------------------------------ +r602 | thomas | 2006-04-18 16:18:35 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + A /iexploder/htdocs/config.rb + M /iexploder/htdocs/cssproperties.in + M /iexploder/htdocs/iexploder.cgi + A /iexploder/htdocs/iexploder.rb + +Split iexploder.cgi into iexploder.rb and config.rb +------------------------------------------------------------------------ +r601 | thomas | 2006-04-18 13:36:25 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + M /iexploder/htdocs/cssvalues.in + +Add items from WebKit/WebCore/css/CSSValueKeywords.in +------------------------------------------------------------------------ +r600 | thomas | 2006-04-18 13:32:45 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + A /iexploder/testcases/opera/4750_Opera_8.5.4_Mac_OS_X-Crash.html + +Add odd new crash from Opera 8.5.4 for Mac +------------------------------------------------------------------------ +r599 | thomas | 2006-04-18 13:10:15 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + A /iexploder/testcases/safari/7483_Safari-Nightly-420+-2006-r13911-2006-04-18.html + +Add new Safari test case +------------------------------------------------------------------------ +r598 | thomas | 2006-04-18 12:25:39 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + M /iexploder/LICENSE.txt + M /iexploder/README.txt + M /iexploder/htdocs/htmlattrs.in + M /iexploder/htdocs/htmltags.in + M /iexploder/htdocs/iexploder.cgi + +iExploder 1.3: sync with modern rendering kits +------------------------------------------------------------------------ +r597 | thomas | 2006-04-18 12:25:18 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + A /iexploder/testcases/firefox/354_1-Firefox-1.5.0.1_Solaris-Crash.html + A /iexploder/testcases/firefox/44_9-Firefox-1.5.0.1_Solaris-Crash.html + A /iexploder/testcases/internet_explorer/8386_11-Internet-Explorer-6.0_WinXP-DoS.html (from /iexploder/testcases/safari/8386_11-Internet-Explorer-6.0_WinXP-DoS.html:596) + A /iexploder/testcases/safari/218-Safari-2.0.3_Mac_OS_X-Crash.html + D /iexploder/testcases/safari/8386_11-Internet-Explorer-6.0_WinXP-DoS.html + +New testcases +------------------------------------------------------------------------ +r596 | thomas | 2006-04-18 12:23:48 -0400 (Tue, 18 Apr 2006) | 1 line +Changed paths: + D /iexploder/testcases/119_4-Safari-Nightly-420+-2005-10-21-Crash.html + D /iexploder/testcases/165367_15-FireFox-1.4.1-Crash.html + D /iexploder/testcases/2009-iCab-3.0.1-Mac_OS_X-Crash.html + D /iexploder/testcases/2289-iCab-3.0.1-Crash.html + D /iexploder/testcases/25057-OmniWeb-5.1.1-Crash.html + D /iexploder/testcases/2624-Opera-8.5-Mac_OS_X-Crash.html + D /iexploder/testcases/502701_7-FireFox-1.4.1-Crash.html + D /iexploder/testcases/60253-OmniWeb-5.1.1-Crash.html + D /iexploder/testcases/6134_19-Safari-2.0.1-412.5-Crash.html + D /iexploder/testcases/8386_11-Internet-Explorer-6.0_WinXP-DoS.html + A /iexploder/testcases/firefox + A /iexploder/testcases/firefox/165367_15-Firefox-1.4.1-Crash.html (from /iexploder/testcases/165367_15-FireFox-1.4.1-Crash.html:595) + A /iexploder/testcases/firefox/502701_7-Firefox-1.4.1-Crash.html (from /iexploder/testcases/502701_7-FireFox-1.4.1-Crash.html:595) + A /iexploder/testcases/icab + A /iexploder/testcases/icab/2009-iCab-3.0.1-Mac_OS_X-Crash.html (from /iexploder/testcases/2009-iCab-3.0.1-Mac_OS_X-Crash.html:595) + A /iexploder/testcases/icab/2289-iCab-3.0.1-Crash.html (from /iexploder/testcases/2289-iCab-3.0.1-Crash.html:595) + A /iexploder/testcases/internet_explorer + A /iexploder/testcases/omniweb + A /iexploder/testcases/omniweb/25057-OmniWeb-5.1.1-Crash.html (from /iexploder/testcases/25057-OmniWeb-5.1.1-Crash.html:595) + A /iexploder/testcases/omniweb/60253-OmniWeb-5.1.1-Crash.html (from /iexploder/testcases/60253-OmniWeb-5.1.1-Crash.html:595) + A /iexploder/testcases/opera + A /iexploder/testcases/opera/2624-Opera-8.5-Mac_OS_X-Crash.html (from /iexploder/testcases/2624-Opera-8.5-Mac_OS_X-Crash.html:595) + A /iexploder/testcases/safari + A /iexploder/testcases/safari/119_4-Safari-Nightly-420+-2005-10-21-Crash.html (from /iexploder/testcases/119_4-Safari-Nightly-420+-2005-10-21-Crash.html:595) + A /iexploder/testcases/safari/6134_19-Safari-2.0.1-412.5-Crash.html (from /iexploder/testcases/6134_19-Safari-2.0.1-412.5-Crash.html:595) + A /iexploder/testcases/safari/8386_11-Internet-Explorer-6.0_WinXP-DoS.html (from /iexploder/testcases/8386_11-Internet-Explorer-6.0_WinXP-DoS.html:595) + +Reshuffle testcases +------------------------------------------------------------------------ +r521 | thomas | 2005-11-03 22:01:43 -0500 (Thu, 03 Nov 2005) | 1 line +Changed paths: + A /iexploder/testcases/2289-iCab-3.0.1-Crash.html + A /iexploder/testcases/60253-OmniWeb-5.1.1-Crash.html + +add some test cases +------------------------------------------------------------------------ +r520 | thomas | 2005-11-03 22:01:19 -0500 (Thu, 03 Nov 2005) | 1 line +Changed paths: + M /iexploder/htdocs/iexploder.cgi + +Add some cute tabs +------------------------------------------------------------------------ +r508 | thomas | 2005-10-21 15:34:38 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + A /iexploder/testcases/165367_15-FireFox-1.4.1-Crash.html (from /iexploder/testcases/165367_15-FireFox-1.4.1-Mac_OS_X-Crash.html:505) + D /iexploder/testcases/165367_15-FireFox-1.4.1-Mac_OS_X-Crash.html + +Crash is not OSX specific +------------------------------------------------------------------------ +r507 | thomas | 2005-10-21 14:59:41 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + M /iexploder/README.txt + +Mention the fact that testcases may not be portable across installations +------------------------------------------------------------------------ +r506 | thomas | 2005-10-21 14:45:48 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + M /iexploder/htdocs/index.html + +Fix lookup html code +------------------------------------------------------------------------ +r505 | thomas | 2005-10-21 14:22:10 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + A /iexploder/testcases/165367_15-FireFox-1.4.1-Mac_OS_X-Crash.html + +QuickDraw crash for Mac OS X +------------------------------------------------------------------------ +r504 | thomas | 2005-10-21 14:14:34 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + A /iexploder/testcases/25057-OmniWeb-5.1.1-Crash.html + +New crash +------------------------------------------------------------------------ +r503 | thomas | 2005-10-21 14:06:45 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + A /iexploder/testcases/8386_11-Internet-Explorer-6.0_WinXP-DoS.html + +IE DoS +------------------------------------------------------------------------ +r502 | thomas | 2005-10-21 13:24:02 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + M /iexploder/README.txt + M /iexploder/htdocs/cssvalues.in + M /iexploder/htdocs/iexploder.cgi + M /iexploder/htdocs/index.html + D /iexploder/testcases/100482.html + D /iexploder/testcases/103399-nscssvaluelist.html + A /iexploder/testcases/119_4-Safari-Nightly-420+-2005-10-21-Crash.html + A /iexploder/testcases/2009-iCab-3.0.1-Mac_OS_X-Crash.html + A /iexploder/testcases/2624-Opera-8.5-Mac_OS_X-Crash.html + A /iexploder/testcases/502701_7-FireFox-1.4.1-Crash.html + A /iexploder/testcases/6134_19-Safari-2.0.1-412.5-Crash.html + D /iexploder/testcases/firefox-caption-iframe-table-47179.html + D /iexploder/testcases/firefox-caption-marquee-27473.html + D /iexploder/testcases/firefox-caption-marquee-66937.html + D /iexploder/testcases/firefox-isindex-18149.html + D /iexploder/testcases/firefox-visibility-caption-111895.html + +1.2 Update, mostly documentation and test cases +------------------------------------------------------------------------ +r501 | thomas | 2005-10-21 11:41:39 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + M /iexploder/tools/osx_last_crash.rb + +back to days, filter out synergy +------------------------------------------------------------------------ +r500 | thomas | 2005-10-21 11:25:28 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + M /iexploder/htdocs/cssvalues.in + M /iexploder/htdocs/iexploder.cgi + M /iexploder/tools/lasthit.rb + +1.2: We now use javascript reloads after 1 second in case the meta breaks (IE) +------------------------------------------------------------------------ +r499 | thomas | 2005-10-21 08:51:07 -0400 (Fri, 21 Oct 2005) | 1 line +Changed paths: + M /iexploder/htdocs/iexploder.cgi + +1.1: Fix up our subtest model +------------------------------------------------------------------------ +r498 | thomas | 2005-10-20 21:55:59 -0400 (Thu, 20 Oct 2005) | 1 line +Changed paths: + M /iexploder/htdocs/iexploder.cgi + +Support for subtests, and compatibility with mod_ruby +------------------------------------------------------------------------ +r497 | thomas | 2005-10-20 20:48:59 -0400 (Thu, 20 Oct 2005) | 1 line +Changed paths: + M /iexploder/htdocs/cssproperties.in + M /iexploder/htdocs/cssvalues.in + M /iexploder/htdocs/htmlattrs.in + M /iexploder/htdocs/htmlvalues.in + M /iexploder/htdocs/iexploder.cgi + +update to v1.0 +------------------------------------------------------------------------ +r455 | tstrombe | 2005-02-28 08:13:25 -0500 (Mon, 28 Feb 2005) | 1 line +Changed paths: + A /iexploder + A /iexploder/LICENSE.txt + A /iexploder/README.txt + A /iexploder/htdocs + A /iexploder/htdocs/cssproperties.in + A /iexploder/htdocs/cssvalues.in + A /iexploder/htdocs/htmlattrs.in + A /iexploder/htdocs/htmltags.in + A /iexploder/htdocs/htmlvalues.in + A /iexploder/htdocs/iexploder.cgi + A /iexploder/htdocs/index.html + A /iexploder/testcases + A /iexploder/testcases/100482.html + A /iexploder/testcases/103399-nscssvaluelist.html + A /iexploder/testcases/firefox-caption-iframe-table-47179.html + A /iexploder/testcases/firefox-caption-marquee-27473.html + A /iexploder/testcases/firefox-caption-marquee-66937.html + A /iexploder/testcases/firefox-isindex-18149.html + A /iexploder/testcases/firefox-visibility-caption-111895.html + A /iexploder/tools + A /iexploder/tools/lasthit.rb + A /iexploder/tools/osx_last_crash.rb + +iexploder software +------------------------------------------------------------------------ diff --git a/WebKitTools/iExploder/LICENSE.txt b/WebKitTools/iExploder/LICENSE.txt new file mode 100644 index 0000000..5199718 --- /dev/null +++ b/WebKitTools/iExploder/LICENSE.txt @@ -0,0 +1,20 @@ +# +# Copyright (c) 2005 Thomas Stromberg <thomas%stromberg.org> +# +# This software is provided 'as-is', without any express or implied warranty. +# In no event will the authors be held liable for any damages arising from the +# use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software in a +# product, an acknowledgment in the product documentation would be appreciated +# but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source distribution. diff --git a/WebKitTools/iExploder/README.txt b/WebKitTools/iExploder/README.txt new file mode 100644 index 0000000..a941697 --- /dev/null +++ b/WebKitTools/iExploder/README.txt @@ -0,0 +1,149 @@ +iExploder 1.3.2 +=============== + +Welcome to iExploder. a highly inefficient, but fairly effective web +browser tester. The code still has a lot of work to be done, but it's +definitely usable. Here are some notable features: + +* Tests all common HTML and CSS tags and attributes, as parsed from +the KHTML, WebKit and Mozilla source trees, as well as tags for +Internet Explorer from MSDN. This also includes a few Javascript hooks. +* Numeric, and String overflow and formatting tests +* Sequential and Randomized Test Case Generation +* Test Case Lookups +* Subtest generation + + +Installation (Standalone) +------------------------- +Make sure you have Ruby installed (comes with Mac OS X, most Linux +distributions). See http://www.ruby-lang.org/ if you do not. + +If you do not already have a webserver setup, you can use the server +built into iexploder. Simply go into the htdocs directory and type: + +% ruby webserver.rb + +A webserver will then start on port 2000 with the iexploder form. If +port 2000 is not preferable, you can pass it another port on the command +line: + +% ruby webserver.rb 2001 + +Please note that lasthit.rb does not currently work with the logs output +from this method. I recommend using a seperate instance/port number +for each browser you test simultaneous using this method. + + +Installation (External Webserver) +--------------------------------- +If you wish to use an external webserver (required for lasthit.rb use), +you may do so. IExploder has been tested with apache. + +Copy the contents of the htdocs/ folder to any directory served +by your webserver. Make sure that directory can execute CGI scripts. If +performance seems to be low, please try using mod_ruby. + + +FAQ: +---- +1) Are the tests always the same? + + The test cases should always be the same on a single installation, but not +necessarily on different installations of iExploder. Random generator seeds +may differ between operating systems and platforms. If you alter the tag and +property counts in config.rb, it will change the test cases as well. + + +2) How do I look up the last successful test for a client? + +Use tools/lasthit.rb. When I get a crash, I usually do something like: + + % tail -15000 /var/log/apache2/access_log | ./lasthit.rb + +Letting you know how many tests and what the last test id was for each +client tested. You can then try to repeat the test, or go through the +subtests to see if you can repeat the crash. + + +3) How do subtests work? + +If you see a crash on a particular test, and would like to determine the exact +line that is crashing it, you can use subtests. To do so, go back to the test +submission form, and start the test from the number that a crash was indicated +on. Instead of leaving the "subtest" field blank, set it to 1. This will rotate +through each subtest for a particular test. + +Each subtest will rotate through a tag offset and a number of tags to +garble, which should help you isolate the instance. The number of tags +used doubles each cycle. Here is an idea of how many subtests to expect +based on your $HTML_MAX_TAGS settings: + +tags subtests +---------------- +32 138 +48 236 +64 332 +96 558 +128 782 + +Most of the time you will be able to replicate a crash within the first +$HTML_MAX_TAGS subtests, but sometimes crashes are due to a combination +of corrupted tags. + + +4) How come I can't seem to repeat the crash? + + Many browser crashes are race conditions that are not easy to repeat. Some +crashes only happen when going from test 4 -> test 5 -> test 6. If you can't +repeat the crash through subtests or a lookup of the failing test, try going +back a few tests. + +That said, some crashes are due to race conditions that are very difficult +to replicate. + + +5) Why did you write this? + + I wanted to make sure that FireFox had as many bugs fixed in it as possible +before the 1.0 release. After 1.0 came out, I kept improving it. + + +6) Why does Internet Explorer run the tests so slowly? + + <META> refresh tags are very fragile in Internet Explorer, and can be easily +be rendered useless by other tags on the page. If this happens, a javascript +refresh will execute after a 1 second delay. + + + +7) How do I change the number of tags iExploder tests per page? + +See config.rb. I personally recommend 32-128 HTML tags per page. While this +seems to be a lot to go through when designing a test case, that's why the +subtest engine was made. Different web browsers will have different +performance characteristics when it comes to the number of tags per page. + +Here are the results with Firefox 2.0b1 (Bon Echo) and the iExploder +built-in webserver running tests 1-250. + +tags seconds pages/second tags/second +----------------------------------------- +32 60 4.0 131 +48 85 2.9 141 +64 95 2.6 168 +96 120 2.1 200 *DEFAULT* +128 140 1.8 228 +196 228 1.1 210 +256 308 0.8 207 + +If you find pages/second to be more important than tags/second, I would +change $HTML_MAX_TAGS to 32. Do keep in mind that large tag counts mean +longer subtest generation periods. + + +8) What other performance enhancements can I make? + +* Before using iExploder, reset your browser history +* Minimize your browser while iExploder is running +* If using Apache, make use of mod_ruby diff --git a/WebKitTools/iExploder/htdocs/config.rb b/WebKitTools/iExploder/htdocs/config.rb new file mode 100644 index 0000000..d9e7e1b --- /dev/null +++ b/WebKitTools/iExploder/htdocs/config.rb @@ -0,0 +1,6 @@ +# Configuration for iExploder.. not generally tuned. + +$HTML_MAX_TAGS = 96; +$HTML_MAX_ATTRS = 4; +$CSS_MAX_PROPS = 5; + diff --git a/WebKitTools/iExploder/htdocs/cssproperties.in b/WebKitTools/iExploder/htdocs/cssproperties.in new file mode 100644 index 0000000..2eb9e7a --- /dev/null +++ b/WebKitTools/iExploder/htdocs/cssproperties.in @@ -0,0 +1,348 @@ +# From WebKit svn r24249 (WebCore/css/CSSPropertyNames.in) +-webkit-appearance +-webkit-background-clip +-webkit-background-composite +-webkit-background-origin +-webkit-background-size +-webkit-binding +-webkit-border-bottom-left-radius +-webkit-border-bottom-right-radius +-webkit-border-fit +-webkit-border-horizontal-spacing +-webkit-border-image +-webkit-border-radius +-webkit-border-top-left-radius +-webkit-border-top-right-radius +-webkit-border-vertical-spacing +-webkit-box-align +-webkit-box-direction +-webkit-box-flex +-webkit-box-flex-group +-webkit-box-lines +-webkit-box-ordinal-group +-webkit-box-orient +-webkit-box-pack +-webkit-box-shadow +-webkit-box-sizing +-webkit-column-break-after +-webkit-column-break-before +-webkit-column-break-inside +-webkit-column-count +-webkit-column-gap +-webkit-column-rule +-webkit-column-rule-color +-webkit-column-rule-style +-webkit-column-rule-width +-webkit-column-width +-webkit-columns +-webkit-dashboard-region +-webkit-font-size-delta +-webkit-highlight +-webkit-line-break +-webkit-line-clamp +-webkit-margin-bottom-collapse +-webkit-margin-collapse +-webkit-margin-start +-webkit-margin-top-collapse +-webkit-marquee +-webkit-marquee-direction +-webkit-marquee-increment +-webkit-marquee-repetition +-webkit-marquee-speed +-webkit-marquee-style +-webkit-match-nearest-mail-blockquote-color +-webkit-nbsp-mode +-webkit-padding-start +-webkit-rtl-ordering +-webkit-text-decorations-in-effect +-webkit-text-fill-color +-webkit-text-security +-webkit-text-size-adjust +-webkit-text-stroke +-webkit-text-stroke-color +-webkit-text-stroke-width +-webkit-user-drag +-webkit-user-modify +-webkit-user-select +background +background-attachment +background-color +background-image +background-position +background-position-x +background-position-y +background-repeat +border +border-bottom +border-bottom-color +border-bottom-style +border-bottom-width +border-collapse +border-color +border-left +border-left-color +border-left-style +border-left-width +border-right +border-right-color +border-right-style +border-right-width +border-spacing +border-style +border-top +border-top-color +border-top-style +border-top-width +border-width +bottom +caption-side +clear +clip +color +content +counter-increment +counter-reset +cursor +direction +display +empty-cells +float +font +font-family +font-size +font-stretch +font-style +font-variant +font-weight +height +left +letter-spacing +line-height +list-style +list-style-image +list-style-position +list-style-type +margin +margin-bottom +margin-left +margin-right +margin-top +max-height +max-width +min-height +min-width +opacity +orphans +outline +outline-color +outline-offset +outline-style +outline-width +overflow +overflow-x +overflow-y +padding +padding-bottom +padding-left +padding-right +padding-top +page +page-break-after +page-break-before +page-break-inside +position +quotes +resize +right +scrollbar-3dlight-color +scrollbar-arrow-color +scrollbar-darkshadow-color +scrollbar-face-color +scrollbar-highlight-color +scrollbar-shadow-color +scrollbar-track-color +size +table-layout +text-align +text-decoration +text-indent +text-line-through +text-line-through-color +text-line-through-mode +text-line-through-style +text-line-through-width +text-overflow +text-overline +text-overline-color +text-overline-mode +text-overline-style +text-overline-width +text-shadow +text-transform +text-underline +text-underline-color +text-underline-mode +text-underline-style +text-underline-width +top +unicode-bidi +vertical-align +visibility +white-space +widows +width +word-break +word-spacing +word-wrap +z-index + +# CSS3 properties - http://www.css3.info/preview/ +background-clip +background-origin +border-image +border-radius +box-shadow +box-sizing +column-count +column-gap +column-min-width +column-rule +column-rule-color +column-rule-style +column-rule-width +column-space-distribution +column-span +column-width +column-width-policy + +# All of the following are from khtml's cssproperties.in as of 19oct2004, but are no longer in WebKit +-khtml-border-horizontal-spacing +-khtml-border-vertical-spacing +-khtml-flow-mode +-khtml-marquee +-khtml-marquee-direction +-khtml-marquee-increment +-khtml-marquee-repetition +-khtml-marquee-speed +-khtml-marquee-style +-khtml-text-decoration-color +-khtml-user-input +scrollbar-base-color + +# Internet Explorer 6.0 - http://msdn.microsoft.com/workshop/author/css/reference/attributes.asp +filter:progid: +filter: +ime-mode +layout-flow +layout-grid +layout-grid-char +layout-grid-line +layout-grid-mode +layout-grid-type +line-break +overflow-x +overflow-y +pagebreakafter +pagebreakbefore +ruby-align +ruby-overhang +ruby-position +text-autospace +text-justify +text-kashida-space +text-underline-position +word-break +writing-mode +zoom + +# from http://msdn.microsoft.com/library/default.asp?url=/workshop/author/filter/reference/reference.asp +filter:progid:DXImageTransform.Microsoft.AlphaImageLoader( +filter:progid:DXImageTransform.Microsoft.Blur( +filter:progid:DXImageTransform.Microsoft.MotionBlur( +filter:progid:DXImageTransform.Microsoft.Gradient( +filter:progid:DXImageTransform.Microsoft.Pixelate( + +# From Mozilla Firefox CVS on 2006-04-15 (layout/style/nsCSSPropList.h) +# grep "^CSS_PROP" nsCSSPropList.h | grep -v "_SVG" |cut -d, -f1 | cut -d\( -f2 | sort +++ /tmp/moz Tue Apr 18 13:45:30 2006 +-moz-appearance +-moz-background-clip +-moz-background-inline-policy +-moz-background-origin +-moz-binding +-moz-border-bottom-colors +-moz-border-left-colors +-moz-border-radius +-moz-border-radius-bottomleft +-moz-border-radius-bottomright +-moz-border-radius-topleft +-moz-border-radius-topright +-moz-border-right-colors +-moz-border-top-colors +-moz-box-align +-moz-box-direction +-moz-box-flex +-moz-box-ordinal-group +-moz-box-orient +-moz-box-pack +-moz-box-sizing +-moz-column-count +-moz-column-gap +-moz-column-width +-moz-float-edge +-moz-force-broken-image-icon +-moz-image-region +-moz-margin-end +-moz-margin-start +-moz-outline-radius +-moz-outline-radius-bottomleft +-moz-outline-radius-bottomright +-moz-outline-radius-topleft +-moz-outline-radius-topright +-moz-padding-end +-moz-padding-start +-moz-user-focus +-moz-user-input +-moz-user-modify +-moz-user-select +-x-background-x-position +-x-background-y-position +azimuth +cue +cue-after +cue-before +elevation +font-size-adjust +margin-end-value +margin-left-ltr-source +margin-left-rtl-source +margin-left-value +margin-right-ltr-source +margin-right-rtl-source +margin-right-value +margin-start-value +marker +marker-offset +marks +padding-end-value +padding-left-ltr-source +padding-left-rtl-source +padding-left-value +padding-right-ltr-source +padding-right-rtl-source +padding-right-value +padding-start-value +pause +pause-after +pause-before +pitch +pitch-range +richness +speak +speak-header +speak-numeral +speak-punctuation +speech-rate +stress +voice-family +volume diff --git a/WebKitTools/iExploder/htdocs/cssvalues.in b/WebKitTools/iExploder/htdocs/cssvalues.in new file mode 100644 index 0000000..c19f78f --- /dev/null +++ b/WebKitTools/iExploder/htdocs/cssvalues.in @@ -0,0 +1,339 @@ +"Trebuchet MS",Verdana, Arial, Helvetica, sans-serif +#339933 !important !important !important +#9999999999999999999999999999999999999999999 +-5, -5, -5 +-9999% +-999999999999999999999999999% +-999999999999999999999999999em +-999999999999999999999999999px +-9999em +-9999px +-webkit-activelink +-webkit-auto +-webkit-baseline-middle +-webkit-body +-webkit-box +-webkit-center +-webkit-focus-ring-color +-webkit-inline-box +-webkit-left +-webkit-link +-webkit-marquee +-webkit-nowrap +-webkit-overlay +-webkit-right +-webkit-text +-webkit-xxx-large +0 +0 auto +0 fixed +2% +90000000000000000000000000000000000000000000% +9999999999999999999999 +99999999999999999999999999999999999999 auto +99999999999999999999999999999999999999999999px +999999px solid #fff +above +absolute +activeborder +activecaption +after-white-space +ahead +alternate +always +appworkspace +aqua +armenian +attr("ATTRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") +auto +avoid +background +backwards +baseline +below +bidi-override +black +blink +block +block clear +block width +block-axis +blue +bold +bolder +border +border-box +both +bottom +break-word +button +button-bevel +buttonface +buttonhighlight +buttonshadow +buttontext +capitalize +caption +captiontext +caret +center +checkbox +circle +cjk-ideographic +clip +clip:rect(-0px -2000000px -200000px -0px) +clip:rect(0px 2000000px 200000px 0px) +close-quote +collapse +compact +condensed +content +content-box +continuous +crop +cross +crosshair +cursive +dashed +decimal +decimal-leading-zero +default +disc +discard +dot-dash +dot-dot-dash +dotted +double +down +e-resize +element +ellipsis +embed +end +expanded +extra-condensed +extra-expanded +fantasy +fast +fixed +forwards +fuchsia +georgian +gray +graytext +green +grey +groove +hand +hebrew +help +helvetica, arial, Courier New, Courier, Mono, Blah, Blah, Blah +hidden +hide +higher +highlight +highlighttext +hiragana +hiragana-iroha +horizontal +icon +ignore +inactiveborder +inactivecaption +inactivecaptiontext +infinite +infobackground +infotext +inherit +initial +inline +inline-axis +inline-block +inline-table +inset +inside +intrinsic +invert +italic +justify +katakana +katakana-iroha +landscape +large +larger +left +level +lighter +lime +line-through +list-item +listbox +listitem +logical +loud +lower +lower-alpha +lower-greek +lower-latin +lower-roman +lowercase +ltr +marker +maroon +match +medium +menu +menulist +menulist-button +menulist-text +menulist-textfield +menutext +message-box +middle +min-intrinsic +mix +monospace +move +multiple +n-resize +narrower +navy +ne-resize +no-close +no-close-quote +no-open-quote +no-repeat +none +normal +normal !important +nowrap +nw-resize +oblique +olive +once +open-quote +orange +outset +outside +overline +padding +pointer +portrait +pre +pre-line +pre-wrap +purple +push-button +radio +read-only +read-write +read-write-plaintext-only +red +relative +repeat +repeat-x +repeat-y +reverse +rgb(9999999999, 999999999, 9999999999999) +ridge +right +round +rtl +run-in +s-resize +sans-serif +scroll +scrollbar +scrollbarbutton-down +scrollbarbutton-left +scrollbarbutton-right +scrollbarbutton-up +scrollbargripper-horizontal +scrollbargripper-vertical +scrollbarthumb-horizontal +scrollbarthumb-vertical +scrollbartrack-horizontal +scrollbartrack-vertical +se-resize +searchfield +searchfield-close +searchfield-results +semi-condensed +semi-expanded +separate +serif +show +silver +single +skip-white-space +slide +slider-horizontal +slider-vertical +sliderthumb-horizontal +sliderthumb-vertical +slow +small +small-caps +small-caption +smaller +solid +space +square +square-button +start +static +status-bar +stretch +sub +super +sw-resize +table +table-caption +table-cell +table-column +table-column-group +table-footer-group +table-header-group +table-row +table-row-group +teal +text +text-bottom +text-top +textfield +thick +thick dashed yellow +thick dotted blue +thin +threeddarkshadow +threedface +threedhighlight +threedlightshadow +threedshadow +top +transparent +ultra-condensed +ultra-expanded +underline +unfurl +up +upper-alpha +upper-latin +upper-roman +uppercase +vertical +visible +visual +w-resize +wait +wave +white +wider +window +windowframe +windowtext +x-large +x-small +xx-large +xx-small +yellow diff --git a/WebKitTools/iExploder/htdocs/htmlattrs.in b/WebKitTools/iExploder/htdocs/htmlattrs.in new file mode 100644 index 0000000..ad92384 --- /dev/null +++ b/WebKitTools/iExploder/htdocs/htmlattrs.in @@ -0,0 +1,259 @@ +# the following come from WebCore 2006-04-15 (WebKit/WebCore/html/HTMLNames.h) + +abbr +accept +accept_charset +accesskey +action +align +alink +alt +archive +autocomplete +autosave +axis +background +behavior +bgcolor +bgproperties +border +bordercolor +cellborder +cellpadding +cellspacing +challenge +char +charoff +charset +checked +cite +class +classid +clear +code +codebase +codetype +color +cols +colspan +compact +composite +content +contenteditable +coords +data +datetime +declare +defer +dir +direction +disabled +enctype +face +for +frame +frameborder +headers +height +hidden +href +hreflang +hspace +http_equiv +id +incremental +ismap +keytype +label +lang +language +left +leftmargin +link +longdesc +loop +marginheight +marginwidth +max +maxlength +mayscript +media +method +min +multiple +name +nohref +noresize +noshade +nowrap +object +onabort +onbeforecopy +onbeforecut +onbeforepaste +onbeforeunload +onblur +onchange +onclick +oncontextmenu +oncopy +oncut +ondblclick +ondrag +ondragend +ondragenter +ondragleave +ondragover +ondragstart +ondrop +onerror +onfocus +oninput +onkeydown +onkeypress +onkeyup +onload +onmousedown +onmousemove +onmouseout +onmouseover +onmouseup +onmousewheel +onpaste +onreset +onresize +onscroll +onsearch +onselect +onselectstart +onsubmit +onunload +pagex +pagey +placeholder +plain +pluginpage +pluginspage +pluginurl +precision +profile +prompt +readonly +rel +results +rev +rows +rowspan +rules +scheme +scope +scrollamount +scrolldelay +scrolling +selected +shape +size +span +src +standby +start +style +summary +tabindex +tableborder +target +text +title +top +topmargin +truespeed +type +usemap +valign +value +valuetype +version +vlink +vspace +width +wrap + +# was in khtml in 2004, but is no longer in WebCore +accept-charset +html +http-equiv +nosave +oversrc +unknown +visibility +z-index + +# From Mozilla CVS 2006-04-15 (mozilla/layout/style/xbl-marquee) +bounce +finish +onbounce +onfinish +onstart + + +# IE specific, from msdn.microsoft.com/workshop/author/dhtml/reference/properties +acceptcharset +allowtransparency +balance +choff +datafld +dataformatas +datapagesize +datasrc +dynsrc +framespacing +galleryimg +hidefocus +methods +scroll +units +urn +volume + +# From Mozilla CVS 2006-04-15 (mozilla/content/base/src/nsGkAtomList.h) +# To get these, I used: +# ggrep -r "Get.*Attr" * | perl -ne 'if (/nsHTMLAtoms::(\w+)/) { \ +# system("grep \\($1, content/base/src/nsGkAtomList.h"); }' \ +# | cut -d\" -f2 | sort -u +autocheck +base +bottommargin +event +font-weight +handler +layout +observer +ping +point-size +rightmargin +variable + +# events from Mozilla CVS 2006-04-15 (mozilla/content/base/src/nsGkAtomList.h) +# cat nsGkAtomList.h | grep GK_ATOM | cut -d\" -f2 | egrep "^on[a-z]+" +onzoom +onunderflow +ontext +onset +onpopupshown +onpopupshowing +onpopuphiding +onpopuphidden +onpaint +onpageshow +onpagehide +onoverflowchanged +onoverflow +onget +ondraggesture +ondragexit +ondragdrop +oncompositionstart +oncompositionend +oncommandupdate +oncommand +onclose diff --git a/WebKitTools/iExploder/htdocs/htmltags.in b/WebKitTools/iExploder/htdocs/htmltags.in new file mode 100644 index 0000000..acac8f3 --- /dev/null +++ b/WebKitTools/iExploder/htdocs/htmltags.in @@ -0,0 +1,128 @@ +# The following come from khtml's htmltags.in from 19oct2004 +# From WebCore svn tree, 2006-04-18 (WebKit/WebCore/html/HTMLNames.h) + +a +abbr +acronym +address +applet +area +b +base +basefont +bdo +big +blockquote +body +br +button +canvas +caption +center +cite +code +col +colgroup +dd +del +dfn +dir +div +dl +dt +em +embed +fieldset +font +form +frame +frameset +h1 +h2 +h3 +h4 +h5 +h6 +head +hr +html +i +iframe +image +img +input +ins +isindex +kbd +keygen +label +layer +legend +li +link +listing +map +marquee +menu +meta +nobr +noembed +noframes +nolayer +noscript +object +ol +optgroup +option +p +param +plaintext +pre +q +s +samp +script +select +small +span +strike +strong +style +sub +sup +table +tbody +td +textarea +tfoot +th +thead +title +tr +tt +u +ul +var +wbr +xmp + +# This was in khtml in 10-2004 +ilayer + +# Additions from Mozilla CVS, 2006-04-18. +# mozilla/parser/htmlparser/public/nsHTMLTagList.h +bgsound +blink +multicol +spacer + +# The following tags used to be in Mozilla in 10-2004, now removed +counter +endnote +parsererror +server +sound +sourcetext + +# From Internet Explorer - http://msdn.microsoft.com/workshop/author/html/reference/elements.asp +xml diff --git a/WebKitTools/iExploder/htdocs/htmlvalues.in b/WebKitTools/iExploder/htdocs/htmlvalues.in new file mode 100644 index 0000000..d54984f --- /dev/null +++ b/WebKitTools/iExploder/htdocs/htmlvalues.in @@ -0,0 +1,35 @@ +# Many of the following are from mangleme.cgi.c's make_up_value() function +# +* +_blank +_parent +_self +_top +about: +about:plugins +file: +http: +jar: +javascript: +left +top +%n%n%n%n%n +ftp: +right +wysiwyg: +bottom +none +ldap: +%i %i +999999999,9999999,999999999,9999999,999999999,9999999,999999999,9999999,9 +999999999,9999999,9 +999999999,9999999 +true +false +_SEARCH +javascript +off +on +vbscript +password +image diff --git a/WebKitTools/iExploder/htdocs/iexploder.cgi b/WebKitTools/iExploder/htdocs/iexploder.cgi new file mode 100755 index 0000000..89e099c --- /dev/null +++ b/WebKitTools/iExploder/htdocs/iexploder.cgi @@ -0,0 +1,45 @@ +#!/usr/bin/ruby +# iExploder - Generates bad HTML files to perform QA for web browsers. +# Developed for the Mozilla Foundation. +##################### +# +# Copyright (c) 2006 Thomas Stromberg <thomas%stromberg.org> +# +# This software is provided 'as-is', without any express or implied warranty. +# In no event will the authors be held liable for any damages arising from the +# use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software in a +# product, an acknowledgment in the product documentation would be appreciated +# but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source distribution. + +require 'cgi'; +require 'iexploder'; +require 'config'; + +### THE INTERACTION ################################## +ie = IExploder.new($HTML_MAX_TAGS, $HTML_MAX_ATTRS, $CSS_MAX_PROPS) +ie.readTagFiles() + +cgi = CGI.new("html4"); +ie.url=ENV['SCRIPT_NAME'] || '?' +ie.test_num = cgi.params['test'][0].to_i +ie.subtest_num = cgi.params['subtest'][0].to_i || 0 +ie.random_mode = cgi.params['random'][0] +ie.lookup_mode = cgi.params['lookup'][0] +ie.stop_num = cgi.params['stop'][0].to_i || 0 +ie.setRandomSeed + +cgi.out('type' => 'text/html') do + ie.buildPage() +end diff --git a/WebKitTools/iExploder/htdocs/iexploder.rb b/WebKitTools/iExploder/htdocs/iexploder.rb new file mode 100644 index 0000000..eee3e38 --- /dev/null +++ b/WebKitTools/iExploder/htdocs/iexploder.rb @@ -0,0 +1,337 @@ +# iExploder - Generates bad HTML files to perform QA for web browsers. +# Developed for the Mozilla Foundation. +##################### +# +# Copyright (c) 2006 Thomas Stromberg <thomas%stromberg.org> +# +# This software is provided 'as-is', without any express or implied warranty. +# In no event will the authors be held liable for any damages arising from the +# use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software in a +# product, an acknowledgment in the product documentation would be appreciated +# but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source distribution. + +$VERSION="1.3.2" + +class IExploder + attr_accessor :test_num, :subtest_num, :lookup_mode, :random_mode, :url + attr_accessor :offset, :lines, :stop_num + + def initialize(max_tags, max_attrs, max_props) + @htmlMaxTags = max_tags + @htmlMaxAttrs = max_attrs + @cssMaxProps = max_props + @mangledTagTotal = 0 + @stop_num = 0 + end + + def setRandomSeed + if @test_num > 0 + srand(@test_num) + else + srand + end + end + + + def readTagFiles + # These if statements are so that mod_ruby doesn't have to reload the files + # each time + + if (! @cssTags) + @cssTags = readTagFile('cssproperties.in'); + end + + if (! @htmlTags) + @htmlTags = readTagFile('htmltags.in'); + end + if (! @htmlAttr) + @htmlAttr = readTagFile('htmlattrs.in'); + end + + if (! @htmlValues) + @htmlValues = readTagFile('htmlvalues.in'); + end + + if (! @cssValues) + @cssValues = readTagFile('cssvalues.in'); + end + + end + + + def readTagFile(filename) + list = Array.new + File.new(filename).readlines.each { |line| + line.chop! + + # Don't include comments. + if (line !~ /^# /) && (line.length > 0) + list << line + end + } + return list + end + + # based on make_up_value, essentially. + def inventValue + value = rand(19); + case value + when 1..3 then return (@htmlValues[rand(@htmlValues.length)]) + when 4..5 then return (@htmlValues[rand(@htmlValues.length)] + inventValue()) + when 6 then return (@htmlValues[rand(@htmlValues.length)] + "//" + inventValue()) + when 7 then return '' + # this may return negative argument? + when 8..10 then return rand(255).chr * (rand(256)+8) + when 11 then return rand(255).chr * (rand(2048)+8) + when 12 then return "#" + rand(999999).to_s + when 13 then return rand(999999).to_s + "%" + when 14..15 then return "&" + rand(999999).to_s + ";" + # filters + when 16 then + return inventValue() + "=" + inventValue() + + # this my return undefined method + for nil:NilClass + when 17 then return inventValue() + "," + inventValue() + else + if rand(5) > 3 + return "-" + rand(999999).to_s + else + return rand(999999).to_s + end + end + end + + # based on make_up_value, essentially. + def inventCssValue(tag) + value = rand(23); + case value + when 1..10 then return @cssValues[rand(@cssValues.length)] + when 11 then return '' + when 12 then return rand(255).chr * (rand(8192)+8) + when 13 + length = rand(1024) + 8 + return (rand(255).chr * length) + " " + (rand(255).chr * length) + " " + (rand(255).chr * length) + when 14 then return (rand(255).chr * (rand(1024)+3)) + "px" + when 15 then return (rand(255).chr * (rand(1024)+3)) + "em" + when 16 then return "url(" + inventValue() + ")" + when 17..18 then return "#" + rand(999999999).to_s + when 19 then return "-" + rand(99999999).to_s + else return rand(99999999).to_s; + end + end + + + def mangleTag(tag) + @mangledTagTotal += 1 + out = '' + + # 20% chance of closing a tag instead of opening it. This + # still counts against @mangledTagTotal, however. + if rand(10) > 8 + out = "</" + tag + ">" + return out + end + + # we're opening it. + out = "<" + tag + + # forgot the space between the tag and the attributes + if rand(15) > 1 + out << ' ' + end + + attrNum = rand(@htmlMaxAttrs) + 1 + + 1.upto(attrNum) { + attr = @htmlAttr[rand(@htmlAttr.length)] + + out << attr + + # 7.5% of the time we skip the = sign. Don't prefix it + # if the attribute ends with a ( however. + + + if rand(15) > 1 + out << '=' + end + + # sometimes quote it, sometimes not. I doubt the importance + # of this test, but mangleme-1.2 added it, and adding more + # random-ness never hurt anything but time. I'll do it less often. + quote = rand(2) + if (quote > 1) + out << "\"" + end + + out << inventValue() + + # end the quote when you are done + if (quote > 1) + out << "\" " + end + + # 5% chance we skip the space at the end of the name + if rand(20) > 1 + out << ' ' + end + + } + + # CSS styles! + if rand(4) > 1 + out << " style=\"" + 1.upto(rand(@cssMaxProps)+1) { + out << @cssTags[rand(@cssTags.length)] + + # very small chance we let the tag run on. + if rand(50) > 1 + out << ": " + end + + out << inventCssValue(tag) + # we almost always put the ; there. + if rand(50) > 1 + out << '; ' + end + } + out << "\"" + end + + out << ">\n" + + # support our local troops! + if (@subtest_num > 0) && filterSubTest() + if tag =~ /html|body|head/ + return '<' + tag + '>' + else + return "<x-#@mangledTagTotal>\n" + end + else + return out + end + end + #end + + def filterSubTest() + result = 1 + if (@mangledTagTotal >= @offset) && (@mangledTagTotal < (@offset + @lines)) + result = nil + end + return result + end + + def nextTestNum() + if random_mode + n = rand(99999999) + else + if @test_num + n = @test_num + 1 + else + n = 1 + end + end + return n + end + + # If we are at line 30 with 8 extra lines, there is no point to try line 31 + # with 8 lines as well.. skip back to 1 and bump up the line count. + def nextSubTestNum() + if (@offset + @lines) > @htmlMaxTags + nextNum = ((@lines * 2 -1)) * @htmlMaxTags + else + nextNum = @subtest_num + 1 + end + return nextNum + end + + + def buildPage + if (! @test_num) || (@test_num < 1) + @test_num = 1 + end + next_num=nextTestNum() + @lines = @subtest_num.div(@htmlMaxTags) + 1 + @offset = @subtest_num.modulo(@htmlMaxTags) + + # building the HTML + bodyText = mangleTag('html') + bodyText << "\n<head>\n" + + # Only do redirects if lookup=1 has not been specified. + if (! @lookup_mode) && (@lines <= @htmlMaxTags) && (@stop_num != @test_num) + newpage = @url + "?" + if @subtest_num > 0 + newpage << "test=" << @test_num.to_s << "&subtest=" << nextSubTestNum().to_s + else + newpage << "test=" << next_num.to_s + end + + if @random_mode + newpage << "&random=1" + end + + if @stop_num > 0 + newpage << "&stop=" << @stop_num.to_s + end + + bodyText << "\t<META HTTP-EQUIV=\"Refresh\" content=\"0;URL=#{newpage}\">\n" + # use both techniques, because you never know how you might be corrupting yourself. + bodyText << "\t<script language=\"javascript\">setTimeout('window.location=\"#{newpage}\"', 1000);</script>\n" + end + + bodyText << "\t" << mangleTag('meta') + bodyText << "\t" << mangleTag('meta') + bodyText << "\t" << mangleTag('link') + + bodyText << "\t<title>[#@test_num] iExploder #{$VERSION} - #{inventValue()}</title>\n" + bodyText << "</head>\n\n" + + # What tags will we be messing with ###################### + tagList = [ 'body'] + + # we already have 5 tags? + 1.upto(@htmlMaxTags - 5 ) { tagList << @htmlTags[rand(@htmlTags.length)] } + + tagList.each { |tag| + bodyText << mangleTag(tag) + bodyText << inventValue() + "\n" + } + bodyText << "</body>\n</html>" + end +end + + + +if $0 == __FILE__ + max=ARGV[0].to_i + puts "testing #{max} tags" + test = IExploder.new(max, 5, 5) + test.readTagFiles() + test.test_num=1 + test.subtest_num=1 + counter=0 + test.lines=0 + + while test.lines < max + test.lines = test.subtest_num.div(max) + 1 + test.offset = test.subtest_num.modulo(max) + test.subtest_num=test.nextSubTestNum + counter = counter + 1 + puts "[#{counter}] subtest #{test.subtest_num} is #{test.lines} lines with #{test.offset} offset" + end + + puts "for #{max} tests, you will have #{counter} iterations until #{test.subtest_num}" +end + diff --git a/WebKitTools/iExploder/htdocs/index.html b/WebKitTools/iExploder/htdocs/index.html new file mode 100644 index 0000000..849bc6b --- /dev/null +++ b/WebKitTools/iExploder/htdocs/index.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + <title>iExploder 1.3.2</title> +</head> +<body> +<h2>iExploder: Web Browser Quality Assurance Tester</h2> +<small>Written by <a href="http://toadstool.se/">Thomas Strömberg</a> for the +<a href="http://www.mozilla.org/firefox/">Mozilla FireFox</a> project</small> + + +<ul> + <li><a href="iexploder.cgi">Start test sequence from the beginning!</a></li> + <li><a href="iexploder.cgi?random=1">Start test sequence in random</a></li> + <li>Start testing from a test number: + <form method="get" action="iexploder.cgi" name="test"> + Test: <input size="9" name="test" value="1"> Subtest: <input size="2" name="subtest" value=""> + <input value="Start" type="submit"> + </form> + </li> + + <li>Lookup a single test number: + <form method="get" action="iexploder.cgi" name="test"> + <input type="hidden" name="lookup" value="1"> + Test: <input size="9" name="test" value="1"> Subtest: <input size="2" name="subtest" value=""> + <input value="Lookup" type="submit"></form> + </li> +</ul> + +If your browser crashes, please contact thomas%stromberg.org! + +</body> +</html> + diff --git a/WebKitTools/iExploder/htdocs/webserver.rb b/WebKitTools/iExploder/htdocs/webserver.rb new file mode 100755 index 0000000..5176172 --- /dev/null +++ b/WebKitTools/iExploder/htdocs/webserver.rb @@ -0,0 +1,75 @@ +#!/usr/bin/ruby +# iExploder - Generates bad HTML files to perform QA for web browsers. +# Developed for the Mozilla Foundation. +##################### +# +# Copyright (c) 2006 Thomas Stromberg <thomas%stromberg.org> +# +# This software is provided 'as-is', without any express or implied warranty. +# In no event will the authors be held liable for any damages arising from the +# use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software in a +# product, an acknowledgment in the product documentation would be appreciated +# but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source distribution. + +require 'webrick' +require 'iexploder'; +require 'config'; + +include WEBrick +### THE INTERACTION ################################## +$ie_preload = IExploder.new($HTML_MAX_TAGS, $HTML_MAX_ATTRS, $CSS_MAX_PROPS) +$ie_preload.readTagFiles() +$ie_preload.url='/iexploder.cgi' + +if ARGV[0] + port = ARGV[0].to_i +else + port = 2000 +end + +puts "* iExploder #{$VERSION} will be available at http://localhost:#{port}" +puts "* Max Tags: #$HTML_MAX_TAGS Max Attrs: #$HTML_MAX_ATTRS Max Props: #$CSS_MAX_PROPS" +puts + +s = HTTPServer.new( :Port => port ) +class IEServlet < HTTPServlet::AbstractServlet + def do_GET(req, res) + ie = $ie_preload.dup + ie.test_num = req.query['test'].to_i + ie.subtest_num = req.query['subtest'].to_i || 0 + ie.random_mode = req.query['random'] + ie.lookup_mode = req.query['lookup'] + ie.stop_num = req.query['stop'].to_i + ie.setRandomSeed + + res['Content-Type'] = 'text/html' + res.body = ie.buildPage() + end +end + +class IEForm < HTTPServlet::AbstractServlet + def do_GET(req, res) + res['Content-Type'] = 'text/html' + res.body = File.open("index.html").readlines.join("\n") + end +end + + + +s.mount("/iexploder.cgi", IEServlet) +s.mount("/", IEForm) +trap("INT") { s.shutdown } + +s.start diff --git a/WebKitTools/iExploder/tools/lasthit.rb b/WebKitTools/iExploder/tools/lasthit.rb new file mode 100755 index 0000000..b569deb --- /dev/null +++ b/WebKitTools/iExploder/tools/lasthit.rb @@ -0,0 +1,53 @@ +#!/usr/bin/ruby +# lasthit, part of iExploder +# +# Shows statistics about recent agents that have tested with iExploder. +# It takes all or part of an apache logfile via stdin, and outputs a list +# of all the agents who tested within that section, what their last test +# was, and how many tests they have done. + +# The usefulness is finding out where a browser crashed. + + +hostHash = Hash.new + +if (ARGV[0]) + file = File.open(ARGV[0]) +else + file = $stdin +end + +file.readlines.each { |line| + if (line =~ /^(.*?) .*iexploder.*?test=(\d+).* HTTP.* \"(.*?)\"$/) + host = $1 + testnum = $2 + agent = $3 + if (! hostHash[host]) + hostHash[host] = Hash.new + end + if (! hostHash[host][agent]) + hostHash[host][agent] = Hash.new + hostHash[host][agent]['total'] = 0 + end + + hostHash[host][agent]['last'] = testnum + if line =~ /subtest=(\d+)/ + hostHash[host][agent]['subtest'] = $1 + else + hostHash[host][agent]['subtest'] = '' + end + hostHash[host][agent]['total'] = hostHash[host][agent]['total'] + 1 + end +} + +printf("%14.14s | %8.8s | %3.3s | %8.8s | %s\n", + "IP", "Test", "SubTest", "Total", "Agent") +puts "---------------------------------------------------------------------------" +hostHash.each_key { |host| + + hostHash[host].each_key { |agent| + printf("%14.14s | %8.8s | %3.3s | %8.8s | %s\n", + host, hostHash[host][agent]['last'], hostHash[host][agent]['subtest'], hostHash[host][agent]['total'], agent); + } +} + diff --git a/WebKitTools/iExploder/tools/osx_last_crash.rb b/WebKitTools/iExploder/tools/osx_last_crash.rb new file mode 100755 index 0000000..5b62c6d --- /dev/null +++ b/WebKitTools/iExploder/tools/osx_last_crash.rb @@ -0,0 +1,48 @@ +#!/usr/bin/ruby +# Gives you information about the most recent crash for each application +# that has crashed within the last 2 days + +$LogDir=ENV['HOME'] + '/Library/Logs/CrashReporter' +$Days=1 +$StackCount=5 + +files=`find #$LogDir -mtime -#$Days -type f | grep -v synergy` +files.each { |filename| + filename.chop! + record = 0 + date='' + stackTrace = [] + + File.open(filename).readlines.each { |line| + #puts line + + if line =~ /^Date.*(200.*)/ + date = $1 + end + + if line =~ /^Thread \d+ Crashed/ + record = 1 + # reset the stack trace + stackTrace = [] + end + + if record + stackTrace << line + record = record + 1 + + # stop recording after $StackCount lines + if record > ($StackCount + 2) + record = nil + end + end + } + + puts File.basename(filename) + " - " + date + puts "===================================================" + stackTrace.each { |line| + puts line + } + puts "" +} + + diff --git a/WebKitTools/iExploder/tools/showtest.rb b/WebKitTools/iExploder/tools/showtest.rb new file mode 100755 index 0000000..af6b101 --- /dev/null +++ b/WebKitTools/iExploder/tools/showtest.rb @@ -0,0 +1,43 @@ +#!/usr/bin/ruby +# showtest.rb - simple CLI interface to grab a testcase +##################### +# +# Copyright (c) 2006 Thomas Stromberg <thomas%stromberg.org> +# +# This software is provided 'as-is', without any express or implied warranty. +# In no event will the authors be held liable for any damages arising from the +# use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software in a +# product, an acknowledgment in the product documentation would be appreciated +# but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source distribution. + +Dir.chdir('../htdocs') +require 'iexploder'; +require 'config'; + +### THE INTERACTION ################################## +ie = IExploder.new($HTML_MAX_TAGS, $HTML_MAX_ATTRS, $CSS_MAX_PROPS) +ie.readTagFiles() + +if ! ARGV[0] + puts "syntax: showtest.rb [test#] [subtest#]" + exit +end + +ie.test_num = ARGV[0].to_i +ie.subtest_num = ARGV[1].to_i || 0 +ie.lookup_mode = 1 +ie.setRandomSeed + +puts ie.buildPage() diff --git a/WebKitTools/mangleme/LICENSE b/WebKitTools/mangleme/LICENSE new file mode 100644 index 0000000..5ab7695 --- /dev/null +++ b/WebKitTools/mangleme/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/WebKitTools/mangleme/Makefile b/WebKitTools/mangleme/Makefile new file mode 100644 index 0000000..90d01e9 --- /dev/null +++ b/WebKitTools/mangleme/Makefile @@ -0,0 +1,16 @@ +# +# HTML manglizer +# -------------- +# Copyright (C) 2004 by Michal Zalewski <lcamtuf@coredump.cx> +# +# Makefile adapted for WebKit project. + +CC = gcc +CFLAGS = -Wall -O3 -fomit-frame-pointer -funroll-loops +OUTDIR = ../../WebKitBuild/mangleme + +all: $(OUTDIR)/mangle.cgi $(OUTDIR)/remangle.cgi + +$(OUTDIR)/%.cgi: %.cgi.c + if [ ! -d $(OUTDIR) ]; then mkdir -p $(OUTDIR); fi + $(CC) $(CFLAGS) $< -o $(OUTDIR)/$*.cgi diff --git a/WebKitTools/mangleme/README b/WebKitTools/mangleme/README new file mode 100644 index 0000000..4fe2928 --- /dev/null +++ b/WebKitTools/mangleme/README @@ -0,0 +1,20 @@ + + HTML manglizer + -------------- + + Copyright (C) 2004 by Michal Zalewski <lcamtuf@coredump.cx> + + A trivial utility to automatically check for HTML parsing flaws. Generates + a basic set of badly mangled tags on request, with auto-refresh back to the + script, so that you can point a browser to it once, and let it run until + it crashes. + + Put it in your cgi-bin directory or any other Apache folder with ExecCGI option + enabled, then visit the URL http://<yourserver>/<cgidir>/mangleme.cgi. + + When the browser crashes, error-log should be examined for the last matching + entry generated by mangle.cgi; extract the hexadecimal value, then invoke + remangle.cgi?hex_value from the browser again. If it crashes, you've reproduced + the problem, and can save the remangle.cgi page using wget or such. + + Check gallery/ for some samples. diff --git a/WebKitTools/mangleme/mangle.cgi.c b/WebKitTools/mangleme/mangle.cgi.c new file mode 100644 index 0000000..12ca948 --- /dev/null +++ b/WebKitTools/mangleme/mangle.cgi.c @@ -0,0 +1,122 @@ +/* + + HTML manglizer + -------------- + Copyright (C) 2004 by Michal Zalewski <lcamtuf@coredump.cx> + + HTML manglizer library. Logs random seeds to error-log; find the last entry before + crash, then pass it to remangle.cgi to reproduce the problem. + + */ + + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "tags.h" + +#define R(x) (rand() % (x)) + +#define MAXTCOUNT 100 +#define MAXPCOUNT 20 +#define MAXSTR2 80 + +void make_up_value(void) { + char c=R(2); + + if (c) putchar('"'); + + switch (R(31)) { + + case 0: printf("javascript:"); make_up_value(); break; +// case 1: printf("jar:"); make_up_value(); break; + case 2: printf("mk:"); make_up_value(); break; + case 3: printf("file:"); make_up_value(); break; + case 4: printf("http:"); make_up_value(); break; + case 5: printf("about:"); make_up_value(); break; + case 6: printf("_blank"); break; + case 7: printf("_self"); break; + case 8: printf("top"); break; + case 9: printf("left"); break; + case 10: putchar('&'); make_up_value(); putchar(';'); break; + case 11: make_up_value(); make_up_value(); break; + + case 12 ... 20: { + int c = R(10) ? R(10) : (1 + R(MAXSTR2) * R(MAXSTR2)); + char* x = malloc(c); + memset(x,R(256),c); + fwrite(x,c,1,stdout); + free(x); + break; + } + + case 21: printf("%s","%n%n%n%n%n%n"); break; + case 22: putchar('#'); break; + case 23: putchar('*'); break; + default: if (R(2)) putchar('-'); printf("%d",rand()); break; + + } + + if (c) putchar('"'); + +} + + +void random_tag(void) { + int tn, tc; + + do tn = R(MAXTAGS); while (!tags[tn][0]); + tc = R(MAXPCOUNT) + 1; + + putchar('<'); + + switch (R(10)) { + case 0: putchar(R(256)); break; + case 1: putchar('/'); + } + + printf("%s", tags[tn][0]); + + while (tc--) { + int pn; + switch (R(32)) { + case 0: putchar(R(256)); + case 1: break; + default: putchar(' '); + } + do pn = R(MAXPARS-1) + 1; while (!tags[tn][pn]); + printf("%s", tags[tn][pn]); + switch (R(32)) { + case 0: putchar(R(256)); + case 1: break; + default: putchar('='); + } + + make_up_value(); + + } + + putchar('>'); + +} + + +int main(int argc,char** argv) { + int tc,seed; + + printf("Content-Type: text/html;charset=utf-8\nRefresh: 0;URL=mangle.cgi\n\n"); + printf("<HTML><HEAD><META HTTP-EQUIV=\"Refresh\" content=\"0;URL=mangle.cgi\">\n"); + printf("<script language=\"javascript\">setTimeout('window.location=\"mangle.cgi\"', 1000);</script>\n"); + + seed = (time(0) ^ (getpid() << 16)); + fprintf(stderr,"[%u] Mangle attempt 0x%08x (%s) -- %s\n", (int)time(0), seed, getenv("HTTP_USER_AGENT"), getenv("REMOTE_ADDR")); + srand(seed); + + tc = R(MAXTCOUNT) + 1; + while (tc--) random_tag(); + fflush(0); + return 0; +} diff --git a/WebKitTools/mangleme/remangle.cgi.c b/WebKitTools/mangleme/remangle.cgi.c new file mode 100644 index 0000000..ccc4472 --- /dev/null +++ b/WebKitTools/mangleme/remangle.cgi.c @@ -0,0 +1,125 @@ +/* + + HTML manglizer + -------------- + Copyright (C) 2004 by Michal Zalewski <lcamtuf@coredump.cx> + + Fault reproduction utility. + + */ + + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "tags.h" + +#define R(x) (rand() % (x)) + +#define MAXTCOUNT 100 +#define MAXPCOUNT 20 +#define MAXSTR2 80 + +void make_up_value(void) { + char c=R(2); + + if (c) putchar('"'); + + switch (R(31)) { + + case 0: printf("javascript:"); make_up_value(); break; +// case 1: printf("jar:"); make_up_value(); break; + case 2: printf("mk:"); make_up_value(); break; + case 3: printf("file:"); make_up_value(); break; + case 4: printf("http:"); make_up_value(); break; + case 5: printf("about:"); make_up_value(); break; + case 6: printf("_blank"); break; + case 7: printf("_self"); break; + case 8: printf("top"); break; + case 9: printf("left"); break; + case 10: putchar('&'); make_up_value(); putchar(';'); break; + case 11: make_up_value(); make_up_value(); break; + + case 12 ... 20: { + int c = R(10) ? R(10) : (1 + R(MAXSTR2) * R(MAXSTR2)); + char* x = malloc(c); + memset(x,R(256),c); + fwrite(x,c,1,stdout); + free(x); + break; + } + + case 21: printf("%s","%n%n%n%n%n%n"); break; + case 22: putchar('#'); break; + case 23: putchar('*'); break; + default: if (R(2)) putchar('-'); printf("%d",rand()); break; + + } + + if (c) putchar('"'); + +} + + +void random_tag(void) { + int tn, tc; + + do tn = R(MAXTAGS); while (!tags[tn][0]); + tc = R(MAXPCOUNT) + 1; + + putchar('<'); + + switch (R(10)) { + case 0: putchar(R(256)); break; + case 1: putchar('/'); + } + + printf("%s", tags[tn][0]); + + while (tc--) { + int pn; + switch (R(32)) { + case 0: putchar(R(256)); + case 1: break; + default: putchar(' '); + } + do pn = R(MAXPARS-1) + 1; while (!tags[tn][pn]); + printf("%s", tags[tn][pn]); + switch (R(32)) { + case 0: putchar(R(256)); + case 1: break; + default: putchar('='); + } + + make_up_value(); + + } + + putchar('>'); + +} + + +int main(int argc,char** argv) { + int tc,seed; + char* x = getenv("QUERY_STRING"); + + if (!x || sscanf(x,"%x",&seed) != 1) { + printf("Content-type: text/plain\n\nMissing or invalid parameter.\n"); + exit(1); + } + + printf("Content-Type: text/html;charset=utf-8\nRefresh: 0;URL=remangle.cgi?0x%08x\n\n", seed); + printf("<HTML><HEAD><META HTTP-EQUIV=\"Refresh\" content=\"0;URL=remangle.cgi?0x%08x\">\n", seed); + printf("<script language=\"javascript\">setTimeout('window.location=\"remangle.cgi?0x%08x\"', 1000);</script>\n", seed); + + srand(seed); + + tc = R(MAXTCOUNT) + 1; + while (tc--) random_tag(); + fflush(0); + return 0; +} diff --git a/WebKitTools/mangleme/tags.h b/WebKitTools/mangleme/tags.h new file mode 100644 index 0000000..5789441 --- /dev/null +++ b/WebKitTools/mangleme/tags.h @@ -0,0 +1,76 @@ +/* + + HTML manglizer + -------------- + Copyright (C) 2004 by Michal Zalewski <lcamtuf@coredump.cx> + + Tag and parameter list: guesstimating / reference compilation. + + */ + + +#define MAXTAGS 80 +#define MAXPARS 20 + +static char* tags[MAXTAGS][MAXPARS] = { + { "A", "NAME", "HREF", "REF", "REV", "TITLE", "TARGET", "SHAPE", "onLoad", "STYLE", 0 }, + { "APPLET", "CODEBASE", "CODE", "NAME", "ALIGN", "ALT", "HEIGHT", "WIDTH", "HSPACE", "VSPACE", "DOWNLOAD", "HEIGHT", "NAME", "TITLE", "onLoad", "STYLE", 0 }, + { "AREA", "SHAPE", "ALT", "CO-ORDS", "HREF", "onLoad", "STYLE", 0 }, + { "B", "onLoad", "STYLE", 0 }, + { "BANNER", "onLoad", "STYLE", 0 }, + { "BASE", "HREF", "TARGET", "onLoad", "STYLE", 0 }, + { "BASEFONT", "SIZE", "onLoad", "STYLE", 0 }, + { "BGSOUND", "SRC", "LOOP", "onLoad", "STYLE", 0 }, + { "BQ", "CLEAR", "NOWRAP", "onLoad", "STYLE", 0 }, + { "BODY", "BACKGROUND", "BGCOLOR", "TEXT", "LINK", "ALINK", "VLINK", "LEFTMARGIN", "TOPMARGIN", "BGPROPERTIES", "onLoad", "STYLE", 0 }, + { "CAPTION", "ALIGN", "VALIGN", "onLoad", "STYLE", 0 }, + { "CENTER", "onLoad", "STYLE", 0 }, + { "COL", "ALIGN", "SPAN", "onLoad", "STYLE", 0 }, + { "COLGROUP", "ALIGN", "VALIGN", "HALIGN", "WIDTH", "SPAN", "onLoad", "STYLE", 0 }, + { "DIV", "ALIGN", "CLASS", "LANG", "onLoad", "STYLE", 0 }, + { "EMBED", "SRC", "HEIGHT", "WIDTH", "UNITS", "NAME", "PALETTE", "onLoad", "STYLE", 0 }, + { "FIG", "SRC", "ALIGN", "HEIGHT", "WIDTH", "UNITS", "IMAGEMAP", "onLoad", "STYLE", 0 }, + { "FN", "ID", "onLoad", "STYLE", 0 }, + { "FONT", "SIZE", "COLOR", "FACE", "onLoad", "STYLE", 0 }, + { "FORM", "ACTION", "METHOD", "ENCTYPE", "TARGET", "SCRIPT", "onLoad", "STYLE", 0 }, + { "FRAME", "SRC", "NAME", "MARGINWIDTH", "MARGINHEIGHT", "SCROLLING", "FRAMESPACING", "onLoad", "STYLE", 0 }, + { "FRAMESET", "ROWS", "COLS", "onLoad", "STYLE", 0 }, + { "H1", "SRC", "DINGBAT", "onLoad", "STYLE", 0 }, + { "HEAD", "onLoad", "STYLE", 0 }, + { "HR", "SRC", "SIZE", "WIDTH", "ALIGN", "COLOR", "onLoad", "STYLE", 0 }, + { "HTML", "onLoad", "STYLE", 0 }, + { "IFRAME", "ALIGN", "FRAMEBORDER", "HEIGHT", "MARGINHEIGHT", "MARGINWIDTH", "NAME", "SCROLLING", "SRC", "ADDRESS", "WIDTH", "onLoad", "STYLE", 0 }, + { "IMG", "ALIGN", "ALT", "SRC", "BORDER", "DYNSRC", "HEIGHT", "HSPACE", "ISMAP", "LOOP", "LOWSRC", "START", "UNITS", "USEMAP", "WIDTH", "VSPACE", "onLoad", "STYLE", 0 }, + { "INPUT", "TYPE", "NAME", "VALUE", "onLoad", "STYLE", 0 }, + { "ISINDEX", "HREF", "PROMPT", "onLoad", "STYLE", 0 }, + { "LI", "SRC", "DINGBAT", "SKIP", "TYPE", "VALUE", "onLoad", "STYLE", 0 }, + { "LINK", "REL", "REV", "HREF", "TITLE", "onLoad", "STYLE", 0 }, + { "MAP", "NAME", "onLoad", "STYLE", 0 }, + { "MARQUEE", "ALIGN", "BEHAVIOR", "BGCOLOR", "DIRECTION", "HEIGHT", "HSPACE", "LOOP", "SCROLLAMOUNT", "SCROLLDELAY", "WIDTH", "VSPACE", "onLoad", "STYLE", 0 }, + { "MENU", "onLoad", "STYLE", 0 }, + { "META", "HTTP-EQUIV", "CONTENT", "NAME", "onLoad", "STYLE", 0 }, + { "MULTICOL", "COLS", "GUTTER", "WIDTH", "onLoad", "STYLE", 0 }, + { "NOFRAMES", "onLoad", "STYLE", 0 }, + { "NOTE", "CLASS", "SRC", "onLoad", "STYLE", 0 }, + { "OVERLAY", "SRC", "X", "Y", "HEIGHT", "WIDTH", "UNITS", "IMAGEMAP", "onLoad", "STYLE", 0 }, + { "PARAM", "NAME", "VALUE", "onLoad", "STYLE", 0 }, + { "RANGE", "FROM", "UNTIL", "onLoad", "STYLE", 0 }, + { "SCRIPT", "LANGUAGE", "onLoad", "STYLE", 0 }, + { "SELECT", "NAME", "SIZE", "MULTIPLE", "WIDTH", "HEIGHT", "UNITS", "onLoad", "STYLE", 0 }, + { "OPTION", "VALUE", "SHAPE", "onLoad", "STYLE", 0 }, + { "SPACER", "TYPE", "SIZE", "WIDTH", "HEIGHT", "ALIGN", "onLoad", "STYLE", 0 }, + { "SPOT", "ID", "onLoad", "STYLE", 0 }, + { "TAB", "INDENT", "TO", "ALIGN", "DP", "onLoad", "STYLE", 0 }, + { "TABLE", "ALIGN", "WIDTH", "BORDER", "CELLPADDING", "CELLSPACING", "BGCOLOR", "VALIGN", "COLSPEC", "UNITS", "DP", "onLoad", "STYLE", 0 }, + { "TBODY", "CLASS", "ID", "onLoad", "STYLE", 0 }, + { "TD", "COLSPAN", "ROWSPAN", "ALIGN", "VALIGN", "BGCOLOR", "onLoad", "STYLE", 0 }, + { "TEXTAREA", "NAME", "COLS", "ROWS", "onLoad", "STYLE", 0 }, + { "TEXTFLOW", "CLASS", "ID", "onLoad", "STYLE", 0 }, + { "TFOOT", "COLSPAN", "ROWSPAN", "ALIGN", "VALIGN", "BGCOLOR", "onLoad", "STYLE", 0 }, + { "TH", "ALIGN", "CLASS", "ID", "onLoad", "STYLE", 0 }, + { "TITLE", "onLoad", "STYLE", 0 }, + { "TR", "ALIGN", "VALIGN", "BGCOLOR", "CLASS", "onLoad", "STYLE", 0 }, + { "UL", "SRC", "DINGBAT", "WRAP", "TYPE", "PLAIN", "onLoad", "STYLE", 0 }, + { 0 } +}; + diff --git a/WebKitTools/vcbin/cl.exe b/WebKitTools/vcbin/cl.exe Binary files differnew file mode 100755 index 0000000..2ec78c9 --- /dev/null +++ b/WebKitTools/vcbin/cl.exe diff --git a/WebKitTools/vcbin/midl.exe b/WebKitTools/vcbin/midl.exe Binary files differnew file mode 100755 index 0000000..55ecd1d --- /dev/null +++ b/WebKitTools/vcbin/midl.exe diff --git a/WebKitTools/wx/browser/browser.bkl b/WebKitTools/wx/browser/browser.bkl new file mode 100644 index 0000000..505d740 --- /dev/null +++ b/WebKitTools/wx/browser/browser.bkl @@ -0,0 +1,64 @@ +<?xml version="1.0" ?> +<!-- +Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com> + +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. + +wxWebKit sample application build file +--> + +<makefile> + <set var="WX_UNICODE">1</set> + <set var="WX_SHARED">1</set> + + <include file="../../../WebKit/wx/wxwk-settings.bkl"/> + + <!-- the WX_PYTHON option was added to presets/wx.bkl in 2.8.5, so define + it in case the presets/wx.bkl doesn't define it for us. --> + <if cond="not isdefined('WX_PYTHON')"> + <set var="WX_PYTHON">0</set> + </if> + <template id="wxwebkit"> + <lib-path>$(WKOUTPUTDIR)</lib-path> + <sys-lib>wxwebkit</sys-lib> + </template> + <exe id="wxBrowser" template="wxwk,xml2,iconv,xslt,icu,jscore,webcore,wxwebkit,curl,pthreads"> + <app-type>gui</app-type> + <runtime-libs>dynamic</runtime-libs> + <set var="BUILDDIR">$(WKOUTPUTDIR)/build/wxbrowser-$(FORMAT)</set> + + <include>$(WK_ROOT)/WebCore/platform/wx</include> + <include>$(WK_ROOT)/WebCore/bridge/wx</include> + <include>$(WK_ROOT)/WebCore/page/wx</include> + <include>$(WK_ROOT)/WebKit/wx</include> + <include>$(WK_ROOT)/WebKit/wx/WebKitSupport</include> + + <sources> + browser.cpp + </sources> + + </exe> + +</makefile> diff --git a/WebKitTools/wx/browser/browser.cpp b/WebKitTools/wx/browser/browser.cpp new file mode 100644 index 0000000..5993432 --- /dev/null +++ b/WebKitTools/wx/browser/browser.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +// webkit includes +#include "WebView.h" +#include "WebFrame.h" + +#include "wx/wxprec.h" +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +class MyApp : public wxApp +{ +public: + + virtual bool OnInit(); +}; + + +IMPLEMENT_APP(MyApp) + +bool MyApp::OnInit() +{ + wxInitAllImageHandlers(); + + // create the main application window + // see WebKit/wx/WebFrame.cpp for how to write a shell around wxWebView. + wxWebFrame *frame = new wxWebFrame(_T("wxWebKit Test App")); + +#ifndef NDEBUG + frame->ShowDebugMenu(true); +#endif + frame->CentreOnScreen(); + frame->Show(true); + + return true; +} diff --git a/WebKitTools/wx/build-wxwebkit b/WebKitTools/wx/build-wxwebkit new file mode 100755 index 0000000..59907c7 --- /dev/null +++ b/WebKitTools/wx/build-wxwebkit @@ -0,0 +1,377 @@ +#!/bin/bash + +# Copyright (C) 2007 Robin Dunn, Kevin Ollivier 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. +# +# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR +# 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. +# +# Driver for the wxWebKit build process. + +set -o errexit +#set -o xtrace + +#---------------------------------------------------------------------- +# Set up the environment + +scriptDir="$(cd $(dirname $0);pwd)" +WK_ROOT=$scriptDir/../.. +WK_ROOTDIR=$WK_ROOT + +cd $scriptDir + +if [ -z $WEBKITOUTPUTDIR ]; then + WEBKITOUTPUTDIR=`cd $WK_ROOT/WebKitTools/Scripts; perl -e "use webkitdirs; print productDir()"` +fi + +WKWINLIBS=WebKitLibraries/win +WINDEPS=" $WKWINLIBS/lib/pthreadVC2.dll" +WINDEPS="$WINDEPS $WKWINLIBS/bin/icuuc34.dll $WKWINLIBS/bin/icudt34.dll $WKWINLIBS/bin/icuin34.dll" +WINDEPS="$WINDEPS $WKWINLIBS/bin/libcurl.dll $WKWINLIBS/bin/libeay32.dll $WKWINLIBS/bin/ssleay32.dll $WKWINLIBS/bin/zlib1.dll" +WINDEPS="$WINDEPS $WKWINLIBS/lib/sqlite3.dll" +WINDEPS="$WINDEPS $WKWINLIBS/bin/libxml2.dll $WKWINLIBS/bin/libxslt.dll" +WINDEPS="$WINDEPS $WKWINLIBS/bin/iconv.dll" + +# TODO: check that we are running from the root of the source tree... + +# cygpath will bork if the dir doesn't exist... +mkdir -p $WEBKITOUTPUTDIR + +if [ $OSTYPE == cygwin ]; then + EXE=.exe + WK_ROOTDIR=`cygpath -d $WK_ROOT` + WEBKITOUTPUTDIR=`cygpath -d $WEBKITOUTPUTDIR` + export WEBKITOUTPUTDIR + if [ -z $WXWIN ]; then + echo "Error, you must set WXWIN to your wxWidgets root directory." + exit 1 + fi + if [ -z $WX_PREFIX ]; then + WX_PREFIX=$WXWIN + fi + if [ -z $BAKEFILE_PATHS ]; then + export BAKEFILE_PATHS=$WXWIN/build/bakefiles/wxpresets + fi + LINKER=`which link` + if [ "$LINKER" = "/usr/bin/link" ]; then + echo "WARNING: wxWebKit builds using MSVC on Windows, but it looks like" + echo "you have the GCC linker on your path. If /usr/bin/link does NOT point" + echo "to the MSVC linker, you need to move it or change your path to pick up" + echo "Microsoft's link.exe program first." + fi + +else + export WEBKITOUTPUTDIR + WX_PREFIX=`wx-config --prefix` + if [ ! -d "$WX_PREFIX" ]; then + echo "ERROR: Cannot find your wxWidgets installation." + echo "Make sure wx-config is on your PATH and points to a valid wxWidgets installation." + exit 1 + fi + + CONFIG=`wx-config --selected-config` + if [ "${CONFIG:0:4}" != "gtk2" -a "${CONFIG:0:3}" != "mac" ]; then + echo "ERROR: This configuration '$CONFIG' is not currently supported by wxWebKit. Please use the win, mac, or gtk2 port depending on your platform." + exit 1 + fi + + if [ ! -d "$WX_PREFIX/share/bakefile" ]; then + echo "ERROR: wxWidgets installation does not have wxpresets." + echo "wx-config is pointing to an installation that does not have Bakefile presets installed. Run `wx-config --version` to ensure your wxWidgets is of version 2.8+." + exit 1 + fi + + if [ -z $BAKEFILE_PATHS ]; then + export BAKEFILE_PATHS=$WX_PREFIX/share/bakefile + fi +fi + +# after all that, make sure that BAKEFILE_PATHS was either set +# previously, or by the code above +if [ -z $BAKEFILE_PATHS ]; then + echo "Error, you must set BAKEFILE_PATHS to the directory containing wxpresets." + exit 1 +fi + +#---------------------------------------------------------------------- +# process command line args + +do_bake=0 +do_prep=0 +do_extras=0 +do_build=0 +do_clean=0 +do_install=0 +use_wxgc=0 +wxdebug=0 +wxpython=0 +make_args='' +other_args='' + +for flag in $*; do + case $flag in + bake) do_bake=1 ;; + prep) do_prep=1 ;; + build) do_build=1 ;; + all) do_extras=1; do_bake=1; do_prep=1; do_build=1 ;; + clean) other_args=clean; do_clean=1 ;; + wxgc) use_wxgc=1 ;; + wxdebug) wxdebug=1 ;; + wxpython) wxpython=1 ;; + wxpython-install) wxpython_install=1 ;; + *) export $flag ;; #other_args='$other_args "$flag"' ;; + esac +done + + +#---------------------------------------------------------------------- + +# if no arguments were passed, do a full build. +if [ $do_bake == 0 -a $do_prep == 0 -a $do_build == 0 -a $do_clean == 0 ]; then + do_bake=1; do_prep=1; do_build=1 +fi + +function do_make { + dir=$1 + cxxflags=$2 + olddir=$PWD + shift + shift + if [ $OSTYPE == cygwin ]; then + cd $dir + nmake -f makefile.vc CXXFLAGS="$cxxflags" $@ + cd $olddir + else + make -C $dir -f GNUmakefile $MAKE_ARGS CXXFLAGS="$cxxflags" $@ + fi + if [ $? != 0 ]; then + exit $? + fi +} + +# output the first parameter that is a dir and exists +function find_existing_dir { + for arg in $*; do + tester=$arg + if [ $OSTYPE == cygwin ]; then + tester=`cygpath -u $arg` + fi + if [ -d $tester ]; then + echo $arg + return + fi + done +} + + +olddir=$PWD + +if [ $do_clean == 1 ]; then + rm -rf $WK_ROOT/JavaScriptCore/DerivedSources + rm -rf $WK_ROOT/WebCore/DerivedSources + rm -rf $WK_ROOT/WebCore/include/JavaScriptCore +else + + mkdir -p $WEBKITOUTPUTDIR/build + + if [ $do_bake == 1 ]; then + # bakefile stuff + cd $WK_ROOT/WebKit/wx + bakefile_gen + + # we need to do this because Bakefile doesn't know which + # platform it's running on with GNU format, and so it defaults + # to the standard Unix file endings and linker args. + if [ "${OSTYPE:0:6}" = "darwin" ]; then + sed "s/libwebcore-wx.so/libwebcore-wx.dylib/" < $WK_ROOT/WebCore/GNUmakefile > temp + mv temp $WK_ROOT/WebCore/GNUmakefile + + sed "s/\-shared/\-dynamiclib/" < $WK_ROOT/WebCore/GNUmakefile > temp + mv temp $WK_ROOT/WebCore/GNUmakefile + + sed "s/libwxwebkit.so/libwxwebkit.dylib/" < $WK_ROOT/WebKit/wx/GNUmakefile > temp + mv temp $WK_ROOT/WebKit/wx/GNUmakefile + + sed "s/\-shared/\-dynamiclib/" < $WK_ROOT/WebKit/wx/GNUmakefile > temp + mv temp $WK_ROOT/WebKit/wx/GNUmakefile + fi + fi + + if [ $do_prep == 1 ]; then + # Other preparation steps + + # since the buildbot will wipe the build tree clean sometimes, we need to reinstall + # the dependencies if they aren't installed. + if [ "${OSTYPE:0:6}" == "darwin" ]; then + $WK_ROOT/WebKitTools/wx/install-unix-extras + fi + + cd $WK_ROOT/JavaScriptCore + ./make-generated-sources.sh + if [ $? != 0 ]; then + exit $? + fi + + cd $WK_ROOT/WebCore + ./make-generated-sources.sh platform/wx/wx-encodings.txt + if [ $? != 0 ]; then + exit $? + fi + fi +fi + + +if [ $do_build == 1 -o $do_clean == 1 ]; then + # Build steps + WXGC_DEFINE="" + if [ $use_wxgc == 1 ]; then + WXGC_DEFINE="-DWTF_USE_WXGC=1" + fi + WX_EXT= + if [ "${OSTYPE:0:6}" == "cygwin" -a $wxdebug == 1 ]; then + WX_EXT=d + fi + if [ "${OSTYPE:0:6}" == "cygwin" -a $wxpython == 1 ]; then + other_args=WX_PYTHON=1 + WX_EXT=h + wxdebug=1 + fi + + if [ "${OSTYPE:0:6}" == "cygwin" ]; then + PLATFORM_OS="win" + elif [ "${OSTYPE:0:6}" == "darwin" ]; then + PLATFORM_OS="mac" + else + PLATFORM_OS="linux" + fi + + WINDEPS="$WINDEPS $WXWIN/lib/vc_dll/wxmsw28u${WX_EXT}_core_vc.dll $WXWIN/lib/vc_dll/wxbase28u${WX_EXT}_vc.dll" + + # NOTE: If we try to do make clean after the Bakefiles were cleaned out, or before they were + # first generated, we will get errors about missing files. + # FIXME: Make the check more robust. + if [ -f $WK_ROOT/JavaScriptCore/GNUmakefile ]; then + do_make $WK_ROOT/JavaScriptCore "-DBUILDING_WX__=1 $WXGC_DEFINE" WX_DEBUG=$wxdebug WEBKIT_ROOT=$WK_ROOTDIR PLATFORM_OS=$PLATFORM_OS $other_args + do_make $WK_ROOT/WebCore "-DBUILDING_WX__=1 $WXGC_DEFINE" WX_DEBUG=$wxdebug WEBKIT_ROOT=$WK_ROOTDIR PLATFORM_OS=$PLATFORM_OS $other_args + do_make $WK_ROOT/WebKit/wx "-DBUILDING_WX__=1 -DWXMAKINGDLL_WEBKIT=1 $WXGC_DEFINE" WX_DEBUG=$wxdebug WEBKIT_ROOT=$WK_ROOTDIR PLATFORM_OS=$PLATFORM_OS $other_args + do_make $WK_ROOT/WebKitTools/wx/browser "-DBUILDING_WX__=1 -DWXUSINGDLL_WEBKIT=1 $WXGC_DEFINE" WX_DEBUG=$wxdebug WEBKIT_ROOT=$WK_ROOTDIR PLATFORM_OS=$PLATFORM_OS $other_args + fi + + if [ $do_build == 1 ]; then + if [ "${OSTYPE:0:6}" = "darwin" ]; then + cd $WEBKITOUTPUTDIR + mkdir -p wxBrowser.app/Contents/MacOS + mkdir -p wxBrowser.app/Contents/Frameworks + cp wxBrowser wxBrowser.app/Contents/MacOS + install_name_tool -change libwxwebkit.dylib @executable_path/../Frameworks/libwxwebkit.dylib wxBrowser.app/Contents/MacOS/wxBrowser + if [ ! -f "$WEBKITOUTPUTDIR/libwxwebkit.dylib" ]; then + ln -s $WEBKITOUTPUTDIR/libwxwebkit.dylib wxBrowser.app/Contents/Frameworks + fi + fi + + if [ $wxpython == 1 ]; then + SWIG=`which swig` + + if [ ! -f "$SWIG" ]; then + echo "ERROR: Cannot find SWIG. Make sure that SWIG 1.3.29 is located on your path."; + exit 1; + fi + + cd $WK_ROOT/WebKit/wx/bindings/python + + SWIG_FLAGS=`python -c "import wx.build.config; import string; print string.join(wx.build.config.swig_args, ' ')"` + WEBKIT_INCLUDE="-I$WK_ROOT/WebKit/wx" + if [ "${OSTYPE:0:6}" == "cygwin" ]; then + WEBKIT_INCLUDE="-I`cygpath -d $WK_ROOT/WebKit/wx`" + fi + + # Determine which include path to use for wxPython's *.i files + # Options are: + # wxPython installed on a posix system + # the wxPython win32 devel tarball + # a wx source tree from a tarball where wxPython is in the wx dir + # a wx source tree from SVN where wxPython is a sibling of the wx dir + WXPY_INCLUDE=`find_existing_dir \ + $WX_PREFIX/include/wx-2.8/wx/wxPython/i_files \ + $WX_PREFIX/include/wx/wxPython/i_files \ + $WX_PREFIX/wxPython/src \ + $WX_PREFIX/../wxPython/src` + if [ -z $WXPY_INCLUDE ]; then + echo "ERROR: Unable to find wxPython's *.i files" + exit 1 + fi + + # Run SWIG + $SWIG $SWIG_FLAGS -I$WXPY_INCLUDE $WEBKIT_INCLUDE -o webview.cpp webview.i + + PY_INCLUDE=`python -c "import sys,distutils.sysconfig; sys.stdout.write(distutils.sysconfig.get_python_inc())"` + PY_VERSION=`python -c "import sys; sys.stdout.write(str(sys.version_info[0]) + str(sys.version_info[1]))"` + PY_LIBDIR=`python -c "import distutils.sysconfig; import sys; sys.stdout.write(distutils.sysconfig.PREFIX)"` + + if [ "${OSTYPE:0:6}" == "cygwin" ]; then + PY_LIBDIR="$PY_LIBDIR\\Libs" + else + PY_LIBDIR="$PY_LIBDIR/lib" + fi + + do_make $WK_ROOT/WebKit/wx/bindings/python "-DBUILDING_WX__=1 -DWXUSINGDLL=1 -DWXUSINGDLL_WEBKIT=1 -I$PY_INCLUDE -I$WX_PREFIX/wxPython/include -I$WX_PREFIX/../wxPython/include $WXGC_DEFINE" \ + WX_DEBUG=$wxdebug WEBKIT_ROOT=$WK_ROOTDIR PLATFORM_OS=$PLATFORM_OS PYTHON_VERSION=$PY_VERSION PYTHON_LIBDIR=$PY_LIBDIR $other_args + if [ "${OSTYPE:0:6}" == "cygwin" ]; then + if [ -f $WEBKITOUTPUTDIR/_webview.pyd -a -f $WEBKITOUTPUTDIR/_webview.dll ]; then + rm $WEBKITOUTPUTDIR/_webview.pyd + mv $WEBKITOUTPUTDIR/_webview.dll $WEBKITOUTPUTDIR/_webview.pyd + fi + fi + fi + + + if [ "$OSTYPE" == "cygwin" ]; then + echo "Copying necessary DLLs to run test and sample applications..." + cd $WK_ROOT + cp $WINDEPS `cygpath -u $WEBKITOUTPUTDIR` + chmod +x `cygpath -u $WEBKITOUTPUTDIR/`*.dll + fi + + BROWSERAPP="wxBrowser" + + if [ "${OSTYPE:0:6}" == "darwin" ]; then + BROWSERAPP="wxBrowser.app/Contents/MacOS/wxBrowser" + fi + + echo "" + echo "" + echo "--- BUILD COMPLETE ---" + echo "" + echo "Next steps:" + echo "" + echo "-- Run '$WK_ROOT/WebKitTools/Scripts/run-javascriptcore-tests --wx' to ensure JSCore tests pass." + echo "" + echo "-- Run $WEBKITOUTPUTDIR/$BROWSERAPP to test your wxWebKit build." + echo "" + echo "" + fi +fi + +if [ $do_clean == 1 ]; then + cd $WK_ROOT/WebKit/wx + bakefile_gen --clean +fi + +cd $olddir diff --git a/WebKitTools/wx/install-unix-extras b/WebKitTools/wx/install-unix-extras new file mode 100755 index 0000000..ec09f85 --- /dev/null +++ b/WebKitTools/wx/install-unix-extras @@ -0,0 +1,172 @@ +#!/bin/sh + +# Copyright (C) 2005, 2006 Apple Computer, Inc. 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. + +# A script to download the extra libraries needed to build WebKit on UNIX-based OSes. +# libxml/libxslt need to be added, but so far I've had them on all the (UNIX) machines +# I've tested on, so I don't have a machine to test the code on. + +DL_CMD="curl -L" + +scriptDir="$(cd $(dirname $0);pwd)" +WK_ROOT=$scriptDir/../.. +WK_ROOTDIR=$WK_ROOT + +DL_DIR=/tmp/webkit-deps +# NOTE: If you change this, make sure the dir is on the path. +DEPS_PREFIX=$WK_ROOT/WebKitLibraries/unix +DLLEXT=so + +if [ "${OSTYPE:0:6}" == "darwin" ]; then + DLLEXT=dylib +fi + +mkdir -p $DL_DIR +mkdir -p $DEPS_PREFIX + +ICU_VERSION="3.4.1" +ICU_TARBALL="icu-$ICU_VERSION.tgz" +ICU_URL="ftp://ftp.software.ibm.com/software/globalization/icu/$ICU_VERSION/$ICU_TARBALL" + +# dependent app, not lib, what should we do for these? + +GPERF_VERSION="3.0.1" +GPERF_TARBALL="gperf-$GPERF_VERSION.tar.gz" +GPERF_URL="ftp://mirrors.kernel.org/gnu/gperf/$GPERF_TARBALL" + +PKG_CONFIG_VERSION="0.20" +PKG_CONFIG_TARBALL="pkg-config-$PKG_CONFIG_VERSION.tar.gz" +PKG_CONFIG_URL="http://pkgconfig.freedesktop.org/releases/$PKG_CONFIG_TARBALL" + +ICONV_VERSION="1.9.2" +ICONV_TARBALL="libiconv-$ICONV_VERSION.tar.gz" +ICONV_URL="http://ftp.gnu.org/pub/gnu/libiconv/$ICONV_TARBALL" + +LIBJPEG_VERSION="6b" +LIBJPEG_TARBALL="jpegsrc.v$LIBJPEG_VERSION.tar.gz" +LIBJPEG_URL="http://www.ijg.org/files/$LIBJPEG_TARBALL" + +LIBPNG_VERSION="1.2.24" +LIBPNG_TARBALL="libpng-$LIBPNG_VERSION.tar.gz" +LIBPNG_URL="ftp://ftp.simplesystems.org/pub/libpng/png/src/$LIBPNG_TARBALL" + +cd $DL_DIR +# build ICU +if [ `which icu-config >/dev/null 2>&1` ]; then + $DL_CMD -o $DL_DIR/$ICU_TARBALL $ICU_URL + + tar xzvf $DL_DIR/$ICU_TARBALL + cd $DL_DIR/icu/source + + chmod +x configure install-sh + + if [ "${OSTYPE:0:6}" == "darwin" ]; then + ./configure --prefix=$DEPS_PREFIX --disable-dependency-tracking + make CFLAGS="-O -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc" \ + LDFLAGS="-arch i386 -arch ppc" + make install + else + ./configure --prefix=$DEPS_PREFIX + + make + #make check + make install + fi + cd $DL_DIR + rm -rf icu +fi + +# TODO: What would be a good way to test for this? +if [ ! -f $DEPS_PREFIX/lib/libiconv.$DLLEXT ]; then + $DL_CMD -o $DL_DIR/$ICONV_TARBALL $ICONV_URL + + tar xzvf $DL_DIR/$ICONV_TARBALL + cd $DL_DIR/libiconv-$ICONV_VERSION + + if [ "${OSTYPE:0:6}" == "darwin" ]; then + ./configure --prefix=$DEPS_PREFIX --disable-dependency-tracking + make CFLAGS="-O -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc" \ + LDFLAGS="-arch i386 -arch ppc" + make install + else + ./configure --prefix=$DEPS_PREFIX + + make + make install + fi + cd $DL_DIR + rm -rf $DL_DIR/libiconv-$ICONV_VERSION +fi + +if [ ! -f $DEPS_PREFIX/lib/libjpeg.a ]; then + $DL_CMD -o $DL_DIR/$LIBJPEG_TARBALL $LIBJPEG_URL + + tar xzvf $DL_DIR/$LIBJPEG_TARBALL + cd $DL_DIR/jpeg-$LIBJPEG_VERSION + + # jpeg install command expects this to exist. + mkdir -p $DEPS_PREFIX/man/man1 + + if [ "${OSTYPE:0:6}" == "darwin" ]; then + ./configure --prefix=$DEPS_PREFIX --disable-dependency-tracking + make CFLAGS="-O -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc" \ + LDFLAGS="-arch i386 -arch ppc" + make install + else + ./configure --prefix=$DEPS_PREFIX + + make + fi + + cp libjpeg.a $DEPS_PREFIX/lib + cp *.h $DEPS_PREFIX/include + + cd $DL_DIR + rm -rf $DL_DIR/jpeg-$LIBJPEG_VERSION +fi + +if [ ! -f $DEPS_PREFIX/lib/libpng.a ]; then + $DL_CMD -o $DL_DIR/$LIBPNG_TARBALL $LIBPNG_URL + + tar xzvf $DL_DIR/$LIBPNG_TARBALL + cd $DL_DIR/libpng-$LIBPNG_VERSION + + if [ "${OSTYPE:0:6}" == "darwin" ]; then + ./configure --prefix=$DEPS_PREFIX --disable-dependency-tracking + make CFLAGS="-O -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc" \ + LDFLAGS="-arch i386 -arch ppc" + make install + else + ./configure --prefix=$DEPS_PREFIX + + make + make install + fi + + cd $DL_DIR + rm -rf $DL_DIR/libpng-$LIBPNG_VERSION +fi |