From: commit-queue@webkit.org Date: Wed, 8 Feb 2012 18:35:50 +0000 (+0000) Subject: [BlackBerry] Upstream DumpRenderTreeBlackBerry X-Git-Tag: 070512121124~13439 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=27222f4b484112bc142e5337bc9566a8a8d77824;p=profile%2Fivi%2Fwebkit-efl.git [BlackBerry] Upstream DumpRenderTreeBlackBerry https://bugs.webkit.org/show_bug.cgi?id=78042 Patch by Rob Buis on 2012-02-08 Reviewed by Antonio Gomes. Source/WebKit: Add abstract interface for our DumpRenderTree solution. * blackberry/Api/DumpRenderTreeClient.h: Added. Tools: Add implementation for our DumpRenderTree solution. * DumpRenderTree/blackberry/DumpRenderTree.cpp: Added. * DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h: Added. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@107105 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog index 56eedad..9c3a66d 100644 --- a/Source/WebKit/ChangeLog +++ b/Source/WebKit/ChangeLog @@ -1,3 +1,14 @@ +2012-02-08 Rob Buis + + [BlackBerry] Upstream DumpRenderTreeBlackBerry + https://bugs.webkit.org/show_bug.cgi?id=78042 + + Reviewed by Antonio Gomes. + + Add abstract interface for our DumpRenderTree solution. + + * blackberry/Api/DumpRenderTreeClient.h: Added. + 2012-02-08 Nima Ghanavatian Initial upstreaming of input handling for BlackBerry port diff --git a/Source/WebKit/blackberry/Api/DumpRenderTreeClient.h b/Source/WebKit/blackberry/Api/DumpRenderTreeClient.h new file mode 100644 index 0000000..03eb5bb --- /dev/null +++ b/Source/WebKit/blackberry/Api/DumpRenderTreeClient.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009, 2010, 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DumpRenderTreeClient_h +#define DumpRenderTreeClient_h + +#include "BlackBerryGlobal.h" + +#include "PlatformString.h" +#include + +namespace WebCore { +class Frame; +class DOMWrapperWorld; +class NavigationAction; +class Node; +class Range; +class ResourceRequest; +class ResourceResponse; +class SecurityOrigin; +} + +namespace BlackBerry { +namespace WebKit { +class WebPage; + +class BLACKBERRY_EXPORT DumpRenderTreeClient { +public: + virtual void runTests() = 0; + + // FrameLoaderClient delegates + virtual void didStartProvisionalLoadForFrame(WebCore::Frame*) = 0; + virtual void didReceiveResponseForFrame(WebCore::Frame*, const WebCore::ResourceResponse&) = 0; + virtual void didCommitLoadForFrame(WebCore::Frame*) = 0; + virtual void didFailProvisionalLoadForFrame(WebCore::Frame*) = 0; + virtual void didFailLoadForFrame(WebCore::Frame*) = 0; + virtual void didFinishLoadForFrame(WebCore::Frame*) = 0; + virtual void didFinishDocumentLoadForFrame(WebCore::Frame*) = 0; + virtual void didClearWindowObjectInWorld(WebCore::DOMWrapperWorld*, JSGlobalContextRef, JSObjectRef windowObject) = 0; + virtual void didReceiveTitleForFrame(const WTF::String& title, WebCore::Frame*) = 0; + virtual void didDecidePolicyForNavigationAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&) = 0; + virtual void didDispatchWillPerformClientRedirect() = 0; + virtual void didHandleOnloadEventsForFrame(WebCore::Frame*) = 0; + + // ChromeClient delegates + virtual void addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID) = 0; + virtual void runJavaScriptAlert(const WTF::String& message) = 0; + virtual bool runJavaScriptConfirm(const WTF::String& message) = 0; + virtual WTF::String runJavaScriptPrompt(const WTF::String& message, const WTF::String& defaultValue) = 0; + virtual bool runBeforeUnloadConfirmPanel(const WTF::String& message) = 0; + virtual void setStatusText(const WTF::String&) = 0; + virtual void exceededDatabaseQuota(WebCore::SecurityOrigin*, const WTF::String& name) = 0; + virtual bool allowsOpeningWindow() = 0; + virtual void windowCreated(WebPage*) = 0; + + // EditorClient delegates + virtual void setAcceptsEditing(bool) = 0; + virtual void didBeginEditing() = 0; + virtual void didEndEditing() = 0; + virtual void didChange() = 0; + virtual void didChangeSelection() = 0; + virtual bool shouldBeginEditingInDOMRange(WebCore::Range*) = 0; + virtual bool shouldEndEditingInDOMRange(WebCore::Range*) = 0; + virtual bool shouldDeleteDOMRange(WebCore::Range*) = 0; + virtual bool shouldChangeSelectedDOMRangeToDOMRangeAffinityStillSelecting(WebCore::Range* fromRange, WebCore::Range* toRange, int affinity, bool stillSelecting) = 0; + virtual bool shouldInsertNode(WebCore::Node*, WebCore::Range*, int insertAction) = 0; + virtual bool shouldInsertText(const WTF::String&, WebCore::Range*, int insertAction) = 0; + virtual bool isSelectTrailingWhitespaceEnabled() const = 0; + +}; +} +} + +#endif // DumpRenderTreeClient_h diff --git a/Tools/ChangeLog b/Tools/ChangeLog index b413b5a..7453672 100644 --- a/Tools/ChangeLog +++ b/Tools/ChangeLog @@ -1,3 +1,15 @@ +2012-02-08 Rob Buis + + [BlackBerry] Upstream DumpRenderTreeBlackBerry + https://bugs.webkit.org/show_bug.cgi?id=78042 + + Reviewed by Antonio Gomes. + + Add implementation for our DumpRenderTree solution. + + * DumpRenderTree/blackberry/DumpRenderTree.cpp: Added. + * DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h: Added. + 2012-02-08 Antti Koivisto REGRESSION (r106681): Null check missing in [WebFrame(WebInternal) _typingStyle] diff --git a/Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp b/Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp new file mode 100644 index 0000000..fb52cfd --- /dev/null +++ b/Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp @@ -0,0 +1,820 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "DumpRenderTree.h" + +#include "AccessibilityController.h" +#include "BackForwardController.h" +#include "BackForwardListImpl.h" +#include "CString.h" +#include "DatabaseTracker.h" +#include "DocumentLoader.h" +#include "DumpRenderTree/GCController.h" +#include "DumpRenderTreeSupport.h" +#include "EditingBehaviorTypes.h" +#include "EditorClientBlackBerry.h" +#include "EditorInsertAction.h" +#include "Element.h" +#include "EventSender.h" +#include "Frame.h" +#include "FrameLoaderTypes.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "HistoryItem.h" +#include "IntSize.h" +#include "LayoutTestController.h" +#include "NotImplemented.h" +#include "OwnArrayPtr.h" +#include "Page.h" +#include "PageGroup.h" +#include "PixelDumpSupport.h" +#include "PixelDumpSupportBlackBerry.h" +#include "Range.h" +#include "RenderTreeAsText.h" +#include "ScriptController.h" +#include "SecurityOrigin.h" +#include "Settings.h" +#include "TextAffinity.h" +#include "Timer.h" +#include "Vector.h" +#include "WebCoreTestSupport.h" +#include "WebPage.h" +#include "WebPageClient.h" +#include "WorkQueue.h" +#include "WorkQueueItem.h" +#include +#include +#include +#include +#include + +#define SDCARD_PATH "/developer" + +volatile bool testDone; + +RefPtr gLayoutTestController; + +WebCore::Frame* mainFrame = 0; +WebCore::Frame* topLoadingFrame = 0; +bool waitForPolicy = false; + +// FIXME: Assuming LayoutTests has been copied to /developer/LayoutTests/ +static const char* const kSDCLayoutTestsURI = "file:///developer/LayoutTests/"; +static const char* httpTestSyntax = "http/tests/"; +static const char* httpPrefixURL = "http://127.0.0.1:8000/"; + +using namespace std; + +static WTF::String drtAffinityDescription(WebCore::EAffinity affinity) +{ + if (affinity == WebCore::UPSTREAM) + return WTF::String("NSSelectionAffinityUpstream"); + if (affinity == WebCore::DOWNSTREAM) + return WTF::String("NSSelectionAffinityDownstream"); + return ""; +} + +static WTF::String drtDumpPath(WebCore::Node* node) +{ + WebCore::Node* parent = node->parentNode(); + WTF::String str = WTF::String::format("%s", node->nodeName().utf8().data()); + if (parent) { + str.append(" > "); + str.append(drtDumpPath(parent)); + } + return str; +} + +static WTF::String drtRangeDescription(WebCore::Range* range) +{ + if (!range) + return "(null)"; + return WTF::String::format("range from %d of %s to %d of %s", range->startOffset(), drtDumpPath(range->startContainer()).utf8().data(), range->endOffset(), drtDumpPath(range->endContainer()).utf8().data()); +} + +static WTF::String drtFrameDescription(WebCore::Frame* frame) +{ + WTF::String name = frame->tree()->uniqueName().string(); + if (frame == mainFrame) { + if (!name.isNull() && name.length()) + return WTF::String::format("main frame \"%s\"", name.utf8().data()); + return "main frame"; + } + if (!name.isNull()) + return WTF::String::format("frame \"%s\"", name.utf8().data()); + return "frame (anonymous)"; +} + +static bool shouldLogFrameLoadDelegates(const WTF::String& url) +{ + return url.contains("loading/"); +} + +namespace BlackBerry { +namespace WebKit { + +DumpRenderTree* DumpRenderTree::s_currentInstance = 0; +bool DumpRenderTree::s_selectTrailingWhitespaceEnabled = false; + +static void createFile(const WTF::String& fileName) +{ + FILE* fd = fopen(fileName.utf8().data(), "wb"); + fclose(fd); +} + +DumpRenderTree::DumpRenderTree(BlackBerry::WebKit::WebPage* page) + : m_gcController(0) + , m_accessibilityController(0) + , m_page(page) + , m_dumpPixels(false) + , m_waitToDumpWatchdogTimer(this, &DumpRenderTree::waitToDumpWatchdogTimerFired) + , m_workTimer(this, &DumpRenderTree::processWork) + , m_acceptsEditing(true) +{ + WTF::String sdcardPath = SDCARD_PATH; + m_resultsDir = sdcardPath + "/results/"; + m_indexFile = sdcardPath + "/index.drt"; + m_doneFile = sdcardPath + "/done"; + m_currentTestFile = sdcardPath + "/current.drt"; + m_page->resetVirtualViewportOnCommitted(false); + m_page->setVirtualViewportSize(800, 600); + s_currentInstance = this; +} + +DumpRenderTree::~DumpRenderTree() +{ + delete m_gcController; + delete m_accessibilityController; +} + +void DumpRenderTree::runTest(const WTF::String& url) +{ + createFile(m_resultsDir + *m_currentTest + ".dump.crash"); + + mainFrame->loader()->stopForUserCancel(); + resetToConsistentStateBeforeTesting(); + if (shouldLogFrameLoadDelegates(url)) + gLayoutTestController->setDumpFrameLoadCallbacks(true); + WTF::String stdoutFile = m_resultsDir + *m_currentTest + ".dump"; + WTF::String stderrFile = m_resultsDir + *m_currentTest + ".stderr"; + + // FIXME: we should preserve the original stdout and stderr here but aren't doing + // that yet due to issues with dup, etc. + freopen(stdoutFile.utf8().data(), "wb", stdout); + freopen(stderrFile.utf8().data(), "wb", stderr); + + FILE* current = fopen(m_currentTestFile.utf8().data(), "w"); + fwrite(m_currentTest->utf8().data(), 1, m_currentTest->utf8().length(), current); + fclose(current); + m_page->load(url.utf8().data(), 0, false); +} + +void DumpRenderTree::doneDrt() +{ + fclose(stdout); + fclose(stderr); + + // Notify the external world that we're done. + createFile(m_doneFile); + (m_page->client())->notifyRunLayoutTestsFinished(); +} + +void DumpRenderTree::runRemainingTests() +{ + // FIXME: fflush should not be necessary but is temporarily required due to a bug in stdio output. + fflush(stdout); + fflush(stderr); + + if (m_currentTest >= m_tests.end() - 1) { + doneDrt(); + return; + } + + m_currentTest++; + if (isHTTPTest(m_currentTest->utf8().data())) { + m_currentHttpTest = m_currentTest->utf8().data(); + m_currentHttpTest.remove(0, strlen(httpTestSyntax)); + runTest(httpPrefixURL + m_currentHttpTest); + } else + runTest(kSDCLayoutTestsURI + *m_currentTest); +} + +void DumpRenderTree::resetToConsistentStateBeforeTesting() +{ + if (isHTTPTest(m_currentTest->utf8().data())) + gLayoutTestController = LayoutTestController::create(String(httpPrefixURL + *m_currentTest).utf8().data(), ""); + else + gLayoutTestController = LayoutTestController::create(String(kSDCLayoutTestsURI + *m_currentTest).utf8().data(), ""); + + gLayoutTestController->setIconDatabaseEnabled(false); + + DumpRenderTreeSupport::resetGeolocationMock(m_page); + + topLoadingFrame = 0; + m_loadFinished = false; + s_selectTrailingWhitespaceEnabled = false; + + testDone = false; + WorkQueue::shared()->clear(); + WorkQueue::shared()->setFrozen(false); + + WebSettings* settings = m_page->settings(); + + settings->setTextReflowMode(WebSettings::TextReflowDisabled); + settings->setJavaScriptEnabled(true); + settings->setLoadsImagesAutomatically(true); + settings->setJavaScriptOpenWindowsAutomatically(true); + settings->setZoomToFitOnLoad(false); + settings->setDefaultFontSize(16); + settings->setDefaultFixedFontSize(13); + settings->setMinimumFontSize(1); + settings->setSerifFontFamily("Times"); + settings->setFixedFontFamily("Courier New"); + settings->setSansSerifFontFamily("Arial"); + settings->setStandardFontFamily("Times"); + settings->setXSSAuditorEnabled(false); + settings->setFrameFlatteningEnabled(false); + settings->setMaximumPagesInCache(0); + settings->setPluginsEnabled(true); + settings->setUserScalable(true); + // Apply new settings to current page, see more in the destructor of WebSettingsTransaction. + WebSettingsTransaction webSettingTransaction(settings); + + BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->clearBackForwardList(false); + + setAcceptsEditing(true); + DumpRenderTreeSupport::setLinksIncludedInFocusChain(true); + + m_page->setVirtualViewportSize(800, 600); + m_page->resetVirtualViewportOnCommitted(false); + m_page->setJavaScriptCanAccessClipboard(true); + + mainFrame = m_page->mainFrame(); + if (mainFrame) { + mainFrame->page()->setTabKeyCyclesThroughElements(true); + mainFrame->page()->settings()->setEditingBehaviorType(WebCore::EditingUnixBehavior); + mainFrame->page()->settings()->setDOMPasteAllowed(true); + mainFrame->page()->settings()->setValidationMessageTimerMagnification(-1); + mainFrame->page()->settings()->setInteractiveFormValidationEnabled(true); + mainFrame->page()->settings()->setAllowFileAccessFromFileURLs(true); + mainFrame->page()->settings()->setAllowUniversalAccessFromFileURLs(true); + mainFrame->page()->settings()->setAuthorAndUserStylesEnabled(true); + mainFrame->page()->settings()->setUsePreHTML5ParserQuirks(false); + mainFrame->tree()->clearName(); + mainFrame->loader()->setOpener(0); + // FIXME: Other ports also clear history/backForwardList allong with visited links. + mainFrame->page()->group().removeVisitedLinks(); + } + + // For now we manually garbage collect between each test to make sure the device won't run out of memory due to lazy collection. + DumpRenderTreeSupport::garbageCollectorCollect(); +} + +void DumpRenderTree::runTests() +{ + m_gcController = new GCController(); + m_accessibilityController = new AccessibilityController(); + getTestsToRun(); + + mainFrame = m_page->mainFrame(); + + m_currentTest = m_tests.begin(); + + if (m_currentTest == m_tests.end()) { + doneDrt(); + return; + } + + if (isHTTPTest(m_currentTest->utf8().data())) { + m_currentHttpTest = m_currentTest->utf8().data(); + m_currentHttpTest.remove(0, strlen(httpTestSyntax)); + runTest(httpPrefixURL + m_currentHttpTest); + } else + runTest(kSDCLayoutTestsURI + *m_currentTest); +} + + +WTF::String DumpRenderTree::dumpFramesAsText(WebCore::Frame* frame) +{ + WTF::String s; + WebCore::Element* documentElement = frame->document()->documentElement(); + if (!documentElement) + return s.utf8().data(); + + if (frame->tree()->parent()) + s = WTF::String::format("\n--------\nFrame: '%s'\n--------\n", frame->tree()->uniqueName().string().utf8().data()); + + s += documentElement->innerText() + "\n"; + + if (gLayoutTestController->dumpChildFramesAsText()) { + WebCore::FrameTree* tree = frame->tree(); + for (WebCore::Frame* child = tree->firstChild(); child; child = child->tree()->nextSibling()) + s += dumpFramesAsText(child); + } + return s; +} + +static void dumpToFile(const WTF::String& data) +{ + fwrite(data.utf8().data(), 1, data.utf8().length(), stdout); +} + +bool DumpRenderTree::isHTTPTest(const WTF::String& test) +{ + if (test.length() < strlen(httpTestSyntax)) + return false; + return test.lower().substring(0, strlen(httpTestSyntax)) == httpTestSyntax; +} + +void DumpRenderTree::getTestsToRun() +{ + Vector files; + + FILE* fd = fopen(m_indexFile.utf8().data(), "r"); + fseek(fd, 0, SEEK_END); + int size = ftell(fd); + fseek(fd, 0, SEEK_SET); + OwnArrayPtr buf = adoptArrayPtr(new char[size]); + fread(buf.get(), 1, size, fd); + fclose(fd); + WTF::String s(buf.get(), size); + s.split("\n", files); + + m_tests = files; +} + +void DumpRenderTree::invalidateAnyPreviousWaitToDumpWatchdog() +{ + m_waitToDumpWatchdogTimer.stop(); + waitForPolicy = false; +} + +WTF::String DumpRenderTree::renderTreeDump() const +{ + if (mainFrame) { + if (mainFrame->view() && mainFrame->view()->layoutPending()) + mainFrame->view()->layout(); + + return externalRepresentation(mainFrame); + } + return ""; +} + +static bool historyItemCompare(const RefPtr& a, const RefPtr& b) +{ + return codePointCompare(a->urlString(), b->urlString()) < 0; +} + +static WTF::String dumpHistoryItem(PassRefPtr item, int indent, bool current) +{ + WTF::String result; + + int start = 0; + if (current) { + result += "curr->"; + start = 6; + } + for (int i = start; i < indent; i++) + result += " "; + + WTF::String url = item->urlString(); + if (url.contains("file://")) { + static WTF::String layoutTestsString("/LayoutTests/"); + static WTF::String fileTestString("(file test):"); + + WTF::String res = url.substring(url.find(layoutTestsString) + layoutTestsString.length()); + if (res.isEmpty()) + return result; + + result += fileTestString; + result += res; + } else + result += url; + + WTF::String target = item->target(); + if (!target.isEmpty()) + result += " (in frame \"" + target + "\")"; + + if (item->isTargetItem()) + result += " **nav target**"; + result += "\n"; + + WebCore::HistoryItemVector children = item->children(); + // Must sort to eliminate arbitrary result ordering which defeats reproducible testing. + nonCopyingSort(children.begin(), children.end(), historyItemCompare); + unsigned resultSize = children.size(); + for (unsigned i = 0; i < resultSize; ++i) + result += dumpHistoryItem(children[i], indent + 4, false); + + return result; +} + +static WTF::String dumpBackForwardListForWebView() +{ + WTF::String result = "\n============== Back Forward List ==============\n"; + // FORMAT: + // " (file test):fast/loader/resources/click-fragment-link.html **nav target**" + // "curr-> (file test):fast/loader/resources/click-fragment-link.html#testfragment **nav target**" + WebCore::BackForwardListImpl* bfList = static_cast(mainFrame->page()->backForward()->client()); + int maxItems = bfList->capacity(); + WebCore::HistoryItemVector entries; + bfList->backListWithLimit(maxItems, entries); + unsigned resultSize = entries.size(); + for (unsigned i = 0; i < resultSize; ++i) + result += dumpHistoryItem(entries[i], 8, false); + + result += dumpHistoryItem(bfList->currentItem(), 8, true); + + bfList->forwardListWithLimit(maxItems, entries); + resultSize = entries.size(); + for (unsigned i = 0; i < resultSize; ++i) + result += dumpHistoryItem(entries[i], 8, false); + + result += "===============================================\n"; + + return result; +} + +void DumpRenderTree::dump() +{ + invalidateAnyPreviousWaitToDumpWatchdog(); + + WTF::String dumpFile = m_resultsDir + *m_currentTest + ".dump"; + + WTF::String resultMimeType = "text/plain"; + WTF::String responseMimeType = mainFrame->loader()->documentLoader()->responseMIMEType(); + + bool dumpAsText = gLayoutTestController->dumpAsText() || responseMimeType == "text/plain"; + WTF::String data = dumpAsText ? dumpFramesAsText(mainFrame) : renderTreeDump(); + + if (gLayoutTestController->dumpBackForwardList()) + data += dumpBackForwardListForWebView(); + + WTF::String result = "Content-Type: " + resultMimeType + "\n" + data; + + dumpToFile(result); + if (m_dumpPixels && !dumpAsText && gLayoutTestController->generatePixelResults()) + dumpWebViewAsPixelsAndCompareWithExpected(gLayoutTestController->expectedPixelHash()); + + WTF::String crashFile = dumpFile + ".crash"; + unlink(crashFile.utf8().data()); + + testDone = true; + runRemainingTests(); +} + +void DumpRenderTree::setWaitToDumpWatchdog(double interval) +{ + invalidateAnyPreviousWaitToDumpWatchdog(); + m_waitToDumpWatchdogTimer.startOneShot(interval); +} + +void DumpRenderTree::waitToDumpWatchdogTimerFired(WebCore::Timer*) +{ + gLayoutTestController->waitToDumpWatchdogTimerFired(); +} + +void DumpRenderTree::processWork(WebCore::Timer*) +{ + if (topLoadingFrame) + return; + + if (WorkQueue::shared()->processWork() && !gLayoutTestController->waitToDump()) + dump(); +} + +void DumpRenderTree::locationChangeForFrame(WebCore::Frame* frame) +{ + if (frame != topLoadingFrame) + return; + + topLoadingFrame = 0; + WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue + if (gLayoutTestController->waitToDump()) + return; + + if (WorkQueue::shared()->count()) + m_workTimer.startOneShot(0); + else + dump(); +} + +// FrameLoadClient delegates. +void DumpRenderTree::didStartProvisionalLoadForFrame(WebCore::Frame* frame) +{ + if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didStartProvisionalLoadForFrame\n", drtFrameDescription(frame).utf8().data()); + + if (!testDone && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks()) + printf("Frame with user gesture \"%s\" - in didStartProvisionalLoadForFrame\n", WebCore::ScriptController::processingUserGesture() ? "true" : "false"); + + if (!topLoadingFrame && !testDone) + topLoadingFrame = frame; + + if (!testDone && gLayoutTestController->stopProvisionalFrameLoads()) { + printf("%s - stopping load in didStartProvisionalLoadForFrame callback\n", drtFrameDescription(frame).utf8().data()); + frame->loader()->stopForUserCancel(); + } +} + +void DumpRenderTree::didCommitLoadForFrame(WebCore::Frame* frame) +{ + if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didCommitLoadForFrame\n", drtFrameDescription(frame).utf8().data()); + + gLayoutTestController->setWindowIsKey(true); +} + +void DumpRenderTree::didFailProvisionalLoadForFrame(WebCore::Frame* frame) +{ + if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didFailProvisionalLoadWithError\n", drtFrameDescription(frame).utf8().data()); + + locationChangeForFrame(frame); +} + +void DumpRenderTree::didFailLoadForFrame(WebCore::Frame* frame) +{ + if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didFailLoadWithError\n", drtFrameDescription(frame).utf8().data()); + + locationChangeForFrame(frame); +} + +void DumpRenderTree::didFinishLoadForFrame(WebCore::Frame* frame) +{ + if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didFinishLoadForFrame\n", drtFrameDescription(frame).utf8().data()); + + if (frame == topLoadingFrame) + m_loadFinished = true; + locationChangeForFrame(frame); +} + +void DumpRenderTree::didFinishDocumentLoadForFrame(WebCore::Frame* frame) +{ + if (!testDone) { + if (gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didFinishDocumentLoadForFrame\n", drtFrameDescription(frame).utf8().data()); + else { + unsigned pendingFrameUnloadEvents = frame->domWindow()->pendingUnloadEventListeners(); + if (pendingFrameUnloadEvents) + printf("%s - has %u onunload handler(s)\n", drtFrameDescription(frame).utf8().data(), pendingFrameUnloadEvents); + } + } +} + +void DumpRenderTree::didClearWindowObjectInWorld(WebCore::DOMWrapperWorld*, JSGlobalContextRef context, JSObjectRef windowObject) +{ + JSValueRef exception = 0; + + gLayoutTestController->makeWindowObject(context, windowObject, &exception); + ASSERT(!exception); + + m_gcController->makeWindowObject(context, windowObject, &exception); + ASSERT(!exception); + + m_accessibilityController->makeWindowObject(context, windowObject, &exception); + ASSERT(!exception); + + JSStringRef eventSenderStr = JSStringCreateWithUTF8CString("eventSender"); + JSValueRef eventSender = makeEventSender(context); + JSObjectSetProperty(context, windowObject, eventSenderStr, eventSender, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0); + JSStringRelease(eventSenderStr); + WebCoreTestSupport::injectInternalsObject(context); +} + +void DumpRenderTree::didReceiveTitleForFrame(const WTF::String& title, WebCore::Frame* frame) +{ + if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didReceiveTitle: %s\n", drtFrameDescription(frame).utf8().data(), title.utf8().data()); + + if (gLayoutTestController->dumpTitleChanges()) + printf("TITLE CHANGED: %s\n", title.utf8().data()); +} + +// ChromeClient delegates. +void DumpRenderTree::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID) +{ + printf("CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.utf8().data()); +} + +void DumpRenderTree::runJavaScriptAlert(const WTF::String& message) +{ + if (!testDone) + printf("ALERT: %s\n", message.utf8().data()); +} + +bool DumpRenderTree::runJavaScriptConfirm(const WTF::String& message) +{ + if (!testDone) + printf("CONFIRM: %s\n", message.utf8().data()); + return true; +} + +WTF::String DumpRenderTree::runJavaScriptPrompt(const WTF::String& message, const WTF::String& defaultValue) +{ + if (!testDone) + printf("PROMPT: %s, default text: %s\n", message.utf8().data(), defaultValue.utf8().data()); + return defaultValue; +} + +bool DumpRenderTree::runBeforeUnloadConfirmPanel(const WTF::String& message) +{ + if (!testDone) + printf("CONFIRM NAVIGATION: %s\n", message.utf8().data()); + return true; +} + +void DumpRenderTree::setStatusText(const WTF::String& status) +{ + if (gLayoutTestController->dumpStatusCallbacks()) + printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", status.utf8().data()); +} + +void DumpRenderTree::exceededDatabaseQuota(WebCore::SecurityOrigin* origin, const WTF::String& name) +{ + if (!testDone && gLayoutTestController->dumpDatabaseCallbacks()) + printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n", origin->protocol().utf8().data(), origin->host().utf8().data(), origin->port(), name.utf8().data()); + + WebCore::DatabaseTracker::tracker().setQuota(mainFrame->document()->securityOrigin(), 5 * 1024 * 1024); +} + +bool DumpRenderTree::allowsOpeningWindow() +{ + return gLayoutTestController->canOpenWindows(); +} + +void DumpRenderTree::windowCreated(BlackBerry::WebKit::WebPage* page) +{ + page->settings()->setJavaScriptOpenWindowsAutomatically(true); +} + +// EditorClient delegates. +void DumpRenderTree::didBeginEditing() +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidBeginEditing:%s\n", "WebViewDidBeginEditingNotification"); +} + +void DumpRenderTree::didEndEditing() +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidEndEditing:%s\n", "WebViewDidEndEditingNotification"); +} + +void DumpRenderTree::didChange() +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidChange:%s\n", "WebViewDidChangeNotification"); +} + +void DumpRenderTree::didChangeSelection() +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: webViewDidChangeSelection:%s\n", "WebViewDidChangeSelectionNotification"); +} + +bool DumpRenderTree::findString(const WTF::String& string, WebCore::FindOptions options) +{ + WebCore::Page* page = mainFrame ? mainFrame->page() : 0; + return page && page->findString(string, options); +} + +bool DumpRenderTree::shouldBeginEditingInDOMRange(WebCore::Range* range) +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", drtRangeDescription(range).utf8().data()); + return m_acceptsEditing; +} + +bool DumpRenderTree::shouldEndEditingInDOMRange(WebCore::Range* range) +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", drtRangeDescription(range).utf8().data()); + return m_acceptsEditing; +} + +bool DumpRenderTree::shouldDeleteDOMRange(WebCore::Range* range) +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", drtRangeDescription(range).utf8().data()); + return m_acceptsEditing; +} + +bool DumpRenderTree::shouldChangeSelectedDOMRangeToDOMRangeAffinityStillSelecting(WebCore::Range* fromRange, WebCore::Range* toRange, int affinity, bool stillSelecting) +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n", drtRangeDescription(fromRange).utf8().data(), drtRangeDescription(toRange).utf8().data(), drtAffinityDescription(static_cast(affinity)).utf8().data(), stillSelecting ? "TRUE" : "FALSE"); + return m_acceptsEditing; +} + +static const char* insertActionString(WebCore::EditorInsertAction action) +{ + switch (action) { + case WebCore::EditorInsertActionTyped: + return "WebViewInsertActionTyped"; + case WebCore::EditorInsertActionPasted: + return "WebViewInsertActionPasted"; + case WebCore::EditorInsertActionDropped: + return "WebViewInsertActionDropped"; + } + ASSERT_NOT_REACHED(); + return "WebViewInsertActionTyped"; +} + +bool DumpRenderTree::shouldInsertNode(WebCore::Node* node, WebCore::Range* range, int action) +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n", drtDumpPath(node).utf8().data(), drtRangeDescription(range).utf8().data(), insertActionString((WebCore::EditorInsertAction)action)); + return m_acceptsEditing; +} + +bool DumpRenderTree::shouldInsertText(const WTF::String& text, WebCore::Range* range, int action) +{ + if (!testDone && gLayoutTestController->dumpEditingCallbacks()) + printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n", text.utf8().data(), drtRangeDescription(range).utf8().data(), insertActionString((WebCore::EditorInsertAction)action)); + return m_acceptsEditing; +} + +void DumpRenderTree::didDecidePolicyForNavigationAction(const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request) +{ + if (!waitForPolicy) + return; + + const char* typeDescription; + switch (action.type()) { + case WebCore::NavigationTypeLinkClicked: + typeDescription = "link clicked"; + break; + case WebCore::NavigationTypeFormSubmitted: + typeDescription = "form submitted"; + break; + case WebCore::NavigationTypeBackForward: + typeDescription = "back/forward"; + break; + case WebCore::NavigationTypeReload: + typeDescription = "reload"; + break; + case WebCore::NavigationTypeFormResubmitted: + typeDescription = "form resubmitted"; + break; + case WebCore::NavigationTypeOther: + typeDescription = "other"; + break; + default: + typeDescription = "illegal value"; + } + + printf("Policy delegate: attempt to load %s with navigation type '%s'\n", request.url().string().utf8().data(), typeDescription); + // FIXME: do originating part. + + gLayoutTestController->notifyDone(); +} + +void DumpRenderTree::didDispatchWillPerformClientRedirect() +{ + if (!testDone && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks()) + printf("Frame with user gesture \"%s\" - in willPerformClientRedirect\n", WebCore::ScriptController::processingUserGesture() ? "true" : "false"); +} + +void DumpRenderTree::didHandleOnloadEventsForFrame(WebCore::Frame* frame) +{ + if (!testDone && gLayoutTestController->dumpFrameLoadCallbacks()) + printf("%s - didHandleOnloadEventsForFrame\n", drtFrameDescription(frame).utf8().data()); +} + +void DumpRenderTree::didReceiveResponseForFrame(WebCore::Frame* frame, const WebCore::ResourceResponse& response) +{ + if (!testDone && gLayoutTestController->dumpResourceResponseMIMETypes()) + printf("%s has MIME type %s\n", response.url().lastPathComponent().utf8().data(), response.mimeType().utf8().data()); +} + +} +} + +// Static dump() function required by cross-platform DRT code. +void dump() +{ + BlackBerry::WebKit::DumpRenderTree* dumper = BlackBerry::WebKit::DumpRenderTree::currentInstance(); + if (!dumper) + return; + + dumper->dump(); +} diff --git a/Tools/DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h b/Tools/DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h new file mode 100644 index 0000000..db2f69a --- /dev/null +++ b/Tools/DumpRenderTree/blackberry/DumpRenderTreeBlackBerry.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DumpRenderTreeBlackBerry_h +#define DumpRenderTreeBlackBerry_h + +#include "BlackBerryGlobal.h" + +#include "DumpRenderTreeClient.h" +#include "PlatformString.h" +#include "Timer.h" +#include +#include + +namespace WebCore { +class Frame; +class DOMWrapperWorld; +class Range; +} + +extern WebCore::Frame* mainFrame; +extern WebCore::Frame* topLoadingFrame; +extern bool waitForPolicy; + +class AccessibilityController; +class GCController; + +namespace BlackBerry { +namespace WebKit { +class WebPage; + +class DumpRenderTree : public BlackBerry::WebKit::DumpRenderTreeClient { +public: + DumpRenderTree(WebPage*); + virtual ~DumpRenderTree(); + + static DumpRenderTree* currentInstance() { return s_currentInstance; } + + void dump(); + + void setWaitToDumpWatchdog(double interval); + + WebPage* page() { return m_page; } + + bool loadFinished() const { return m_loadFinished; } + + // FrameLoaderClient delegates + void didStartProvisionalLoadForFrame(WebCore::Frame*); + void didCommitLoadForFrame(WebCore::Frame*); + void didFailProvisionalLoadForFrame(WebCore::Frame*); + void didFailLoadForFrame(WebCore::Frame*); + void didFinishLoadForFrame(WebCore::Frame*); + void didFinishDocumentLoadForFrame(WebCore::Frame*); + void didClearWindowObjectInWorld(WebCore::DOMWrapperWorld*, JSGlobalContextRef, JSObjectRef windowObject); + void didReceiveTitleForFrame(const WTF::String& title, WebCore::Frame*); + void didDecidePolicyForNavigationAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&); + void didDispatchWillPerformClientRedirect(); + void didHandleOnloadEventsForFrame(WebCore::Frame*); + void didReceiveResponseForFrame(WebCore::Frame*, const WebCore::ResourceResponse&); + + // ChromeClient delegates + void addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID); + void runJavaScriptAlert(const WTF::String& message); + bool runJavaScriptConfirm(const WTF::String& message); + WTF::String runJavaScriptPrompt(const WTF::String& message, const WTF::String& defaultValue); + bool runBeforeUnloadConfirmPanel(const WTF::String& message); + void setStatusText(const WTF::String&); + void exceededDatabaseQuota(WebCore::SecurityOrigin*, const WTF::String& name); + bool allowsOpeningWindow(); + void windowCreated(WebPage*); + + // EditorClient delegates + void setAcceptsEditing(bool acceptsEditing) { m_acceptsEditing = acceptsEditing; } + + void didBeginEditing(); + void didEndEditing(); + void didChange(); + void didChangeSelection(); + bool findString(const WTF::String&, WebCore::FindOptions); + bool shouldBeginEditingInDOMRange(WebCore::Range*); + bool shouldEndEditingInDOMRange(WebCore::Range*); + bool shouldDeleteDOMRange(WebCore::Range*); + bool shouldChangeSelectedDOMRangeToDOMRangeAffinityStillSelecting(WebCore::Range* fromRange, WebCore::Range* toRange, int affinity, bool stillSelecting); + bool shouldInsertNode(WebCore::Node*, WebCore::Range*, int insertAction); + bool shouldInsertText(const WTF::String&, WebCore::Range*, int insertAction); + + bool isSelectTrailingWhitespaceEnabled() const { return s_selectTrailingWhitespaceEnabled; } + void setSelectTrailingWhitespaceEnabled(bool enabled) { s_selectTrailingWhitespaceEnabled = enabled; } + +private: + void runTest(const WTF::String& url); + void runTests(); + + void processWork(WebCore::Timer*); + +private: + static DumpRenderTree* s_currentInstance; + + WTF::String dumpFramesAsText(WebCore::Frame*); + void locationChangeForFrame(WebCore::Frame*); + + void doneDrt(); + void getTestsToRun(); + bool isHTTPTest(const WTF::String& test); + WTF::String renderTreeDump() const; + void resetToConsistentStateBeforeTesting(); + void runRemainingTests(); + void invalidateAnyPreviousWaitToDumpWatchdog(); + void waitToDumpWatchdogTimerFired(WebCore::Timer*); + + Vector m_tests; + Vector::iterator m_currentTest; + + WTF::String m_resultsDir; + WTF::String m_indexFile; + WTF::String m_doneFile; + WTF::String m_currentHttpTest; + WTF::String m_currentTestFile; + + GCController* m_gcController; + AccessibilityController* m_accessibilityController; + WebPage* m_page; + bool m_dumpPixels; + WebCore::Timer m_waitToDumpWatchdogTimer; + WebCore::Timer m_workTimer; + + bool m_acceptsEditing; + bool m_loadFinished; + static bool s_selectTrailingWhitespaceEnabled; +}; +} +} + +#endif // DumpRenderTreeBlackBerry_h