diff options
Diffstat (limited to 'WebKitTools')
103 files changed, 3988 insertions, 766 deletions
diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json index f4b0822..eda05f1 100644 --- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/config.json @@ -14,6 +14,7 @@ { "name": "apple-macpro-1", "platform": "mac-snowleopard" }, { "name": "apple-macpro-2", "platform": "mac-snowleopard" }, { "name": "apple-macpro-3", "platform": "mac-snowleopard" }, + { "name": "apple-macpro-4", "platform": "mac-leopard" }, { "name": "apple-windows-1", "platform": "win"}, { "name": "apple-windows-2", "platform": "win"}, @@ -51,7 +52,7 @@ }, { "name": "Leopard Intel Release (Tests)", "type": "Test", "builddir": "leopard-intel-release-tests", "platform": "mac-leopard", "configuration": "release", "architectures": ["i386"], - "slavenames": ["apple-pixel-1", "test-slave"] + "slavenames": ["apple-macpro-4", "apple-pixel-1", "test-slave"] }, { "name": "Leopard Intel Debug (Build)", "type": "Build", "builddir": "leopard-intel-debug", diff --git a/WebKitTools/BuildSlaveSupport/test-result-archive b/WebKitTools/BuildSlaveSupport/test-result-archive index df02dbd..af66bf0 100644 --- a/WebKitTools/BuildSlaveSupport/test-result-archive +++ b/WebKitTools/BuildSlaveSupport/test-result-archive @@ -23,10 +23,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import optparse, os, shutil, subprocess, sys +import optparse, os, shutil, subprocess, sys, zipfile sourceRootDirectory = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) -layoutTestResultsDir = os.path.abspath(os.path.join(sourceRootDirectory, "layout-test-results")) archiveFile = os.path.join(sourceRootDirectory, "layout-test-results.zip") def main(): @@ -43,9 +42,16 @@ def main(): if action not in ('archive'): parser.error("Action is required") - return archiveTestResults(options.configuration, options.platform) + layoutTestResultsDir = os.path.abspath(os.path.join(sourceRootDirectory, "layout-test-results")) + if options.platform == 'chromium': + # See results_directory() in webkitpy/layout_tests/port/chromium.py. + layoutTestResultsDir = os.path.abspath(os.path.join(sourceRootDirectory, + "WebKit", "chromium", "webkit", options.configuration.capitalize(), + "layout-test-results")) -def archiveTestResults(configuration, platform): + return archiveTestResults(options.configuration, options.platform, layoutTestResultsDir) + +def archiveTestResults(configuration, platform, layoutTestResultsDir): assert platform in ('mac', 'win', 'gtk', 'qt', 'chromium') try: @@ -66,9 +72,14 @@ def archiveTestResults(configuration, platform): if platform == 'mac': if subprocess.call(["ditto", "-c", "-k", "--sequesterRsrc", layoutTestResultsDir, archiveFile]): return 1 - elif platform in ('win', 'gtk', 'qt', 'chromium'): + elif platform in ('win', 'gtk', 'qt'): if subprocess.call(["zip", "-r", archiveFile, "."], cwd=layoutTestResultsDir): return 1 + elif platform == 'chromium': + cwd = os.getcwd() + os.chdir(layoutTestResultsDir) + zipFilesRecursively(archiveFile, ["."]) + os.chdir(cwd) try: shutil.rmtree(layoutTestResultsDir) @@ -82,5 +93,26 @@ def archiveTestResults(configuration, platform): if e.errno != 90: raise +def zipFilesRecursively(archiveFile, files): + """Make a zip archive. + + Args: + archiveFile: The resultant zip archive file name. + files: A list of files to be archived. If a list item is a directory, + files in the directory are archived recursively.""" + zipper = zipfile.ZipFile(archiveFile, 'w', zipfile.ZIP_DEFLATED) + for file in files: + if os.path.isdir(file): + for dirPath, dirNames, fileNames in os.walk(file): + for fileName in fileNames: + relativePath = os.path.join(dirPath, fileName) + print "Adding", relativePath + zipper.write(relativePath) + else: + print "Adding", file + zipper.write(file) + zipper.close() + print "Created zip archive: ", archiveFile + if __name__ == '__main__': sys.exit(main()) diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog index 987fe7c..e911169 100644 --- a/WebKitTools/ChangeLog +++ b/WebKitTools/ChangeLog @@ -1,3 +1,997 @@ +2010-08-09 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Ariya Hidayat. + + [Qt] QtTestBrowser: proper set scene rect + + When resizesToContents is ON scene's rect is set to the boundary of + the mainFrame. However, navigating to other web page should keep resizing + scene's rect according to the new document loaded. Patch addresses this issue. + + Now resizesToContents and scrolling properly work on QtTestBrowser. + + * QtTestBrowser/webview.cpp: + (WebViewGraphicsBased::setPage): + (WebViewGraphicsBased::contentsSizeChanged): + (WebViewGraphicsBased::setResizesToContents): + (WebViewGraphicsBased::resizeEvent): + * QtTestBrowser/webview.h: + +2010-08-09 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Ariya Hidayat. + + [Qt] QtTestBrowser: Clean up LauncherWindow code. + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::LauncherWindow): Moves applyPrefs methods call from the constructor to init(). + (LauncherWindow::init): Fixed comments. + (LauncherWindow::applyPrefs): Move the method around. + (LauncherWindow::createChrome): Move more code of this method around, for grouping, and fixing up comments. + +2010-08-09 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Ariya Hidayat. + + [Qt] QtTestBrowser: make reset-zooming to animate when tiled backing store is on. + + It gets control+0 the same visual effect as control++ or control-. + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::toggleZoomTextOnly): + +2010-08-09 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Ariya Hidayat. + + [Qt] QtTestBrowser:: make m_zoomLevels a static member. + + Not all instances of LauncherWindow need its own m_zoomLevel. + + * QtTestBrowser/launcherwindow.cpp: + * QtTestBrowser/launcherwindow.h: + +2010-08-09 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Add zoom support for injected bundle + https://bugs.webkit.org/show_bug.cgi?id=43759 + + Use zoom factor SPI to implement zoom related eventSender functions. + + * WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl: + * WebKitTestRunner/InjectedBundle/EventSendingController.cpp: + (WTR::EventSendingController::textZoomIn): + (WTR::EventSendingController::textZoomOut): + (WTR::EventSendingController::zoomPageIn): + (WTR::EventSendingController::zoomPageOut): + * WebKitTestRunner/InjectedBundle/EventSendingController.h: + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::reset): Reset zoom mode and level for each test. + +2010-08-09 Gavin Barraclough <barraclough@apple.com> + + Speculative chromium build fix III. + + * DumpRenderTree/chromium/MockSpellCheck.h: + * DumpRenderTree/chromium/NotificationPresenter.h: + * DumpRenderTree/chromium/WebViewHost.h: + (WebViewHost::addClearHeader): + (WebViewHost::clearHeaders): + +2010-08-09 Ojan Vafai <ojan@chromium.org> + + Reviewed by Tony Chang. + + increase the number of test results that we save + https://bugs.webkit.org/show_bug.cgi?id=43763 + + Now that we do incremental uploads, we can increase the number of + results that we save for http://test-results.appspot.com/dashboards/flakiness_dashboard.html. + + * Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py: + +2010-08-09 Evan Martin <evan@chromium.org> + + Reviewed by Tony Chang. + + [chromium] DRT error print statement incorrectly tries to print a FILE* + https://bugs.webkit.org/show_bug.cgi?id=43747 + + * DumpRenderTree/chromium/ImageDiff.cpp: + (writeFile): pass the correct pointer. + +2010-08-09 Victor Wang <victorw@chromium.org> + + Reviewed by Ojan Vafai. + + Upload incremental test results json to server by default. + + https://bugs.webkit.org/show_bug.cgi?id=43743 + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-08-09 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + EWS bots wait 2 minutes between patches + https://bugs.webkit.org/show_bug.cgi?id=43731 + + * Scripts/webkitpy/tool/bot/queueengine.py: + - Don't sleep after failures. This was a hold-over from + an earlier design. + * Scripts/webkitpy/tool/commands/earlywarningsystem.py: + - EWS bots were not properly reporting true/false from process_work_item. + They were always returning None, thus false, thus always logging + as a failure and sleeping 2 minutes after each patch. + +2010-08-09 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Stub out EventSender for WebKitTestRunner + https://bugs.webkit.org/show_bug.cgi?id=43703 + + * WebKitTestRunner/DerivedSources.make: + * WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm: + Add ability to pass javascript arguments to the wrapped object. + + * WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl: Added. + * WebKitTestRunner/InjectedBundle/EventSendingController.cpp: Added. + (WTR::EventSendingController::create): + (WTR::EventSendingController::EventSendingController): + (WTR::EventSendingController::~EventSendingController): + (WTR::EventSendingController::wrapperClass): + (WTR::setExceptionForString): + (WTR::EventSendingController::mouseDown): + (WTR::EventSendingController::mouseUp): + (WTR::EventSendingController::mouseMoveTo): + (WTR::EventSendingController::keyDown): + (WTR::EventSendingController::contextClick): + (WTR::EventSendingController::leapForward): + (WTR::EventSendingController::textZoomIn): + (WTR::EventSendingController::textZoomOut): + (WTR::EventSendingController::zoomPageIn): + (WTR::EventSendingController::zoomPageOut): + (WTR::EventSendingController::makeWindowObject): + * WebKitTestRunner/InjectedBundle/EventSendingController.h: Added. + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + (WTR::InjectedBundle::reset): + * WebKitTestRunner/InjectedBundle/InjectedBundle.h: + (WTR::InjectedBundle::eventSendingController): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::didClearWindowForFrame): + Add stubbed out EventSenderController. + + * WebKitTestRunner/InjectedBundle/GCController.h: + Remove incorrect comment. + + * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj: + * WebKitTestRunner/win/InjectedBundle.vcproj: + Add new files. + +2010-08-08 Kent Tamura <tkent@chromium.org> + + Unreviewed, trivial fix. + + Fix "WindowsError: [Error 32] The process cannot access the file + because it is being used by another process" introduced by r64959. + + * BuildSlaveSupport/test-result-archive: + +2010-08-08 Kent Tamura <tkent@chromium.org> + + Reviewed by Tony Chang. + + Chromium buildbot: Avoid "zip" command dependency + https://bugs.webkit.org/show_bug.cgi?id=43470 + + * BuildSlaveSupport/test-result-archive: + For Chromium port, creates a zip archive with zipfile package of Python + instead of external "zip" command. We'd like to avoid additional + command installation. + +2010-08-08 Jon Honeycutt <jhoneycutt@apple.com> + + WebKitTestRunner should add the QuickTime dir to the PATH environment + variable + https://bugs.webkit.org/show_bug.cgi?id=43686 + + Reviewed by Dan Bernstein. + + * WebKitTestRunner/win/TestControllerWin.cpp: + (WTR::addQTDirToPATH): + Copied from DRT. + (WTR::TestController::platformInitialize): + Call addQTDirToPath(). + * WebKitTestRunner/win/WebKitTestRunner.vcproj: + Link to shlwapi.lib for SHGetValue. + +2010-08-07 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + WebKitTestRunner needs layoutTestController.dumpTitleChanges + <rdar://problem/8213861> + https://bugs.webkit.org/show_bug.cgi?id=42683 + + * WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl: + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::didReceiveTitleForFrame): + (WTR::InjectedBundlePage::didFinishDocumentLoadForFrame): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + (WTR::LayoutTestController::LayoutTestController): + * WebKitTestRunner/InjectedBundle/LayoutTestController.h: + (WTR::LayoutTestController::dumpTitleChanges): + (WTR::LayoutTestController::shouldDumpTitleChanges): + +2010-08-07 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + WebKitTestRunner needs to print onunload handler information + <rdar://problem/8213831> + https://bugs.webkit.org/show_bug.cgi?id=42703 + + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::operator<<): + (WTR::InjectedBundlePage::didFinishDocumentLoadForFrame): + +2010-08-07 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Add additional loader client functions need to complete WebKitTestRunner + https://bugs.webkit.org/show_bug.cgi?id=43684 + + Remove unnecessary and jarring underscores as well. + + * MiniBrowser/mac/WebBundle/WebBundleMain.m: + (didClearWindowObjectForFrame): + (didCreatePage): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::InjectedBundlePage): + (WTR::InjectedBundlePage::didStartProvisionalLoadForFrame): + (WTR::InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame): + (WTR::InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame): + (WTR::InjectedBundlePage::didCommitLoadForFrame): + (WTR::InjectedBundlePage::didFinishLoadForFrame): + (WTR::InjectedBundlePage::didFailLoadWithErrorForFrame): + (WTR::InjectedBundlePage::didReceiveTitleForFrame): + (WTR::InjectedBundlePage::didClearWindowForFrame): + (WTR::InjectedBundlePage::didCancelClientRedirectForFrame): + (WTR::InjectedBundlePage::willPerformClientRedirectForFrame): + (WTR::InjectedBundlePage::didChangeLocationWithinPageForFrame): + (WTR::InjectedBundlePage::didFinishDocumentLoadForFrame): + (WTR::InjectedBundlePage::didHandleOnloadEventsForFrame): + (WTR::InjectedBundlePage::didDisplayInsecureContentForFrame): + (WTR::InjectedBundlePage::didRunInsecureContentForFrame): + (WTR::InjectedBundlePage::willAddMessageToConsole): + (WTR::InjectedBundlePage::willSetStatusbarText): + (WTR::InjectedBundlePage::willRunJavaScriptAlert): + (WTR::InjectedBundlePage::willRunJavaScriptConfirm): + (WTR::InjectedBundlePage::willRunJavaScriptPrompt): + (WTR::InjectedBundlePage::shouldBeginEditing): + (WTR::InjectedBundlePage::shouldEndEditing): + (WTR::InjectedBundlePage::shouldInsertNode): + (WTR::InjectedBundlePage::shouldInsertText): + (WTR::InjectedBundlePage::shouldDeleteRange): + (WTR::InjectedBundlePage::shouldChangeSelectedRange): + (WTR::InjectedBundlePage::shouldApplyStyle): + (WTR::InjectedBundlePage::didBeginEditing): + (WTR::InjectedBundlePage::didEndEditing): + (WTR::InjectedBundlePage::didChange): + (WTR::InjectedBundlePage::didChangeSelection): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.h: + +2010-08-07 Dan Bernstein <mitz@apple.com> + + Build fix. + + * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj: Made the references + to JSGCController.{cpp,h} relative to the build root. + +2010-08-07 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + WebKitTestRunner needs GCController + <rdar://problem/8213834> + https://bugs.webkit.org/show_bug.cgi?id=42701 + + * WebKitTestRunner/DerivedSources.make: + * WebKitTestRunner/InjectedBundle/Bindings/GCController.idl: Added. + * WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h: + (WTR::setProperty): + * WebKitTestRunner/InjectedBundle/GCController.cpp: Added. + (WTR::GCController::create): + (WTR::GCController::GCController): + (WTR::GCController::~GCController): + (WTR::GCController::wrapperClass): + (WTR::GCController::collect): + (WTR::GCController::collectOnAlternateThread): + (WTR::GCController::getJSObjectCount): + (WTR::GCController::makeWindowObject): + * WebKitTestRunner/InjectedBundle/GCController.h: Added. + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + (WTR::InjectedBundle::reset): + * WebKitTestRunner/InjectedBundle/InjectedBundle.h: + (WTR::InjectedBundle::bundle): + (WTR::InjectedBundle::gcController): + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::didClearWindowForFrame): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + (WTR::LayoutTestController::keepWebHistory): + * WebKitTestRunner/InjectedBundle/LayoutTestController.h: + * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj: + * WebKitTestRunner/win/InjectedBundle.vcproj: + +2010-08-05 Jon Honeycutt <jhoneycutt@apple.com> + + WebKitTestRunner needs to be able to set the font smoothing type + https://bugs.webkit.org/show_bug.cgi?id=43406 + + Reviewed by Adam Roben. + + * WebKitTestRunner/TestInvocation.cpp: + (WTR::TestInvocation::resetPreferencesToConsistentValues): + Set the font smoothing level to + kWKFontSmoothingLevelNoSubpixelAntiAliasing to match DRT. + +2010-08-06 Jon Honeycutt <jhoneycutt@apple.com> + + Fix a missed variable rename. + + Unreviewed. + + * Scripts/old-run-webkit-tests: + +2010-08-06 Jon Honeycutt <jhoneycutt@apple.com> + + mac-wk2/Skipped should be used on Windows when running regression tests + https://bugs.webkit.org/show_bug.cgi?id=43494 + + Reviewed by Adam Roben. + + * Scripts/old-run-webkit-tests: + If the platform is win-wk2, also read the mac-wk2 skipped list. + +2010-08-06 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + [DRT/Chromium] Should revoke scheduled tasks + https://bugs.webkit.org/show_bug.cgi?id=43560 + + * DumpRenderTree/chromium/DRTDevToolsAgent.cpp: + (DRTDevToolsAgent::reset): Calls RevokeAll(). + * DumpRenderTree/chromium/DRTDevToolsAgent.h: + * DumpRenderTree/chromium/DRTDevToolsClient.cpp: + (DRTDevToolsClient::reset): Calls RevokeAll(). + * DumpRenderTree/chromium/DRTDevToolsClient.h: + * DumpRenderTree/chromium/EventSender.cpp: + (EventSender::reset): Calls RevokeAll(). + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::reset): Calls RevokeAll(). + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::resetTestController): Calls DRTDevToolsAgent::reset() and DRTDevToolsClient::reset(). + +2010-08-06 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Antonio Gomes. + + [Qt] Fix the DRT build on Mac OS X + + * DumpRenderTree/qt/DumpRenderTree.pro: + +2010-08-06 Jochen Eisinger <jochen@chromium.org> + + Reviewed by Pavel Feldman. + + Rietvield's upload.py moved to a different location. + https://bugs.webkit.org/show_bug.cgi?id=43613 + + * Scripts/webkitpy/thirdparty/__init__.py: + +2010-05-23 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + QueueStatusServer needs better queue-status pages + https://bugs.webkit.org/show_bug.cgi?id=39562 + + The primary goal of this patch is to display queue + positions somewhere on the site so that it's easier + for commit-queue users to know when their pach will + be landed. I also tried to improve the root page + to be more useful than the previous wall of status text. + + * QueueStatusServer/handlers/recentstatus.py: + * QueueStatusServer/main.py: + * QueueStatusServer/model/queues.py: + * QueueStatusServer/templates/recentstatus.html: + +2010-08-05 Victor Wang <victorw@chromium.org> + + Reviewed by Ojan Vafai. + + Add option to generate/upload incremental json results to test result server. + Also refactor the json results generator unittest code to test + incremental and aggregated json results. + + https://bugs.webkit.org/show_bug.cgi?id=43519 + + * Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py: + * Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py: + * Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-08-05 Jian Li <jianli@chromium.org> + + Reviewed by David Levin. + + Unify blob related feature defines to ENABLE(BLOB). + https://bugs.webkit.org/show_bug.cgi?id=43081 + + * Scripts/build-webkit: + +2010-08-05 Satish Sampath <satish@chromium.org> + + Reviewed by Jeremy Orlow. + + Add speech input controller mock in WebKit and a layout test. + https://bugs.webkit.org/show_bug.cgi?id=43477 + + Added LayoutTestController::setMockSpeechInputResultCallback method. + + * DumpRenderTree/LayoutTestController.cpp: + (setMockSpeechInputResultCallback): Wrapper invoking the member function. + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::setMockSpeechInputResult): Sets the mock result. + (LayoutTestController::speechInputController): Creates the mock controller. + * DumpRenderTree/chromium/LayoutTestController.h: + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::speechInputController): Creates the mock controller. + * DumpRenderTree/chromium/WebViewHost.h: + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setMockSpeechInputResult): dummy method. + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setMockSpeechInputResult): dummy method. + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::setMockSpeechInputResult): dummy method. + * DumpRenderTree/qt/LayoutTestControllerQt.h: + * DumpRenderTree/win/LayoutTestControllerWin.cpp: dummy method. + (LayoutTestController::setMockSpeechInputResult): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: dummy method. + (LayoutTestController::setMockSpeechInputResult): + +2010-08-04 Adam Roben <aroben@apple.com> + + Fix the path to TestNetscapePlugin's directory on Windows + + Fixes <http://webkit.org/b/43513> WebKitTestRunner on Windows fails to + load TestNetscapePlugin + + Reviewed by Jon Honeycutt. + + * WebKitTestRunner/win/TestControllerWin.cpp: + (WTR::TestController::initializeTestPluginDirectory): + TestNetscapePlugin is in a TestNetscapePlugin[_Debug] directory that's + next to WebKitTestRunner.exe. Previously we were passing the directory + that contains WebKitTestRunner.exe. Also fixed some leaks. + +2010-08-05 Kenichi Ishibashi <bashi@google.com> + + Reviewed by Shinichiro Hamaji. + + check-webkit-style returns non-zero when patch is entirely minus lines. + https://bugs.webkit.org/show_bug.cgi?id=38169 + + * Scripts/check-webkit-style: + Check whether a patch contains modified files that are entirely minus lines. + * Scripts/webkitpy/style/filereader.py: + Add a variable that holds number of files that contain only deleted lines. + * Scripts/webkitpy/style/patchreader.py: + Count up modified files that contain only deleted lines. + +2010-08-05 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Yury Semikhatsky. + + DevTools: get rid of delayed command dispatching on front-end side. + + https://bugs.webkit.org/show_bug.cgi?id=43479 + + * DumpRenderTree/chromium/DRTDevToolsAgent.cpp: + (DRTDevToolsAgent::detach): + (DRTDevToolsAgent::frontendLoaded): + * DumpRenderTree/chromium/DRTDevToolsAgent.h: + * DumpRenderTree/chromium/DRTDevToolsClient.cpp: + (DRTDevToolsClient::~DRTDevToolsClient): + (DRTDevToolsClient::sendFrontendLoaded): + * DumpRenderTree/chromium/DRTDevToolsClient.h: + +2010-08-04 Kenichi Ishibashi <bashi@google.com> + + Reviewed by Shinichiro Hamaji. + + Fixes check-webkit-style false positive on "new uint32_t." + https://bugs.webkit.org/show_bug.cgi?id=43077 + + * Scripts/webkitpy/style/checkers/cpp.py: + * Scripts/webkitpy/style/checkers/cpp_unittest.py: + +2010-08-04 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + [DRT/Chromium] Remove base/linked_ptr.h dependency + https://bugs.webkit.org/show_bug.cgi?id=43472 + + Replace linked_ptr<TestNavigationEntry> with RefPtr<TestNavigationEntry>. + We need to use RefPtr<> because m_pendingEntry points an object in + m_entries or not in m_entries. + + * DumpRenderTree/chromium/TestNavigationController.cpp: + (TestNavigationEntry::create): Added. + (TestNavigationController::activeEntry): + (TestNavigationController::didNavigateToEntry): + (TestNavigationController::discardPendingEntry): + (TestNavigationController::insertEntry): + (TestNavigationController::navigateToPendingEntry): + * DumpRenderTree/chromium/TestNavigationController.h: + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::loadURLForFrame): + Use TestNavigationEntry::create(). + (WebViewHost::updateURL): + Use RefPtr<>. + (WebViewHost::updateSessionHistory): + Remove unnecessary static_cast<>. + +2010-08-04 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + Fix a problem that "archived test results" step doesn't work on Chromium buildbots + https://bugs.webkit.org/show_bug.cgi?id=43333 + + * BuildSlaveSupport/test-result-archive: + - Make layoutTestResultsDir local and pass it to archiveTestResults() + - Adjust layoutTestResultsDir for Chromium + +2010-08-04 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + NRWT: websocket_server startup detection failure + https://bugs.webkit.org/show_bug.cgi?id=43466 + + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + Increase timeout value: 5 second -> 10 second + +2010-08-04 Victor Wang <victorw@chromium.org> + + Reviewed by Ojan Vafai. + + -. Add result.json incremental merging functionality to test results app engine. + -. blobstore is not suitable for AE data merging and there is no API to + programatically edit existing blob or write a new one yet, so replace blobstore + with datastore. If file is oversize (>1000*1000 bytes), store file data in + multiple datastore entries. + -. Fix styles. + + Test: jsonresults_unittest to test merging logics. + + https://bugs.webkit.org/show_bug.cgi?id=38599 + + * TestResultServer/handlers/dashboardhandler.py: + * TestResultServer/handlers/menu.py: + * TestResultServer/handlers/testfilehandler.py: + * TestResultServer/main.py: + * TestResultServer/model/dashboardfile.py: + * TestResultServer/model/datastorefile.py: Added. + * TestResultServer/model/jsonresults.py: Added. + * TestResultServer/model/jsonresults_unittest.py: Added. + * TestResultServer/model/testfile.py: + * TestResultServer/templates/uploadform.html: + +2010-08-04 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Kenneth Christiansen. + + [Qt] [QtTestBrowser] Remove unneeded QAction class members + https://bugs.webkit.org/show_bug.cgi?id=43518 + + LauncherWindow class has two totally unneeded class members: m_flopAnimated and + m_flipYAnimated. Also, in initializeView method there are some dead code block + trying to connect them at the wrong time, when they have not been instanciated. + + This patch: + + - removes the two cited class members in favor of local variables in createChrome method; + - removes the dead code block. + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::LauncherWindow): + (LauncherWindow::initializeView): + (LauncherWindow::createChrome): + * QtTestBrowser/launcherwindow.h: + +2010-08-04 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Simon Hausmann and Kenneth Christiansen. + + [Qt] [QtTestBrowser] Clean up static and global menu state controls + https://bugs.webkit.org/show_bug.cgi?id=43448 + + After LauncherWindow class was refactored out of from main.cpp, all global variables that + were hanging in main.cpp became temporarily public static class members of newly added + LauncherWindow class. This design was not properly handling the initial purpose of the + global variables: newly created launcher windows should inherit the settings of the originating + one. + + In order to properly fix the problem, this patch introduces a WindowOptions class, as a POD. It + comprises all data needed to handling the goal described above. + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::LauncherWindow): The class now receives an optional WindowOptions pointer object + holding all user settings configured in the menus and command line. + It also receices an optional QGraphicsScene points in case we are doing + a "Clone Window". + (LauncherWindow::init): Removed the usesGraphics parameter because the class member m_userData holds its + value. + (LauncherWindow::initializeView): Ditto. + (LauncherWindow::createChrome): Changed all references to gXXX to m_userData.XXX + (LauncherWindow::applyPrefs): Removed the "LauncherWindow* source" parameter. All data needed to properly + apply the preferences is provided by m_userData. + (LauncherWindow::toggleAcceleratedCompositing): Change gXXX by m_userData.XXX + (LauncherWindow::toggleResizesToContents): Ditto. + (LauncherWindow::toggleWebGL): Ditto. + (LauncherWindow::toggleFrameFlattening): Ditto. + (LauncherWindow::toggleQGLWidgetViewport): Ditto. + (LauncherWindow::changeViewportUpdateMode): Ditto. + (LauncherWindow::showFPS): Ditto. + (LauncherWindow::newWindow): Changed to pass the userData. + (LauncherWindow::cloneWindow): Ditto. + * QtTestBrowser/launcherwindow.h: + (WindowOptions::WindowOptions): + * QtTestBrowser/main.cpp: + (requiresGraphicsView): + (LauncherApplication::handleUserOptions): + (main): + +2010-08-04 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Build fix for gcc not importing all symbols from convenience libraries. + Works on 10.6 only for Mac until the build system is reworked. + + * wx/build/settings.py: + +2010-08-04 Markus Goetz <Markus.Goetz@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Change wording in QtTestBrowser + https://bugs.webkit.org/show_bug.cgi?id=43241 + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::createChrome): + +2010-08-04 Aaron Boodman <aa@chromium.org> + + Reviewed by Eric Seidel. + + prepare-ChangeLog fails mysteriously if curl doesn't support ssl + https://bugs.webkit.org/show_bug.cgi?id=43460 + + * Scripts/prepare-ChangeLog: + +2010-08-03 MORITA Hajime <morrita@google.com> + + Reviewed by Tony Chang. + + [DRT] Assertion failed when drag and move a draggable element. + https://bugs.webkit.org/show_bug.cgi?id=41695 + + mouseMoveToX() did call [WebHTMLView mouseDragged] even if dragging started. + But Cocoa doesn't call mouseDragged() until dragging is done. + Other part of DumpRenderTree also assumes Cocoa behavior and an assertion + on UIDelegate failed when mouseDragged() is called during dragging. + This change eliminated the mouseDragged() call when dragging begins, + which is implicated by draggingInfo instance. + + * DumpRenderTree/mac/EventSendingController.mm: + (-[EventSendingController mouseMoveToX:Y:]): + + Test: fast/events/dragging-mouse-moves.html + +2010-08-02 Steve Block <steveblock@google.com> + + Reviewed by Alexey Proskuryakov. + + Adds Geolocation LayoutTests for the case where permission is not granted or denied immediately + https://bugs.webkit.org/show_bug.cgi?id=40002 + + The code in LayoutTestController::setGeolocationPermission() was moved to + setGeolocationPermissionCommon() to allow each port to provide its own + implementation of setGeolocationPermission(). + + For the Mac port, setGeolocationPermission() notifies the UIDelegate of the + new permission, so it can call back to WebCore if permission requests are in + progress and are waiting for a response. A minor fix to the Mac + MockGeolocationProvider was also required to make sure that the mock provider + calls back to WebCore when it is first started. + + For other ports, LayoutTestController::setGeolocationPermission() is not + implemented. + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::setGeolocationPermissionCommon): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setGeolocationPermission): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setGeolocationPermission): + * DumpRenderTree/mac/MockGeolocationProvider.mm: + (-[MockGeolocationProvider registerWebView:]): + * DumpRenderTree/mac/UIDelegate.h: + * DumpRenderTree/mac/UIDelegate.mm: + (-[UIDelegate webView:decidePolicyForGeolocationRequestFromOrigin:frame:listener:]): + (-[UIDelegate setGeolocationPermission:]): + (-[UIDelegate dealloc]): + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + (LayoutTestController::setGeolocationPermission): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::setGeolocationPermission): + +2010-08-03 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + [DRT/Chromium] Implement --testshell-startup-dialog + https://bugs.webkit.org/show_bug.cgi?id=40616 + + * DumpRenderTree/chromium/DumpRenderTree.cpp: + (main): Check --testshell-startup-dialog, and call openStartUpDialog() + if it is specfied. + * DumpRenderTree/chromium/TestShell.h: + Declare openStartUpDialog(). + * DumpRenderTree/chromium/TestShellGtk.cpp: + (openStartupDialog): + * DumpRenderTree/chromium/TestShellMac.mm: + (openStartupDialog): + * DumpRenderTree/chromium/TestShellWin.cpp: + (openStartupDialog): + +2010-08-03 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + [DRT/Chromium] Remove dependency of base/md5.h + https://bugs.webkit.org/show_bug.cgi?id=43403 + + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::dumpImage): Use wtf/MD5.h + +2010-08-03 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by David Kilzer. + + Limit ApplicationCache Total and Per-Origin Storage Capacity (Quotas) + https://bugs.webkit.org/show_bug.cgi?id=40627 + + Part 6 - LayoutTest and Cleanup + + Allow tests to delete application caches and set application cache + origin quotas, so they can be tested. + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (dumpApplicationCacheDelegateCallbacksCallback): JavaScript callback, delegates to the controller. + (clearAllApplicationCachesCallback): should delete all application caches. + (setApplicationCacheOriginQuotaCallback): should set the origin quota for the localhost tests. + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController::dumpApplicationCacheDelegateCallbacks): accessor to see if application cache callbacks should be output. + (LayoutTestController::setDumpApplicationCacheDelegateCallbacks): enable or disable debug output when the application cache quota is reached. + + Mac implementation. + + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::clearAllApplicationCaches): delete application caches. + (LayoutTestController::setApplicationCacheOriginQuota): set the quota for localhost. + * DumpRenderTree/mac/UIDelegate.mm: + (-[UIDelegate webView:frame:exceededDatabaseQuotaForSecurityOrigin:database:]): style fix. + (-[UIDelegate webView:exceededApplicationCacheOriginQuotaForSecurityOrigin:]): reset the quota. + + Stub implementations for other platforms. + + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::clearAllApplicationCaches): + (LayoutTestController::setApplicationCacheOriginQuota): + * DumpRenderTree/chromium/LayoutTestController.h: + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::clearAllApplicationCaches): + (LayoutTestController::setApplicationCacheOriginQuota): + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::clearAllApplicationCaches): + (LayoutTestController::setApplicationCacheOriginQuota): + * DumpRenderTree/qt/LayoutTestControllerQt.h: + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + (LayoutTestController::clearAllApplicationCaches): + (LayoutTestController::setApplicationCacheOriginQuota): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::clearAllApplicationCaches): + (LayoutTestController::setApplicationCacheOriginQuota): + +2010-08-03 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by David Kilzer. + + Limit ApplicationCache Total and Per-Origin Storage Capacity (Quotas) + https://bugs.webkit.org/show_bug.cgi?id=40627 + + Part 5 - Refactor Quota Management in WebSecurityOrigin into Managers + + Change old style calls to make use of the managers. + + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setDatabaseQuota): + * DumpRenderTree/mac/UIDelegate.mm: + (-[UIDelegate webView:frame:exceededDatabaseQuotaForSecurityOrigin:database:]): + +2010-08-03 Mark Rowe <mrowe@apple.com> + + Add a new Leopard build slave to run the release tests. + + * BuildSlaveSupport/build.webkit.org-config/config.json: + +2010-08-03 Jon Honeycutt <jhoneycutt@apple.com> + + WebKitTestRunner needs to activate the Mac font ascent hack + https://bugs.webkit.org/show_bug.cgi?id=43404 + + Reviewed by Darin Adler. + + * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp: + (WTR::InjectedBundle::initialize): + Call WKBundleActivateMacFontAscentHack(). + +2010-08-03 Alex Milowski <alex@milowski.com> + + Reviewed by Beth Dakin. + + Changed the default for MathML support so that is is enabled by default. + + * Scripts/build-webkit: + +2010-08-03 Sam Weinig <sam@webkit.org> + + Roll r64566 back in this time with all the overloads in place.. + + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::shouldInsertNode): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + * WebKitTestRunner/StringFunctions.h: + * WebKitTestRunner/TestInvocation.cpp: + (WTR::TestInvocation::resetPreferencesToConsistentValues): + (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): + * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj: + +2010-08-03 Sam Weinig <sam@webkit.org> + + Rollout r64566. It broke all the WebKit2 tests. + + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::operator<<): + (WTR::InjectedBundlePage::shouldInsertNode): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + * WebKitTestRunner/StringFunctions.h: Removed. + * WebKitTestRunner/TestInvocation.cpp: + (WTR::createWKURL): + (WTR::WKStringToUTF8): + (WTR::TestInvocation::resetPreferencesToConsistentValues): + (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): + * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj: + +2010-08-03 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + WTR: Move all the utility functions for working with strings to a shared header. + https://bugs.webkit.org/show_bug.cgi?id=43386 + + * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp: + (WTR::InjectedBundlePage::shouldInsertNode): + * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp: + * WebKitTestRunner/StringFunctions.h: Added. + * WebKitTestRunner/TestInvocation.cpp: + (WTR::TestInvocation::resetPreferencesToConsistentValues): + (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): + * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj: + +2010-08-02 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Kenneth Christiansen. + + [Qt] QtTestBrowser not setting preferredContentsSize for resizesToContents + https://bugs.webkit.org/show_bug.cgi?id=43168 + + QGraphicsWebView resizesToContents property has to work together with QWebPage's + setPreferredContentsSize as stated by the docs. Patch addresses that for QtTestBrowser. + + * QtTestBrowser/launcherwindow.cpp: + (LauncherWindow::applyPrefs): + * QtTestBrowser/webview.cpp: + (WebViewGraphicsBased::setResizesToContents): Properly handle scene, webview and viewport sizes + needed when toggle resizesToContents on/off. + (WebViewGraphicsBased::resizeEvent): + * QtTestBrowser/webview.h: + (WebViewGraphicsBased::setCustomLayoutSize): Setter helper. + (WebViewGraphicsBased::customLayoutSize): Getter helper. + +2010-08-03 Jochen Eisinger <jochen@chromium.org> + + Unreviewed. Adding myself as committer. + + * Scripts/webkitpy/common/config/committers.py: + +2010-08-02 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Yury Semikhatsky. + + Chromium DevTools: Get rid of DevTools RPC. + + https://bugs.webkit.org/show_bug.cgi?id=43335 + + * DumpRenderTree/chromium/DRTDevToolsAgent.cpp: + (DRTDevToolsAgent::sendMessageToInspectorFrontend): + (DRTDevToolsAgent::call): + * DumpRenderTree/chromium/DRTDevToolsAgent.h: + * DumpRenderTree/chromium/DRTDevToolsCallArgs.h: + (DRTDevToolsCallArgs::DRTDevToolsCallArgs): + * DumpRenderTree/chromium/DRTDevToolsClient.cpp: + (DRTDevToolsClient::sendMessageToBackend): + (DRTDevToolsClient::call): + * DumpRenderTree/chromium/DRTDevToolsClient.h: + +2010-08-02 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + [DRT/Chromium] Remove dependencies to some Chromium headers + https://bugs.webkit.org/show_bug.cgi?id=43396 + + * DumpRenderTree/chromium/CppVariant.h: + Remove base/basictypes.h because webkit_support.h contains it. + * DumpRenderTree/chromium/EventSender.cpp: + (getCurrentEventTimeSec): Use new wrapper function. + * DumpRenderTree/chromium/TestNavigationController.h: + Remove base/basictypes.h because webkit_support.h contains it. + * DumpRenderTree/chromium/TestShell.cpp: + (dumpHistoryItem): Use new wrapper function. + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::cancelledError): Use new wrapper function. + (WebViewHost::didFailResourceLoad): Use new wrapper function. + +2010-08-02 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Xan Lopez. + + [GTK] DRT implement execCommand() + https://bugs.webkit.org/show_bug.cgi?id=35351 + + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::execCommand): Implement using webkit_web_view_execute_core_command_by_name. + (LayoutTestController::isCommandEnabled): Implement using webkit_web_view_is_command_enabled. + (LayoutTestController::setCacheModel): Move below LayoutTestController::isCommandEnabled. + 2010-08-02 Sam Weinig <sam@webkit.org> Reviewed by Anders Carlsson. @@ -8,6 +1002,21 @@ 2010-08-02 Jon Honeycutt <jhoneycutt@apple.com> + WebKitTestRunner needs to support loading custom fonts (via the + WEBKIT_TESTFONTS environment variable) + https://bugs.webkit.org/show_bug.cgi?id=42782 + + Reviewed by Adam Roben. + + * WebKitTestRunner/InjectedBundle/win/ActivateFonts.cpp: + (WTR::fontsPath): + Copied from DRT code. Removed the fallback to DumpRenderTree.resources/, + as this directory doesn't appear to be created anymore. + (WTR::activateFonts): + Loop through the fonts, and call AddFontResourceExW() for each. + +2010-08-02 Jon Honeycutt <jhoneycutt@apple.com> + Restore the WebKitTestRunner.sln that was removed, and remove the correct one. diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp index d98164b..52b539c 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp @@ -41,7 +41,8 @@ #include <wtf/RefPtr.h> LayoutTestController::LayoutTestController(const std::string& testPathOrURL, const std::string& expectedPixelHash) - : m_dumpAsPDF(false) + : m_dumpApplicationCacheDelegateCallbacks(false) + , m_dumpAsPDF(false) , m_dumpAsText(false) , m_dumpBackForwardList(false) , m_dumpChildFrameScrollPositions(false) @@ -92,6 +93,13 @@ PassRefPtr<LayoutTestController> LayoutTestController::create(const std::string& // Static Functions +static JSValueRef dumpApplicationCacheDelegateCallbacksCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpApplicationCacheDelegateCallbacks(true); + return JSValueMakeUndefined(context); +} + static JSValueRef dumpAsPDFCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); @@ -310,6 +318,15 @@ static JSValueRef callShouldCloseOnWebViewCallback(JSContextRef context, JSObjec return JSValueMakeBoolean(context, controller->callShouldCloseOnWebView()); } +static JSValueRef clearAllApplicationCachesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->clearAllApplicationCaches(); + + return JSValueMakeUndefined(context); +} + static JSValueRef clearAllDatabasesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -842,7 +859,21 @@ static JSValueRef setAppCacheMaximumSizeCallback(JSContextRef context, JSObjectR controller->setAppCacheMaximumSize(static_cast<unsigned long long>(size)); return JSValueMakeUndefined(context); +} + +static JSValueRef setApplicationCacheOriginQuotaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + + double size = JSValueToNumber(context, arguments[0], NULL); + if (!isnan(size)) + controller->setApplicationCacheOriginQuota(static_cast<unsigned long long>(size)); + + return JSValueMakeUndefined(context); } static JSValueRef setAuthenticationPasswordCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -1019,6 +1050,20 @@ static JSValueRef setMockGeolocationErrorCallback(JSContextRef context, JSObject return JSValueMakeUndefined(context); } +static JSValueRef setMockSpeechInputResultCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> result(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setMockSpeechInputResult(result.get()); + + return JSValueMakeUndefined(context); +} + static JSValueRef setNewWindowsCopyBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac implementation @@ -1763,6 +1808,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "apiTestNewWindowDataLoadBaseURL", apiTestNewWindowDataLoadBaseURLCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "apiTestGoToCurrentBackForwardItem", apiTestGoToCurrentBackForwardItemCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "callShouldCloseOnWebView", callShouldCloseOnWebViewCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "clearAllApplicationCaches", clearAllApplicationCachesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "clearAllDatabases", clearAllDatabasesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "clearBackForwardList", clearBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "clearPersistentUserStyleSheet", clearPersistentUserStyleSheetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1772,6 +1818,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "disableImageLoading", disableImageLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dispatchPendingLoadRequests", dispatchPendingLoadRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "display", displayCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpApplicationCacheDelegateCallbacks", dumpApplicationCacheDelegateCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpAsText", dumpAsTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpBackForwardList", dumpBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpChildFrameScrollPositions", dumpChildFrameScrollPositionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1826,7 +1873,8 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "setAllowUniversalAccessFromFileURLs", setAllowUniversalAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAllowFileAccessFromFileURLs", setAllowFileAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAlwaysAcceptCookies", setAlwaysAcceptCookiesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setApplicationCacheOriginQuota", setApplicationCacheOriginQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAuthenticationPassword", setAuthenticationPasswordCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAuthenticationUsername", setAuthenticationUsernameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAuthorAndUserStylesEnabled", setAuthorAndUserStylesEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1848,6 +1896,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "setMockDeviceOrientation", setMockDeviceOrientationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setMockGeolocationError", setMockGeolocationErrorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setMockGeolocationPosition", setMockGeolocationPositionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setMockSpeechInputResult", setMockSpeechInputResultCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setNewWindowsCopyBackForwardList", setNewWindowsCopyBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPOSIXLocale", setPOSIXLocaleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPersistentUserStyleSheetLocation", setPersistentUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1941,7 +1990,7 @@ void LayoutTestController::waitToDumpWatchdogTimerFired() notifyDone(); } -void LayoutTestController::setGeolocationPermission(bool allow) +void LayoutTestController::setGeolocationPermissionCommon(bool allow) { m_isGeolocationPermissionSet = true; m_geolocationPermission = allow; diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h index 39cc3fb..f76870b 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/LayoutTestController.h @@ -45,6 +45,7 @@ public: void makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception); void addDisallowedURL(JSStringRef url); + void clearAllApplicationCaches(); void clearAllDatabases(); void clearBackForwardList(); void clearPersistentUserStyleSheet(); @@ -79,6 +80,7 @@ public: void setAllowUniversalAccessFromFileURLs(bool); void setAllowFileAccessFromFileURLs(bool); void setAppCacheMaximumSize(unsigned long long quota); + void setApplicationCacheOriginQuota(unsigned long long quota); void setAuthorAndUserStylesEnabled(bool); void setCacheModel(int); void setCustomPolicyDelegate(bool setDelegate, bool permissive); @@ -91,6 +93,7 @@ public: void setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma); void setMockGeolocationError(int code, JSStringRef message); void setMockGeolocationPosition(double latitude, double longitude, double accuracy); + void setMockSpeechInputResult(JSStringRef result); void setPersistentUserStyleSheetLocation(JSStringRef path); void setPluginsEnabled(bool flag); void setPopupBlockingEnabled(bool flag); @@ -126,6 +129,9 @@ public: bool generatePixelResults() const { return m_generatePixelResults; } void setGeneratePixelResults(bool generatePixelResults) { m_generatePixelResults = generatePixelResults; } + bool dumpApplicationCacheDelegateCallbacks() const { return m_dumpApplicationCacheDelegateCallbacks; } + void setDumpApplicationCacheDelegateCallbacks(bool dumpCallbacks) { m_dumpApplicationCacheDelegateCallbacks = dumpCallbacks; } + bool dumpBackForwardList() const { return m_dumpBackForwardList; } void setDumpBackForwardList(bool dumpBackForwardList) { m_dumpBackForwardList = dumpBackForwardList; } @@ -287,6 +293,9 @@ public: private: LayoutTestController(const std::string& testPathOrURL, const std::string& expectedPixelHash); + void setGeolocationPermissionCommon(bool allow); + + bool m_dumpApplicationCacheDelegateCallbacks; bool m_dumpAsPDF; bool m_dumpAsText; bool m_dumpBackForwardList; diff --git a/WebKitTools/DumpRenderTree/chromium/CppVariant.h b/WebKitTools/DumpRenderTree/chromium/CppVariant.h index d34a163..3aa5abb 100644 --- a/WebKitTools/DumpRenderTree/chromium/CppVariant.h +++ b/WebKitTools/DumpRenderTree/chromium/CppVariant.h @@ -42,8 +42,8 @@ #ifndef CppVariant_h #define CppVariant_h -#include "base/basictypes.h" #include "public/WebBindings.h" +#include "webkit/support/webkit_support.h" #include <string> #include <wtf/Vector.h> diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp index 0ff77a0..b05fe21 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.cpp @@ -36,7 +36,6 @@ #include "public/WebCString.h" #include "public/WebDevToolsAgent.h" -#include "public/WebDevToolsMessageData.h" #include "public/WebString.h" #include "public/WebView.h" #include "webkit/support/webkit_support.h" @@ -55,12 +54,17 @@ DRTDevToolsAgent::DRTDevToolsAgent() WebDevToolsAgent::setMessageLoopDispatchHandler(&DRTDevToolsAgent::dispatchMessageLoop); } +void DRTDevToolsAgent::reset() +{ + m_callMethodFactory.RevokeAll(); +} + void DRTDevToolsAgent::setWebView(WebView* webView) { m_webView = webView; } -void DRTDevToolsAgent::sendMessageToFrontend(const WebDevToolsMessageData& data) +void DRTDevToolsAgent::sendMessageToInspectorFrontend(const WebKit::WebString& data) { if (m_drtDevToolsClient) m_drtDevToolsClient->asyncCall(DRTDevToolsCallArgs(data)); @@ -100,7 +104,7 @@ void DRTDevToolsAgent::call(const DRTDevToolsCallArgs &args) { WebDevToolsAgent* agent = webDevToolsAgent(); if (agent) - agent->dispatchMessageFromFrontend(args.m_data); + agent->dispatchOnInspectorBackend(args.m_data); if (DRTDevToolsCallArgs::callsCount() == 1 && m_drtDevToolsClient) m_drtDevToolsClient->allMessagesProcessed(); } @@ -121,7 +125,7 @@ void DRTDevToolsAgent::attach(DRTDevToolsClient* client) agent->attach(); } -void DRTDevToolsAgent::detach(DRTDevToolsClient* client) +void DRTDevToolsAgent::detach() { ASSERT(m_drtDevToolsClient); WebDevToolsAgent* agent = webDevToolsAgent(); @@ -130,6 +134,12 @@ void DRTDevToolsAgent::detach(DRTDevToolsClient* client) m_drtDevToolsClient = 0; } +void DRTDevToolsAgent::frontendLoaded() { + WebDevToolsAgent* agent = webDevToolsAgent(); + if (agent) + agent->frontendLoaded(); +} + bool DRTDevToolsAgent::setTimelineProfilingEnabled(bool enabled) { WebDevToolsAgent* agent = webDevToolsAgent(); diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h index 37fc119..df52866 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsAgent.h @@ -52,11 +52,12 @@ class DRTDevToolsAgent : public WebKit::WebDevToolsAgentClient public: DRTDevToolsAgent(); virtual ~DRTDevToolsAgent() {} + void reset(); void setWebView(WebKit::WebView*); // WebDevToolsAgentClient implementation. - virtual void sendMessageToFrontend(const WebKit::WebDevToolsMessageData&); + virtual void sendMessageToInspectorFrontend(const WebKit::WebString&); virtual int hostIdentifier() { return m_routingID; } virtual void forceRepaint(); virtual void runtimeFeatureStateChanged(const WebKit::WebString& feature, bool enabled); @@ -67,7 +68,8 @@ public: void asyncCall(const DRTDevToolsCallArgs&); void attach(DRTDevToolsClient*); - void detach(DRTDevToolsClient*); + void detach(); + void frontendLoaded(); bool evaluateInWebInspector(long callID, const std::string& script); bool setTimelineProfilingEnabled(bool enable); diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h index e4a3d48..b1ac2ec 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsCallArgs.h @@ -31,22 +31,15 @@ #ifndef DRTDevToolsCallArgs_h #define DRTDevToolsCallArgs_h -#include "public/WebDevToolsMessageData.h" #include "public/WebString.h" #include <wtf/Assertions.h> class DRTDevToolsCallArgs { public: - DRTDevToolsCallArgs(const WebKit::WebDevToolsMessageData& data) + DRTDevToolsCallArgs(const WebKit::WebString& data) : m_data(data) { ++m_callsCount; - - // The same behaviour as we have in case of IPC. - for (size_t i = 0; i < m_data.arguments.size(); ++i) { - if (m_data.arguments[i].isNull()) - m_data.arguments[i] = WebKit::WebString::fromUTF8(""); - } } DRTDevToolsCallArgs(const DRTDevToolsCallArgs& args) @@ -63,7 +56,7 @@ public: static int callsCount() { return m_callsCount; } - WebKit::WebDevToolsMessageData m_data; + WebKit::WebString m_data; private: static int m_callsCount; diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp index e14f008..42f3724 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.cpp @@ -61,10 +61,20 @@ DRTDevToolsClient::~DRTDevToolsClient() // m_drtDevToolsAgent and we should clean pending requests a bit earlier. m_callMethodFactory.RevokeAll(); if (m_drtDevToolsAgent) - m_drtDevToolsAgent->detach(this); + m_drtDevToolsAgent->detach(); } -void DRTDevToolsClient::sendMessageToAgent(const WebDevToolsMessageData& data) +void DRTDevToolsClient::reset() +{ + m_callMethodFactory.RevokeAll(); +} + +void DRTDevToolsClient::sendFrontendLoaded() { + if (m_drtDevToolsAgent) + m_drtDevToolsAgent->frontendLoaded(); +} + +void DRTDevToolsClient::sendMessageToBackend(const WebString& data) { if (m_drtDevToolsAgent) m_drtDevToolsAgent->asyncCall(DRTDevToolsCallArgs(data)); @@ -103,7 +113,7 @@ void DRTDevToolsClient::asyncCall(const DRTDevToolsCallArgs& args) void DRTDevToolsClient::call(const DRTDevToolsCallArgs& args) { - m_webDevToolsFrontend->dispatchMessageFromAgent(args.m_data); + m_webDevToolsFrontend->dispatchOnInspectorFrontend(args.m_data); if (DRTDevToolsCallArgs::callsCount() == 1) allMessagesProcessed(); } diff --git a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h index f08644b..37b1e9d 100644 --- a/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h +++ b/WebKitTools/DumpRenderTree/chromium/DRTDevToolsClient.h @@ -53,9 +53,11 @@ class DRTDevToolsClient : public WebKit::WebDevToolsFrontendClient public: DRTDevToolsClient(DRTDevToolsAgent*, WebKit::WebView*); virtual ~DRTDevToolsClient(); + void reset(); // WebDevToolsFrontendClient implementation - virtual void sendMessageToAgent(const WebKit::WebDevToolsMessageData&); + virtual void sendFrontendLoaded(); + virtual void sendMessageToBackend(const WebKit::WebString&); virtual void sendDebuggerCommandToAgent(const WebKit::WebString& command); virtual void activateWindow(); diff --git a/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp index 2885cf6..726e412 100644 --- a/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp @@ -36,8 +36,6 @@ using namespace std; -void platformInit(); - static const char optionComplexText[] = "--complex-text"; static const char optionDumpAllPixels[] = "--dump-all-pixels"; static const char optionNotree[] = "--notree"; @@ -48,6 +46,7 @@ static const char optionTree[] = "--tree"; static const char optionPixelTestsWithName[] = "--pixel-tests="; static const char optionTestShell[] = "--test-shell"; static const char optionAllowExternalPages[] = "--allow-external-pages"; +static const char optionStartupDialog[] = "--testshell-startup-dialog"; static void runTest(TestShell& shell, TestParams& params, const string& testName, bool testShellMode) { @@ -91,6 +90,7 @@ int main(int argc, char* argv[]) bool serverMode = false; bool testShellMode = false; bool allowExternalPages = false; + bool startupDialog = false; for (int i = 1; i < argc; ++i) { string argument(argv[i]); if (argument == "-") @@ -107,6 +107,8 @@ int main(int argc, char* argv[]) serverMode = true; } else if (argument == optionAllowExternalPages) allowExternalPages = true; + else if (argument == optionStartupDialog) + startupDialog = true; else if (argument.size() && argument[0] == '-') fprintf(stderr, "Unknown option: %s\n", argv[i]); else @@ -117,6 +119,9 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } + if (startupDialog) + openStartupDialog(); + { // Explicit scope for the TestShell instance. TestShell shell(testShellMode); shell.setAllowExternalPages(allowExternalPages); diff --git a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp index 4e84c96..bb3c07f 100644 --- a/WebKitTools/DumpRenderTree/chromium/EventSender.cpp +++ b/WebKitTools/DumpRenderTree/chromium/EventSender.cpp @@ -45,7 +45,6 @@ #include "TestShell.h" #include "base/keyboard_codes.h" -#include "base/time.h" #include "public/WebDragData.h" #include "public/WebDragOperation.h" #include "public/WebPoint.h" @@ -124,7 +123,7 @@ static uint32 timeOffsetMs = 0; static double getCurrentEventTimeSec() { - return (TimeTicks::Now().ToInternalValue() / Time::kMicrosecondsPerMillisecond + timeOffsetMs) / 1000.0; + return (webkit_support::GetCurrentTimeInMillisecond() + timeOffsetMs) / 1000.0; } static void advanceEventTime(int32_t deltaMs) @@ -324,6 +323,7 @@ void EventSender::reset() timeOffsetMs = 0; touchModifiers = 0; touchPoints.clear(); + m_methodFactory.RevokeAll(); } WebView* EventSender::webview() diff --git a/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp b/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp index 27e9946..d1adc3d 100644 --- a/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp +++ b/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp @@ -321,12 +321,12 @@ static bool writeFile(const char* outFile, const unsigned char* data, size_t dat { FILE* file = fopen(outFile, "wb"); if (!file) { - fprintf(stderr, "ImageDiff: Unable to create file \"%s\"\n", file); + fprintf(stderr, "ImageDiff: Unable to create file \"%s\"\n", outFile); return false; } if (dataSize != fwrite(data, 1, dataSize, file)) { fclose(file); - fprintf(stderr, "ImageDiff: Unable to write data to file \"%s\"\n", file); + fprintf(stderr, "ImageDiff: Unable to write data to file \"%s\"\n", outFile); return false; } fclose(file); diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp index cd27c18..e82a65e 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp @@ -47,6 +47,7 @@ #include "public/WebSecurityPolicy.h" #include "public/WebSettings.h" #include "public/WebSize.h" +#include "public/WebSpeechInputControllerMock.h" #include "public/WebURL.h" #include "public/WebView.h" #include "webkit/support/webkit_support.h" @@ -154,6 +155,8 @@ LayoutTestController::LayoutTestController(TestShell* shell) bindMethod("setCallCloseOnWebViews", &LayoutTestController::setCallCloseOnWebViews); bindMethod("setPrivateBrowsingEnabled", &LayoutTestController::setPrivateBrowsingEnabled); bindMethod("setUseDashboardCompatibilityMode", &LayoutTestController::setUseDashboardCompatibilityMode); + bindMethod("clearAllApplicationCaches", &LayoutTestController::clearAllApplicationCaches); + bindMethod("setApplicationCacheOriginQuota", &LayoutTestController::setApplicationCacheOriginQuota); bindMethod("setJavaScriptCanAccessClipboard", &LayoutTestController::setJavaScriptCanAccessClipboard); bindMethod("setXSSAuditorEnabled", &LayoutTestController::setXSSAuditorEnabled); @@ -172,6 +175,7 @@ LayoutTestController::LayoutTestController(TestShell* shell) bindMethod("setMockGeolocationPosition", &LayoutTestController::setMockGeolocationPosition); bindMethod("setMockGeolocationError", &LayoutTestController::setMockGeolocationError); bindMethod("abortModal", &LayoutTestController::abortModal); + bindMethod("setMockSpeechInputResult", &LayoutTestController::setMockSpeechInputResult); // The fallback method is called when an unknown method is invoked. bindFallbackMethod(&LayoutTestController::fallbackMethod); @@ -510,6 +514,7 @@ void LayoutTestController::reset() else m_closeRemainingWindows = true; m_workQueue.reset(); + m_timeoutFactory.RevokeAll(); } void LayoutTestController::locationChangeDone() @@ -648,6 +653,18 @@ void LayoutTestController::setUseDashboardCompatibilityMode(const CppArgumentLis result->setNull(); } +void LayoutTestController::clearAllApplicationCaches(const CppArgumentList&, CppVariant* result) +{ + // FIXME: implement to support Application Cache Quotas. + result->setNull(); +} + +void LayoutTestController::setApplicationCacheOriginQuota(const CppArgumentList&, CppVariant* result) +{ + // FIXME: implement to support Application Cache Quotas. + result->setNull(); +} + void LayoutTestController::setScrollbarPolicy(const CppArgumentList&, CppVariant* result) { // FIXME: implement. @@ -1355,3 +1372,19 @@ void LayoutTestController::abortModal(const CppArgumentList& arguments, CppVaria { result->setNull(); } + +void LayoutTestController::setMockSpeechInputResult(const CppArgumentList& arguments, CppVariant* result) +{ + result->setNull(); + if (arguments.size() < 1 || !arguments[0].isString()) + return; + + m_speechInputControllerMock->setMockRecognitionResult(cppVariantToWebString(arguments[0])); +} + +WebKit::WebSpeechInputController* LayoutTestController::speechInputController(WebKit::WebSpeechInputListener* listener) +{ + if (!m_speechInputControllerMock.get()) + m_speechInputControllerMock.set(WebSpeechInputControllerMock::create(listener)); + return m_speechInputControllerMock.get(); +} diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h index 6748352..fb91544 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h @@ -46,6 +46,13 @@ #include "public/WebString.h" #include "public/WebURL.h" #include <wtf/Deque.h> +#include <wtf/OwnPtr.h> + +namespace WebKit { +class WebSpeechInputController; +class WebSpeechInputControllerMock; +class WebSpeechInputListener; +} class TestShell; @@ -250,6 +257,11 @@ public: void addOriginAccessWhitelistEntry(const CppArgumentList&, CppVariant*); void removeOriginAccessWhitelistEntry(const CppArgumentList&, CppVariant*); + // Clears all Application Caches. + void clearAllApplicationCaches(const CppArgumentList&, CppVariant*); + // Sets the Application Quota for the localhost origin. + void setApplicationCacheOriginQuota(const CppArgumentList&, CppVariant*); + // Clears all databases. void clearAllDatabases(const CppArgumentList&, CppVariant*); // Sets the default quota for all origins @@ -293,10 +305,14 @@ public: // Empty stub method to keep parity with object model exposed by global LayoutTestController. void abortModal(const CppArgumentList&, CppVariant*); + // Speech input related functions. + void setMockSpeechInputResult(const CppArgumentList&, CppVariant*); + public: // The following methods are not exposed to JavaScript. void setWorkQueueFrozen(bool frozen) { m_workQueue.setFrozen(frozen); } + WebKit::WebSpeechInputController* speechInputController(WebKit::WebSpeechInputListener*); bool shouldDumpAsText() { return m_dumpAsText; } bool shouldDumpEditingCallbacks() { return m_dumpEditingCallbacks; } bool shouldDumpFrameLoadCallbacks() { return m_dumpFrameLoadCallbacks; } @@ -467,6 +483,8 @@ private: CppVariant m_webHistoryItemCount; WebKit::WebURL m_userStyleSheetLocation; + + OwnPtr<WebKit::WebSpeechInputControllerMock> m_speechInputControllerMock; }; #endif // LayoutTestController_h diff --git a/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.h b/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.h index 8c2ba92..c680340 100644 --- a/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.h +++ b/WebKitTools/DumpRenderTree/chromium/MockSpellCheck.h @@ -73,7 +73,7 @@ private: bool initializeIfNeeded(); // A table that consists of misspelled words. - HashMap<WebCore::String, bool> m_misspelledWords; + HashMap<WTF::String, bool> m_misspelledWords; // A flag representing whether or not this object is initialized. bool m_initialized; diff --git a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h index f30862f..5c7a400 100644 --- a/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h +++ b/WebKitTools/DumpRenderTree/chromium/NotificationPresenter.h @@ -61,10 +61,10 @@ private: TestShell* m_shell; // Set of allowed origins. - HashSet<WebCore::String> m_allowedOrigins; + HashSet<WTF::String> m_allowedOrigins; // Map of active replacement IDs to the titles of those notifications - HashMap<WebCore::String, WebCore::String> m_replacements; + HashMap<WTF::String, WTF::String> m_replacements; }; #endif // NotificationPresenter_h diff --git a/WebKitTools/DumpRenderTree/chromium/TestNavigationController.cpp b/WebKitTools/DumpRenderTree/chromium/TestNavigationController.cpp index 8b4f954..9653c07 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestNavigationController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestNavigationController.cpp @@ -40,6 +40,17 @@ using namespace std; // ---------------------------------------------------------------------------- // TestNavigationEntry +PassRefPtr<TestNavigationEntry> TestNavigationEntry::create() +{ + return adoptRef(new TestNavigationEntry); +} + +PassRefPtr<TestNavigationEntry> TestNavigationEntry::create( + int pageID, const WebURL& url, const WebString& title, const WebString& targetFrame) +{ + return adoptRef(new TestNavigationEntry(pageID, url, title, targetFrame)); +} + TestNavigationEntry::TestNavigationEntry() : m_pageID(-1) {} @@ -136,7 +147,7 @@ TestNavigationEntry* TestNavigationController::lastCommittedEntry() const TestNavigationEntry* TestNavigationController::activeEntry() const { - TestNavigationEntry* entry = m_pendingEntry; + TestNavigationEntry* entry = m_pendingEntry.get(); if (!entry) entry = lastCommittedEntry(); return entry; @@ -182,14 +193,14 @@ void TestNavigationController::didNavigateToEntry(TestNavigationEntry* entry) m_entries[existingEntryIndex].get() : 0; if (!existingEntry) { // No existing entry, then simply ignore this navigation! - } else if (existingEntry == m_pendingEntry) { + } else if (existingEntry == m_pendingEntry.get()) { // The given entry might provide a new URL... e.g., navigating back to a // page in session history could have resulted in a new client redirect. existingEntry->setURL(entry->URL()); existingEntry->setContentState(entry->contentState()); m_lastCommittedEntryIndex = m_pendingEntryIndex; m_pendingEntryIndex = -1; - m_pendingEntry = 0; + m_pendingEntry.clear(); } else if (m_pendingEntry && m_pendingEntry->pageID() == -1 && GURL(m_pendingEntry->URL()) == GURL(existingEntry->URL().spec())) { // Not a new navigation @@ -206,15 +217,12 @@ void TestNavigationController::didNavigateToEntry(TestNavigationEntry* entry) m_lastCommittedEntryIndex = existingEntryIndex; } - delete entry; updateMaxPageID(); } void TestNavigationController::discardPendingEntry() { - if (m_pendingEntryIndex == -1) - delete m_pendingEntry; - m_pendingEntry = 0; + m_pendingEntry.clear(); m_pendingEntryIndex = -1; } @@ -231,7 +239,7 @@ void TestNavigationController::insertEntry(TestNavigationEntry* entry) } } - m_entries.append(linked_ptr<TestNavigationEntry>(entry)); + m_entries.append(RefPtr<TestNavigationEntry>(entry)); m_lastCommittedEntryIndex = static_cast<int>(m_entries.size()) - 1; updateMaxPageID(); } @@ -250,10 +258,10 @@ void TestNavigationController::navigateToPendingEntry(bool reload) // For session history navigations only the pending_entry_index_ is set. if (!m_pendingEntry) { ASSERT(m_pendingEntryIndex != -1); - m_pendingEntry = m_entries[m_pendingEntryIndex].get(); + m_pendingEntry = m_entries[m_pendingEntryIndex]; } - if (m_host->navigate(*m_pendingEntry, reload)) { + if (m_host->navigate(*m_pendingEntry.get(), reload)) { // Note: this is redundant if navigation completed synchronously because // DidNavigateToEntry call this as well. updateMaxPageID(); diff --git a/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h b/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h index bd3c2f4..d75c3bf 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h +++ b/WebKitTools/DumpRenderTree/chromium/TestNavigationController.h @@ -31,13 +31,14 @@ #ifndef TestNavigationController_h #define TestNavigationController_h -#include "base/basictypes.h" -#include "base/linked_ptr.h" #include "public/WebDataSource.h" #include "public/WebHistoryItem.h" #include "public/WebString.h" #include "public/WebURL.h" +#include "webkit/support/webkit_support.h" #include <string> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> #include <wtf/Vector.h> // Associated with browser-initated navigations to hold tracking data. @@ -56,16 +57,17 @@ public: }; // Stores one back/forward navigation state for the test shell. -class TestNavigationEntry: public Noncopyable { +class TestNavigationEntry: public RefCounted<TestNavigationEntry> { public: - TestNavigationEntry(); - TestNavigationEntry(int pageID, - const WebKit::WebURL&, - const WebKit::WebString& title, - const WebKit::WebString& targetFrame); + static PassRefPtr<TestNavigationEntry> create(); + static PassRefPtr<TestNavigationEntry> create( + int pageID, + const WebKit::WebURL&, + const WebKit::WebString& title, + const WebKit::WebString& targetFrame); // Virtual to allow test_shell to extend the class. - ~TestNavigationEntry(); + virtual ~TestNavigationEntry(); // Set / Get the URI void setURL(const WebKit::WebURL& url) { m_url = url; } @@ -86,6 +88,12 @@ public: const WebKit::WebString& targetFrame() const { return m_targetFrame; } private: + TestNavigationEntry(); + TestNavigationEntry(int pageID, + const WebKit::WebURL&, + const WebKit::WebString& title, + const WebKit::WebString& targetFrame); + // Describes the current page that the tab represents. This is not relevant // for all tab contents types. int32_t m_pageID; @@ -120,8 +128,7 @@ public: // Causes the controller to go to the specified index. void goToIndex(int); - // Causes the controller to load the specified entry. The controller - // assumes ownership of the entry. + // Causes the controller to load the specified entry. // NOTE: Do not pass an entry that the controller already owns! void loadEntry(TestNavigationEntry*); @@ -156,9 +163,9 @@ public: // Returns the index of the last committed entry. int lastCommittedEntryIndex() const { return m_lastCommittedEntryIndex; } - // Used to inform us of a navigation being committed for a tab. We will take - // ownership of the entry. Any entry located forward to the current entry will - // be deleted. The new entry becomes the current entry. + // Used to inform us of a navigation being committed for a tab. Any entry + // located forward to the current entry will be deleted. The new entry + // becomes the current entry. void didNavigateToEntry(TestNavigationEntry*); // Used to inform us to discard its pending entry. @@ -180,14 +187,14 @@ private: void updateMaxPageID(); // List of NavigationEntry for this tab - typedef Vector<linked_ptr<TestNavigationEntry> > NavigationEntryList; + typedef Vector<RefPtr<TestNavigationEntry> > NavigationEntryList; typedef NavigationEntryList::iterator NavigationEntryListIterator; NavigationEntryList m_entries; // An entry we haven't gotten a response for yet. This will be discarded // when we navigate again. It's used only so we know what the currently // displayed tab is. - TestNavigationEntry* m_pendingEntry; + RefPtr<TestNavigationEntry> m_pendingEntry; // currently visible entry int m_lastCommittedEntryIndex; diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp index 507f084..64c20b0 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp @@ -35,10 +35,8 @@ #include "DRTDevToolsClient.h" #include "LayoutTestController.h" #include "WebViewHost.h" -#include "base/md5.h" // FIXME: Wrap by webkit_support. #include "base/string16.h" #include "gfx/codec/png_codec.h" // FIXME: Remove dependecy. WebCore/platform/image-encoder is better? -#include "net/base/escape.h" // FIXME: Remove dependency. #include "public/WebDataSource.h" #include "public/WebDocument.h" #include "public/WebElement.h" @@ -48,6 +46,7 @@ #include "public/WebScriptController.h" #include "public/WebSettings.h" #include "public/WebSize.h" +#include "public/WebSpeechInputControllerMock.h" #include "public/WebString.h" #include "public/WebURLRequest.h" #include "public/WebURLResponse.h" @@ -58,6 +57,7 @@ #include <algorithm> #include <cctype> #include <vector> +#include <wtf/MD5.h> using namespace WebKit; using namespace std; @@ -278,6 +278,9 @@ void TestShell::resetTestController() m_eventSender->reset(); m_webViewHost->reset(); m_notificationPresenter->reset(); + m_drtDevToolsAgent->reset(); + if (m_drtDevToolsClient) + m_drtDevToolsClient->reset(); } void TestShell::loadURL(const WebURL& url) @@ -422,7 +425,7 @@ static string dumpHistoryItem(const WebHistoryItem& item, int indent, bool isCur url.replace(0, pos + layoutTestsPatternSize, fileTestPrefix); } else if (!url.find(dataUrlPattern)) { // URL-escape data URLs to match results upstream. - string path = EscapePath(url.substr(dataUrlPatternSize)); + string path = webkit_support::EscapePath(url.substr(dataUrlPatternSize)); url.replace(dataUrlPatternSize, url.length(), path); } @@ -585,13 +588,18 @@ void TestShell::dumpImage(skia::PlatformCanvas* canvas) const // some images that are the pixel identical on windows and other platforms // but have different MD5 sums. At this point, rebaselining all the windows // tests is too much of a pain, so we just check in different baselines. - MD5Context ctx; - MD5Init(&ctx); - MD5Update(&ctx, sourceBitmap.getPixels(), sourceBitmap.getSize()); - - MD5Digest digest; - MD5Final(&digest, &ctx); - string md5hash = MD5DigestToBase16(digest); + MD5 digester; + Vector<uint8_t, 16> digestValue; + digester.addBytes(reinterpret_cast<const uint8_t*>(sourceBitmap.getPixels()), sourceBitmap.getSize()); + digester.checksum(digestValue); + string md5hash; + md5hash.reserve(16 * 2); + for (unsigned i = 0; i < 16; ++i) { + char hex[3]; + // Use "x", not "X". The string must be lowercased. + sprintf(hex, "%02x", digestValue[i]); + md5hash.append(hex); + } // Only encode and dump the png if the hashes don't match. Encoding the image // is really expensive. diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.h b/WebKitTools/DumpRenderTree/chromium/TestShell.h index 0615552..47261a3 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShell.h +++ b/WebKitTools/DumpRenderTree/chromium/TestShell.h @@ -185,5 +185,6 @@ private: }; void platformInit(int*, char***); +void openStartupDialog(); #endif // TestShell_h diff --git a/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp b/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp index a9d374c..56ee618 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestShellGtk.cpp @@ -194,3 +194,12 @@ void platformInit(int* argc, char*** argv) setupFontconfig(); } + +void openStartupDialog() +{ + GtkWidget* dialog = gtk_message_dialog_new( + 0, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Attach to me?"); + gtk_window_set_title(GTK_WINDOW(dialog), "DumpRenderTree"); + gtk_dialog_run(GTK_DIALOG(dialog)); // Runs a nested message loop. + gtk_widget_destroy(dialog); +} diff --git a/WebKitTools/DumpRenderTree/chromium/TestShellMac.mm b/WebKitTools/DumpRenderTree/chromium/TestShellMac.mm index 19cfd07..71d990e 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShellMac.mm +++ b/WebKitTools/DumpRenderTree/chromium/TestShellMac.mm @@ -127,3 +127,13 @@ void TestShell::waitTestFinished() void platformInit(int*, char***) { } + +void openStartupDialog() +{ + // FIXME: This code doesn't work. Need NSApplication event loop? + NSAlert* alert = [[[NSAlert alloc] init] autorelease]; + alert.messageText = @"Attach to me?"; + alert.informativeText = @"This would probably be a good time to attach your debugger."; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; +} diff --git a/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp b/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp index 72f800c..0d818c4 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestShellWin.cpp @@ -149,3 +149,8 @@ void platformInit(int*, char***) } // We don't need to release the font explicitly. } + +void openStartupDialog() +{ + ::MessageBox(0, L"Attach to me?", L"DumpRenderTree", MB_OK); +} diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp index c57aeb5..a145bf9 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp +++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp @@ -35,7 +35,6 @@ #include "TestNavigationController.h" #include "TestShell.h" #include "TestWebWorker.h" -#include "net/base/net_errors.h" // FIXME: can we remove this? #include "public/WebCString.h" #include "public/WebConsoleMessage.h" #include "public/WebContextMenuData.h" @@ -166,35 +165,6 @@ static void printResponseDescription(const WebURLResponse& response) response.httpStatusCode()); } -static void printErrorDescription(const WebURLError& error) -{ - string domain = error.domain.utf8(); - int code = error.reason; - - if (domain == net::kErrorDomain) { - domain = "NSURLErrorDomain"; - switch (error.reason) { - case net::ERR_ABORTED: - code = -999; - break; - case net::ERR_UNSAFE_PORT: - // Our unsafe port checking happens at the network stack level, but we - // make this translation here to match the behavior of stock WebKit. - domain = "WebKitErrorDomain"; - code = 103; - break; - case net::ERR_ADDRESS_INVALID: - case net::ERR_ADDRESS_UNREACHABLE: - code = -1004; - break; - } - } else - LOG_ERROR("Unknown error domain"); - - printf("<NSError domain %s, code %d, failing URL \"%s\">", - domain.c_str(), code, error.unreachableURL.spec().data()); -} - static void printNodeDescription(const WebNode& node, int exception) { if (exception) { @@ -531,6 +501,11 @@ WebKit::WebGeolocationService* WebViewHost::geolocationService() return m_geolocationServiceMock.get(); } +WebSpeechInputController* WebViewHost::speechInputController(WebKit::WebSpeechInputListener* listener) +{ + return m_shell->layoutTestController()->speechInputController(listener); +} + // WebWidgetClient ----------------------------------------------------------- void WebViewHost::didInvalidateRect(const WebRect& rect) @@ -715,11 +690,7 @@ WebURLError WebViewHost::cannotHandleRequestError(WebFrame*, const WebURLRequest WebURLError WebViewHost::cancelledError(WebFrame*, const WebURLRequest& request) { - WebURLError error; - error.domain = WebString::fromUTF8(net::kErrorDomain); - error.reason = net::ERR_ABORTED; - error.unreachableURL = request.url(); - return error; + return webkit_support::CreateCancelledError(request); } void WebViewHost::unableToImplementPolicyWithError(WebFrame* frame, const WebURLError& error) @@ -960,7 +931,7 @@ void WebViewHost::didFailResourceLoad(WebFrame*, unsigned identifier, const WebU if (m_shell->shouldDumpResourceLoadCallbacks()) { printResourceDescription(identifier); fputs(" - didFailLoadingWithError: ", stdout); - printErrorDescription(error); + fputs(webkit_support::MakeURLErrorDescription(error).c_str(), stdout); fputs("\n", stdout); } m_resourceIdentifierMap.remove(identifier); @@ -1081,7 +1052,7 @@ void WebViewHost::loadURLForFrame(const WebURL& url, const WebString& frameName) if (!url.isValid()) return; TestShell::resizeWindowForTest(this, url); - navigationController()->loadEntry(new TestNavigationEntry(-1, url, WebString(), frameName)); + navigationController()->loadEntry(TestNavigationEntry::create(-1, url, WebString(), frameName).get()); } bool WebViewHost::navigate(const TestNavigationEntry& entry, bool reload) @@ -1180,7 +1151,7 @@ void WebViewHost::updateURL(WebFrame* frame) WebDataSource* ds = frame->dataSource(); ASSERT(ds); const WebURLRequest& request = ds->request(); - OwnPtr<TestNavigationEntry> entry(new TestNavigationEntry); + RefPtr<TestNavigationEntry> entry(TestNavigationEntry::create()); // The referrer will be empty on https->http transitions. It // would be nice if we could get the real referrer from somewhere. @@ -1194,7 +1165,7 @@ void WebViewHost::updateURL(WebFrame* frame) if (!historyItem.isNull()) entry->setContentState(historyItem); - navigationController()->didNavigateToEntry(entry.leakPtr()); + navigationController()->didNavigateToEntry(entry.get()); updateAddressBar(frame->view()); m_lastPageIdUpdated = max(m_lastPageIdUpdated, m_pageId); } @@ -1207,7 +1178,7 @@ void WebViewHost::updateSessionHistory(WebFrame* frame) if (m_pageId == -1) return; - TestNavigationEntry* entry = static_cast<TestNavigationEntry*>(navigationController()->entryWithPageID(m_pageId)); + TestNavigationEntry* entry = navigationController()->entryWithPageID(m_pageId); if (!entry) return; diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h index 1e51be7..d95c59f 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h +++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h @@ -46,6 +46,8 @@ class TestShell; namespace WebKit { class WebFrame; class WebGeolocationServiceMock; +class WebSpeechInputController; +class WebSpeechInputListener; class WebURL; struct WebRect; struct WebURLError; @@ -83,8 +85,8 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, void loadURLForFrame(const WebKit::WebURL&, const WebKit::WebString& frameName); TestNavigationController* navigationController() { return m_navigationController.get(); } - void addClearHeader(const WebCore::String& header) { m_clearHeaders.add(header); } - const HashSet<WebCore::String>& clearHeaders() const { return m_clearHeaders; } + void addClearHeader(const WTF::String& header) { m_clearHeaders.add(header); } + const HashSet<WTF::String>& clearHeaders() const { return m_clearHeaders; } // NavigationHost virtual bool navigate(const TestNavigationEntry&, bool reload); @@ -126,6 +128,7 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, virtual void focusAccessibilityObject(const WebKit::WebAccessibilityObject&); virtual WebKit::WebNotificationPresenter* notificationPresenter(); virtual WebKit::WebGeolocationService* geolocationService(); + virtual WebKit::WebSpeechInputController* speechInputController(WebKit::WebSpeechInputListener*); // WebKit::WebWidgetClient virtual void didInvalidateRect(const WebKit::WebRect&); @@ -259,7 +262,7 @@ private: bool m_selectTrailingWhitespaceEnabled; // Set of headers to clear in willSendRequest. - HashSet<WebCore::String> m_clearHeaders; + HashSet<WTF::String> m_clearHeaders; // true if we should block any redirects bool m_blocksRedirects; diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp index 2aece10..b0c1cba 100644 --- a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp @@ -60,6 +60,8 @@ int webkit_web_frame_page_number_for_element_by_id(WebKitWebFrame* frame, const int webkit_web_frame_number_of_pages(WebKitWebFrame* frame, float pageWidth, float pageHeight); void webkit_web_inspector_execute_script(WebKitWebInspector* inspector, long callId, const gchar* script); gchar* webkit_web_frame_marker_text_for_list_item(WebKitWebFrame* frame, JSContextRef context, JSValueRef nodeObject); +void webkit_web_view_execute_core_command_by_name(WebKitWebView* webView, const gchar* name, const gchar* value); +gboolean webkit_web_view_is_command_enabled(WebKitWebView* webView, const gchar* name); } static gchar* copyWebSettingKey(gchar* preferenceKey) @@ -460,6 +462,18 @@ void LayoutTestController::setMockGeolocationError(int code, JSStringRef message // See https://bugs.webkit.org/show_bug.cgi?id=28264. } +void LayoutTestController::setGeolocationPermission(bool allow) +{ + // FIXME: Implement for Geolocation layout tests. + setGeolocationPermissionCommon(allow); +} + +void LayoutTestController::setMockSpeechInputResult(JSStringRef result) +{ + // FIXME: Implement for speech input layout tests. + // See https://bugs.webkit.org/show_bug.cgi?id=39485. +} + void LayoutTestController::setIconDatabaseEnabled(bool flag) { // FIXME: implement @@ -504,18 +518,30 @@ bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef i void LayoutTestController::execCommand(JSStringRef name, JSStringRef value) { - // FIXME: implement + WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); + ASSERT(view); + + gchar* cName = JSStringCopyUTF8CString(name); + gchar* cValue = JSStringCopyUTF8CString(value); + webkit_web_view_execute_core_command_by_name(view, cName, cValue); + g_free(cName); + g_free(cValue); } -void LayoutTestController::setCacheModel(int) +bool LayoutTestController::isCommandEnabled(JSStringRef name) { - // FIXME: implement + WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); + ASSERT(view); + + gchar* cName = JSStringCopyUTF8CString(name); + gboolean result = webkit_web_view_is_command_enabled(view, cName); + g_free(cName); + return result; } -bool LayoutTestController::isCommandEnabled(JSStringRef /*name*/) +void LayoutTestController::setCacheModel(int) { // FIXME: implement - return false; } void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef jsURL) @@ -528,6 +554,16 @@ void LayoutTestController::clearPersistentUserStyleSheet() // FIXME: implement } +void LayoutTestController::clearAllApplicationCaches() +{ + // FIXME: implement to support Application Cache quotas. +} + +void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota) +{ + // FIXME: implement to support Application Cache quotas. +} + void LayoutTestController::clearAllDatabases() { webkit_remove_all_web_databases(); diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm index 77999bd..9031c63 100644 --- a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm +++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm @@ -449,13 +449,13 @@ static int buildModifierFlags(const WebScriptObject* modifiers) NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; if (subView) { if (leftMouseButtonDown) { - [subView mouseDragged:event]; if (draggingInfo) { // Per NSDragging.h: draggingSources may not implement draggedImage:movedTo: if ([[draggingInfo draggingSource] respondsToSelector:@selector(draggedImage:movedTo:)]) [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition]; [[mainFrame webView] draggingUpdated:draggingInfo]; - } + } else + [subView mouseDragged:event]; } else [subView mouseMoved:event]; } diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm index 7db7fff..c0eb722 100644 --- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -33,6 +33,7 @@ #import "EditingDelegate.h" #import "MockGeolocationProvider.h" #import "PolicyDelegate.h" +#import "UIDelegate.h" #import "WorkQueue.h" #import "WorkQueueItem.h" #import <Foundation/Foundation.h> @@ -60,6 +61,7 @@ #import <WebKit/WebKitErrors.h> #import <WebKit/WebPreferences.h> #import <WebKit/WebPreferencesPrivate.h> +#import <WebKit/WebQuotaManager.h> #import <WebKit/WebScriptWorld.h> #import <WebKit/WebSecurityOriginPrivate.h> #import <WebKit/WebTypesInternal.h> @@ -123,6 +125,11 @@ bool LayoutTestController::callShouldCloseOnWebView() return [[mainFrame webView] shouldClose]; } +void LayoutTestController::clearAllApplicationCaches() +{ + [WebApplicationCache deleteAllApplicationCaches]; +} + void LayoutTestController::clearAllDatabases() { [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases]; @@ -293,6 +300,13 @@ void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) [WebApplicationCache setMaximumSize:size]; } +void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota) +{ + WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"http://127.0.0.1:8000"]]; + [[origin applicationCacheQuotaManager] setQuota:quota]; + [origin release]; +} + void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag) { [[[mainFrame webView] preferences] setAuthorAndUserStylesEnabled:flag]; @@ -310,7 +324,7 @@ void LayoutTestController::setCustomPolicyDelegate(bool setDelegate, bool permis void LayoutTestController::setDatabaseQuota(unsigned long long quota) { WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"file:///"]]; - [origin setQuota:quota]; + [[origin databaseQuotaManager] setQuota:quota]; [origin release]; } @@ -342,6 +356,18 @@ void LayoutTestController::setMockGeolocationError(int code, JSStringRef message [[MockGeolocationProvider shared] setError:error]; } +void LayoutTestController::setGeolocationPermission(bool allow) +{ + setGeolocationPermissionCommon(allow); + [[[mainFrame webView] UIDelegate] didSetMockGeolocationPermission]; +} + +void LayoutTestController::setMockSpeechInputResult(JSStringRef result) +{ + // FIXME: Implement for speech input layout tests. + // See https://bugs.webkit.org/show_bug.cgi?id=39485. +} + void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled) { // FIXME: Workaround <rdar://problem/6480108> diff --git a/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm b/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm index 55d7257..e03cae2 100644 --- a/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm +++ b/WebKitTools/DumpRenderTree/mac/MockGeolocationProvider.mm @@ -74,6 +74,9 @@ - (void)registerWebView:(WebView *)webView { _registeredViews.add(webView); + + if (!_timer) + _timer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(timerFired) userInfo:0 repeats:NO]; } - (void)unregisterWebView:(WebView *)webView diff --git a/WebKitTools/DumpRenderTree/mac/UIDelegate.h b/WebKitTools/DumpRenderTree/mac/UIDelegate.h index da472d6..a8017ad 100644 --- a/WebKitTools/DumpRenderTree/mac/UIDelegate.h +++ b/WebKitTools/DumpRenderTree/mac/UIDelegate.h @@ -32,6 +32,10 @@ @private NSRect m_frame; + NSMutableSet *m_pendingGeolocationPermissionListeners; + NSTimer *m_timer; } +- (void)didSetMockGeolocationPermission; + @end diff --git a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm index 3dc378a..f9afdb1 100644 --- a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm +++ b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm @@ -33,8 +33,10 @@ #import "DumpRenderTreeDraggingInfo.h" #import "EventSendingController.h" #import "LayoutTestController.h" +#import <WebKit/WebApplicationCache.h> #import <WebKit/WebFramePrivate.h> #import <WebKit/WebHTMLViewPrivate.h> +#import <WebKit/WebQuotaManager.h> #import <WebKit/WebSecurityOriginPrivate.h> #import <WebKit/WebUIDelegatePrivate.h> #import <WebKit/WebView.h> @@ -155,12 +157,24 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil; - (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(WebSecurityOrigin *)origin database:(NSString *)databaseIdentifier { - if (!done && gLayoutTestController->dumpDatabaseCallbacks()) + if (!done && gLayoutTestController->dumpDatabaseCallbacks()) { printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n", [[origin protocol] UTF8String], [[origin host] UTF8String], [origin port], [databaseIdentifier UTF8String]); + } static const unsigned long long defaultQuota = 5 * 1024 * 1024; - [origin setQuota:defaultQuota]; + [[origin databaseQuotaManager] setQuota:defaultQuota]; +} + +- (void)webView:(WebView *)sender exceededApplicationCacheOriginQuotaForSecurityOrigin:(WebSecurityOrigin *)origin +{ + if (!done && gLayoutTestController->dumpApplicationCacheDelegateCallbacks()) { + printf("UI DELEGATE APPLICATION CACHE CALLBACK: exceededApplicationCacheOriginQuotaForSecurityOrigin:{%s, %s, %i}\n", + [[origin protocol] UTF8String], [[origin host] UTF8String], [origin port]); + } + + static const unsigned long long defaultOriginQuota = [WebApplicationCache defaultOriginQuota]; + [[origin applicationCacheQuotaManager] setQuota:defaultOriginQuota]; } - (void)webView:(WebView *)sender setStatusText:(NSString *)text @@ -171,13 +185,43 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil; - (void)webView:(WebView *)webView decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin *)origin frame:(WebFrame *)frame listener:(id<WebGeolocationPolicyListener>)listener { - // FIXME: If mock permission isn't set yet, we should send the response asynchronously. - if (gLayoutTestController->isGeolocationPermissionSet() && gLayoutTestController->geolocationPermission()) + if (!gLayoutTestController->isGeolocationPermissionSet()) { + if (!m_pendingGeolocationPermissionListeners) + m_pendingGeolocationPermissionListeners = [[NSMutableSet set] retain]; + [m_pendingGeolocationPermissionListeners addObject:listener]; + return; + } + + if (gLayoutTestController->geolocationPermission()) [listener allow]; else [listener deny]; } +- (void)didSetMockGeolocationPermission +{ + ASSERT(gLayoutTestController->isGeolocationPermissionSet()); + if (m_pendingGeolocationPermissionListeners && !m_timer) + m_timer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(timerFired) userInfo:0 repeats:NO]; +} + +- (void)timerFired +{ + ASSERT(gLayoutTestController->isGeolocationPermissionSet()); + m_timer = 0; + NSEnumerator* enumerator = [m_pendingGeolocationPermissionListeners objectEnumerator]; + id<WebGeolocationPolicyListener> listener; + while ((listener = [enumerator nextObject])) { + if (gLayoutTestController->geolocationPermission()) + [listener allow]; + else + [listener deny]; + } + [m_pendingGeolocationPermissionListeners removeAllObjects]; + [m_pendingGeolocationPermissionListeners release]; + m_pendingGeolocationPermissionListeners = nil; +} + - (BOOL)webView:(WebView *)sender shouldHaltPlugin:(DOMNode *)pluginNode { return NO; @@ -193,6 +237,8 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil; { [draggingInfo release]; draggingInfo = nil; + [m_pendingGeolocationPermissionListeners release]; + m_pendingGeolocationPermissionListeners = nil; [super dealloc]; } diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro index b66eb5d..63554b2 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro @@ -13,7 +13,7 @@ INCLUDEPATH += ../../../JavaScriptCore/ForwardingHeaders INCLUDEPATH += $$BASEDIR DESTDIR = ../../../bin -!win32:!symbian { +unix:!mac { CONFIG += link_pkgconfig PKGCONFIG += fontconfig } diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp index ca51f1b..e682fd0 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp @@ -494,6 +494,16 @@ void LayoutTestController::dispatchPendingLoadRequests() // FIXME: Implement for testing fix for 6727495 } +void LayoutTestController::clearAllApplicationCaches() +{ + // FIXME: implement to support Application Cache quotas. +} + +void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota) +{ + // FIXME: implement to support Application Cache quotas. +} + void LayoutTestController::setDatabaseQuota(int size) { if (!m_topLoadingFrame) @@ -705,6 +715,12 @@ void LayoutTestController::setMockGeolocationPosition(double latitude, double lo DumpRenderTreeSupportQt::setMockGeolocationPosition(latitude, longitude, accuracy); } +void LayoutTestController::setMockSpeechInputResult(const QString& result) +{ + // FIXME: Implement for speech input layout tests. + // See https://bugs.webkit.org/show_bug.cgi?id=39485. +} + void LayoutTestController::evaluateScriptInIsolatedWorld(int worldID, const QString& script) { DumpRenderTreeSupportQt::evaluateScriptInIsolatedWorld(m_drt->webPage()->mainFrame(), worldID, script); diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h index 1dee6ce..f9986b1 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h @@ -174,6 +174,9 @@ public slots: void dispatchPendingLoadRequests(); void disableImageLoading(); + void clearAllApplicationCaches(); + void setApplicationCacheOriginQuota(unsigned long long quota); + void setDatabaseQuota(int size); void clearAllDatabases(); void setIconDatabaseEnabled(bool enable); @@ -205,6 +208,8 @@ public slots: bool isGeolocationPermissionSet() const { return m_isGeolocationPermissionSet; } bool geolocationPermission() const { return m_geolocationPermission; } + void setMockSpeechInputResult(const QString& result); + // Empty stub method to keep parity with object model exposed by global LayoutTestController. void abortModal() {} diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp index 6519a97..31bc6ce 100644 --- a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp +++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp @@ -393,6 +393,18 @@ void LayoutTestController::setMockGeolocationError(int code, JSStringRef message // See https://bugs.webkit.org/show_bug.cgi?id=28264. } +void LayoutTestController::setGeolocationPermission(bool allow) +{ + // FIXME: Implement for Geolocation layout tests. + setGeolocationPermissionCommon(allow); +} + +void LayoutTestController::setMockSpeechInputResult(JSStringRef result) +{ + // FIXME: Implement for speech input layout tests. + // See https://bugs.webkit.org/show_bug.cgi?id=39485. +} + void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled) { // See also <rdar://problem/6480108> @@ -888,6 +900,16 @@ bool LayoutTestController::isCommandEnabled(JSStringRef /*name*/) return false; } +void LayoutTestController::clearAllApplicationCaches() +{ + // FIXME: implement to support Application Cache quotas. +} + +void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota) +{ + // FIXME: implement to support Application Cache quotas. +} + void LayoutTestController::clearAllDatabases() { COMPtr<IWebDatabaseManager> databaseManager; diff --git a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp index fd6b2d2..7c80ff2 100644 --- a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp +++ b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp @@ -228,6 +228,16 @@ void LayoutTestController::clearPersistentUserStyleSheet() // FIXME: implement } +void LayoutTestController::clearAllApplicationCaches() +{ + // FIXME: implement to support Application Cache quotas. +} + +void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota) +{ + // FIXME: implement to support Application Cache quotas. +} + void LayoutTestController::clearAllDatabases() { // FIXME: implement @@ -289,6 +299,18 @@ void LayoutTestController::setMockGeolocationError(int code, JSStringRef message // See https://bugs.webkit.org/show_bug.cgi?id=28264. } +void LayoutTestController::setGeolocationPermission(bool allow) +{ + // FIXME: Implement for Geolocation layout tests. + setGeolocationPermissionCommon(allow); +} + +void LayoutTestController::setMockSpeechInputResult(JSStringRef result) +{ + // FIXME: Implement for speech input layout tests. + // See https://bugs.webkit.org/show_bug.cgi?id=39485. +} + void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled) { // FIXME: implement diff --git a/WebKitTools/MiniBrowser/mac/WebBundle/WebBundleMain.m b/WebKitTools/MiniBrowser/mac/WebBundle/WebBundleMain.m index c4f4a68..8e0a576 100644 --- a/WebKitTools/MiniBrowser/mac/WebBundle/WebBundleMain.m +++ b/WebKitTools/MiniBrowser/mac/WebBundle/WebBundleMain.m @@ -35,37 +35,9 @@ static WKBundleRef globalBundle; -// WKBundlePageClient +// WKBundlePageClient functions -void didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) -{ -} - -void didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) -{ -} - -void didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) -{ -} - -void didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) -{ -} - -void didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) -{ -} - -void didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) -{ -} - -void didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, const void *clientInfo) -{ -} - -void didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, JSGlobalContextRef context, JSObjectRef window, const void *clientInfo) +void didClearWindowObjectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, JSGlobalContextRef context, JSObjectRef window, const void *clientInfo) { WKURLRef wkURL = WKBundleFrameCopyURL(WKBundlePageGetMainFrame(page)); CFURLRef cfURL = WKURLCopyCFURL(0, wkURL); @@ -88,18 +60,10 @@ void didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientI { LOG(@"WKBundleClient - didCreatePage\n"); - WKBundlePageLoaderClient client = { - 0, - 0, - didStartProvisionalLoadForFrame, - didReceiveServerRedirectForProvisionalLoadForFrame, - didFailProvisionalLoadWithErrorForFrame, - didCommitLoadForFrame, - didFinishLoadForFrame, - didFailLoadWithErrorForFrame, - didReceiveTitleForFrame, - didClearWindowForFrame - }; + WKBundlePageLoaderClient client; + memset(&client, 0, sizeof(client)); + client.didClearWindowObjectForFrame = didClearWindowObjectForFrame; + WKBundlePageSetLoaderClient(page, &client); } diff --git a/WebKitTools/QtTestBrowser/launcherwindow.cpp b/WebKitTools/QtTestBrowser/launcherwindow.cpp index 177adea..095a984 100644 --- a/WebKitTools/QtTestBrowser/launcherwindow.cpp +++ b/WebKitTools/QtTestBrowser/launcherwindow.cpp @@ -32,48 +32,25 @@ #include "launcherwindow.h" -bool LauncherWindow::gUseGraphicsView = false; -bool LauncherWindow::gUseCompositing = true; -bool LauncherWindow::gCacheWebView = false; -bool LauncherWindow::gShowFrameRate = false; -bool LauncherWindow::gResizesToContents = false; -bool LauncherWindow::gUseTiledBackingStore = false; -QGraphicsView::ViewportUpdateMode LauncherWindow::gViewportUpdateMode = QGraphicsView::MinimalViewportUpdate; -QUrl LauncherWindow::gInspectorUrl; - -#if defined(Q_WS_MAEMO_5) || defined(Q_WS_S60) -bool LauncherWindow::gUseFrameFlattening = true; -#else -bool LauncherWindow::gUseFrameFlattening = false; -#endif +const int gExitClickArea = 80; +QVector<int> LauncherWindow::m_zoomLevels; -#if defined(QT_CONFIGURED_WITH_OPENGL) -bool LauncherWindow::gUseQGLWidgetViewport = false; -#endif - -LauncherWindow::LauncherWindow(LauncherWindow* other, bool shareScene) +LauncherWindow::LauncherWindow(WindowOptions* data, QGraphicsScene* sharedScene) : MainWindow() , m_currentZoom(100) , m_view(0) , m_inspector(0) , m_formatMenuAction(0) - , m_flipAnimated(0) - , m_flipYAnimated(0) #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) , m_zoomAnimation(0) #endif { - if (other) { - init(other->isGraphicsBased()); - applyPrefs(other); - if (shareScene && other->isGraphicsBased()) { - QGraphicsView* otherView = static_cast<QGraphicsView*>(other->m_view); - static_cast<QGraphicsView*>(m_view)->setScene(otherView->scene()); - } - } else { - init(gUseGraphicsView); - applyPrefs(); - } + if (data) + m_windowOptions = *data; + + init(); + if (sharedScene && data->useGraphicsView) + static_cast<QGraphicsView*>(m_view)->setScene(sharedScene); createChrome(); } @@ -83,7 +60,7 @@ LauncherWindow::~LauncherWindow() grabZoomKeys(false); } -void LauncherWindow::init(bool useGraphicsView) +void LauncherWindow::init() { QSplitter* splitter = new QSplitter(Qt::Vertical, this); setCentralWidget(splitter); @@ -95,7 +72,7 @@ void LauncherWindow::init(bool useGraphicsView) resize(800, 600); #endif - initializeView(useGraphicsView); + initializeView(); connect(page(), SIGNAL(loadStarted()), this, SLOT(loadStarted())); connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished())); @@ -103,30 +80,34 @@ void LauncherWindow::init(bool useGraphicsView) this, SLOT(showLinkHover(const QString&, const QString&))); connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool))); + applyPrefs(); + m_inspector = new WebInspector(splitter); #ifndef QT_NO_PROPERTIES - if (!gInspectorUrl.isEmpty()) - m_inspector->setProperty("_q_inspectorUrl", gInspectorUrl); + if (!m_windowOptions.inspectorUrl.isEmpty()) + m_inspector->setProperty("_q_inspectorUrl", m_windowOptions.inspectorUrl); #endif m_inspector->setPage(page()); m_inspector->hide(); connect(this, SIGNAL(destroyed()), m_inspector, SLOT(deleteLater())); // the zoom values are chosen to be like in Mozilla Firefox 3 - m_zoomLevels << 30 << 50 << 67 << 80 << 90; - m_zoomLevels << 100; - m_zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300; + if (!m_zoomLevels.count()) { + m_zoomLevels << 30 << 50 << 67 << 80 << 90; + m_zoomLevels << 100; + m_zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300; + } grabZoomKeys(true); } -void LauncherWindow::initializeView(bool useGraphicsView) +void LauncherWindow::initializeView() { delete m_view; QSplitter* splitter = static_cast<QSplitter*>(centralWidget()); - if (!useGraphicsView) { + if (!m_windowOptions.useGraphicsView) { WebViewTraditional* view = new WebViewTraditional(splitter); view->setPage(page()); @@ -137,12 +118,6 @@ void LauncherWindow::initializeView(bool useGraphicsView) WebViewGraphicsBased* view = new WebViewGraphicsBased(splitter); view->setPage(page()); - if (m_flipAnimated) - connect(m_flipAnimated, SIGNAL(triggered()), view, SLOT(animatedFlip())); - - if (m_flipYAnimated) - connect(m_flipYAnimated, SIGNAL(triggered()), view, SLOT(animatedYFlip())); - connect(view, SIGNAL(currentFPSUpdated(int)), this, SLOT(updateFPS(int))); view->installEventFilter(this); @@ -158,6 +133,26 @@ void LauncherWindow::initializeView(bool useGraphicsView) #endif } +void LauncherWindow::applyPrefs() +{ + QWebSettings* settings = page()->settings(); + settings->setAttribute(QWebSettings::AcceleratedCompositingEnabled, m_windowOptions.useCompositing); + settings->setAttribute(QWebSettings::TiledBackingStoreEnabled, m_windowOptions.useTiledBackingStore); + settings->setAttribute(QWebSettings::FrameFlatteningEnabled, m_windowOptions.useFrameFlattening); + settings->setAttribute(QWebSettings::WebGLEnabled, m_windowOptions.useWebGL); + + if (!isGraphicsBased()) + return; + + WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view); + view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode); + view->setFrameRateMeasurementEnabled(m_windowOptions.showFrameRate); + view->setItemCacheMode(m_windowOptions.cacheWebView ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache); + + if (m_windowOptions.resizesToContents) + toggleResizesToContents(m_windowOptions.resizesToContents); +} + void LauncherWindow::createChrome() { QMenu* fileMenu = menuBar()->addMenu("&File"); @@ -196,6 +191,10 @@ void LauncherWindow::createChrome() viewMenu->addAction("Dump HTML", this, SLOT(dumpHtml())); // viewMenu->addAction("Dump plugins", this, SLOT(dumpPlugins())); + zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); + zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); + resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); + QMenu* formatMenu = new QMenu("F&ormat", this); m_formatMenuAction = menuBar()->addMenu(formatMenu); m_formatMenuAction->setVisible(false); @@ -207,25 +206,19 @@ void LauncherWindow::createChrome() writingMenu->addAction(page()->action(QWebPage::SetTextDirectionLeftToRight)); writingMenu->addAction(page()->action(QWebPage::SetTextDirectionRightToLeft)); - zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); - zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); - resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); - QMenu* windowMenu = menuBar()->addMenu("&Window"); QAction* toggleFullScreen = windowMenu->addAction("Toggle FullScreen", this, SIGNAL(enteredFullScreenMode(bool))); toggleFullScreen->setCheckable(true); toggleFullScreen->setChecked(false); - - // when exit fullscreen mode by clicking on the exit area (bottom right corner) we must - // uncheck the Toggle FullScreen action + // When exit fullscreen mode by clicking on the exit area (bottom right corner) we must + // uncheck the Toggle FullScreen action. toggleFullScreen->connect(this, SIGNAL(enteredFullScreenMode(bool)), SLOT(setChecked(bool))); - QMenu* toolsMenu = menuBar()->addMenu("&Develop"); - QWebSettings* settings = page()->settings(); + QMenu* toolsMenu = menuBar()->addMenu("&Develop"); QMenu* graphicsViewMenu = toolsMenu->addMenu("QGraphicsView"); - QAction* toggleGraphicsView = graphicsViewMenu->addAction("Toggle use of QGraphicsView", this, SLOT(initializeView(bool))); + QAction* toggleGraphicsView = graphicsViewMenu->addAction("Toggle use of QGraphicsView", this, SLOT(initializeView())); toggleGraphicsView->setCheckable(true); toggleGraphicsView->setChecked(isGraphicsBased()); @@ -242,7 +235,7 @@ void LauncherWindow::createChrome() toggleFrameFlattening->setChecked(settings->testAttribute(QWebSettings::FrameFlatteningEnabled)); #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) - QAction* touchMockAction = toolsMenu->addAction("Toggle multitouch mocking", this, SLOT(setTouchMocking(bool))); + QAction* touchMockAction = toolsMenu->addAction("Toggle touch mocking", this, SLOT(setTouchMocking(bool))); touchMockAction->setCheckable(true); touchMockAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_T)); #endif @@ -277,20 +270,20 @@ void LauncherWindow::createChrome() QAction* toggleResizesToContents = graphicsViewMenu->addAction("Toggle Resizes To Contents Mode", this, SLOT(toggleResizesToContents(bool))); toggleResizesToContents->setCheckable(true); - toggleResizesToContents->setChecked(gResizesToContents); + toggleResizesToContents->setChecked(m_windowOptions.resizesToContents); toggleResizesToContents->setEnabled(isGraphicsBased()); toggleResizesToContents->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); QAction* toggleTiledBackingStore = graphicsViewMenu->addAction("Toggle Tiled Backing Store", this, SLOT(toggleTiledBackingStore(bool))); toggleTiledBackingStore->setCheckable(true); - toggleTiledBackingStore->setChecked(false); + toggleTiledBackingStore->setChecked(m_windowOptions.useTiledBackingStore); toggleTiledBackingStore->setEnabled(isGraphicsBased()); toggleTiledBackingStore->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); #if defined(QT_CONFIGURED_WITH_OPENGL) QAction* toggleQGLWidgetViewport = graphicsViewMenu->addAction("Toggle use of QGLWidget Viewport", this, SLOT(toggleQGLWidgetViewport(bool))); toggleQGLWidgetViewport->setCheckable(true); - toggleQGLWidgetViewport->setChecked(gUseQGLWidgetViewport); + toggleQGLWidgetViewport->setChecked(m_windowOptions.useQGLWidgetViewport); toggleQGLWidgetViewport->setEnabled(isGraphicsBased()); toggleQGLWidgetViewport->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); #endif @@ -301,23 +294,23 @@ void LauncherWindow::createChrome() QAction* fullUpdate = viewportUpdateMenu->addAction("FullViewportUpdate"); fullUpdate->setCheckable(true); - fullUpdate->setChecked((gViewportUpdateMode == QGraphicsView::FullViewportUpdate) ? true : false); + fullUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::FullViewportUpdate) ? true : false); QAction* minimalUpdate = viewportUpdateMenu->addAction("MinimalViewportUpdate"); minimalUpdate->setCheckable(true); - minimalUpdate->setChecked((gViewportUpdateMode == QGraphicsView::MinimalViewportUpdate) ? true : false); + minimalUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::MinimalViewportUpdate) ? true : false); QAction* smartUpdate = viewportUpdateMenu->addAction("SmartViewportUpdate"); smartUpdate->setCheckable(true); - smartUpdate->setChecked((gViewportUpdateMode == QGraphicsView::SmartViewportUpdate) ? true : false); + smartUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::SmartViewportUpdate) ? true : false); QAction* boundingRectUpdate = viewportUpdateMenu->addAction("BoundingRectViewportUpdate"); boundingRectUpdate->setCheckable(true); - boundingRectUpdate->setChecked((gViewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) ? true : false); + boundingRectUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) ? true : false); QAction* noUpdate = viewportUpdateMenu->addAction("NoViewportUpdate"); noUpdate->setCheckable(true); - noUpdate->setChecked((gViewportUpdateMode == QGraphicsView::NoViewportUpdate) ? true : false); + noUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::NoViewportUpdate) ? true : false); QSignalMapper* signalMapper = new QSignalMapper(viewportUpdateMenu); signalMapper->setMapping(fullUpdate, QGraphicsView::FullViewportUpdate); @@ -343,18 +336,18 @@ void LauncherWindow::createChrome() graphicsViewMenu->addSeparator(); - m_flipAnimated = graphicsViewMenu->addAction("Animated Flip"); - m_flipAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); - m_flipAnimated->setEnabled(isGraphicsBased()); + QAction* flipAnimated = graphicsViewMenu->addAction("Animated Flip"); + flipAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); + flipAnimated->setEnabled(isGraphicsBased()); - m_flipYAnimated = graphicsViewMenu->addAction("Animated Y-Flip"); - m_flipYAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); - m_flipYAnimated->setEnabled(isGraphicsBased()); + QAction* flipYAnimated = graphicsViewMenu->addAction("Animated Y-Flip"); + flipYAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); + flipYAnimated->setEnabled(isGraphicsBased()); if (isGraphicsBased()) { WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view); - connect(m_flipAnimated, SIGNAL(triggered()), view, SLOT(animatedFlip())); - connect(m_flipYAnimated, SIGNAL(triggered()), view, SLOT(animatedYFlip())); + connect(flipAnimated, SIGNAL(triggered()), view, SLOT(animatedFlip())); + connect(flipYAnimated, SIGNAL(triggered()), view, SLOT(animatedYFlip())); } QAction* cloneWindow = graphicsViewMenu->addAction("Clone Window", this, SLOT(cloneWindow())); @@ -367,7 +360,7 @@ void LauncherWindow::createChrome() showFPS->setCheckable(true); showFPS->setEnabled(isGraphicsBased()); showFPS->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); - showFPS->setChecked(gShowFrameRate); + showFPS->setChecked(m_windowOptions.showFrameRate); } bool LauncherWindow::isGraphicsBased() const @@ -375,39 +368,6 @@ bool LauncherWindow::isGraphicsBased() const return bool(qobject_cast<QGraphicsView*>(m_view)); } -inline void applySetting(QWebSettings::WebAttribute type, QWebSettings* settings, QWebSettings* other, bool defaultValue) -{ - settings->setAttribute(type, other ? other->testAttribute(type) : defaultValue); -} - -void LauncherWindow::applyPrefs(LauncherWindow* source) -{ - QWebSettings* other = source ? source->page()->settings() : 0; - QWebSettings* settings = page()->settings(); - - applySetting(QWebSettings::AcceleratedCompositingEnabled, settings, other, gUseCompositing); - applySetting(QWebSettings::TiledBackingStoreEnabled, settings, other, gUseTiledBackingStore); - applySetting(QWebSettings::WebGLEnabled, settings, other, false); - applySetting(QWebSettings::FrameFlatteningEnabled, settings, other, gUseFrameFlattening); - - if (!isGraphicsBased()) - return; - - WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view); - WebViewGraphicsBased* otherView = source ? qobject_cast<WebViewGraphicsBased*>(source->m_view) : 0; - - view->setViewportUpdateMode(otherView ? otherView->viewportUpdateMode() : gViewportUpdateMode); - view->setFrameRateMeasurementEnabled(otherView ? otherView->frameRateMeasurementEnabled() : gShowFrameRate); - - if (otherView) { - view->setItemCacheMode(otherView->itemCacheMode()); - view->setResizesToContents(otherView->resizesToContents()); - } else { - view->setItemCacheMode(gCacheWebView ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache); - view->setResizesToContents(gResizesToContents); - } -} - void LauncherWindow::keyPressEvent(QKeyEvent* event) { #ifdef Q_WS_MAEMO_5 @@ -629,7 +589,7 @@ void LauncherWindow::zoomOut() void LauncherWindow::resetZoom() { m_currentZoom = 100; - page()->mainFrame()->setZoomFactor(1.0); + applyZoom(); } void LauncherWindow::toggleZoomTextOnly(bool b) @@ -711,7 +671,7 @@ void LauncherWindow::setTouchMocking(bool on) void LauncherWindow::toggleAcceleratedCompositing(bool toggle) { - gUseCompositing = toggle; + m_windowOptions.useCompositing = toggle; page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, toggle); } @@ -722,12 +682,13 @@ void LauncherWindow::toggleTiledBackingStore(bool toggle) void LauncherWindow::toggleResizesToContents(bool toggle) { - gResizesToContents = toggle; + m_windowOptions.resizesToContents = toggle; static_cast<WebViewGraphicsBased*>(m_view)->setResizesToContents(toggle); } void LauncherWindow::toggleWebGL(bool toggle) { + m_windowOptions.useWebGL = toggle; page()->settings()->setAttribute(QWebSettings::WebGLEnabled, toggle); } @@ -751,7 +712,7 @@ void LauncherWindow::toggleFullScreenMode(bool enable) void LauncherWindow::toggleFrameFlattening(bool toggle) { - gUseFrameFlattening = toggle; + m_windowOptions.useFrameFlattening = toggle; page()->settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, toggle); } @@ -771,7 +732,7 @@ void LauncherWindow::toggleQGLWidgetViewport(bool enable) if (!isGraphicsBased()) return; - gUseQGLWidgetViewport = enable; + m_windowOptions.useQGLWidgetViewport = enable; WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view); view->setViewport(enable ? new QGLWidget() : 0); @@ -780,13 +741,13 @@ void LauncherWindow::toggleQGLWidgetViewport(bool enable) void LauncherWindow::changeViewportUpdateMode(int mode) { - gViewportUpdateMode = QGraphicsView::ViewportUpdateMode(mode); + m_windowOptions.viewportUpdateMode = QGraphicsView::ViewportUpdateMode(mode); if (!isGraphicsBased()) return; WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view); - view->setViewportUpdateMode(gViewportUpdateMode); + view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode); } void LauncherWindow::showFPS(bool enable) @@ -794,7 +755,7 @@ void LauncherWindow::showFPS(bool enable) if (!isGraphicsBased()) return; - gShowFrameRate = enable; + m_windowOptions.showFrameRate = enable; WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view); view->setFrameRateMeasurementEnabled(enable); @@ -867,14 +828,14 @@ void LauncherWindow::updateFPS(int fps) LauncherWindow* LauncherWindow::newWindow() { - LauncherWindow* mw = new LauncherWindow(this, false); + LauncherWindow* mw = new LauncherWindow(&m_windowOptions); mw->show(); return mw; } LauncherWindow* LauncherWindow::cloneWindow() { - LauncherWindow* mw = new LauncherWindow(this, true); + LauncherWindow* mw = new LauncherWindow(&m_windowOptions, qobject_cast<QGraphicsView*>(m_view)->scene()); mw->show(); return mw; } diff --git a/WebKitTools/QtTestBrowser/launcherwindow.h b/WebKitTools/QtTestBrowser/launcherwindow.h index f9f157d..9319d24 100644 --- a/WebKitTools/QtTestBrowser/launcherwindow.h +++ b/WebKitTools/QtTestBrowser/launcherwindow.h @@ -75,11 +75,48 @@ #undef KeyPress #endif +class WindowOptions { +public: + WindowOptions() + : useGraphicsView(false) + , useCompositing(true) + , useTiledBackingStore(false) + , useWebGL(false) +#if defined(Q_WS_MAEMO_5) || defined(Q_WS_S60) + , useFrameFlattening(true) +#else + , useFrameFlattening(false) +#endif + , cacheWebView(false) + , showFrameRate(false) + , resizesToContents(false) + , viewportUpdateMode(QGraphicsView::MinimalViewportUpdate) +#if defined(QT_CONFIGURED_WITH_OPENGL) + , useQGLWidgetViewport(false) +#endif + { + } + + bool useGraphicsView; + bool useCompositing; + bool useTiledBackingStore; + bool useWebGL; + bool useFrameFlattening; + bool cacheWebView; + bool showFrameRate; + bool resizesToContents; + QGraphicsView::ViewportUpdateMode viewportUpdateMode; +#if defined(QT_CONFIGURED_WITH_OPENGL) + bool useQGLWidgetViewport; +#endif + QUrl inspectorUrl; +}; + class LauncherWindow : public MainWindow { Q_OBJECT public: - LauncherWindow(LauncherWindow* other = 0, bool shareScene = false); + LauncherWindow(WindowOptions* data = 0, QGraphicsScene* sharedScene = 0); virtual ~LauncherWindow(); virtual void keyPressEvent(QKeyEvent* event); @@ -91,22 +128,6 @@ public: bool eventFilter(QObject* obj, QEvent* event); -public: - static const int gExitClickArea = 80; - static bool gUseGraphicsView; - static bool gUseCompositing; - static bool gCacheWebView; - static bool gShowFrameRate; - static bool gResizesToContents; - static bool gUseTiledBackingStore; - static bool gUseFrameFlattening; - static QGraphicsView::ViewportUpdateMode gViewportUpdateMode; - static QUrl gInspectorUrl; - -#if defined(QT_CONFIGURED_WITH_OPENGL) - static bool gUseQGLWidgetViewport; -#endif - protected slots: void loadStarted(); void loadFinished(); @@ -127,7 +148,7 @@ protected slots: /* void dumpPlugins() */ void dumpHtml(); - void initializeView(bool useGraphicsView = false); + void initializeView(); void setTouchMocking(bool on); void toggleAcceleratedCompositing(bool toggle); @@ -158,22 +179,22 @@ signals: void enteredFullScreenMode(bool on); private: - void init(bool useGraphicsView = false); + void init(); bool isGraphicsBased() const; void createChrome(); - void applyPrefs(LauncherWindow* other = 0); + void applyPrefs(); void applyZoom(); private: - QVector<int> m_zoomLevels; + static QVector<int> m_zoomLevels; int m_currentZoom; QWidget* m_view; WebInspector* m_inspector; + WindowOptions m_windowOptions; + QAction* m_formatMenuAction; - QAction* m_flipAnimated; - QAction* m_flipYAnimated; #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) QPropertyAnimation* m_zoomAnimation; diff --git a/WebKitTools/QtTestBrowser/main.cpp b/WebKitTools/QtTestBrowser/main.cpp index 33a6416..842290b 100644 --- a/WebKitTools/QtTestBrowser/main.cpp +++ b/WebKitTools/QtTestBrowser/main.cpp @@ -33,6 +33,8 @@ #include "launcherwindow.h" #include "urlloader.h" +WindowOptions windowOptions; + int launcherMain(const QApplication& app) { #ifndef NDEBUG @@ -89,7 +91,7 @@ LauncherApplication::LauncherApplication(int& argc, char** argv) static void requiresGraphicsView(const QString& option) { - if (LauncherWindow::gUseGraphicsView) + if (windowOptions.useGraphicsView) return; appQuit(1, QString("%1 only works in combination with the -graphicsbased option").arg(option)); } @@ -121,31 +123,31 @@ void LauncherApplication::handleUserOptions() } if (args.contains("-graphicsbased")) - LauncherWindow::gUseGraphicsView = true; + windowOptions.useGraphicsView = true; if (args.contains("-no-compositing")) { requiresGraphicsView("-no-compositing"); - LauncherWindow::gUseCompositing = false; + windowOptions.useCompositing = false; } if (args.contains("-show-fps")) { requiresGraphicsView("-show-fps"); - LauncherWindow::gShowFrameRate = true; + windowOptions.showFrameRate = true; } if (args.contains("-cache-webview")) { requiresGraphicsView("-cache-webview"); - LauncherWindow::gCacheWebView = true; + windowOptions.cacheWebView = true; } if (args.contains("-tiled-backing-store")) { requiresGraphicsView("-tiled-backing-store"); - LauncherWindow::gUseTiledBackingStore = true; + windowOptions.useTiledBackingStore = true; } if (args.contains("-resizes-to-contents")) { requiresGraphicsView("-resizes-to-contents"); - LauncherWindow::gResizesToContents = true; + windowOptions.resizesToContents = true; } QString arg1("-viewport-update-mode"); @@ -160,13 +162,13 @@ void LauncherApplication::handleUserOptions() if (idx == -1) appQuit(1, QString("%1 value has to be one of [%2]").arg(arg1).arg(formatKeys(updateModes))); - LauncherWindow::gViewportUpdateMode = static_cast<QGraphicsView::ViewportUpdateMode>(idx); + windowOptions.viewportUpdateMode = static_cast<QGraphicsView::ViewportUpdateMode>(idx); } QString inspectorUrlArg("-inspector-url"); int inspectorUrlIndex = args.indexOf(inspectorUrlArg); if (inspectorUrlIndex != -1) - LauncherWindow::gInspectorUrl = takeOptionValue(&args, inspectorUrlIndex); + windowOptions.inspectorUrl = takeOptionValue(&args, inspectorUrlIndex); int robotIndex = args.indexOf("-r"); if (robotIndex != -1) { @@ -213,7 +215,7 @@ int main(int argc, char **argv) foreach (QString url, urls) { LauncherWindow* newWindow; if (!window) - newWindow = window = new LauncherWindow(); + newWindow = window = new LauncherWindow(&windowOptions); else newWindow = window->newWindow(); diff --git a/WebKitTools/QtTestBrowser/webview.cpp b/WebKitTools/QtTestBrowser/webview.cpp index d06493e..c8eecd6 100644 --- a/WebKitTools/QtTestBrowser/webview.cpp +++ b/WebKitTools/QtTestBrowser/webview.cpp @@ -79,25 +79,70 @@ WebViewGraphicsBased::WebViewGraphicsBased(QWidget* parent) connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateFrameRate())); } +void WebViewGraphicsBased::setPage(QWebPage* page) +{ + connect(page->mainFrame(), SIGNAL(contentsSizeChanged(const QSize&)), SLOT(contentsSizeChanged(const QSize&))); + m_item->setPage(page); +} + +void WebViewGraphicsBased::contentsSizeChanged(const QSize& size) +{ + if (m_resizesToContents) + scene()->setSceneRect(0, 0, size.width(), size.height()); +} + void WebViewGraphicsBased::setResizesToContents(bool b) { + if (b == m_resizesToContents) + return; + m_resizesToContents = b; m_item->setResizesToContents(m_resizesToContents); + + // When setting resizesToContents ON, our web view widget will always size as big as the + // web content being displayed, and so will the QWebPage's viewport. It implies that internally + // WebCore will work as if there was no content rendered offscreen, and then no scrollbars need + // drawing. In order to keep scrolling working, we: + // + // 1) Set QGraphicsView's scrollbars policy back to 'auto'. + // 2) Set scene's boundaries rect to an invalid size, which automatically makes it to be as big + // as it needs to enclose all items onto it. We do that because QGraphicsView also calculates + // the size of its scrollable area according to the amount of content in scene that is rendered + // offscreen. + // 3) Set QWebPage's preferredContentsSize according to the size of QGraphicsView's viewport, + // so WebCore properly lays pages out. + // + // On the other hand, when toggling resizesToContents OFF, we set back the default values, as + // opposite as described above. if (m_resizesToContents) { setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_item->page()->setPreferredContentsSize(size()); + QRectF itemRect(m_item->geometry().topLeft(), m_item->page()->mainFrame()->contentsSize()); + m_item->setGeometry(itemRect); + scene()->setSceneRect(itemRect); } else { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_item->page()->setPreferredContentsSize(QSize()); + QRect viewportRect(QPoint(0, 0), size()); + m_item->setGeometry(viewportRect); + scene()->setSceneRect(viewportRect); } } void WebViewGraphicsBased::resizeEvent(QResizeEvent* event) { QGraphicsView::resizeEvent(event); - if (m_resizesToContents) + + QSize size(event->size()); + + if (m_resizesToContents) { + m_item->page()->setPreferredContentsSize(size); return; - QRectF rect(QPoint(0, 0), event->size()); + } + + QRectF rect(QPoint(0, 0), size); m_item->setGeometry(rect); scene()->setSceneRect(rect); } diff --git a/WebKitTools/QtTestBrowser/webview.h b/WebKitTools/QtTestBrowser/webview.h index 9b533b3..5e7c0c3 100644 --- a/WebKitTools/QtTestBrowser/webview.h +++ b/WebKitTools/QtTestBrowser/webview.h @@ -71,14 +71,15 @@ class WebViewGraphicsBased : public QGraphicsView { public: WebViewGraphicsBased(QWidget* parent); - virtual void resizeEvent(QResizeEvent*); - void setPage(QWebPage* page) { m_item->setPage(page); } + void setPage(QWebPage* page); + void setItemCacheMode(QGraphicsItem::CacheMode mode) { m_item->setCacheMode(mode); } QGraphicsItem::CacheMode itemCacheMode() { return m_item->cacheMode(); } void setFrameRateMeasurementEnabled(bool enabled); bool frameRateMeasurementEnabled() const { return m_measureFps; } + virtual void resizeEvent(QResizeEvent*); virtual void paintEvent(QPaintEvent* event); void setResizesToContents(bool b); @@ -106,6 +107,7 @@ public slots: void updateFrameRate(); void animatedFlip(); void animatedYFlip(); + void contentsSizeChanged(const QSize&); signals: void yFlipRequest(); diff --git a/WebKitTools/QueueStatusServer/handlers/queuestatus.py b/WebKitTools/QueueStatusServer/handlers/queuestatus.py new file mode 100644 index 0000000..6282a98 --- /dev/null +++ b/WebKitTools/QueueStatusServer/handlers/queuestatus.py @@ -0,0 +1,58 @@ +# Copyright (C) 2010 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 google.appengine.ext import webapp +from google.appengine.ext.webapp import template + +from model.queues import queues, display_name_for_queue +from model.workitems import WorkItems + +from model import queuestatus + + +class QueueStatus(webapp.RequestHandler): + def _rows_for_work_items(self, work_items): + if not work_items: + return [] + rows = [] + for item_id in work_items.item_ids: + rows.append({ + "attachment_id": item_id, + "bug_id": 1, + }) + return rows + + def get(self, queue_name): + work_items = WorkItems.all().filter("queue_name =", queue_name).get() + statuses = queuestatus.QueueStatus.all().filter("queue_name =", queue_name).order("-date").fetch(6) + template_values = { + "display_queue_name": display_name_for_queue(queue_name), + "work_item_rows": self._rows_for_work_items(work_items), + "statuses": statuses, + } + self.response.out.write(template.render("templates/queuestatus.html", template_values)) diff --git a/WebKitTools/QueueStatusServer/handlers/recentstatus.py b/WebKitTools/QueueStatusServer/handlers/recentstatus.py index d1df78c..e2b8c2f 100644 --- a/WebKitTools/QueueStatusServer/handlers/recentstatus.py +++ b/WebKitTools/QueueStatusServer/handlers/recentstatus.py @@ -26,32 +26,68 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import datetime + from google.appengine.ext import webapp from google.appengine.ext.webapp import template -from model.queues import queues +from model.queues import queues, display_name_for_queue from model.queuestatus import QueueStatus +from model.workitems import WorkItems + + +class QueueBubble(object): + """View support class for recentstatus.html""" + def __init__(self, queue_name): + self._queue_name = queue_name + self._work_items = WorkItems.all().filter("queue_name =", queue_name).get() + self._last_status = QueueStatus.all().filter("queue_name =", queue_name).order("-date").get() + + def name(self): + return self._queue_name + + def display_name(self): + return display_name_for_queue(self._queue_name) + + def _last_status_date(self): + if not self._last_status: + return None + return self._last_status.date + + def last_heard_from(self): + if not self._work_items: + return self._last_status_date() + return max(self._last_status_date(), self._work_items.date) + + def is_alive(self): + if not self.last_heard_from(): + return False + return self.last_heard_from() > (datetime.datetime.now() - datetime.timedelta(minutes=30)) + + def status_class(self): + if not self.is_alive(): + return "dead" + if self.pending_items_count() > 1: + return "behind" + return "alive" + + def status_text(self): + if not self._work_items: + return "Offline" + if not self._work_items.item_ids: + return "Idle" + return self._last_status.message + + def pending_items_count(self): + if not self._work_items: + return 0 + return len(self._work_items.item_ids) + -class RecentStatus(webapp.RequestHandler): - def _title_case(self, string): - words = string.split(" ") - words = map(lambda word: word.capitalize(), words) - return " ".join(words) - - def _pretty_queue_name(self, queue_name): - return self._title_case(queue_name.replace("-", " ")) - - # We could change "/" to just redirect to /queue-status/commit-queue in the future - # at which point we would not need a default value for queue_name here. - def get(self, queue_name="commit-queue"): - queue_status = {} - for queue in queues: - statuses = QueueStatus.all().filter("queue_name =", queue).order("-date").fetch(6) - if not statuses: - continue - queue_status[queue] = statuses +class QueuesOverview(webapp.RequestHandler): + def get(self): template_values = { - "queue_status" : queue_status, + "queues": [QueueBubble(queue_name) for queue_name in queues], } self.response.out.write(template.render("templates/recentstatus.html", template_values)) diff --git a/WebKitTools/QueueStatusServer/main.py b/WebKitTools/QueueStatusServer/main.py index fb6fc4b..e550dc5 100644 --- a/WebKitTools/QueueStatusServer/main.py +++ b/WebKitTools/QueueStatusServer/main.py @@ -37,7 +37,8 @@ from handlers.dashboard import Dashboard from handlers.gc import GC from handlers.patch import Patch from handlers.patchstatus import PatchStatus -from handlers.recentstatus import RecentStatus +from handlers.queuestatus import QueueStatus +from handlers.recentstatus import QueuesOverview from handlers.showresults import ShowResults from handlers.statusbubble import StatusBubble from handlers.svnrevision import SVNRevision @@ -49,7 +50,7 @@ from handlers.updateworkitems import UpdateWorkItems webapp.template.register_template_library('filters.webkit_extras') routes = [ - ('/', RecentStatus), + ('/', QueuesOverview), ('/dashboard', Dashboard), ('/gc', GC), (r'/patch-status/(.*)/(.*)', PatchStatus), @@ -57,7 +58,7 @@ routes = [ (r'/results/(.*)', ShowResults), (r'/status-bubble/(.*)', StatusBubble), (r'/svn-revision/(.*)', SVNRevision), - (r'/queue-status/(.*)', RecentStatus), + (r'/queue-status/(.*)', QueueStatus), ('/update-status', UpdateStatus), ('/update-work-items', UpdateWorkItems), ('/update-svn-revision', UpdateSVNRevision), diff --git a/WebKitTools/QueueStatusServer/model/queues.py b/WebKitTools/QueueStatusServer/model/queues.py index 46f2f15..2f0884f 100644 --- a/WebKitTools/QueueStatusServer/model/queues.py +++ b/WebKitTools/QueueStatusServer/model/queues.py @@ -41,6 +41,24 @@ queues = [ ] +# FIXME: We need some sort of Queue object. +def _title_case(string): + words = string.split(" ") + words = map(lambda word: word.capitalize(), words) + return " ".join(words) + + +def display_name_for_queue(queue_name): + # HACK: chromium-ews is incorrectly named. + display_name = queue_name.replace("chromium-ews", "cr-linux-ews") + + display_name = display_name.replace("-", " ") + display_name = display_name.replace("cr", "chromium") + display_name = _title_case(display_name) + display_name = display_name.replace("Ews", "EWS") + return display_name + + def name_with_underscores(dashed_name): regexp = re.compile("-") return regexp.sub("_", dashed_name) diff --git a/WebKitTools/QueueStatusServer/templates/queuestatus.html b/WebKitTools/QueueStatusServer/templates/queuestatus.html new file mode 100644 index 0000000..38c125f --- /dev/null +++ b/WebKitTools/QueueStatusServer/templates/queuestatus.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> +<head> +<title>{{ display_queue_name }} Status</title> +<link type="text/css" rel="stylesheet" href="/stylesheets/dashboard.css" /> +</head> +<body> +<h1>{{ display_queue_name }} Status</h1> + +<h3>Recent Status</h3> + +<div class="status-details"> + <ul> + {% for status in statuses %} + <li>{% if status.active_bug_id %} + <span class="status-bug"> + Patch {{ status.active_patch_id|force_escape|webkit_attachment_id|safe }} from bug + {{ status.active_bug_id|force_escape|webkit_bug_id|safe }}: + </span>{% endif %} + <span class="status-message">{{ status.message|force_escape|urlize|webkit_linkify|safe }}</span> + {% if status.results_file %} + <span class="status-results">[{{ status.key.id|results_link|safe }}]</span> + {% endif %} + <span class="status-date">{{ status.date|timesince }} ago</span> + </li> + {% endfor %} + </ul> +</div> + +<h3>Patches in queue</h3> +<table> + <tr><th>Position</th><th>Patch</th></tr> + {% for row in work_item_rows %} + <tr> + <td>#{{ forloop.counter }}</td> + <td> + {{ row.attachment_id|force_escape|webkit_attachment_id|safe }} + </td> + </tr> + {% endfor %} +</table> + +</body> +</html> diff --git a/WebKitTools/QueueStatusServer/templates/recentstatus.html b/WebKitTools/QueueStatusServer/templates/recentstatus.html index 2bb9fbb..808d8d7 100644 --- a/WebKitTools/QueueStatusServer/templates/recentstatus.html +++ b/WebKitTools/QueueStatusServer/templates/recentstatus.html @@ -3,22 +3,52 @@ <head> <title>WebKit Queue Status</title> <link type="text/css" rel="stylesheet" href="/stylesheets/dashboard.css" /> +<style> +.queue_bubble { + border: 1px solid black; + margin-bottom: 10px; + border-radius: 10px; + padding: 5px; +} +.queue_name { + float:left; +} +.last_heard_from { + float: right; +} +.status_text { + clear: both; +} +.alive { + background-color: #8FDF5F; +} +.behind { + background-color: #FFFC6C; +} +.dead { + background-color: #E98080; +} +</style> </head> <body> -<h1>WebKit Queue Status</h1>{% for queue_name, statuses in queue_status.items %} -<div class="status-details"> - <h2>{{ queue_name }}</h2> - <ul>{% for status in statuses %} - <li>{% if status.active_bug_id %} - <span class="status-bug"> - Patch {{ status.active_patch_id|force_escape|webkit_attachment_id|safe }} from bug - {{ status.active_bug_id|force_escape|webkit_bug_id|safe }}: - </span>{% endif %} - <span class="status-message">{{ status.message|force_escape|urlize|webkit_linkify|safe }}</span>{% if status.results_file %} - <span class="status-results">[{{ status.key.id|results_link|safe }}]</span>{% endif %} - <span class="status-date">{{ status.date|timesince }} ago</span> - </li>{% endfor %} - </ul> -</div>{% endfor %} +<h1>WebKit Queue Status</h1> +{% for queue in queues %} +<div class="queue_bubble {{ queue.status_class }}"> + <div class="queue_name"> + <a href="/queue-status/{{ queue.name }}"> + {{ queue.display_name }} + </a> + </div> + {% if queue.last_heard_from %} + <div class="last_heard_from">{{ queue.last_heard_from|timesince }} ago</div> + {% endif %} + <div class="status_text"> + Status: {{ queue.status_text|force_escape|urlize|webkit_linkify|safe }} + </div> + <div> + {{ queue.pending_items_count }} pending + </div> +</div> +{% endfor %} </body> </html> diff --git a/WebKitTools/Scripts/build-webkit b/WebKitTools/Scripts/build-webkit index 4639949..3b8dd9c 100755 --- a/WebKitTools/Scripts/build-webkit +++ b/WebKitTools/Scripts/build-webkit @@ -60,8 +60,8 @@ my ($linkPrefetchSupport, $threeDCanvasSupport, $threeDRenderingSupport, $channe $javaScriptDebuggerSupport, $mathmlSupport, $offlineWebApplicationSupport, $rubySupport, $systemMallocSupport, $sandboxSupport, $sharedWorkersSupport, $svgSupport, $svgAnimationSupport, $svgAsImageSupport, $svgDOMObjCBindingsSupport, $svgFontsSupport, $svgForeignObjectSupport, $svgUseSupport, $videoSupport, $webSocketsSupport, $webTimingSupport, $wmlSupport, $wcssSupport, $xhtmlmpSupport, $workersSupport, - $xpathSupport, $xsltSupport, $coverageSupport, $notificationsSupport, $blobSliceSupport, $tiledBackingStoreSupport, - $fileReaderSupport, $fileWriterSupport, $fileSystemSupport, $directoryUploadSupport, $deviceOrientationSupport); + $xpathSupport, $xsltSupport, $coverageSupport, $notificationsSupport, $blobSupport, $tiledBackingStoreSupport, + $fileWriterSupport, $fileSystemSupport, $directoryUploadSupport, $deviceOrientationSupport); my @features = ( { option => "link-prefetch", desc => "Toggle pre fetching support", @@ -73,8 +73,8 @@ my @features = ( { option => "3d-rendering", desc => "Toggle 3D rendering support", define => "ENABLE_3D_RENDERING", default => (isAppleMacWebKit() && !isTiger()), value => \$threeDRenderingSupport }, - { option => "blob-slice", desc => "Toggle Blob.slice support", - define => "ENABLE_BLOB_SLICE", default => (isAppleMacWebKit()), value => \$blobSliceSupport }, + { option => "blob", desc => "Toggle Blob support", + define => "ENABLE_BLOB", default => (isAppleMacWebKit()), value => \$blobSupport }, { option => "channel-messaging", desc => "Toggle MessageChannel and MessagePort support", define => "ENABLE_CHANNEL_MESSAGING", default => 1, value => \$channelMessagingSupport }, @@ -125,7 +125,7 @@ my @features = ( define => "ENABLE_JAVASCRIPT_DEBUGGER", default => 1, value => \$javaScriptDebuggerSupport }, { option => "mathml", desc => "Toggle MathML support", - define => "ENABLE_MATHML", default => 0, value => \$mathmlSupport }, + define => "ENABLE_MATHML", default => 1, value => \$mathmlSupport }, { option => "notifications", desc => "Toggle Desktop Notifications Support", define => "ENABLE_NOTIFICATIONS", default => 0, value => \$notificationsSupport }, @@ -196,9 +196,6 @@ my @features = ( { option => "xslt", desc => "Toggle XSLT support", define => "ENABLE_XSLT", default => 1, value => \$xsltSupport }, - { option => "file-reader", desc => "Toggle FileReader support", - define => "ENABLE_FILE_READER", default => isAppleWebKit(), value => \$fileReaderSupport }, - { option => "file-writer", desc => "Toggle FileWriter support", define => "ENABLE_FILE_WRITER", default => 0, value => \$fileWriterSupport }, diff --git a/WebKitTools/Scripts/check-webkit-style b/WebKitTools/Scripts/check-webkit-style index 9a1ae1e..e29d4b1 100755 --- a/WebKitTools/Scripts/check-webkit-style +++ b/WebKitTools/Scripts/check-webkit-style @@ -121,11 +121,12 @@ def main(): error_count = style_processor.error_count file_count = file_reader.file_count + delete_only_file_count = file_reader.delete_only_file_count _log.info("Total errors found: %d in %d files" % (error_count, file_count)) # We fail when style errors are found or there are no checked files. - sys.exit(error_count > 0 or file_count == 0) + sys.exit(error_count > 0 or (file_count == 0 and delete_only_file_count == 0)) if __name__ == "__main__": diff --git a/WebKitTools/Scripts/old-run-webkit-tests b/WebKitTools/Scripts/old-run-webkit-tests index b46c129..97ef3dc 100755 --- a/WebKitTools/Scripts/old-run-webkit-tests +++ b/WebKitTools/Scripts/old-run-webkit-tests @@ -2159,7 +2159,14 @@ sub readSkippedFiles($) { my ($constraintPath) = @_; - foreach my $level (@platformTestHierarchy) { + my @skippedFileDirectories = @platformTestHierarchy; + + # Because nearly all of the skipped tests for WebKit 2 on Mac are due to + # cross-platform issues, Windows will use both the Mac and Windows skipped + # lists to avoid maintaining separate lists. + push(@skippedFileDirectories, catdir($platformBaseDirectory, "mac-wk2")) if $platform eq "win-wk2"; + + foreach my $level (@skippedFileDirectories) { if (open SKIPPED, "<", "$level/Skipped") { if ($verbose) { my ($dir, $name) = splitpath($level); diff --git a/WebKitTools/Scripts/prepare-ChangeLog b/WebKitTools/Scripts/prepare-ChangeLog index 2ef1eb4..1488939 100755 --- a/WebKitTools/Scripts/prepare-ChangeLog +++ b/WebKitTools/Scripts/prepare-ChangeLog @@ -264,8 +264,16 @@ if ($bugNumber) { # care about validating that bugs.webkit.org is who it says it is here. my $descriptionLine = `curl --insecure --silent "$bugXMLURL" | grep short_desc`; if ($descriptionLine !~ /<short_desc>(.*)<\/short_desc>/) { - print STDERR " Bug $bugNumber has no bug description. Maybe you set wrong bug ID?\n"; - print STDERR " The bug URL: $bugXMLURL\n"; + # Maybe the reason the above did not work is because the curl that is installed doesn't + # support ssl at all. + if (`curl --version | grep ^Protocols` !~ /\bhttps\b/) { + print STDERR " Could not get description for bug $bugNumber.\n"; + print STDERR " It looks like your version of curl does not support ssl.\n"; + print STDERR " If you are using macports, this can be fixed with sudo port install curl+ssl.\n"; + } else { + print STDERR " Bug $bugNumber has no bug description. Maybe you set wrong bug ID?\n"; + print STDERR " The bug URL: $bugXMLURL\n"; + } exit 1; } $bugDescription = decodeEntities($1); diff --git a/WebKitTools/Scripts/webkitpy/common/config/committers.py b/WebKitTools/Scripts/webkitpy/common/config/committers.py index 25b1725..5ebf18a 100644 --- a/WebKitTools/Scripts/webkitpy/common/config/committers.py +++ b/WebKitTools/Scripts/webkitpy/common/config/committers.py @@ -123,6 +123,7 @@ committers_unable_to_review = [ Committer("Jessie Berlin", ["jberlin@webkit.org", "jberlin@apple.com"]), Committer("Jesus Sanchez-Palencia", ["jesus@webkit.org", "jesus.palencia@openbossa.org"], "jeez_"), Committer("Jocelyn Turcotte", "jocelyn.turcotte@nokia.com", "jturcotte"), + Committer("Jochen Eisinger", "jochen@chromium.org", "jochen__"), Committer("John Abd-El-Malek", "jam@chromium.org", "jam"), Committer("John Gregg", ["johnnyg@google.com", "johnnyg@chromium.org"], "johnnyg"), Committer("Joost de Valk", ["joost@webkit.org", "webkit-dev@joostdevalk.nl"], "Altha"), diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py index c0525ea..6c36c93 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_layout_results_generator.py @@ -56,7 +56,8 @@ class JSONLayoutResultsGenerator(json_results_generator.JSONResultsGeneratorBase def __init__(self, port, builder_name, build_name, build_number, results_file_base_path, builder_base_url, - test_timings, expectations, result_summary, all_tests): + test_timings, expectations, result_summary, all_tests, + generate_incremental_results=False): """Modifies the results.json file. Grabs it off the archive directory if it is not found locally. @@ -66,7 +67,8 @@ class JSONLayoutResultsGenerator(json_results_generator.JSONResultsGeneratorBase """ super(JSONLayoutResultsGenerator, self).__init__( builder_name, build_name, build_number, results_file_base_path, - builder_base_url, {}, port.test_repository_paths()) + builder_base_url, {}, port.test_repository_paths(), + generate_incremental_results) self._port = port self._expectations = expectations diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py index 595fc2b..e746bc0 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py @@ -60,7 +60,7 @@ class TestResult(object): class JSONResultsGeneratorBase(object): """A JSON results generator for generic tests.""" - MAX_NUMBER_OF_BUILD_RESULTS_TO_LOG = 750 + MAX_NUMBER_OF_BUILD_RESULTS_TO_LOG = 1500 # Min time (seconds) that will be added to the JSON. MIN_TIME = 1 JSON_PREFIX = "ADD_RESULTS(" @@ -82,10 +82,12 @@ class JSONResultsGeneratorBase(object): ALL_FIXABLE_COUNT = "allFixableCount" RESULTS_FILENAME = "results.json" + INCREMENTAL_RESULTS_FILENAME = "incremental_results.json" def __init__(self, builder_name, build_name, build_number, results_file_base_path, builder_base_url, - test_results_map, svn_repositories=None): + test_results_map, svn_repositories=None, + generate_incremental_results=False): """Modifies the results.json file. Grabs it off the archive directory if it is not found locally. @@ -108,41 +110,59 @@ class JSONResultsGeneratorBase(object): self._builder_base_url = builder_base_url self._results_file_path = os.path.join(results_file_base_path, self.RESULTS_FILENAME) + self._incremental_results_file_path = os.path.join( + results_file_base_path, self.INCREMENTAL_RESULTS_FILENAME) self._test_results_map = test_results_map self._test_results = test_results_map.values() + self._generate_incremental_results = generate_incremental_results self._svn_repositories = svn_repositories if not self._svn_repositories: self._svn_repositories = {} self._json = None + self._archived_results = None def generate_json_output(self): """Generates the JSON output file.""" + + # Generate the JSON output file that has full results. + # FIXME: stop writing out the full results file once all bots use + # incremental results. if not self._json: self._json = self.get_json() if self._json: - # Specify separators in order to get compact encoding. - json_data = simplejson.dumps(self._json, separators=(',', ':')) - json_string = self.JSON_PREFIX + json_data + self.JSON_SUFFIX + self._generate_json_file(self._json, self._results_file_path) - results_file = codecs.open(self._results_file_path, "w", "utf-8") - results_file.write(json_string) - results_file.close() + # Generate the JSON output file that only has incremental results. + if self._generate_incremental_results: + json = self.get_json(incremental=True) + if json: + self._generate_json_file( + json, self._incremental_results_file_path) - def get_json(self): + def get_json(self, incremental=False): """Gets the results for the results.json file.""" - if self._json: - return self._json - - results_json, error = self._get_archived_json_results() - if error: - # If there was an error don't write a results.json - # file at all as it would lose all the information on the bot. - _log.error("Archive directory is inaccessible. Not modifying " - "or clobbering the results.json file: " + str(error)) - return None + if incremental: + results_json = {} + else: + if self._json: + return self._json + + if not self._archived_results: + self._archived_results, error = \ + self._get_archived_json_results() + if error: + # If there was an error don't write a results.json + # file at all as it would lose all the information on the + # bot. + _log.error("Archive directory is inaccessible. Not " + "modifying or clobbering the results.json " + "file: " + str(error)) + return None + + results_json = self._archived_results builder_name = self._builder_name if results_json and builder_name not in results_json: @@ -168,8 +188,19 @@ class JSONResultsGeneratorBase(object): for test in all_failing_tests: self._insert_test_time_and_result(test, tests) - self._json = results_json - return self._json + return results_json + + def set_archived_results(self, archived_results): + self._archived_results = archived_results + + def _generate_json_file(self, json, file_path): + # Specify separators in order to get compact encoding. + json_data = simplejson.dumps(json, separators=(',', ':')) + json_string = self.JSON_PREFIX + json_data + self.JSON_SUFFIX + + results_file = codecs.open(file_path, "w", "utf-8") + results_file.write(json_string) + results_file.close() def _get_test_timing(self, test_name): """Returns test timing data (elapsed time) in second diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py index 0a60cc7..785cc1c 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator_unittest.py @@ -45,6 +45,13 @@ class JSONGeneratorTest(unittest.TestCase): self.builder_name = 'DUMMY_BUILDER_NAME' self.build_name = 'DUMMY_BUILD_NAME' self.build_number = 'DUMMY_BUILDER_NUMBER' + self._json = None + self._num_runs = 0 + self._tests_list = set([]) + self._test_timings = {} + self._failed_tests = {} + self._passed_tests = set([]) + self._skipped_tests = set([]) def _test_json_generation(self, passed_tests, failed_tests, skipped_tests): # Make sure we have sets (rather than lists). @@ -52,12 +59,13 @@ class JSONGeneratorTest(unittest.TestCase): skipped_tests = set(skipped_tests) tests_list = passed_tests | set(failed_tests.keys()) test_timings = {} + i = 0 for test in tests_list: - test_timings[test] = float(random.randint(1, 10)) + test_timings[test] = float(self._num_runs * 100 + i) + i += 1 port_obj = port.get(None) - # Generate a JSON file. generator = json_results_generator.JSONResultsGenerator(port_obj, self.builder_name, self.build_name, self.build_number, '', @@ -68,8 +76,39 @@ class JSONGeneratorTest(unittest.TestCase): skipped_tests, tests_list) - json = generator.get_json() - + # Test incremental json results + incremental_json = generator.get_json(incremental=True) + self._verify_json_results( + tests_list, + test_timings, + passed_tests, + failed_tests, + skipped_tests, + incremental_json, + 1) + + # Test aggregated json results + generator.set_archived_results(self._json) + json = generator.get_json(incremental=False) + self._json = json + self._num_runs += 1 + self._tests_list |= tests_list + self._test_timings.update(test_timings) + self._failed_tests.update(failed_tests) + self._passed_tests |= passed_tests + self._skipped_tests |= skipped_tests + self._verify_json_results( + self._tests_list, + self._test_timings, + self._passed_tests, + self._failed_tests, + self._skipped_tests, + self._json, + self._num_runs) + + def _verify_json_results(self, tests_list, test_timings, + passed_tests, failed_tests, + skipped_tests, json, num_runs): # Aliasing to a short name for better access to its constants. JRG = json_results_generator.JSONResultsGenerator @@ -79,11 +118,18 @@ class JSONGeneratorTest(unittest.TestCase): buildinfo = json[self.builder_name] self.assertTrue(JRG.FIXABLE in buildinfo) self.assertTrue(JRG.TESTS in buildinfo) - self.assertTrue(len(buildinfo[JRG.BUILD_NUMBERS]) == 1) + self.assertTrue(len(buildinfo[JRG.BUILD_NUMBERS]) == num_runs) self.assertTrue(buildinfo[JRG.BUILD_NUMBERS][0] == self.build_number) - if tests_list or skipped_tests: - fixable = buildinfo[JRG.FIXABLE][0] + if tests_list or skipped_tests: + fixable = {} + for fixable_items in buildinfo[JRG.FIXABLE]: + for (type, count) in fixable_items.iteritems(): + if type in fixable: + fixable[type] = fixable[type] + count + else: + fixable[type] = count + if passed_tests: self.assertTrue(fixable[JRG.PASS_RESULT] == len(passed_tests)) else: @@ -100,26 +146,35 @@ class JSONGeneratorTest(unittest.TestCase): for test_name, failure in failed_tests.iteritems(): self.assertTrue(test_name in tests) test = tests[test_name] - self.assertTrue(test[JRG.RESULTS][0][0] == 1) - self.assertTrue(test[JRG.RESULTS][0][1] == JRG.FAIL_RESULT) - self.assertTrue(test[JRG.TIMES][0][0] == 1) - self.assertTrue(test[JRG.TIMES][0][1] == - int(test_timings[test_name])) + + failed = 0 + for result in test[JRG.RESULTS]: + if result[1] == JRG.FAIL_RESULT: + failed = result[0] + self.assertTrue(failed == 1) + + timing_count = 0 + for timings in test[JRG.TIMES]: + if timings[1] == test_timings[test_name]: + timing_count = timings[0] + self.assertTrue(timing_count == 1) fixable_count = len(skipped_tests) + len(failed_tests.keys()) if skipped_tests or failed_tests: - self.assertTrue(buildinfo[JRG.FIXABLE_COUNT][0] == fixable_count) + self.assertTrue(sum(buildinfo[JRG.FIXABLE_COUNT]) == fixable_count) def test_json_generation(self): reason = test_expectations.TEXT self._test_json_generation([], {}, []) - self._test_json_generation(['A', 'B'], {}, []) - self._test_json_generation([], {'A': reason, 'B': reason}, []) - self._test_json_generation([], {}, ['A', 'B']) - self._test_json_generation(['A'], {'B': reason, 'C': reason}, []) - self._test_json_generation([], {'A': reason, 'B': reason}, ['C', 'D']) - self._test_json_generation(['A', 'B', 'C'], {'D': reason}, ['E', 'F']) + self._test_json_generation(['A1', 'B1'], {}, []) + self._test_json_generation([], {'A2': reason, 'B2': reason}, []) + self._test_json_generation([], {}, ['A3', 'B3']) + self._test_json_generation(['A4'], {'B4': reason, 'C4': reason}, []) + self._test_json_generation( + [], {'A5': reason, 'B5': reason}, ['C5', 'D5']) + self._test_json_generation( + ['A6', 'B6', 'C6'], {'D6': reason}, ['E6', 'F6']) if __name__ == '__main__': diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py index 81bf39e..7346671 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py @@ -60,7 +60,7 @@ _DEFAULT_WSS_PORT = 9323 def url_is_alive(url): """Checks to see if we get an http response from |url|. - We poll the url 5 times with a 1 second delay. If we don't + We poll the url 20 times with a 0.5 second delay. If we don't get a reply in that time, we give up and assume the httpd didn't start properly. @@ -70,7 +70,7 @@ def url_is_alive(url): True if the url is alive. """ sleep_time = 0.5 - wait_time = 5 + wait_time = 10 while wait_time > 0: try: response = urllib.urlopen(url) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py index 41aab62..490ac3c 100755 --- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py @@ -889,7 +889,8 @@ class TestRunner: self._port, self._options.builder_name, self._options.build_name, self._options.build_number, self._options.results_directory, BUILDER_BASE_URL, individual_test_timings, - self._expectations, result_summary, self._test_files_list) + self._expectations, result_summary, self._test_files_list, + not self._options.upload_full_results) _log.debug("Finished writing JSON files.") @@ -900,8 +901,12 @@ class TestRunner: _log.info("Uploading JSON files for builder: %s", self._options.builder_name) - attrs = [('builder', self._options.builder_name)] - json_files = ["expectations.json", "results.json"] + attrs = [("builder", self._options.builder_name)] + json_files = ["expectations.json"] + if self._options.upload_full_results: + json_files.append("results.json") + else: + json_files.append("incremental_results.json") files = [(file, os.path.join(self._options.results_directory, file)) for file in json_files] @@ -1656,6 +1661,10 @@ def parse_args(args=None): optparse.make_option("--test-results-server", default="", help=("If specified, upload results json files to this appengine " "server.")), + optparse.make_option("--upload-full-results", + action="store_true", + default=False, + help="If true, upload full json results to server."), ] option_list = (configuration_options + print_options + diff --git a/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py b/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py index 9e4240c..62f40ea 100644 --- a/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py @@ -2451,6 +2451,9 @@ def check_identifier_name_in_declaration(filename, line_number, line, error): line = sub(r'(unsigned|signed) (?=char|short|int|long)', '', line) line = sub(r'\b(inline|using|static|const|volatile|auto|register|extern|typedef|restrict|struct|class|virtual)(?=\W)', '', line) + # Remove "new" and "new (expr)" to simplify, too. + line = sub(r'new\s*(\([^)]*\))?', '', line) + # Remove all template parameters by removing matching < and >. # Loop until no templates are removed to remove nested templates. while True: diff --git a/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py b/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py index c927db6..16b1a3c 100644 --- a/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py @@ -3715,6 +3715,12 @@ class WebKitStyleTest(CppStyleTestBase): self.assert_lint('unsigned _fillRule : 1;', '_fillRule' + name_underscore_error_message) + # new operators in initialization. + self.assert_lint('OwnPtr<uint32_t> variable(new uint32_t);', '') + self.assert_lint('OwnPtr<uint32_t> variable(new (expr) uint32_t);', '') + self.assert_lint('OwnPtr<uint32_t> under_score(new uint32_t);', + 'under_score' + name_underscore_error_message) + def test_comments(self): # A comment at the beginning of a line is ok. diff --git a/WebKitTools/Scripts/webkitpy/style/filereader.py b/WebKitTools/Scripts/webkitpy/style/filereader.py index 48455b3..1a24cb5 100644 --- a/WebKitTools/Scripts/webkitpy/style/filereader.py +++ b/WebKitTools/Scripts/webkitpy/style/filereader.py @@ -47,6 +47,10 @@ class TextFileReader(object): file_count: The total number of files passed to this instance for processing, including non-text files and files that should be skipped. + delete_only_file_count: The total number of files that are not + processed this instance actually because + the files don't have any modified lines + but should be treated as processed. """ @@ -59,6 +63,7 @@ class TextFileReader(object): """ self._processor = processor self.file_count = 0 + self.delete_only_file_count = 0 def _read_lines(self, file_path): """Read the file at a path, and return its lines. @@ -146,3 +151,12 @@ class TextFileReader(object): self._process_directory(directory=path) else: self.process_file(path) + + def count_delete_only_file(self): + """Count up files that contains only deleted lines. + + Files which has no modified or newly-added lines don't need + to check style, but should be treated as checked. For that + purpose, we just count up the number of such files. + """ + self.delete_only_file_count += 1 diff --git a/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py b/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py index 558ec5a..6328337 100644 --- a/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py @@ -159,3 +159,8 @@ class TextFileReaderTest(LoggingTestCase): processed = [(['bar'], file_path2, None), (['foo'], file_path1, None)] self._assert_file_reader(processed, 2) + + def test_count_delete_only_file(self): + self._file_reader.count_delete_only_file() + delete_only_file_count = self._file_reader.delete_only_file_count + self.assertEquals(delete_only_file_count, 1) diff --git a/WebKitTools/Scripts/webkitpy/style/patchreader.py b/WebKitTools/Scripts/webkitpy/style/patchreader.py index 7ba2b66..576504a 100644 --- a/WebKitTools/Scripts/webkitpy/style/patchreader.py +++ b/WebKitTools/Scripts/webkitpy/style/patchreader.py @@ -73,3 +73,8 @@ class PatchReader(object): if line_numbers: self._text_file_reader.process_file(file_path=path, line_numbers=line_numbers) + else: + # We don't check the file which contains deleted lines only + # but would like to treat it as to be processed so that + # we count up number of such files. + self._text_file_reader.count_delete_only_file() diff --git a/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py b/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py index 10791e4..2453c6b 100644 --- a/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/patchreader_unittest.py @@ -45,10 +45,15 @@ class PatchReaderTest(unittest.TestCase): def __init__(self): self.passed_to_process_file = [] """A list of (file_path, line_numbers) pairs.""" + self.delete_only_file_count = 0 + """A number of times count_delete_only_file() called""" def process_file(self, file_path, line_numbers): self.passed_to_process_file.append((file_path, line_numbers)) + def count_delete_only_file(self): + self.delete_only_file_count += 1 + def setUp(self): file_reader = self.MockTextFileReader() self._file_reader = file_reader @@ -57,9 +62,11 @@ class PatchReaderTest(unittest.TestCase): def _call_check_patch(self, patch_string): self._patch_checker.check(patch_string) - def _assert_checked(self, passed_to_process_file): + def _assert_checked(self, passed_to_process_file, delete_only_file_count): self.assertEquals(self._file_reader.passed_to_process_file, passed_to_process_file) + self.assertEquals(self._file_reader.delete_only_file_count, + delete_only_file_count) def test_check_patch(self): # The modified line_numbers array for this patch is: [2]. @@ -71,7 +78,7 @@ index ef65bee..e3db70e 100644 # Required for Python to search this directory for module files +# New line """) - self._assert_checked([("__init__.py", set([2]))]) + self._assert_checked([("__init__.py", set([2]))], 0) def test_check_patch_with_deletion(self): self._call_check_patch("""Index: __init__.py @@ -82,4 +89,4 @@ index ef65bee..e3db70e 100644 -foobar """) # _mock_check_file should not be called for the deletion patch. - self._assert_checked([]) + self._assert_checked([], 1) diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py index 704970d..3a7aff3 100644 --- a/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py +++ b/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py @@ -79,7 +79,7 @@ installer.install(url="http://www.adambarth.com/webkit/eliza", rietveld_dir = os.path.join(autoinstalled_dir, "rietveld") installer = AutoInstaller(target_dir=rietveld_dir) -installer.install(url="http://webkit-rietveld.googlecode.com/svn/trunk/static/upload.py", +installer.install(url="http://webkit-rietveld.googlecode.com/svn/trunk/upload.py", target_name="upload.py") diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py index a1a66a1..36cbc5f 100644 --- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py +++ b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py @@ -107,7 +107,8 @@ class QueueEngine: self._open_work_log(work_item) try: if not self._delegate.process_work_item(work_item): - self._sleep("Unable to process work item.") + log("Unable to process work item.") + continue except ScriptError, e: # Use a special exit code to indicate that the error was already # handled in the child process and we should just keep looping. diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py index 9fbfda6..750bbfd 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py @@ -152,8 +152,8 @@ class AbstractCommitterOnlyEWS(AbstractEarlyWarningSystem): def process_work_item(self, patch): if not self._committers.committer_by_email(patch.attacher_email()): self._did_error(patch, "%s cannot process patches from non-committers :(" % self.name) - return - AbstractEarlyWarningSystem.process_work_item(self, patch) + return False + return AbstractEarlyWarningSystem.process_work_item(self, patch) class MacEWS(AbstractCommitterOnlyEWS): diff --git a/WebKitTools/TestResultServer/handlers/dashboardhandler.py b/WebKitTools/TestResultServer/handlers/dashboardhandler.py index 45bc471..587d737 100644 --- a/WebKitTools/TestResultServer/handlers/dashboardhandler.py +++ b/WebKitTools/TestResultServer/handlers/dashboardhandler.py @@ -3,7 +3,7 @@ # 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 @@ -13,7 +13,7 @@ # * 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 @@ -38,6 +38,7 @@ from model.dashboardfile import DashboardFile PARAM_FILE = "file" + def get_content_type(filename): return mimetypes.guess_type(filename)[0] or "application/octet-stream" diff --git a/WebKitTools/TestResultServer/handlers/menu.py b/WebKitTools/TestResultServer/handlers/menu.py index ad2599d..f2f3855 100644 --- a/WebKitTools/TestResultServer/handlers/menu.py +++ b/WebKitTools/TestResultServer/handlers/menu.py @@ -3,7 +3,7 @@ # 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 @@ -13,7 +13,7 @@ # * 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 @@ -61,4 +61,3 @@ class Menu(webapp.RequestHandler): self.response.out.write( template.render("templates/menu.html", template_values)) - diff --git a/WebKitTools/TestResultServer/handlers/testfilehandler.py b/WebKitTools/TestResultServer/handlers/testfilehandler.py index 972b606..97953e7 100644 --- a/WebKitTools/TestResultServer/handlers/testfilehandler.py +++ b/WebKitTools/TestResultServer/handlers/testfilehandler.py @@ -3,7 +3,7 @@ # 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 @@ -13,7 +13,7 @@ # * 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 @@ -30,11 +30,10 @@ import logging import urllib from google.appengine.api import users -from google.appengine.ext import blobstore from google.appengine.ext import webapp -from google.appengine.ext.webapp import blobstore_handlers from google.appengine.ext.webapp import template +from model.jsonresults import JsonResults from model.testfile import TestFile PARAM_BUILDER = "builder" @@ -43,10 +42,11 @@ PARAM_FILE = "file" PARAM_NAME = "name" PARAM_KEY = "key" PARAM_TEST_TYPE = "testtype" +PARAM_INCREMENTAL = "incremental" class DeleteFile(webapp.RequestHandler): - """Delete test file for a given builder and name from datastore (metadata) and blobstore (file data).""" + """Delete test file for a given builder and name from datastore.""" def get(self): key = self.request.get(PARAM_KEY) @@ -55,7 +55,7 @@ class DeleteFile(webapp.RequestHandler): name = self.request.get(PARAM_NAME) logging.debug( - "Deleting File, builder: %s, test_type: %s, name: %s, blob key: %s.", + "Deleting File, builder: %s, test_type: %s, name: %s, key: %s.", builder, test_type, name, key) TestFile.delete_file(key, builder, test_type, name, 100) @@ -65,7 +65,7 @@ class DeleteFile(webapp.RequestHandler): % (builder, test_type, name)) -class GetFile(blobstore_handlers.BlobstoreDownloadHandler): +class GetFile(webapp.RequestHandler): """Get file content or list of files for given builder and name.""" def _get_file_list(self, builder, test_type, name): @@ -77,7 +77,8 @@ class GetFile(blobstore_handlers.BlobstoreDownloadHandler): name: file name """ - files = TestFile.get_files(builder, test_type, name, 100) + files = TestFile.get_files( + builder, test_type, name, load_data=False, limit=100) if not files: logging.info("File not found, builder: %s, test_type: %s, name: %s.", builder, test_type, name) @@ -103,16 +104,15 @@ class GetFile(blobstore_handlers.BlobstoreDownloadHandler): name: file name """ - files = TestFile.get_files(builder, test_type, name, 1) + files = TestFile.get_files( + builder, test_type, name, load_data=True, limit=1) if not files: logging.info("File not found, builder: %s, test_type: %s, name: %s.", builder, test_type, name) return - blob_key = files[0].blob_key - blob_info = blobstore.get(blob_key) - if blob_info: - self.send_blob(blob_info, "text/plain") + self.response.headers["Content-Type"] = "text/plain; charset=utf-8" + self.response.out.write(files[0].data) def get(self): builder = self.request.get(PARAM_BUILDER) @@ -133,89 +133,69 @@ class GetFile(blobstore_handlers.BlobstoreDownloadHandler): return self._get_file_content(builder, test_type, name) -class GetUploadUrl(webapp.RequestHandler): - """Get an url for uploading file to blobstore. A special url is required for each blobsotre upload.""" - - def get(self): - upload_url = blobstore.create_upload_url("/testfile/upload") - logging.info("Getting upload url: %s.", upload_url) - self.response.out.write(upload_url) - - -class Upload(blobstore_handlers.BlobstoreUploadHandler): - """Upload file to blobstore.""" +class Upload(webapp.RequestHandler): + """Upload test results file to datastore.""" def post(self): - uploaded_files = self.get_uploads("file") - if not uploaded_files: - return self._upload_done([("Missing upload file field.")]) + file_params = self.request.POST.getall(PARAM_FILE) + if not file_params: + self.response.out.write("FAIL: missing upload file field.") + return builder = self.request.get(PARAM_BUILDER) if not builder: - for blob_info in uploaded_files: - blob_info.delete() - - return self._upload_done([("Missing builder parameter in upload request.")]) + self.response.out.write("FAIL: missing builder parameter.") + return test_type = self.request.get(PARAM_TEST_TYPE) + incremental = self.request.get(PARAM_INCREMENTAL) logging.debug( "Processing upload request, builder: %s, test_type: %s.", builder, test_type) + # There are two possible types of each file_params in the request: + # one file item or a list of file items. + # Normalize file_params to a file item list. + files = [] + logging.debug("test: %s, type:%s", file_params, type(file_params)) + for item in file_params: + if not isinstance(item, list) and not isinstance(item, tuple): + item = [item] + files.extend(item) + errors = [] - for blob_info in uploaded_files: - tf = TestFile.update_file(builder, test_type, blob_info) - if not tf: + for file in files: + filename = file.filename.lower() + if ((incremental and filename == "results.json") or + (filename == "incremental_results.json")): + # Merge incremental json results. + saved_file = JsonResults.update(builder, test_type, file.value) + else: + saved_file = TestFile.update( + builder, test_type, file.filename, file.value) + + if not saved_file: errors.append( "Upload failed, builder: %s, test_type: %s, name: %s." % - (builder, test_type, blob_info.filename)) - blob_info.delete() - - return self._upload_done(errors) - - def _upload_done(self, errors): - logging.info("upload done.") + (builder, test_type, file.filename)) - error_messages = [] - for error in errors: - logging.info(error) - error_messages.append("error=%s" % urllib.quote(error)) - - if error_messages: - redirect_url = "/uploadfail?%s" % "&".join(error_messages) + if errors: + messages = "FAIL: " + "; ".join(errors) + logging.warning(messages) + self.response.set_status(500, messages) + self.response.out.write("FAIL") else: - redirect_url = "/uploadsuccess" - - logging.info(redirect_url) - # BlobstoreUploadHandler requires redirect at the end. - self.redirect(redirect_url) + self.response.set_status(200) + self.response.out.write("OK") class UploadForm(webapp.RequestHandler): - """Show a form so user can submit a file to blobstore.""" + """Show a form so user can upload a file.""" def get(self): - upload_url = blobstore.create_upload_url("/testfile/upload") template_values = { - "upload_url": upload_url, + "upload_url": "/testfile/upload", } self.response.out.write(template.render("templates/uploadform.html", template_values)) - -class UploadStatus(webapp.RequestHandler): - """Return status of file uploading""" - - def get(self): - logging.debug("Update status") - - if self.request.path == "/uploadsuccess": - self.response.set_status(200) - self.response.out.write("OK") - else: - errors = self.request.params.getall("error") - if errors: - messages = "FAIL: " + "; ".join(errors) - logging.warning(messages) - self.response.set_status(500, messages) - self.response.out.write("FAIL") diff --git a/WebKitTools/TestResultServer/main.py b/WebKitTools/TestResultServer/main.py index 7a0d237..aa6e432 100644 --- a/WebKitTools/TestResultServer/main.py +++ b/WebKitTools/TestResultServer/main.py @@ -3,7 +3,7 @@ # 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 @@ -13,7 +13,7 @@ # * 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 @@ -42,17 +42,15 @@ routes = [ ('/dashboards/update', dashboardhandler.UpdateDashboardFile), ('/dashboards/([^?]+)?', dashboardhandler.GetDashboardFile), ('/testfile/delete', testfilehandler.DeleteFile), - ('/testfile/uploadurl', testfilehandler.GetUploadUrl), ('/testfile/upload', testfilehandler.Upload), ('/testfile/uploadform', testfilehandler.UploadForm), ('/testfile/?', testfilehandler.GetFile), - ('/uploadfail', testfilehandler.UploadStatus), - ('/uploadsuccess', testfilehandler.UploadStatus), ('/*|/menu', menu.Menu), ] application = webapp.WSGIApplication(routes, debug=True) + def main(): run_wsgi_app(application) diff --git a/WebKitTools/TestResultServer/model/dashboardfile.py b/WebKitTools/TestResultServer/model/dashboardfile.py index c74f071..57d3f6f 100644 --- a/WebKitTools/TestResultServer/model/dashboardfile.py +++ b/WebKitTools/TestResultServer/model/dashboardfile.py @@ -3,7 +3,7 @@ # 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 @@ -13,7 +13,7 @@ # * 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 @@ -36,6 +36,7 @@ from google.appengine.ext import db SVN_PATH_DASHBOARD = ("http://src.chromium.org/viewvc/chrome/trunk/tools/" "dashboards/") + class DashboardFile(db.Model): name = db.StringProperty() data = db.BlobProperty() @@ -92,7 +93,7 @@ class DashboardFile(db.Model): if not files: logging.info("No existing file, added as new file.") return cls.add_file(name, data) - + logging.debug("Updating existing file.") file = files[0] file.data = data diff --git a/WebKitTools/TestResultServer/model/datastorefile.py b/WebKitTools/TestResultServer/model/datastorefile.py new file mode 100755 index 0000000..dd4c366 --- /dev/null +++ b/WebKitTools/TestResultServer/model/datastorefile.py @@ -0,0 +1,129 @@ +# Copyright (C) 2010 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 datetime import datetime +import logging + +from google.appengine.ext import db + +MAX_DATA_ENTRY_PER_FILE = 10 +MAX_ENTRY_LEN = 1000 * 1000 + + +class DataEntry(db.Model): + """Datastore entry that stores one segmant of file data + (<1000*1000 bytes). + """ + + data = db.BlobProperty() + + @classmethod + def get(cls, key): + return db.get(key) + + def get_data(self, key): + return db.get(key) + + +class DataStoreFile(db.Model): + """This class stores file in datastore. + If a file is oversize (>1000*1000 bytes), the file is split into + multiple segments and stored in multiple datastore entries. + """ + + name = db.StringProperty() + data_keys = db.ListProperty(db.Key) + date = db.DateTimeProperty(auto_now_add=True) + + data = None + + def delete_data(self, keys=None): + if not keys: + keys = self.data_keys + + for key in keys: + data_entry = DataEntry.get(key) + if data_entry: + data_entry.delete() + + def save_data(self, data): + if not data: + logging.warning("No data to save.") + return False + + if len(data) > (MAX_DATA_ENTRY_PER_FILE * MAX_ENTRY_LEN): + logging.error("File too big, can't save to datastore: %dK", + len(data) / 1024) + return False + + start = 0 + keys = self.data_keys + self.data_keys = [] + while start < len(data): + if keys: + key = keys.pop(0) + data_entry = DataEntry.get(key) + if not data_entry: + logging.warning("Found key, but no data entry: %s", key) + data_entry = DataEntry() + else: + data_entry = DataEntry() + + data_entry.data = db.Blob(data[start: start + MAX_ENTRY_LEN]) + data_entry.put() + + logging.info("Data saved: %s.", data_entry.key()) + self.data_keys.append(data_entry.key()) + + start = start + MAX_ENTRY_LEN + + if keys: + self.delete_data(keys) + + self.data = data + + return True + + def load_data(self): + if not self.data_keys: + logging.warning("No data to load.") + return None + + data = [] + for key in self.data_keys: + logging.info("Loading data for key: %s.", key) + data_entry = DataEntry.get(key) + if not data_entry: + logging.error("No data found for key: %s.", key) + return None + + data.append(data_entry.data) + + self.data = "".join(data) + + return self.data diff --git a/WebKitTools/TestResultServer/model/jsonresults.py b/WebKitTools/TestResultServer/model/jsonresults.py new file mode 100755 index 0000000..d86fbcd --- /dev/null +++ b/WebKitTools/TestResultServer/model/jsonresults.py @@ -0,0 +1,365 @@ +# Copyright (C) 2010 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 datetime import datetime +from django.utils import simplejson +import logging + +from model.testfile import TestFile + +JSON_RESULTS_FILE = "results.json" +JSON_RESULTS_PREFIX = "ADD_RESULTS(" +JSON_RESULTS_SUFFIX = ");" +JSON_RESULTS_VERSION_KEY = "version" +JSON_RESULTS_BUILD_NUMBERS = "buildNumbers" +JSON_RESULTS_TESTS = "tests" +JSON_RESULTS_RESULTS = "results" +JSON_RESULTS_TIMES = "times" +JSON_RESULTS_VERSION = 3 +JSON_RESULTS_MAX_BUILDS = 750 + + +class JsonResults(object): + @classmethod + def _strip_prefix_suffix(cls, data): + """Strip out prefix and suffix of json results string. + + Args: + data: json file content. + + Returns: + json string without prefix and suffix. + """ + + assert(data.startswith(JSON_RESULTS_PREFIX)) + assert(data.endswith(JSON_RESULTS_SUFFIX)) + + return data[len(JSON_RESULTS_PREFIX): + len(data) - len(JSON_RESULTS_SUFFIX)] + + @classmethod + def _generate_file_data(cls, json, sort_keys=False): + """Given json string, generate file content data by adding + prefix and suffix. + + Args: + json: json string without prefix and suffix. + + Returns: + json file data. + """ + + data = simplejson.dumps(json, separators=(',', ':'), + sort_keys=sort_keys) + return JSON_RESULTS_PREFIX + data + JSON_RESULTS_SUFFIX + + @classmethod + def _load_json(cls, file_data): + """Load json file to a python object. + + Args: + file_data: json file content. + + Returns: + json object or + None on failure. + """ + + json_results_str = cls._strip_prefix_suffix(file_data) + if not json_results_str: + logging.warning("No json results data.") + return None + + try: + return simplejson.loads(json_results_str) + except Exception, err: + logging.debug(json_results_str) + logging.error("Failed to load json results: %s", str(err)) + return None + + @classmethod + def _merge_json(cls, aggregated_json, incremental_json): + """Merge incremental json into aggregated json results. + + Args: + aggregated_json: aggregated json object. + incremental_json: incremental json object. + + Returns: + True if merge succeeds or + False on failure. + """ + + # Merge non tests property data. + # Tests properties are merged in _merge_tests. + if not cls._merge_non_test_data(aggregated_json, incremental_json): + return False + + # Merge tests results and times + incremental_tests = incremental_json[JSON_RESULTS_TESTS] + if incremental_tests: + aggregated_tests = aggregated_json[JSON_RESULTS_TESTS] + cls._merge_tests(aggregated_tests, incremental_tests) + + return True + + @classmethod + def _merge_non_test_data(cls, aggregated_json, incremental_json): + """Merge incremental non tests property data into aggregated json results. + + Args: + aggregated_json: aggregated json object. + incremental_json: incremental json object. + + Returns: + True if merge succeeds or + False on failure. + """ + + incremental_builds = incremental_json[JSON_RESULTS_BUILD_NUMBERS] + aggregated_builds = aggregated_json[JSON_RESULTS_BUILD_NUMBERS] + aggregated_build_number = int(aggregated_builds[0]) + # Loop through all incremental builds, start from the oldest run. + for index in reversed(range(len(incremental_builds))): + build_number = int(incremental_builds[index]) + logging.debug("Merging build %s, incremental json index: %d.", + build_number, index) + + # Return if not all build numbers in the incremental json results + # are newer than the most recent build in the aggregated results. + # FIXME: make this case work. + if build_number < aggregated_build_number: + logging.warning(("Build %d in incremental json is older than " + "the most recent build in aggregated results: %d"), + build_number, aggregated_build_number) + return False + + # Return if the build number is duplicated. + # FIXME: skip the duplicated build and merge rest of the results. + # Need to be careful on skiping the corresponding value in + # _merge_tests because the property data for each test could + # be accumulated. + if build_number == aggregated_build_number: + logging.warning("Duplicate build %d in incremental json", + build_number) + return False + + # Merge this build into aggreagated results. + cls._merge_one_build(aggregated_json, incremental_json, index) + logging.debug("Merged build %s, merged json: %s.", + build_number, aggregated_json) + + return True + + @classmethod + def _merge_one_build(cls, aggregated_json, incremental_json, + incremental_index): + """Merge one build of incremental json into aggregated json results. + + Args: + aggregated_json: aggregated json object. + incremental_json: incremental json object. + incremental_index: index of the incremental json results to merge. + """ + + for key in incremental_json.keys(): + # Merge json results except "tests" properties (results, times etc). + # "tests" properties will be handled separately. + if key == JSON_RESULTS_TESTS: + continue + + if key in aggregated_json: + aggregated_json[key].insert( + 0, incremental_json[key][incremental_index]) + aggregated_json[key] = \ + aggregated_json[key][:JSON_RESULTS_MAX_BUILDS] + else: + aggregated_json[key] = incremental_json[key] + + @classmethod + def _merge_tests(cls, aggregated_json, incremental_json): + """Merge "tests" properties:results, times. + + Args: + aggregated_json: aggregated json object. + incremental_json: incremental json object. + """ + + for test_name in incremental_json: + incremental_test = incremental_json[test_name] + if test_name in aggregated_json: + aggregated_test = aggregated_json[test_name] + cls._insert_item_run_length_encoded( + incremental_test[JSON_RESULTS_RESULTS], + aggregated_test[JSON_RESULTS_RESULTS]) + cls._insert_item_run_length_encoded( + incremental_test[JSON_RESULTS_TIMES], + aggregated_test[JSON_RESULTS_TIMES]) + else: + aggregated_json[test_name] = incremental_test + + @classmethod + def _insert_item_run_length_encoded(cls, incremental_item, aggregated_item): + """Inserts the incremental run-length encoded results into the aggregated + run-length encoded results. + + Args: + incremental_item: incremental run-length encoded results. + aggregated_item: aggregated run-length encoded results. + """ + + for item in incremental_item: + if len(aggregated_item) and item[1] == aggregated_item[0][1]: + aggregated_item[0][0] = min( + aggregated_item[0][0] + item[0], JSON_RESULTS_MAX_BUILDS) + else: + # The test item values need to be summed from continuous runs. + # If there is an older item (not most recent one) whose value is + # same as the one to insert, then we should remove the old item + # from aggregated list. + for i in reversed(range(1, len(aggregated_item))): + if item[1] == aggregated_item[i][1]: + aggregated_item.pop(i) + + aggregated_item.insert(0, item) + + @classmethod + def _check_json(cls, builder, json): + """Check whether the given json is valid. + + Args: + builder: builder name this json is for. + json: json object to check. + + Returns: + True if the json is valid or + False otherwise. + """ + + version = json[JSON_RESULTS_VERSION_KEY] + if version > JSON_RESULTS_VERSION: + logging.error("Results JSON version '%s' is not supported.", + version) + return False + + if not builder in json: + logging.error("Builder '%s' is not in json results.", builder) + return False + + results_for_builder = json[builder] + if not JSON_RESULTS_BUILD_NUMBERS in results_for_builder: + logging.error("Missing build number in json results.") + return False + + return True + + @classmethod + def merge(cls, builder, aggregated, incremental, sort_keys=False): + """Merge incremental json file data with aggregated json file data. + + Args: + builder: builder name. + aggregated: aggregated json file data. + incremental: incremental json file data. + sort_key: whether or not to sort key when dumping json results. + + Returns: + Merged json file data if merge succeeds or + None on failure. + """ + + if not incremental: + logging.warning("Nothing to merge.") + return None + + logging.info("Loading incremental json...") + incremental_json = cls._load_json(incremental) + if not incremental_json: + return None + + logging.info("Checking incremental json...") + if not cls._check_json(builder, incremental_json): + return None + + logging.info("Loading existing aggregated json...") + aggregated_json = cls._load_json(aggregated) + if not aggregated_json: + return incremental + + logging.info("Checking existing aggregated json...") + if not cls._check_json(builder, aggregated_json): + return incremental + + logging.info("Merging json results...") + try: + if not cls._merge_json( + aggregated_json[builder], + incremental_json[builder]): + return None + except Exception, err: + logging.error("Failed to merge json results: %s", str(err)) + return None + + aggregated_json[JSON_RESULTS_VERSION_KEY] = JSON_RESULTS_VERSION + + return cls._generate_file_data(aggregated_json, sort_keys) + + @classmethod + def update(cls, builder, test_type, incremental): + """Update datastore json file data by merging it with incremental json + file. + + Args: + builder: builder name. + test_type: type of test results. + incremental: incremental json file data to merge. + + Returns: + TestFile object if update succeeds or + None on failure. + """ + + files = TestFile.get_files(builder, test_type, JSON_RESULTS_FILE) + if files: + file = files[0] + new_results = cls.merge(builder, file.data, incremental) + else: + # Use the incremental data if there is no aggregated file to merge. + file = TestFile() + file.builder = builder + file.name = JSON_RESULTS_FILE + new_results = incremental + logging.info("No existing json results, incremental json is saved.") + + if not new_results: + return None + + if not file.save(new_results): + return None + + return file diff --git a/WebKitTools/TestResultServer/model/jsonresults_unittest.py b/WebKitTools/TestResultServer/model/jsonresults_unittest.py new file mode 100755 index 0000000..fd646c8 --- /dev/null +++ b/WebKitTools/TestResultServer/model/jsonresults_unittest.py @@ -0,0 +1,256 @@ +# Copyright (C) 2010 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. + +import unittest + +from jsonresults import JsonResults + +JSON_RESULTS_TEMPLATE = ( + '{"Webkit":{' + '"allFixableCount":[[TESTDATA_COUNT]],' + '"buildNumbers":[[TESTDATA_BUILDNUMBERS]],' + '"chromeRevision":[[TESTDATA_CHROMEREVISION]],' + '"deferredCounts":[[TESTDATA_COUNTS]],' + '"fixableCount":[[TESTDATA_COUNT]],' + '"fixableCounts":[[TESTDATA_COUNTS]],' + '"secondsSinceEpoch":[[TESTDATA_TIMES]],' + '"tests":{[TESTDATA_TESTS]},' + '"webkitRevision":[[TESTDATA_WEBKITREVISION]],' + '"wontfixCounts":[[TESTDATA_COUNTS]]' + '},' + '"version":3' + '}') + +JSON_RESULTS_COUNTS_TEMPLATE = ( + '{' + '"C":[TESTDATA],' + '"F":[TESTDATA],' + '"I":[TESTDATA],' + '"O":[TESTDATA],' + '"P":[TESTDATA],' + '"T":[TESTDATA],' + '"X":[TESTDATA],' + '"Z":[TESTDATA]}') + +JSON_RESULTS_TESTS_TEMPLATE = ( + '"[TESTDATA_TEST_NAME]":{' + '"results":[[TESTDATA_TEST_RESULTS]],' + '"times":[[TESTDATA_TEST_TIMES]]}') + +JSON_RESULTS_PREFIX = "ADD_RESULTS(" +JSON_RESULTS_SUFFIX = ");" + + +class JsonResultsTest(unittest.TestCase): + def setUp(self): + self._builder = "Webkit" + + def _make_test_json(self, test_data): + if not test_data: + return JSON_RESULTS_PREFIX + JSON_RESULTS_SUFFIX + + (builds, tests) = test_data + if not builds or not tests: + return JSON_RESULTS_PREFIX + JSON_RESULTS_SUFFIX + + json = JSON_RESULTS_TEMPLATE + + counts = [] + build_numbers = [] + webkit_revision = [] + chrome_revision = [] + times = [] + for build in builds: + counts.append(JSON_RESULTS_COUNTS_TEMPLATE.replace("[TESTDATA]", build)) + build_numbers.append("1000%s" % build) + webkit_revision.append("2000%s" % build) + chrome_revision.append("3000%s" % build) + times.append("100000%s000" % build) + + json = json.replace("[TESTDATA_COUNTS]", ",".join(counts)) + json = json.replace("[TESTDATA_COUNT]", ",".join(builds)) + json = json.replace("[TESTDATA_BUILDNUMBERS]", ",".join(build_numbers)) + json = json.replace("[TESTDATA_WEBKITREVISION]", ",".join(webkit_revision)) + json = json.replace("[TESTDATA_CHROMEREVISION]", ",".join(chrome_revision)) + json = json.replace("[TESTDATA_TIMES]", ",".join(times)) + + json_tests = [] + for test in tests: + t = JSON_RESULTS_TESTS_TEMPLATE.replace("[TESTDATA_TEST_NAME]", test[0]) + t = t.replace("[TESTDATA_TEST_RESULTS]", test[1]) + t = t.replace("[TESTDATA_TEST_TIMES]", test[2]) + json_tests.append(t) + + json = json.replace("[TESTDATA_TESTS]", ",".join(json_tests)) + + return JSON_RESULTS_PREFIX + json + JSON_RESULTS_SUFFIX + + def _test_merge(self, aggregated_data, incremental_data, expected_data): + aggregated_results = self._make_test_json(aggregated_data) + incremental_results = self._make_test_json(incremental_data) + merged_results = JsonResults.merge(self._builder, + aggregated_results, incremental_results, sort_keys=True) + + if expected_data: + expected_results = self._make_test_json(expected_data) + self.assertEquals(merged_results, expected_results) + else: + self.assertFalse(merged_results) + + def test(self): + # Empty incremental results json. + # Nothing to merge. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Incremental results + None, + # Expect no merge happens. + None) + + # No actual incremental test results (only prefix and suffix) to merge. + # Nothing to merge. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Incremental results + ([], []), + # Expected no merge happens. + None) + + # No existing aggregated results. + # Merged results == new incremental results. + self._test_merge( + # Aggregated results + None, + # Incremental results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Expected results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]])) + + # Single test for single run. + # Incremental results has the latest build and same test results for + # that run. + # Insert the incremental results at the first place and sum number + # of runs for "P" (200 + 1) to get merged results. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Incremental results + (["3"], [["001.html", "[1,\"P\"]", "[1,\"0\"]"]]), + # Expected results + (["3", "2", "1"], [["001.html", "[201,\"P\"]", "[201,\"0\"]"]])) + + # Single test for single run. + # Incremental results has the latest build but different test results + # for that run. + # Insert the incremental results at the first place. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Incremental results + (["3"], [["001.html", "[1, \"I\"]", "[1,\"1\"]"]]), + # Expected results + (["3", "2", "1"], [["001.html", "[1,\"I\"],[200,\"P\"]", "[1,\"1\"],[200,\"0\"]"]])) + + # Single test for single run. + # Incremental results has the latest build but different test results + # for that run. + # The test "results" and "times" need to be continuous, so the old + # [10,"I"] result should be dropped because a new result of same type [1,"I"] + # is inserted in front of [200,"P"]. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"],[10,\"I\"]", "[200,\"0\"],[10,\"1\"]"]]), + # Incremental results + (["3"], [["001.html", "[1,\"I\"]", "[1,\"1\"]"]]), + # Expected results + (["3", "2", "1"], [["001.html", "[1,\"I\"],[200,\"P\"]", "[1,\"1\"],[200,\"0\"]"]])) + + # Multiple tests for single run. + # All tests have incremental updates. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"], ["002.html", "[100,\"I\"]", "[100,\"1\"]"]]), + # Incremental results + (["3"], [["001.html", "[1,\"P\"]", "[1,\"0\"]"], ["002.html", "[1,\"I\"]", "[1,\"1\"]"]]), + # Expected results + (["3", "2", "1"], [["001.html", "[201,\"P\"]", "[201,\"0\"]"], ["002.html", "[101,\"I\"]", "[101,\"1\"]"]])) + + # Multiple tests for single run. + # Not all tests have update. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"], ["002.html", "[100,\"I\"]", "[100,\"1\"]"]]), + # Incremental results + (["3"], [["002.html", "[1,\"I\"]", "[1,\"1\"]"]]), + # Expected results + (["3", "2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"], ["002.html", "[101,\"I\"]", "[101,\"1\"]"]])) + + # Single test for multiple runs. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Incremental results + (["4", "3"], [["001.html", "[2, \"I\"]", "[2,\"2\"]"]]), + # Expected results + (["4", "3", "2", "1"], [["001.html", "[2,\"I\"],[200,\"P\"]", "[2,\"2\"],[200,\"0\"]"]])) + + # Multiple tests for multiple runs. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"], ["002.html", "[10,\"Z\"]", "[10,\"0\"]"]]), + # Incremental results + (["4", "3"], [["001.html", "[2, \"I\"]", "[2,\"2\"]"], ["002.html", "[1,\"C\"]", "[1,\"1\"]"]]), + # Expected results + (["4", "3", "2", "1"], [["001.html", "[2,\"I\"],[200,\"P\"]", "[2,\"2\"],[200,\"0\"]"], ["002.html", "[1,\"C\"],[10,\"Z\"]", "[1,\"1\"],[10,\"0\"]"]])) + + # Test the build in incremental results is older than the most recent + # build in aggregated results. + # The incremental results should be dropped and no merge happens. + self._test_merge( + # Aggregated results + (["3", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Incremental results + (["2"], [["001.html", "[1, \"P\"]", "[1,\"0\"]"]]), + # Expected no merge happens. + None) + + # Test the build in incremental results is same as the build in + # aggregated results. + # The incremental results should be dropped and no merge happens. + self._test_merge( + # Aggregated results + (["2", "1"], [["001.html", "[200,\"P\"]", "[200,\"0\"]"]]), + # Incremental results + (["3", "2"], [["001.html", "[2, \"P\"]", "[2,\"0\"]"]]), + # Expected no merge happens. + None) + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/TestResultServer/model/testfile.py b/WebKitTools/TestResultServer/model/testfile.py index 35ab967..ce92b65 100644 --- a/WebKitTools/TestResultServer/model/testfile.py +++ b/WebKitTools/TestResultServer/model/testfile.py @@ -3,7 +3,7 @@ # 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 @@ -13,7 +13,7 @@ # * 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 @@ -29,16 +29,14 @@ from datetime import datetime import logging -from google.appengine.ext import blobstore from google.appengine.ext import db +from model.datastorefile import DataStoreFile -class TestFile(db.Model): + +class TestFile(DataStoreFile): builder = db.StringProperty() - name = db.StringProperty() test_type = db.StringProperty() - blob_key = db.StringProperty() - date = db.DateTimeProperty(auto_now_add=True) @classmethod def delete_file(cls, key, builder, test_type, name, limit): @@ -63,7 +61,7 @@ class TestFile(db.Model): return True @classmethod - def get_files(cls, builder, test_type, name, limit): + def get_files(cls, builder, test_type, name, load_data=True, limit=1): query = TestFile.all() if builder: query = query.filter("builder =", builder) @@ -72,51 +70,54 @@ class TestFile(db.Model): if name: query = query.filter("name =", name) - return query.order("-date").fetch(limit) + files = query.order("-date").fetch(limit) + if load_data: + for file in files: + file.load_data() + + return files @classmethod - def add_file(cls, builder, test_type, blob_info): + def add_file(cls, builder, test_type, name, data): file = TestFile() file.builder = builder file.test_type = test_type - file.name = blob_info.filename - file.blob_key = str(blob_info.key()) - file.put() + file.name = name + + if not file.save(data): + return None logging.info( - "File saved, builder: %s, test_type: %s, name: %s, blob key: %s.", - builder, test_type, file.name, file.blob_key) + "File saved, builder: %s, test_type: %s, name: %s, key: %s.", + builder, test_type, file.name, str(file.data_keys)) return file @classmethod - def update_file(cls, builder, test_type, blob_info): - files = cls.get_files(builder, test_type, blob_info.filename, 1) + def update(cls, builder, test_type, name, data): + files = cls.get_files(builder, test_type, name) if not files: - return cls.add_file(builder, test_type, blob_info) + return cls.add_file(builder, test_type, name, data) file = files[0] - old_blob_info = blobstore.BlobInfo.get(file.blob_key) - if old_blob_info: - old_blob_info.delete() - - file.builder = builder - file.test_type = test_type - file.name = blob_info.filename - file.blob_key = str(blob_info.key()) - file.date = datetime.now() - file.put() + if not file.save(data): + return None logging.info( - "File replaced, builder: %s, test_type: %s, name: %s, blob key: %s.", - builder, test_type, file.name, file.blob_key) + "File replaced, builder: %s, test_type: %s, name: %s, data key: %s.", + builder, test_type, file.name, str(file.data_keys)) return file - def _delete_all(self): - if self.blob_key: - blob_info = blobstore.BlobInfo.get(self.blob_key) - if blob_info: - blob_info.delete() + def save(self, data): + if not self.save_data(data): + return False + + self.date = datetime.now() + self.put() + return True + + def _delete_all(self): + self.delete_data() self.delete() diff --git a/WebKitTools/TestResultServer/templates/uploadform.html b/WebKitTools/TestResultServer/templates/uploadform.html index 933f9f5..3506c9c 100644 --- a/WebKitTools/TestResultServer/templates/uploadform.html +++ b/WebKitTools/TestResultServer/templates/uploadform.html @@ -18,6 +18,9 @@ <td><input class=inputtext type="text" name="testtype" value=""/></td> </tr> </table> + <br> + <div><input class=button type="checkbox" name="incremental">Incremental results, merge with server file.</div> + <br> <div><input class=button type="file" name="file" multiple></div> <br> <div><input class=button type="submit" value="Upload"></div> diff --git a/WebKitTools/WebKitTestRunner/DerivedSources.make b/WebKitTools/WebKitTestRunner/DerivedSources.make index 6134380..c308a8a 100644 --- a/WebKitTools/WebKitTestRunner/DerivedSources.make +++ b/WebKitTools/WebKitTestRunner/DerivedSources.make @@ -26,6 +26,8 @@ VPATH = \ # INTERFACES = \ + EventSendingController \ + GCController \ LayoutTestController \ # diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm index fa47143..0de2fd0 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm @@ -245,30 +245,31 @@ JSValueRef ${className}::@{[$function->signature->name]}(JSContextRef context, J ${implementationClassName}* impl = to${implementationClassName}(context, thisObject); if (!impl) return JSValueMakeUndefined(context); + EOF - my @parameters = (); - my @specifiedParameters = @{$function->parameters}; + my $functionCall; + if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { + $functionCall = "impl->" . $function->signature->name . "(context, argumentCount, arguments, exception)"; + } else { + my @parameters = (); + my @specifiedParameters = @{$function->parameters}; - push(@contents, "\n") if scalar @specifiedParameters; + $self->_includeHeaders(\%contentsIncludes, $function->signature->type, $function->signature); - $self->_includeHeaders(\%contentsIncludes, $function->signature->type, $function->signature); + foreach my $i (0..$#specifiedParameters) { + my $parameter = $specifiedParameters[$i]; - foreach my $i (0..$#specifiedParameters) { - my $parameter = $specifiedParameters[$i]; + $self->_includeHeaders(\%contentsIncludes, $idlType, $parameter); - $self->_includeHeaders(\%contentsIncludes, $idlType, $parameter); + push(@contents, " " . $self->_platformTypeVariableDeclaration($parameter, $parameter->name, "arguments[$i]", "argumentCount > $i") . "\n"); + + push(@parameters, $self->_parameterExpression($parameter)); + } - push(@contents, " " . $self->_platformTypeVariableDeclaration($parameter, $parameter->name, "arguments[$i]", "argumentCount > $i") . "\n"); - - push(@parameters, $self->_parameterExpression($parameter)); + $functionCall = "impl->" . $function->signature->name . "(" . join(", ", @parameters) . ")"; } - - my $isVoidReturn = $function->signature->type eq "void"; - my $functionName = "impl->" . $function->signature->name; - my $functionCall = $functionName . "(" . join(", ", @parameters) . ")"; - - push(@contents, "\n") unless scalar @specifiedParameters == 1; - push(@contents, " ${functionCall};\n\n") if $isVoidReturn; + + push(@contents, " ${functionCall};\n\n") if $function->signature->type eq "void"; push(@contents, " return " . $self->_returnExpression($function->signature, $functionCall) . ";\n}\n"); } } diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl new file mode 100644 index 0000000..1e47772 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +module WTR { + + interface EventSendingController { + [CustomArgumentHandling] void mouseDown(); + [CustomArgumentHandling] void mouseUp(); + [CustomArgumentHandling] void mouseMoveTo(); + [CustomArgumentHandling] void keyDown(); + [CustomArgumentHandling] void contextClick(); // CustomArgumentHandling only to throw exception while not implemented. + [CustomArgumentHandling] void leapForward(/*in unsigned long delay*/); // CustomArgumentHandling only to throw exception while not implemented. + + // Zoom functions. + void textZoomIn(); + void textZoomOut(); + void zoomPageIn(); + void zoomPageOut(); + }; + +} diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl new file mode 100644 index 0000000..eb3ddee --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +module WTR { + + interface GCController { + void collect(); + void collectOnAlternateThread(in boolean waitUntilDone); + unsigned long long getJSObjectCount(); + }; + +} diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h index 9839cb4..d885801 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h @@ -27,6 +27,7 @@ #define JSWrapper_h #include "JSWrappable.h" +#include <JavaScriptCore/JSRetainPtr.h> namespace WTR { @@ -45,6 +46,12 @@ inline JSValueRef toJS(JSContextRef context, JSWrappable* impl) return JSWrapper::wrap(context, impl); } +inline void setProperty(JSContextRef context, JSObjectRef object, const char* propertyName, JSWrappable* value, JSPropertyAttributes attributes, JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName)); + JSObjectSetProperty(context, object, propertyNameString.get(), JSWrapper::wrap(context, value), attributes, exception); +} + } // namespace WTR #endif // JSWrapper_h diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl index 2eca583..7993d78 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl @@ -37,6 +37,7 @@ module WTR { void dumpEditingCallbacks(); void dumpSelectionRect(); void dumpStatusCallbacks(); + void dumpTitleChanges(); // Special options. void keepWebHistory(); diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp new file mode 100644 index 0000000..472cf6c --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 "EventSendingController.h" + +#include "InjectedBundle.h" +#include "InjectedBundlePage.h" +#include "JSEventSendingController.h" +#include <WebKit2/WKBundlePage.h> +#include <WebKit2/WKBundlePagePrivate.h> +#include <WebKit2/WKBundlePrivate.h> + +namespace WTR { + +static const float ZoomMultiplierRatio = 1.2f; + +PassRefPtr<EventSendingController> EventSendingController::create() +{ + return adoptRef(new EventSendingController); +} + +EventSendingController::EventSendingController() +{ +} + +EventSendingController::~EventSendingController() +{ +} + +JSClassRef EventSendingController::wrapperClass() +{ + return JSEventSendingController::eventSendingControllerClass(); +} + +static void setExceptionForString(JSContextRef context, JSValueRef* exception, const char* string) +{ + JSRetainPtr<JSStringRef> exceptionString(Adopt, JSStringCreateWithUTF8CString(string)); + *exception = JSValueMakeString(context, exceptionString.get()); +} + +void EventSendingController::mouseDown(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + setExceptionForString(context, exception, "EventSender.mouseDown is not yet supported."); +} + +void EventSendingController::mouseUp(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + setExceptionForString(context, exception, "EventSender.mouseUp is not yet supported."); +} + +void EventSendingController::mouseMoveTo(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + setExceptionForString(context, exception, "EventSender.mouseMoveTo is not yet supported."); +} + +void EventSendingController::keyDown(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + setExceptionForString(context, exception, "EventSender.keyDown is not yet supported."); +} + +void EventSendingController::contextClick(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + setExceptionForString(context, exception, "EventSender.contextClick is not yet supported."); +} + +void EventSendingController::leapForward(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + setExceptionForString(context, exception, "EventSender.leapForward is not yet supported."); +} + +void EventSendingController::textZoomIn() +{ + WKBundlePageSetZoomMode(InjectedBundle::shared().page()->page(), kWKBundlePageZoomModeTextOnly); + float zoomFactor = WKBundlePageGetZoomFactor(InjectedBundle::shared().page()->page()); + WKBundlePageSetZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor * ZoomMultiplierRatio); +} + +void EventSendingController::textZoomOut() +{ + WKBundlePageSetZoomMode(InjectedBundle::shared().page()->page(), kWKBundlePageZoomModeTextOnly); + float zoomFactor = WKBundlePageGetZoomFactor(InjectedBundle::shared().page()->page()); + WKBundlePageSetZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor / ZoomMultiplierRatio); +} + +void EventSendingController::zoomPageIn() +{ + WKBundlePageSetZoomMode(InjectedBundle::shared().page()->page(), kWKBundlePageZoomModePage); + float zoomFactor = WKBundlePageGetZoomFactor(InjectedBundle::shared().page()->page()); + WKBundlePageSetZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor * ZoomMultiplierRatio); +} + +void EventSendingController::zoomPageOut() +{ + WKBundlePageSetZoomMode(InjectedBundle::shared().page()->page(), kWKBundlePageZoomModePage); + float zoomFactor = WKBundlePageGetZoomFactor(InjectedBundle::shared().page()->page()); + WKBundlePageSetZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor / ZoomMultiplierRatio); +} + +// Object Creation + +void EventSendingController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) +{ + setProperty(context, windowObject, "eventSender", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); +} + +} // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/EventSendingController.h b/WebKitTools/WebKitTestRunner/InjectedBundle/EventSendingController.h new file mode 100644 index 0000000..400f60d --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/EventSendingController.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 EventSendingController_h +#define EventSendingController_h + +#include "JSWrappable.h" +#include <wtf/PassRefPtr.h> + +namespace WTR { + +class EventSendingController : public JSWrappable { +public: + static PassRefPtr<EventSendingController> create(); + virtual ~EventSendingController(); + + void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); + + // JSWrappable + virtual JSClassRef wrapperClass(); + + void mouseDown(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + void mouseUp(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + void mouseMoveTo(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + void keyDown(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + void contextClick(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + void leapForward(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + + // Zoom functions. + void textZoomIn(); + void textZoomOut(); + void zoomPageIn(); + void zoomPageOut(); + +private: + EventSendingController(); +}; + +} // namespace WTR + +#endif // EventSendingController_h diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/GCController.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/GCController.cpp new file mode 100644 index 0000000..0eba2df --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/GCController.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "GCController.h" + +#include "InjectedBundle.h" +#include "JSGCController.h" +#include <WebKit2/WKBundlePrivate.h> + +namespace WTR { + +PassRefPtr<GCController> GCController::create() +{ + return adoptRef(new GCController); +} + +GCController::GCController() +{ +} + +GCController::~GCController() +{ +} + +JSClassRef GCController::wrapperClass() +{ + return JSGCController::gCControllerClass(); +} + +void GCController::collect() +{ + WKBundleGarbageCollectJavaScriptObjects(InjectedBundle::shared().bundle()); +} + +void GCController::collectOnAlternateThread(bool waitUntilDone) +{ + WKBundleGarbageCollectJavaScriptObjectsOnAlternateThreadForDebugging(InjectedBundle::shared().bundle(), waitUntilDone); +} + +size_t GCController::getJSObjectCount() +{ + return WKBundleGetJavaScriptObjectsCount(InjectedBundle::shared().bundle()); +} + +// Object Creation + +void GCController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) +{ + setProperty(context, windowObject, "GCController", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); +} + +} // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/GCController.h b/WebKitTools/WebKitTestRunner/InjectedBundle/GCController.h new file mode 100644 index 0000000..760fbb1 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/GCController.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCController_h +#define GCController_h + +#include "JSWrappable.h" +#include <wtf/PassRefPtr.h> + +namespace WTR { + +class GCController : public JSWrappable { +public: + static PassRefPtr<GCController> create(); + virtual ~GCController(); + + void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); + + // JSWrappable + virtual JSClassRef wrapperClass(); + + void collect(); + void collectOnAlternateThread(bool waitUntilDone); + size_t getJSObjectCount(); + +private: + GCController(); +}; + +} // namespace WTR + +#endif // GCController_h diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp index 095bd9c..02dfeb1 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp @@ -81,6 +81,7 @@ void InjectedBundle::initialize(WKBundleRef bundle) WKBundleSetClient(m_bundle, &client); activateFonts(); + WKBundleActivateMacFontAscentHack(m_bundle); } void InjectedBundle::done() @@ -132,15 +133,15 @@ void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messag void InjectedBundle::reset() { m_outputStream.str(""); + m_layoutTestController = LayoutTestController::create(); + m_gcController = GCController::create(); + m_eventSendingController = EventSendingController::create(); + WKBundleSetShouldTrackVisitedLinks(m_bundle, false); WKBundleRemoveAllVisitedLinks(m_bundle); - m_mainPage->reset(); -} -void InjectedBundle::setShouldTrackVisitedLinks() -{ - WKBundleSetShouldTrackVisitedLinks(m_bundle, true); + m_mainPage->reset(); } void InjectedBundle::closeOtherPages() diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h index 42eb3a1..ba021b1 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundle.h @@ -26,6 +26,8 @@ #ifndef InjectedBundle_h #define InjectedBundle_h +#include "EventSendingController.h" +#include "GCController.h" #include "LayoutTestController.h" #include <WebKit2/WKBase.h> #include <WebKit2/WKBundleBase.h> @@ -46,17 +48,19 @@ public: // Initialize the InjectedBundle. void initialize(WKBundleRef); - void done(); + WKBundleRef bundle() const { return m_bundle; } LayoutTestController* layoutTestController() { return m_layoutTestController.get(); } + GCController* gcController() { return m_gcController.get(); } + EventSendingController* eventSendingController() { return m_eventSendingController.get(); } + InjectedBundlePage* page() { return m_mainPage.get(); } size_t pageCount() { return !!m_mainPage + m_otherPages.size(); } void closeOtherPages(); + void done(); std::ostringstream& os() { return m_outputStream; } - void setShouldTrackVisitedLinks(); - private: InjectedBundle(); ~InjectedBundle(); @@ -76,6 +80,8 @@ private: OwnPtr<InjectedBundlePage> m_mainPage; RefPtr<LayoutTestController> m_layoutTestController; + RefPtr<GCController> m_gcController; + RefPtr<EventSendingController> m_eventSendingController; std::ostringstream m_outputStream; }; diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp index 406787e..40a098e 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp @@ -26,6 +26,7 @@ #include "InjectedBundlePage.h" #include "InjectedBundle.h" +#include "StringFunctions.h" #include <JavaScriptCore/JSRetainPtr.h> #include <WebKit2/WKArray.h> #include <WebKit2/WKBundleFrame.h> @@ -34,43 +35,27 @@ #include <WebKit2/WKBundlePagePrivate.h> #include <WebKit2/WKRetainPtr.h> #include <WebKit2/WKBundleRange.h> -#include <WebKit2/WKString.h> -#include <WebKit2/WKStringCF.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/RetainPtr.h> -#include <wtf/Vector.h> using namespace std; namespace WTR { -static ostream& operator<<(ostream& out, CFStringRef stringRef) -{ - if (!stringRef) - return out; - CFIndex bufferLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef), kCFStringEncodingUTF8) + 1; - Vector<char> buffer(bufferLength); - if (!CFStringGetCString(stringRef, buffer.data(), bufferLength, kCFStringEncodingUTF8)) - return out; - return out << buffer.data(); -} - -static ostream& operator<<(ostream& out, const RetainPtr<CFStringRef>& stringRef) -{ - return out << stringRef.get(); -} - -static ostream& operator<<(ostream& out, WKStringRef stringRef) -{ - if (!stringRef) - return out; - RetainPtr<CFStringRef> cfString(AdoptCF, WKStringCopyCFString(0, stringRef)); - return out << cfString; -} +static ostream& operator<<(ostream& out, WKBundleFrameRef frame) +{ + WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame)); + if (WKBundleFrameIsMainFrame(frame)) { + if (!WKStringIsEmpty(name.get())) + out << "main frame \"" << name << "\""; + else + out << "main frame"; + } else { + if (!WKStringIsEmpty(name.get())) + out << "frame \"" << name << "\""; + else + out << "frame (anonymous)"; + } -static ostream& operator<<(ostream& out, const WKRetainPtr<WKStringRef>& stringRef) -{ - return out << stringRef.get(); + return out; } static string dumpPath(WKBundleNodeRef node) @@ -111,42 +96,49 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page) WKBundlePageLoaderClient loaderClient = { 0, this, - _didStartProvisionalLoadForFrame, - _didReceiveServerRedirectForProvisionalLoadForFrame, - _didFailProvisionalLoadWithErrorForFrame, - _didCommitLoadForFrame, - _didFinishLoadForFrame, - _didFailLoadWithErrorForFrame, - _didReceiveTitleForFrame, - _didClearWindowForFrame + didStartProvisionalLoadForFrame, + didReceiveServerRedirectForProvisionalLoadForFrame, + didFailProvisionalLoadWithErrorForFrame, + didCommitLoadForFrame, + didFinishLoadForFrame, + didFailLoadWithErrorForFrame, + didReceiveTitleForFrame, + didClearWindowForFrame, + didCancelClientRedirectForFrame, + willPerformClientRedirectForFrame, + didChangeLocationWithinPageForFrame, + didFinishDocumentLoadForFrame, + didHandleOnloadEventsForFrame, + didDisplayInsecureContentForFrame, + didRunInsecureContentForFrame }; WKBundlePageSetLoaderClient(m_page, &loaderClient); WKBundlePageUIClient uiClient = { 0, this, - _willAddMessageToConsole, - _willSetStatusbarText, - _willRunJavaScriptAlert, - _willRunJavaScriptConfirm, - _willRunJavaScriptPrompt + willAddMessageToConsole, + willSetStatusbarText, + willRunJavaScriptAlert, + willRunJavaScriptConfirm, + willRunJavaScriptPrompt }; WKBundlePageSetUIClient(m_page, &uiClient); WKBundlePageEditorClient editorClient = { 0, this, - _shouldBeginEditing, - _shouldEndEditing, - _shouldInsertNode, - _shouldInsertText, - _shouldDeleteRange, - _shouldChangeSelectedRange, - _shouldApplyStyle, - _didBeginEditing, - _didEndEditing, - _didChange, - _didChangeSelection + shouldBeginEditing, + shouldEndEditing, + shouldInsertNode, + shouldInsertText, + shouldDeleteRange, + shouldChangeSelectedRange, + shouldApplyStyle, + didBeginEditing, + didEndEditing, + didChange, + didChangeSelection }; WKBundlePageSetEditorClient(m_page, &editorClient); } @@ -158,50 +150,89 @@ InjectedBundlePage::~InjectedBundlePage() void InjectedBundlePage::reset() { WKBundlePageClearMainFrameName(m_page); + + WKBundlePageSetZoomFactor(m_page, 1.0f); + WKBundlePageSetZoomMode(m_page, kWKBundlePageZoomModePage); } // Loader Client Callbacks -void InjectedBundlePage::_didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didStartProvisionalLoadForFrame(frame); } -void InjectedBundlePage::_didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame); } -void InjectedBundlePage::_didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame); } -void InjectedBundlePage::_didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(frame); } -void InjectedBundlePage::_didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(frame); } -void InjectedBundlePage::_didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame); } -void InjectedBundlePage::_didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveTitleForFrame(title, frame); } -void InjectedBundlePage::_didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, JSGlobalContextRef context, JSObjectRef window, const void *clientInfo) +void InjectedBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, JSGlobalContextRef context, JSObjectRef window, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, context, window); } +void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) +{ + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCancelClientRedirectForFrame(frame); +} + +void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKURLRef url, double delay, double date, const void* clientInfo) +{ + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willPerformClientRedirectForFrame(frame, url, delay, date); +} + +void InjectedBundlePage::didChangeLocationWithinPageForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) +{ + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChangeLocationWithinPageForFrame(frame); +} + +void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) +{ + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishDocumentLoadForFrame(frame); +} + +void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) +{ + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didHandleOnloadEventsForFrame(frame); +} + +void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) +{ + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didDisplayInsecureContentForFrame(frame); +} + +void InjectedBundlePage::didRunInsecureContentForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo) +{ + static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didRunInsecureContentForFrame(frame); +} + + void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame) { if (frame == WKBundlePageGetMainFrame(m_page)) @@ -355,37 +386,74 @@ void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame) void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame) { + if (!InjectedBundle::shared().layoutTestController()->shouldDumpTitleChanges()) + return; + + InjectedBundle::shared().os() << "TITLE CHANGED: " << title << "\n"; } void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, JSGlobalContextRef context, JSObjectRef window) { JSValueRef exception = 0; InjectedBundle::shared().layoutTestController()->makeWindowObject(context, window, &exception); + InjectedBundle::shared().gcController()->makeWindowObject(context, window, &exception); + InjectedBundle::shared().eventSendingController()->makeWindowObject(context, window, &exception); +} + +void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundleFrameRef frame) +{ +} + +void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundleFrameRef frame, WKURLRef url, double delay, double date) +{ +} + +void InjectedBundlePage::didChangeLocationWithinPageForFrame(WKBundleFrameRef frame) +{ +} + +void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundleFrameRef frame) +{ + unsigned pendingFrameUnloadEvents = WKBundleFrameGetPendingUnloadCount(frame); + if (pendingFrameUnloadEvents) + InjectedBundle::shared().os() << frame << " - has " << pendingFrameUnloadEvents << " onunload handler(s)\n"; +} + +void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundleFrameRef frame) +{ +} + +void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundleFrameRef frame) +{ +} + +void InjectedBundlePage::didRunInsecureContentForFrame(WKBundleFrameRef frame) +{ } // UI Client Callbacks -void InjectedBundlePage::_willAddMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo) +void InjectedBundlePage::willAddMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willAddMessageToConsole(message, lineNumber); } -void InjectedBundlePage::_willSetStatusbarText(WKBundlePageRef page, WKStringRef statusbarText, const void *clientInfo) +void InjectedBundlePage::willSetStatusbarText(WKBundlePageRef page, WKStringRef statusbarText, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSetStatusbarText(statusbarText); } -void InjectedBundlePage::_willRunJavaScriptAlert(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::willRunJavaScriptAlert(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptAlert(message, frame); } -void InjectedBundlePage::_willRunJavaScriptConfirm(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::willRunJavaScriptConfirm(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptConfirm(message, frame); } -void InjectedBundlePage::_willRunJavaScriptPrompt(WKBundlePageRef page, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void *clientInfo) +void InjectedBundlePage::willRunJavaScriptPrompt(WKBundlePageRef page, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void *clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptPrompt(message, defaultValue, frame); } @@ -421,57 +489,57 @@ void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRe // Editor Client Callbacks -bool InjectedBundlePage::_shouldBeginEditing(WKBundlePageRef page, WKBundleRangeRef range, const void* clientInfo) +bool InjectedBundlePage::shouldBeginEditing(WKBundlePageRef page, WKBundleRangeRef range, const void* clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldBeginEditing(range); } -bool InjectedBundlePage::_shouldEndEditing(WKBundlePageRef page, WKBundleRangeRef range, const void* clientInfo) +bool InjectedBundlePage::shouldEndEditing(WKBundlePageRef page, WKBundleRangeRef range, const void* clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldEndEditing(range); } -bool InjectedBundlePage::_shouldInsertNode(WKBundlePageRef page, WKBundleNodeRef node, WKBundleRangeRef rangeToReplace, WKInsertActionType action, const void* clientInfo) +bool InjectedBundlePage::shouldInsertNode(WKBundlePageRef page, WKBundleNodeRef node, WKBundleRangeRef rangeToReplace, WKInsertActionType action, const void* clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertNode(node, rangeToReplace, action); } -bool InjectedBundlePage::_shouldInsertText(WKBundlePageRef page, WKStringRef text, WKBundleRangeRef rangeToReplace, WKInsertActionType action, const void* clientInfo) +bool InjectedBundlePage::shouldInsertText(WKBundlePageRef page, WKStringRef text, WKBundleRangeRef rangeToReplace, WKInsertActionType action, const void* clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldInsertText(text, rangeToReplace, action); } -bool InjectedBundlePage::_shouldDeleteRange(WKBundlePageRef page, WKBundleRangeRef range, const void* clientInfo) +bool InjectedBundlePage::shouldDeleteRange(WKBundlePageRef page, WKBundleRangeRef range, const void* clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldDeleteRange(range); } -bool InjectedBundlePage::_shouldChangeSelectedRange(WKBundlePageRef page, WKBundleRangeRef fromRange, WKBundleRangeRef toRange, WKAffinityType affinity, bool stillSelecting, const void* clientInfo) +bool InjectedBundlePage::shouldChangeSelectedRange(WKBundlePageRef page, WKBundleRangeRef fromRange, WKBundleRangeRef toRange, WKAffinityType affinity, bool stillSelecting, const void* clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldChangeSelectedRange(fromRange, toRange, affinity, stillSelecting); } -bool InjectedBundlePage::_shouldApplyStyle(WKBundlePageRef page, WKBundleCSSStyleDeclarationRef style, WKBundleRangeRef range, const void* clientInfo) +bool InjectedBundlePage::shouldApplyStyle(WKBundlePageRef page, WKBundleCSSStyleDeclarationRef style, WKBundleRangeRef range, const void* clientInfo) { return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->shouldApplyStyle(style, range); } -void InjectedBundlePage::_didBeginEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) +void InjectedBundlePage::didBeginEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didBeginEditing(notificationName); } -void InjectedBundlePage::_didEndEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) +void InjectedBundlePage::didEndEditing(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didEndEditing(notificationName); } -void InjectedBundlePage::_didChange(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) +void InjectedBundlePage::didChange(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChange(notificationName); } -void InjectedBundlePage::_didChangeSelection(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) +void InjectedBundlePage::didChangeSelection(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo) { static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didChangeSelection(notificationName); } @@ -492,7 +560,7 @@ bool InjectedBundlePage::shouldEndEditing(WKBundleRangeRef range) bool InjectedBundlePage::shouldInsertNode(WKBundleNodeRef node, WKBundleRangeRef rangeToReplace, WKInsertActionType action) { - static const char *insertactionstring[] = { + static const char* insertactionstring[] = { "WebViewInsertActionTyped", "WebViewInsertActionPasted", "WebViewInsertActionDropped", diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h index f7d64f9..8909883 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h @@ -44,14 +44,21 @@ public: private: // Loader Client - static void _didStartProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void* clientInfo); - static void _didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void* clientInfo); - static void _didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, const void* clientInfo); - static void _didCommitLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void* clientInfo); - static void _didFinishLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void* clientInfo); - static void _didFailLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, const void* clientInfo); - static void _didReceiveTitleForFrame(WKBundlePageRef, WKStringRef title, WKBundleFrameRef, const void* clientInfo); - static void _didClearWindowForFrame(WKBundlePageRef, WKBundleFrameRef, JSGlobalContextRef, JSObjectRef window, const void* clientInfo); + static void didStartProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didCommitLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didFinishLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didFailLoadWithErrorForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didReceiveTitleForFrame(WKBundlePageRef, WKStringRef title, WKBundleFrameRef, const void*); + static void didClearWindowForFrame(WKBundlePageRef, WKBundleFrameRef, JSGlobalContextRef, JSObjectRef window, const void*); + static void didCancelClientRedirectForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void willPerformClientRedirectForFrame(WKBundlePageRef, WKBundleFrameRef, WKURLRef url, double delay, double date, const void*); + static void didChangeLocationWithinPageForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didFinishDocumentLoadForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didHandleOnloadEventsForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didDisplayInsecureContentForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); + static void didRunInsecureContentForFrame(WKBundlePageRef, WKBundleFrameRef, const void*); void didStartProvisionalLoadForFrame(WKBundleFrameRef); void didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef); void didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef); @@ -60,13 +67,20 @@ private: void didFailLoadWithErrorForFrame(WKBundleFrameRef); void didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef); void didClearWindowForFrame(WKBundleFrameRef, JSGlobalContextRef, JSObjectRef window); + void didCancelClientRedirectForFrame(WKBundleFrameRef); + void willPerformClientRedirectForFrame(WKBundleFrameRef, WKURLRef url, double delay, double date); + void didChangeLocationWithinPageForFrame(WKBundleFrameRef); + void didFinishDocumentLoadForFrame(WKBundleFrameRef); + void didHandleOnloadEventsForFrame(WKBundleFrameRef); + void didDisplayInsecureContentForFrame(WKBundleFrameRef); + void didRunInsecureContentForFrame(WKBundleFrameRef); // UI Client - static void _willAddMessageToConsole(WKBundlePageRef, WKStringRef message, uint32_t lineNumber, const void* clientInfo); - static void _willSetStatusbarText(WKBundlePageRef, WKStringRef statusbarText, const void* clientInfo); - static void _willRunJavaScriptAlert(WKBundlePageRef, WKStringRef message, WKBundleFrameRef frame, const void* clientInfo); - static void _willRunJavaScriptConfirm(WKBundlePageRef, WKStringRef message, WKBundleFrameRef frame, const void* clientInfo); - static void _willRunJavaScriptPrompt(WKBundlePageRef, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void* clientInfo); + static void willAddMessageToConsole(WKBundlePageRef, WKStringRef message, uint32_t lineNumber, const void* clientInfo); + static void willSetStatusbarText(WKBundlePageRef, WKStringRef statusbarText, const void* clientInfo); + static void willRunJavaScriptAlert(WKBundlePageRef, WKStringRef message, WKBundleFrameRef frame, const void* clientInfo); + static void willRunJavaScriptConfirm(WKBundlePageRef, WKStringRef message, WKBundleFrameRef frame, const void* clientInfo); + static void willRunJavaScriptPrompt(WKBundlePageRef, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void* clientInfo); void willAddMessageToConsole(WKStringRef message, uint32_t lineNumber); void willSetStatusbarText(WKStringRef statusbarText); void willRunJavaScriptAlert(WKStringRef message, WKBundleFrameRef); @@ -74,17 +88,17 @@ private: void willRunJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef); // Editor client - static bool _shouldBeginEditing(WKBundlePageRef, WKBundleRangeRef, const void* clientInfo); - static bool _shouldEndEditing(WKBundlePageRef, WKBundleRangeRef, const void* clientInfo); - static bool _shouldInsertNode(WKBundlePageRef, WKBundleNodeRef, WKBundleRangeRef rangeToReplace, WKInsertActionType, const void* clientInfo); - static bool _shouldInsertText(WKBundlePageRef, WKStringRef, WKBundleRangeRef rangeToReplace, WKInsertActionType, const void* clientInfo); - static bool _shouldDeleteRange(WKBundlePageRef, WKBundleRangeRef, const void* clientInfo); - static bool _shouldChangeSelectedRange(WKBundlePageRef, WKBundleRangeRef fromRange, WKBundleRangeRef toRange, WKAffinityType, bool stillSelecting, const void* clientInfo); - static bool _shouldApplyStyle(WKBundlePageRef, WKBundleCSSStyleDeclarationRef style, WKBundleRangeRef range, const void* clientInfo); - static void _didBeginEditing(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); - static void _didEndEditing(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); - static void _didChange(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); - static void _didChangeSelection(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); + static bool shouldBeginEditing(WKBundlePageRef, WKBundleRangeRef, const void* clientInfo); + static bool shouldEndEditing(WKBundlePageRef, WKBundleRangeRef, const void* clientInfo); + static bool shouldInsertNode(WKBundlePageRef, WKBundleNodeRef, WKBundleRangeRef rangeToReplace, WKInsertActionType, const void* clientInfo); + static bool shouldInsertText(WKBundlePageRef, WKStringRef, WKBundleRangeRef rangeToReplace, WKInsertActionType, const void* clientInfo); + static bool shouldDeleteRange(WKBundlePageRef, WKBundleRangeRef, const void* clientInfo); + static bool shouldChangeSelectedRange(WKBundlePageRef, WKBundleRangeRef fromRange, WKBundleRangeRef toRange, WKAffinityType, bool stillSelecting, const void* clientInfo); + static bool shouldApplyStyle(WKBundlePageRef, WKBundleCSSStyleDeclarationRef style, WKBundleRangeRef range, const void* clientInfo); + static void didBeginEditing(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); + static void didEndEditing(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); + static void didChange(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); + static void didChangeSelection(WKBundlePageRef, WKStringRef notificationName, const void* clientInfo); bool shouldBeginEditing(WKBundleRangeRef); bool shouldEndEditing(WKBundleRangeRef); bool shouldInsertNode(WKBundleNodeRef, WKBundleRangeRef rangeToReplace, WKInsertActionType); diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp index 8fda21e..f2393f1 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp @@ -28,12 +28,12 @@ #include "InjectedBundle.h" #include "InjectedBundlePage.h" #include "JSLayoutTestController.h" -#include <JavaScriptCore/JSRetainPtr.h> +#include "StringFunctions.h" #include <WebKit2/WKBundleFrame.h> #include <WebKit2/WKBundleFramePrivate.h> #include <WebKit2/WKBundlePagePrivate.h> +#include <WebKit2/WKBundlePrivate.h> #include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKStringCF.h> #include <WebKit2/WebKit2.h> namespace WTR { @@ -42,37 +42,6 @@ namespace WTR { // Eventually it should be changed to match. static const CFTimeInterval waitToDumpWatchdogInterval = 6.0; -static RetainPtr<CFStringRef> toCF(JSStringRef string) -{ - return RetainPtr<CFStringRef>(AdoptCF, JSStringCopyCFString(0, string)); -} - -static RetainPtr<CFStringRef> toCF(WKStringRef string) -{ - return RetainPtr<CFStringRef>(AdoptCF, WKStringCopyCFString(0, string)); -} - -static WKRetainPtr<WKStringRef> toWK(JSStringRef string) -{ - return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithCFString(toCF(string).get())); -} - -static JSRetainPtr<JSStringRef> toJS(WKStringRef string) -{ - return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithCFString(toCF(string).get())); -} - -static JSRetainPtr<JSStringRef> toJS(const WKRetainPtr<WKStringRef>& string) -{ - return toJS(string.get()); -} - -static void setProperty(JSContextRef context, JSObjectRef object, const char* propertyName, JSWrappable* value, JSPropertyAttributes attributes, JSValueRef* exception) -{ - JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName)); - JSObjectSetProperty(context, object, propertyNameString.get(), JSWrapper::wrap(context, value), attributes, exception); -} - static JSValueRef propertyValue(JSContextRef context, JSObjectRef object, const char* propertyName) { if (!object) @@ -119,6 +88,7 @@ LayoutTestController::LayoutTestController() , m_shouldCloseExtraWindows(false) , m_dumpEditingCallbacks(false) , m_dumpStatusCallbacks(false) + , m_dumpTitleChanges(false) , m_waitToDump(false) , m_testRepaint(false) , m_testRepaintSweepHorizontally(false) @@ -195,7 +165,7 @@ bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef anima void LayoutTestController::keepWebHistory() { - InjectedBundle::shared().setShouldTrackVisitedLinks(); + WKBundleSetShouldTrackVisitedLinks(InjectedBundle::shared().bundle(), true); } JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSValueRef element) diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h b/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h index 75aeb9e..7c3125c 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/LayoutTestController.h @@ -27,7 +27,6 @@ #define LayoutTestController_h #include "JSWrappable.h" -#include <JavaScriptCore/JavaScriptCore.h> #include <JavaScriptCore/JSRetainPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RetainPtr.h> @@ -56,6 +55,7 @@ public: void dumpEditingCallbacks() { m_dumpEditingCallbacks = true; } void dumpSelectionRect() { } // Will need to do something when we support pixel tests. void dumpStatusCallbacks() { m_dumpStatusCallbacks = true; } + void dumpTitleChanges() { m_dumpTitleChanges = true; } // Special options. void keepWebHistory(); @@ -88,6 +88,7 @@ public: bool shouldDumpMainFrameScrollPosition() const { return m_whatToDump == RenderTree; } bool shouldDumpStatusCallbacks() const { return m_dumpStatusCallbacks; } + bool shouldDumpTitleChanges() const { return m_dumpTitleChanges; } bool waitToDump() const { return m_waitToDump; } void waitToDumpWatchdogTimerFired(); @@ -108,6 +109,7 @@ private: bool m_dumpEditingCallbacks; bool m_dumpStatusCallbacks; + bool m_dumpTitleChanges; bool m_waitToDump; // True if waitUntilDone() has been called, but notifyDone() has not yet been called. bool m_testRepaint; bool m_testRepaintSweepHorizontally; diff --git a/WebKitTools/WebKitTestRunner/InjectedBundle/win/ActivateFonts.cpp b/WebKitTools/WebKitTestRunner/InjectedBundle/win/ActivateFonts.cpp index c7532ce..d9f08c9 100644 --- a/WebKitTools/WebKitTestRunner/InjectedBundle/win/ActivateFonts.cpp +++ b/WebKitTools/WebKitTestRunner/InjectedBundle/win/ActivateFonts.cpp @@ -25,11 +25,83 @@ #include "ActivateFonts.h" +#include <string> +#include <wtf/Vector.h> + +static LPCWSTR fontsEnvironmentVariable = L"WEBKIT_TESTFONTS"; + namespace WTR { +using namespace std; + +static const wstring& fontsPath() +{ + static wstring path; + static bool initialized; + + if (initialized) + return path; + initialized = true; + + DWORD size = ::GetEnvironmentVariableW(fontsEnvironmentVariable, 0, 0); + Vector<WCHAR> buffer(size); + if (!::GetEnvironmentVariableW(fontsEnvironmentVariable, buffer.data(), buffer.size())) + return path; + + path = buffer.data(); + if (path[path.length() - 1] != '\\') + path.append(L"\\"); + + return path; +} + + void activateFonts() { - // FIXME: Not implemented. + static LPCWSTR fontsToInstall[] = { + TEXT("AHEM____.ttf"), + TEXT("Apple Chancery.ttf"), + TEXT("Courier Bold.ttf"), + TEXT("Courier.ttf"), + TEXT("Helvetica Bold Oblique.ttf"), + TEXT("Helvetica Bold.ttf"), + TEXT("Helvetica Oblique.ttf"), + TEXT("Helvetica.ttf"), + TEXT("Helvetica Neue Bold Italic.ttf"), + TEXT("Helvetica Neue Bold.ttf"), + TEXT("Helvetica Neue Condensed Black.ttf"), + TEXT("Helvetica Neue Condensed Bold.ttf"), + TEXT("Helvetica Neue Italic.ttf"), + TEXT("Helvetica Neue Light Italic.ttf"), + TEXT("Helvetica Neue Light.ttf"), + TEXT("Helvetica Neue UltraLight Italic.ttf"), + TEXT("Helvetica Neue UltraLight.ttf"), + TEXT("Helvetica Neue.ttf"), + TEXT("Lucida Grande.ttf"), + TEXT("Lucida Grande Bold.ttf"), + TEXT("Monaco.ttf"), + TEXT("Papyrus.ttf"), + TEXT("Times Bold Italic.ttf"), + TEXT("Times Bold.ttf"), + TEXT("Times Italic.ttf"), + TEXT("Times Roman.ttf"), + TEXT("WebKit Layout Tests 2.ttf"), + TEXT("WebKit Layout Tests.ttf"), + TEXT("WebKitWeightWatcher100.ttf"), + TEXT("WebKitWeightWatcher200.ttf"), + TEXT("WebKitWeightWatcher300.ttf"), + TEXT("WebKitWeightWatcher400.ttf"), + TEXT("WebKitWeightWatcher500.ttf"), + TEXT("WebKitWeightWatcher600.ttf"), + TEXT("WebKitWeightWatcher700.ttf"), + TEXT("WebKitWeightWatcher800.ttf"), + TEXT("WebKitWeightWatcher900.ttf") + }; + + wstring resourcesPath = fontsPath(); + + for (unsigned i = 0; i < ARRAYSIZE(fontsToInstall); ++i) + ::AddFontResourceExW(wstring(resourcesPath + fontsToInstall[i]).c_str(), FR_PRIVATE, 0); } } diff --git a/WebKitTools/WebKitTestRunner/StringFunctions.h b/WebKitTools/WebKitTestRunner/StringFunctions.h new file mode 100644 index 0000000..4f8fe93 --- /dev/null +++ b/WebKitTools/WebKitTestRunner/StringFunctions.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 StringFunctions_h +#define StringFunctions_h + +#include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/JavaScriptCore.h> +#include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WKString.h> +#include <WebKit2/WKStringCF.h> +#include <WebKit2/WKURL.h> +#include <WebKit2/WKURLCF.h> +#include <sstream> +#include <wtf/Platform.h> +#include <wtf/RetainPtr.h> +#include <wtf/Vector.h> + +namespace WTR { + +// Conversion functions + +inline RetainPtr<CFStringRef> toCF(JSStringRef string) +{ + return RetainPtr<CFStringRef>(AdoptCF, JSStringCopyCFString(0, string)); +} + +inline RetainPtr<CFStringRef> toCF(WKStringRef string) +{ + return RetainPtr<CFStringRef>(AdoptCF, WKStringCopyCFString(0, string)); +} + +inline WKRetainPtr<WKStringRef> toWK(JSStringRef string) +{ + return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithCFString(toCF(string).get())); +} + +inline WKRetainPtr<WKStringRef> toWK(JSRetainPtr<JSStringRef> string) +{ + return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithCFString(toCF(string.get()).get())); +} + +inline JSRetainPtr<JSStringRef> toJS(WKStringRef string) +{ + return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithCFString(toCF(string).get())); +} + +inline JSRetainPtr<JSStringRef> toJS(const WKRetainPtr<WKStringRef>& string) +{ + return toJS(string.get()); +} + +// Streaming functions + +inline std::ostream& operator<<(std::ostream& out, CFStringRef stringRef) +{ + if (!stringRef) + return out; + CFIndex bufferLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef), kCFStringEncodingUTF8) + 1; + Vector<char> buffer(bufferLength); + if (!CFStringGetCString(stringRef, buffer.data(), bufferLength, kCFStringEncodingUTF8)) + return out; + return out << buffer.data(); +} + +inline std::ostream& operator<<(std::ostream& out, const RetainPtr<CFStringRef>& stringRef) +{ + return out << stringRef.get(); +} + +inline std::ostream& operator<<(std::ostream& out, WKStringRef stringRef) +{ + if (!stringRef) + return out; + return out << toCF(stringRef); +} + +inline std::ostream& operator<<(std::ostream& out, const WKRetainPtr<WKStringRef>& stringRef) +{ + return out << stringRef.get(); +} + +// URL creation + +inline WKURLRef createWKURL(const char* pathOrURL) +{ + RetainPtr<CFStringRef> pathOrURLCFString(AdoptCF, CFStringCreateWithCString(0, pathOrURL, kCFStringEncodingUTF8)); + RetainPtr<CFURLRef> cfURL; + if (CFStringHasPrefix(pathOrURLCFString.get(), CFSTR("http://")) || CFStringHasPrefix(pathOrURLCFString.get(), CFSTR("https://"))) + cfURL.adoptCF(CFURLCreateWithString(0, pathOrURLCFString.get(), 0)); + else +#if PLATFORM(WIN) + cfURL.adoptCF(CFURLCreateWithFileSystemPath(0, pathOrURLCFString.get(), kCFURLWindowsPathStyle, false)); +#else + cfURL.adoptCF(CFURLCreateWithFileSystemPath(0, pathOrURLCFString.get(), kCFURLPOSIXPathStyle, false)); +#endif + return WKURLCreateWithCFURL(cfURL.get()); +} + + +} // namespace WTR + +#endif // StringFunctions_h diff --git a/WebKitTools/WebKitTestRunner/TestInvocation.cpp b/WebKitTools/WebKitTestRunner/TestInvocation.cpp index 658911b..9a0f0aa 100644 --- a/WebKitTools/WebKitTestRunner/TestInvocation.cpp +++ b/WebKitTools/WebKitTestRunner/TestInvocation.cpp @@ -26,47 +26,18 @@ #include "TestInvocation.h" #include "PlatformWebView.h" +#include "StringFunctions.h" #include "TestController.h" #include <WebKit2/WKContextPrivate.h> +#include <WebKit2/WKPreferencesPrivate.h> #include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKStringCF.h> -#include <WebKit2/WKURLCF.h> -#include <wtf/PassOwnPtr.h> #include <wtf/RetainPtr.h> -#include <wtf/Vector.h> using namespace WebKit; +using namespace std; namespace WTR { -static WKURLRef createWKURL(const char* pathOrURL) -{ - RetainPtr<CFStringRef> pathOrURLCFString(AdoptCF, CFStringCreateWithCString(0, pathOrURL, kCFStringEncodingUTF8)); - RetainPtr<CFURLRef> cfURL; - if (CFStringHasPrefix(pathOrURLCFString.get(), CFSTR("http://")) || CFStringHasPrefix(pathOrURLCFString.get(), CFSTR("https://"))) - cfURL.adoptCF(CFURLCreateWithString(0, pathOrURLCFString.get(), 0)); - else -#if defined(WIN32) || defined(_WIN32) - cfURL.adoptCF(CFURLCreateWithFileSystemPath(0, pathOrURLCFString.get(), kCFURLWindowsPathStyle, false)); -#else - cfURL.adoptCF(CFURLCreateWithFileSystemPath(0, pathOrURLCFString.get(), kCFURLPOSIXPathStyle, false)); -#endif - return WKURLCreateWithCFURL(cfURL.get()); -} - -static PassOwnPtr<Vector<char> > WKStringToUTF8(WKStringRef wkStringRef) -{ - RetainPtr<CFStringRef> cfString(AdoptCF, WKStringCopyCFString(0, wkStringRef)); - CFIndex bufferLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfString.get()), kCFStringEncodingUTF8) + 1; - OwnPtr<Vector<char> > buffer(new Vector<char>(bufferLength)); - if (!CFStringGetCString(cfString.get(), buffer->data(), bufferLength, kCFStringEncodingUTF8)) { - buffer->shrink(1); - (*buffer)[0] = 0; - } else - buffer->shrink(strlen(buffer->data()) + 1); - return buffer.release(); -} - TestInvocation::TestInvocation(const char* pathOrURL) : m_url(AdoptWK, createWKURL(pathOrURL)) , m_pathOrURL(fastStrDup(pathOrURL)) @@ -99,8 +70,8 @@ static void sizeWebViewForCurrentTest(char* pathOrURL) void TestInvocation::resetPreferencesToConsistentValues() { WKPreferencesRef preferences = WKContextGetPreferences(TestController::shared().context()); - WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true); + WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing); } void TestInvocation::invoke() @@ -165,8 +136,11 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName if (CFEqual(cfMessageName.get(), CFSTR("Done"))) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); - OwnPtr<Vector<char> > utf8Message = WKStringToUTF8(static_cast<WKStringRef>(messageBody)); - dump(utf8Message->data()); + ostringstream out; + out << static_cast<WKStringRef>(messageBody); + + dump(out.str().c_str()); + m_gotFinalMessage = true; return; } diff --git a/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj b/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj index eccf330..6f78289 100644 --- a/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj +++ b/WebKitTools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ 6510A78B11EC643800410867 /* WebKitWeightWatcher800.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6510A78011EC643800410867 /* WebKitWeightWatcher800.ttf */; }; 6510A78C11EC643800410867 /* WebKitWeightWatcher900.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6510A78111EC643800410867 /* WebKitWeightWatcher900.ttf */; }; 65EB85A011EC67CC0034D300 /* ActivateFonts.mm in Sources */ = {isa = PBXBuildFile; fileRef = 65EB859F11EC67CC0034D300 /* ActivateFonts.mm */; }; + BC14E4DB120E02D000826C0C /* GCController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC14E4D9120E02D000826C0C /* GCController.cpp */; }; + BC14E4EA120E03D800826C0C /* JSGCController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC14E4E8120E03D800826C0C /* JSGCController.cpp */; }; BC25193E11D15D8B002EBC01 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC7934A411906584005EA8E2 /* Cocoa.framework */; }; BC25193F11D15D8B002EBC01 /* WebKit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC7934AB1190658C005EA8E2 /* WebKit2.framework */; }; BC25194011D15D8B002EBC01 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCDA2B991191051F00C3BC47 /* JavaScriptCore.framework */; }; @@ -43,6 +45,8 @@ BC7934AC1190658C005EA8E2 /* WebKit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC7934AB1190658C005EA8E2 /* WebKit2.framework */; }; BC7934E811906846005EA8E2 /* PlatformWebViewMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC7934E711906846005EA8E2 /* PlatformWebViewMac.mm */; }; BC8C795C11D2785D004535A1 /* TestControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC8C795B11D2785D004535A1 /* TestControllerMac.mm */; }; + BC8FD8CA120E527F00F3E71A /* EventSendingController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC8FD8C9120E527F00F3E71A /* EventSendingController.cpp */; }; + BC8FD8D2120E545B00F3E71A /* JSEventSendingController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC8FD8D0120E545B00F3E71A /* JSEventSendingController.cpp */; }; BC952C0D11F3B965003398B4 /* JSWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC952C0C11F3B965003398B4 /* JSWrapper.cpp */; }; BC952F1F11F3C652003398B4 /* JSLayoutTestController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC952F1D11F3C652003398B4 /* JSLayoutTestController.cpp */; }; BCC997A411D3C8F60017BCA2 /* InjectedBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCC997A011D3C8F60017BCA2 /* InjectedBundle.cpp */; }; @@ -85,6 +89,11 @@ 65EB859D11EC67CC0034D300 /* ActivateFonts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActivateFonts.h; sourceTree = "<group>"; }; 65EB859F11EC67CC0034D300 /* ActivateFonts.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ActivateFonts.mm; sourceTree = "<group>"; }; 8DD76FA10486AA7600D96B5E /* WebKitTestRunner */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = WebKitTestRunner; sourceTree = BUILT_PRODUCTS_DIR; }; + BC14E4D8120E02D000826C0C /* GCController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCController.h; sourceTree = "<group>"; }; + BC14E4D9120E02D000826C0C /* GCController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCController.cpp; sourceTree = "<group>"; }; + BC14E4E1120E032000826C0C /* GCController.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GCController.idl; sourceTree = "<group>"; }; + BC14E4E8120E03D800826C0C /* JSGCController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSGCController.cpp; path = DerivedSources/WebKitTestRunner/JSGCController.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + BC14E4E9120E03D800826C0C /* JSGCController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSGCController.h; path = DerivedSources/WebKitTestRunner/JSGCController.h; sourceTree = BUILT_PRODUCTS_DIR; }; BC25184611D15767002EBC01 /* InjectedBundleMain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleMain.cpp; sourceTree = "<group>"; }; BC25186211D15D54002EBC01 /* InjectedBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InjectedBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; BC25186311D15D54002EBC01 /* InjectedBundle-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "InjectedBundle-Info.plist"; sourceTree = "<group>"; }; @@ -101,6 +110,11 @@ BC7934DD119066EC005EA8E2 /* PlatformWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformWebView.h; sourceTree = "<group>"; }; BC7934E711906846005EA8E2 /* PlatformWebViewMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformWebViewMac.mm; sourceTree = "<group>"; }; BC8C795B11D2785D004535A1 /* TestControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestControllerMac.mm; sourceTree = "<group>"; }; + BC8FD8C8120E527F00F3E71A /* EventSendingController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventSendingController.h; sourceTree = "<group>"; }; + BC8FD8C9120E527F00F3E71A /* EventSendingController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventSendingController.cpp; sourceTree = "<group>"; }; + BC8FD8CB120E52B000F3E71A /* EventSendingController.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EventSendingController.idl; sourceTree = "<group>"; }; + BC8FD8D0120E545B00F3E71A /* JSEventSendingController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSEventSendingController.cpp; path = DerivedSources/WebKitTestRunner/JSEventSendingController.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + BC8FD8D1120E545B00F3E71A /* JSEventSendingController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSEventSendingController.h; path = DerivedSources/WebKitTestRunner/JSEventSendingController.h; sourceTree = BUILT_PRODUCTS_DIR; }; BC952C0B11F3B965003398B4 /* JSWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWrapper.h; sourceTree = "<group>"; }; BC952C0C11F3B965003398B4 /* JSWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWrapper.cpp; sourceTree = "<group>"; }; BC952C0E11F3B97B003398B4 /* JSWrappable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWrappable.h; sourceTree = "<group>"; }; @@ -109,6 +123,7 @@ BC952ED311F3C318003398B4 /* CodeGeneratorTestRunner.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = CodeGeneratorTestRunner.pm; sourceTree = "<group>"; }; BC952F1D11F3C652003398B4 /* JSLayoutTestController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSLayoutTestController.cpp; path = DerivedSources/WebKitTestRunner/JSLayoutTestController.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; BC952F1E11F3C652003398B4 /* JSLayoutTestController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSLayoutTestController.h; path = DerivedSources/WebKitTestRunner/JSLayoutTestController.h; sourceTree = BUILT_PRODUCTS_DIR; }; + BC99A4841208901A007E9F08 /* StringFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringFunctions.h; sourceTree = "<group>"; }; BCC997A011D3C8F60017BCA2 /* InjectedBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundle.cpp; sourceTree = "<group>"; }; BCC997A111D3C8F60017BCA2 /* InjectedBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundle.h; sourceTree = "<group>"; }; BCC997A211D3C8F60017BCA2 /* InjectedBundlePage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePage.cpp; sourceTree = "<group>"; }; @@ -149,7 +164,8 @@ isa = PBXGroup; children = ( BC952EC511F3C10F003398B4 /* DerivedSources.make */, - 08FB7795FE84155DC02AAC07 /* Source */, + BC99CBF11207642D00FDEE76 /* Shared */, + 08FB7795FE84155DC02AAC07 /* TestRunner */, BC25183511D1571D002EBC01 /* InjectedBundle */, BC793401118F7C8A005EA8E2 /* Configurations */, 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, @@ -159,7 +175,7 @@ name = WebKitTestRunner; sourceTree = "<group>"; }; - 08FB7795FE84155DC02AAC07 /* Source */ = { + 08FB7795FE84155DC02AAC07 /* TestRunner */ = { isa = PBXGroup; children = ( BC7933FE118F7C74005EA8E2 /* mac */, @@ -170,7 +186,7 @@ BCD7D2F611921278006DB7EE /* TestInvocation.h */, BCD7D2F711921278006DB7EE /* TestInvocation.cpp */, ); - name = Source; + name = TestRunner; sourceTree = "<group>"; }; 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = { @@ -200,11 +216,25 @@ path = mac; sourceTree = "<group>"; }; + BC14E4E0120E02F900826C0C /* Controllers */ = { + isa = PBXGroup; + children = ( + BC8FD8C9120E527F00F3E71A /* EventSendingController.cpp */, + BC8FD8C8120E527F00F3E71A /* EventSendingController.h */, + BC14E4D9120E02D000826C0C /* GCController.cpp */, + BC14E4D8120E02D000826C0C /* GCController.h */, + BCC9981711D3F51E0017BCA2 /* LayoutTestController.cpp */, + BCC9981611D3F51E0017BCA2 /* LayoutTestController.h */, + ); + name = Controllers; + sourceTree = "<group>"; + }; BC25183511D1571D002EBC01 /* InjectedBundle */ = { isa = PBXGroup; children = ( BC952D3A11F3BF1F003398B4 /* Derived Sources */, BC952C0A11F3B939003398B4 /* Bindings */, + BC14E4E0120E02F900826C0C /* Controllers */, 65EB859E11EC67CC0034D300 /* mac */, 65EB859D11EC67CC0034D300 /* ActivateFonts.h */, BCC997A011D3C8F60017BCA2 /* InjectedBundle.cpp */, @@ -212,8 +242,6 @@ BC25184611D15767002EBC01 /* InjectedBundleMain.cpp */, BCC997A211D3C8F60017BCA2 /* InjectedBundlePage.cpp */, BCC997A311D3C8F60017BCA2 /* InjectedBundlePage.h */, - BCC9981711D3F51E0017BCA2 /* LayoutTestController.cpp */, - BCC9981611D3F51E0017BCA2 /* LayoutTestController.h */, ); path = InjectedBundle; sourceTree = "<group>"; @@ -266,6 +294,8 @@ BC952C0E11F3B97B003398B4 /* JSWrappable.h */, BC952C0C11F3B965003398B4 /* JSWrapper.cpp */, BC952C0B11F3B965003398B4 /* JSWrapper.h */, + BC8FD8CB120E52B000F3E71A /* EventSendingController.idl */, + BC14E4E1120E032000826C0C /* GCController.idl */, BC952ED211F3C29F003398B4 /* LayoutTestController.idl */, ); path = Bindings; @@ -274,12 +304,24 @@ BC952D3A11F3BF1F003398B4 /* Derived Sources */ = { isa = PBXGroup; children = ( + BC8FD8D0120E545B00F3E71A /* JSEventSendingController.cpp */, + BC8FD8D1120E545B00F3E71A /* JSEventSendingController.h */, + BC14E4E8120E03D800826C0C /* JSGCController.cpp */, + BC14E4E9120E03D800826C0C /* JSGCController.h */, BC952F1D11F3C652003398B4 /* JSLayoutTestController.cpp */, BC952F1E11F3C652003398B4 /* JSLayoutTestController.h */, ); name = "Derived Sources"; sourceTree = "<group>"; }; + BC99CBF11207642D00FDEE76 /* Shared */ = { + isa = PBXGroup; + children = ( + BC99A4841208901A007E9F08 /* StringFunctions.h */, + ); + name = Shared; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -401,6 +443,10 @@ 65EB85A011EC67CC0034D300 /* ActivateFonts.mm in Sources */, BC952C0D11F3B965003398B4 /* JSWrapper.cpp in Sources */, BC952F1F11F3C652003398B4 /* JSLayoutTestController.cpp in Sources */, + BC14E4DB120E02D000826C0C /* GCController.cpp in Sources */, + BC14E4EA120E03D800826C0C /* JSGCController.cpp in Sources */, + BC8FD8CA120E527F00F3E71A /* EventSendingController.cpp in Sources */, + BC8FD8D2120E545B00F3E71A /* JSEventSendingController.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj b/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj index d283083..71dcf95 100644 --- a/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj +++ b/WebKitTools/WebKitTestRunner/win/InjectedBundle.vcproj @@ -288,6 +288,22 @@ Name="Derived Sources"
>
<File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSEventSendingController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSEventSendingController.h"
+ >
+ </File>
+ <File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSGCController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSGCController.h"
+ >
+ </File>
+ <File
RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSLayoutTestController.cpp"
>
</File>
@@ -321,6 +337,22 @@ >
</File>
<File
+ RelativePath="..\InjectedBundle\EventSendingController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\InjectedBundle\EventSendingController.h"
+ >
+ </File>
+ <File
+ RelativePath="..\InjectedBundle\GCController.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\InjectedBundle\GCController.h"
+ >
+ </File>
+ <File
RelativePath="..\InjectedBundle\LayoutTestController.cpp"
>
</File>
diff --git a/WebKitTools/WebKitTestRunner/win/TestControllerWin.cpp b/WebKitTools/WebKitTestRunner/win/TestControllerWin.cpp index 9bec373..f650d7f 100644 --- a/WebKitTools/WebKitTestRunner/win/TestControllerWin.cpp +++ b/WebKitTools/WebKitTestRunner/win/TestControllerWin.cpp @@ -27,14 +27,67 @@ #include <fcntl.h> #include <io.h> +#include <shlwapi.h> +#include <string> #include <WebKit2/WKStringCF.h> +#include <wtf/RetainPtr.h> +#include <wtf/Vector.h> + +using namespace std; namespace WTR { +#if !defined(NDEBUG) && (!defined(DEBUG_INTERNAL) || defined(DEBUG_ALL)) +const LPWSTR testPluginDirectoryName = L"TestNetscapePlugin_Debug"; +#else +const LPWSTR testPluginDirectoryName = L"TestNetscapePlugin"; +#endif + +static void addQTDirToPATH() +{ + static LPCWSTR pathEnvironmentVariable = L"PATH"; + static LPCWSTR quickTimeKeyName = L"Software\\Apple Computer, Inc.\\QuickTime"; + static LPCWSTR quickTimeSysDir = L"QTSysDir"; + static bool initialized; + + if (initialized) + return; + initialized = true; + + // Get the QuickTime dll directory from the registry. The key can be in either HKLM or HKCU. + WCHAR qtPath[MAX_PATH]; + DWORD qtPathBufferLen = sizeof(qtPath); + DWORD keyType; + HRESULT result = ::SHGetValueW(HKEY_LOCAL_MACHINE, quickTimeKeyName, quickTimeSysDir, &keyType, (LPVOID)qtPath, &qtPathBufferLen); + if (result != ERROR_SUCCESS || !qtPathBufferLen || keyType != REG_SZ) { + qtPathBufferLen = sizeof(qtPath); + result = ::SHGetValueW(HKEY_CURRENT_USER, quickTimeKeyName, quickTimeSysDir, &keyType, (LPVOID)qtPath, &qtPathBufferLen); + if (result != ERROR_SUCCESS || !qtPathBufferLen || keyType != REG_SZ) + return; + } + + // Read the current PATH. + DWORD pathSize = ::GetEnvironmentVariableW(pathEnvironmentVariable, 0, 0); + Vector<WCHAR> oldPath(pathSize); + if (!::GetEnvironmentVariableW(pathEnvironmentVariable, oldPath.data(), oldPath.size())) + return; + + // And add the QuickTime dll. + wstring newPath; + newPath.append(qtPath); + newPath.append(L";"); + newPath.append(oldPath.data(), oldPath.size()); + ::SetEnvironmentVariableW(pathEnvironmentVariable, newPath.data()); +} + void TestController::platformInitialize() { _setmode(1, _O_BINARY); _setmode(2, _O_BINARY); + + // Add the QuickTime dll directory to PATH or QT 7.6 will fail to initialize on systems + // linked with older versions of qtmlclientlib.dll. + addQTDirToPATH(); } void TestController::initializeInjectedBundlePath() @@ -52,9 +105,12 @@ void TestController::initializeInjectedBundlePath() void TestController::initializeTestPluginDirectory() { - CFStringRef exeContainerPath = CFURLCopyFileSystemPath(CFURLCreateCopyDeletingLastPathComponent(0, CFBundleCopyExecutableURL(CFBundleGetMainBundle())), kCFURLWindowsPathStyle); - CFMutableStringRef bundlePath = CFStringCreateMutableCopy(0, 0, exeContainerPath); - m_testPluginDirectory.adopt(WKStringCreateWithCFString(bundlePath)); + RetainPtr<CFURLRef> bundleURL(AdoptCF, CFBundleCopyExecutableURL(CFBundleGetMainBundle())); + RetainPtr<CFURLRef> bundleDirectoryURL(AdoptCF, CFURLCreateCopyDeletingLastPathComponent(0, bundleURL.get())); + RetainPtr<CFStringRef> testPluginDirectoryNameString(AdoptCF, CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar*>(testPluginDirectoryName), wcslen(testPluginDirectoryName))); + RetainPtr<CFURLRef> testPluginDirectoryURL(AdoptCF, CFURLCreateCopyAppendingPathComponent(0, bundleDirectoryURL.get(), testPluginDirectoryNameString.get(), true)); + RetainPtr<CFStringRef> testPluginDirectoryPath(AdoptCF, CFURLCopyFileSystemPath(testPluginDirectoryURL.get(), kCFURLWindowsPathStyle)); + m_testPluginDirectory.adopt(WKStringCreateWithCFString(testPluginDirectoryPath.get())); } } // namespace WTR diff --git a/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj b/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj index 4802c3a..7375bd4 100644 --- a/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj +++ b/WebKitTools/WebKitTestRunner/win/WebKitTestRunner.vcproj @@ -56,7 +56,7 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/NXCOMPAT"
- AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib shlwapi.lib"
SubSystem="1"
TargetMachine="1"
/>
@@ -128,7 +128,7 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/NXCOMPAT"
- AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib shlwapi.lib"
SubSystem="1"
TargetMachine="1"
/>
@@ -199,7 +199,7 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/NXCOMPAT"
- AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib shlwapi.lib"
SubSystem="1"
/>
<Tool
@@ -269,7 +269,7 @@ <Tool
Name="VCLinkerTool"
AdditionalOptions="/NXCOMPAT"
- AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib shlwapi.lib"
SubSystem="1"
/>
<Tool
diff --git a/WebKitTools/wx/build/settings.py b/WebKitTools/wx/build/settings.py index 2d144f6..be43873 100644 --- a/WebKitTools/wx/build/settings.py +++ b/WebKitTools/wx/build/settings.py @@ -303,8 +303,15 @@ def common_configure(conf): conf.env['LIB_WX'] = wxlibs conf.env['LIBPATH_WX'] = wxlibpaths - conf.env['LIB_JSCORE'] = [libprefix + 'jscore'] - conf.env['LIB_WEBCORE'] = [libprefix + 'webcore'] + if building_on_win32: + conf.env['LIB_JSCORE'] = [libprefix + 'jscore'] + conf.env['LIB_WEBCORE'] = [libprefix + 'webcore'] + elif sys.platform.startswith('darwin'): + conf.env['LINKFLAGS_JSCORE'] = ['-Wl,-force_load,%s' % os.path.join(output_dir, 'libjscore.a')] + conf.env['LINKFLAGS_WEBCORE'] = ['-Wl,-force_load,%s' % os.path.join(output_dir, 'libwebcore.a')] + else: + conf.env['LINKFLAGS_JSCORE'] = ['-Wl,-whole-archive', '-ljscore', '-Wl,-no-whole-archive'] + conf.env['LINKFLAGS_WEBCORE'] = ['-Wl,-whole-archive', '-lwebcore', '-Wl,-no-whole-archive'] if sys.platform.startswith('darwin'): conf.env['LIB_ICU'] = ['icucore'] |