summaryrefslogtreecommitdiffstats
path: root/WebKitTools
diff options
context:
space:
mode:
Diffstat (limited to 'WebKitTools')
-rw-r--r--WebKitTools/ChangeLog1025
-rw-r--r--WebKitTools/DumpRenderTree/DumpRenderTree.sln21
-rw-r--r--WebKitTools/DumpRenderTree/LayoutTestController.cpp42
-rw-r--r--WebKitTools/DumpRenderTree/LayoutTestController.h12
-rw-r--r--WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp40
-rw-r--r--WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h1
-rw-r--r--WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp12
-rw-r--r--WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp10
-rw-r--r--WebKitTools/DumpRenderTree/gtk/EventSender.cpp80
-rw-r--r--WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp43
-rw-r--r--WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig6
-rw-r--r--WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig2
-rw-r--r--WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm6
-rw-r--r--WebKitTools/DumpRenderTree/mac/HistoryDelegate.mm7
-rw-r--r--WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm32
-rw-r--r--WebKitTools/DumpRenderTree/mac/UIDelegate.mm5
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp14
-rw-r--r--WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro19
-rw-r--r--WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp260
-rw-r--r--WebKitTools/DumpRenderTree/qt/EventSenderQt.h64
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp316
-rw-r--r--WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h147
-rw-r--r--WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp129
-rw-r--r--WebKitTools/DumpRenderTree/qt/TextInputControllerQt.h56
-rw-r--r--WebKitTools/DumpRenderTree/qt/WorkQueue.cpp2
-rw-r--r--WebKitTools/DumpRenderTree/qt/WorkQueue.h2
-rw-r--r--WebKitTools/DumpRenderTree/qt/WorkQueueItem.h5
-rw-r--r--WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp94
-rw-r--r--WebKitTools/DumpRenderTree/qt/jsobjects.cpp665
-rw-r--r--WebKitTools/DumpRenderTree/qt/jsobjects.h149
-rw-r--r--WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp31
-rw-r--r--WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj97
-rw-r--r--WebKitTools/DumpRenderTree/win/EventSender.cpp10
-rw-r--r--WebKitTools/DumpRenderTree/win/EventSender.h3
-rw-r--r--WebKitTools/DumpRenderTree/win/HistoryDelegate.cpp221
-rw-r--r--WebKitTools/DumpRenderTree/win/HistoryDelegate.h72
-rw-r--r--WebKitTools/DumpRenderTree/win/ImageDiff.vcproj67
-rw-r--r--WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp103
-rw-r--r--WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc4
-rw-r--r--WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj72
-rwxr-xr-xWebKitTools/DumpRenderTree/win/UIDelegate.cpp5
-rw-r--r--WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp5
-rw-r--r--WebKitTools/FindSafari/FindSafari.rc4
-rw-r--r--WebKitTools/FindSafari/FindSafari.vcproj2
-rw-r--r--WebKitTools/GtkLauncher/main.c6
-rw-r--r--WebKitTools/Scripts/VCSUtils.pm137
-rwxr-xr-xWebKitTools/Scripts/bisect-builds4
-rwxr-xr-xWebKitTools/Scripts/bugzilla-tool122
-rw-r--r--WebKitTools/Scripts/modules/bugzilla.py26
-rw-r--r--WebKitTools/Scripts/modules/buildbot.py14
-rw-r--r--WebKitTools/Scripts/modules/buildbot_unittest.py16
-rw-r--r--WebKitTools/Scripts/modules/committers.py31
-rw-r--r--WebKitTools/Scripts/modules/cpp_style.py85
-rw-r--r--WebKitTools/Scripts/modules/cpp_style_unittest.py100
-rw-r--r--WebKitTools/Scripts/modules/scm.py16
-rw-r--r--WebKitTools/Scripts/modules/scm_unittest.py59
-rwxr-xr-xWebKitTools/Scripts/pdevenv14
-rwxr-xr-xWebKitTools/Scripts/prepare-ChangeLog27
-rwxr-xr-xWebKitTools/Scripts/resolve-ChangeLogs63
-rwxr-xr-xWebKitTools/Scripts/run-iexploder-tests3
-rwxr-xr-xWebKitTools/Scripts/run-javascriptcore-tests13
-rwxr-xr-xWebKitTools/Scripts/run-jsc7
-rwxr-xr-xWebKitTools/Scripts/run-launcher2
-rwxr-xr-xWebKitTools/Scripts/run-mangleme-tests3
-rwxr-xr-xWebKitTools/Scripts/run-sunspider13
-rwxr-xr-xWebKitTools/Scripts/run-webkit-tests4
-rwxr-xr-xWebKitTools/Scripts/sunspider-compare-results4
-rwxr-xr-xWebKitTools/Scripts/svn-apply125
-rwxr-xr-xWebKitTools/Scripts/svn-create-patch72
-rwxr-xr-xWebKitTools/Scripts/svn-unapply103
-rwxr-xr-xWebKitTools/Scripts/update-webkit8
-rw-r--r--WebKitTools/Scripts/webkitdirs.pm31
-rw-r--r--WebKitTools/WinLauncher/WinLauncher.vcproj109
-rw-r--r--WebKitTools/pywebsocket/COPYING28
-rw-r--r--WebKitTools/pywebsocket/MANIFEST.in6
-rw-r--r--WebKitTools/pywebsocket/README6
-rw-r--r--WebKitTools/pywebsocket/example/echo_client.py195
-rw-r--r--WebKitTools/pywebsocket/example/echo_wsh.py44
-rw-r--r--WebKitTools/pywebsocket/mod_pywebsocket/__init__.py102
-rw-r--r--WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py205
-rw-r--r--WebKitTools/pywebsocket/mod_pywebsocket/handshake.py178
-rw-r--r--WebKitTools/pywebsocket/mod_pywebsocket/headerparserhandler.py99
-rw-r--r--WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py223
-rw-r--r--WebKitTools/pywebsocket/mod_pywebsocket/standalone.py254
-rw-r--r--WebKitTools/pywebsocket/mod_pywebsocket/util.py52
-rw-r--r--WebKitTools/pywebsocket/setup.py63
-rw-r--r--WebKitTools/pywebsocket/test/config.py45
-rw-r--r--WebKitTools/pywebsocket/test/mock.py205
-rw-r--r--WebKitTools/pywebsocket/test/run_all.py64
-rw-r--r--WebKitTools/pywebsocket/test/test_dispatch.py222
-rw-r--r--WebKitTools/pywebsocket/test/test_handshake.py316
-rw-r--r--WebKitTools/pywebsocket/test/test_mock.py126
-rw-r--r--WebKitTools/pywebsocket/test/test_msgutil.py149
-rw-r--r--WebKitTools/pywebsocket/test/test_util.py57
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/blank_wsh.py31
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/origin_check_wsh.py42
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py44
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py45
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py39
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/sub/plain_wsh.py40
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py45
-rw-r--r--WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py45
-rw-r--r--WebKitTools/wx/browser/wscript2
-rw-r--r--WebKitTools/wx/build/build_utils.py36
-rw-r--r--WebKitTools/wx/build/settings.py91
-rwxr-xr-xWebKitTools/wx/install-unix-extras28
-rw-r--r--WebKitTools/wx/packaging/build-mac-installer.py157
-rw-r--r--WebKitTools/wx/packaging/build-win-installer.py44
-rw-r--r--WebKitTools/wx/packaging/wxWebKitInstaller.iss.in2
109 files changed, 6938 insertions, 1571 deletions
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 6a8a912..7dcbf6c 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,1028 @@
+2009-10-28 Roland Steiner <rolandsteiner@chromium.org>
+
+ Adding myself to the committers list.
+
+ * Scripts/modules/committers.py:
+
+2009-10-28 Chris Fleizach <cfleizach@apple.com>
+
+ Adding myself to the committers list.
+
+ * Scripts/modules/committers.py:
+
+2009-10-28 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk>
+
+ Reviewed by Jan Alonzo.
+
+ [GTK] API to start inspector for a WebView
+ https://bugs.webkit.org/show_bug.cgi?id=22551
+
+ Use the new inspector API to implement the LayoutTestController
+ interfaces used to test the inspector.
+
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (webInspectorInspectWebView):
+ (createWebView):
+ * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+ (LayoutTestController::showWebInspector):
+ (LayoutTestController::closeWebInspector):
+ (LayoutTestController::evaluateInWebInspector):
+
+2009-10-28 Shinichiro Hamaji <hamaji@chromium.org>
+
+ Reviewed by Eric Seidel.
+
+ [Qt] WebFrame::counterValueForElementById must not be exposed
+ https://bugs.webkit.org/show_bug.cgi?id=30882
+
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::counterValueForElementById):
+
+2009-10-28 Kenneth Rohde Christiansen <kenneth@webkit.org>
+
+ Rubberstamped by Oliver Hunt.
+
+ Fix the warning:
+
+ "warning: ignoring return value of 'char* getcwd(char*, size_t)',
+ declared with attribute warn_unused_result".
+
+ by actually checking the result. In the case it is null, an
+ error has occoured, so treat it as the other fatal errors.
+
+ * DumpRenderTree/qt/DumpRenderTree.cpp:
+ (WebCore::DumpRenderTree::initializeFonts):
+
+2009-10-27 Shinichiro Hamaji <hamaji@chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Provide a way to get counter values with layoutTestContoller
+ https://bugs.webkit.org/show_bug.cgi?id=30555
+
+ Define layoutTestContoller.counterValueForElementById.
+
+ * DumpRenderTree/LayoutTestController.cpp:
+ (counterValueForElementByIdCallback):
+ (LayoutTestController::staticFunctions):
+ * DumpRenderTree/LayoutTestController.h:
+ * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+ (LayoutTestController::counterValueForElementById):
+
+2009-10-27 Kenneth Rohde Christiansen <kenneth@webkit.org>
+
+ Rubberstamped by Oliver Hunt.
+
+ Change two methods to be internal for DRT use only.
+
+ Part of [Qt] Review all new API in Qt 4.6
+ https://bugs.webkit.org/show_bug.cgi?id=29843#c11
+
+ * DumpRenderTree/qt/DumpRenderTree.cpp:
+ (WebCore::DumpRenderTree::resetToConsistentStateBeforeTesting):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::whiteListAccessFromOrigin):
+
+2009-10-27 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ REGRESSION: svn-apply exits(1) when applying a patch with a file add
+ https://bugs.webkit.org/show_bug.cgi?id=30826
+
+ * Scripts/svn-apply:
+ - Add () around all system() calls.
+ - Use the correct system() == 0 or die instead of system() or die
+ - Add descriptive messages to all die statements.
+
+2009-10-27 Steve Block <steveblock@google.com>
+
+ Reviewed by NOBODY.
+
+ Adds steveblock@google.com to list of committers.
+
+ * Scripts/modules/committers.py: Adds steveblock@google.com to list of committers.
+
+2009-10-27 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ svn-apply can exit(0) even on patch failure
+ https://bugs.webkit.org/show_bug.cgi?id=29622
+
+ * Scripts/svn-apply:
+ - Add a bunch of "or die" statements, hopefully catching all
+ possible cases where failure could still exit(0).
+
+2009-10-27 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ svn-* scripts should share code through VCSUtils.pm
+ https://bugs.webkit.org/show_bug.cgi?id=30791
+
+ Just moving code into a shared location.
+
+ * Scripts/VCSUtils.pm:
+ * Scripts/prepare-ChangeLog:
+ * Scripts/resolve-ChangeLogs:
+ * Scripts/svn-apply:
+ * Scripts/svn-create-patch:
+ * Scripts/svn-unapply:
+ * Scripts/update-webkit:
+
+2009-10-27 Vadim Zeitlin <vadim@wxwidgets.org>
+
+ Suppress a huge number of MSVC warnings when building wxWebKit.
+
+ * wx/build/settings.py:
+
+2009-10-26 Eric Seidel <eric@webkit.org>
+
+ No review, just adding Mike Belshe to the committers list.
+
+ * Scripts/modules/committers.py:
+
+2009-10-26 Laszlo Gombos <laszlo.1.gombos@nokia.com>
+
+ Reviewed by Darin Adler.
+
+ Make .rc files compile on Windows without depending on MFC headers
+ https://bugs.webkit.org/show_bug.cgi?id=30750
+
+ * DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc: Use
+ windows.h instead of afxres.h because it exists even when MFC is not
+ installed, and is all that's needed here.
+
+ * FindSafari/FindSafari.rc: Ditto
+
+2009-10-24 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ bugzilla-tool post-diff should know how to mark commit-queue=?
+ https://bugs.webkit.org/show_bug.cgi?id=29202
+
+ * Scripts/bugzilla-tool:
+ - Add --commit-queue option to post-diff, post-commits and create-bug.
+ * Scripts/modules/bugzilla.py:
+ - Added support for --commit-queue to add_patch_to_bug and create_bug_with_patch.
+ - Added _fill_attachment_form to share code between add_patch_to_bug and create_bug_with_patch.
+
+2009-10-23 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ bugzilla-tool commit-queue does not notice modifications to committers.py
+ https://bugs.webkit.org/show_bug.cgi?id=30084
+
+ * Scripts/bugzilla-tool:
+ - Make commit-queue re-exec itself instead of using while(1).
+ - Add a --is-relaunch parameter to commit-queue to bypass initialization on re-launch.
+ - Add a _next_patch() method which calls exec() (and could eventually call update-webkit too).
+
+2009-10-22 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ commit-queue will get stuck on patches if land-patches terminates unexpectedly
+ https://bugs.webkit.org/show_bug.cgi?id=30634
+
+ * Scripts/bugzilla-tool:
+ - Add a way for land-patches to exit(2) to indicate an error, but one it has handled.
+ - Make commit-queue auto cq- any patch where land-patches exited anything other than '0' or '2'.
+
+2009-10-26 Yuzo Fujishima <yuzo@google.com>
+
+ Reviewed by Eric Seidel.
+
+ Upgrade pywebsocket to 0.4.1. This will make reusing LayoutTests/fast/js/resources easier, for example.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30763
+
+ * pywebsocket/mod_pywebsocket/__init__.py:
+ * pywebsocket/mod_pywebsocket/dispatch.py:
+ * pywebsocket/mod_pywebsocket/headerparserhandler.py:
+ * pywebsocket/mod_pywebsocket/standalone.py:
+ * pywebsocket/setup.py:
+ * pywebsocket/test/test_dispatch.py:
+
+2009-10-26 Carol Szabo <carol.szabo@nokia.com>
+
+ Reviewed by David Levin.
+
+ REGRESSION: 2 failures in run-webkit-unittests
+ https://bugs.webkit.org/show_bug.cgi?id=30645
+
+ * Scripts/modules/cpp_style_unittest.py:
+ Fixed a few test scenarios which apparently lost some spaces from
+ text literals.
+
+2009-10-26 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fix. Make sure isQt() doesn't return true if --wx was passed to build-webkit.
+
+ * Scripts/webkitdirs.pm:
+
+2009-10-26 Csaba Osztrogonác <ossy@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ Unification of using null device in perl scripts.
+ https://bugs.webkit.org/show_bug.cgi?id=30572
+
+ * Scripts/VCSUtils.pm:
+ * Scripts/bisect-builds:
+ * Scripts/resolve-ChangeLogs:
+ * Scripts/run-iexploder-tests:
+ * Scripts/run-jsc:
+ * Scripts/run-mangleme-tests:
+ * Scripts/run-webkit-tests:
+ * Scripts/webkitdirs.pm:
+ Using File::Spec->devnull() instead of hard coded /dev/null.
+
+2009-10-26 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Holger Freyther.
+
+ Reviewers are missing from committers.py
+ https://bugs.webkit.org/show_bug.cgi?id=30733
+
+ * Scripts/modules/committers.py:
+
+2009-10-23 Eric Seidel <eric@webkit.org>
+
+ No review, only adding Alice to the list of reviewers.
+
+ * Scripts/modules/committers.py:
+
+2009-10-23 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Eric Carlson.
+
+ fast/media/mq-transform-02.html failed on Leopard Commit Bot
+ https://bugs.webkit.org/show_bug.cgi?id=30700
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (resetDefaultsToConsistentValues): Update QuickTime version check.
+
+2009-10-23 Kevin Ollivier <kevino@theolliviers.com>
+
+ wxMac 10.4 build fix, needs to link against WebKitSystemInterfaceTiger to get
+ character measurement APIs that are private on Tiger.
+
+ * wx/build/settings.py:
+
+2009-10-22 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by NOBODY (build fix).
+ Build fix following bug #30696.
+
+ * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+ (LayoutTestController::evaluateScriptInIsolatedWorld):
+
+2009-10-22 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig & Geoff Garen.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30696
+ Enable isolated-worlds tests on mac.
+
+ Add private interface for DRT to invoke execution in a given world.
+
+ * DumpRenderTree/LayoutTestController.cpp:
+ (evaluateScriptInIsolatedWorldCallback):
+ (LayoutTestController::staticFunctions):
+ * DumpRenderTree/LayoutTestController.h:
+ * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+ (LayoutTestController::evaluateScriptInIsolatedWorld):
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::evaluateScriptInIsolatedWorld):
+
+2009-10-21 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ bugzilla-tool's "patch failed to download an apply" error should give more information
+ https://bugs.webkit.org/show_bug.cgi?id=30632
+
+ * Scripts/modules/scm.py:
+ - Use the common run_command method instead of custom POpen code.
+ - Make run_command know how to take pipes as input.
+ * Scripts/modules/scm_unittest.py:
+ - Add new tests to cover change.
+ - Also move test_error_handlers into new SCMClassTests so we don't run it 3 times.
+
+2009-10-21 Kent Tamura <tkent@chromium.org>
+
+ Unreviewed. Adding myself to the committers list.
+
+ * Scripts/modules/committers.py:
+
+2009-10-21 Robin Dunn <robin@alldunn.com>
+
+ Reviewed by Kevin Ollivier.
+
+ Update the Windows installer builder to work with Vista / Win 7 and with git.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30649
+
+ * wx/build/build_utils.py:
+ * wx/packaging/build-mac-installer.py:
+ * wx/packaging/build-win-installer.py:
+ * wx/packaging/wxWebKitInstaller.iss.in:
+
+2009-10-21 Alejandro G. Castro <alex@igalia.com>
+
+ Reviewed by Gustavo Noronha.
+
+ [GTK] Added conditional code to avoid using
+ gdk_window_get_root_coords if we do not have a gtk+ release newer
+ than 2.17.3.
+ https://bugs.webkit.org/show_bug.cgi?id=30636
+
+ * WebKitTools/DumpRenderTree/gtk/EventSender.cpp:
+
+2009-10-21 Shu Chang <Chang.Shu@nokia.com>
+
+ Reviewed by Eric Seidel.
+
+ [Qt] Added dummy implementation for keepWebHistory()
+ https://bugs.webkit.org/show_bug.cgi?id=30592
+
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::keepWebHistory):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+
+2009-10-21 Alejandro G. Castro <alex@igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ [GTK] Fixed the double click condition, it is not double click if
+ we move in just in one direction.
+ https://bugs.webkit.org/show_bug.cgi?id=30636
+
+ * WebKitTools/DumpRenderTree/gtk/EventSender.cpp:
+
+2009-10-21 Alejandro G. Castro <alex@igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ [GTK] Initialize the events completly before emitting them.
+ https://bugs.webkit.org/show_bug.cgi?id=30633
+
+ * WebKitTools/DumpRenderTree/gtk/EventSender.cpp:
+
+2009-10-21 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fix. Fix for when linking using --as-needed with gcc.
+
+ * wx/browser/wscript:
+
+2009-10-21 Kevin Ollivier <kevino@theolliviers.com>
+
+ wxMac 10.4 build fix. Build and link against a version of libcurl new enough
+ to support all the features used by CURL backend.
+
+ * wx/build/settings.py:
+ * wx/install-unix-extras:
+
+2009-10-20 Anton Muhin <antonm@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Add {ager,antonm,yurys}@chromium.org into committers.py
+ https://bugs.webkit.org/show_bug.cgi?id=30560
+
+ * Scripts/modules/committers.py:
+
+2009-10-20 Kenneth Rohde Christiansen <kenneth@webkit.org>
+
+ Reviewed by Tor Arne Vestbø.
+
+ Make the Netscape Test plugin available to the Qt launcher.
+
+ * Scripts/run-launcher:
+
+2009-10-20 Fumitoshi Ukai <ukai@chromium.org>
+
+ Reviewed by David Levin.
+
+ Removed WebSocket runtime settings.
+ https://bugs.webkit.org/show_bug.cgi?id=29896
+
+ WebSocket runtime configuration is supported by chromium/v8 only.
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (resetDefaultsToConsistentValues):
+ * DumpRenderTree/win/DumpRenderTree.cpp:
+ (resetDefaultsToConsistentValues):
+
+2009-10-19 Nate Chapin <japhet@chromium.org>
+
+ Reviewed by Adam Barth.
+
+ Add testFail() to test plugin so we can test our handling of a
+ plugin invoke call returning false.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30239
+
+ * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp: Add testFail().
+ (pluginInvoke):
+ (testIdentifierToString): Always return true, since returning false will now cause an exception to be thrown.
+
+2009-10-19 Zan Dobersek <zandobersek@gmail.com>
+
+ Reviewed by Gustavo Noronha.
+
+ Enable DOM pasting when running layout tests.
+
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (resetDefaultsToConsistentValues):
+
+2009-10-18 Kenneth Rohde Christiansen <kenneth@webkit.org>
+
+ Reviewed by Simon Hausmann.
+
+ Use the setPreferredContentsSize method instead
+ of setFixedContentsSize, as the method has been renamed.
+
+ * DumpRenderTree/qt/DumpRenderTree.cpp:
+ (WebCore::DumpRenderTree::open):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::setFixedContentsSize):
+
+2009-10-16 Steve Falkenburg <sfalken@apple.com>
+
+ Reviewed by Dan Bernstein.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30456
+ Fixes for new Debug_All Windows build configuration.
+
+ * DumpRenderTree/win/DumpRenderTree.cpp:
+ (sharedCFURLCache): Use new DEBUG_ALL preprocessor define for library naming.
+ * DumpRenderTree/win/DumpRenderTree.vcproj: Remove unused DEBUG_WEBKIT_HAS_SUFFIX.
+
+2009-10-16 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ commit-queue status bot should list which buildbot is blocking the queue
+ https://bugs.webkit.org/show_bug.cgi?id=30452
+
+ Add new methods and testing.
+
+ * Scripts/bugzilla-tool:
+ * Scripts/modules/buildbot.py:
+ * Scripts/modules/buildbot_unittest.py:
+
+2009-10-16 Eric Seidel <eric@webkit.org>
+
+ Reviewed by Adam Barth.
+
+ run-webkit-tests fails when CWD is not inside a WebKit checkout
+ https://bugs.webkit.org/show_bug.cgi?id=30451
+
+ * Scripts/modules/scm.py: in_working_directory shouldn't throw exceptions on failure.
+ * Scripts/modules/scm_unittest.py:
+ - Remove use of original_path (we don't need to restore the CWD).
+ - Don't use '.' to find the webkit checkout, use __file__ instead.
+
+2009-10-16 Steve Falkenburg <sfalken@apple.com>
+
+ Reviewed by Adam Roben.
+
+ Add a Debug_All configuration to build entire stack as debug.
+ Change Debug_Internal to:
+ - stop using _debug suffix for all WebKit/Safari binaries
+ - not use _debug as a DLL naming suffix
+ - use non-debug C runtime lib.
+
+ * DumpRenderTree/DumpRenderTree.sln: Add Debug_All configuration.
+ * DumpRenderTree/win/DumpRenderTree.vcproj: Add Debug_All configuration.
+ * DumpRenderTree/win/ImageDiff.vcproj: Add Debug_All configuration.
+ * DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj:
+ Add missing debug.vsprops inherited property sheet.
+ Add Debug_All configuration.
+ * FindSafari/FindSafari.vcproj: Renamed single configuration from "Release" to "all".
+ * WinLauncher/WinLauncher.vcproj:
+ Removed extraneous definitions inherited from vsprops.
+ Add Debug_All configuration.
+
+2009-10-16 Carol Szabo <carol.szabo@nokia.com>
+
+ Reviewed by David Levin.
+
+ check-webkit-style is wrong about indent checking in namespaces
+ in header files and a few other things
+ https://bugs.webkit.org/show_bug.cgi?id=30362
+
+ The few other things include:
+ + check-webkit-style does not require spaces around the equal sign
+ inside 'if' statements and around binary operators that take
+ numeric literals.
+ + check-webkit-style reports false errors for the / operator
+ when part of a filename in the #include directive.
+
+ * Scripts/modules/cpp_style.py:
+ Improved indentation checking and space checking around
+ binary operators. While the checks are still not perfect,
+ they are clearly better than before.
+ * Scripts/modules/cpp_style_unittest.py:
+ Added test cases for the newly supported checks and modified old
+ test cases to match the new guidelines
+
+2009-10-16 Kevin Ollivier <kevino@theolliviers.com>
+
+ wxMSW build fix. Link to MSW library needed by PluginPackageWin.cpp.
+
+ * wx/build/settings.py:
+
+2009-10-15 Yuzo Fujishima <yuzo@google.com>
+
+ Reviewed by David Levin.
+
+ Add mod_pywebsocket to test Web Sockets.
+ http://code.google.com/p/pywebsocket/
+ https://bugs.webkit.org/show_bug.cgi?id=27490
+
+ * pywebsocket/COPYING: Added.
+ * pywebsocket/MANIFEST.in: Added.
+ * pywebsocket/README: Added.
+ * pywebsocket/example/echo_client.py: Added.
+ * pywebsocket/example/echo_wsh.py: Added.
+ * pywebsocket/mod_pywebsocket/__init__.py: Added.
+ * pywebsocket/mod_pywebsocket/dispatch.py: Added.
+ * pywebsocket/mod_pywebsocket/handshake.py: Added.
+ * pywebsocket/mod_pywebsocket/headerparserhandler.py: Added.
+ * pywebsocket/mod_pywebsocket/msgutil.py: Added.
+ * pywebsocket/mod_pywebsocket/standalone.py: Added.
+ * pywebsocket/mod_pywebsocket/util.py: Added.
+ * pywebsocket/setup.py: Added.
+ * pywebsocket/test/config.py: Added.
+ * pywebsocket/test/mock.py: Added.
+ * pywebsocket/test/run_all.py: Added.
+ * pywebsocket/test/test_dispatch.py: Added.
+ * pywebsocket/test/test_handshake.py: Added.
+ * pywebsocket/test/test_mock.py: Added.
+ * pywebsocket/test/test_msgutil.py: Added.
+ * pywebsocket/test/test_util.py: Added.
+ * pywebsocket/test/testdata/handlers/blank_wsh.py: Added.
+ * pywebsocket/test/testdata/handlers/origin_check_wsh.py: Added.
+ * pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py: Added.
+ * pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py: Added.
+ * pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py: Added.
+ * pywebsocket/test/testdata/handlers/sub/plain_wsh.py: Added.
+ * pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py: Added.
+ * pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py: Added.
+
+2009-10-15 James Robinson <jamesr@google.com>
+
+ Reviewed by David Levin.
+
+ Updates check-webkit-style to reflect that code inside a namespace should not be indented, even in a header file.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30426
+
+ * Scripts/modules/cpp_style.py:
+ * Scripts/modules/cpp_style_unittest.py:
+
+2009-10-15 Brian Weinstein <bweinstein@apple.com>
+
+ Reviewed by Adam Roben.
+
+ Fixes <http://webkit.org/b/30411>.
+ REGRESSION(49485): pdevenv doesn't compile in parallel for non-chromium builds on Windows.
+
+ Added a check for isChromium() in pdevenv, and pass /useenv if we are not
+ building Chromium.
+
+ * Scripts/pdevenv:
+
+2009-10-15 Robin Dunn <robin@alldunn.com>
+
+ Reviewed by Kevin Ollivier.
+
+ Add Mac package building scripts for wx.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30405
+
+ * wx/build/build_utils.py:
+ * wx/build/settings.py:
+ * wx/packaging/build-mac-installer.py: Added.
+
+2009-10-15 Zan Dobersek <zandobersek@gmail.com>
+
+ Reviewed by Gustavo Noronha.
+
+ Enable Web Sockets support when running layout tests.
+
+ * DumpRenderTree/gtk/DumpRenderTree.cpp:
+ (resetDefaultsToConsistentValues):
+
+2009-10-15 Xan Lopez <xlopez@igalia.com>
+
+ Reviewed by Gustavo Noronha.
+
+ Need to initialize event.button.button, since in most cases a
+ button number is not passed as an argument.
+
+ * DumpRenderTree/gtk/EventSender.cpp:
+ (mouseDownCallback):
+ (mouseUpCallback):
+
+2009-10-15 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fix. More SDK fixes for Mac, make sure we use the SDK corresponding to
+ the OS if none was explicitly set.
+
+ * wx/build/settings.py:
+
+2009-10-14 Pavel Feldman <pfeldman@chromium.org>
+
+ Reviewed by Timothy Hatcher.
+
+ Web Inspector: enable developers extras within inspector layout tests.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30014
+
+ * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+ (LayoutTestController::showWebInspector):
+ (LayoutTestController::closeWebInspector):
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::showWebInspector):
+ (LayoutTestController::closeWebInspector):
+
+2009-10-14 José Millán Soto <jmillan@igalia.com>
+
+ Reviewed by Jan Alonzo.
+
+ GtkLauncher is using a deprecated signal
+ https://bugs.webkit.org/show_bug.cgi?id=30364
+
+ Modified GtkLauncher to use notify::title signal instead of
+ deprecated title-changed signal
+
+ * GtkLauncher/main.c:
+ (notify_title_cb):
+ (create_browser):
+
+2009-10-14 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Don't set the history delegate on new windows that are opened during a test, as the history delegate:
+ 1 - Disables WebHistory
+ 2 - Doesn't make sense in that context anyway.
+
+ * DumpRenderTree/win/DumpRenderTree.cpp:
+ (createWebViewAndOffscreenWindow):
+
+2009-10-14 Kevin Ollivier <kevino@theolliviers.com>
+
+ wxMac build fix. Ensure 10.4 compatibility for deps, and allow the user to specify
+ the SDK to use since Python overrides any user-set value of MACOSX_DEPLOYMENT_TARGET.
+
+ * wx/build/settings.py:
+ * wx/install-unix-extras:
+
+2009-10-14 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ WebKit Win API should provide a delegate interface for global history.
+ https://bugs.webkit.org/show_bug.cgi?id=29905
+
+ * DumpRenderTree/LayoutTestController.cpp:
+ (LayoutTestController::LayoutTestController):
+ * DumpRenderTree/LayoutTestController.h:
+ (LayoutTestController::dumpHistoryDelegateCallbacks):
+ (LayoutTestController::setDumpHistoryDelegateCallbacks):
+
+ * DumpRenderTree/win/DumpRenderTree.cpp:
+ (shouldLogHistoryDelegates):
+ (runTest):
+ (createWebViewAndOffscreenWindow):
+ (main):
+ * DumpRenderTree/win/DumpRenderTree.vcproj:
+
+ Add the IWebHistoryDelegate to DRT Windows:
+ * DumpRenderTree/win/HistoryDelegate.cpp: Added.
+ (wstringFromBSTR):
+ (HistoryDelegate::HistoryDelegate):
+ (HistoryDelegate::~HistoryDelegate):
+ (HistoryDelegate::QueryInterface):
+ (HistoryDelegate::AddRef):
+ (HistoryDelegate::Release):
+ (HistoryDelegate::didNavigateWithNavigationData):
+ (HistoryDelegate::didPerformClientRedirectFromURL):
+ (HistoryDelegate::didPerformServerRedirectFromURL):
+ (HistoryDelegate::updateHistoryTitle):
+ (HistoryDelegate::populateVisitedLinksForWebView):
+ * DumpRenderTree/win/HistoryDelegate.h: Added.
+
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::removeAllVisitedLinks):
+
+2009-10-14 Shu Chang <Chang.Shu@nokia.com>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] Implement support for setPOSIXLocale on Qt.
+ https://bugs.webkit.org/show_bug.cgi?id=30268
+
+ * DumpRenderTree/qt/DumpRenderTree.cpp:
+ (WebCore::DumpRenderTree::resetToConsistentStateBeforeTesting):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+ (LayoutTestController::setPOSIXLocale):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h:
+
+2009-10-13 Stephanie Lewis <slewis@apple.com>
+
+ Unreviewed, adding myself to reviewers list.
+
+ * Scripts/modules/committers.py:
+
+2009-10-13 Stephanie Lewis <slewis@apple.com>
+
+ Reviewed by Mark Rowe.
+
+ Fix null assignment so root tests work again.
+
+ * Scripts/webkitdirs.pm:
+
+2009-10-13 Andras Becsi <becsi.andras@stud.u-szeged.hu>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] Refactor LayoutTestController, EventSender, TextInputController and WorkQueueItem classes
+ out of jsobjects into separate files to get a more structured DumpRenderTree implementation.
+ This is done in preparation of implementing missing features in DRT.
+ No functionality changes made yet.
+
+ * DumpRenderTree/qt/DumpRenderTree.cpp:
+ * DumpRenderTree/qt/DumpRenderTree.pro:
+ * DumpRenderTree/qt/EventSenderQt.cpp: Added.
+ (EventSender::EventSender):
+ (EventSender::mouseDown):
+ (EventSender::mouseUp):
+ (EventSender::mouseMoveTo):
+ (EventSender::leapForward):
+ (EventSender::keyDown):
+ (EventSender::contextClick):
+ (EventSender::scheduleAsynchronousClick):
+ (EventSender::frameUnderMouse):
+ * DumpRenderTree/qt/EventSenderQt.h: Added.
+ (EventSender::clearKillRing):
+ * DumpRenderTree/qt/LayoutTestControllerQt.cpp: Added.
+ (LayoutTestController::LayoutTestController):
+ (LayoutTestController::reset):
+ (LayoutTestController::processWork):
+ (LayoutTestController::maybeDump):
+ (LayoutTestController::waitUntilDone):
+ (LayoutTestController::notifyDone):
+ (LayoutTestController::windowCount):
+ (LayoutTestController::clearBackForwardList):
+ (LayoutTestController::dumpEditingCallbacks):
+ (LayoutTestController::dumpResourceLoadCallbacks):
+ (LayoutTestController::queueBackNavigation):
+ (LayoutTestController::queueForwardNavigation):
+ (LayoutTestController::queueLoad):
+ (LayoutTestController::queueReload):
+ (LayoutTestController::queueScript):
+ (LayoutTestController::provisionalLoad):
+ (LayoutTestController::timerEvent):
+ (LayoutTestController::encodeHostName):
+ (LayoutTestController::decodeHostName):
+ (LayoutTestController::setJavaScriptProfilingEnabled):
+ (LayoutTestController::setFixedContentsSize):
+ (LayoutTestController::setPrivateBrowsingEnabled):
+ (LayoutTestController::setPopupBlockingEnabled):
+ (LayoutTestController::pauseAnimationAtTimeOnElementWithId):
+ (LayoutTestController::pauseTransitionAtTimeOnElementWithId):
+ (LayoutTestController::numberOfActiveAnimations):
+ (LayoutTestController::disableImageLoading):
+ (LayoutTestController::dispatchPendingLoadRequests):
+ (LayoutTestController::setDatabaseQuota):
+ (LayoutTestController::clearAllDatabases):
+ (LayoutTestController::whiteListAccessFromOrigin):
+ (LayoutTestController::waitForPolicyDelegate):
+ (LayoutTestController::overridePreference):
+ * DumpRenderTree/qt/LayoutTestControllerQt.h: Added.
+ (LayoutTestController::isLoading):
+ (LayoutTestController::setLoading):
+ (LayoutTestController::shouldDumpAsText):
+ (LayoutTestController::shouldDumpBackForwardList):
+ (LayoutTestController::shouldDumpChildrenAsText):
+ (LayoutTestController::shouldDumpDatabaseCallbacks):
+ (LayoutTestController::shouldDumpStatusCallbacks):
+ (LayoutTestController::shouldWaitUntilDone):
+ (LayoutTestController::canOpenWindows):
+ (LayoutTestController::shouldDumpTitleChanges):
+ (LayoutTestController::waitForPolicy):
+ (LayoutTestController::dumpAsText):
+ (LayoutTestController::dumpChildFramesAsText):
+ (LayoutTestController::dumpDatabaseCallbacks):
+ (LayoutTestController::dumpStatusCallbacks):
+ (LayoutTestController::setCanOpenWindows):
+ (LayoutTestController::dumpBackForwardList):
+ (LayoutTestController::setCloseRemainingWindowsWhenComplete):
+ (LayoutTestController::display):
+ (LayoutTestController::dumpTitleChanges):
+ (LayoutTestController::dumpSelectionRect):
+ * DumpRenderTree/qt/TextInputControllerQt.cpp: Added.
+ (TextInputController::TextInputController):
+ (TextInputController::doCommand):
+ * DumpRenderTree/qt/TextInputControllerQt.h: Added.
+ * DumpRenderTree/qt/WorkQueue.cpp:
+ * DumpRenderTree/qt/WorkQueue.h:
+ * DumpRenderTree/qt/WorkQueueItem.h:
+ * DumpRenderTree/qt/WorkQueueItemQt.cpp: Added.
+ (findFrameNamed):
+ (LoadItem::invoke):
+ (ReloadItem::invoke):
+ (ScriptItem::invoke):
+ (BackForwardItem::invoke):
+ * DumpRenderTree/qt/jsobjects.cpp: Move all the above classes into separate files
+ * DumpRenderTree/qt/jsobjects.h:
+
+2009-10-13 Dmitry Titov <dimich@chromium.org>
+
+ Not reviewed, adding myself to the list of reviewers.
+
+ * Scripts/modules/committers.py:
+
+2009-10-13 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ <rdar://problem/6660507> Add "privacy mode" to Netscape Plug-in API
+
+ Make the private browsing mode testable by the test plug-in.
+
+ * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp:
+ (pluginGetProperty):
+ * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h:
+ * DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp:
+ (NPP_New):
+ (NPP_SetValue):
+
+2009-10-13 Pavel Feldman <pfeldman@chromium.org>
+
+ No review, just adding self to the list of reviewers.
+
+ * Scripts/modules/committers.py:
+
+2009-10-12 Pavel Feldman <pfeldman@chromium.org>
+
+ Reviewed by Adam Roben.
+
+ Web Inspector: Use proper web view in inspector layout
+ tests for windows.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30298
+
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::showWebInspector):
+ (LayoutTestController::closeWebInspector):
+ (LayoutTestController::evaluateInWebInspector):
+
+2009-10-12 Fumitoshi Ukai <ukai@chromium.org>
+
+ Reviewed by Sam Weinig.
+
+ Enable experimentalWebSocket in DumpRenderTree for LayoutTest.
+ https://bugs.webkit.org/show_bug.cgi?id=29841
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (resetDefaultsToConsistentValues):
+ * DumpRenderTree/win/DumpRenderTree.cpp:
+ (resetDefaultsToConsistentValues):
+
+2009-10-12 Yaar Schnitman <yaar@chromium.org>
+
+ Reviewed by Dimitri Glazkov.
+
+ Chromium Port - Windows
+ https://bugs.webkit.org/show_bug.cgi?id=29969
+
+ * Scripts/pdevenv: removed msvc's /useenv for chromium builds
+ * Scripts/webkitdirs.pm:
+
+2009-10-12 Csaba Osztrogonac <ossy@webkit.org>
+
+ Reviewed by Darin Adler.
+
+ jsc scripts cleanup and Qt/GTK fix
+ https://bugs.webkit.org/show_bug.cgi?id=30288
+
+ Duplicated jscPath() moved to webkitdirs.pm.
+ New jscProductDir() added to webkitdirs.pm instead of duplicated codes.
+ Configuration added (release/debug) to path for Qt-port on Windows.
+
+ * Scripts/run-javascriptcore-tests:
+ * Scripts/run-jsc:
+ * Scripts/run-sunspider:
+ * Scripts/sunspider-compare-results:
+ * Scripts/webkitdirs.pm:
+
+2009-10-11 Adam Barth <abarth@webkit.org>
+
+ Unreviewed. Add Collin to committers.py.
+
+ * Scripts/modules/committers.py:
+
+2009-10-11 Kevin Ollivier <kevino@theolliviers.com>
+
+ wx build fix, add bindings to source/include dirs now that there are sources there.
+
+ * wx/build/settings.py:
+
+2009-10-09 Mark Rowe <mrowe@apple.com>
+
+ Reviewed by Brady Eidson.
+
+ Enable plug-in halting in DumpRenderTree.
+
+ We drop the plug-in halting delay to 1 second and opt in the delegate method to never halt plug-ins.
+ This is sufficient to ensure that the crash covered by <rdar://problem/7290671> no longer occurs.
+
+ * DumpRenderTree/mac/DumpRenderTree.mm:
+ (resetDefaultsToConsistentValues):
+ * DumpRenderTree/mac/UIDelegate.mm:
+ (-[UIDelegate webView:shouldHaltPlugin:]):
+
+2009-10-08 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Dan Bernstein.
+
+ Ask the History Delegate to populate the visited links hash.
+ <rdar://problem/7285293> and https://webkit.org/b/29904
+
+ Add the ability for LayoutTestController to clear all visited links.
+ Also lets the History Delegate dump visited links, but only if this test specifically cleared them.
+
+ * DumpRenderTree/LayoutTestController.cpp:
+ (LayoutTestController::LayoutTestController):
+ (removeAllVisitedLinksCallback):
+ (LayoutTestController::staticFunctions):
+ * DumpRenderTree/LayoutTestController.h:
+ * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+ (LayoutTestController::removeAllVisitedLinks):
+
+ * DumpRenderTree/mac/HistoryDelegate.mm:
+ (-[HistoryDelegate populateVisitedLinksForWebView:]):
+
+ * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+ (LayoutTestController::removeAllVisitedLinks):
+ * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+ (LayoutTestController::removeAllVisitedLinks):
+ * DumpRenderTree/wx/LayoutTestControllerWx.cpp:
+ (LayoutTestController::removeAllVisitedLinks):
+
+
+2009-10-08 Daniel Bates <dbates@webkit.org>
+
+ Reviewed by Adam Roben.
+
+ https://bugs.webkit.org/show_bug.cgi?id=30175
+
+ The Windows DRT equivalent of DoDragDrop (i.e. UIDelegate::doDragDrop) does not return
+ the OLE drag-and-drop return value like the function it emulates. Currently,
+ UIDelegate::doDragDrop returns a hard-coded S_OK. Hence, the caller cannot determine
+ whether the drag-and-drop operation was successful or was cancelled.
+
+ This patch fixes this issue by having UIDelegate::doDragDrop return the OLE drag-and-drop
+ return value according to whether the drop operation was successful or not.
+
+ * DumpRenderTree/win/EventSender.cpp:
+ (doMouseUp): Added parameter oleDragAndDropReturnValue.
+ (replaySavedEvents): Ditto.
+ * DumpRenderTree/win/EventSender.h:
+ * DumpRenderTree/win/UIDelegate.cpp:
+ (UIDelegate::doDragDrop): Modified to return OLE drag-and-drop return value.
+
+2009-10-08 Alejandro G. Castro <alex@igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ [GTK] Added support for a parameter setting the button that was
+ pressed in the mouseDown function.
+ https://bugs.webkit.org/show_bug.cgi?id=30220
+
+ * WebKitTools/DumpRenderTree/gtk/EventSender.cpp:
+
+2009-10-08 Alejandro G. Castro <alex@igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ [GTK] Added a line to the bottom of the expected result to match
+ the output of the test.
+ https://bugs.webkit.org/show_bug.cgi?id=30220
+
+ * LayoutTests/platform/gtk/editing/pasteboard/middle-click-onpaste-
+ expected.txt:
+
2009-10-08 Adam Roben <aroben@apple.com>
Use QueryInterface to get IWebInspectorPrivate
diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.sln b/WebKitTools/DumpRenderTree/DumpRenderTree.sln
index 43d2b61..399c002 100644
--- a/WebKitTools/DumpRenderTree/DumpRenderTree.sln
+++ b/WebKitTools/DumpRenderTree/DumpRenderTree.sln
@@ -11,29 +11,38 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiff", "win\ImageDiff.
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug_All|Win32 = Debug_All|Win32
Debug_Internal|Win32 = Debug_Internal|Win32
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_All|Win32.Build.0 = Debug_All|Win32
{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_All|Win32.ActiveCfg = Debug_All|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_All|Win32.Build.0 = Debug_All|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
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug_All|Win32.ActiveCfg = all|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug_All|Win32.Build.0 = all|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug_Internal|Win32.ActiveCfg = all|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug_Internal|Win32.Build.0 = all|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug|Win32.ActiveCfg = all|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug|Win32.Build.0 = all|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Release|Win32.ActiveCfg = all|Win32
+ {DA31DA52-6675-48D4-89E0-333A7144397C}.Release|Win32.Build.0 = all|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.Build.0 = Debug_All|Win32
{59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_Internal|Win32.ActiveCfg = Debug_Internal|Win32
{59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_Internal|Win32.Build.0 = Debug_Internal|Win32
{59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.ActiveCfg = Debug|Win32
diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp
index 1f34325..daf888f 100644
--- a/WebKitTools/DumpRenderTree/LayoutTestController.cpp
+++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp
@@ -31,6 +31,7 @@
#include "WorkQueue.h"
#include "WorkQueueItem.h"
+#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSObjectRef.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <stdio.h>
@@ -48,12 +49,14 @@ LayoutTestController::LayoutTestController(const std::string& testPathOrURL, con
, m_dumpDatabaseCallbacks(false)
, m_dumpEditingCallbacks(false)
, m_dumpFrameLoadCallbacks(false)
+ , m_dumpHistoryDelegateCallbacks(false)
, m_dumpResourceLoadCallbacks(false)
, m_dumpResourceResponseMIMETypes(false)
, m_dumpSelectionRect(false)
, m_dumpSourceAsWebArchive(false)
, m_dumpStatusCallbacks(false)
, m_dumpTitleChanges(false)
+ , m_dumpVisitedLinksCallback(false)
, m_dumpWillCacheResponse(false)
, m_callCloseOnWebViews(true)
, m_canOpenWindows(false)
@@ -204,6 +207,14 @@ static JSValueRef pathToLocalResourceCallback(JSContextRef context, JSObjectRef
return JSValueMakeString(context, convertedPath.get());
}
+static JSValueRef removeAllVisitedLinksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+ controller->setDumpVisitedLinksCallback(true);
+ controller->removeAllVisitedLinks();
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef repaintSweepHorizontallyCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
@@ -374,6 +385,22 @@ static JSValueRef execCommandCallback(JSContextRef context, JSObjectRef function
return JSValueMakeUndefined(context);
}
+static JSValueRef counterValueForElementByIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ JSRetainPtr<JSStringRef> elementId(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+ if (*exception)
+ return JSValueMakeUndefined(context);
+
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+ JSRetainPtr<JSStringRef> counterValue(controller->counterValueForElementById(elementId.get()));
+ if (!counterValue.get())
+ return JSValueMakeUndefined(context);
+ return JSValueMakeString(context, counterValue.get());
+}
+
static JSValueRef grantDesktopNotificationPermissionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
// Has Windows implementation
@@ -968,6 +995,18 @@ static JSValueRef evaluateInWebInspectorCallback(JSContextRef context, JSObjectR
return JSValueMakeUndefined(context);
}
+static JSValueRef evaluateScriptInIsolatedWorldCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+ double worldID = JSValueToNumber(context, arguments[0], exception);
+ ASSERT(!*exception);
+ JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[1], exception));
+ ASSERT(!*exception);
+
+ controller->evaluateScriptInIsolatedWorld(static_cast<unsigned>(worldID), JSContextGetGlobalObject(context), script.get());
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef elementDoesAutoCompleteForElementWithIdCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
@@ -1176,7 +1215,9 @@ JSStaticFunction* LayoutTestController::staticFunctions()
{ "elementDoesAutoCompleteForElementWithId", elementDoesAutoCompleteForElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "evaluateInWebInspector", evaluateInWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "evaluateScriptInIsolatedWorld", evaluateScriptInIsolatedWorldCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "execCommand", execCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "counterValueForElementById", counterValueForElementByIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "grantDesktopNotificationPermission", grantDesktopNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isCommandEnabled", isCommandEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1193,6 +1234,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
{ "queueLoadingScript", queueLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "queueNonLoadingScript", queueNonLoadingScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "queueReload", queueReloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "removeAllVisitedLinks", removeAllVisitedLinksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "repaintSweepHorizontally", repaintSweepHorizontallyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setAlwaysAcceptCookies", setAlwaysAcceptCookiesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h
index 7c829ef..79ffb99 100644
--- a/WebKitTools/DumpRenderTree/LayoutTestController.h
+++ b/WebKitTools/DumpRenderTree/LayoutTestController.h
@@ -30,6 +30,7 @@
#define LayoutTestController_h
#include <JavaScriptCore/JSObjectRef.h>
+#include <JavaScriptCore/JSRetainPtr.h>
#include <wtf/RefCounted.h>
#include <string>
#include <vector>
@@ -51,6 +52,7 @@ public:
void dispatchPendingLoadRequests();
void display();
void execCommand(JSStringRef name, JSStringRef value);
+ JSRetainPtr<JSStringRef> counterValueForElementById(JSStringRef id);
bool isCommandEnabled(JSStringRef name);
void keepWebHistory();
void notifyDone();
@@ -62,6 +64,7 @@ public:
void queueLoadingScript(JSStringRef script);
void queueNonLoadingScript(JSStringRef script);
void queueReload();
+ void removeAllVisitedLinks();
void setAcceptsEditing(bool acceptsEditing);
void setAppCacheMaximumSize(unsigned long long quota);
void setAuthorAndUserStylesEnabled(bool);
@@ -120,6 +123,9 @@ public:
bool dumpFrameLoadCallbacks() const { return m_dumpFrameLoadCallbacks; }
void setDumpFrameLoadCallbacks(bool dumpFrameLoadCallbacks) { m_dumpFrameLoadCallbacks = dumpFrameLoadCallbacks; }
+ bool dumpHistoryDelegateCallbacks() const { return m_dumpHistoryDelegateCallbacks; }
+ void setDumpHistoryDelegateCallbacks(bool dumpHistoryDelegateCallbacks) { m_dumpHistoryDelegateCallbacks = dumpHistoryDelegateCallbacks; }
+
bool dumpResourceLoadCallbacks() const { return m_dumpResourceLoadCallbacks; }
void setDumpResourceLoadCallbacks(bool dumpResourceLoadCallbacks) { m_dumpResourceLoadCallbacks = dumpResourceLoadCallbacks; }
@@ -137,6 +143,9 @@ public:
bool dumpTitleChanges() const { return m_dumpTitleChanges; }
void setDumpTitleChanges(bool dumpTitleChanges) { m_dumpTitleChanges = dumpTitleChanges; }
+
+ bool dumpVisitedLinksCallback() const { return m_dumpVisitedLinksCallback; }
+ void setDumpVisitedLinksCallback(bool dumpVisitedLinksCallback) { m_dumpVisitedLinksCallback = dumpVisitedLinksCallback; }
bool dumpWillCacheResponse() const { return m_dumpWillCacheResponse; }
void setDumpWillCacheResponse(bool dumpWillCacheResponse) { m_dumpWillCacheResponse = dumpWillCacheResponse; }
@@ -206,6 +215,7 @@ public:
void showWebInspector();
void closeWebInspector();
void evaluateInWebInspector(long callId, JSStringRef script);
+ void evaluateScriptInIsolatedWorld(unsigned worldId, JSObjectRef globalObject, JSStringRef script);
void setPOSIXLocale(JSStringRef locale);
@@ -219,12 +229,14 @@ private:
bool m_dumpDatabaseCallbacks;
bool m_dumpEditingCallbacks;
bool m_dumpFrameLoadCallbacks;
+ bool m_dumpHistoryDelegateCallbacks;
bool m_dumpResourceLoadCallbacks;
bool m_dumpResourceResponseMIMETypes;
bool m_dumpSelectionRect;
bool m_dumpSourceAsWebArchive;
bool m_dumpStatusCallbacks;
bool m_dumpTitleChanges;
+ bool m_dumpVisitedLinksCallback;
bool m_dumpWillCacheResponse;
bool m_callCloseOnWebViews;
bool m_canOpenWindows;
diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
index 3a04c3c..14280ba 100644
--- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
+++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp
@@ -106,13 +106,17 @@ NPClass *getPluginClass(void)
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 ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM 5
-#define NUM_PROPERTY_IDENTIFIERS 6
+enum {
+ ID_PROPERTY_PROPERTY = 0,
+ ID_PROPERTY_EVENT_LOGGING,
+ ID_PROPERTY_HAS_STREAM,
+ ID_PROPERTY_TEST_OBJECT,
+ ID_PROPERTY_LOG_DESTROY,
+ ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM,
+ ID_PROPERTY_PRIVATE_BROWSING_ENABLED,
+ ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED,
+ NUM_PROPERTY_IDENTIFIERS
+};
static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
@@ -122,6 +126,8 @@ static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
"testObject",
"logDestroy",
"returnErrorFromNewStream",
+ "privateBrowsingEnabled",
+ "cachedPrivateBrowsingEnabled",
};
enum {
@@ -144,6 +150,7 @@ enum {
ID_TEST_POSTURL_FILE,
ID_TEST_CONSTRUCT,
ID_TEST_THROW_EXCEPTION_METHOD,
+ ID_TEST_FAIL_METHOD,
ID_DESTROY_NULL_STREAM,
NUM_METHOD_IDENTIFIERS
};
@@ -169,6 +176,7 @@ static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
"testPostURLFile",
"testConstruct",
"testThrowException",
+ "testFail",
"destroyNullStream"
};
@@ -226,6 +234,14 @@ static bool pluginGetProperty(NPObject* obj, NPIdentifier name, NPVariant* resul
} else if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result);
return true;
+ } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_PRIVATE_BROWSING_ENABLED]) {
+ NPBool privateBrowsingEnabled = FALSE;
+ browser->getvalue(plugin->npp, NPNVprivateModeBool, &privateBrowsingEnabled);
+ BOOLEAN_TO_NPVARIANT(privateBrowsingEnabled, *result);
+ return true;
+ } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED]) {
+ BOOLEAN_TO_NPVARIANT(plugin->cachedPrivateBrowsingMode, *result);
+ return true;
}
return false;
}
@@ -309,13 +325,13 @@ static NPIdentifier variantToIdentifier(NPVariant variant)
static bool testIdentifierToString(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
if (argCount != 1)
- return false;
+ return true;
NPIdentifier identifier = variantToIdentifier(args[0]);
if (!identifier)
- return false;
+ return true;
NPUTF8* utf8String = browser->utf8fromidentifier(identifier);
if (!utf8String)
- return false;
+ return true;
STRINGZ_TO_NPVARIANT(utf8String, *result);
return true;
}
@@ -669,6 +685,10 @@ static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* a
else if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) {
browser->setexception(header, "plugin object testThrowException SUCCESS");
return true;
+ } else if (name == pluginMethodIdentifiers[ID_TEST_FAIL_METHOD]) {
+ NPObject* windowScriptObject;
+ browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject);
+ browser->invoke(plugin->npp, windowScriptObject, name, args, argCount, result);
} else if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM])
return destroyNullStream(plugin, args, argCount, result);
diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h
index 17b11e1..7437d04 100644
--- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h
+++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.h
@@ -35,6 +35,7 @@ typedef struct {
NPBool logSetWindow;
NPBool logDestroy;
NPBool returnErrorFromNewStream;
+ NPBool cachedPrivateBrowsingMode;
NPObject* testObject;
NPStream* stream;
char* onStreamLoad;
diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp
index 88618c3..125d2e8 100644
--- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp
+++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp
@@ -130,7 +130,9 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, ch
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
+ browser->getvalue(instance, NPNVprivateModeBool, (void *)&obj->cachedPrivateBrowsingMode);
browser->setvalue(instance, NPPVpluginEventModel, (void *)obj->eventModel);
+
return NPERR_NO_ERROR;
}
@@ -383,5 +385,13 @@ NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
{
- return NPERR_GENERIC_ERROR;
+ PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
+
+ switch (variable) {
+ case NPNVprivateModeBool:
+ obj->cachedPrivateBrowsingMode = *(NPBool*)value;
+ return NPERR_NO_ERROR;
+ default:
+ return NPERR_GENERIC_ERROR;
+ }
}
diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
index 6ecd774..4ed6e36 100644
--- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
@@ -319,6 +319,8 @@ static void resetDefaultsToConsistentValues()
"enable-offline-web-application-cache", TRUE,
"enable-universal-access-from-file-uris", TRUE,
"enable-scripts", TRUE,
+ "enable-web-sockets", TRUE,
+ "enable-dom-paste", TRUE,
"default-font-family", "Times",
"monospace-font-family", "Courier",
"serif-font-family", "Times",
@@ -706,6 +708,11 @@ static void databaseQuotaExceeded(WebKitWebView* view, WebKitWebFrame* frame, We
static WebKitWebView* webViewCreate(WebKitWebView*, WebKitWebFrame*);
+static WebKitWebView* webInspectorInspectWebView(WebKitWebInspector*, gpointer data)
+{
+ return WEBKIT_WEB_VIEW(webkit_web_view_new());
+}
+
static WebKitWebView* createWebView()
{
WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
@@ -730,6 +737,9 @@ static WebKitWebView* createWebView()
"signal::database-quota-exceeded", databaseQuotaExceeded, 0,
NULL);
+ WebKitWebInspector* inspector = webkit_web_view_get_inspector(view);
+ g_signal_connect(inspector, "inspect-web-view", G_CALLBACK(webInspectorInspectWebView), 0);
+
return view;
}
diff --git a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp
index c3c72c1..f42928c 100644
--- a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp
@@ -53,6 +53,7 @@ extern "C" {
}
static bool down = false;
+static bool currentEventButton = 1;
static bool dragMode = true;
static bool replayingSavedEvents = false;
static int lastMousePositionX;
@@ -122,12 +123,27 @@ static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef functio
static void updateClickCount(int /* button */)
{
// FIXME: take the last clicked button number and the time of last click into account.
- if (lastClickPositionX != lastMousePositionX && lastClickPositionY != lastMousePositionY)
+ if (lastClickPositionX != lastMousePositionX || lastClickPositionY != lastMousePositionY)
clickCount = 1;
else
clickCount++;
}
+#if !GTK_CHECK_VERSION(2,17,3)
+static void getRootCoords(GtkWidget* view, int* rootX, int* rootY)
+{
+ GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(view));
+ int tmpX, tmpY;
+
+ gtk_widget_translate_coordinates(view, window, lastMousePositionX, lastMousePositionY, &tmpX, &tmpY);
+
+ gdk_window_get_origin(window->window, rootX, rootY);
+
+ *rootX += tmpX;
+ *rootY += tmpY;
+}
+#endif
+
static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
@@ -140,9 +156,29 @@ static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function,
memset(&event, 0, sizeof(event));
event.type = GDK_BUTTON_PRESS;
event.button.button = 1;
+
+ if (argumentCount == 1) {
+ event.button.button = (int)JSValueToNumber(context, arguments[0], exception) + 1;
+ g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
+ }
+
+ currentEventButton = event.button.button;
+
event.button.x = lastMousePositionX;
event.button.y = lastMousePositionY;
event.button.window = GTK_WIDGET(view)->window;
+ event.button.time = GDK_CURRENT_TIME;
+ event.button.device = gdk_device_get_core_pointer();
+
+ int x_root, y_root;
+#if GTK_CHECK_VERSION(2,17,3)
+ gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &x_root, &y_root);
+#else
+ getRootCoords(GTK_WIDGET(view), &x_root, &y_root);
+#endif
+
+ event.button.x_root = x_root;
+ event.button.y_root = y_root;
updateClickCount(1);
@@ -177,9 +213,29 @@ static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JS
memset(&event, 0, sizeof(event));
event.type = GDK_BUTTON_RELEASE;
event.button.button = 1;
+
+ if (argumentCount == 1) {
+ event.button.button = (int)JSValueToNumber(context, arguments[0], exception) + 1;
+ g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
+ }
+
+ currentEventButton = event.button.button;
+
event.button.x = lastMousePositionX;
event.button.y = lastMousePositionY;
event.button.window = GTK_WIDGET(view)->window;
+ event.button.time = GDK_CURRENT_TIME;
+ event.button.device = gdk_device_get_core_pointer();
+
+ int x_root, y_root;
+#if GTK_CHECK_VERSION(2,17,3)
+ gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &x_root, &y_root);
+#else
+ getRootCoords(GTK_WIDGET(view), &x_root, &y_root);
+#endif
+
+ event.button.x_root = x_root;
+ event.button.y_root = y_root;
if ((dragMode && !replayingSavedEvents) || msgQueue[endOfQueue].delay) {
msgQueue[endOfQueue].event = event;
@@ -213,11 +269,33 @@ static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function
g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
GdkEvent event;
+ memset(&event, 0, sizeof(event));
event.type = GDK_MOTION_NOTIFY;
event.motion.x = lastMousePositionX;
event.motion.y = lastMousePositionY;
event.motion.time = GDK_CURRENT_TIME;
event.motion.window = GTK_WIDGET(view)->window;
+ event.motion.device = gdk_device_get_core_pointer();
+
+ int x_root, y_root;
+#if GTK_CHECK_VERSION(2,17,3)
+ gdk_window_get_root_coords(GTK_WIDGET(view)->window, lastMousePositionX, lastMousePositionY, &x_root, &y_root);
+#else
+ getRootCoords(GTK_WIDGET(view), &x_root, &y_root);
+#endif
+
+ event.motion.x_root = x_root;
+ event.motion.y_root = y_root;
+
+ if (down) {
+ if (currentEventButton == 1)
+ event.motion.state = GDK_BUTTON1_MASK;
+ else if (currentEventButton == 2)
+ event.motion.state = GDK_BUTTON2_MASK;
+ else if (currentEventButton == 3)
+ event.motion.state = GDK_BUTTON3_MASK;
+ } else
+ event.motion.state = 0;
if (dragMode && down && !replayingSavedEvents) {
msgQueue[endOfQueue].event = event;
diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
index 0b4a38f..631fc31 100644
--- a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
+++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
* Copyright (C) 2008 Nuanti Ltd.
* Copyright (C) 2009 Jan Michael Alonzo <jmalonzo@gmail.com>
+ * Copyright (C) 2009 Collabora Ltd.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -52,6 +53,8 @@ unsigned int webkit_web_frame_number_of_active_animations(WebKitWebFrame* frame)
void webkit_application_cache_set_maximum_size(unsigned long long size);
unsigned int webkit_worker_thread_count(void);
void webkit_white_list_access_from_origin(const gchar* sourceOrigin, const gchar* destinationProtocol, const gchar* destinationHost, bool allowDestinationSubdomains);
+gchar* webkit_web_frame_counter_value_for_element_by_id(WebKitWebFrame* frame, const gchar* id);
+void webkit_web_inspector_execute_script(WebKitWebInspector* inspector, long callId, const gchar* script);
}
static gchar* copyWebSettingKey(gchar* preferenceKey)
@@ -118,6 +121,17 @@ void LayoutTestController::display()
displayWebView();
}
+JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
+{
+ gchar* idGChar = JSStringCopyUTF8CString(id);
+ gchar* counterValueGChar = webkit_web_frame_counter_value_for_element_by_id(mainFrame, idGChar);
+ g_free(idGChar);
+ if (!counterValueGChar)
+ return 0;
+ JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithUTF8CString(counterValueGChar));
+ return counterValue;
+}
+
void LayoutTestController::keepWebHistory()
{
// FIXME: implement
@@ -474,15 +488,40 @@ void LayoutTestController::addUserStyleSheet(JSStringRef source)
void LayoutTestController::showWebInspector()
{
- // FIXME: Implement this.
+ WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
+ WebKitWebSettings* webSettings = webkit_web_view_get_settings(webView);
+ WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
+
+ g_object_set(webSettings, "enable-developer-extras", TRUE, NULL);
+ webkit_web_inspector_inspect_coordinates(inspector, 0, 0);
}
void LayoutTestController::closeWebInspector()
{
- // FIXME: Implement this.
+ WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
+ WebKitWebSettings* webSettings = webkit_web_view_get_settings(webView);
+ WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
+
+ webkit_web_inspector_close(inspector);
+ g_object_set(webSettings, "enable-developer-extras", FALSE, NULL);
}
void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
{
+ WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
+ WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
+ char* scriptString = JSStringCopyUTF8CString(script);
+
+ webkit_web_inspector_execute_script(inspector, callId, scriptString);
+ g_free(scriptString);
+}
+
+void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
+{
+ // FIXME: Implement this.
+}
+
+void LayoutTestController::removeAllVisitedLinks()
+{
// FIXME: Implement this.
}
diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig
index 79d1e14..a72dd7d 100644
--- a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig
+++ b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig
@@ -22,11 +22,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
HEADER_SEARCH_PATHS = ForwardingHeaders mac/InternalHeaders;
-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
+FRAMEWORK_SEARCH_PATHS = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks;
GCC_PREPROCESSOR_DEFINITIONS = ENABLE_DASHBOARD_SUPPORT WEBKIT_VERSION_MIN_REQUIRED=WEBKIT_VERSION_LATEST;
DEBUG_INFORMATION_FORMAT = dwarf
PREBINDING = NO
diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig
index 05af1e5..96a39a9 100644
--- a/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig
+++ b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig
@@ -28,6 +28,7 @@ ARCHS_ = $(ARCHS_1040);
ARCHS_1040 = $(NATIVE_ARCH);
ARCHS_1050 = $(NATIVE_ARCH);
ARCHS_1060 = $(ARCHS_STANDARD_32_64_BIT);
+ARCHS_1070 = $(ARCHS_STANDARD_32_64_BIT);
ONLY_ACTIVE_ARCH = YES;
@@ -36,3 +37,4 @@ MACOSX_DEPLOYMENT_TARGET_ = 10.4;
MACOSX_DEPLOYMENT_TARGET_1040 = 10.4;
MACOSX_DEPLOYMENT_TARGET_1050 = 10.5;
MACOSX_DEPLOYMENT_TARGET_1060 = 10.6;
+MACOSX_DEPLOYMENT_TARGET_1070 = 10.7;
diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
index 0c33381..98f4f9c 100644
--- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
+++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
@@ -409,7 +409,7 @@ static void resetDefaultsToConsistentValues()
[preferences setCacheModel:WebCacheModelDocumentBrowser];
[preferences setXSSAuditorEnabled:NO];
[preferences setExperimentalNotificationsEnabled:NO];
- [preferences setExperimentalWebSocketsEnabled:NO];
+ [preferences setPluginAllowedRunTime:1];
[preferences setPrivateBrowsingEnabled:NO];
[preferences setAuthorAndUserStylesEnabled:YES];
@@ -434,9 +434,9 @@ static void resetDefaultsToConsistentValues()
SInt32 qtVersion;
OSErr err = Gestalt(gestaltQuickTimeVersion, &qtVersion);
assert(err == noErr);
- // Bug 7228836 exists in at least 7.6.3 and 7.6.4, hopefully it will be fixed in 7.6.5.
+ // Bug 7228836 exists in at least 7.6.3 through 7.6.4, hopefully it will be fixed in 7.6.5.
// FIXME: Once we know the exact versions of QuickTime affected, we can update this check.
- if (qtVersion <= 0x07640000)
+ if (qtVersion <= 0x07648000) // 7.6.4, final release (0x8). See http://developer.apple.com/mac/library/techn
[preferences setAcceleratedCompositingEnabled:NO];
else
#endif
diff --git a/WebKitTools/DumpRenderTree/mac/HistoryDelegate.mm b/WebKitTools/DumpRenderTree/mac/HistoryDelegate.mm
index 9e2b836..cbc4093 100644
--- a/WebKitTools/DumpRenderTree/mac/HistoryDelegate.mm
+++ b/WebKitTools/DumpRenderTree/mac/HistoryDelegate.mm
@@ -29,6 +29,7 @@
#import "LayoutTestController.h"
#import <WebKit/WebNavigationData.h>
+#import <WebKit/WebView.h>
@interface NSURL (DRTExtras)
- (NSString *)_drt_descriptionSuitableForTestResult;
@@ -71,4 +72,10 @@
printf("WebView updated the title for history URL \"%s\" to \"%s\".\n", [[[NSURL URLWithString:url]_drt_descriptionSuitableForTestResult] UTF8String], [title UTF8String]);
}
+- (void)populateVisitedLinksForWebView:(WebView *)webView
+{
+ if (gLayoutTestController->dumpVisitedLinksCallback())
+ printf("Asked to populate visited links for WebView \"%s\"\n", [[[NSURL URLWithString:[webView mainFrameURL]] _drt_descriptionSuitableForTestResult] UTF8String]);
+}
+
@end
diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
index 233c5fd..4d6a609 100644
--- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
+++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
@@ -42,6 +42,7 @@
#import <WebKit/DOMElement.h>
#import <WebKit/WebApplicationCache.h>
#import <WebKit/WebBackForwardList.h>
+#import <WebKit/WebCoreStatistics.h>
#import <WebKit/WebDatabaseManagerPrivate.h>
#import <WebKit/WebDataSource.h>
#import <WebKit/WebFrame.h>
@@ -151,6 +152,19 @@ void LayoutTestController::display()
displayWebView();
}
+JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
+{
+ RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id));
+ NSString *idNS = (NSString *)idCF.get();
+
+ DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS];
+ if (!element)
+ return 0;
+
+ JSRetainPtr<JSStringRef> counterValue(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame counterValueForElement:element]));
+ return counterValue;
+}
+
void LayoutTestController::keepWebHistory()
{
if (![WebHistory optionalSharedHistory]) {
@@ -333,6 +347,11 @@ void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value
[[WebPreferences standardPreferences] _setPreferenceForTestWithValue:valueNS forKey:keyNS];
}
+void LayoutTestController::removeAllVisitedLinks()
+{
+ [WebHistory _removeAllVisitedLinks];
+}
+
void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
{
RetainPtr<CFStringRef> urlString(AdoptCF, JSStringCopyCFString(0, jsURL));
@@ -482,24 +501,26 @@ void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart)
{
RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
NSString *sourceNS = (NSString *)sourceCF.get();
- [WebView _addUserScriptToGroup:@"org.webkit.DumpRenderTree" source:sourceNS url:nil worldID:1 whitelist:nil blacklist:nil injectionTime:(runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd)];
+ [WebView _addUserScriptToGroup:@"org.webkit.DumpRenderTree" worldID:1 source:sourceNS url:nil whitelist:nil blacklist:nil injectionTime:(runAtStart ? WebInjectAtDocumentStart : WebInjectAtDocumentEnd)];
}
void LayoutTestController::addUserStyleSheet(JSStringRef source)
{
RetainPtr<CFStringRef> sourceCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, source));
NSString *sourceNS = (NSString *)sourceCF.get();
- [WebView _addUserStyleSheetToGroup:@"org.webkit.DumpRenderTree" source:sourceNS url:nil worldID:1 whitelist:nil blacklist:nil];
+ [WebView _addUserStyleSheetToGroup:@"org.webkit.DumpRenderTree" worldID:1 source:sourceNS url:nil whitelist:nil blacklist:nil];
}
void LayoutTestController::showWebInspector()
{
+ [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:true];
[[[mainFrame webView] inspector] show:nil];
}
void LayoutTestController::closeWebInspector()
{
[[[mainFrame webView] inspector] close:nil];
+ [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:false];
}
void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
@@ -508,3 +529,10 @@ void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef scrip
NSString *scriptNS = (NSString *)scriptCF.get();
[[[mainFrame webView] inspector] evaluateInFrontend:nil callId:callId script:scriptNS];
}
+
+void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
+{
+ RetainPtr<CFStringRef> scriptCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, script));
+ NSString *scriptNS = (NSString *)scriptCF.get();
+ [mainFrame _stringByEvaluatingJavaScriptInIsolatedWorld:worldID WithGlobalObject:globalObject FromString:scriptNS];
+}
diff --git a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm
index a52d5be..393899e 100644
--- a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm
+++ b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm
@@ -157,6 +157,11 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil;
[geolocation setIsAllowed:gLayoutTestController->geolocationPermission()];
}
+- (BOOL)webView:(WebView *)sender shouldHaltPlugin:(DOMNode *)pluginNode
+{
+ return NO;
+}
+
- (void)dealloc
{
[draggingInfo release];
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp
index 83626ac..9faa37f 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp
@@ -30,6 +30,9 @@
*/
#include "DumpRenderTree.h"
+#include "EventSenderQt.h"
+#include "LayoutTestControllerQt.h"
+#include "TextInputControllerQt.h"
#include "jsobjects.h"
#include "testplugin.h"
#include "WorkQueue.h"
@@ -65,6 +68,7 @@ extern void qt_dump_set_accepts_editing(bool b);
extern void qt_dump_frame_loader(bool b);
extern void qt_drt_clearFrameName(QWebFrame* qFrame);
extern void qt_drt_overwritePluginDirectories();
+extern void qt_drt_resetOriginAccessWhiteLists();
namespace WebCore {
@@ -285,9 +289,10 @@ void DumpRenderTree::resetToConsistentStateBeforeTesting()
//WorkQueue::shared()->setFrozen(false);
m_controller->reset();
- QWebSecurityOrigin::resetOriginAccessWhiteLists();
+ qt_drt_resetOriginAccessWhiteLists();
- setlocale(LC_ALL, "");
+ QLocale qlocale;
+ QLocale::setDefault(qlocale);
}
void DumpRenderTree::open(const QUrl& aurl)
@@ -312,7 +317,7 @@ void DumpRenderTree::open(const QUrl& aurl)
int width = isW3CTest ? 480 : maxViewWidth;
int height = isW3CTest ? 360 : maxViewHeight;
m_page->view()->resize(QSize(width, height));
- m_page->setFixedContentsSize(QSize());
+ m_page->setPreferredContentsSize(QSize());
m_page->setViewportSize(QSize(width, height));
QFocusEvent ev(QEvent::FocusIn);
@@ -591,7 +596,8 @@ void DumpRenderTree::initializeFonts()
exit(1);
}
char currentPath[PATH_MAX+1];
- getcwd(currentPath, PATH_MAX);
+ if (!getcwd(currentPath, PATH_MAX))
+ qFatal("Couldn't get current working directory");
QByteArray configFile = currentPath;
FcConfig *config = FcConfigCreate();
configFile += "/WebKitTools/DumpRenderTree/qt/fonts.conf";
diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro
index 0daf8bd..571313c 100644
--- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro
+++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro
@@ -12,8 +12,23 @@ PKGCONFIG += fontconfig
QT = core gui network
macx: QT += xml
-HEADERS = WorkQueue.h WorkQueueItem.h DumpRenderTree.h jsobjects.h testplugin.h
-SOURCES = WorkQueue.cpp DumpRenderTree.cpp main.cpp jsobjects.cpp testplugin.cpp
+HEADERS = WorkQueue.h \
+ WorkQueueItem.h \
+ DumpRenderTree.h \
+ EventSenderQt.h \
+ TextInputControllerQt.h \
+ LayoutTestControllerQt.h \
+ jsobjects.h \
+ testplugin.h
+SOURCES = WorkQueue.cpp \
+ DumpRenderTree.cpp \
+ EventSenderQt.cpp \
+ TextInputControllerQt.cpp \
+ WorkQueueItemQt.cpp \
+ LayoutTestControllerQt.cpp \
+ main.cpp \
+ jsobjects.cpp \
+ testplugin.cpp
unix:!mac {
QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR
diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
new file mode 100644
index 0000000..bbefed9
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.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 "EventSenderQt.h"
+
+//#include <QtDebug>
+EventSender::EventSender(QWebPage* parent)
+ : QObject(parent)
+{
+ m_page = parent;
+}
+
+void EventSender::mouseDown(int button)
+{
+ Qt::MouseButton mouseButton;
+ switch (button) {
+ case 0:
+ mouseButton = Qt::LeftButton;
+ break;
+ case 1:
+ mouseButton = Qt::MidButton;
+ break;
+ case 2:
+ mouseButton = Qt::RightButton;
+ break;
+ case 3:
+ // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
+ mouseButton = Qt::MidButton;
+ break;
+ default:
+ mouseButton = Qt::LeftButton;
+ break;
+ }
+
+// qDebug() << "EventSender::mouseDown" << frame;
+ QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, mouseButton, mouseButton, Qt::NoModifier);
+ QApplication::sendEvent(m_page, &event);
+}
+
+void EventSender::mouseUp(int button)
+{
+ Qt::MouseButton mouseButton;
+ switch (button) {
+ case 0:
+ mouseButton = Qt::LeftButton;
+ break;
+ case 1:
+ mouseButton = Qt::MidButton;
+ break;
+ case 2:
+ mouseButton = Qt::RightButton;
+ break;
+ case 3:
+ // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
+ mouseButton = Qt::MidButton;
+ break;
+ default:
+ mouseButton = Qt::LeftButton;
+ break;
+ }
+
+// qDebug() << "EventSender::mouseUp" << frame;
+ QMouseEvent event(QEvent::MouseButtonRelease, m_mousePos, mouseButton, mouseButton, 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 == 0xf700) {
+ s = QString();
+ code = Qt::Key_Up;
+ if (modifs & Qt::MetaModifier) {
+ code = Qt::Key_PageUp;
+ modifs &= ~Qt::MetaModifier;
+ }
+ } else if (code == 0xf701) {
+ s = QString();
+ code = Qt::Key_Down;
+ if (modifs & Qt::MetaModifier) {
+ code = Qt::Key_PageDown;
+ modifs &= ~Qt::MetaModifier;
+ }
+ } else if (code == 'a' && modifs == Qt::ControlModifier) {
+ s = QString();
+ code = Qt::Key_Home;
+ modifs = 0;
+ } else
+ code = string.unicode()->toUpper().unicode();
+ } else {
+ //qDebug() << ">>>>>>>>> keyDown" << string;
+
+ if (string.startsWith(QLatin1Char('F')) && string.count() <= 3) {
+ s = s.mid(1);
+ int functionKey = s.toInt();
+ Q_ASSERT(functionKey >= 1 && functionKey <= 35);
+ code = Qt::Key_F1 + (functionKey - 1);
+ // map special keycode strings used by the tests to something that works for Qt/X11
+ } else if (string == QLatin1String("leftArrow")) {
+ s = QString();
+ code = Qt::Key_Left;
+ } else if (string == QLatin1String("rightArrow")) {
+ s = QString();
+ code = Qt::Key_Right;
+ } else if (string == QLatin1String("upArrow")) {
+ s = QString();
+ code = Qt::Key_Up;
+ } else if (string == QLatin1String("downArrow")) {
+ s = QString();
+ code = Qt::Key_Down;
+ } else if (string == QLatin1String("pageUp")) {
+ s = QString();
+ code = Qt::Key_PageUp;
+ } else if (string == QLatin1String("pageDown")) {
+ s = QString();
+ code = Qt::Key_PageDown;
+ } else if (string == QLatin1String("home")) {
+ s = QString();
+ code = Qt::Key_Home;
+ } else if (string == QLatin1String("end")) {
+ s = QString();
+ code = Qt::Key_End;
+ } else if (string == QLatin1String("delete")) {
+ s = QString();
+ code = Qt::Key_Delete;
+ }
+ }
+ QKeyEvent event(QEvent::KeyPress, code, modifs, s);
+ QApplication::sendEvent(m_page, &event);
+ QKeyEvent event2(QEvent::KeyRelease, code, modifs, s);
+ QApplication::sendEvent(m_page, &event2);
+}
+
+void EventSender::contextClick()
+{
+ QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
+ QApplication::sendEvent(m_page, &event);
+ QMouseEvent event2(QEvent::MouseButtonRelease, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
+ QApplication::sendEvent(m_page, &event2);
+}
+
+void EventSender::scheduleAsynchronousClick()
+{
+ QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonPress, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
+ QApplication::postEvent(m_page, event);
+ QMouseEvent* event2 = new QMouseEvent(QEvent::MouseButtonRelease, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
+ QApplication::postEvent(m_page, event2);
+}
+
+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;
+}
diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
new file mode 100644
index 0000000..fd74455
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.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 EventSenderQt_h
+#define EventSenderQt_h
+
+#include <QApplication>
+#include <QEvent>
+#include <QMouseEvent>
+#include <QObject>
+#include <QPoint>
+#include <QString>
+#include <QStringList>
+
+#include <qwebpage.h>
+#include <qwebframe.h>
+
+class EventSender : public QObject {
+ Q_OBJECT
+public:
+ EventSender(QWebPage* parent);
+
+public slots:
+ void mouseDown(int button = 0);
+ void mouseUp(int button = 0);
+ void mouseMoveTo(int x, int y);
+ void leapForward(int ms);
+ void keyDown(const QString& string, const QStringList& modifiers = QStringList());
+ void clearKillRing() {}
+ void contextClick();
+ void scheduleAsynchronousClick();
+
+private:
+ QPoint m_mousePos;
+ QWebPage* m_page;
+ int m_timeLeap;
+ QWebFrame* frameUnderMouse() const;
+};
+#endif // EventSenderQt_h
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
new file mode 100644
index 0000000..b8de6a5
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.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 "LayoutTestControllerQt.h"
+
+#include "DumpRenderTree.h"
+#include "WorkQueue.h"
+#include "WorkQueueItem.h"
+
+extern void qt_dump_editing_callbacks(bool b);
+extern void qt_dump_resource_load_callbacks(bool b);
+extern void qt_drt_setJavaScriptProfilingEnabled(QWebFrame*, bool enabled);
+extern bool qt_drt_pauseAnimation(QWebFrame*, const QString& name, double time, const QString& elementId);
+extern bool qt_drt_pauseTransitionOfProperty(QWebFrame*, const QString& name, double time, const QString& elementId);
+extern int qt_drt_numberOfActiveAnimations(QWebFrame*);
+extern void qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains);
+extern QString qt_drt_counterValueForElementById(QWebFrame* qFrame, const QString& id);
+
+LayoutTestController::LayoutTestController(WebCore::DumpRenderTree* drt)
+ : QObject()
+ , m_drt(drt)
+{
+ reset();
+}
+
+void LayoutTestController::reset()
+{
+ m_isLoading = true;
+ m_textDump = false;
+ m_dumpBackForwardList = false;
+ m_dumpChildrenAsText = false;
+ m_canOpenWindows = false;
+ m_waitForDone = false;
+ m_dumpTitleChanges = false;
+ m_dumpDatabaseCallbacks = false;
+ m_dumpStatusCallbacks = false;
+ m_timeoutTimer.stop();
+ m_topLoadingFrame = 0;
+ m_waitForPolicy = false;
+ qt_dump_editing_callbacks(false);
+ qt_dump_resource_load_callbacks(false);
+}
+
+void LayoutTestController::processWork()
+{
+ // qDebug() << ">>>processWork";
+
+ // if we didn't start a new load, then we finished all the commands, so we're ready to dump state
+ if (!WorkQueue::shared()->processWork() && !shouldWaitUntilDone()) {
+ emit done();
+ m_isLoading = false;
+ }
+}
+
+// Called on loadFinished on mainFrame.
+void LayoutTestController::maybeDump(bool success)
+{
+ Q_ASSERT(sender() == m_topLoadingFrame);
+
+ // as the function is called on loadFinished, the test might
+ // already have dumped and thus no longer be active, thus
+ // bail out here.
+ if (!m_isLoading)
+ return;
+
+ m_topLoadingFrame = 0;
+ WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
+
+ if (!shouldWaitUntilDone()) {
+ if (WorkQueue::shared()->count())
+ QTimer::singleShot(0, this, SLOT(processWork()));
+ else {
+ if (success)
+ emit done();
+ m_isLoading = false;
+ }
+ }
+}
+
+void LayoutTestController::waitUntilDone()
+{
+ //qDebug() << ">>>>waitForDone";
+ m_waitForDone = true;
+ m_timeoutTimer.start(11000, this);
+}
+
+QString LayoutTestController::counterValueForElementById(const QString& id)
+{
+ return qt_drt_counterValueForElementById(m_drt->webPage()->mainFrame(), id);
+}
+
+void LayoutTestController::keepWebHistory()
+{
+ // FIXME: implement
+}
+
+void LayoutTestController::notifyDone()
+{
+ qDebug() << ">>>>notifyDone";
+ if (!m_timeoutTimer.isActive())
+ return;
+ m_timeoutTimer.stop();
+ emit done();
+ m_isLoading = false;
+ m_waitForDone = false;
+ m_waitForPolicy = 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::dumpResourceLoadCallbacks()
+{
+ qt_dump_resource_load_callbacks(true);
+}
+
+void LayoutTestController::queueBackNavigation(int howFarBackward)
+{
+ //qDebug() << ">>>queueBackNavigation" << howFarBackward;
+ WorkQueue::shared()->queue(new BackItem(howFarBackward, m_drt->webPage()));
+}
+
+void LayoutTestController::queueForwardNavigation(int howFarForward)
+{
+ //qDebug() << ">>>queueForwardNavigation" << howFarForward;
+ WorkQueue::shared()->queue(new ForwardItem(howFarForward, m_drt->webPage()));
+}
+
+void LayoutTestController::queueLoad(const QString& url, const QString& target)
+{
+ //qDebug() << ">>>queueLoad" << url << target;
+ QUrl mainResourceUrl = m_drt->webPage()->mainFrame()->url();
+ QString absoluteUrl = mainResourceUrl.resolved(QUrl(url)).toEncoded();
+ WorkQueue::shared()->queue(new LoadItem(absoluteUrl, target, m_drt->webPage()));
+}
+
+void LayoutTestController::queueReload()
+{
+ //qDebug() << ">>>queueReload";
+ WorkQueue::shared()->queue(new ReloadItem(m_drt->webPage()));
+}
+
+void LayoutTestController::queueScript(const QString &url)
+{
+ //qDebug() << ">>>queueScript" << url;
+ WorkQueue::shared()->queue(new ScriptItem(url, m_drt->webPage()));
+}
+
+void LayoutTestController::provisionalLoad()
+{
+ QWebFrame* frame = qobject_cast<QWebFrame*>(sender());
+ if (!m_topLoadingFrame && m_isLoading)
+ m_topLoadingFrame = frame;
+}
+
+void LayoutTestController::timerEvent(QTimerEvent *ev)
+{
+ if (ev->timerId() == m_timeoutTimer.timerId()) {
+ //qDebug() << ">>>>>>>>>>>>> timeout";
+ notifyDone();
+ } else
+ QObject::timerEvent(ev);
+}
+
+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;
+}
+
+void LayoutTestController::setJavaScriptProfilingEnabled(bool enable)
+{
+ m_topLoadingFrame->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
+ qt_drt_setJavaScriptProfilingEnabled(m_topLoadingFrame, enable);
+}
+
+void LayoutTestController::setFixedContentsSize(int width, int height)
+{
+ m_topLoadingFrame->page()->setPreferredContentsSize(QSize(width, height));
+}
+
+void LayoutTestController::setPrivateBrowsingEnabled(bool enable)
+{
+ m_drt->webPage()->settings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, enable);
+}
+
+void LayoutTestController::setPopupBlockingEnabled(bool enable)
+{
+ m_drt->webPage()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, !enable);
+}
+
+void LayoutTestController::setPOSIXLocale(const QString& locale)
+{
+ QLocale qlocale(locale);
+ QLocale::setDefault(qlocale);
+}
+
+bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(const QString& animationName,
+ double time,
+ const QString& elementId)
+{
+ QWebFrame* frame = m_drt->webPage()->mainFrame();
+ Q_ASSERT(frame);
+ return qt_drt_pauseAnimation(frame, animationName, time, elementId);
+}
+
+bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(const QString& propertyName,
+ double time,
+ const QString& elementId)
+{
+ QWebFrame* frame = m_drt->webPage()->mainFrame();
+ Q_ASSERT(frame);
+ return qt_drt_pauseTransitionOfProperty(frame, propertyName, time, elementId);
+}
+
+unsigned LayoutTestController::numberOfActiveAnimations() const
+{
+ QWebFrame* frame = m_drt->webPage()->mainFrame();
+ Q_ASSERT(frame);
+ return qt_drt_numberOfActiveAnimations(frame);
+}
+
+void LayoutTestController::disableImageLoading()
+{
+ // FIXME: Implement for testing fix for https://bugs.webkit.org/show_bug.cgi?id=27896
+ // Also need to make sure image loading is re-enabled for each new test.
+}
+
+void LayoutTestController::dispatchPendingLoadRequests()
+{
+ // FIXME: Implement for testing fix for 6727495
+}
+
+void LayoutTestController::setDatabaseQuota(int size)
+{
+ if (!m_topLoadingFrame)
+ return;
+ m_topLoadingFrame->securityOrigin().setDatabaseQuota(size);
+}
+
+void LayoutTestController::clearAllDatabases()
+{
+ QWebDatabase::removeAllDatabases();
+}
+
+void LayoutTestController::whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains)
+{
+ qt_drt_whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains);
+}
+
+void LayoutTestController::waitForPolicyDelegate()
+{
+ m_waitForPolicy = true;
+ waitUntilDone();
+}
+
+void LayoutTestController::overridePreference(const QString& name, const QVariant& value)
+{
+ QWebSettings* settings = m_topLoadingFrame->page()->settings();
+
+ if (name == "WebKitJavaScriptEnabled")
+ settings->setAttribute(QWebSettings::JavascriptEnabled, value.toBool());
+ else if (name == "WebKitTabToLinksPreferenceKey")
+ settings->setAttribute(QWebSettings::LinksIncludedInFocusChain, value.toBool());
+ else if (name == "WebKitOfflineWebApplicationCacheEnabled")
+ settings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, value.toBool());
+ else if (name == "WebKitDefaultFontSize")
+ settings->setFontSize(QWebSettings::DefaultFontSize, value.toInt());
+}
diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
new file mode 100644
index 0000000..cab014c
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.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 LayoutTestControllerQt_h
+#define LayoutTestControllerQt_h
+
+#include <QBasicTimer>
+#include <QObject>
+#include <QSize>
+#include <QString>
+#include <QtDebug>
+#include <QTimer>
+#include <QTimerEvent>
+#include <QVariant>
+
+#include <qwebdatabase.h>
+#include <qwebframe.h>
+#include <qwebhistory.h>
+#include <qwebpage.h>
+#include <qwebsecurityorigin.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 shouldDumpBackForwardList() const { return m_dumpBackForwardList; }
+ bool shouldDumpChildrenAsText() const { return m_dumpChildrenAsText; }
+ bool shouldDumpDatabaseCallbacks() const { return m_dumpDatabaseCallbacks; }
+ bool shouldDumpStatusCallbacks() const { return m_dumpStatusCallbacks; }
+ bool shouldWaitUntilDone() const { return m_waitForDone; }
+ bool canOpenWindows() const { return m_canOpenWindows; }
+ bool shouldDumpTitleChanges() const { return m_dumpTitleChanges; }
+ bool waitForPolicy() const { return m_waitForPolicy; }
+
+ 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 dumpDatabaseCallbacks() { m_dumpDatabaseCallbacks = true; }
+ void dumpStatusCallbacks() { m_dumpStatusCallbacks = true; }
+ void setCanOpenWindows() { m_canOpenWindows = true; }
+ void waitUntilDone();
+ QString counterValueForElementById(const QString& id);
+ void keepWebHistory();
+ void notifyDone();
+ void dumpBackForwardList() { m_dumpBackForwardList = true; }
+ void dumpEditingCallbacks();
+ void dumpResourceLoadCallbacks();
+ void queueBackNavigation(int howFarBackward);
+ void queueForwardNavigation(int howFarForward);
+ void queueLoad(const QString& url, const QString& target = QString());
+ void queueReload();
+ void queueScript(const QString& url);
+ 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 {}
+ void setJavaScriptProfilingEnabled(bool enable);
+ void setFixedContentsSize(int width, int height);
+ void setPrivateBrowsingEnabled(bool enable);
+ void setPopupBlockingEnabled(bool enable);
+ void setPOSIXLocale(const QString& locale);
+
+ bool pauseAnimationAtTimeOnElementWithId(const QString& animationName, double time, const QString& elementId);
+ bool pauseTransitionAtTimeOnElementWithId(const QString& propertyName, double time, const QString& elementId);
+ unsigned numberOfActiveAnimations() const;
+
+ void whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains);
+
+ void dispatchPendingLoadRequests();
+ void disableImageLoading();
+
+ void setDatabaseQuota(int size);
+ void clearAllDatabases();
+
+ void waitForPolicyDelegate();
+ void overridePreference(const QString& name, const QVariant& value);
+
+private slots:
+ void processWork();
+
+private:
+ bool m_isLoading;
+ bool m_textDump;
+ bool m_dumpBackForwardList;
+ bool m_dumpChildrenAsText;
+ bool m_canOpenWindows;
+ bool m_waitForDone;
+ bool m_dumpTitleChanges;
+ bool m_dumpDatabaseCallbacks;
+ bool m_dumpStatusCallbacks;
+ bool m_waitForPolicy;
+
+ QBasicTimer m_timeoutTimer;
+ QWebFrame* m_topLoadingFrame;
+ WebCore::DumpRenderTree* m_drt;
+};
+
+#endif // LayoutTestControllerQt_h
diff --git a/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp
new file mode 100644
index 0000000..7b8f120
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.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 "TextInputControllerQt.h"
+
+#include <QApplication>
+#include <QKeyEvent>
+
+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/TextInputControllerQt.h b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.h
new file mode 100644
index 0000000..7c7433e
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.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 TextInputControllerQt_h
+#define TextInputControllerQt_h
+
+#include <QList>
+#include <QObject>
+#include <QString>
+#include "qwebpage.h"
+
+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 // TextInputControllerQt_h
diff --git a/WebKitTools/DumpRenderTree/qt/WorkQueue.cpp b/WebKitTools/DumpRenderTree/qt/WorkQueue.cpp
index ae24e0d..f8448e4 100644
--- a/WebKitTools/DumpRenderTree/qt/WorkQueue.cpp
+++ b/WebKitTools/DumpRenderTree/qt/WorkQueue.cpp
@@ -30,8 +30,6 @@
#include "config.h"
#include "WorkQueue.h"
-#include "WorkQueueItem.h"
-
static const unsigned queueLength = 1024;
static WorkQueueItem* theQueue[queueLength];
diff --git a/WebKitTools/DumpRenderTree/qt/WorkQueue.h b/WebKitTools/DumpRenderTree/qt/WorkQueue.h
index 8adbfcd..902ba0d 100644
--- a/WebKitTools/DumpRenderTree/qt/WorkQueue.h
+++ b/WebKitTools/DumpRenderTree/qt/WorkQueue.h
@@ -30,7 +30,7 @@
#ifndef WorkQueue_h
#define WorkQueue_h
-class WorkQueueItem;
+#include "WorkQueueItem.h"
class WorkQueue {
public:
diff --git a/WebKitTools/DumpRenderTree/qt/WorkQueueItem.h b/WebKitTools/DumpRenderTree/qt/WorkQueueItem.h
index 0e10f62..9819ec0 100644
--- a/WebKitTools/DumpRenderTree/qt/WorkQueueItem.h
+++ b/WebKitTools/DumpRenderTree/qt/WorkQueueItem.h
@@ -30,8 +30,9 @@
#ifndef WorkQueueItem_h
#define WorkQueueItem_h
-#include <qstring.h>
-#include <qpointer.h>
+#include <QPointer>
+#include <QString>
+#include <qwebframe.h>
#include <qwebpage.h>
class WorkQueueItem {
diff --git a/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp b/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp
new file mode 100644
index 0000000..807a6a4
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.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 "WorkQueueItem.h"
+
+QWebFrame* findFrameNamed(const QString& frameName, QWebFrame* frame)
+{
+ if (frame->frameName() == frameName)
+ return frame;
+
+ foreach (QWebFrame* childFrame, frame->childFrames())
+ if (QWebFrame* f = findFrameNamed(frameName, childFrame))
+ return f;
+
+ return 0;
+}
+
+bool LoadItem::invoke() const
+{
+ //qDebug() << ">>>LoadItem::invoke";
+ Q_ASSERT(m_webPage);
+
+ QWebFrame* frame = 0;
+ const QString t = target();
+ if (t.isEmpty())
+ frame = m_webPage->mainFrame();
+ else
+ frame = findFrameNamed(t, m_webPage->mainFrame());
+
+ if (!frame)
+ return false;
+
+ frame->load(url());
+ return true;
+}
+
+bool ReloadItem::invoke() const
+{
+ //qDebug() << ">>>ReloadItem::invoke";
+ Q_ASSERT(m_webPage);
+ m_webPage->triggerAction(QWebPage::Reload);
+ return true;
+}
+
+bool ScriptItem::invoke() const
+{
+ //qDebug() << ">>>ScriptItem::invoke";
+ Q_ASSERT(m_webPage);
+ m_webPage->mainFrame()->evaluateJavaScript(script());
+ return true;
+}
+
+bool BackForwardItem::invoke() const
+{
+ //qDebug() << ">>>BackForwardItem::invoke";
+ Q_ASSERT(m_webPage);
+ if (!m_howFar)
+ return false;
+
+ if (m_howFar > 0) {
+ for (int i = 0; i != m_howFar; ++i)
+ m_webPage->triggerAction(QWebPage::Forward);
+ } else {
+ for (int i = 0; i != m_howFar; --i)
+ m_webPage->triggerAction(QWebPage::Back);
+ }
+ return true;
+}
diff --git a/WebKitTools/DumpRenderTree/qt/jsobjects.cpp b/WebKitTools/DumpRenderTree/qt/jsobjects.cpp
index b2d8528..e747aeb 100644
--- a/WebKitTools/DumpRenderTree/qt/jsobjects.cpp
+++ b/WebKitTools/DumpRenderTree/qt/jsobjects.cpp
@@ -27,672 +27,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <jsobjects.h>
-
-#include "DumpRenderTree.h"
-#include "WorkQueue.h"
-#include "WorkQueueItem.h"
-
-#include <qapplication.h>
-#include <qevent.h>
-#include <qtimer.h>
-#include <qwebdatabase.h>
-#include <qwebframe.h>
-#include <qwebhistory.h>
#include <qwebpage.h>
-#include <qwebsecurityorigin.h>
-
-extern void qt_dump_editing_callbacks(bool b);
-extern void qt_dump_resource_load_callbacks(bool b);
-extern void qt_drt_setJavaScriptProfilingEnabled(QWebFrame*, bool enabled);
-extern bool qt_drt_pauseAnimation(QWebFrame*, const QString &name, double time, const QString &elementId);
-extern bool qt_drt_pauseTransitionOfProperty(QWebFrame*, const QString &name, double time, const QString &elementId);
-extern int qt_drt_numberOfActiveAnimations(QWebFrame*);
-
-QWebFrame* findFrameNamed(const QString &frameName, QWebFrame* frame)
-{
- if (frame->frameName() == frameName)
- return frame;
-
- foreach (QWebFrame *childFrame, frame->childFrames())
- if (QWebFrame *f = findFrameNamed(frameName, childFrame))
- return f;
-
- return 0;
-}
-
-bool LoadItem::invoke() const
-{
- //qDebug() << ">>>LoadItem::invoke";
- Q_ASSERT(m_webPage);
-
- QWebFrame* frame = 0;
- const QString t = target();
- if (t.isEmpty())
- frame = m_webPage->mainFrame();
- else
- frame = findFrameNamed(t, m_webPage->mainFrame());
-
- if (!frame)
- return false;
-
- frame->load(url());
- return true;
-}
-
-bool ReloadItem::invoke() const
-{
- //qDebug() << ">>>ReloadItem::invoke";
- Q_ASSERT(m_webPage);
- m_webPage->triggerAction(QWebPage::Reload);
- return true;
-}
-
-bool ScriptItem::invoke() const
-{
- //qDebug() << ">>>ScriptItem::invoke";
- Q_ASSERT(m_webPage);
- m_webPage->mainFrame()->evaluateJavaScript(script());
- return true;
-}
-
-bool BackForwardItem::invoke() const
-{
- //qDebug() << ">>>BackForwardItem::invoke";
- Q_ASSERT(m_webPage);
- if (!m_howFar)
- return false;
-
- if (m_howFar > 0) {
- for (int i = 0; i != m_howFar; ++i)
- m_webPage->triggerAction(QWebPage::Forward);
- } else {
- for (int i = 0; i != m_howFar; --i)
- m_webPage->triggerAction(QWebPage::Back);
- }
- return true;
-}
-
-LayoutTestController::LayoutTestController(WebCore::DumpRenderTree *drt)
- : QObject()
- , m_drt(drt)
-{
- reset();
-}
-
-void LayoutTestController::reset()
-{
- m_isLoading = true;
- m_textDump = false;
- m_dumpBackForwardList = false;
- m_dumpChildrenAsText = false;
- m_canOpenWindows = false;
- m_waitForDone = false;
- m_dumpTitleChanges = false;
- m_dumpDatabaseCallbacks = false;
- m_dumpStatusCallbacks = false;
- m_timeoutTimer.stop();
- m_topLoadingFrame = 0;
- m_waitForPolicy = false;
- qt_dump_editing_callbacks(false);
- qt_dump_resource_load_callbacks(false);
-}
-
-void LayoutTestController::processWork()
-{
- qDebug() << ">>>processWork";
-
- // if we didn't start a new load, then we finished all the commands, so we're ready to dump state
- if (!WorkQueue::shared()->processWork() && !shouldWaitUntilDone()) {
- emit done();
- m_isLoading = false;
- }
-}
-
-// Called on loadFinished on mainFrame.
-void LayoutTestController::maybeDump(bool success)
-{
- Q_ASSERT(sender() == m_topLoadingFrame);
-
- // as the function is called on loadFinished, the test might
- // already have dumped and thus no longer be active, thus
- // bail out here.
- if (!m_isLoading)
- return;
-
- m_topLoadingFrame = 0;
- WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
-
- if (!shouldWaitUntilDone()) {
- if (WorkQueue::shared()->count())
- QTimer::singleShot(0, this, SLOT(processWork()));
- else {
- if (success)
- emit done();
- m_isLoading = false;
- }
- }
-}
-
-void LayoutTestController::waitUntilDone()
-{
- //qDebug() << ">>>>waitForDone";
- m_waitForDone = true;
- m_timeoutTimer.start(11000, this);
-}
-
-void LayoutTestController::notifyDone()
-{
- //qDebug() << ">>>>notifyDone";
- if (!m_timeoutTimer.isActive())
- return;
- m_timeoutTimer.stop();
- emit done();
- m_isLoading = false;
- m_waitForDone = false;
- m_waitForPolicy = 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::dumpResourceLoadCallbacks()
-{
- qt_dump_resource_load_callbacks(true);
-}
-
-void LayoutTestController::queueBackNavigation(int howFarBackward)
-{
- //qDebug() << ">>>queueBackNavigation" << howFarBackward;
- WorkQueue::shared()->queue(new BackItem(howFarBackward, m_drt->webPage()));
-}
-
-void LayoutTestController::queueForwardNavigation(int howFarForward)
-{
- //qDebug() << ">>>queueForwardNavigation" << howFarForward;
- WorkQueue::shared()->queue(new ForwardItem(howFarForward, m_drt->webPage()));
-}
-
-void LayoutTestController::queueLoad(const QString &url, const QString &target)
-{
- //qDebug() << ">>>queueLoad" << url << target;
- QUrl mainResourceUrl = m_drt->webPage()->mainFrame()->url();
- QString absoluteUrl = mainResourceUrl.resolved(QUrl(url)).toEncoded();
- WorkQueue::shared()->queue(new LoadItem(absoluteUrl, target, m_drt->webPage()));
-}
-
-void LayoutTestController::queueReload()
-{
- //qDebug() << ">>>queueReload";
- WorkQueue::shared()->queue(new ReloadItem(m_drt->webPage()));
-}
-
-void LayoutTestController::queueScript(const QString &url)
-{
- //qDebug() << ">>>queueScript" << url;
- WorkQueue::shared()->queue(new ScriptItem(url, m_drt->webPage()));
-}
-
-void LayoutTestController::provisionalLoad()
-{
- QWebFrame* frame = qobject_cast<QWebFrame*>(sender());
- if (!m_topLoadingFrame && m_isLoading)
- m_topLoadingFrame = frame;
-}
-
-void LayoutTestController::timerEvent(QTimerEvent *ev)
-{
- if (ev->timerId() == m_timeoutTimer.timerId()) {
- qDebug() << ">>>>>>>>>>>>> timeout";
- notifyDone();
- } else
- QObject::timerEvent(ev);
-}
-
-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;
-}
-
-void LayoutTestController::setJavaScriptProfilingEnabled(bool enable)
-{
- m_topLoadingFrame->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
- qt_drt_setJavaScriptProfilingEnabled(m_topLoadingFrame, enable);
-}
-
-void LayoutTestController::setFixedContentsSize(int width, int height)
-{
- m_topLoadingFrame->page()->setFixedContentsSize(QSize(width, height));
-}
-
-void LayoutTestController::setPrivateBrowsingEnabled(bool enable)
-{
- m_drt->webPage()->settings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, enable);
-}
-
-void LayoutTestController::setPopupBlockingEnabled(bool enable)
-{
- m_drt->webPage()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, !enable);
-}
-
-bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(const QString &animationName,
- double time,
- const QString &elementId)
-{
- QWebFrame* frame = m_drt->webPage()->mainFrame();
- Q_ASSERT(frame);
- return qt_drt_pauseAnimation(frame, animationName, time, elementId);
-}
-
-bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(const QString &propertyName,
- double time,
- const QString &elementId)
-{
- QWebFrame* frame = m_drt->webPage()->mainFrame();
- Q_ASSERT(frame);
- return qt_drt_pauseTransitionOfProperty(frame, propertyName, time, elementId);
-}
-
-unsigned LayoutTestController::numberOfActiveAnimations() const
-{
- QWebFrame* frame = m_drt->webPage()->mainFrame();
- Q_ASSERT(frame);
- return qt_drt_numberOfActiveAnimations(frame);
-}
-
-void LayoutTestController::disableImageLoading()
-{
- // FIXME: Implement for testing fix for https://bugs.webkit.org/show_bug.cgi?id=27896
- // Also need to make sure image loading is re-enabled for each new test.
-}
-
-void LayoutTestController::dispatchPendingLoadRequests()
-{
- // FIXME: Implement for testing fix for 6727495
-}
-
-void LayoutTestController::setDatabaseQuota(int size)
-{
- if (!m_topLoadingFrame)
- return;
- m_topLoadingFrame->securityOrigin().setDatabaseQuota(size);
-}
-
-void LayoutTestController::clearAllDatabases()
-{
- QWebDatabase::removeAllDatabases();
-}
-
-void LayoutTestController::whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains)
-{
- QWebSecurityOrigin::whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains);
-}
-
-void LayoutTestController::waitForPolicyDelegate()
-{
- m_waitForPolicy = true;
- waitUntilDone();
-}
-
-void LayoutTestController::overridePreference(const QString& name, const QVariant& value)
-{
- QWebSettings* settings = m_topLoadingFrame->page()->settings();
-
- if (name == "WebKitJavaScriptEnabled")
- settings->setAttribute(QWebSettings::JavascriptEnabled, value.toBool());
- else if (name == "WebKitTabToLinksPreferenceKey")
- settings->setAttribute(QWebSettings::LinksIncludedInFocusChain, value.toBool());
- else if (name == "WebKitOfflineWebApplicationCacheEnabled")
- settings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, value.toBool());
- else if (name == "WebKitDefaultFontSize")
- settings->setFontSize(QWebSettings::DefaultFontSize, value.toInt());
-}
-
-EventSender::EventSender(QWebPage *parent)
- : QObject(parent)
-{
- m_page = parent;
-}
-
-void EventSender::mouseDown(int button)
-{
- Qt::MouseButton mouseButton;
- switch (button) {
- case 0:
- mouseButton = Qt::LeftButton;
- break;
- case 1:
- mouseButton = Qt::MidButton;
- break;
- case 2:
- mouseButton = Qt::RightButton;
- break;
- case 3:
- // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
- mouseButton = Qt::MidButton;
- break;
- default:
- mouseButton = Qt::LeftButton;
- break;
- }
-
-// qDebug() << "EventSender::mouseDown" << frame;
- QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, mouseButton, mouseButton, Qt::NoModifier);
- QApplication::sendEvent(m_page, &event);
-}
-
-void EventSender::mouseUp(int button)
-{
- Qt::MouseButton mouseButton;
- switch (button) {
- case 0:
- mouseButton = Qt::LeftButton;
- break;
- case 1:
- mouseButton = Qt::MidButton;
- break;
- case 2:
- mouseButton = Qt::RightButton;
- break;
- case 3:
- // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
- mouseButton = Qt::MidButton;
- break;
- default:
- mouseButton = Qt::LeftButton;
- break;
- }
-
-// qDebug() << "EventSender::mouseUp" << frame;
- QMouseEvent event(QEvent::MouseButtonRelease, m_mousePos, mouseButton, mouseButton, 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 == 0xf700) {
- s = QString();
- code = Qt::Key_Up;
- if (modifs & Qt::MetaModifier) {
- code = Qt::Key_PageUp;
- modifs &= ~Qt::MetaModifier;
- }
- } else if (code == 0xf701) {
- s = QString();
- code = Qt::Key_Down;
- if (modifs & Qt::MetaModifier) {
- code = Qt::Key_PageDown;
- modifs &= ~Qt::MetaModifier;
- }
- } else if (code == 'a' && modifs == Qt::ControlModifier) {
- s = QString();
- code = Qt::Key_Home;
- modifs = 0;
- } else
- code = string.unicode()->toUpper().unicode();
- } else {
- qDebug() << ">>>>>>>>> keyDown" << string;
-
- if (string.startsWith(QLatin1Char('F')) && string.count() <= 3) {
- s = s.mid(1);
- int functionKey = s.toInt();
- Q_ASSERT(functionKey >= 1 && functionKey <= 35);
- code = Qt::Key_F1 + (functionKey - 1);
- // map special keycode strings used by the tests to something that works for Qt/X11
- } else if (string == QLatin1String("leftArrow")) {
- s = QString();
- code = Qt::Key_Left;
- } else if (string == QLatin1String("rightArrow")) {
- s = QString();
- code = Qt::Key_Right;
- } else if (string == QLatin1String("upArrow")) {
- s = QString();
- code = Qt::Key_Up;
- } else if (string == QLatin1String("downArrow")) {
- s = QString();
- code = Qt::Key_Down;
- } else if (string == QLatin1String("pageUp")) {
- s = QString();
- code = Qt::Key_PageUp;
- } else if (string == QLatin1String("pageDown")) {
- s = QString();
- code = Qt::Key_PageDown;
- } else if (string == QLatin1String("home")) {
- s = QString();
- code = Qt::Key_Home;
- } else if (string == QLatin1String("end")) {
- s = QString();
- code = Qt::Key_End;
- } else if (string == QLatin1String("delete")) {
- s = QString();
- code = Qt::Key_Delete;
- }
- }
- QKeyEvent event(QEvent::KeyPress, code, modifs, s);
- QApplication::sendEvent(m_page, &event);
- QKeyEvent event2(QEvent::KeyRelease, code, modifs, s);
- QApplication::sendEvent(m_page, &event2);
-}
-
-void EventSender::contextClick()
-{
- QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
- QApplication::sendEvent(m_page, &event);
- QMouseEvent event2(QEvent::MouseButtonRelease, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
- QApplication::sendEvent(m_page, &event2);
-}
-
-void EventSender::scheduleAsynchronousClick()
-{
- QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonPress, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
- QApplication::postEvent(m_page, event);
- QMouseEvent* event2 = new QMouseEvent(QEvent::MouseButtonRelease, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
- QApplication::postEvent(m_page, event2);
-}
-
-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);
-}
GCController::GCController(QWebPage* parent)
: QObject(parent)
diff --git a/WebKitTools/DumpRenderTree/qt/jsobjects.h b/WebKitTools/DumpRenderTree/qt/jsobjects.h
index c076bb9..3ee566b 100644
--- a/WebKitTools/DumpRenderTree/qt/jsobjects.h
+++ b/WebKitTools/DumpRenderTree/qt/jsobjects.h
@@ -29,156 +29,9 @@
#ifndef JSOBJECTS_H
#define JSOBJECTS_H
-#include <qobject.h>
-#include <qdebug.h>
-#include <qpoint.h>
-#include <qstringlist.h>
-#include <qsize.h>
-#include <qbasictimer.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 shouldDumpBackForwardList() const { return m_dumpBackForwardList; }
- bool shouldDumpChildrenAsText() const { return m_dumpChildrenAsText; }
- bool shouldDumpDatabaseCallbacks() const { return m_dumpDatabaseCallbacks; }
- bool shouldDumpStatusCallbacks() const { return m_dumpStatusCallbacks; }
- bool shouldWaitUntilDone() const { return m_waitForDone; }
- bool canOpenWindows() const { return m_canOpenWindows; }
- bool shouldDumpTitleChanges() const { return m_dumpTitleChanges; }
- bool waitForPolicy() const { return m_waitForPolicy; }
-
- 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 dumpDatabaseCallbacks() { m_dumpDatabaseCallbacks = true; }
- void dumpStatusCallbacks() { m_dumpStatusCallbacks = true; }
- void setCanOpenWindows() { m_canOpenWindows = true; }
- void waitUntilDone();
- void notifyDone();
- void dumpBackForwardList() { m_dumpBackForwardList = true; }
- void dumpEditingCallbacks();
- void dumpResourceLoadCallbacks();
- void queueBackNavigation(int howFarBackward);
- void queueForwardNavigation(int howFarForward);
- void queueLoad(const QString &url, const QString &target = QString());
- void queueReload();
- void queueScript(const QString &url);
- 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 {}
- void setJavaScriptProfilingEnabled(bool enable);
- void setFixedContentsSize(int width, int height);
- void setPrivateBrowsingEnabled(bool enable);
- void setPopupBlockingEnabled(bool enable);
-
- bool pauseAnimationAtTimeOnElementWithId(const QString &animationName, double time, const QString &elementId);
- bool pauseTransitionAtTimeOnElementWithId(const QString &propertyName, double time, const QString &elementId);
- unsigned numberOfActiveAnimations() const;
-
- void whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains);
-
- void dispatchPendingLoadRequests();
- void disableImageLoading();
-
- void setDatabaseQuota(int size);
- void clearAllDatabases();
-
- void waitForPolicyDelegate();
- void overridePreference(const QString& name, const QVariant& value);
-
-private slots:
- void processWork();
-
-private:
- bool m_isLoading;
- bool m_textDump;
- bool m_dumpBackForwardList;
- bool m_dumpChildrenAsText;
- bool m_canOpenWindows;
- bool m_waitForDone;
- bool m_dumpTitleChanges;
- bool m_dumpDatabaseCallbacks;
- bool m_dumpStatusCallbacks;
- bool m_waitForPolicy;
-
- QBasicTimer m_timeoutTimer;
- QWebFrame *m_topLoadingFrame;
- WebCore::DumpRenderTree *m_drt;
-};
+#include <QObject>
class QWebPage;
-class QWebFrame;
-
-class EventSender : public QObject
-{
- Q_OBJECT
-public:
- EventSender(QWebPage *parent);
-
-public slots:
- void mouseDown(int button = 0);
- void mouseUp(int button = 0);
- void mouseMoveTo(int x, int y);
- void leapForward(int ms);
- void keyDown(const QString &string, const QStringList &modifiers=QStringList());
- void clearKillRing() {}
- void contextClick();
- void scheduleAsynchronousClick();
-
-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();
-};
class GCController : public QObject
{
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
index 7e013a7..d486d06 100644
--- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
+++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp
@@ -31,6 +31,7 @@
#include "EditingDelegate.h"
#include "FrameLoadDelegate.h"
+#include "HistoryDelegate.h"
#include "LayoutTestController.h"
#include "PixelDumpSupport.h"
#include "PolicyDelegate.h"
@@ -97,6 +98,7 @@ COMPtr<FrameLoadDelegate> sharedFrameLoadDelegate;
COMPtr<UIDelegate> sharedUIDelegate;
COMPtr<EditingDelegate> sharedEditingDelegate;
COMPtr<ResourceLoadDelegate> sharedResourceLoadDelegate;
+COMPtr<HistoryDelegate> sharedHistoryDelegate;
IWebFrame* frame;
HWND webViewWindow;
@@ -199,7 +201,7 @@ static const wstring& fontsPath()
return path;
}
-#ifdef DEBUG_WEBKIT_HAS_SUFFIX
+#ifdef DEBUG_ALL
#define WEBKITDLL TEXT("WebKit_debug.dll")
#else
#define WEBKITDLL TEXT("WebKit.dll")
@@ -681,6 +683,11 @@ static bool shouldLogFrameLoadDelegates(const char* pathOrURL)
return strstr(pathOrURL, "/loading/") || strstr(pathOrURL, "\\loading\\");
}
+static bool shouldLogHistoryDelegates(const char* pathOrURL)
+{
+ return strstr(pathOrURL, "/globalhistory/") || strstr(pathOrURL, "\\globalhistory\\");
+}
+
static void resetDefaultsToConsistentValues(IWebPreferences* preferences)
{
#ifdef USE_MAC_FONTS
@@ -737,7 +744,6 @@ static void resetDefaultsToConsistentValues(IWebPreferences* preferences)
prefsPrivate->setAuthorAndUserStylesEnabled(TRUE);
prefsPrivate->setDeveloperExtrasEnabled(FALSE);
prefsPrivate->setExperimentalNotificationsEnabled(TRUE);
- prefsPrivate->setExperimentalWebSocketsEnabled(FALSE);
prefsPrivate->setShouldPaintNativeControls(FALSE); // FIXME - need to make DRT pass with Windows native controls <http://bugs.webkit.org/show_bug.cgi?id=25592>
prefsPrivate->setXSSAuditorEnabled(FALSE);
prefsPrivate->setOfflineWebApplicationCacheEnabled(TRUE);
@@ -836,6 +842,17 @@ static void runTest(const string& testPathOrURL)
if (shouldLogFrameLoadDelegates(pathOrURL.c_str()))
gLayoutTestController->setDumpFrameLoadCallbacks(true);
+ COMPtr<IWebView> webView;
+ if (SUCCEEDED(frame->webView(&webView))) {
+ COMPtr<IWebViewPrivate> viewPrivate;
+ if (SUCCEEDED(webView->QueryInterface(&viewPrivate))) {
+ if (shouldLogHistoryDelegates(pathOrURL.c_str())) {
+ gLayoutTestController->setDumpHistoryDelegateCallbacks(true);
+ viewPrivate->setHistoryDelegate(sharedHistoryDelegate.get());
+ } else
+ viewPrivate->setHistoryDelegate(0);
+ }
+ }
COMPtr<IWebHistory> history;
if (SUCCEEDED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
history->setOptionalSharedHistory(0);
@@ -843,8 +860,7 @@ static void runTest(const string& testPathOrURL)
resetWebViewToConsistentStateBeforeTesting();
prevTestBFItem = 0;
- COMPtr<IWebView> webView;
- if (SUCCEEDED(frame->webView(&webView))) {
+ if (webView) {
COMPtr<IWebBackForwardList> bfList;
if (SUCCEEDED(webView->backForwardList(&bfList)))
bfList->currentItem(&prevTestBFItem);
@@ -1095,9 +1111,11 @@ IWebView* createWebViewAndOffscreenWindow(HWND* webViewWindow)
#if USE(CFNETWORK)
RetainPtr<CFURLCacheRef> sharedCFURLCache()
{
+#ifndef DEBUG_ALL
+ HMODULE module = GetModuleHandle(TEXT("CFNetwork.dll"));
+#else
HMODULE module = GetModuleHandle(TEXT("CFNetwork_debug.dll"));
- if (!module)
- module = GetModuleHandle(TEXT("CFNetwork.dll"));
+#endif
if (!module)
return 0;
@@ -1153,6 +1171,7 @@ int main(int argc, char* argv[])
sharedUIDelegate.adoptRef(new UIDelegate);
sharedEditingDelegate.adoptRef(new EditingDelegate);
sharedResourceLoadDelegate.adoptRef(new ResourceLoadDelegate);
+ sharedHistoryDelegate.adoptRef(new HistoryDelegate);
// FIXME - need to make DRT pass with Windows native controls <http://bugs.webkit.org/show_bug.cgi?id=25592>
COMPtr<IWebPreferences> tmpPreferences;
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj
index dea2467..ba3640c 100644
--- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj
+++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj
@@ -185,7 +185,7 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(ProjectDir)\.&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ProjectDir)\..\cg&quot;;&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\private&quot;;&quot;$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitOutputDir)\Include\private\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitOutputDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"
- PreprocessorDefinitions="_CONSOLE;DEBUG_WEBKIT_HAS_SUFFIX"
+ PreprocessorDefinitions="_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="DumpRenderTreePrefix.h"
/>
@@ -376,6 +376,77 @@
CommandLine="if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;&#x0D;&#x0A;if not defined ARCHIVE_BUILD (if defined PRODUCTION exit /b)&#x0D;&#x0A;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;&#x0D;&#x0A;if not exist &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; exit /b&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CFNetwork.resources&quot; &quot;$(WebKitOutputDir)\bin\CFNetwork.resources&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CoreFoundation.resources&quot; &quot;$(WebKitOutputDir)\bin\CoreFoundation.resources&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CharacterSets&quot; &quot;$(WebKitOutputDir)\bin\CharacterSets&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\dnssd.dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icudt40.dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;"
/>
</Configuration>
+ <Configuration
+ Name="Debug_All|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash&#x0D;&#x0A;if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%&#x0D;&#x0A;cmd /c&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; grep XX$(ProjectName)XX &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;if errorlevel 1 exit 1&#x0D;&#x0A;echo XX$(ProjectName)XX &gt; &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\DumpRenderTree&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\DumpRenderTree\ForwardingHeaders\wtf&quot;&#x0D;&#x0A;"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)\.&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ProjectDir)\..\cg&quot;;&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\private&quot;;&quot;$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitOutputDir)\Include\private\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include\private&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitOutputDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"
+ PreprocessorDefinitions="_CONSOLE"
+ DisableSpecificWarnings="4146"
+ ForcedIncludeFiles="DumpRenderTreePrefix.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKitGUID$(WebKitConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreGraphics$(LibraryConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib CFNetwork$(LibraryConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib gdi32.lib ole32.lib oleaut32.lib user32.lib shlwapi.lib oleacc.lib comsuppw.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="if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;&#x0D;&#x0A;if not defined ARCHIVE_BUILD (if defined PRODUCTION exit /b)&#x0D;&#x0A;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;&#x0D;&#x0A;if not exist &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; exit /b&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CFNetwork$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CFNetwork.resources&quot; &quot;$(WebKitOutputDir)\bin\CFNetwork.resources&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CoreFoundation.resources&quot; &quot;$(WebKitOutputDir)\bin\CoreFoundation.resources&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CharacterSets&quot; &quot;$(WebKitOutputDir)\bin\CharacterSets&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\dnssd.dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icudt40.dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\libxml2$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\libxslt$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\SQLite3$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\zlib1$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
@@ -456,6 +527,14 @@
>
</File>
<File
+ RelativePath=".\HistoryDelegate.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\HistoryDelegate.h"
+ >
+ </File>
+ <File
RelativePath=".\PolicyDelegate.cpp"
>
</File>
@@ -555,6 +634,14 @@
Name="VCCLCompilerTool"
/>
</FileConfiguration>
+ <FileConfiguration
+ Name="Debug_All|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
</File>
<File
RelativePath="..\cairo\PixelDumpSupportCairo.h"
@@ -583,6 +670,14 @@
Name="VCCustomBuildTool"
/>
</FileConfiguration>
+ <FileConfiguration
+ Name="Debug_All|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
</File>
<File
RelativePath="..\cg\PixelDumpSupportCG.cpp"
diff --git a/WebKitTools/DumpRenderTree/win/EventSender.cpp b/WebKitTools/DumpRenderTree/win/EventSender.cpp
index 721b238..dd5bf9d 100644
--- a/WebKitTools/DumpRenderTree/win/EventSender.cpp
+++ b/WebKitTools/DumpRenderTree/win/EventSender.cpp
@@ -194,7 +194,7 @@ static inline POINTL pointl(const POINT& point)
return result;
}
-static void doMouseUp(MSG msg)
+static void doMouseUp(MSG msg, HRESULT* oleDragAndDropReturnValue = 0)
{
COMPtr<IWebFramePrivate> framePrivate;
if (SUCCEEDED(frame->QueryInterface(&framePrivate)))
@@ -215,6 +215,8 @@ static void doMouseUp(MSG msg)
didDragEnter = true;
}
HRESULT hr = draggingInfo->dropSource()->QueryContinueDrag(0, 0);
+ if (oleDragAndDropReturnValue)
+ *oleDragAndDropReturnValue = hr;
webViewDropTarget->DragOver(0, pointl(screenPoint), &effect);
if (hr == DRAGDROP_S_DROP && effect != DROPEFFECT_NONE) {
DWORD effect = 0;
@@ -314,7 +316,7 @@ static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function
return JSValueMakeUndefined(context);
}
-void replaySavedEvents()
+void replaySavedEvents(HRESULT* oleDragAndDropReturnValue)
{
replayingSavedEvents = true;
@@ -326,7 +328,7 @@ void replaySavedEvents()
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
- doMouseUp(msg);
+ doMouseUp(msg, oleDragAndDropReturnValue);
break;
case WM_MOUSEMOVE:
doMouseMove(msg);
@@ -370,7 +372,7 @@ void replaySavedEvents()
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
- doMouseUp(msg);
+ doMouseUp(msg, oleDragAndDropReturnValue);
break;
case WM_MOUSEMOVE:
doMouseMove(msg);
diff --git a/WebKitTools/DumpRenderTree/win/EventSender.h b/WebKitTools/DumpRenderTree/win/EventSender.h
index 9ae0aec..79d7dab 100644
--- a/WebKitTools/DumpRenderTree/win/EventSender.h
+++ b/WebKitTools/DumpRenderTree/win/EventSender.h
@@ -31,11 +31,12 @@
class DraggingInfo;
+typedef long HRESULT;
typedef const struct OpaqueJSContext* JSContextRef;
typedef struct OpaqueJSValue* JSObjectRef;
JSObjectRef makeEventSender(JSContextRef context);
-void replaySavedEvents();
+void replaySavedEvents(HRESULT* oleDragAndDropReturnValue = 0);
extern DraggingInfo* draggingInfo;
diff --git a/WebKitTools/DumpRenderTree/win/HistoryDelegate.cpp b/WebKitTools/DumpRenderTree/win/HistoryDelegate.cpp
new file mode 100644
index 0000000..8a41fac
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/win/HistoryDelegate.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2009 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 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 "config.h"
+#include "HistoryDelegate.h"
+
+#include "DumpRenderTree.h"
+#include "DumpRenderTreeWin.h"
+#include "LayoutTestController.h"
+#include <string>
+#include <WebKit/WebKit.h>
+
+using std::wstring;
+
+static inline wstring wstringFromBSTR(BSTR str)
+{
+ return wstring(str, ::SysStringLen(str));
+}
+
+HistoryDelegate::HistoryDelegate()
+ : m_refCount(1)
+{
+}
+
+HistoryDelegate::~HistoryDelegate()
+{
+}
+
+ // IUnknown
+HRESULT HistoryDelegate::QueryInterface(REFIID riid, void** ppvObject)
+{
+ *ppvObject = 0;
+ if (IsEqualGUID(riid, IID_IUnknown))
+ *ppvObject = static_cast<IWebHistoryDelegate*>(this);
+ else if (IsEqualGUID(riid, IID_IWebHistoryDelegate))
+ *ppvObject = static_cast<IWebHistoryDelegate*>(this);
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+}
+
+ULONG HistoryDelegate::AddRef(void)
+{
+ return ++m_refCount;
+}
+
+ULONG HistoryDelegate::Release(void)
+{
+ ULONG newRef = --m_refCount;
+ if (!newRef)
+ delete(this);
+
+ return newRef;
+}
+
+// IWebHistoryDelegate
+HRESULT HistoryDelegate::didNavigateWithNavigationData(IWebView* webView, IWebNavigationData* navigationData, IWebFrame* webFrame)
+{
+ if (!gLayoutTestController->dumpHistoryDelegateCallbacks())
+ return S_OK;
+
+ BSTR urlBSTR;
+ if (FAILED(navigationData->url(&urlBSTR)))
+ return E_FAIL;
+ wstring url;
+ if (urlBSTR)
+ url = urlSuitableForTestResult(wstringFromBSTR(urlBSTR));
+ SysFreeString(urlBSTR);
+
+ BSTR titleBSTR;
+ if (FAILED(navigationData->title(&titleBSTR)))
+ return E_FAIL;
+ wstring title;
+ if (titleBSTR)
+ title = wstringFromBSTR(titleBSTR);
+ SysFreeString(titleBSTR);
+
+ COMPtr<IWebURLRequest> request;
+ if (FAILED(navigationData->originalRequest(&request)))
+ return E_FAIL;
+
+ BSTR httpMethodBSTR;
+ if (FAILED(request->HTTPMethod(&httpMethodBSTR)))
+ return E_FAIL;
+ wstring httpMethod;
+ if (httpMethodBSTR)
+ httpMethod = wstringFromBSTR(httpMethodBSTR);
+ SysFreeString(httpMethodBSTR);
+
+ COMPtr<IWebURLResponse> response;
+ if (FAILED(navigationData->response(&response)))
+ return E_FAIL;
+
+ COMPtr<IWebHTTPURLResponse> httpResponse;
+ if (FAILED(response->QueryInterface(&httpResponse)))
+ return E_FAIL;
+
+ int statusCode = 0;
+ if (FAILED(httpResponse->statusCode(&statusCode)))
+ return E_FAIL;
+
+ BOOL hasSubstituteData;
+ if (FAILED(navigationData->hasSubstituteData(&hasSubstituteData)))
+ return E_FAIL;
+
+ BSTR clientRedirectSourceBSTR;
+ if (FAILED(navigationData->clientRedirectSource(&clientRedirectSourceBSTR)))
+ return E_FAIL;
+ bool hasClientRedirect = clientRedirectSourceBSTR && SysStringLen(clientRedirectSourceBSTR);
+ wstring redirectSource;
+ if (clientRedirectSourceBSTR)
+ redirectSource = urlSuitableForTestResult(wstringFromBSTR(clientRedirectSourceBSTR));
+ SysFreeString(clientRedirectSourceBSTR);
+
+ bool wasFailure = hasSubstituteData || (httpResponse && statusCode >= 400);
+
+ printf("WebView navigated to url \"%S\" with title \"%S\" with HTTP equivalent method \"%S\". The navigation was %s and was %s%S.\n",
+ url.c_str(),
+ title.c_str(),
+ httpMethod.c_str(),
+ wasFailure ? "a failure" : "successful",
+ hasClientRedirect ? "a client redirect from " : "not a client redirect",
+ redirectSource.c_str());
+
+ return S_OK;
+}
+
+HRESULT HistoryDelegate::didPerformClientRedirectFromURL(IWebView*, BSTR sourceURL, BSTR destinationURL, IWebFrame*)
+{
+ if (!gLayoutTestController->dumpHistoryDelegateCallbacks())
+ return S_OK;
+
+ wstring source;
+ if (sourceURL)
+ source = urlSuitableForTestResult(wstringFromBSTR(sourceURL));
+
+ wstring destination;
+ if (destinationURL)
+ destination = urlSuitableForTestResult(wstringFromBSTR(destinationURL));
+
+ printf("WebView performed a client redirect from \"%S\" to \"%S\".\n", source.c_str(), destination.c_str());
+ return S_OK;
+}
+
+HRESULT HistoryDelegate::didPerformServerRedirectFromURL(IWebView* webView, BSTR sourceURL, BSTR destinationURL, IWebFrame* webFrame)
+{
+ if (!gLayoutTestController->dumpHistoryDelegateCallbacks())
+ return S_OK;
+
+ wstring source;
+ if (sourceURL)
+ source = urlSuitableForTestResult(wstringFromBSTR(sourceURL));
+
+ wstring destination;
+ if (destinationURL)
+ destination = urlSuitableForTestResult(wstringFromBSTR(destinationURL));
+
+ printf("WebView performed a server redirect from \"%S\" to \"%S\".\n", source.c_str(), destination.c_str());
+ return S_OK;
+}
+
+HRESULT HistoryDelegate::updateHistoryTitle(IWebView* webView, BSTR titleBSTR, BSTR urlBSTR)
+{
+ if (!gLayoutTestController->dumpHistoryDelegateCallbacks())
+ return S_OK;
+
+ wstring url;
+ if (urlBSTR)
+ url = urlSuitableForTestResult(wstringFromBSTR(urlBSTR));
+
+ wstring title;
+ if (titleBSTR)
+ title = wstringFromBSTR(titleBSTR);
+
+ printf("WebView updated the title for history URL \"%S\" to \"%S\".\n", url.c_str(), title.c_str());
+ return S_OK;
+}
+
+HRESULT HistoryDelegate::populateVisitedLinksForWebView(IWebView* webView)
+{
+ if (!gLayoutTestController->dumpHistoryDelegateCallbacks())
+ return S_OK;
+
+ BSTR urlBSTR;
+ if (FAILED(webView->mainFrameURL(&urlBSTR)))
+ return E_FAIL;
+
+ wstring url;
+ if (urlBSTR)
+ url = urlSuitableForTestResult(wstringFromBSTR(urlBSTR));
+ SysFreeString(urlBSTR);
+
+ if (gLayoutTestController->dumpVisitedLinksCallback())
+ printf("Asked to populate visited links for WebView \"%S\"\n", url.c_str());
+
+ return S_OK;
+}
diff --git a/WebKitTools/DumpRenderTree/win/HistoryDelegate.h b/WebKitTools/DumpRenderTree/win/HistoryDelegate.h
new file mode 100644
index 0000000..41be670
--- /dev/null
+++ b/WebKitTools/DumpRenderTree/win/HistoryDelegate.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 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 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.
+ */
+
+#ifndef HistoryDelegate_h
+#define HistoryDelegate_h
+
+#include <WebKit/WebKit.h>
+#include <wtf/OwnPtr.h>
+
+class HistoryDelegate : public IWebHistoryDelegate {
+public:
+ HistoryDelegate();
+ virtual ~HistoryDelegate();
+
+ // IUnknown
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef(void);
+ virtual ULONG STDMETHODCALLTYPE Release(void);
+
+ // IWebHistoryDelegate
+ virtual HRESULT STDMETHODCALLTYPE didNavigateWithNavigationData(
+ /* [in] */ IWebView* webView,
+ /* [in] */ IWebNavigationData* navigationData,
+ /* [in] */ IWebFrame* webFrame);
+
+ virtual HRESULT STDMETHODCALLTYPE didPerformClientRedirectFromURL(
+ /* [in] */ IWebView* webView,
+ /* [in] */ BSTR sourceURL,
+ /* [in] */ BSTR destinationURL,
+ /* [in] */ IWebFrame* webFrame);
+
+ virtual HRESULT STDMETHODCALLTYPE didPerformServerRedirectFromURL(
+ /* [in] */ IWebView* webView,
+ /* [in] */ BSTR sourceURL,
+ /* [in] */ BSTR destinationURL,
+ /* [in] */ IWebFrame* webFrame);
+
+ virtual HRESULT STDMETHODCALLTYPE updateHistoryTitle(
+ /* [in] */ IWebView* webView,
+ /* [in] */ BSTR title,
+ /* [in] */ BSTR url);
+
+ virtual HRESULT STDMETHODCALLTYPE populateVisitedLinksForWebView(
+ /* [in] */ IWebView* webView);
+
+private:
+ ULONG m_refCount;
+};
+
+#endif // HistoryDelegate_h
diff --git a/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj
index 37bddeb..d9f5225 100644
--- a/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj
+++ b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj
@@ -216,6 +216,73 @@
CommandLine="if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;&#x0D;&#x0A;if not defined ARCHIVE_BUILD (if defined PRODUCTION exit /b)&#x0D;&#x0A;&#x0D;&#x0A;if not exist &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; exit /b&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CoreFoundation.resources&quot; &quot;$(WebKitOutputDir)\bin\CoreFoundation.resources&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;"
/>
</Configuration>
+ <Configuration
+ Name="Debug_All|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash&#x0D;&#x0A;if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%&#x0D;&#x0A;cmd /c&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; grep XX$(ProjectName)XX &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;if errorlevel 1 exit 1&#x0D;&#x0A;echo XX$(ProjectName)XX &gt; &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\include&quot;;&quot;$(WebKitOutputDir)\include\private&quot;;&quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"
+ />
+ <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"
+ CommandLine="if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;&#x0D;&#x0A;if not defined ARCHIVE_BUILD (if defined PRODUCTION exit /b)&#x0D;&#x0A;&#x0D;&#x0A;if not exist &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; exit /b&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d /e /i &quot;$(WebKitLibrariesDir)\bin\CoreFoundation.resources&quot; &quot;$(WebKitOutputDir)\bin\CoreFoundation.resources&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).dll&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitLibrariesDir)\bin\CoreGraphics$(LibraryConfigSuffix).pdb&quot; &quot;$(WebKitOutputDir)\bin&quot;&#x0D;&#x0A;"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp
index cf3ac85..d3cac7a 100644
--- a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp
+++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp
@@ -876,34 +876,68 @@ void LayoutTestController::addUserStyleSheet(JSStringRef source)
void LayoutTestController::showWebInspector()
{
- COMPtr<IWebViewPrivate> webView;
- if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
+ 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->setDeveloperExtrasEnabled(true);
+
+ COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
+ if (!viewPrivate)
return;
COMPtr<IWebInspector> inspector;
- if (SUCCEEDED(webView->inspector(&inspector)))
+ if (SUCCEEDED(viewPrivate->inspector(&inspector)))
inspector->show();
}
void LayoutTestController::closeWebInspector()
{
- COMPtr<IWebViewPrivate> webView;
- if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
+ COMPtr<IWebView> webView;
+ if (FAILED(frame->webView(&webView)))
+ return;
+
+ COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
+ if (!viewPrivate)
return;
COMPtr<IWebInspector> inspector;
- if (SUCCEEDED(webView->inspector(&inspector)))
- inspector->close();
+ if (FAILED(viewPrivate->inspector(&inspector)))
+ return;
+
+ inspector->close();
+
+ COMPtr<IWebPreferences> preferences;
+ if (FAILED(webView->preferences(&preferences)))
+ return;
+
+ COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences);
+ if (!prefsPrivate)
+ return;
+
+ prefsPrivate->setDeveloperExtrasEnabled(false);
}
void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script)
{
- COMPtr<IWebViewPrivate> webView;
- if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView))))
+ COMPtr<IWebView> webView;
+ if (FAILED(frame->webView(&webView)))
+ return;
+
+ COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
+ if (!viewPrivate)
return;
COMPtr<IWebInspector> inspector;
- if (FAILED(webView->inspector(&inspector)))
+ if (FAILED(viewPrivate->inspector(&inspector)))
return;
COMPtr<IWebInspectorPrivate> inspectorPrivate(Query, inspector);
@@ -912,3 +946,52 @@ void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef scrip
inspectorPrivate->evaluateInFrontend(callId, bstrT(script).GetBSTR());
}
+
+void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned worldId, JSObjectRef globalObject, JSStringRef script)
+{
+ COMPtr<IWebFramePrivate> framePrivate(Query, frame);
+ if (!framePrivate)
+ return;
+
+ BSTR result;
+ if (FAILED(framePrivate->stringByEvaluatingJavaScriptInIsolatedWorld(worldId, reinterpret_cast<OLE_HANDLE>(globalObject), bstrT(script).GetBSTR(), &result)))
+ return;
+ SysFreeString(result);
+}
+
+void LayoutTestController::removeAllVisitedLinks()
+{
+ COMPtr<IWebHistory> history;
+ if (FAILED(WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(history), reinterpret_cast<void**>(&history))))
+ return;
+
+ COMPtr<IWebHistory> sharedHistory;
+ if (FAILED(history->optionalSharedHistory(&sharedHistory)) || !sharedHistory)
+ return;
+
+ COMPtr<IWebHistoryPrivate> sharedHistoryPrivate;
+ if (FAILED(sharedHistory->QueryInterface(&sharedHistoryPrivate)))
+ return;
+
+ sharedHistoryPrivate->removeAllVisitedLinks();
+}
+
+JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
+{
+ COMPtr<IWebFramePrivate> framePrivate(Query, frame);
+ if (!framePrivate)
+ return 0;
+
+ wstring idWstring = jsStringRefToWString(id);
+ BSTR idBSTR = SysAllocStringLen((OLECHAR*)idWstring.c_str(), idWstring.length());
+ BSTR counterValueBSTR;
+ if (FAILED(framePrivate->counterValueForElementById(idBSTR, &counterValueBSTR)))
+ return 0;
+
+ wstring counterValue(counterValueBSTR, SysStringLen(counterValueBSTR));
+ SysFreeString(idBSTR);
+ SysFreeString(counterValueBSTR);
+ JSRetainPtr<JSStringRef> counterValueJS(Adopt, JSStringCreateWithCharacters(counterValue.data(), counterValue.length()));
+ return counterValueJS;
+}
+
diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc
index cccc69c..a8fbbcd 100644
--- a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc
+++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.rc
@@ -7,7 +7,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
-#include "afxres.h"
+#include "windows.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@@ -34,7 +34,7 @@ END
2 TEXTINCLUDE
BEGIN
- "#include ""afxres.h""\r\n"
+ "#include ""windows.h""\r\n"
"\0"
END
diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj
index 0e0918d..b1f2073 100644
--- a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj
+++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj
@@ -157,7 +157,7 @@
<Configuration
Name="Debug_Internal|Win32"
ConfigurationType="2"
- InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops"
CharacterSet="1"
>
<Tool
@@ -293,6 +293,76 @@
CommandLine="if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;"
/>
</Configuration>
+ <Configuration
+ Name="Debug_All|Win32"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash&#x0D;&#x0A;if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%&#x0D;&#x0A;cmd /c&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; grep XX$(ProjectName)XX &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;if errorlevel 1 exit 1&#x0D;&#x0A;echo XX$(ProjectName)XX &gt; &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(ProjectDir)..\..\TestNetscapePlugin.subproj&quot;;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;"
+ PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
+ RuntimeLibrary="3"
+ DisableSpecificWarnings="4819"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ AdditionalIncludeDirectories=""
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix)\np$(ProjectName)$(WebKitConfigSuffix).dll"
+ ModuleDefinitionFile="TestNetscapePlugin$(WebKitConfigSuffix).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"
+ CommandLine="if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
diff --git a/WebKitTools/DumpRenderTree/win/UIDelegate.cpp b/WebKitTools/DumpRenderTree/win/UIDelegate.cpp
index b78fd3e..16724d7 100755
--- a/WebKitTools/DumpRenderTree/win/UIDelegate.cpp
+++ b/WebKitTools/DumpRenderTree/win/UIDelegate.cpp
@@ -502,13 +502,14 @@ HRESULT STDMETHODCALLTYPE UIDelegate::doDragDrop(
*performedEffect = 0;
draggingInfo = new DraggingInfo(object, source);
- replaySavedEvents();
+ HRESULT oleDragAndDropReturnValue = DRAGDROP_S_CANCEL;
+ replaySavedEvents(&oleDragAndDropReturnValue);
if (draggingInfo) {
*performedEffect = draggingInfo->performedDropEffect();
delete draggingInfo;
draggingInfo = 0;
}
- return S_OK;
+ return oleDragAndDropReturnValue;
}
HRESULT STDMETHODCALLTYPE UIDelegate::webViewGetDlgCode(
diff --git a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp
index bfe1d99..72f85ae 100644
--- a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp
+++ b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp
@@ -313,3 +313,8 @@ void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef scrip
{
// FIXME: Implement this.
}
+
+void LayoutTestController::removeAllVisitedLinks()
+{
+ // FIXME: Implement this.
+}
diff --git a/WebKitTools/FindSafari/FindSafari.rc b/WebKitTools/FindSafari/FindSafari.rc
index 20c2da2..7d4abac 100644
--- a/WebKitTools/FindSafari/FindSafari.rc
+++ b/WebKitTools/FindSafari/FindSafari.rc
@@ -7,7 +7,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
-#include "afxres.h"
+#include "windows.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@@ -34,7 +34,7 @@ END
2 TEXTINCLUDE
BEGIN
- "#include ""afxres.h""\r\n"
+ "#include ""windows.h""\r\n"
"\0"
END
diff --git a/WebKitTools/FindSafari/FindSafari.vcproj b/WebKitTools/FindSafari/FindSafari.vcproj
index 48ea3df..083fa4d 100644
--- a/WebKitTools/FindSafari/FindSafari.vcproj
+++ b/WebKitTools/FindSafari/FindSafari.vcproj
@@ -15,7 +15,7 @@
</ToolFiles>
<Configurations>
<Configuration
- Name="Release|Win32"
+ Name="all|Win32"
ConfigurationType="1"
InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\release.vsprops"
CharacterSet="1"
diff --git a/WebKitTools/GtkLauncher/main.c b/WebKitTools/GtkLauncher/main.c
index 6994674..2f9350d 100644
--- a/WebKitTools/GtkLauncher/main.c
+++ b/WebKitTools/GtkLauncher/main.c
@@ -65,11 +65,11 @@ link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpoin
}
static void
-title_change_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data)
+notify_title_cb (WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
{
if (main_title)
g_free (main_title);
- main_title = g_strdup (title);
+ main_title = g_strdup (webkit_web_view_get_title(web_view));
update_title (GTK_WINDOW (main_window));
}
@@ -118,7 +118,7 @@ create_browser ()
web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view));
- g_signal_connect (web_view, "title-changed", G_CALLBACK (title_change_cb), web_view);
+ g_signal_connect (web_view, "notify::title", G_CALLBACK (notify_title_cb), web_view);
g_signal_connect (web_view, "notify::load-status", G_CALLBACK (notify_load_status_cb), web_view);
g_signal_connect (web_view, "notify::progress", G_CALLBACK (notify_progress_cb), web_view);
g_signal_connect (web_view, "hovering-over-link", G_CALLBACK (link_hover_cb), web_view);
diff --git a/WebKitTools/Scripts/VCSUtils.pm b/WebKitTools/Scripts/VCSUtils.pm
index 6ec12c9..e1e0bc2 100644
--- a/WebKitTools/Scripts/VCSUtils.pm
+++ b/WebKitTools/Scripts/VCSUtils.pm
@@ -40,10 +40,13 @@ BEGIN {
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(
+ &canonicalizePath
&chdirReturningRelativePath
&determineSVNRoot
&determineVCSRoot
+ &fixChangeLogPatch
&gitBranch
+ &gitdiff2svndiff
&isGit
&isGitBranchBuild
&isGitDirectory
@@ -51,8 +54,10 @@ BEGIN {
&isSVNDirectory
&isSVNVersion16OrNewer
&makeFilePathRelative
+ &normalizePath
&pathRelativeToSVNRepositoryRootForPath
&svnRevisionForDirectory
+ &svnStatus
);
%EXPORT_TAGS = ( );
@EXPORT_OK = ();
@@ -70,7 +75,7 @@ my $svnVersion;
sub isGitDirectory($)
{
my ($dir) = @_;
- return system("cd $dir && git rev-parse > /dev/null 2>&1") == 0;
+ return system("cd $dir && git rev-parse > " . File::Spec->devnull() . " 2>&1") == 0;
}
sub isGit()
@@ -159,7 +164,6 @@ sub determineGitRoot()
sub determineSVNRoot()
{
- my $devNull = File::Spec->devnull();
my $last = '';
my $path = '.';
my $parent = '..';
@@ -169,7 +173,7 @@ sub determineSVNRoot()
my $thisRoot;
my $thisUUID;
# Ignore error messages in case we've run past the root of the checkout.
- open INFO, "svn info '$path' 2> $devNull |" or die;
+ open INFO, "svn info '$path' 2> " . File::Spec->devnull() . " |" or die;
while (<INFO>) {
if (/^Repository Root: (.+)/) {
$thisRoot = $1;
@@ -268,4 +272,131 @@ sub makeFilePathRelative($)
return $gitRoot . $path;
}
+sub normalizePath($)
+{
+ my ($path) = @_;
+ $path =~ s/\\/\//g;
+ return $path;
+}
+
+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 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>) {
+ # Input may use a different EOL sequence than $/, so avoid chomp.
+ $_ = removeEOL($_);
+ my $normalizedStatPath = File::Spec->catdir(File::Spec->splitdir(substr($_, 7)));
+ if ($normalizedFullPath eq $normalizedStatPath) {
+ $svnStatus = "$_\n";
+ 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 = removeEOL(<SVN>) . "\n";
+ }
+ close SVN;
+ return $svnStatus;
+}
+
+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 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;
+}
+
+
1;
diff --git a/WebKitTools/Scripts/bisect-builds b/WebKitTools/Scripts/bisect-builds
index 93e9223..55bf238 100755
--- a/WebKitTools/Scripts/bisect-builds
+++ b/WebKitTools/Scripts/bisect-builds
@@ -368,7 +368,7 @@ sub mountAndRunNightly($$$$)
while (-e $mountPath) {
$i++;
usleep 100 if $i > 1;
- `hdiutil detach '$mountPath' 2> /dev/null`;
+ exec "hdiutil", "detach '$mountPath' 2> " . File::Spec->devnull();
die "Could not unmount $diskImage at $mountPath" if $i > 100;
}
die "Can't mount $diskImage: $mountPath already exists!" if -e $mountPath;
@@ -393,7 +393,7 @@ sub mountAndRunNightly($$$$)
$tempFile ||= "";
`DYLD_FRAMEWORK_PATH=$frameworkPath WEBKIT_UNSET_DYLD_FRAMEWORK_PATH=YES $safari $tempFile`;
- `hdiutil detach '$mountPath' 2> /dev/null`;
+ exec "hdiutil", "detach '$mountPath' 2> " . File::Spec->devnull();
}
sub parseRevisions($$;$)
diff --git a/WebKitTools/Scripts/bugzilla-tool b/WebKitTools/Scripts/bugzilla-tool
index ec5aa0d..8e899b5 100755
--- a/WebKitTools/Scripts/bugzilla-tool
+++ b/WebKitTools/Scripts/bugzilla-tool
@@ -73,7 +73,7 @@ def commit_message_for_this_commit(scm):
log("Parsing ChangeLog: %s" % changelog_path)
changelog_entry = ChangeLog(changelog_path).latest_entry()
if not changelog_entry:
- error("Failed to parse ChangeLog: " + os.path.abspath(changelog_path))
+ raise ScriptError(message="Failed to parse ChangeLog: " + os.path.abspath(changelog_path))
changelog_messages.append(changelog_entry)
# FIXME: We should sort and label the ChangeLog messages like commit-log-editor does.
@@ -325,6 +325,11 @@ class LandPatchesFromBugs(Command):
options += WebKitLandingScripts.land_options()
Command.__init__(self, 'Lands all patches on a bug optionally testing them first', 'BUGID', options=options)
+ @staticmethod
+ def handled_error(error):
+ log(error)
+ exit(2) # Exit 2 insted of 1 to indicate to the commit-queue to indicate we handled the error, and that the queue should keep looping.
+
@classmethod
def land_patches(cls, bug_id, patches, options, tool):
try:
@@ -344,11 +349,11 @@ class LandPatchesFromBugs(Command):
except CheckoutNeedsUpdate, e:
log("Commit was rejected because the checkout is out of date. Please update and try again.")
log("You can pass --no-build to skip building/testing after update if you believe the new commits did not affect the results.")
- error(e)
+ cls.handled_error(e)
except ScriptError, e:
# Mark the patch as commit-queue- and comment in the bug.
tool.bugs.reject_patch_from_commit_queue(patch['id'], e.message_with_output())
- error(e)
+ cls.handled_error(e)
@staticmethod
def _fetch_list_of_patches_to_land(options, args, tool):
@@ -420,6 +425,7 @@ class PostDiffAsPatchToBug(Command):
return [
make_option("--no-obsolete", action="store_false", dest="obsolete_patches", default=True, help="Do not obsolete old patches before posting this one."),
make_option("--no-review", action="store_false", dest="review", default=True, help="Do not mark the patch for review."),
+ make_option("--request-commit", action="store_true", dest="request_commit", default=False, help="Mark the patch as needing auto-commit after review."),
]
@staticmethod
@@ -443,7 +449,7 @@ class PostDiffAsPatchToBug(Command):
diff_file = StringIO.StringIO(diff) # add_patch_to_bug expects a file-like object
description = options.description or "Patch v1"
- tool.bugs.add_patch_to_bug(bug_id, diff_file, description, mark_for_review=options.review)
+ tool.bugs.add_patch_to_bug(bug_id, diff_file, description, mark_for_review=options.review, mark_for_commit_queue=options.request_commit)
class PostCommitsAsPatchesToBug(Command):
@@ -493,7 +499,7 @@ class PostCommitsAsPatchesToBug(Command):
diff_file = self._diff_file_for_commit(tool, commit_id)
description = options.description or commit_message.description(lstrip=True, strip_url=True)
comment_text = self._comment_text_for_commit(options, commit_message, tool, commit_id)
- tool.bugs.add_patch_to_bug(bug_id, diff_file, description, comment_text, mark_for_review=options.review)
+ tool.bugs.add_patch_to_bug(bug_id, diff_file, description, comment_text, mark_for_review=options.review, mark_for_commit_queue=options.request_commit)
class RolloutCommit(Command):
@@ -560,6 +566,7 @@ class CreateBug(Command):
make_option("--component", action="store", type="string", dest="component", help="Component for the new bug."),
make_option("--no-prompt", action="store_false", dest="prompt", default=True, help="Do not prompt for bug title and comment; use commit log instead."),
make_option("--no-review", action="store_false", dest="review", default=True, help="Do not mark the patch for review."),
+ make_option("--request-commit", action="store_true", dest="request_commit", default=False, help="Mark the patch as needing auto-commit after review."),
]
Command.__init__(self, 'Create a bug from local changes or local commits.', '[COMMITISH]', options=options)
@@ -583,7 +590,7 @@ class CreateBug(Command):
diff = tool.scm().create_patch_from_local_commit(commit_id)
diff_file = StringIO.StringIO(diff) # create_bug_with_patch expects a file-like object
- bug_id = tool.bugs.create_bug_with_patch(bug_title, comment_text, options.component, diff_file, "Patch v1", cc=options.cc, mark_for_review=options.review)
+ bug_id = tool.bugs.create_bug_with_patch(bug_title, comment_text, options.component, diff_file, "Patch v1", cc=options.cc, mark_for_review=options.review, mark_for_commit_queue=options.request_commit)
if bug_id and len(commit_ids) > 1:
options.bug_id = bug_id
@@ -603,7 +610,7 @@ class CreateBug(Command):
diff = tool.scm().create_patch()
diff_file = StringIO.StringIO(diff) # create_bug_with_patch expects a file-like object
- bug_id = tool.bugs.create_bug_with_patch(bug_title, comment_text, options.component, diff_file, "Patch v1", cc=options.cc, mark_for_review=options.review)
+ bug_id = tool.bugs.create_bug_with_patch(bug_title, comment_text, options.component, diff_file, "Patch v1", cc=options.cc, mark_for_review=options.review, mark_for_commit_queue=options.request_commit)
def prompt_for_bug_title_and_comment(self):
bug_title = raw_input("Bug title: ")
@@ -644,6 +651,7 @@ class CheckTreeStatus(Command):
class LandPatchesFromCommitQueue(Command):
def __init__(self):
options = [
+ make_option("--is-relaunch", action="store_true", dest="is_relaunch", default=False, help="Internal: Used by the queue to indicate that it's relaunching itself."),
make_option("--no-confirm", action="store_false", dest="confirm", default=True, help="Do not ask the user for confirmation before running the queue. Dangerous!"),
make_option("--status-host", action="store", type="string", dest="status_host", default=StatusBot.default_host, help="Do not ask the user for confirmation before running the queue. Dangerous!"),
]
@@ -675,16 +683,25 @@ class LandPatchesFromCommitQueue(Command):
wake_time = datetime.now() + timedelta(seconds=cls.seconds_to_sleep)
return "%s Sleeping until %s (%s)." % (message, wake_time.strftime(cls.log_date_format), cls.sleep_duration_text)
- @classmethod
- def _sleep(cls, message):
- log(cls._sleep_message(message))
- time.sleep(cls.seconds_to_sleep)
+ def _sleep(self, message):
+ log(self._sleep_message(message))
+ time.sleep(self.seconds_to_sleep)
+ self._next_patch()
def _update_status_and_sleep(self, message):
status_message = self._sleep_message(message)
self.status_bot.update_status(status_message)
log(status_message)
time.sleep(self.seconds_to_sleep)
+ self._next_patch()
+
+ def _next_patch(self):
+ # Re-exec this script to catch any updates to the script.
+ # Make sure that the re-execed commit-queue does not wait for the user.
+ args = sys.argv[:]
+ if args.count("--is-relaunch") == 0:
+ args.append("--is-relaunch")
+ os.execvp(sys.argv[0], args)
@staticmethod
def _open_log_file(log_path):
@@ -705,50 +722,55 @@ class LandPatchesFromCommitQueue(Command):
log_file.close()
def execute(self, options, args, tool):
- log("CAUTION: commit-queue will discard all local changes in %s" % tool.scm().checkout_root)
- if options.confirm:
- response = raw_input("Are you sure? Type 'yes' to continue: ")
- if (response != 'yes'):
- error("User declined.")
+ if not options.is_relaunch:
+ log("CAUTION: commit-queue will discard all local changes in %s" % tool.scm().checkout_root)
+ if options.confirm:
+ response = raw_input("Are you sure? Type 'yes' to continue: ")
+ if (response != 'yes'):
+ error("User declined.")
queue_log = self._add_log_to_output_tee(self.queue_log_path)
- log("Running WebKit Commit Queue. %s" % datetime.now().strftime(self.log_date_format))
+ if not options.is_relaunch:
+ log("Running WebKit Commit Queue. %s" % datetime.now().strftime(self.log_date_format))
self.status_bot = StatusBot(host=options.status_host)
- while (True):
- # Either of these calls could throw URLError which shouldn't stop the queue.
- # We catch all exceptions just in case.
- try:
- # Fetch patches instead of just bug ids to that we validate reviewer/committer flags on every patch.
- patches = tool.bugs.fetch_patches_from_commit_queue(reject_invalid_patches=True)
- if not len(patches):
- self._update_status_and_sleep("Empty queue.")
- continue
- patch_ids = map(lambda patch: patch['id'], patches)
- first_bug_id = patches[0]['bug_id']
- log("%s in commit queue [%s]" % (pluralize('patch', len(patches)), ", ".join(patch_ids)))
-
- if not tool.buildbot.core_builders_are_green():
- self._update_status_and_sleep("Builders (http://build.webkit.org) are red.")
- continue
-
- self.status_bot.update_status("Landing patches from bug %s." % first_bug_id, bug_id=first_bug_id)
- except Exception, e:
- # Don't try tell the status bot, in case telling it causes an exception.
- self._sleep("Exception while checking queue and bots: %s." % e)
- continue
-
- # Try to land patches on the first bug in the queue before looping
- bug_log_path = os.path.join(self.bug_logs_directory, "%s.log" % first_bug_id)
- bug_log = self._add_log_to_output_tee(bug_log_path)
- bugzilla_tool_path = __file__ # re-execute this script
- bugzilla_tool_args = [bugzilla_tool_path, 'land-patches', '--force-clean', '--commit-queue', '--quiet', first_bug_id]
- WebKitLandingScripts.run_command_with_teed_output(bugzilla_tool_args, sys.stdout)
- self._remove_log_from_output_tee(bug_log)
-
- log("Finished WebKit Commit Queue. %s" % datetime.now().strftime(self.log_date_format))
- self._remove_log_from_output_tee(queue_log)
+ # Either of these calls could throw URLError which shouldn't stop the queue.
+ # We catch all exceptions just in case.
+ try:
+ # Fetch patches instead of just bug ids to that we validate reviewer/committer flags on every patch.
+ patches = tool.bugs.fetch_patches_from_commit_queue(reject_invalid_patches=True)
+ if not len(patches):
+ self._update_status_and_sleep("Empty queue.")
+ patch_ids = map(lambda patch: patch['id'], patches)
+ first_bug_id = patches[0]['bug_id']
+ log("%s in commit queue [%s]" % (pluralize('patch', len(patches)), ", ".join(patch_ids)))
+
+ red_builders_names = tool.buildbot.red_core_builders_names()
+ if red_builders_names:
+ red_builders_names = map(lambda name: '"%s"' % name, red_builders_names) # Add quotes around the names.
+ self._update_status_and_sleep("Builders [%s] are red. See http://build.webkit.org." % ", ".join(red_builders_names))
+
+ self.status_bot.update_status("Landing patches from bug %s." % first_bug_id, bug_id=first_bug_id)
+ except Exception, e:
+ # Don't try tell the status bot, in case telling it causes an exception.
+ self._sleep("Exception while checking queue and bots: %s." % e)
+
+ # Try to land patches on the first bug in the queue before looping
+ bug_log_path = os.path.join(self.bug_logs_directory, "%s.log" % first_bug_id)
+ bug_log = self._add_log_to_output_tee(bug_log_path)
+ bugzilla_tool_path = __file__ # re-execute this script
+ bugzilla_tool_args = [bugzilla_tool_path, 'land-patches', '--force-clean', '--commit-queue', '--quiet', first_bug_id]
+ try:
+ WebKitLandingScripts.run_and_throw_if_fail(bugzilla_tool_args)
+ except ScriptError, e:
+ # Unexpected failure! Mark the patch as commit-queue- and comment in the bug.
+ # exit(2) is a special exit code we use to indicate that the error was already handled by land-patches and we should keep looping anyway.
+ if e.exit_code != 2:
+ tool.bugs.reject_patch_from_commit_queue(patch['id'], "Unexpected failure when landing patch! Please file a bug against bugzilla-tool.\n%s" % e.message_with_output())
+ self._remove_log_from_output_tee(bug_log)
+ # self._remove_log_from_output_tee(queue_log) # implicit in the exec()
+ self._next_patch()
class NonWrappingEpilogIndentedHelpFormatter(IndentedHelpFormatter):
diff --git a/WebKitTools/Scripts/modules/bugzilla.py b/WebKitTools/Scripts/modules/bugzilla.py
index daf3f19..fe81b48 100644
--- a/WebKitTools/Scripts/modules/bugzilla.py
+++ b/WebKitTools/Scripts/modules/bugzilla.py
@@ -294,7 +294,18 @@ class Bugzilla:
self.authenticated = True
- def add_patch_to_bug(self, bug_id, patch_file_object, description, comment_text=None, mark_for_review=False):
+ def _fill_attachment_form(self, description, patch_file_object, comment_text=None, mark_for_review=False, mark_for_commit_queue=False, bug_id=None):
+ self.browser['description'] = description
+ self.browser['ispatch'] = ("1",)
+ self.browser['flag_type-1'] = ('?',) if mark_for_review else ('X',)
+ self.browser['flag_type-3'] = ('?',) if mark_for_commit_queue else ('X',)
+ if bug_id:
+ patch_name = "bug-%s-%s.patch" % (bug_id, timestamp())
+ else:
+ patch_name ="%s.patch" % timestamp()
+ self.browser.add_file(patch_file_object, "text/plain", patch_name, 'data')
+
+ def add_patch_to_bug(self, bug_id, patch_file_object, description, comment_text=None, mark_for_review=False, mark_for_commit_queue=False):
self.authenticate()
log('Adding patch "%s" to bug %s' % (description, bug_id))
@@ -304,13 +315,10 @@ class Bugzilla:
self.browser.open("%sattachment.cgi?action=enter&bugid=%s" % (self.bug_server_url, bug_id))
self.browser.select_form(name="entryform")
- self.browser['description'] = description
- self.browser['ispatch'] = ("1",)
+ self._fill_attachment_form(description, patch_file_object, mark_for_review=mark_for_review, mark_for_commit_queue=mark_for_commit_queue, bug_id=bug_id)
if comment_text:
log(comment_text)
self.browser['comment'] = comment_text
- self.browser['flag_type-1'] = ('?',) if mark_for_review else ('X',)
- self.browser.add_file(patch_file_object, "text/plain", "bug-%s-%s.patch" % (bug_id, timestamp()))
self.browser.submit()
def prompt_for_component(self, components):
@@ -334,7 +342,7 @@ class Bugzilla:
error_message = "\n" + '\n'.join([" " + line.strip() for line in text_lines if line.strip()])
raise BugzillaError("Bug not created: %s" % error_message)
- def create_bug_with_patch(self, bug_title, bug_description, component, patch_file_object, patch_description, cc, mark_for_review=False):
+ def create_bug_with_patch(self, bug_title, bug_description, component, patch_file_object, patch_description, cc, mark_for_review=False, mark_for_commit_queue=False):
self.authenticate()
log('Creating bug with patch description "%s"' % patch_description)
@@ -355,10 +363,8 @@ class Bugzilla:
if bug_description:
log(bug_description)
self.browser['comment'] = bug_description
- self.browser['description'] = patch_description
- self.browser['ispatch'] = ("1",)
- self.browser['flag_type-1'] = ('?',) if mark_for_review else ('X',)
- self.browser.add_file(patch_file_object, "text/plain", "%s.patch" % timestamp(), 'data')
+
+ self._fill_attachment_form(patch_description, patch_file_object, mark_for_review=mark_for_review, mark_for_commit_queue=mark_for_commit_queue)
response = self.browser.submit()
bug_id = self._check_create_bug_response(response.read())
diff --git a/WebKitTools/Scripts/modules/buildbot.py b/WebKitTools/Scripts/modules/buildbot.py
index 4478429..e948d8c 100644
--- a/WebKitTools/Scripts/modules/buildbot.py
+++ b/WebKitTools/Scripts/modules/buildbot.py
@@ -83,11 +83,19 @@ class BuildBot:
builders.append(builder)
return builders
- def core_builders_are_green(self):
+ def red_core_builders(self):
+ red_builders = []
for builder in self._builder_statuses_with_names_matching_regexps(self.builder_statuses(), self.core_builder_names_regexps):
if not builder['is_green']:
- return False
- return True
+ red_builders.append(builder)
+ return red_builders
+
+ def red_core_builders_names(self):
+ red_builders = self.red_core_builders()
+ return map(lambda builder: builder['name'], red_builders)
+
+ def core_builders_are_green(self):
+ return not self.red_core_builders()
def builder_statuses(self):
build_status_url = self.buildbot_server_url + 'one_box_per_builder'
diff --git a/WebKitTools/Scripts/modules/buildbot_unittest.py b/WebKitTools/Scripts/modules/buildbot_unittest.py
index 461e5a2..a85f2ea 100644
--- a/WebKitTools/Scripts/modules/buildbot_unittest.py
+++ b/WebKitTools/Scripts/modules/buildbot_unittest.py
@@ -91,6 +91,22 @@ class BuildBotTest(unittest.TestCase):
for key, expected_value in expected_parsing.items():
self.assertEquals(builder[key], expected_value, ("Builder %d parse failure for key: %s: Actual='%s' Expected='%s'" % (x, key, builder[key], expected_value)))
+ def test_core_builder_methods(self):
+ buildbot = BuildBot()
+
+ # Override builder_statuses function to not touch the network.
+ def example_builder_statuses(): # We could use instancemethod() to bind 'self' but we don't need to.
+ return BuildBotTest._expected_example_one_box_parsings
+ buildbot.builder_statuses = example_builder_statuses
+
+ buildbot.core_builder_names_regexps = [ 'Leopard', "Windows.*Build" ]
+ self.assertEquals(buildbot.red_core_builders_names(), [])
+ self.assertTrue(buildbot.core_builders_are_green())
+
+ buildbot.core_builder_names_regexps = [ 'SnowLeopard', 'Qt' ]
+ self.assertEquals(buildbot.red_core_builders_names(), [ u'SnowLeopard Intel Release', u'Qt Linux Release' ])
+ self.assertFalse(buildbot.core_builders_are_green())
+
def test_builder_name_regexps(self):
buildbot = BuildBot()
diff --git a/WebKitTools/Scripts/modules/committers.py b/WebKitTools/Scripts/modules/committers.py
index e157fb4..fc263eb 100644
--- a/WebKitTools/Scripts/modules/committers.py
+++ b/WebKitTools/Scripts/modules/committers.py
@@ -42,22 +42,28 @@ class Reviewer(Committer):
Committer.__init__(self, name, email)
self.can_review = True
-# All reviewers are committers, so this list is only of committers
-# who are not reviewers.
+# This is intended as a cannonical, machine-readable list of all non-reviewer committers for WebKit.
+# If your name is missing here and you are a committer, please add it. No review needed.
+# All reviewers are committers, so this list is only of committers who are not reviewers.
committers_unable_to_review = [
Committer("Aaron Boodman", "aa@chromium.org"),
Committer("Adam Langley", "agl@chromium.org"),
Committer("Albert J. Wong", "ajwong@chromium.org"),
+ Committer("Anton Muhin", "antonm@chromium.org"),
Committer("Antonio Gomes", "tonikitoo@webkit.org"),
Committer("Anthony Ricaud", "rik@webkit.org"),
Committer("Ben Murdoch", "benm@google.com"),
+ Committer("Chris Fleizach", "cfleizach@apple.com"),
Committer("Brent Fulgham", "bfulgham@webkit.org"),
Committer("Brian Weinstein", "bweinstein@apple.com"),
Committer("Cameron McCormack", "cam@webkit.org"),
+ Committer("Collin Jackson", "collinj@webkit.org"),
+ Committer("Csaba Osztrogonac", "ossy@webkit.org"),
Committer("Daniel Bates", "dbates@webkit.org"),
Committer("Drew Wilson", "atwilson@chromium.org"),
Committer("Dirk Schulze", "krit@webkit.org"),
Committer("Dmitry Titov", "dimich@chromium.org"),
+ Committer("Dumitru Daniliuc", "dumi@chromium.org"),
Committer("Eli Fidler", "eli@staikos.net"),
Committer("Eric Roman", "eroman@chromium.org"),
Committer("Fumitoshi Ukai", "ukai@chromium.org"),
@@ -69,38 +75,53 @@ committers_unable_to_review = [
Committer("Joseph Pecoraro", "joepeck@webkit.org"),
Committer("Julie Parent", "jparent@google.com"),
Committer("Kenneth Rohde Christiansen", "kenneth@webkit.org"),
+ Committer("Kent Tamura", "tkent@chromium.org"),
Committer("Laszlo Gombos", "laszlo.1.gombos@nokia.com"),
+ Committer("Mads Ager", "ager@chromium.org"),
+ Committer("Mike Belshe", "mike@belshe.com"),
Committer("Nate Chapin", "japhet@chromium.org"),
Committer("Ojan Vafai", "ojan@chromium.org"),
Committer("Pam Greene", "pam@chromium.org"),
Committer("Peter Kasting", "pkasting@google.com"),
Committer("Pierre d'Herbemont", "pdherbemont@free.fr"),
+ Committer("Roland Steiner", "rolandsteiner@chromium.org"),
Committer("Ryosuke Niwa", "rniwa@webkit.org"),
Committer("Scott Violet", "sky@chromium.org"),
Committer("Shinichiro Hamaji", "hamaji@chromium.org"),
+ Committer("Steve Block", "steveblock@google.com"),
Committer("Tony Chang", "tony@chromium.org"),
Committer("Yael Aharon", "yael.aharon@nokia.com"),
Committer("Yong Li", "yong.li@torchmobile.com"),
+ Committer("Yury Semikhatsky", "yurys@chromium.org"),
Committer("Zoltan Horvath", "zoltan@webkit.org"),
]
+# This is intended as a cannonical, machine-readable list of all reviewers for WebKit.
+# If your name is missing here and you are a reviewer, please add it. No review needed.
reviewers_list = [
Reviewer("Adam Barth", "abarth@webkit.org"),
+ Reviewer("Ada Chan", "adachan@apple.com"),
Reviewer("Adam Roben", "aroben@apple.com"),
Reviewer("Adam Treat", "treat@kde.org"),
Reviewer("Adele Peterson", "adele@apple.com"),
Reviewer("Alexey Proskuryakov", "ap@webkit.org"),
+ Reviewer("Alice Liu", "alice.liu@apple.com"),
+ Reviewer("Alp Toker", "alp@nuanti.com"),
Reviewer("Anders Carlsson", "andersca@apple.com"),
Reviewer("Antti Koivisto", "koivisto@iki.fi"),
Reviewer("Ariya Hidayat", "ariya.hidayat@trolltech.com"),
Reviewer("Brady Eidson", "beidson@apple.com"),
+ Reviewer("Cameron Zwarich", "zwarich@apple.com"),
Reviewer("Dan Bernstein", "mitz@webkit.org"),
Reviewer("Darin Adler", "darin@apple.com"),
Reviewer("Darin Fisher", "fishd@chromium.org"),
+ Reviewer("David Harrison", "harrison@apple.com"),
Reviewer("David Hyatt", "hyatt@apple.com"),
Reviewer("David Kilzer", "ddkilzer@webkit.org"),
Reviewer("David Levin", "levin@chromium.org"),
Reviewer("Dimitri Glazkov", "dglazkov@chromium.org"),
+ Reviewer("Don Melton", "gramps@apple.com"),
+ Reviewer("Dmitri Titov", "dimich@chromium.org"),
Reviewer("Eric Carlson", "eric.carlson@apple.com"),
Reviewer("Eric Seidel", "eric@webkit.org"),
Reviewer("Gavin Barraclough", "barraclough@apple.com"),
@@ -110,16 +131,22 @@ reviewers_list = [
Reviewer("Holger Freyther", "zecke@selfish.org"),
Reviewer("Jan Alonzo", "jmalonzo@gmail.com"),
Reviewer("John Sullivan", "sullivan@apple.com"),
+ Reviewer("Jon Honeycutt", "jhoneycutt@apple.com"),
Reviewer("Justin Garcia", "justin.garcia@apple.com"),
+ Reviewer("Kevin Decker", "kdecker@apple.com"),
Reviewer("Kevin McCullough", "kmccullough@apple.com"),
Reviewer("Kevin Ollivier", "kevino@theolliviers.com"),
+ Reviewer("Lars Knoll", "lars@trolltech.com"),
Reviewer("Maciej Stachowiak", "mjs@apple.com"),
Reviewer("Mark Rowe", "mrowe@apple.com"),
Reviewer("Nikolas Zimmermann", "zimmermann@kde.org"),
Reviewer("Oliver Hunt", "oliver@apple.com"),
+ Reviewer("Pavel Feldman", "pfeldman@chromium.org"),
+ Reviewer("Rob Buis", "rwlbuis@gmail.com"),
Reviewer("Sam Weinig", "sam@webkit.org"),
Reviewer("Simon Fraser", "simon.fraser@apple.com"),
Reviewer("Simon Hausmann", "hausmann@webkit.org"),
+ Reviewer("Stephanie Lewis", "slewis@apple.com"),
Reviewer("Steve Falkenburg", "sfalken@apple.com"),
Reviewer("Timothy Hatcher", "timothy@hatcher.name"),
Reviewer(u'Tor Arne Vestb\xf8', "vestbo@webkit.org"),
diff --git a/WebKitTools/Scripts/modules/cpp_style.py b/WebKitTools/Scripts/modules/cpp_style.py
index 0c9dfa0..485b07c 100644
--- a/WebKitTools/Scripts/modules/cpp_style.py
+++ b/WebKitTools/Scripts/modules/cpp_style.py
@@ -1533,16 +1533,15 @@ def check_spacing(filename, clean_lines, line_number, error):
# Don't try to do spacing checks for operator methods
line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line)
-
- # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
- # Otherwise not. Note we only check for non-spaces on *both* sides;
- # sometimes people put non-spaces on one side when aligning ='s among
- # many lines (not that this is behavior that I approve of...)
- if search(r'[\w.]=[\w.]', line) and not search(r'\b(if|while) ', line):
+ # Don't try to do spacing checks for #include statements at minimum it
+ # messes up checks for spacing around /
+ if match(r'\s*#\s*include', line):
+ return
+ if search(r'[\w.]=[\w.]', line):
error(filename, line_number, 'whitespace/operators', 4,
'Missing spaces around =')
- # FIXME: It's not ok to have spaces around binary operators like + - * / .
+ # FIXME: It's not ok to have spaces around binary operators like .
# You should always have whitespace around binary operators.
# Alas, we can't test < or > because they're legitimately used sans spaces
@@ -1559,12 +1558,6 @@ def check_spacing(filename, clean_lines, line_number, error):
if matched:
error(filename, line_number, 'whitespace/operators', 3,
'Missing spaces around %s' % matched.group(1))
- # We allow no-spaces around << and >> when used like this: 10<<20, but
- # not otherwise (particularly, not when used as streams)
- matched = search(r'[^0-9\s](<<|>>)[^0-9\s=]', line)
- if matched:
- error(filename, line_number, 'whitespace/operators', 3,
- 'Missing spaces around %s' % matched.group(1))
# There shouldn't be space around unary operators
matched = search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
@@ -1699,50 +1692,32 @@ def check_namespace_indentation(filename, clean_lines, line_number, file_extensi
if not namespace_match:
return
- namespace_indentation = namespace_match.group('namespace_indentation')
-
- is_header_file = file_extension == 'h'
- is_implementation_file = not is_header_file
+ current_indentation_level = len(namespace_match.group('namespace_indentation'))
+ if current_indentation_level > 0:
+ error(filename, line_number, 'whitespace/indent', 4,
+ 'namespace should never be indented.')
+ return
+ looking_for_semicolon = False;
line_offset = 0
-
- if is_header_file:
- inner_indentation = namespace_indentation + ' ' * 4
-
- for current_line in clean_lines.raw_lines[line_number + 1:]:
- line_offset += 1
-
- # Skip not only empty lines but also those with preprocessor directives.
- # Goto labels don't occur in header files, so no need to check for those.
- if current_line.strip() == '' or current_line.startswith('#'):
- continue
-
- if not current_line.startswith(inner_indentation):
- # If something unindented was discovered, make sure it's a closing brace.
- if not current_line.startswith(namespace_indentation + '}'):
+ in_preprocessor_directive = False;
+ for current_line in clean_lines.elided[line_number + 1:]:
+ line_offset += 1
+ if not current_line.strip():
+ continue
+ if not current_indentation_level:
+ if not (in_preprocessor_directive or looking_for_semicolon):
+ if not match(r'\S', current_line):
error(filename, line_number + line_offset, 'whitespace/indent', 4,
- 'In a header, code inside a namespace should be indented.')
- break
-
- if is_implementation_file:
- for current_line in clean_lines.raw_lines[line_number + 1:]:
- line_offset += 1
-
- # Skip not only empty lines but also those with (goto) labels.
- # The goto label regexp accepts spaces or the beginning of a
- # comment (if anything) after the initial colon.
- if current_line.strip() == '' or match(r'\w+\s*:([\s\/].*)?$', current_line):
- continue
-
- remaining_line = current_line[len(namespace_indentation):]
- if not match(r'\S', remaining_line):
- error(filename, line_number + line_offset, 'whitespace/indent', 4,
- 'In an implementation file, code inside a namespace should not be indented.')
-
- # Just check the first non-empty line in any case, because
- # otherwise we would need to count opened and closed braces,
- # which is obviously a lot more complicated.
- break
-
+ 'Code inside a namespace should not be indented.')
+ if in_preprocessor_directive or (current_line.strip()[0] == '#'): # This takes care of preprocessor directive syntax.
+ in_preprocessor_directive = current_line[-1] == '\\'
+ else:
+ looking_for_semicolon = ((current_line.find(';') == -1) and (current_line.strip()[-1] != '}')) or (current_line[-1] == '\\')
+ else:
+ looking_for_semicolon = False; # If we have a brace we may not need a semicolon.
+ current_indentation_level += current_line.count('{') - current_line.count('}')
+ if current_indentation_level < 0:
+ break;
def check_using_std(filename, clean_lines, line_number, error):
"""Looks for 'using std::foo;' statements which should be replaced with 'using namespace std;'.
diff --git a/WebKitTools/Scripts/modules/cpp_style_unittest.py b/WebKitTools/Scripts/modules/cpp_style_unittest.py
index 322356e..d5637f4 100644
--- a/WebKitTools/Scripts/modules/cpp_style_unittest.py
+++ b/WebKitTools/Scripts/modules/cpp_style_unittest.py
@@ -1265,6 +1265,12 @@ class CppStyleTest(CppStyleTestBase):
self.assert_lint('a<Foo&> t <<= &b | &c;', '')
self.assert_lint('a<Foo*> t <<= &b & &c; // Test', '')
self.assert_lint('a<Foo*> t <<= *b / &c; // Test', '')
+ self.assert_lint('if (a=b == 1)', 'Missing spaces around = [whitespace/operators] [4]')
+ self.assert_lint('a = 1<<20', 'Missing spaces around << [whitespace/operators] [3]')
+ self.assert_lint('if (a = b == 1)', '')
+ self.assert_lint('a = 1 << 20', '')
+ self.assert_multi_line_lint('#include "config.h"\n#include <sys/io.h>\n',
+ '')
def test_spacing_before_last_semicolon(self):
self.assert_lint('call_function() ;',
@@ -2806,40 +2812,39 @@ class WebKitStyleTest(CppStyleTestBase):
'Weird number of spaces at line-start. Are you using a 4-space indent? [whitespace/indent] [3]')
# FIXME: No tests for 8-spaces.
- # 3. In a header, code inside a namespace should be indented.
+ # 3. In a header, code inside a namespace should not be indented.
self.assert_multi_line_lint(
'namespace WebCore {\n\n'
- ' class Document {\n'
- ' int myVariable;\n'
- ' };\n'
+ 'class Document {\n'
+ ' int myVariable;\n'
+ '};\n'
'}',
'',
'foo.h')
self.assert_multi_line_lint(
'namespace OuterNamespace {\n'
' namespace InnerNamespace {\n'
- ' class Document {\n'
- ' };\n'
- ' };\n'
+ ' class Document {\n'
+ '};\n'
+ '};\n'
'}',
- '',
+ ['Code inside a namespace should not be indented. [whitespace/indent] [4]', 'namespace should never be indented. [whitespace/indent] [4]'],
'foo.h')
self.assert_multi_line_lint(
'namespace WebCore {\n'
'#if 0\n'
' class Document {\n'
- ' };\n'
+ '};\n'
'#endif\n'
'}',
- '',
+ 'Code inside a namespace should not be indented. [whitespace/indent] [4]',
'foo.h')
self.assert_multi_line_lint(
'namespace WebCore {\n'
'class Document {\n'
'};\n'
'}',
- 'In a header, code inside a namespace should be indented.'
- ' [whitespace/indent] [4]',
+ '',
'foo.h')
# 4. In an implementation file (files with the extension .cpp, .c
@@ -2858,14 +2863,52 @@ class WebKitStyleTest(CppStyleTestBase):
'namespace OuterNamespace {\n'
'namespace InnerNamespace {\n'
'Document::Foo() { }\n'
- '}',
- '',
+ ' void* p;\n'
+ '}\n'
+ '}\n',
+ 'Code inside a namespace should not be indented. [whitespace/indent] [4]',
'foo.cpp')
self.assert_multi_line_lint(
- ' namespace WebCore {\n\n'
- 'start: // Pointless code, but tests the label regexp.\n'
- ' goto start;\n'
- ' }',
+ 'namespace OuterNamespace {\n'
+ 'namespace InnerNamespace {\n'
+ 'Document::Foo() { }\n'
+ '}\n'
+ ' void* p;\n'
+ '}\n',
+ 'Code inside a namespace should not be indented. [whitespace/indent] [4]',
+ 'foo.cpp')
+ self.assert_multi_line_lint(
+ 'namespace WebCore {\n\n'
+ ' const char* foo = "start:;"\n'
+ ' "dfsfsfs";\n'
+ '}\n',
+ 'Code inside a namespace should not be indented. [whitespace/indent] [4]',
+ 'foo.cpp')
+ self.assert_multi_line_lint(
+ 'namespace WebCore {\n\n'
+ 'const char* foo(void* a = ";", // ;\n'
+ ' void* b);\n'
+ ' void* p;\n'
+ '}\n',
+ 'Code inside a namespace should not be indented. [whitespace/indent] [4]',
+ 'foo.cpp')
+ self.assert_multi_line_lint(
+ 'namespace WebCore {\n\n'
+ 'const char* foo[] = {\n'
+ ' "void* b);", // ;\n'
+ ' "asfdf",\n'
+ ' }\n'
+ ' void* p;\n'
+ '}\n',
+ 'Code inside a namespace should not be indented. [whitespace/indent] [4]',
+ 'foo.cpp')
+ self.assert_multi_line_lint(
+ 'namespace WebCore {\n\n'
+ 'const char* foo[] = {\n'
+ ' "void* b);", // }\n'
+ ' "asfdf",\n'
+ ' }\n'
+ '}\n',
'',
'foo.cpp')
self.assert_multi_line_lint(
@@ -2875,15 +2918,30 @@ class WebKitStyleTest(CppStyleTestBase):
'start: // infinite loops are fun!\n'
' goto start;\n'
' }',
- '',
+ 'namespace should never be indented. [whitespace/indent] [4]',
'foo.cpp')
self.assert_multi_line_lint(
'namespace WebCore {\n'
' Document::Foo() { }\n'
'}',
- 'In an implementation file, code inside a namespace should not be indented.'
+ 'Code inside a namespace should not be indented.'
' [whitespace/indent] [4]',
'foo.cpp')
+ self.assert_multi_line_lint(
+ 'namespace WebCore {\n'
+ '#define abc(x) x; \\\n'
+ ' x\n'
+ '}',
+ '',
+ 'foo.cpp')
+ self.assert_multi_line_lint(
+ 'namespace WebCore {\n'
+ '#define abc(x) x; \\\n'
+ ' x\n'
+ ' void* x;'
+ '}',
+ 'Code inside a namespace should not be indented. [whitespace/indent] [4]',
+ 'foo.cpp')
# 5. A case label should line up with its switch statement. The
# case statement is indented.
@@ -3246,7 +3304,7 @@ class WebKitStyleTest(CppStyleTestBase):
'')
self.assert_multi_line_lint(
'namespace WebCore {\n'
- ' int foo;\n'
+ 'int foo;\n'
'};\n',
'')
self.assert_multi_line_lint(
diff --git a/WebKitTools/Scripts/modules/scm.py b/WebKitTools/Scripts/modules/scm.py
index 3daecbc..3ffa23b 100644
--- a/WebKitTools/Scripts/modules/scm.py
+++ b/WebKitTools/Scripts/modules/scm.py
@@ -124,9 +124,14 @@ class SCM:
@staticmethod
def run_command(args, cwd=None, input=None, error_handler=default_error_handler, return_exit_code=False):
- stdin = subprocess.PIPE if input else None
+ if hasattr(input, 'read'): # Check if the input is a file.
+ stdin = input
+ string_to_communicate = None
+ else:
+ stdin = subprocess.PIPE if input else None
+ string_to_communicate = input
process = subprocess.Popen(args, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd)
- output = process.communicate(input)[0].rstrip()
+ output = process.communicate(string_to_communicate)[0].rstrip()
exit_code = process.wait()
if exit_code:
script_error = ScriptError(script_args=args, exit_code=exit_code, output=output, cwd=cwd)
@@ -166,11 +171,8 @@ class SCM:
args = [self.script_path('svn-apply'), '--reviewer', patch['reviewer']]
if force:
args.append('--force')
- patch_apply_process = subprocess.Popen(args, stdin=curl_process.stdout)
- return_code = patch_apply_process.wait()
- if return_code:
- raise ScriptError(message="Patch %s from bug %s failed to download and apply." % (patch['url'], patch['bug_id']))
+ self.run_command(args, input=curl_process.stdout)
def run_status_and_extract_filenames(self, status_command, status_regexp):
filenames = []
@@ -392,7 +394,7 @@ class Git(SCM):
@classmethod
def in_working_directory(cls, path):
- return cls.run_command(['git', 'rev-parse', '--is-inside-work-tree'], cwd=path) == "true"
+ return cls.run_command(['git', 'rev-parse', '--is-inside-work-tree'], cwd=path, error_handler=ignore_error) == "true"
@classmethod
def find_checkout_root(cls, path):
diff --git a/WebKitTools/Scripts/modules/scm_unittest.py b/WebKitTools/Scripts/modules/scm_unittest.py
index 58494a0..784303f 100644
--- a/WebKitTools/Scripts/modules/scm_unittest.py
+++ b/WebKitTools/Scripts/modules/scm_unittest.py
@@ -95,8 +95,6 @@ class SVNTestRepository:
@classmethod
def setup(cls, test_object):
- test_object.original_path = os.path.abspath('.')
-
# Create an test SVN repository
test_object.svn_repo_path = tempfile.mkdtemp(suffix="svn_test_repo")
test_object.svn_repo_url = "file://%s" % test_object.svn_repo_path # Not sure this will work on windows
@@ -115,23 +113,30 @@ class SVNTestRepository:
run(['rm', '-rf', test_object.svn_repo_path])
run(['rm', '-rf', test_object.svn_checkout_path])
+# For testing the SCM baseclass directly.
+class SCMClassTests(unittest.TestCase):
+ def setUp(self):
+ self.dev_null = open(os.devnull, "w") # Used to make our Popen calls quiet.
-class SCMTest(unittest.TestCase):
- def _create_patch(self, patch_contents):
- patch_path = os.path.join(self.svn_checkout_path, 'patch.diff')
- write_into_file_at_path(patch_path, patch_contents)
- patch = {}
- patch['reviewer'] = 'Joe Cool'
- patch['bug_id'] = '12345'
- patch['url'] = 'file://%s' % urllib.pathname2url(patch_path)
- return patch
+ def tearDown(self):
+ self.dev_null.close()
- def _setup_webkittools_scripts_symlink(self, local_scm):
- webkit_scm = detect_scm_system(self.original_path)
- webkit_scripts_directory = webkit_scm.scripts_directory()
- local_scripts_directory = local_scm.scripts_directory()
- os.mkdir(os.path.dirname(local_scripts_directory))
- os.symlink(webkit_scripts_directory, local_scripts_directory)
+ def test_run_command_with_pipe(self):
+ input_process = subprocess.Popen(['/bin/echo', 'foo\nbar'], stdout=subprocess.PIPE, stderr=self.dev_null)
+ self.assertEqual(SCM.run_command(['/usr/bin/grep', 'bar'], input=input_process.stdout), "bar")
+
+ # Test the non-pipe case too:
+ self.assertEqual(SCM.run_command(['/usr/bin/grep', 'bar'], input="foo\nbar"), "bar")
+
+ command_returns_non_zero = ['/bin/sh', '--invalid-option']
+ # Test when the input pipe process fails.
+ input_process = subprocess.Popen(command_returns_non_zero, stdout=subprocess.PIPE, stderr=self.dev_null)
+ self.assertTrue(input_process.poll() != 0)
+ self.assertRaises(ScriptError, SCM.run_command, ['/usr/bin/grep', 'bar'], input=input_process.stdout)
+
+ # Test when the run_command process fails.
+ input_process = subprocess.Popen(['/bin/echo', 'foo\nbar'], stdout=subprocess.PIPE, stderr=self.dev_null) # grep shows usage and calls exit(2) when called w/o arguments.
+ self.assertRaises(ScriptError, SCM.run_command, command_returns_non_zero, input=input_process.stdout)
def test_error_handlers(self):
git_failure_message="Merge conflict during commit: Your file or directory 'WebCore/ChangeLog' is probably out-of-date: resource out of date; try updating at /usr/local/libexec/git-core//git-svn line 469"
@@ -152,6 +157,24 @@ svn: resource out of date; try updating
self.assertRaises(ScriptError, commit_error_handler, ScriptError(output='blah blah blah'))
+# GitTest and SVNTest inherit from this so any test_ methods here will be run once for this class and then once for each subclass.
+class SCMTest(unittest.TestCase):
+ def _create_patch(self, patch_contents):
+ patch_path = os.path.join(self.svn_checkout_path, 'patch.diff')
+ write_into_file_at_path(patch_path, patch_contents)
+ patch = {}
+ patch['reviewer'] = 'Joe Cool'
+ patch['bug_id'] = '12345'
+ patch['url'] = 'file://%s' % urllib.pathname2url(patch_path)
+ return patch
+
+ def _setup_webkittools_scripts_symlink(self, local_scm):
+ webkit_scm = detect_scm_system(os.path.dirname(os.path.abspath(__file__)))
+ webkit_scripts_directory = webkit_scm.scripts_directory()
+ local_scripts_directory = local_scm.scripts_directory()
+ os.mkdir(os.path.dirname(local_scripts_directory))
+ os.symlink(webkit_scripts_directory, local_scripts_directory)
+
# Tests which both GitTest and SVNTest should run.
# FIXME: There must be a simpler way to add these w/o adding a wrapper method to both subclasses
def _shared_test_commit_with_message(self):
@@ -188,7 +211,6 @@ class SVNTest(SCMTest):
def tearDown(self):
SVNTestRepository.tear_down(self)
- os.chdir(self.original_path)
def test_create_patch_is_full_patch(self):
test_dir_path = os.path.join(self.svn_checkout_path, 'test_dir')
@@ -284,7 +306,6 @@ class GitTest(SCMTest):
def tearDown(self):
SVNTestRepository.tear_down(self)
self._tear_down_git_clone_of_svn_repository()
- os.chdir(self.original_path)
def test_detection(self):
scm = detect_scm_system(self.git_checkout_path)
diff --git a/WebKitTools/Scripts/pdevenv b/WebKitTools/Scripts/pdevenv
index 818e4ee..cab8b16 100755
--- a/WebKitTools/Scripts/pdevenv
+++ b/WebKitTools/Scripts/pdevenv
@@ -6,6 +6,9 @@ use warnings;
use File::Temp qw/tempfile/;
use FindBin;
+use lib $FindBin::Bin;
+use webkitdirs;
+
my ($fh, $path) = tempfile(UNLINK => 0, SUFFIX => '.cmd') or die;
chomp(my $vcBin = `cygpath -w "$FindBin::Bin/../vcbin"`);
@@ -28,8 +31,15 @@ if ($ENV{'VS80COMNTOOLS'}) {
print $fh "\@echo off\n\n";
print $fh "call \"\%" . $vsToolsVar . "\%\\vsvars32.bat\"\n\n";
print $fh "set PATH=$vcBin;$scriptsPath;\%PATH\%\n\n";
-print $fh "IF EXIST \"\%VSINSTALLDIR\%\\Common7\\IDE\\devenv.com\" (devenv.com /useenv " . join(" ", @ARGV) . ") ELSE ";
-print $fh "VCExpress.exe /useenv " . join(" ", @ARGV) . "\n";
+
+my $useenv = "/useenv ";
+if (isChromium()) {
+ $useenv = "";
+}
+
+print $fh "IF EXIST \"\%VSINSTALLDIR\%\\Common7\\IDE\\devenv.com\" (devenv.com " . $useenv . join(" ", @ARGV) . ") ELSE ";
+print $fh "VCExpress.exe " . $useenv . join(" ", @ARGV) . "\n";
+
close $fh;
diff --git a/WebKitTools/Scripts/prepare-ChangeLog b/WebKitTools/Scripts/prepare-ChangeLog
index ed31005..dd864df 100755
--- a/WebKitTools/Scripts/prepare-ChangeLog
+++ b/WebKitTools/Scripts/prepare-ChangeLog
@@ -85,7 +85,6 @@ sub isConflictStatus($);
sub statusDescription($$$$);
sub propertyChangeDescription($);
sub extractLineRange($);
-sub canonicalizePath($);
sub testListForChangeLog(@);
sub get_function_line_ranges($$);
sub get_function_line_ranges_for_c($$);
@@ -95,7 +94,6 @@ sub method_decl_to_selector($);
sub processPaths(\@);
sub reviewerAndDescriptionForGitCommit($);
sub normalizeLineEndings($$);
-sub normalizePath($);
sub decodeEntities($);
# Project time zone for Cupertino, CA, US
@@ -429,24 +427,6 @@ if ($openChangeLogs && @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($)
{
@@ -1717,13 +1697,6 @@ sub normalizeLineEndings($$)
return $string;
}
-sub normalizePath($)
-{
- my ($path) = @_;
- $path =~ s/\\/\//g;
- return $path;
-}
-
sub decodeEntities($)
{
my ($text) = @_;
diff --git a/WebKitTools/Scripts/resolve-ChangeLogs b/WebKitTools/Scripts/resolve-ChangeLogs
index db497f9..1a2d2af 100755
--- a/WebKitTools/Scripts/resolve-ChangeLogs
+++ b/WebKitTools/Scripts/resolve-ChangeLogs
@@ -44,7 +44,6 @@ sub canonicalRelativePath($);
sub conflictFiles($);
sub findChangeLog($);
sub findUnmergedChangeLogs();
-sub fixChangeLogPatch($);
sub fixMergedChangeLogs($;@);
sub fixOneMergedChangeLog($);
sub hasGitUnmergedFiles();
@@ -56,7 +55,6 @@ sub resolveChangeLog($);
sub resolveConflict($);
sub showStatus($;$);
sub usageAndExit();
-sub normalizePath($);
my $isGit = isGit();
my $isSVN = isSVN();
@@ -281,57 +279,6 @@ sub findUnmergedChangeLogs()
return @results;
}
-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 fixMergedChangeLogs($;@)
{
my $revisionRange = shift;
@@ -408,7 +355,7 @@ sub fixOneMergedChangeLog($)
close FILE;
# Apply the new patch
- open(PATCH, "| patch -p1 $file > /dev/null") or die $!;
+ open(PATCH, "| patch -p1 $file > " . File::Spec->devnull()) or die $!;
print PATCH $newPatch;
close(PATCH) or die $!;
@@ -460,7 +407,7 @@ sub mergeChanges($$$)
unlink("${fileNewer}.orig");
unlink("${fileNewer}.rej");
- open(PATCH, "| patch --fuzz=3 --binary $fileNewer > /dev/null") or die $!;
+ open(PATCH, "| patch --fuzz=3 --binary $fileNewer > " . File::Spec->devnull()) or die $!;
print PATCH fixChangeLogPatch($patch);
close(PATCH);
@@ -571,9 +518,3 @@ sub showStatus($;$)
}
}
-sub normalizePath($)
-{
- my ($path) = @_;
- $path =~ s/\\/\//g;
- return $path;
-}
diff --git a/WebKitTools/Scripts/run-iexploder-tests b/WebKitTools/Scripts/run-iexploder-tests
index f5e8a6c..ed5ecd6 100755
--- a/WebKitTools/Scripts/run-iexploder-tests
+++ b/WebKitTools/Scripts/run-iexploder-tests
@@ -32,6 +32,7 @@ use strict;
use warnings;
use Cwd;
+use File::Spec;
use FindBin;
use Getopt::Long;
use IPC::Open2;
@@ -149,7 +150,7 @@ sub openHTTPDIfNeeded()
"-c", "User \"#$<\"");
my $retryCount = 20;
- while (system("/usr/bin/curl -q --silent --stderr - --output /dev/null $listen") && $retryCount) {
+ while (system("/usr/bin/curl -q --silent --stderr - --output " . File::Spec->devnull() . " $listen") && $retryCount) {
sleep 1;
--$retryCount;
}
diff --git a/WebKitTools/Scripts/run-javascriptcore-tests b/WebKitTools/Scripts/run-javascriptcore-tests
index 865ae1d..fb4c388 100755
--- a/WebKitTools/Scripts/run-javascriptcore-tests
+++ b/WebKitTools/Scripts/run-javascriptcore-tests
@@ -100,21 +100,10 @@ if (!defined($root) && !$skipBuild) {
}
-my $productDir = productDir();
-
-$productDir .= "/JavaScriptCore" if isQt();
-$productDir .= "/Programs" if isGtk();
+my $productDir = jscProductDir();
$ENV{DYLD_FRAMEWORK_PATH} = $productDir;
setPathForRunningWebKitApp(\%ENV) if isCygwin();
-sub jscPath($)
-{
- my ($productDir) = @_;
- my $jscName = "jsc";
- $jscName .= "_debug" if (isCygwin() && ($configuration eq "Debug"));
- return "$productDir/$jscName";
-}
-
sub testapiPath($)
{
my ($productDir) = @_;
diff --git a/WebKitTools/Scripts/run-jsc b/WebKitTools/Scripts/run-jsc
index 20dc5e8..e5341c1 100755
--- a/WebKitTools/Scripts/run-jsc
+++ b/WebKitTools/Scripts/run-jsc
@@ -30,6 +30,7 @@
use strict;
use warnings;
+use File::Spec;
use FindBin;
use lib $FindBin::Bin;
use Getopt::Long;
@@ -43,10 +44,10 @@ GetOptions("count|c=i" => \$count,
"verbose|v" => \$verbose);
die "$usage\n" if (@ARGV < 1);
-my $jsc = productDir() . "/jsc @ARGV";
-$jsc .= " 2> /dev/null" unless $verbose;
+my $jsc = jscProductDir() . "/jsc @ARGV";
+$jsc .= " 2> " . File::Spec->devnull() unless $verbose;
-my $dyld = productDir();
+my $dyld = jscProductDir();
$ENV{"DYLD_FRAMEWORK_PATH"} = $dyld;
print STDERR "Running $count time(s): DYLD_FRAMEWORK_PATH=$dyld $jsc\n";
diff --git a/WebKitTools/Scripts/run-launcher b/WebKitTools/Scripts/run-launcher
index ee462ba..e12a64a 100755
--- a/WebKitTools/Scripts/run-launcher
+++ b/WebKitTools/Scripts/run-launcher
@@ -49,6 +49,8 @@ if (isQt()) {
my $libDir = catdir(productDir(), 'lib');
$launcherPath = catdir($launcherPath, "bin", "QtLauncher");
+ $ENV{QTWEBKIT_PLUGIN_PATH} = catdir($libDir, 'plugins');
+
print "Starting webkit launcher, running against the built WebKit in $libDir...\n";
if (isDarwin()) {
$ENV{DYLD_LIBRARY_PATH} = $ENV{DYLD_LIBRARY_PATH} ? "$libDir:$ENV{DYLD_LIBRARY_PATH}" : $libDir;
diff --git a/WebKitTools/Scripts/run-mangleme-tests b/WebKitTools/Scripts/run-mangleme-tests
index 93b7894..43ac74b 100755
--- a/WebKitTools/Scripts/run-mangleme-tests
+++ b/WebKitTools/Scripts/run-mangleme-tests
@@ -32,6 +32,7 @@ use strict;
use warnings;
use Cwd;
+use File::Spec;
use FindBin;
use Getopt::Long;
use IPC::Open2;
@@ -152,7 +153,7 @@ sub openHTTPDIfNeeded()
"-c", "User \"#$<\"");
my $retryCount = 20;
- while (system("/usr/bin/curl -q --silent --stderr - --output /dev/null $listen") && $retryCount) {
+ while (system("/usr/bin/curl -q --silent --stderr - --output " . File::Spec->devnull() . " $listen") && $retryCount) {
sleep 1;
--$retryCount;
}
diff --git a/WebKitTools/Scripts/run-sunspider b/WebKitTools/Scripts/run-sunspider
index 367fd06..e63f5d1 100755
--- a/WebKitTools/Scripts/run-sunspider
+++ b/WebKitTools/Scripts/run-sunspider
@@ -103,23 +103,12 @@ sub setupEnvironmentForExecution($)
# FIXME: Other platforms may wish to augment this method to use LD_LIBRARY_PATH, etc.
}
-sub jscPath($)
-{
- my ($productDir) = @_;
- my $jscName = "jsc";
- $jscName .= "_debug" if (isCygwin() && ($configuration eq "Debug"));
- return "$productDir/$jscName";
-}
-
buildJSC();
chdirWebKit();
chdir("SunSpider");
-my $productDir = productDir();
-# FIXME: This hack should be pushed down into productDir()
-$productDir .= "/JavaScriptCore" if isQt();
-$productDir .= "/Programs" if isGtk();
+my $productDir = jscProductDir();
setupEnvironmentForExecution($productDir);
my @args = ("--shell", jscPath($productDir), "--runs", $testRuns);
diff --git a/WebKitTools/Scripts/run-webkit-tests b/WebKitTools/Scripts/run-webkit-tests
index a08a53c..6056035 100755
--- a/WebKitTools/Scripts/run-webkit-tests
+++ b/WebKitTools/Scripts/run-webkit-tests
@@ -321,7 +321,7 @@ if (!defined($root)) {
local *DEVNULL;
my ($childIn, $childOut, $childErr);
if ($quiet) {
- open(DEVNULL, ">", File::Spec->devnull) or die "Failed to open /dev/null";
+ open(DEVNULL, ">", File::Spec->devnull()) or die "Failed to open /dev/null";
$childOut = ">&DEVNULL";
$childErr = ">&DEVNULL";
} else {
@@ -1351,7 +1351,7 @@ sub openHTTPDIfNeeded()
open2(\*HTTPDIN, \*HTTPDOUT, $httpdPath, @args);
my $retryCount = 20;
- while (system("/usr/bin/curl -q --silent --stderr - --output /dev/null $listen") && $retryCount) {
+ while (system("/usr/bin/curl -q --silent --stderr - --output " . File::Spec->devnull() . " $listen") && $retryCount) {
sleep 1;
--$retryCount;
}
diff --git a/WebKitTools/Scripts/sunspider-compare-results b/WebKitTools/Scripts/sunspider-compare-results
index ce87a23..a207d7a 100755
--- a/WebKitTools/Scripts/sunspider-compare-results
+++ b/WebKitTools/Scripts/sunspider-compare-results
@@ -107,9 +107,7 @@ sub pathToJSC()
buildJSC();
- my $productDir = productDir();
- # FIXME: This hack should be pushed down into productDir()
- $productDir .= "/JavaScriptCore" if (isQt() or isGtk());
+ my $productDir = jscProductDir();
setupEnvironmentForExecution($productDir);
return pathToBuiltJSC($productDir);
diff --git a/WebKitTools/Scripts/svn-apply b/WebKitTools/Scripts/svn-apply
index 19c8c56..7d14e3a 100755
--- a/WebKitTools/Scripts/svn-apply
+++ b/WebKitTools/Scripts/svn-apply
@@ -74,15 +74,12 @@ use VCSUtils;
sub addDirectoriesIfNeeded($);
sub applyPatch($$;$);
sub checksum($);
-sub fixChangeLogPatch($);
-sub gitdiff2svndiff($);
sub handleBinaryChange($$);
sub isDirectoryEmptyForRemoval($);
sub patch($);
sub removeDirectoriesIfNeeded();
sub setChangeLogDateAndReviewer($$);
sub removeEOL($);
-sub svnStatus($);
# These should be replaced by an scm class/module:
sub scmKnowsOfFile($);
@@ -178,8 +175,9 @@ if ($merge) {
die "--merge is currently only supported for SVN" unless isSVN();
# How do we handle Git patches applied to an SVN checkout here?
for my $file (sort keys %versions) {
- print "Getting version $versions{$file} of $file\n";
- system "svn", "update", "-r", $versions{$file}, $file;
+ my $version = $versions{$file};
+ print "Getting version $version of $file\n";
+ system("svn", "update", "-r", $version, $file) == 0 or die "Failed to run svn update -r $version $file.";
}
}
@@ -258,74 +256,6 @@ sub checksum($)
return $checksum;
}
-sub fixChangeLogPatch($)
-{
- my $patch = shift;
- my $contextLineCount = 3;
-
- return $patch if $patch !~ /\n@@ -1,(\d+) \+1,(\d+) @@\r?\n( .*\r?\n)+(\+.*\r?\n)+( .*\r?\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) = @_;
@@ -334,7 +264,7 @@ sub handleBinaryChange($$)
# The last line is allowed to have up to two '=' characters at the end (to signify padding).
if ($contents =~ m#((\n[A-Za-z0-9+/]{76})*\n[A-Za-z0-9+/]{2,74}?[A-Za-z0-9+/=]{2}\n)#) {
# Addition or Modification
- open FILE, ">", $fullPath or die;
+ open FILE, ">", $fullPath or die "Failed to open $fullPath.";
print FILE decode_base64($1);
close FILE;
if (!scmKnowsOfFile($fullPath)) {
@@ -373,6 +303,7 @@ sub patch($)
unless ($patch =~ m|^Index: ([^\r\n]+)|) {
my $separator = '-' x 67;
warn "Failed to find 'Index:' in:\n$separator\n$patch\n$separator\n";
+ die unless $force;
return;
}
my $fullPath = $1;
@@ -413,7 +344,7 @@ sub patch($)
unlink("$fullPath.orig") if -e "$fullPath.orig" && checksum($fullPath) eq checksum("$fullPath.orig");
scmAdd($fullPath);
# What is this for?
- system "svn", "stat", "$fullPath.orig" if isSVN() && -e "$fullPath.orig";
+ system("svn", "stat", "$fullPath.orig") if isSVN() && -e "$fullPath.orig";
}
}
}
@@ -455,38 +386,6 @@ sub removeEOL($)
return $line;
}
-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>) {
- # Input may use a different EOL sequence than $/, so avoid chomp.
- $_ = removeEOL($_);
- my $normalizedStatPath = File::Spec->catdir(File::Spec->splitdir(substr($_, 7)));
- if ($normalizedFullPath eq $normalizedStatPath) {
- $svnStatus = "$_\n";
- 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 = removeEOL(<SVN>) . "\n";
- }
- close SVN;
- return $svnStatus;
-}
-
# This could be made into a more general "status" call, except svn and git
# have different ideas about "moving" files which might get confusing.
sub scmWillDeleteFile($)
@@ -524,10 +423,10 @@ sub scmCopy($$)
{
my ($source, $destination) = @_;
if (isSVN()) {
- system "svn", "copy", $source, $destination;
+ system("svn", "copy", $source, $destination) == 0 or die "Failed to svn copy $source $destination.";
} elsif (isGit()) {
- system "cp", $source, $destination;
- system "git", "add", $destination;
+ system("cp", $source, $destination) == 0 or die "Failed to copy $source $destination.";
+ system("git", "add", $destination) == 0 or die "Failed to git add $destination.";
}
}
@@ -535,9 +434,9 @@ sub scmAdd($)
{
my ($path) = @_;
if (isSVN()) {
- system "svn", "add", $path;
+ system("svn", "add", $path) == 0 or die "Failed to svn add $path.";
} elsif (isGit()) {
- system "git", "add", $path;
+ system("git", "add", $path) == 0 or die "Failed to git add $path.";
}
}
@@ -555,6 +454,6 @@ sub scmRemove($)
close SVN;
print $svnOutput if $svnOutput;
} elsif (isGit()) {
- system "git", "rm", "--force", $path;
+ system("git", "rm", "--force", $path) == 0 or die "Failed to git rm --force $path.";
}
}
diff --git a/WebKitTools/Scripts/svn-create-patch b/WebKitTools/Scripts/svn-create-patch
index 3f40783..768a8ed 100755
--- a/WebKitTools/Scripts/svn-create-patch
+++ b/WebKitTools/Scripts/svn-create-patch
@@ -56,12 +56,10 @@ use Time::gmtime;
use VCSUtils;
sub binarycmp($$);
-sub canonicalizePath($);
sub findBaseUrl($);
sub findMimeType($;$);
sub findModificationType($);
sub findSourceFileAndRevision($);
-sub fixChangeLogPatch($);
sub generateDiff($$);
sub generateFileList($\%);
sub isBinaryMimeType($);
@@ -132,25 +130,6 @@ sub binarycmp($$)
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) = @_;
@@ -211,57 +190,6 @@ sub findSourceFileAndRevision($)
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, $prefix) = @_;
diff --git a/WebKitTools/Scripts/svn-unapply b/WebKitTools/Scripts/svn-unapply
index a4cec9a..94bb1ce 100755
--- a/WebKitTools/Scripts/svn-unapply
+++ b/WebKitTools/Scripts/svn-unapply
@@ -71,12 +71,9 @@ use lib $FindBin::Bin;
use VCSUtils;
sub checksum($);
-sub fixChangeLogPatch($);
-sub gitdiff2svndiff($);
sub patch($);
sub revertDirectories();
sub removeEOL($);
-sub svnStatus($);
sub unapplyPatch($$;$);
sub unsetChangeLogDate($$);
@@ -158,74 +155,6 @@ sub checksum($)
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) = @_;
@@ -338,38 +267,6 @@ sub removeEOL($)
return $line;
}
-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>) {
- # Input may use a different EOL sequence than $/, so avoid chomp.
- $_ = removeEOL($_);
- my $normalizedStatPath = File::Spec->catdir(File::Spec->splitdir(substr($_, 7)));
- if ($normalizedFullPath eq $normalizedStatPath) {
- $svnStatus = "$_\n";
- 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 = removeEOL(<SVN>) . "\n";
- }
- close SVN;
- return $svnStatus;
-}
-
sub unapplyPatch($$;$)
{
my ($patch, $fullPath, $options) = @_;
diff --git a/WebKitTools/Scripts/update-webkit b/WebKitTools/Scripts/update-webkit
index e562cc0..b503004 100755
--- a/WebKitTools/Scripts/update-webkit
+++ b/WebKitTools/Scripts/update-webkit
@@ -39,7 +39,6 @@ use VCSUtils;
use webkitdirs;
sub runSvnUpdate();
-sub normalizePath($);
# Handle options
my $quiet = '';
@@ -105,10 +104,3 @@ sub runSvnUpdate()
or die "Could not open resolve-ChangeLogs script: $!.\n";
}
}
-
-sub normalizePath($)
-{
- my ($path) = @_;
- $path =~ s/\\/\//g;
- return $path;
-}
diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm
index d5177dd..16f9c26 100644
--- a/WebKitTools/Scripts/webkitdirs.pm
+++ b/WebKitTools/Scripts/webkitdirs.pm
@@ -117,7 +117,7 @@ sub determineBaseProductDir
unlink($personalPlistFile) || die "Could not delete $personalPlistFile: $!";
}
- open PRODUCT, "defaults read com.apple.Xcode PBXApplicationwideBuildSettings 2> /dev/null |" or die;
+ open PRODUCT, "defaults read com.apple.Xcode PBXApplicationwideBuildSettings 2> " . File::Spec->devnull() . " |" or die;
$baseProductDir = join '', <PRODUCT>;
close PRODUCT;
@@ -125,7 +125,7 @@ sub determineBaseProductDir
undef $baseProductDir unless $baseProductDir =~ /^\//;
if (!defined($baseProductDir)) {
- open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> /dev/null |" or die;
+ open PRODUCT, "defaults read com.apple.Xcode PBXProductDirectory 2> " . File::Spec->devnull() . " |" or die;
$baseProductDir = <PRODUCT>;
close PRODUCT;
if ($baseProductDir) {
@@ -215,6 +215,14 @@ sub determineArchitecture
}
}
+sub jscPath($)
+{
+ my ($productDir) = @_;
+ my $jscName = "jsc";
+ $jscName .= "_debug" if (isCygwin() && ($configuration eq "Debug"));
+ return "$productDir/$jscName";
+}
+
sub argumentsForConfiguration()
{
determineConfiguration();
@@ -300,6 +308,16 @@ sub productDir
return $configurationProductDir;
}
+sub jscProductDir
+{
+ my $productDir = productDir();
+ $productDir .= "/JavaScriptCore" if isQt();
+ $productDir .= "/$configuration" if (isQt() && isWindows());
+ $productDir .= "/Programs" if isGtk();
+
+ return $productDir;
+}
+
sub configuration()
{
determineConfiguration();
@@ -792,7 +810,7 @@ sub determineIsQt()
}
# The presence of QTDIR only means Qt if --gtk is not on the command-line
- if (isGtk()) {
+ if (isGtk() || isWx()) {
$isQt = 0;
return;
}
@@ -1100,7 +1118,12 @@ sub buildVisualStudioProject
$action = "/clean";
}
- my @command = ($vcBuildPath, $winProjectPath, $action, $config);
+ my $useenv = "/useenv";
+ if (isChromium()) {
+ $useenv = "";
+ }
+
+ my @command = ($vcBuildPath, $useenv, $winProjectPath, $action, $config);
print join(" ", @command), "\n";
return system @command;
diff --git a/WebKitTools/WinLauncher/WinLauncher.vcproj b/WebKitTools/WinLauncher/WinLauncher.vcproj
index 5fddb48..9b7c42c 100644
--- a/WebKitTools/WinLauncher/WinLauncher.vcproj
+++ b/WebKitTools/WinLauncher/WinLauncher.vcproj
@@ -39,17 +39,10 @@
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\include\WebKit&quot;;&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore&quot;;&quot;$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\JavaScriptCore&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ProjectDir)&quot;;&quot;$(IntDir)\Include&quot;;&quot;$(WebKitOutputDir)\obj\WebKit\DerivedSources&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
- MinimalRebuild="true"
- ExceptionHandling="0"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- RuntimeTypeInfo="false"
UsePrecompiledHeader="2"
WarningLevel="1"
- Detect64BitPortabilityProblems="false"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -125,12 +118,8 @@
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\include\WebKit&quot;;&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore&quot;;&quot;$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitOutputDir)\Include\icu&quot;;&quot;$(WebKitLibrariesDir)\Include\icu&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitOutputDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitOutputDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ProjectDir)&quot;;&quot;$(IntDir)\include&quot;;&quot;$(WebKitOutputDir)\obj\WebKit\DerivedSources&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINNT=0x501"
- ExceptionHandling="0"
- RuntimeLibrary="2"
- RuntimeTypeInfo="false"
UsePrecompiledHeader="2"
WarningLevel="1"
- Detect64BitPortabilityProblems="false"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -206,17 +195,10 @@
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\include\WebKit&quot;;&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore&quot;;&quot;$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\JavaScriptCore&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ProjectDir)&quot;;&quot;$(IntDir)\Include&quot;;&quot;$(WebKitOutputDir)\obj\WebKit\DerivedSources&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
- MinimalRebuild="true"
- ExceptionHandling="0"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- RuntimeTypeInfo="false"
UsePrecompiledHeader="2"
WarningLevel="1"
- Detect64BitPortabilityProblems="false"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -289,17 +271,86 @@
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\include\WebKit&quot;;&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore&quot;;&quot;$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\JavaScriptCore&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ProjectDir)&quot;;&quot;$(IntDir)\Include&quot;;&quot;$(WebKitOutputDir)\obj\WebKit\DerivedSources&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
- MinimalRebuild="true"
- ExceptionHandling="0"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- RuntimeTypeInfo="false"
UsePrecompiledHeader="2"
WarningLevel="1"
- Detect64BitPortabilityProblems="false"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkLibraryDependencies="false"
+ AdditionalDependencies="comctl32.lib shlwapi.lib user32.lib ole32.lib oleaut32.lib WebKitGUID$(WebKitConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="&quot;$(WebKitOutputDir)\lib&quot;;&quot;$(ProjectDir)\..\..\..\&quot;"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ TypeLibraryFile=""
+ ComponentFileName=""
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_All|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(WebKitLibrariesDir)\tools\vsprops\common.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_internal.vsprops;$(WebKitLibrariesDir)\tools\vsprops\debug_all.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash&#x0D;&#x0A;if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%&#x0D;&#x0A;cmd /c&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; grep XX$(ProjectName)XX &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;if errorlevel 1 exit 1&#x0D;&#x0A;echo XX$(ProjectName)XX &gt; &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(WebKitOutputDir)\include\WebKit&quot;;&quot;$(WebKitOutputDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;;&quot;$(WebKitOutputDir)\Include\WebCore&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore&quot;;&quot;$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\WebCore\ForwardingHeaders&quot;;&quot;$(WebKitOutputDir)\Include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\JavaScriptCore&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ProjectDir)&quot;;&quot;$(IntDir)\Include&quot;;&quot;$(WebKitOutputDir)\obj\WebKit\DerivedSources&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
+ UsePrecompiledHeader="2"
+ WarningLevel="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -392,6 +443,14 @@
UsePrecompiledHeader="1"
/>
</FileConfiguration>
+ <FileConfiguration
+ Name="Debug_All|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
</File>
<File
RelativePath=".\WinLauncher.cpp"
diff --git a/WebKitTools/pywebsocket/COPYING b/WebKitTools/pywebsocket/COPYING
new file mode 100644
index 0000000..ab9d52d
--- /dev/null
+++ b/WebKitTools/pywebsocket/COPYING
@@ -0,0 +1,28 @@
+Copyright 2009, Google 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:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+OWNER 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.
diff --git a/WebKitTools/pywebsocket/MANIFEST.in b/WebKitTools/pywebsocket/MANIFEST.in
new file mode 100644
index 0000000..1925688
--- /dev/null
+++ b/WebKitTools/pywebsocket/MANIFEST.in
@@ -0,0 +1,6 @@
+include COPYING
+include MANIFEST.in
+include README
+recursive-include example *.py
+recursive-include mod_pywebsocket *.py
+recursive-include test *.py
diff --git a/WebKitTools/pywebsocket/README b/WebKitTools/pywebsocket/README
new file mode 100644
index 0000000..1f9f05f
--- /dev/null
+++ b/WebKitTools/pywebsocket/README
@@ -0,0 +1,6 @@
+Install this package by:
+$ python setup.py build
+$ sudo python setup.py install
+
+Then read document by:
+$ pydoc mod_pywebsocket
diff --git a/WebKitTools/pywebsocket/example/echo_client.py b/WebKitTools/pywebsocket/example/echo_client.py
new file mode 100644
index 0000000..61b129c
--- /dev/null
+++ b/WebKitTools/pywebsocket/example/echo_client.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Web Socket Echo client.
+
+This is an example Web Socket client that talks with echo_wsh.py.
+This may be useful for checking mod_pywebsocket installation.
+
+Note:
+This code is far from robust, e.g., we cut corners in handshake.
+"""
+
+
+import codecs
+from optparse import OptionParser
+import socket
+import sys
+
+
+_DEFAULT_PORT = 80
+_DEFAULT_SECURE_PORT = 443
+_UNDEFINED_PORT = -1
+
+_UPGRADE_HEADER = 'Upgrade: WebSocket\r\n'
+_CONNECTION_HEADER = 'Connection: Upgrade\r\n'
+_EXPECTED_RESPONSE = (
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
+ _UPGRADE_HEADER +
+ _CONNECTION_HEADER)
+
+
+def _method_line(resource):
+ return 'GET %s HTTP/1.1\r\n' % resource
+
+
+def _origin_header(origin):
+ return 'Origin: %s\r\n' % origin
+
+
+class _TLSSocket(object):
+ """Wrapper for a TLS connection."""
+
+ def __init__(self, raw_socket):
+ self._ssl = socket.ssl(raw_socket)
+
+ def send(self, bytes):
+ return self._ssl.write(bytes)
+
+ def recv(self, size=-1):
+ return self._ssl.read(size)
+
+ def close(self):
+ # Nothing to do.
+ pass
+
+
+class EchoClient(object):
+ """Web Socket echo client."""
+
+ def __init__(self, options):
+ self._options = options
+ self._socket = None
+
+ def run(self):
+ """Run the client.
+
+ Shake hands and then repeat sending message and receiving its echo.
+ """
+ self._socket = socket.socket()
+ try:
+ self._socket.connect((self._options.server_host,
+ self._options.server_port))
+ if self._options.use_tls:
+ self._socket = _TLSSocket(self._socket)
+ self._handshake()
+ for line in self._options.message.split(','):
+ frame = '\x00' + line.encode('utf-8') + '\xff'
+ self._socket.send(frame)
+ if self._options.verbose:
+ print 'Send: %s' % line
+ received = self._socket.recv(len(frame))
+ if received != frame:
+ raise Exception('Incorrect echo: %r' % received)
+ if self._options.verbose:
+ print 'Recv: %s' % received[1:-1].decode('utf-8')
+ finally:
+ self._socket.close()
+
+ def _handshake(self):
+ self._socket.send(_method_line(self._options.resource))
+ self._socket.send(_UPGRADE_HEADER)
+ self._socket.send(_CONNECTION_HEADER)
+ self._socket.send(self._format_host_header())
+ self._socket.send(_origin_header(self._options.origin))
+ self._socket.send('\r\n')
+
+ for expected_char in _EXPECTED_RESPONSE:
+ received = self._socket.recv(1)[0]
+ if expected_char != received:
+ raise Exception('Handshake failure')
+ # We cut corners and skip other headers.
+ self._skip_headers()
+
+ def _skip_headers(self):
+ terminator = '\r\n\r\n'
+ pos = 0
+ while pos < len(terminator):
+ received = self._socket.recv(1)[0]
+ if received == terminator[pos]:
+ pos += 1
+ elif received == terminator[0]:
+ pos = 1
+ else:
+ pos = 0
+
+ def _format_host_header(self):
+ host = 'Host: ' + self._options.server_host
+ if ((not self._options.use_tls and
+ self._options.server_port != _DEFAULT_PORT) or
+ (self._options.use_tls and
+ self._options.server_port != _DEFAULT_SECURE_PORT)):
+ host += ':' + str(self._options.server_port)
+ host += '\r\n'
+ return host
+
+
+def main():
+ sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
+
+ parser = OptionParser()
+ parser.add_option('-s', '--server_host', dest='server_host', type='string',
+ default='localhost', help='server host')
+ parser.add_option('-p', '--server_port', dest='server_port', type='int',
+ default=_UNDEFINED_PORT, help='server port')
+ parser.add_option('-o', '--origin', dest='origin', type='string',
+ default='http://localhost/', help='origin')
+ parser.add_option('-r', '--resource', dest='resource', type='string',
+ default='/echo', help='resource path')
+ parser.add_option('-m', '--message', dest='message', type='string',
+ help='comma-separated messages to send')
+ parser.add_option('-q', '--quiet', dest='verbose', action='store_false',
+ default=True, help='suppress messages')
+ parser.add_option('-t', '--tls', dest='use_tls', action='store_true',
+ default=False, help='use TLS (wss://)')
+ (options, unused_args) = parser.parse_args()
+
+ # Default port number depends on whether TLS is used.
+ if options.server_port == _UNDEFINED_PORT:
+ if options.use_tls:
+ options.server_port = _DEFAULT_SECURE_PORT
+ else:
+ options.server_port = _DEFAULT_PORT
+
+ # optparse doesn't seem to handle non-ascii default values.
+ # Set default message here.
+ if not options.message:
+ options.message = u'Hello,\u65e5\u672c' # "Japan" in Japanese
+
+ EchoClient(options).run()
+
+
+if __name__ == '__main__':
+ main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/example/echo_wsh.py b/WebKitTools/pywebsocket/example/echo_wsh.py
new file mode 100644
index 0000000..f680fa5
--- /dev/null
+++ b/WebKitTools/pywebsocket/example/echo_wsh.py
@@ -0,0 +1,44 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+from mod_pywebsocket import msgutil
+
+
+def web_socket_do_extra_handshake(request):
+ pass # Always accept.
+
+
+def web_socket_transfer_data(request):
+ while True:
+ line = msgutil.receive_message(request)
+ msgutil.send_message(request, line)
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/__init__.py b/WebKitTools/pywebsocket/mod_pywebsocket/__init__.py
new file mode 100644
index 0000000..beacc9e
--- /dev/null
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/__init__.py
@@ -0,0 +1,102 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Web Socket extension for Apache HTTP Server.
+
+mod_pywebsocket is a Web Socket extension for Apache HTTP Server
+intended for testing or experimental purposes. mod_python is required.
+
+Installation:
+
+0. Prepare an Apache HTTP Server for which mod_python is enabled.
+
+1. Specify the following Apache HTTP Server directives to suit your
+ configuration.
+
+ If mod_pywebsocket is not in the Python path, specify the following.
+ <websock_lib> is the directory where mod_pywebsocket is installed.
+
+ PythonPath "sys.path+['<websock_lib>']"
+
+ Always specify the following. <websock_handlers> is the directory where
+ user-written Web Socket handlers are placed.
+
+ PythonOption mod_pywebsocket.handler_root <websock_handlers>
+ PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
+
+ To limit the search for Web Socket handlers to a directory <scan_dir>
+ under <websock_handlers>, configure as follows:
+
+ PythonOption mod_pywebsocket.handler_scan <scan_dir>
+
+ <scan_dir> is useful in saving scan time when <websock_handlers>
+ contains many non-Web Socket handler files.
+
+ Example snippet of httpd.conf:
+ (mod_pywebsocket is in /websock_lib, Web Socket handlers are in
+ /websock_handlers, port is 80 for ws, 443 for wss.)
+
+ <IfModule python_module>
+ PythonPath "sys.path+['/websock_lib']"
+ PythonOption mod_pywebsocket.handler_root /websock_handlers
+ PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
+ </IfModule>
+
+Writing Web Socket handlers:
+
+When a Web Socket request comes in, the resource name
+specified in the handshake is considered as if it is a file path under
+<websock_handlers> and the handler defined in
+<websock_handlers>/<resource_name>_wsh.py is invoked.
+
+For example, if the resource name is /example/chat, the handler defined in
+<websock_handlers>/example/chat_wsh.py is invoked.
+
+A Web Socket handler is composed of the following two functions:
+
+ web_socket_do_extra_handshake(request)
+ web_socket_transfer_data(request)
+
+where:
+ request: mod_python request.
+
+web_socket_do_extra_handshake is called during the handshake after the
+headers are successfully parsed and Web Socket properties (ws_location,
+ws_origin, ws_protocol, and ws_resource) are added to request. A handler
+can reject the request by raising an exception.
+
+web_socket_transfer_data is called after the handshake completed
+successfully. A handler can receive/send messages from/to the client
+using request. mod_pywebsocket.msgutil module provides utilities
+for data transfer.
+"""
+
+
+# vi:sts=4 sw=4 et tw=72
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py b/WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py
new file mode 100644
index 0000000..84422eb
--- /dev/null
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py
@@ -0,0 +1,205 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Dispatch Web Socket request.
+"""
+
+
+import os
+import re
+
+import util
+
+
+_SOURCE_PATH_PATTERN = re.compile(r'(?i)_wsh\.py$')
+_SOURCE_SUFFIX = '_wsh.py'
+_DO_EXTRA_HANDSHAKE_HANDLER_NAME = 'web_socket_do_extra_handshake'
+_TRANSFER_DATA_HANDLER_NAME = 'web_socket_transfer_data'
+
+
+class DispatchError(Exception):
+ """Exception in dispatching Web Socket request."""
+
+ pass
+
+
+def _normalize_path(path):
+ """Normalize path.
+
+ Args:
+ path: the path to normalize.
+
+ Path is converted to the absolute path.
+ The input path can use either '\\' or '/' as the separator.
+ The normalized path always uses '/' regardless of the platform.
+ """
+
+ path = path.replace('\\', os.path.sep)
+ path = os.path.abspath(path)
+ path = path.replace('\\', '/')
+ return path
+
+
+def _path_to_resource_converter(base_dir):
+ base_dir = _normalize_path(base_dir)
+ base_len = len(base_dir)
+ suffix_len = len(_SOURCE_SUFFIX)
+ def converter(path):
+ if not path.endswith(_SOURCE_SUFFIX):
+ return None
+ path = _normalize_path(path)
+ if not path.startswith(base_dir):
+ return None
+ return path[base_len:-suffix_len]
+ return converter
+
+
+def _source_file_paths(directory):
+ """Yield Web Socket Handler source file names in the given directory."""
+
+ for root, unused_dirs, files in os.walk(directory):
+ for base in files:
+ path = os.path.join(root, base)
+ if _SOURCE_PATH_PATTERN.search(path):
+ yield path
+
+
+def _source(source_str):
+ """Source a handler definition string."""
+
+ global_dic = {}
+ try:
+ exec source_str in global_dic
+ except Exception:
+ raise DispatchError('Error in sourcing handler:' +
+ util.get_stack_trace())
+ return (_extract_handler(global_dic, _DO_EXTRA_HANDSHAKE_HANDLER_NAME),
+ _extract_handler(global_dic, _TRANSFER_DATA_HANDLER_NAME))
+
+
+def _extract_handler(dic, name):
+ if name not in dic:
+ raise DispatchError('%s is not defined.' % name)
+ handler = dic[name]
+ if not callable(handler):
+ raise DispatchError('%s is not callable.' % name)
+ return handler
+
+
+class Dispatcher(object):
+ """Dispatches Web Socket requests.
+
+ This class maintains a map from resource name to handlers.
+ """
+
+ def __init__(self, root_dir, scan_dir=None):
+ """Construct an instance.
+
+ Args:
+ root_dir: The directory where handler definition files are
+ placed.
+ scan_dir: The directory where handler definition files are
+ searched. scan_dir must be a directory under root_dir,
+ including root_dir itself. If scan_dir is None, root_dir
+ is used as scan_dir. scan_dir can be useful in saving
+ scan time when root_dir contains many subdirectories.
+ """
+
+ self._handlers = {}
+ self._source_warnings = []
+ if scan_dir is None:
+ scan_dir = root_dir
+ if not os.path.abspath(scan_dir).startswith(os.path.abspath(root_dir)):
+ raise DispatchError('scan_dir:%s must be a directory under '
+ 'root_dir:%s.' % (scan_dir, root_dir))
+ self._source_files_in_dir(root_dir, scan_dir)
+
+ def source_warnings(self):
+ """Return warnings in sourcing handlers."""
+
+ return self._source_warnings
+
+ def do_extra_handshake(self, request):
+ """Do extra checking in Web Socket handshake.
+
+ Select a handler based on request.uri and call its
+ web_socket_do_extra_handshake function.
+
+ Args:
+ request: mod_python request.
+ """
+
+ do_extra_handshake_, unused_transfer_data = self._handler(request)
+ try:
+ do_extra_handshake_(request)
+ except Exception:
+ raise DispatchError('%s raised exception: %s' %
+ (_DO_EXTRA_HANDSHAKE_HANDLER_NAME, util.get_stack_trace()))
+
+ def transfer_data(self, request):
+ """Let a handler transfer_data with a Web Socket client.
+
+ Select a handler based on request.ws_resource and call its
+ web_socket_transfer_data function.
+
+ Args:
+ request: mod_python request.
+ """
+
+ unused_do_extra_handshake, transfer_data_ = self._handler(request)
+ try:
+ transfer_data_(request)
+ except Exception:
+ raise DispatchError('%s raised exception: %s' %
+ (_TRANSFER_DATA_HANDLER_NAME, util.get_stack_trace()))
+
+ def _handler(self, request):
+ try:
+ return self._handlers[request.ws_resource]
+ except KeyError:
+ raise DispatchError('No handler for: %r' % request.ws_resource)
+
+ def _source_files_in_dir(self, root_dir, scan_dir):
+ """Source all the handler source files in the scan_dir directory.
+
+ The resource path is determined relative to root_dir.
+ """
+
+ to_resource = _path_to_resource_converter(root_dir)
+ for path in _source_file_paths(scan_dir):
+ try:
+ handlers = _source(open(path).read())
+ except DispatchError, e:
+ self._source_warnings.append('%s: %s' % (path, e))
+ continue
+ self._handlers[to_resource(path)] = handlers
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/handshake.py b/WebKitTools/pywebsocket/mod_pywebsocket/handshake.py
new file mode 100644
index 0000000..a67aadd
--- /dev/null
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/handshake.py
@@ -0,0 +1,178 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Web Socket handshaking.
+
+Note: request.connection.write/read are used in this module, even though
+mod_python document says that they should be used only in connection handlers.
+Unfortunately, we have no other options. For example, request.write/read are
+not suitable because they don't allow direct raw bytes writing/reading.
+"""
+
+
+import re
+
+
+_DEFAULT_WEB_SOCKET_PORT = 80
+_DEFAULT_WEB_SOCKET_SECURE_PORT = 443
+_WEB_SOCKET_SCHEME = 'ws'
+_WEB_SOCKET_SECURE_SCHEME = 'wss'
+
+_METHOD_LINE = re.compile(r'^GET ([^ ]+) HTTP/1.1\r\n$')
+
+_MANDATORY_HEADERS = [
+ # key, expected value or None
+ ['Upgrade', 'WebSocket'],
+ ['Connection', 'Upgrade'],
+ ['Host', None],
+ ['Origin', None],
+]
+
+
+def _default_port(is_secure):
+ if is_secure:
+ return _DEFAULT_WEB_SOCKET_SECURE_PORT
+ else:
+ return _DEFAULT_WEB_SOCKET_PORT
+
+
+class HandshakeError(Exception):
+ """Exception in Web Socket Handshake."""
+
+ pass
+
+
+def _validate_protocol(protocol):
+ """Validate WebSocket-Protocol string."""
+
+ if not protocol:
+ raise HandshakeError('Invalid WebSocket-Protocol: empty')
+ for c in protocol:
+ if not 0x21 <= ord(c) <= 0x7e:
+ raise HandshakeError('Illegal character in protocol: %r' % c)
+
+
+class Handshaker(object):
+ """This class performs Web Socket handshake."""
+
+ def __init__(self, request, dispatcher):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ dispatcher: Dispatcher (dispatch.Dispatcher).
+
+ Handshaker will add attributes such as ws_resource in performing
+ handshake.
+ """
+
+ self._request = request
+ self._dispatcher = dispatcher
+
+ def do_handshake(self):
+ """Perform Web Socket Handshake."""
+
+ self._check_header_lines()
+ self._set_resource()
+ self._set_origin()
+ self._set_location()
+ self._set_protocol()
+ self._dispatcher.do_extra_handshake(self._request)
+ self._send_handshake()
+
+ def _set_resource(self):
+ self._request.ws_resource = self._request.uri
+
+ def _set_origin(self):
+ self._request.ws_origin = self._request.headers_in['Origin']
+
+ def _set_location(self):
+ location_parts = []
+ if self._request.is_https():
+ location_parts.append(_WEB_SOCKET_SECURE_SCHEME)
+ else:
+ location_parts.append(_WEB_SOCKET_SCHEME)
+ location_parts.append('://')
+ host, port = self._parse_host_header()
+ connection_port = self._request.connection.local_addr[1]
+ if port != connection_port:
+ raise HandshakeError('Header/connection port mismatch: %d/%d' %
+ (port, connection_port))
+ location_parts.append(host)
+ if (port != _default_port(self._request.is_https())):
+ location_parts.append(':')
+ location_parts.append(str(port))
+ location_parts.append(self._request.uri)
+ self._request.ws_location = ''.join(location_parts)
+
+ def _parse_host_header(self):
+ fields = self._request.headers_in['Host'].split(':', 1)
+ if len(fields) == 1:
+ return fields[0], _default_port(self._request.is_https())
+ try:
+ return fields[0], int(fields[1])
+ except ValueError, e:
+ raise HandshakeError('Invalid port number format: %r' % e)
+
+ def _set_protocol(self):
+ protocol = self._request.headers_in.get('WebSocket-Protocol')
+ if protocol is not None:
+ _validate_protocol(protocol)
+ self._request.ws_protocol = protocol
+
+ def _send_handshake(self):
+ self._request.connection.write(
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n')
+ self._request.connection.write('Upgrade: WebSocket\r\n')
+ self._request.connection.write('Connection: Upgrade\r\n')
+ self._request.connection.write('WebSocket-Origin: ')
+ self._request.connection.write(self._request.ws_origin)
+ self._request.connection.write('\r\n')
+ self._request.connection.write('WebSocket-Location: ')
+ self._request.connection.write(self._request.ws_location)
+ self._request.connection.write('\r\n')
+ if self._request.ws_protocol:
+ self._request.connection.write('WebSocket-Protocol: ')
+ self._request.connection.write(self._request.ws_protocol)
+ self._request.connection.write('\r\n')
+ self._request.connection.write('\r\n')
+
+ def _check_header_lines(self):
+ for key, expected_value in _MANDATORY_HEADERS:
+ actual_value = self._request.headers_in.get(key)
+ if not actual_value:
+ raise HandshakeError('Header %s is not defined' % key)
+ if expected_value:
+ if actual_value != expected_value:
+ raise HandshakeError('Illegal value for header %s: %s' %
+ (key, actual_value))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/headerparserhandler.py b/WebKitTools/pywebsocket/mod_pywebsocket/headerparserhandler.py
new file mode 100644
index 0000000..124b9f1
--- /dev/null
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/headerparserhandler.py
@@ -0,0 +1,99 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""PythonHeaderParserHandler for mod_pywebsocket.
+
+Apache HTTP Server and mod_python must be configured such that this
+function is called to handle Web Socket request.
+"""
+
+
+from mod_python import apache
+
+import dispatch
+import handshake
+import util
+
+
+# PythonOption to specify the handler root directory.
+_PYOPT_HANDLER_ROOT = 'mod_pywebsocket.handler_root'
+
+# PythonOption to specify the handler scan directory.
+# This must be a directory under the root directory.
+# The default is the root directory.
+_PYOPT_HANDLER_SCAN = 'mod_pywebsocket.handler_scan'
+
+
+def _create_dispatcher():
+ _HANDLER_ROOT = apache.main_server.get_options().get(
+ _PYOPT_HANDLER_ROOT, None)
+ if not _HANDLER_ROOT:
+ raise Exception('PythonOption %s is not defined' % _PYOPT_HANDLER_ROOT,
+ apache.APLOG_ERR)
+ _HANDLER_SCAN = apache.main_server.get_options().get(
+ _PYOPT_HANDLER_SCAN, _HANDLER_ROOT)
+ dispatcher = dispatch.Dispatcher(_HANDLER_ROOT, _HANDLER_SCAN)
+ for warning in dispatcher.source_warnings():
+ apache.log_error('mod_pywebsocket: %s' % warning, apache.APLOG_WARNING)
+ return dispatcher
+
+
+# Initialize
+_dispatcher = _create_dispatcher()
+
+
+def headerparserhandler(request):
+ """Handle request.
+
+ Args:
+ request: mod_python request.
+
+ This function is named headerparserhandler because it is the default name
+ for a PythonHeaderParserHandler.
+ """
+
+ try:
+ handshaker = handshake.Handshaker(request, _dispatcher)
+ handshaker.do_handshake()
+ request.log_error('mod_pywebsocket: resource: %r' % request.ws_resource,
+ apache.APLOG_DEBUG)
+ _dispatcher.transfer_data(request)
+ except handshake.HandshakeError, e:
+ # Handshake for ws/wss failed.
+ # But the request can be valid http/https request.
+ request.log_error('mod_pywebsocket: %s' % e, apache.APLOG_INFO)
+ return apache.DECLINED
+ except dispatch.DispatchError, e:
+ request.log_error('mod_pywebsocket: %s' % e, apache.APLOG_WARNING)
+ return apache.DECLINED
+ return apache.DONE # Return DONE such that no other handlers are invoked.
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py b/WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py
new file mode 100644
index 0000000..bdb554d
--- /dev/null
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py
@@ -0,0 +1,223 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Message related utilities.
+
+Note: request.connection.write/read are used in this module, even though
+mod_python document says that they should be used only in connection handlers.
+Unfortunately, we have no other options. For example, request.write/read are
+not suitable because they don't allow direct raw bytes writing/reading.
+"""
+
+
+import Queue
+import threading
+
+
+def send_message(request, message):
+ """Send message.
+
+ Args:
+ request: mod_python request.
+ message: unicode string to send.
+ """
+
+ request.connection.write('\x00' + message.encode('utf-8') + '\xff')
+
+
+def receive_message(request):
+ """Receive a Web Socket frame and return its payload as unicode string.
+
+ Args:
+ request: mod_python request.
+ """
+
+ while True:
+ # Read 1 byte.
+ # mp_conn.read will block if no bytes are available.
+ # Timeout is controlled by TimeOut directive of Apache.
+ frame_type_str = request.connection.read(1)
+ frame_type = ord(frame_type_str[0])
+ if (frame_type & 0x80) == 0x80:
+ # The payload length is specified in the frame.
+ # Read and discard.
+ length = _payload_length(request)
+ _receive_bytes(request, length)
+ else:
+ # The payload is delimited with \xff.
+ bytes = _read_until(request, '\xff')
+ message = bytes.decode('utf-8')
+ if frame_type == 0x00:
+ return message
+ # Discard data of other types.
+
+
+def _payload_length(request):
+ length = 0
+ while True:
+ b_str = request.connection.read(1)
+ b = ord(b_str[0])
+ length = length * 128 + (b & 0x7f)
+ if (b & 0x80) == 0:
+ break
+ return length
+
+
+def _receive_bytes(request, length):
+ bytes = []
+ while length > 0:
+ new_bytes = request.connection.read(length)
+ bytes.append(new_bytes)
+ length -= len(new_bytes)
+ return ''.join(bytes)
+
+
+def _read_until(request, delim_char):
+ bytes = []
+ while True:
+ ch = request.connection.read(1)
+ if ch == delim_char:
+ break
+ bytes.append(ch)
+ return ''.join(bytes)
+
+
+class MessageReceiver(threading.Thread):
+ """This class receives messages from the client.
+
+ This class provides three ways to receive messages: blocking, non-blocking,
+ and via callback. Callback has the highest precedence.
+
+ Note: This class should not be used with the standalone server for wss
+ because pyOpenSSL used by the server raises a fatal error if the socket
+ is accessed from multiple threads.
+ """
+ def __init__(self, request, onmessage=None):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ onmessage: a function to be called when a message is received.
+ May be None. If not None, the function is called on
+ another thread. In that case, MessageReceiver.receive
+ and MessageReceiver.receive_nowait are useless because
+ they will never return any messages.
+ """
+ threading.Thread.__init__(self)
+ self._request = request
+ self._queue = Queue.Queue()
+ self._onmessage = onmessage
+ self._stop_requested = False
+ self.setDaemon(True)
+ self.start()
+
+ def run(self):
+ while not self._stop_requested:
+ message = receive_message(self._request)
+ if self._onmessage:
+ self._onmessage(message)
+ else:
+ self._queue.put(message)
+
+ def receive(self):
+ """ Receive a message from the channel, blocking.
+
+ Returns:
+ message as a unicode string.
+ """
+ return self._queue.get()
+
+ def receive_nowait(self):
+ """ Receive a message from the channel, non-blocking.
+
+ Returns:
+ message as a unicode string if available. None otherwise.
+ """
+ try:
+ message = self._queue.get_nowait()
+ except Queue.Empty:
+ message = None
+ return message
+
+ def stop(self):
+ """Request to stop this instance.
+
+ The instance will be stopped after receiving the next message.
+ This method may not be very useful, but there is no clean way
+ in Python to forcefully stop a running thread.
+ """
+ self._stop_requested = True
+
+
+class MessageSender(threading.Thread):
+ """This class sends messages to the client.
+
+ This class provides both synchronous and asynchronous ways to send
+ messages.
+
+ Note: This class should not be used with the standalone server for wss
+ because pyOpenSSL used by the server raises a fatal error if the socket
+ is accessed from multiple threads.
+ """
+ def __init__(self, request):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ """
+ threading.Thread.__init__(self)
+ self._request = request
+ self._queue = Queue.Queue()
+ self.setDaemon(True)
+ self.start()
+
+ def run(self):
+ while True:
+ message, condition = self._queue.get()
+ condition.acquire()
+ send_message(self._request, message)
+ condition.notify()
+ condition.release()
+
+ def send(self, message):
+ """Send a message, blocking."""
+
+ condition = threading.Condition()
+ condition.acquire()
+ self._queue.put((message, condition))
+ condition.wait()
+
+ def send_nowait(self, message):
+ """Send a message, non-blocking."""
+
+ self._queue.put((message, threading.Condition()))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/standalone.py b/WebKitTools/pywebsocket/mod_pywebsocket/standalone.py
new file mode 100644
index 0000000..a4c142b
--- /dev/null
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/standalone.py
@@ -0,0 +1,254 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Standalone Web Socket server.
+
+Use this server to run mod_pywebsocket without Apache HTTP Server.
+
+Usage:
+ python standalone.py [-p <ws_port>] [-w <websock_handlers>]
+ [-s <scan_dir>]
+ [-d <document_root>]
+
+<ws_port> is the port number to use for ws:// connection.
+
+<document_root> is the path to the root directory of HTML files.
+
+<websock_handlers> is the path to the root directory of Web Socket handlers.
+See __init__.py for details of <websock_handlers> and how to write Web Socket
+handlers. If this path is relative, <document_root> is used as the base.
+
+<scan_dir> is a path under the root directory. If specified, only the handlers
+under scan_dir are scanned. This is useful in saving scan time.
+
+Note:
+This server is derived from SocketServer.ThreadingMixIn. Hence a thread is
+used for each request.
+"""
+
+import BaseHTTPServer
+import SimpleHTTPServer
+import SocketServer
+import logging
+import optparse
+import os
+import socket
+import sys
+
+_HAS_OPEN_SSL = False
+try:
+ import OpenSSL.SSL
+ _HAS_OPEN_SSL = True
+except ImportError:
+ pass
+
+import dispatch
+import handshake
+
+
+class _StandaloneConnection(object):
+ """Mimic mod_python mp_conn."""
+
+ def __init__(self, request_handler):
+ """Construct an instance.
+
+ Args:
+ request_handler: A WebSocketRequestHandler instance.
+ """
+ self._request_handler = request_handler
+
+ def get_local_addr(self):
+ """Getter to mimic mp_conn.local_addr."""
+ return (self._request_handler.server.server_name,
+ self._request_handler.server.server_port)
+ local_addr = property(get_local_addr)
+
+ def write(self, data):
+ """Mimic mp_conn.write()."""
+ return self._request_handler.wfile.write(data)
+
+ def read(self, length):
+ """Mimic mp_conn.read()."""
+ return self._request_handler.rfile.read(length)
+
+
+class _StandaloneRequest(object):
+ """Mimic mod_python request."""
+
+ def __init__(self, request_handler, use_tls):
+ """Construct an instance.
+
+ Args:
+ request_handler: A WebSocketRequestHandler instance.
+ """
+ self._request_handler = request_handler
+ self.connection = _StandaloneConnection(request_handler)
+ self._use_tls = use_tls
+
+ def get_uri(self):
+ """Getter to mimic request.uri."""
+ return self._request_handler.path
+ uri = property(get_uri)
+
+ def get_headers_in(self):
+ """Getter to mimic request.headers_in."""
+ return self._request_handler.headers
+ headers_in = property(get_headers_in)
+
+ def is_https(self):
+ """Mimic request.is_https()."""
+ return self._use_tls
+
+
+class WebSocketServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
+ """HTTPServer specialized for Web Socket."""
+
+ SocketServer.ThreadingMixIn.daemon_threads = True
+
+ def __init__(self, server_address, RequestHandlerClass):
+ """Override SocketServer.BaseServer.__init__."""
+
+ SocketServer.BaseServer.__init__(
+ self, server_address, RequestHandlerClass)
+ self.socket = self._create_socket()
+ self.server_bind()
+ self.server_activate()
+
+ def _create_socket(self):
+ socket_ = socket.socket(self.address_family, self.socket_type)
+ if WebSocketServer.options.use_tls:
+ ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
+ ctx.use_privatekey_file(WebSocketServer.options.private_key)
+ ctx.use_certificate_file(WebSocketServer.options.certificate)
+ socket_ = OpenSSL.SSL.Connection(ctx, socket_)
+ return socket_
+
+class WebSocketRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+ """SimpleHTTPRequestHandler specialized for Web Socket."""
+
+ def setup(self):
+ """Override SocketServer.StreamRequestHandler.setup."""
+
+ self.connection = self.request
+ self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
+ self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
+
+ def __init__(self, *args, **keywords):
+ self._request = _StandaloneRequest(
+ self, WebSocketRequestHandler.options.use_tls)
+ self._dispatcher = dispatch.Dispatcher(
+ WebSocketRequestHandler.options.websock_handlers,
+ WebSocketRequestHandler.options.scan_dir)
+ self._print_warnings_if_any()
+ self._handshaker = handshake.Handshaker(self._request,
+ self._dispatcher)
+ SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(
+ self, *args, **keywords)
+
+ def _print_warnings_if_any(self):
+ warnings = self._dispatcher.source_warnings()
+ if warnings:
+ for warning in warnings:
+ logging.warning('mod_pywebsocket: %s' % warning)
+
+ def parse_request(self):
+ """Override BaseHTTPServer.BaseHTTPRequestHandler.parse_request.
+
+ Return True to continue processing for HTTP(S), False otherwise.
+ """
+ result = SimpleHTTPServer.SimpleHTTPRequestHandler.parse_request(self)
+ if result:
+ try:
+ self._handshaker.do_handshake()
+ self._dispatcher.transfer_data(self._request)
+ return False
+ except handshake.HandshakeError, e:
+ # Handshake for ws(s) failed. Assume http(s).
+ logging.info('mod_pywebsocket: %s' % e)
+ return True
+ except dispatch.DispatchError, e:
+ logging.warning('mod_pywebsocket: %s' % e)
+ return False
+ return result
+
+
+def _main():
+ logging.basicConfig()
+
+ parser = optparse.OptionParser()
+ parser.add_option('-p', '--port', dest='port', type='int',
+ default=handshake._DEFAULT_WEB_SOCKET_PORT,
+ help='port to listen to')
+ parser.add_option('-w', '--websock_handlers', dest='websock_handlers',
+ default='.',
+ help='Web Socket handlers root directory.')
+ parser.add_option('-s', '--scan_dir', dest='scan_dir',
+ default=None,
+ help=('Web Socket handlers scan directory. '
+ 'Must be a directory under websock_handlers.'))
+ parser.add_option('-d', '--document_root', dest='document_root',
+ default='.',
+ help='Document root directory.')
+ parser.add_option('-t', '--tls', dest='use_tls', action='store_true',
+ default=False, help='use TLS (wss://)')
+ parser.add_option('-k', '--private_key', dest='private_key',
+ default='', help='TLS private key file.')
+ parser.add_option('-c', '--certificate', dest='certificate',
+ default='', help='TLS certificate file.')
+ options = parser.parse_args()[0]
+
+ if options.use_tls:
+ if not _HAS_OPEN_SSL:
+ print >>sys.stderr, 'To use TLS, install pyOpenSSL.'
+ sys.exit(1)
+ if not options.private_key or not options.certificate:
+ print >>sys.stderr, ('To use TLS, specify private_key and '
+ 'certificate.')
+ sys.exit(1)
+
+ if not options.scan_dir:
+ options.scan_dir = options.websock_handlers
+
+ WebSocketRequestHandler.options = options
+ WebSocketServer.options = options
+
+ os.chdir(options.document_root)
+
+ server = WebSocketServer(('', options.port), WebSocketRequestHandler)
+ server.serve_forever()
+
+
+if __name__ == '__main__':
+ _main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/util.py b/WebKitTools/pywebsocket/mod_pywebsocket/util.py
new file mode 100644
index 0000000..4835298
--- /dev/null
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/util.py
@@ -0,0 +1,52 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Web Sockets utilities.
+"""
+
+
+import StringIO
+import traceback
+
+
+def get_stack_trace():
+ """Get the current stack trace as string.
+
+ This is needed to support Python 2.3.
+ TODO: Remove this when we only support Python 2.4 and above.
+ Use traceback.format_exc instead.
+ """
+
+ out = StringIO.StringIO()
+ traceback.print_exc(file=out)
+ return out.getvalue()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/setup.py b/WebKitTools/pywebsocket/setup.py
new file mode 100644
index 0000000..1810a6d
--- /dev/null
+++ b/WebKitTools/pywebsocket/setup.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Set up script for mod_pywebsocket.
+"""
+
+
+from distutils.core import setup
+import sys
+
+
+_PACKAGE_NAME = 'mod_pywebsocket'
+
+if sys.version < '2.3':
+ print >>sys.stderr, '%s requires Python 2.3 or later.' % _PACKAGE_NAME
+ sys.exit(1)
+
+setup(author='Yuzo Fujishima',
+ author_email='yuzo@chromium.org',
+ description='Web Socket extension for Apache HTTP Server.',
+ long_description=(
+ 'mod_pywebsocket is an Apache HTTP Server extension for '
+ 'Web Socket (http://tools.ietf.org/html/'
+ 'draft-hixie-thewebsocketprotocol). '
+ 'See mod_pywebsocket/__init__.py for more detail.'),
+ license='See COPYING',
+ name=_PACKAGE_NAME,
+ packages=[_PACKAGE_NAME],
+ url='http://code.google.com/p/pywebsocket/',
+ version='0.4.1',
+ )
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/config.py b/WebKitTools/pywebsocket/test/config.py
new file mode 100644
index 0000000..5aaab8c
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/config.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Configuration for testing.
+
+Test files should import this module before mod_pywebsocket.
+"""
+
+
+import os
+import sys
+
+
+# Add the parent directory to sys.path to enable importing mod_pywebsocket.
+sys.path += [os.path.join(os.path.split(__file__)[0], '..')]
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/mock.py b/WebKitTools/pywebsocket/test/mock.py
new file mode 100644
index 0000000..3b85d64
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/mock.py
@@ -0,0 +1,205 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Mocks for testing.
+"""
+
+
+import Queue
+import threading
+
+
+class _MockConnBase(object):
+ """Base class of mocks for mod_python.apache.mp_conn.
+
+ This enables tests to check what is written to a (mock) mp_conn.
+ """
+
+ def __init__(self):
+ self._write_data = []
+
+ def write(self, data):
+ """Override mod_python.apache.mp_conn.write."""
+
+ self._write_data.append(data)
+
+ def written_data(self):
+ """Get bytes written to this mock."""
+
+ return ''.join(self._write_data)
+
+
+class MockConn(_MockConnBase):
+ """Mock for mod_python.apache.mp_conn.
+
+ This enables tests to specify what should be read from a (mock) mp_conn as
+ well as to check what is written to it.
+ """
+
+ def __init__(self, read_data):
+ """Constructs an instance.
+
+ Args:
+ read_data: bytes that should be returned when read* methods are
+ called.
+ """
+
+ _MockConnBase.__init__(self)
+ self._read_data = read_data
+ self._read_pos = 0
+
+ def readline(self):
+ """Override mod_python.apache.mp_conn.readline."""
+
+ if self._read_pos >= len(self._read_data):
+ return ''
+ end_index = self._read_data.find('\n', self._read_pos) + 1
+ if not end_index:
+ end_index = len(self._read_data)
+ return self._read_up_to(end_index)
+
+ def read(self, length):
+ """Override mod_python.apache.mp_conn.read."""
+
+ if self._read_pos >= len(self._read_data):
+ return ''
+ end_index = min(len(self._read_data), self._read_pos + length)
+ return self._read_up_to(end_index)
+
+ def _read_up_to(self, end_index):
+ line = self._read_data[self._read_pos:end_index]
+ self._read_pos = end_index
+ return line
+
+
+class MockBlockingConn(_MockConnBase):
+ """Blocking mock for mod_python.apache.mp_conn.
+
+ This enables tests to specify what should be read from a (mock) mp_conn as
+ well as to check what is written to it.
+ Callers of read* methods will block if there is no bytes available.
+ """
+
+ def __init__(self):
+ _MockConnBase.__init__(self)
+ self._queue = Queue.Queue()
+
+ def readline(self):
+ """Override mod_python.apache.mp_conn.readline."""
+ line = ''
+ while True:
+ c = self._queue.get()
+ line += c
+ if c == '\n':
+ return line
+
+ def read(self, length):
+ """Override mod_python.apache.mp_conn.read."""
+
+ data = ''
+ for unused in range(length):
+ data += self._queue.get()
+ return data
+
+ def put_bytes(self, bytes):
+ """Put bytes to be read from this mock.
+
+ Args:
+ bytes: bytes to be read.
+ """
+
+ for byte in bytes:
+ self._queue.put(byte)
+
+
+class MockTable(dict):
+ """Mock table.
+
+ This mimics mod_python mp_table. Note that only the methods used by
+ tests are overridden.
+ """
+
+ def __init__(self, copy_from={}):
+ if isinstance(copy_from, dict):
+ copy_from = copy_from.items()
+ for key, value in copy_from:
+ self.__setitem__(key, value)
+
+ def __getitem__(self, key):
+ return super(MockTable, self).__getitem__(key.lower())
+
+ def __setitem__(self, key, value):
+ super(MockTable, self).__setitem__(key.lower(), value)
+
+ def get(self, key, def_value=None):
+ return super(MockTable, self).get(key.lower(), def_value)
+
+
+class MockRequest(object):
+ """Mock request.
+
+ This mimics mod_python request.
+ """
+
+ def __init__(self, uri=None, headers_in={}, connection=None,
+ is_https=False):
+ """Construct an instance.
+
+ Arguments:
+ uri: URI of the request.
+ headers_in: Request headers.
+ connection: Connection used for the request.
+ is_https: Whether this request is over SSL.
+
+ See the document of mod_python Request for details.
+ """
+ self.uri = uri
+ self.connection = connection
+ self.headers_in = MockTable(headers_in)
+ # self.is_https_ needs to be accessible from tests. To avoid name
+ # conflict with self.is_https(), it is named as such.
+ self.is_https_ = is_https
+
+ def is_https(self):
+ """Return whether this request is over SSL."""
+ return self.is_https_
+
+
+class MockDispatcher(object):
+ """Mock for dispatch.Dispatcher."""
+
+ def do_extra_handshake(self, conn_context):
+ pass
+
+ def transfer_data(self, conn_context):
+ pass
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/run_all.py b/WebKitTools/pywebsocket/test/run_all.py
new file mode 100644
index 0000000..3885618
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/run_all.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Run all tests in the same directory.
+"""
+
+
+import os
+import re
+import unittest
+
+
+_TEST_MODULE_PATTERN = re.compile(r'^(test_.+)\.py$')
+
+
+def _list_test_modules(directory):
+ module_names = []
+ for filename in os.listdir(directory):
+ match = _TEST_MODULE_PATTERN.search(filename)
+ if match:
+ module_names.append(match.group(1))
+ return module_names
+
+
+def _suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromNames(
+ _list_test_modules(os.path.join(os.path.split(__file__)[0], '.')))
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='_suite')
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/test_dispatch.py b/WebKitTools/pywebsocket/test/test_dispatch.py
new file mode 100644
index 0000000..d617205
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/test_dispatch.py
@@ -0,0 +1,222 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Tests for dispatch module."""
+
+
+
+import os
+import unittest
+
+import config # This must be imported before mod_pywebsocket.
+from mod_pywebsocket import dispatch
+
+import mock
+
+
+_TEST_HANDLERS_DIR = os.path.join(
+ os.path.split(__file__)[0], 'testdata', 'handlers')
+
+_TEST_HANDLERS_SUB_DIR = os.path.join(_TEST_HANDLERS_DIR, 'sub')
+
+class DispatcherTest(unittest.TestCase):
+ def test_normalize_path(self):
+ self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
+ dispatch._normalize_path('/a/b'))
+ self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
+ dispatch._normalize_path('\\a\\b'))
+ self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
+ dispatch._normalize_path('/a/c/../b'))
+ self.assertEqual(os.path.abspath('abc').replace('\\', '/'),
+ dispatch._normalize_path('abc'))
+
+ def test_converter(self):
+ converter = dispatch._path_to_resource_converter('/a/b')
+ self.assertEqual('/h', converter('/a/b/h_wsh.py'))
+ self.assertEqual('/c/h', converter('/a/b/c/h_wsh.py'))
+ self.assertEqual(None, converter('/a/b/h.py'))
+ self.assertEqual(None, converter('a/b/h_wsh.py'))
+
+ converter = dispatch._path_to_resource_converter('a/b')
+ self.assertEqual('/h', converter('a/b/h_wsh.py'))
+
+ converter = dispatch._path_to_resource_converter('/a/b///')
+ self.assertEqual('/h', converter('/a/b/h_wsh.py'))
+ self.assertEqual('/h', converter('/a/b/../b/h_wsh.py'))
+
+ converter = dispatch._path_to_resource_converter('/a/../a/b/../b/')
+ self.assertEqual('/h', converter('/a/b/h_wsh.py'))
+
+ converter = dispatch._path_to_resource_converter(r'\a\b')
+ self.assertEqual('/h', converter(r'\a\b\h_wsh.py'))
+ self.assertEqual('/h', converter(r'/a/b/h_wsh.py'))
+
+ def test_source_file_paths(self):
+ paths = list(dispatch._source_file_paths(_TEST_HANDLERS_DIR))
+ paths.sort()
+ self.assertEqual(7, len(paths))
+ expected_paths = [
+ os.path.join(_TEST_HANDLERS_DIR, 'blank_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'origin_check_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'exception_in_transfer_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub', 'non_callable_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub', 'plain_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'wrong_handshake_sig_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'wrong_transfer_sig_wsh.py'),
+ ]
+ for expected, actual in zip(expected_paths, paths):
+ self.assertEqual(expected, actual)
+
+ def test_source(self):
+ self.assertRaises(dispatch.DispatchError, dispatch._source, '')
+ self.assertRaises(dispatch.DispatchError, dispatch._source, 'def')
+ self.assertRaises(dispatch.DispatchError, dispatch._source, '1/0')
+ self.failUnless(dispatch._source(
+ 'def web_socket_do_extra_handshake(request):pass\n'
+ 'def web_socket_transfer_data(request):pass\n'))
+
+ def test_source_warnings(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ warnings = dispatcher.source_warnings()
+ warnings.sort()
+ expected_warnings = [
+ (os.path.join(_TEST_HANDLERS_DIR, 'blank_wsh.py') +
+ ': web_socket_do_extra_handshake is not defined.'),
+ (os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'non_callable_wsh.py') +
+ ': web_socket_do_extra_handshake is not callable.'),
+ (os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'wrong_handshake_sig_wsh.py') +
+ ': web_socket_do_extra_handshake is not defined.'),
+ (os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'wrong_transfer_sig_wsh.py') +
+ ': web_socket_transfer_data is not defined.'),
+ ]
+ self.assertEquals(4, len(warnings))
+ for expected, actual in zip(expected_warnings, warnings):
+ self.assertEquals(expected, actual)
+
+ def test_do_extra_handshake(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ request = mock.MockRequest()
+ request.ws_resource = '/origin_check'
+ request.ws_origin = 'http://example.com'
+ dispatcher.do_extra_handshake(request) # Must not raise exception.
+
+ request.ws_origin = 'http://bad.example.com'
+ self.assertRaises(dispatch.DispatchError,
+ dispatcher.do_extra_handshake, request)
+
+ def test_transfer_data(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = '/origin_check'
+ request.ws_protocol = 'p1'
+
+ dispatcher.transfer_data(request)
+ self.assertEqual('origin_check_wsh.py is called for /origin_check, p1',
+ request.connection.written_data())
+
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = '/sub/plain'
+ request.ws_protocol = None
+ dispatcher.transfer_data(request)
+ self.assertEqual('sub/plain_wsh.py is called for /sub/plain, None',
+ request.connection.written_data())
+
+ def test_transfer_data_no_handler(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ for resource in ['/blank', '/sub/non_callable',
+ '/sub/no_wsh_at_the_end', '/does/not/exist']:
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = resource
+ request.ws_protocol = 'p2'
+ try:
+ dispatcher.transfer_data(request)
+ self.fail()
+ except dispatch.DispatchError, e:
+ self.failUnless(str(e).find('No handler') != -1)
+ except Exception:
+ self.fail()
+
+ def test_transfer_data_handler_exception(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = '/sub/exception_in_transfer'
+ request.ws_protocol = 'p3'
+ try:
+ dispatcher.transfer_data(request)
+ self.fail()
+ except dispatch.DispatchError, e:
+ self.failUnless(str(e).find('Intentional') != -1)
+ except Exception:
+ self.fail()
+
+ def test_scan_dir(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ self.assertEqual(3, len(disp._handlers))
+ self.failUnless(disp._handlers.has_key('/origin_check'))
+ self.failUnless(disp._handlers.has_key('/sub/exception_in_transfer'))
+ self.failUnless(disp._handlers.has_key('/sub/plain'))
+
+ def test_scan_sub_dir(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, _TEST_HANDLERS_SUB_DIR)
+ self.assertEqual(2, len(disp._handlers))
+ self.failIf(disp._handlers.has_key('/origin_check'))
+ self.failUnless(disp._handlers.has_key('/sub/exception_in_transfer'))
+ self.failUnless(disp._handlers.has_key('/sub/plain'))
+
+ def test_scan_sub_dir_as_root(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_SUB_DIR,
+ _TEST_HANDLERS_SUB_DIR)
+ self.assertEqual(2, len(disp._handlers))
+ self.failIf(disp._handlers.has_key('/origin_check'))
+ self.failIf(disp._handlers.has_key('/sub/exception_in_transfer'))
+ self.failIf(disp._handlers.has_key('/sub/plain'))
+ self.failUnless(disp._handlers.has_key('/exception_in_transfer'))
+ self.failUnless(disp._handlers.has_key('/plain'))
+
+ def test_scan_dir_must_under_root(self):
+ dispatch.Dispatcher('a/b', 'a/b/c') # OK
+ dispatch.Dispatcher('a/b///', 'a/b') # OK
+ self.assertRaises(dispatch.DispatchError,
+ dispatch.Dispatcher, 'a/b/c', 'a/b')
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/test_handshake.py b/WebKitTools/pywebsocket/test/test_handshake.py
new file mode 100644
index 0000000..dd1f65c
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/test_handshake.py
@@ -0,0 +1,316 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Tests for handshake module."""
+
+
+import unittest
+
+import config # This must be imported before mod_pywebsocket.
+from mod_pywebsocket import handshake
+
+import mock
+
+
+_GOOD_REQUEST = (
+ 80,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'sample',
+ }
+)
+
+_GOOD_RESPONSE_DEFAULT_PORT = (
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'WebSocket-Origin: http://example.com\r\n'
+ 'WebSocket-Location: ws://example.com/demo\r\n'
+ 'WebSocket-Protocol: sample\r\n'
+ '\r\n')
+
+_GOOD_RESPONSE_SECURE = (
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'WebSocket-Origin: http://example.com\r\n'
+ 'WebSocket-Location: wss://example.com/demo\r\n'
+ 'WebSocket-Protocol: sample\r\n'
+ '\r\n')
+
+_GOOD_REQUEST_NONDEFAULT_PORT = (
+ 8081,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com:8081',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'sample',
+ }
+)
+
+_GOOD_RESPONSE_NONDEFAULT_PORT = (
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'WebSocket-Origin: http://example.com\r\n'
+ 'WebSocket-Location: ws://example.com:8081/demo\r\n'
+ 'WebSocket-Protocol: sample\r\n'
+ '\r\n')
+
+_GOOD_RESPONSE_SECURE_NONDEF = (
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'WebSocket-Origin: http://example.com\r\n'
+ 'WebSocket-Location: wss://example.com:8081/demo\r\n'
+ 'WebSocket-Protocol: sample\r\n'
+ '\r\n')
+
+_GOOD_REQUEST_NO_PROTOCOL = (
+ 80,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ }
+)
+
+_GOOD_RESPONSE_NO_PROTOCOL = (
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'WebSocket-Origin: http://example.com\r\n'
+ 'WebSocket-Location: ws://example.com/demo\r\n'
+ '\r\n')
+
+_GOOD_REQUEST_WITH_OPTIONAL_HEADERS = (
+ 80,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'sample',
+ 'AKey':'AValue',
+ 'EmptyValue':'',
+ }
+)
+
+_BAD_REQUESTS = (
+ ( # HTTP request
+ 80,
+ '/demo',
+ {
+ 'Host':'www.google.com',
+ 'User-Agent':'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5;'
+ ' en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3'
+ ' GTB6 GTBA',
+ 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,'
+ '*/*;q=0.8',
+ 'Accept-Language':'en-us,en;q=0.5',
+ 'Accept-Encoding':'gzip,deflate',
+ 'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
+ 'Keep-Alive':'300',
+ 'Connection':'keep-alive',
+ }
+ ),
+ ( # Missing Upgrade
+ 80,
+ '/demo',
+ {
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'sample',
+ }
+ ),
+ ( # Wrong Upgrade
+ 80,
+ '/demo',
+ {
+ 'Upgrade':'NonWebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'sample',
+ }
+ ),
+ ( # Empty WebSocket-Protocol
+ 80,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'',
+ }
+ ),
+ ( # Wrong port number format
+ 80,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com:0x50',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'sample',
+ }
+ ),
+ ( # Header/connection port mismatch
+ 8080,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'sample',
+ }
+ ),
+ ( # Illegal WebSocket-Protocol
+ 80,
+ '/demo',
+ {
+ 'Upgrade':'WebSocket',
+ 'Connection':'Upgrade',
+ 'Host':'example.com',
+ 'Origin':'http://example.com',
+ 'WebSocket-Protocol':'illegal protocol',
+ }
+ ),
+)
+
+
+def _create_request(request_def):
+ conn = mock.MockConn('')
+ conn.local_addr = ('0.0.0.0', request_def[0])
+ return mock.MockRequest(
+ uri=request_def[1],
+ headers_in=request_def[2],
+ connection=conn)
+
+
+class HandshakerTest(unittest.TestCase):
+ def test_validate_protocol(self):
+ handshake._validate_protocol('sample') # should succeed.
+ handshake._validate_protocol('Sample') # should succeed.
+ self.assertRaises(handshake.HandshakeError,
+ handshake._validate_protocol,
+ 'sample protocol')
+ self.assertRaises(handshake.HandshakeError,
+ handshake._validate_protocol,
+ # "Japan" in Japanese
+ u'\u65e5\u672c')
+
+ def test_good_request_default_port(self):
+ request = _create_request(_GOOD_REQUEST)
+ handshaker = handshake.Handshaker(request,
+ mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_DEFAULT_PORT,
+ request.connection.written_data())
+ self.assertEqual('/demo', request.ws_resource)
+ self.assertEqual('http://example.com', request.ws_origin)
+ self.assertEqual('ws://example.com/demo', request.ws_location)
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_secure_default_port(self):
+ request = _create_request(_GOOD_REQUEST)
+ request.connection.local_addr = ('0.0.0.0', 443)
+ request.is_https_ = True
+ handshaker = handshake.Handshaker(request,
+ mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_SECURE,
+ request.connection.written_data())
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_nondefault_port(self):
+ request = _create_request(_GOOD_REQUEST_NONDEFAULT_PORT)
+ handshaker = handshake.Handshaker(request,
+ mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_NONDEFAULT_PORT,
+ request.connection.written_data())
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_secure_non_default_port(self):
+ request = _create_request(_GOOD_REQUEST_NONDEFAULT_PORT)
+ request.is_https_ = True
+ handshaker = handshake.Handshaker(request,
+ mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_SECURE_NONDEF,
+ request.connection.written_data())
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_default_no_protocol(self):
+ request = _create_request(_GOOD_REQUEST_NO_PROTOCOL)
+ handshaker = handshake.Handshaker(request,
+ mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_NO_PROTOCOL,
+ request.connection.written_data())
+ self.assertEqual(None, request.ws_protocol)
+
+ def test_good_request_optional_headers(self):
+ request = _create_request(_GOOD_REQUEST_WITH_OPTIONAL_HEADERS)
+ handshaker = handshake.Handshaker(request,
+ mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual('AValue',
+ request.headers_in['AKey'])
+ self.assertEqual('',
+ request.headers_in['EmptyValue'])
+
+ def test_bad_requests(self):
+ for request in map(_create_request, _BAD_REQUESTS):
+ handshaker = handshake.Handshaker(request,
+ mock.MockDispatcher())
+ self.assertRaises(handshake.HandshakeError, handshaker.do_handshake)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/test_mock.py b/WebKitTools/pywebsocket/test/test_mock.py
new file mode 100644
index 0000000..8b137d1
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/test_mock.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Tests for mock module."""
+
+
+import Queue
+import threading
+import unittest
+
+import mock
+
+
+class MockConnTest(unittest.TestCase):
+ def setUp(self):
+ self._conn = mock.MockConn('ABC\r\nDEFG\r\n\r\nHIJK')
+
+ def test_readline(self):
+ self.assertEqual('ABC\r\n', self._conn.readline())
+ self.assertEqual('DEFG\r\n', self._conn.readline())
+ self.assertEqual('\r\n', self._conn.readline())
+ self.assertEqual('HIJK', self._conn.readline())
+ self.assertEqual('', self._conn.readline())
+
+ def test_read(self):
+ self.assertEqual('ABC\r\nD', self._conn.read(6))
+ self.assertEqual('EFG\r\n\r\nHI', self._conn.read(9))
+ self.assertEqual('JK', self._conn.read(10))
+ self.assertEqual('', self._conn.read(10))
+
+ def test_read_and_readline(self):
+ self.assertEqual('ABC\r\nD', self._conn.read(6))
+ self.assertEqual('EFG\r\n', self._conn.readline())
+ self.assertEqual('\r\nHIJK', self._conn.read(9))
+ self.assertEqual('', self._conn.readline())
+
+ def test_write(self):
+ self._conn.write('Hello\r\n')
+ self._conn.write('World\r\n')
+ self.assertEqual('Hello\r\nWorld\r\n', self._conn.written_data())
+
+
+class MockBlockingConnTest(unittest.TestCase):
+ def test_read(self):
+ class LineReader(threading.Thread):
+ def __init__(self, conn, queue):
+ threading.Thread.__init__(self)
+ self._queue = queue
+ self._conn = conn
+ self.setDaemon(True)
+ self.start()
+ def run(self):
+ while True:
+ data = self._conn.readline()
+ self._queue.put(data)
+ conn = mock.MockBlockingConn()
+ queue = Queue.Queue()
+ reader = LineReader(conn, queue)
+ self.failUnless(queue.empty())
+ conn.put_bytes('Foo bar\r\n')
+ read = queue.get()
+ self.assertEqual('Foo bar\r\n', read)
+
+
+class MockTableTest(unittest.TestCase):
+ def test_create_from_dict(self):
+ table = mock.MockTable({'Key':'Value'})
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['key'])
+
+ def test_create_from_list(self):
+ table = mock.MockTable([('Key', 'Value')])
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['key'])
+
+ def test_create_from_tuple(self):
+ table = mock.MockTable((('Key', 'Value'),))
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['key'])
+
+ def test_set_and_get(self):
+ table = mock.MockTable()
+ self.assertEqual(None, table.get('Key'))
+ table['Key'] = 'Value'
+ self.assertEqual('Value', table.get('Key'))
+ self.assertEqual('Value', table.get('key'))
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['Key'])
+ self.assertEqual('Value', table['key'])
+ self.assertEqual('Value', table['KEY'])
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/test_msgutil.py b/WebKitTools/pywebsocket/test/test_msgutil.py
new file mode 100644
index 0000000..b3ba539
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/test_msgutil.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Tests for msgutil module."""
+
+
+import Queue
+import unittest
+
+import config # This must be imported before mod_pywebsocket.
+from mod_pywebsocket import msgutil
+
+import mock
+
+
+def _create_request(read_data):
+ return mock.MockRequest(connection=mock.MockConn(read_data))
+
+def _create_blocking_request():
+ return mock.MockRequest(connection=mock.MockBlockingConn())
+
+class MessageTest(unittest.TestCase):
+ def test_send_message(self):
+ request = _create_request('')
+ msgutil.send_message(request, 'Hello')
+ self.assertEqual('\x00Hello\xff', request.connection.written_data())
+
+ def test_send_message_unicode(self):
+ request = _create_request('')
+ msgutil.send_message(request, u'\u65e5')
+ # U+65e5 is encoded as e6,97,a5 in UTF-8
+ self.assertEqual('\x00\xe6\x97\xa5\xff',
+ request.connection.written_data())
+
+ def test_receive_message(self):
+ request = _create_request('\x00Hello\xff\x00World!\xff')
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertEqual('World!', msgutil.receive_message(request))
+
+ def test_receive_message_unicode(self):
+ request = _create_request('\x00\xe6\x9c\xac\xff')
+ # U+672c is encoded as e6,9c,ac in UTF-8
+ self.assertEqual(u'\u672c', msgutil.receive_message(request))
+
+ def test_receive_message_discard(self):
+ request = _create_request('\x80\x06IGNORE\x00Hello\xff'
+ '\x01DISREGARD\xff\x00World!\xff')
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertEqual('World!', msgutil.receive_message(request))
+
+ def test_payload_length(self):
+ for length, bytes in ((0, '\x00'), (0x7f, '\x7f'), (0x80, '\x81\x00'),
+ (0x1234, '\x80\xa4\x34')):
+ self.assertEqual(length,
+ msgutil._payload_length(_create_request(bytes)))
+
+ def test_receive_bytes(self):
+ request = _create_request('abcdefg')
+ self.assertEqual('abc', msgutil._receive_bytes(request, 3))
+ self.assertEqual('defg', msgutil._receive_bytes(request, 4))
+
+ def test_read_until(self):
+ request = _create_request('abcXdefgX')
+ self.assertEqual('abc', msgutil._read_until(request, 'X'))
+ self.assertEqual('defg', msgutil._read_until(request, 'X'))
+
+
+class MessageReceiverTest(unittest.TestCase):
+ def test_queue(self):
+ request = _create_blocking_request()
+ receiver = msgutil.MessageReceiver(request)
+
+ self.assertEqual(None, receiver.receive_nowait())
+
+ request.connection.put_bytes('\x00Hello!\xff')
+ self.assertEqual('Hello!', receiver.receive())
+
+ def test_onmessage(self):
+ onmessage_queue = Queue.Queue()
+ def onmessage_handler(message):
+ onmessage_queue.put(message)
+
+ request = _create_blocking_request()
+ receiver = msgutil.MessageReceiver(request, onmessage_handler)
+
+ request.connection.put_bytes('\x00Hello!\xff')
+ self.assertEqual('Hello!', onmessage_queue.get())
+
+
+class MessageSenderTest(unittest.TestCase):
+ def test_send(self):
+ request = _create_blocking_request()
+ sender = msgutil.MessageSender(request)
+
+ sender.send('World')
+ self.assertEqual('\x00World\xff', request.connection.written_data())
+
+ def test_send_nowait(self):
+ # Use a queue to check the bytes written by MessageSender.
+ # request.connection.written_data() cannot be used here because
+ # MessageSender runs in a separate thread.
+ send_queue = Queue.Queue()
+ def write(bytes):
+ send_queue.put(bytes)
+ request = _create_blocking_request()
+ request.connection.write = write
+
+ sender = msgutil.MessageSender(request)
+
+ sender.send_nowait('Hello')
+ sender.send_nowait('World')
+ self.assertEqual('\x00Hello\xff', send_queue.get())
+ self.assertEqual('\x00World\xff', send_queue.get())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/test_util.py b/WebKitTools/pywebsocket/test/test_util.py
new file mode 100644
index 0000000..8058b6d
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/test_util.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+#
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Tests for util module."""
+
+
+import unittest
+
+import config # This must be imported before mod_pywebsocket.
+from mod_pywebsocket import util
+
+
+class UtilTest(unittest.TestCase):
+ def test_get_stack_trace(self):
+ self.assertEqual('None\n', util.get_stack_trace())
+ try:
+ a = 1 / 0 # Intentionally raise exception.
+ except Exception:
+ trace = util.get_stack_trace()
+ self.failUnless(trace.startswith('Traceback'))
+ self.failUnless(trace.find('ZeroDivisionError') != -1)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/blank_wsh.py b/WebKitTools/pywebsocket/test/testdata/handlers/blank_wsh.py
new file mode 100644
index 0000000..7f87c6a
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/blank_wsh.py
@@ -0,0 +1,31 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+# intentionally left blank
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/origin_check_wsh.py b/WebKitTools/pywebsocket/test/testdata/handlers/origin_check_wsh.py
new file mode 100644
index 0000000..2c139fa
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/origin_check_wsh.py
@@ -0,0 +1,42 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+def web_socket_do_extra_handshake(request):
+ if request.ws_origin == 'http://example.com':
+ return
+ raise ValueError('Unacceptable origin: %r' % request.ws_origin)
+
+
+def web_socket_transfer_data(request):
+ request.connection.write('origin_check_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py b/WebKitTools/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py
new file mode 100644
index 0000000..b982d02
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py
@@ -0,0 +1,44 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Exception in web_socket_transfer_data().
+"""
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ raise Exception('Intentional Exception for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py b/WebKitTools/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py
new file mode 100644
index 0000000..17e7be1
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Correct signatures, wrong file name.
+"""
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ request.connection.write(
+ 'sub/no_wsh_at_the_end.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py b/WebKitTools/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py
new file mode 100644
index 0000000..26352eb
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py
@@ -0,0 +1,39 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Non-callable handlers.
+"""
+
+
+web_socket_do_extra_handshake = True
+web_socket_transfer_data = 1
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/sub/plain_wsh.py b/WebKitTools/pywebsocket/test/testdata/handlers/sub/plain_wsh.py
new file mode 100644
index 0000000..db3ff69
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/sub/plain_wsh.py
@@ -0,0 +1,40 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ request.connection.write('sub/plain_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py b/WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py
new file mode 100644
index 0000000..6bf659b
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Wrong web_socket_do_extra_handshake signature.
+"""
+
+
+def no_web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ request.connection.write(
+ 'sub/wrong_handshake_sig_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py b/WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py
new file mode 100644
index 0000000..e0e2e55
--- /dev/null
+++ b/WebKitTools/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google 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:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+# OWNER 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.
+
+
+"""Wrong web_socket_transfer_data() signature.
+"""
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def no_web_socket_transfer_data(request):
+ request.connection.write(
+ 'sub/wrong_transfer_sig_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/WebKitTools/wx/browser/wscript b/WebKitTools/wx/browser/wscript
index 530cd75..d5246c1 100644
--- a/WebKitTools/wx/browser/wscript
+++ b/WebKitTools/wx/browser/wscript
@@ -45,7 +45,7 @@ def build(bld):
includes = ' '.join(include_paths),
source = 'browser.cpp',
target = 'wxBrowser',
- uselib = 'WX CURL ICU SQLITE3 XSLT XML WXWEBKIT ' + get_config(),
+ uselib = 'WXWEBKIT WX ' + get_config(),
libpath = [output_dir],
uselib_local = '',
install_path = output_dir)
diff --git a/WebKitTools/wx/build/build_utils.py b/WebKitTools/wx/build/build_utils.py
index 0a795a8..b767d9f 100644
--- a/WebKitTools/wx/build/build_utils.py
+++ b/WebKitTools/wx/build/build_utils.py
@@ -27,13 +27,12 @@ import commands
import glob
import os
import platform
+import re
import shutil
import sys
import urllib
import urlparse
-import Logs
-
def get_output(command):
"""
Windows-compatible function for getting output from a command.
@@ -110,6 +109,7 @@ def update_wx_deps(conf, wk_root, msvc_version='msvc2008'):
"""
Download and update tools needed to build the wx port.
"""
+ import Logs
Logs.info('Ensuring wxWebKit dependencies are up-to-date.')
wklibs_dir = os.path.join(wk_root, 'WebKitLibraries')
@@ -154,3 +154,35 @@ def flattenSources(sources):
flat_sources.extend(group)
return flat_sources
+
+def git_branch_name():
+ try:
+ branches = commands.getoutput("git branch --no-color")
+ match = re.search('^\* (.*)', branches, re.MULTILINE)
+ if match:
+ return ".%s" % match.group(1)
+ except:
+ pass
+
+ return ""
+
+def get_config(wk_root):
+ config_file = os.path.join(wk_root, 'WebKitBuild', 'Configuration')
+ config = 'Debug'
+
+ if os.path.exists(config_file):
+ config = open(config_file).read()
+
+ return config
+
+def svn_revision():
+ if os.system("git info") == 0:
+ info = commands.getoutput("git-svn info ../..")
+ else:
+ info = commands.getoutput("svn info")
+
+ for line in info.split("\n"):
+ if line.startswith("Revision: "):
+ return line.replace("Revision: ", "").strip()
+
+ return ""
diff --git a/WebKitTools/wx/build/settings.py b/WebKitTools/wx/build/settings.py
index 4019273..652a880 100644
--- a/WebKitTools/wx/build/settings.py
+++ b/WebKitTools/wx/build/settings.py
@@ -95,8 +95,9 @@ jscore_dirs = [
]
webcore_dirs = [
- 'accessibility',
- 'bindings/js',
+ 'accessibility',
+ 'bindings',
+ 'bindings/js',
'bridge',
'bridge/c',
'css',
@@ -139,21 +140,8 @@ webcore_dirs = [
'xml'
]
-config_file = os.path.join(wk_root, 'WebKitBuild', 'Configuration')
-config = 'Debug'
-
-if os.path.exists(config_file):
- config = open(config_file).read()
-
-config_dir = config
-
-try:
- branches = commands.getoutput("git branch --no-color")
- match = re.search('^\* (.*)', branches, re.MULTILINE)
- if match:
- config_dir += ".%s" % match.group(1)
-except:
- pass
+config = get_config(wk_root)
+config_dir = config + git_branch_name()
output_dir = os.path.join(wk_root, 'WebKitBuild', config_dir)
@@ -203,6 +191,7 @@ def common_set_options(opt):
opt.add_option('--wxpython', action='store_true', default=False, help='Create the wxPython bindings.')
opt.add_option('--wx-compiler-prefix', action='store', default='vc',
help='Specify a different compiler prefix (do this if you used COMPILER_PREFIX when building wx itself)')
+ opt.add_option('--macosx-version', action='store', default='', help="Version of OS X to build for.")
def common_configure(conf):
"""
@@ -245,11 +234,32 @@ def common_configure(conf):
msvc_version = 'msvc2005'
msvclibs_dir = os.path.join(wklibs_dir, msvc_version, 'win')
- conf.env.append_value('CXXFLAGS', ['/wd4291','/wd4344','/wd4396','/wd4800'])
+
+ # Disable several warnings which occur many times during the build.
+ # Some of them are harmless (4099, 4344, 4396, 4800) and working around
+ # them in WebKit code is probably just not worth it. We can simply do
+ # nothing about the others (4503). A couple are possibly valid but
+ # there are just too many of them in the code so fixing them is
+ # impossible in practice and just results in tons of distracting output
+ # (4244, 4291). Finally 4996 is actively harmful as it is given for
+ # just about any use of standard C/C++ library facilities.
+ conf.env.append_value('CXXFLAGS', [
+ '/wd4099', # type name first seen using 'struct' now seen using 'class'
+ '/wd4244', # conversion from 'xxx' to 'yyy', possible loss of data:
+ '/wd4291', # no matching operator delete found (for placement new)
+ '/wd4344', # behaviour change in template deduction
+ '/wd4396', # inline can't be used in friend declaration
+ '/wd4503', # decorated name length exceeded, name was truncated
+ '/wd4800', # forcing value to bool 'true' or 'false'
+ '/wd4996', # deprecated function
+ ])
+
+ # This one also occurs in C code, so disable it there as well.
+ conf.env.append_value('CCFLAGS', ['/wd4996'])
for use in port_uses[build_port]:
conf.env.append_value('CXXDEFINES', ['WTF_USE_%s' % use])
-
+
if build_port == "wx":
update_wx_deps(conf, wk_root, msvc_version)
@@ -265,7 +275,7 @@ def common_configure(conf):
conf.env['CPPPATH_WX'] = wxincludes
conf.env['LIB_WX'] = wxlibs
conf.env['LIBPATH_WX'] = wxlibpaths
-
+
if sys.platform.startswith('darwin'):
conf.env['LIB_ICU'] = ['icucore']
# Apple does not ship the ICU headers with Mac OS X, so WebKit includes a copy of 3.2 headers
@@ -274,15 +284,33 @@ def common_configure(conf):
conf.env.append_value('CPPPATH', wklibs_dir)
conf.env.append_value('LIBPATH', wklibs_dir)
- # WebKit only supports 10.4+
+ min_version = None
+
mac_target = 'MACOSX_DEPLOYMENT_TARGET'
- if mac_target in os.environ and os.environ[mac_target] == '10.3':
- os.environ[mac_target] = '10.4'
+ if Options.options.macosx_version != '':
+ min_version = Options.options.macosx_version
- if mac_target in conf.env and conf.env[mac_target] == '10.3':
- conf.env[mac_target] = '10.4'
-
- #conf.env['PREFIX'] = output_dir
+ # WebKit only supports 10.4+, but ppc systems often set this to earlier systems
+ if not min_version:
+ min_version = commands.getoutput('sw_vers -productVersion')[:4]
+ if min_version in ['10.1','10.2','10.3']:
+ min_version = '10.4'
+
+ os.environ[mac_target] = conf.env[mac_target] = min_version
+
+ sdk_version = min_version
+ if min_version == "10.4":
+ sdk_version += "u"
+ conf.env.append_value('LIB', ['WebKitSystemInterfaceTiger'])
+
+ sdkroot = '/Developer/SDKs/MacOSX%s.sdk' % sdk_version
+ sdkflags = ['-arch', 'i386', '-isysroot', sdkroot]
+
+ conf.env.append_value('CPPFLAGS', sdkflags)
+ conf.env.append_value('LINKFLAGS', sdkflags)
+
+ conf.env.append_value('CPPPATH_SQLITE3', [os.path.join(wklibs_dir, 'WebCoreSQLite3')])
+ conf.env.append_value('LIB_SQLITE3', ['WebCoreSQLite3'])
libprefix = ''
if building_on_win32:
@@ -310,7 +338,7 @@ def common_configure(conf):
conf.env.append_value('LIB', [
'kernel32', 'user32','gdi32','comdlg32','winspool','winmm',
'shell32', 'comctl32', 'ole32', 'oleaut32', 'uuid', 'advapi32',
- 'wsock32', 'gdiplus'])
+ 'wsock32', 'gdiplus', 'version'])
conf.env['LIB_ICU'] = ['icudt', 'icule', 'iculx', 'icuuc', 'icuin', 'icuio', 'icutu']
@@ -337,9 +365,10 @@ def common_configure(conf):
conf.check_cfg(msg='Checking for libxslt', path='xslt-config', args='--cflags --libs', package='', uselib_store='XSLT', mandatory=True)
conf.check_cfg(path='xml2-config', args='--cflags --libs', package='', uselib_store='XML', mandatory=True)
- conf.check_cfg(path='curl-config', args='--cflags --libs', package='', uselib_store='CURL', mandatory=True)
- if sys.platform.startswith('darwin'):
- conf.env.append_value('LIB', ['WebCoreSQLite3'])
+ if sys.platform.startswith('darwin') and min_version and min_version == '10.4':
+ conf.check_cfg(path=os.path.join(wklibs_dir, 'unix', 'bin', 'curl-config'), args='--cflags --libs', package='', uselib_store='CURL', mandatory=True)
+ else:
+ conf.check_cfg(path='curl-config', args='--cflags --libs', package='', uselib_store='CURL', mandatory=True)
if not sys.platform.startswith('darwin'):
conf.check_cfg(package='cairo', args='--cflags --libs', uselib_store='WX', mandatory=True)
diff --git a/WebKitTools/wx/install-unix-extras b/WebKitTools/wx/install-unix-extras
index 68d81e4..00c936c 100755
--- a/WebKitTools/wx/install-unix-extras
+++ b/WebKitTools/wx/install-unix-extras
@@ -74,6 +74,12 @@ LIBPNG_VERSION="1.2.33"
LIBPNG_TARBALL="libpng-$LIBPNG_VERSION.tar.gz"
LIBPNG_URL="http://wxwebkit.wxcommunity.com/downloads/deps/$LIBPNG_TARBALL"
+LIBCURL_VERSION="7.19.6"
+LIBCURL_TARBALL="curl-$LIBCURL_VERSION.tar.gz"
+LIBCURL_URL="http://curl.haxx.se/download/$LIBCURL_TARBALL"
+
+export MAC_OS_X_DEPLOYMENT_TARGET=10.4
+
cd $DL_DIR
# build ICU
if [ `which icu-config >/dev/null 2>&1` ]; then
@@ -170,3 +176,25 @@ if [ ! -f $DEPS_PREFIX/lib/libpng.a ]; then
cd $DL_DIR
rm -rf $DL_DIR/libpng-$LIBPNG_VERSION
fi
+
+if [ ! -f $DEPS_PREFIX/lib/libcurl.$DLLEXT ]; then
+ $DL_CMD -o $DL_DIR/$LIBCURL_TARBALL $LIBCURL_URL
+
+ tar xzvf $DL_DIR/$LIBCURL_TARBALL
+ cd $DL_DIR/curl-$LIBCURL_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/curl-$LIBCURL_VERSION
+fi
diff --git a/WebKitTools/wx/packaging/build-mac-installer.py b/WebKitTools/wx/packaging/build-mac-installer.py
new file mode 100644
index 0000000..a0c1b22
--- /dev/null
+++ b/WebKitTools/wx/packaging/build-mac-installer.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2009 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.
+#
+# Script for building Mac .pkg installer
+
+import commands
+import distutils.sysconfig
+import glob
+import optparse
+import os
+import shutil
+import string
+import sys
+import tempfile
+
+script_dir = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.abspath(os.path.join(script_dir, "..", "build")))
+
+from build_utils import *
+
+import wx
+
+wxwk_root = os.path.abspath(os.path.join(script_dir, "..", "..", ".."))
+wxwebkit_dir = os.path.abspath(os.path.join(wxwk_root, "WebKitBuild", get_config(wxwk_root) + git_branch_name()))
+
+wx_version = wx.__version__[:5]
+py_version = sys.version[:3]
+
+wxwk_version = svn_revision()
+
+platform = "osx"
+
+pkgname = "wxWebKit-%s-wx%s-py%s" % (platform, wx_version[:3], py_version)
+
+tempdir = "/tmp/%s" % (pkgname)
+
+if os.path.exists(tempdir):
+ shutil.rmtree(tempdir)
+ os.makedirs(tempdir)
+
+installroot = os.path.join(tempdir, "install-root")
+installapps = os.path.join(tempdir, "install-apps")
+
+sp_root = distutils.sysconfig.get_python_lib()
+wx_root = sp_root
+if sys.platform.startswith("darwin"):
+ wx_root = "/usr/local/lib/wxPython-unicode-%s" % wx.__version__
+ sp_root = "%s/lib/python%s/site-packages" % (wx_root, py_version)
+sitepackages = "%s/wx-%s-mac-unicode/wx" % (sp_root, wx_version[:3])
+prefix = sitepackages
+
+def mac_update_dependencies(dylib, prefix):
+ """
+ Copies any non-system dependencies into the bundle, and
+ updates the install name path to the new path in the bundle.
+ """
+ global wx_root
+ system_prefixes = ["/usr/lib", "/System/Library", wx_root]
+
+ output = commands.getoutput("otool -L %s" % dylib).strip()
+ for line in output.split("\n"):
+ filename = line.split("(")[0].strip()
+ if os.path.exists(filename):
+ print "checking dll %s" % filename
+ copy = True
+ for sys_prefix in system_prefixes:
+ if filename.startswith(sys_prefix):
+ copy = False
+
+ if copy:
+ copydir = os.path.dirname(dylib)
+
+ filedir, basename = os.path.split(filename)
+ dest_filename = os.path.join(prefix, basename)
+ copyname = os.path.join(copydir, basename)
+ if not os.path.exists(copyname):
+ shutil.copy(filename, copydir)
+ os.system("install_name_tool -id %s %s" % (dest_filename, copyname))
+
+ os.system("install_name_tool -change %s %s %s" % (filename, dest_filename, dylib))
+
+def exitIfError(cmd):
+ print cmd
+ retval = os.system(cmd)
+ if retval != 0:
+ if os.path.exists(tempdir):
+ shutil.rmtree(tempdir)
+ sys.exit(1)
+
+wxroot = installroot + prefix
+wxpythonroot = installroot + sitepackages
+
+try:
+ if not os.path.exists(wxroot):
+ os.makedirs(wxroot)
+
+ if not os.path.exists(wxpythonroot):
+ os.makedirs(wxpythonroot)
+
+ for wildcard in ["*.py", "*.so", "*.dylib"]:
+ files = glob.glob(os.path.join(wxwebkit_dir, wildcard))
+ for afile in files:
+ shutil.copy(afile, wxpythonroot)
+
+ if sys.platform.startswith("darwin"):
+ dylib_path = os.path.join(wxpythonroot, "libwxwebkit.dylib")
+ os.system("install_name_tool -id %s %s" % (os.path.join(prefix, "libwxwebkit.dylib"), dylib_path))
+ mac_update_dependencies(dylib_path, prefix)
+ mac_update_dependencies(os.path.join(wxpythonroot, "_webview.so"), prefix)
+
+ demodir = installroot + "/Applications/wxWebKit/Demos"
+ if not os.path.exists(demodir):
+ os.makedirs(demodir)
+
+ shutil.copy(os.path.join(wxwk_root, "WebKit", "wx", "bindings", "python", "samples", "simple.py"), demodir)
+
+ if os.path.exists(pkgname + ".pkg"):
+ shutil.rmtree(pkgname + ".pkg")
+
+ pkg_args = ['--title ' + pkgname,
+ '--out %s.pkg' % pkgname,
+ '--version ' + wxwk_version.strip(),
+ '--id org.wxwebkit.wxwebkit',
+ '--domain system',
+ '--root-volume-only',
+ '--root ' + installroot,
+ '--resources %s/mac/resources' % script_dir,
+ '--verbose'
+ ]
+
+ packagemaker = "/Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker"
+ exitIfError(packagemaker + " %s" % (string.join(pkg_args, " ")))
+finally:
+ if os.path.exists(tempdir):
+ shutil.rmtree(tempdir)
diff --git a/WebKitTools/wx/packaging/build-win-installer.py b/WebKitTools/wx/packaging/build-win-installer.py
index beed705..2bb8034 100644
--- a/WebKitTools/wx/packaging/build-win-installer.py
+++ b/WebKitTools/wx/packaging/build-win-installer.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# Copyright (C) 2008 Kevin Ollivier All rights reserved.
#
@@ -30,6 +30,14 @@ import commands
import glob
from subprocess import *
+script_dir = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.abspath(os.path.join(script_dir, "..", "build")))
+
+from build_utils import *
+
+wxwk_root = os.path.abspath(os.path.join(script_dir, "..", "..", ".."))
+wxwebkit_dir = os.path.abspath(os.path.join(wxwk_root, "WebKitBuild", get_config(wxwk_root) + git_branch_name()))
+
# Find InnoSetup executable
def getInnoSetupPath():
name = "ISCC.exe"
@@ -37,6 +45,7 @@ def getInnoSetupPath():
dirs = os.environ["PATH"].split(":")
# Add the default file path
dirs.append("C:\\Program Files\\Inno Setup 5")
+ dirs.append("C:\\Program Files (x86)\\Inno Setup 5")
if os.environ.has_key("INNO5"):
retval = os.environ["INNO5"]
@@ -48,40 +57,19 @@ def getInnoSetupPath():
retval = filepath
return retval
-
-def getWebKitOutputDir():
- retval = ""
- if os.environ.has_key("WEBKITOUTPUTDIR"):
- retval = os.environ["WEBKITOUTPUTDIR"]
-
- if retval == "":
- retval = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "WebKitBuild"))
-
- return os.path.join(retval, "Release")
-
-def getRevisionString():
- pipe = Popen("svnversion", shell=True, stdout=PIPE).stdout
- svnrevision = pipe.read().strip()
- print "r" + svnrevision
- svnrevision = string.split(svnrevision, ":")[0]
- svnrevision = svnrevision.replace("M", "")
- svnrevision = "r" + svnrevision
-
- return svnrevision
if __name__ == "__main__":
innoSetup = getInnoSetupPath()
- buildDir = getWebKitOutputDir()
os.chdir(sys.path[0])
- svnrevision = getRevisionString()
+ svnrevision = svn_revision()
if not os.path.exists(innoSetup):
print "ERROR: Cannot find InnoSetup."
#sys.exit(1)
- if not os.path.exists(buildDir):
- print "ERROR: Build dir %s doesn't exist." % buildDir
+ if not os.path.exists(wxwebkit_dir):
+ print "ERROR: Build dir %s doesn't exist." % wxwebkit_dir
sys.exit(1)
fileList = """
@@ -89,7 +77,7 @@ CopyMode: alwaysoverwrite; Source: *.pyd; DestDir: "{app}"
CopyMode: alwaysoverwrite; Source: *.py; DestDir: "{app}"
"""
- dlls = glob.glob(os.path.join(buildDir, "*.dll"))
+ dlls = glob.glob(os.path.join(wxwebkit_dir, "*.dll"))
for dll in dlls:
if dll.find("wxbase") == -1 and dll.find("wxmsw") == -1:
fileList += """CopyMode: alwaysoverwrite; Source: %s; DestDir: "{app}" \n""" % dll
@@ -97,8 +85,8 @@ CopyMode: alwaysoverwrite; Source: *.py; DestDir: "{app}"
installerTemplate = open("wxWebKitInstaller.iss.in", "r").read()
installerTemplate = installerTemplate.replace("<<VERSION>>", svnrevision)
- installerTemplate = installerTemplate.replace("<<ROOTDIR>>", buildDir )
- installerTemplate = installerTemplate.replace("<<PYTHONVER>>", "2.5" )
+ installerTemplate = installerTemplate.replace("<<ROOTDIR>>", wxwebkit_dir )
+ installerTemplate = installerTemplate.replace("<<PYTHONVER>>", sys.version[0:3] )
installerTemplate = installerTemplate.replace("<<FILES>>", fileList )
outputFile = open("wxWebKitInstaller.iss", "w")
diff --git a/WebKitTools/wx/packaging/wxWebKitInstaller.iss.in b/WebKitTools/wx/packaging/wxWebKitInstaller.iss.in
index a2c808c..ebc89d4 100644
--- a/WebKitTools/wx/packaging/wxWebKitInstaller.iss.in
+++ b/WebKitTools/wx/packaging/wxWebKitInstaller.iss.in
@@ -17,7 +17,7 @@ UninstallFilesDir={app}\Uninstall
Compression=bzip/9
SourceDir=<<ROOTDIR>>
OutputDir=win-installer
-OutputBaseFilename=wxWebKit-Py<<PYTHONVER>>-<<VERSION>>
+OutputBaseFilename=wxWebKit-wx2.8-Py<<PYTHONVER>>-<<VERSION>>
DisableStartupPrompt=yes
AllowNoIcons=yes
DisableProgramGroupPage=yes