~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Tools/DumpRenderTree/blackberry/DumpRenderTree.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 */
 
18
 
 
19
#include "config.h"
 
20
#include "DumpRenderTree.h"
 
21
 
 
22
#include "APICast.h"
 
23
#include "AccessibilityController.h"
 
24
#include "BackForwardController.h"
 
25
#include "BackForwardListImpl.h"
 
26
#include "Credential.h"
 
27
#include "DatabaseTracker.h"
 
28
#include "DocumentLoader.h"
 
29
#include "DumpRenderTree/GCController.h"
 
30
#include "DumpRenderTreeSupport.h"
 
31
#include "EditingBehaviorTypes.h"
 
32
#include "EditorClientBlackBerry.h"
 
33
#include "EditorInsertAction.h"
 
34
#include "Element.h"
 
35
#include "EventSender.h"
 
36
#include "Frame.h"
 
37
#include "FrameLoaderTypes.h"
 
38
#include "FrameTree.h"
 
39
#include "FrameView.h"
 
40
#include "HistoryItem.h"
 
41
#include "IntSize.h"
 
42
#include "JSDOMBinding.h"
 
43
#include "NotImplemented.h"
 
44
#include "Page.h"
 
45
#include "PageGroup.h"
 
46
#include "PixelDumpSupport.h"
 
47
#include "PixelDumpSupportBlackBerry.h"
 
48
#include "Range.h"
 
49
#include "RenderTreeAsText.h"
 
50
#include "ScriptController.h"
 
51
#include "SecurityOrigin.h"
 
52
#include "Settings.h"
 
53
#include "TestRunner.h"
 
54
#include "TextAffinity.h"
 
55
#include "Timer.h"
 
56
#include "WebCoreTestSupport.h"
 
57
#include "WebPage.h"
 
58
#include "WebPageClient.h"
 
59
#include "WorkQueue.h"
 
60
#include "WorkQueueItem.h"
 
61
#include <BlackBerryPlatformLayoutTest.h>
 
62
#include <BlackBerryPlatformPrimitives.h>
 
63
#include <WebSettings.h>
 
64
#include <stdio.h>
 
65
#include <sys/stat.h>
 
66
#include <unistd.h>
 
67
#include <wtf/NonCopyingSort.h>
 
68
#include <wtf/OwnArrayPtr.h>
 
69
#include <wtf/Vector.h>
 
70
 
 
71
#define SDCARD_PATH "/developer"
 
72
 
 
73
volatile bool testDone;
 
74
 
 
75
RefPtr<TestRunner> gTestRunner;
 
76
 
 
77
WebCore::Frame* mainFrame = 0;
 
78
WebCore::Frame* topLoadingFrame = 0;
 
79
bool waitForPolicy = false;
 
80
bool runFromCommandLine = false;
 
81
 
 
82
// FIXME: Assuming LayoutTests has been copied to /developer/LayoutTests/
 
83
static const char* const kSDCLayoutTestsURI = "file:///developer/LayoutTests/";
 
84
static const char* httpTestSyntax = "http/tests/";
 
85
static const char* localTestSyntax = "local/";
 
86
static const char* httpPrefixURL = "http://127.0.0.1:8000/";
 
87
 
 
88
using namespace std;
 
89
 
 
90
static String drtAffinityDescription(WebCore::EAffinity affinity)
 
91
{
 
92
    if (affinity == WebCore::UPSTREAM)
 
93
        return String("NSSelectionAffinityUpstream");
 
94
    if (affinity == WebCore::DOWNSTREAM)
 
95
        return String("NSSelectionAffinityDownstream");
 
96
    return "";
 
97
}
 
98
 
 
99
static String drtDumpPath(WebCore::Node* node)
 
100
{
 
101
    WebCore::Node* parent = node->parentNode();
 
102
    String str = String::format("%s", node->nodeName().utf8().data());
 
103
    if (parent) {
 
104
        str.append(" > ");
 
105
        str.append(drtDumpPath(parent));
 
106
    }
 
107
    return str;
 
108
}
 
109
 
 
110
static String drtRangeDescription(WebCore::Range* range)
 
111
{
 
112
    if (!range)
 
113
        return "(null)";
 
114
    return 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());
 
115
}
 
116
 
 
117
static String drtFrameDescription(WebCore::Frame* frame)
 
118
{
 
119
    String name = frame->tree()->uniqueName().string();
 
120
    if (frame == mainFrame) {
 
121
        if (!name.isNull() && name.length())
 
122
            return String::format("main frame \"%s\"", name.utf8().data());
 
123
        return "main frame";
 
124
    }
 
125
    if (!name.isNull())
 
126
        return String::format("frame \"%s\"", name.utf8().data());
 
127
    return "frame (anonymous)";
 
128
}
 
129
 
 
130
static WTF::String drtCredentialDescription(WebCore::Credential&)
 
131
{
 
132
    // TODO: Implementation needed.
 
133
    return "<unknown>";
 
134
}
 
135
 
 
136
static bool shouldLogFrameLoadDelegates(const String& url)
 
137
{
 
138
    return url.contains("loading/");
 
139
}
 
140
 
 
141
namespace BlackBerry {
 
142
namespace WebKit {
 
143
 
 
144
DumpRenderTree* DumpRenderTree::s_currentInstance = 0;
 
145
bool DumpRenderTree::s_selectTrailingWhitespaceEnabled = false;
 
146
 
 
147
static void createFile(const String& fileName)
 
148
{
 
149
    FILE* fd = fopen(fileName.utf8().data(), "wb");
 
150
    fclose(fd);
 
151
}
 
152
 
 
153
DumpRenderTree::DumpRenderTree(BlackBerry::WebKit::WebPage* page)
 
154
    : m_gcController(0)
 
155
    , m_accessibilityController(0)
 
156
    , m_page(page)
 
157
    , m_enablePixelTests(getenv("pixelTests"))
 
158
    , m_waitToDumpWatchdogTimer(this, &DumpRenderTree::waitToDumpWatchdogTimerFired)
 
159
    , m_workTimer(this, &DumpRenderTree::processWork)
 
160
    , m_acceptsEditing(true)
 
161
{
 
162
    const char* workerNumber = getenv("WORKER_NUMBER") ? getenv("WORKER_NUMBER") : "0";
 
163
    String sdcardPath = SDCARD_PATH;
 
164
    m_resultsDir = sdcardPath + "/results/";
 
165
    m_doneFile = sdcardPath + "/done" + workerNumber;
 
166
    m_currentTestFile = sdcardPath + "/current" + workerNumber + ".drt";
 
167
    m_page->resetVirtualViewportOnCommitted(false);
 
168
    m_page->setVirtualViewportSize(Platform::IntSize(800, 600));
 
169
    s_currentInstance = this;
 
170
}
 
171
 
 
172
DumpRenderTree::~DumpRenderTree()
 
173
{
 
174
    delete m_gcController;
 
175
    delete m_accessibilityController;
 
176
}
 
177
 
 
178
void DumpRenderTree::runTest(const String& url, const String& imageHash)
 
179
{
 
180
    mainFrame->loader()->stopForUserCancel();
 
181
    resetToConsistentStateBeforeTesting(url, imageHash);
 
182
    if (shouldLogFrameLoadDelegates(url))
 
183
        gTestRunner->setDumpFrameLoadCallbacks(true);
 
184
    if (!runFromCommandLine) {
 
185
        createFile(m_resultsDir + *m_currentTest + ".dump.crash");
 
186
 
 
187
        String stdoutFile = m_resultsDir + *m_currentTest + ".dump";
 
188
        String stderrFile = m_resultsDir + *m_currentTest + ".stderr";
 
189
 
 
190
        // FIXME: we should preserve the original stdout and stderr here but aren't doing
 
191
        // that yet due to issues with dup, etc.
 
192
        freopen(stdoutFile.utf8().data(), "wb", stdout);
 
193
        freopen(stderrFile.utf8().data(), "wb", stderr);
 
194
    }
 
195
    FILE* current = fopen(m_currentTestFile.utf8().data(), "w");
 
196
    fwrite(m_currentTest->utf8().data(), 1, m_currentTest->utf8().length(), current);
 
197
    fclose(current);
 
198
    m_page->load(url, BlackBerry::Platform::String::emptyString(), false);
 
199
}
 
200
 
 
201
void DumpRenderTree::doneDrt()
 
202
{
 
203
    fclose(stdout);
 
204
    fclose(stderr);
 
205
    unlink(getPPSPath().c_str());
 
206
 
 
207
    // Notify the external world that we're done.
 
208
    createFile(m_doneFile);
 
209
    (m_page->client())->notifyRunLayoutTestsFinished();
 
210
}
 
211
 
 
212
void DumpRenderTree::runCurrentTest()
 
213
{
 
214
    String imageHash = "";
 
215
    int posSplitter = m_currentTest->find('?');
 
216
    if (posSplitter > 1 && (unsigned)posSplitter < m_currentTest->length() - 1) {
 
217
        imageHash = m_currentTest->substring(posSplitter + 1);
 
218
        m_currentTest->truncate(posSplitter);
 
219
    }
 
220
    if (isHTTPTest(m_currentTest->utf8().data())) {
 
221
        m_currentHttpTest = m_currentTest->utf8().data();
 
222
        m_currentHttpTest.remove(0, strlen(httpTestSyntax));
 
223
        runTest(httpPrefixURL + m_currentHttpTest, imageHash);
 
224
    } else
 
225
        runTest(kSDCLayoutTestsURI + *m_currentTest, imageHash);
 
226
}
 
227
 
 
228
void DumpRenderTree::runRemainingTests()
 
229
{
 
230
    if (runFromCommandLine) {
 
231
        doneDrt();
 
232
        return;
 
233
    }
 
234
 
 
235
    // FIXME: fflush should not be necessary but is temporarily required due to a bug in stdio output.
 
236
    fflush(stdout);
 
237
    fflush(stderr);
 
238
 
 
239
    if (m_currentTest >= m_tests.end() - 1) {
 
240
        m_tests.clear();
 
241
        if (m_bufferedTests.size() > 0) {
 
242
            m_tests.append(m_bufferedTests);
 
243
            m_bufferedTests.clear();
 
244
            m_currentTest = m_tests.begin();
 
245
            runCurrentTest();
 
246
        }
 
247
        return;
 
248
    }
 
249
 
 
250
    m_currentTest++;
 
251
    runCurrentTest();
 
252
}
 
253
 
 
254
void DumpRenderTree::resetToConsistentStateBeforeTesting(const String& url, const String& imageHash)
 
255
{
 
256
    gTestRunner = TestRunner::create(url.utf8().data(), imageHash.utf8().data());
 
257
 
 
258
    gTestRunner->setIconDatabaseEnabled(false);
 
259
 
 
260
    DumpRenderTreeSupport::resetGeolocationMock(m_page);
 
261
 
 
262
    topLoadingFrame = 0;
 
263
    m_loadFinished = false;
 
264
    s_selectTrailingWhitespaceEnabled = false;
 
265
 
 
266
    testDone = false;
 
267
    WorkQueue::shared()->clear();
 
268
    WorkQueue::shared()->setFrozen(false);
 
269
 
 
270
    WebSettings* settings = m_page->settings();
 
271
 
 
272
    settings->setTextReflowMode(WebSettings::TextReflowDisabled);
 
273
    settings->setJavaScriptEnabled(true);
 
274
    settings->setLoadsImagesAutomatically(true);
 
275
    settings->setJavaScriptOpenWindowsAutomatically(true);
 
276
    settings->setZoomToFitOnLoad(false);
 
277
    settings->setDefaultFontSize(16);
 
278
    settings->setDefaultFixedFontSize(13);
 
279
    settings->setMinimumFontSize(1);
 
280
    settings->setSerifFontFamily("Times");
 
281
    settings->setFixedFontFamily("Courier New");
 
282
    settings->setSansSerifFontFamily("Arial");
 
283
    settings->setStandardFontFamily("Times");
 
284
    settings->setXSSAuditorEnabled(false);
 
285
    settings->setFrameFlatteningEnabled(false);
 
286
    settings->setMaximumPagesInCache(0);
 
287
    settings->setPluginsEnabled(true);
 
288
    // Apply new settings to current page, see more in the destructor of WebSettingsTransaction.
 
289
    WebSettingsTransaction webSettingTransaction(settings);
 
290
 
 
291
    BlackBerry::WebKit::DumpRenderTree::currentInstance()->page()->clearBackForwardList(false);
 
292
 
 
293
    setAcceptsEditing(true);
 
294
    DumpRenderTreeSupport::setLinksIncludedInFocusChain(true);
 
295
 
 
296
    m_page->setVirtualViewportSize(Platform::IntSize(800, 600));
 
297
    m_page->resetVirtualViewportOnCommitted(false);
 
298
    m_page->setUserScalable(true);
 
299
    m_page->setJavaScriptCanAccessClipboard(true);
 
300
 
 
301
    if (WebCore::Page* page = DumpRenderTreeSupport::corePage(m_page)) {
 
302
        page->setTabKeyCyclesThroughElements(true);
 
303
 
 
304
        // FIXME: Remove this once BlackBerry uses resetInternalsObject: https://bugs.webkit.org/show_bug.cgi?id=86899.
 
305
        page->settings()->setEditingBehaviorType(WebCore::EditingUnixBehavior);
 
306
 
 
307
        page->settings()->setDOMPasteAllowed(true);
 
308
        page->settings()->setValidationMessageTimerMagnification(-1);
 
309
        page->settings()->setInteractiveFormValidationEnabled(true);
 
310
        page->settings()->setAllowFileAccessFromFileURLs(true);
 
311
        page->settings()->setAllowUniversalAccessFromFileURLs(true);
 
312
        page->settings()->setAuthorAndUserStylesEnabled(true);
 
313
        page->settings()->setUsePreHTML5ParserQuirks(false);
 
314
        // FIXME: Other ports also clear history/backForwardList allong with visited links.
 
315
        page->group().removeVisitedLinks();
 
316
        if (mainFrame = page->mainFrame()) {
 
317
            mainFrame->tree()->clearName();
 
318
            mainFrame->loader()->setOpener(0);
 
319
            // [WebKit bug #86899] Reset JS state settings.
 
320
            JSGlobalContextRef jsContext = toGlobalRef(mainFrame->script()->globalObject(WebCore::mainThreadNormalWorld())->globalExec());
 
321
            WebCoreTestSupport::resetInternalsObject(jsContext);
 
322
        }
 
323
    }
 
324
 
 
325
    // For now we manually garbage collect between each test to make sure the device won't run out of memory due to lazy collection.
 
326
    DumpRenderTreeSupport::garbageCollectorCollect();
 
327
}
 
328
 
 
329
void DumpRenderTree::runTests()
 
330
{
 
331
    m_gcController = new GCController();
 
332
    m_accessibilityController = new AccessibilityController();
 
333
    if (!ensurePPS()) {
 
334
        fprintf(stderr, "Failed to open PPS file '%s', error=%d\n", getPPSPath().c_str(), errno);
 
335
        (m_page->client())->notifyRunLayoutTestsFinished();
 
336
        return;
 
337
    }
 
338
 
 
339
    mainFrame = DumpRenderTreeSupport::corePage(m_page)->mainFrame();
 
340
 
 
341
    if (const char* testFile = getenv("drtTestFile")) {
 
342
        runFromCommandLine = true;
 
343
        addTest(testFile);
 
344
    } else {
 
345
        // Get Test file name from PPS: /pps/services/drt/input
 
346
        // Example: test_file::fast/js/arguments.html
 
347
        waitForTest();
 
348
    }
 
349
}
 
350
 
 
351
void DumpRenderTree::addTest(const char* testFile)
 
352
{
 
353
    String test(testFile);
 
354
    if (test == "#DONE")
 
355
        doneDrt();
 
356
    else if (!test.isEmpty()) {
 
357
        if (m_tests.isEmpty()) {
 
358
            // No test is being run, initialize iterator and start test
 
359
            m_tests.append(test);
 
360
            m_currentTest = m_tests.begin();
 
361
            runCurrentTest();
 
362
        } else
 
363
            m_bufferedTests.append(test);
 
364
    }
 
365
}
 
366
 
 
367
String DumpRenderTree::dumpFramesAsText(WebCore::Frame* frame)
 
368
{
 
369
    String s;
 
370
    WebCore::Element* documentElement = frame->document()->documentElement();
 
371
    if (!documentElement)
 
372
        return s.utf8().data();
 
373
 
 
374
    if (frame->tree()->parent())
 
375
        s = String::format("\n--------\nFrame: '%s'\n--------\n", frame->tree()->uniqueName().string().utf8().data());
 
376
 
 
377
    s = s + documentElement->innerText() + "\n";
 
378
 
 
379
    if (gTestRunner->dumpChildFramesAsText()) {
 
380
        WebCore::FrameTree* tree = frame->tree();
 
381
        for (WebCore::Frame* child = tree->firstChild(); child; child = child->tree()->nextSibling())
 
382
            s = s + dumpFramesAsText(child);
 
383
    }
 
384
    return s;
 
385
}
 
386
 
 
387
static void dumpToFile(const String& data)
 
388
{
 
389
    fwrite(data.utf8().data(), 1, data.utf8().length(), stdout);
 
390
}
 
391
 
 
392
bool DumpRenderTree::isHTTPTest(const String& test)
 
393
{
 
394
    if (test.length() < strlen(httpTestSyntax))
 
395
        return false;
 
396
    String testLower = test.lower();
 
397
    int lenHttpTestSyntax = strlen(httpTestSyntax);
 
398
    return testLower.substring(0, lenHttpTestSyntax) == httpTestSyntax
 
399
        && testLower.substring(lenHttpTestSyntax, strlen(localTestSyntax)) != localTestSyntax;
 
400
}
 
401
 
 
402
void DumpRenderTree::invalidateAnyPreviousWaitToDumpWatchdog()
 
403
{
 
404
    m_waitToDumpWatchdogTimer.stop();
 
405
    waitForPolicy = false;
 
406
}
 
407
 
 
408
String DumpRenderTree::renderTreeDump() const
 
409
{
 
410
    if (mainFrame) {
 
411
        if (mainFrame->view() && mainFrame->view()->layoutPending())
 
412
            mainFrame->view()->layout();
 
413
 
 
414
        return externalRepresentation(mainFrame);
 
415
    }
 
416
    return "";
 
417
}
 
418
 
 
419
static bool historyItemCompare(const RefPtr<WebCore::HistoryItem>& a, const RefPtr<WebCore::HistoryItem>& b)
 
420
{
 
421
    return codePointCompare(a->urlString(), b->urlString()) < 0;
 
422
}
 
423
 
 
424
static String dumpHistoryItem(PassRefPtr<WebCore::HistoryItem> item, int indent, bool current)
 
425
{
 
426
    String result;
 
427
 
 
428
    int start = 0;
 
429
    if (current) {
 
430
        result = result + "curr->";
 
431
        start = 6;
 
432
    }
 
433
    for (int i = start; i < indent; i++)
 
434
        result = result + " ";
 
435
 
 
436
    String url = item->urlString();
 
437
    if (url.contains("file://")) {
 
438
        static String layoutTestsString("/LayoutTests/");
 
439
        static String fileTestString("(file test):");
 
440
 
 
441
        String res = url.substring(url.find(layoutTestsString) + layoutTestsString.length());
 
442
        if (res.isEmpty())
 
443
            return result;
 
444
 
 
445
        result = result + fileTestString;
 
446
        result = result + res;
 
447
    } else
 
448
        result = result + url;
 
449
 
 
450
    String target = item->target();
 
451
    if (!target.isEmpty())
 
452
        result = result + " (in frame \"" + target + "\")";
 
453
 
 
454
    if (item->isTargetItem())
 
455
        result = result + "  **nav target**";
 
456
    result = result + "\n";
 
457
 
 
458
    WebCore::HistoryItemVector children = item->children();
 
459
    // Must sort to eliminate arbitrary result ordering which defeats reproducible testing.
 
460
    nonCopyingSort(children.begin(), children.end(), historyItemCompare);
 
461
    unsigned resultSize = children.size();
 
462
    for (unsigned i = 0; i < resultSize; ++i)
 
463
        result = result + dumpHistoryItem(children[i], indent + 4, false);
 
464
 
 
465
    return result;
 
466
}
 
467
 
 
468
static String dumpBackForwardListForWebView()
 
469
{
 
470
    String result = "\n============== Back Forward List ==============\n";
 
471
    // FORMAT:
 
472
    // "        (file test):fast/loader/resources/click-fragment-link.html  **nav target**"
 
473
    // "curr->  (file test):fast/loader/resources/click-fragment-link.html#testfragment  **nav target**"
 
474
    WebCore::BackForwardListImpl* bfList = static_cast<WebCore::BackForwardListImpl*>(mainFrame->page()->backForward()->client());
 
475
    int maxItems = bfList->capacity();
 
476
    WebCore::HistoryItemVector entries;
 
477
    bfList->backListWithLimit(maxItems, entries);
 
478
    unsigned resultSize = entries.size();
 
479
    for (unsigned i = 0; i < resultSize; ++i)
 
480
        result = result + dumpHistoryItem(entries[i], 8, false);
 
481
 
 
482
    result = result + dumpHistoryItem(bfList->currentItem(), 8, true);
 
483
 
 
484
    bfList->forwardListWithLimit(maxItems, entries);
 
485
    resultSize = entries.size();
 
486
    for (unsigned i = 0; i < resultSize; ++i)
 
487
        result = result + dumpHistoryItem(entries[i], 8, false);
 
488
 
 
489
    result = result +  "===============================================\n";
 
490
 
 
491
    return result;
 
492
}
 
493
 
 
494
void DumpRenderTree::dump()
 
495
{
 
496
    if (testDone)
 
497
        return;
 
498
 
 
499
    invalidateAnyPreviousWaitToDumpWatchdog();
 
500
 
 
501
    String dumpFile = m_resultsDir + *m_currentTest + ".dump";
 
502
 
 
503
    String resultMimeType = "text/plain";
 
504
    String responseMimeType = mainFrame->loader()->documentLoader()->responseMIMEType();
 
505
 
 
506
    bool dumpAsText = gTestRunner->dumpAsText() || responseMimeType == "text/plain";
 
507
    String data = dumpAsText ? dumpFramesAsText(mainFrame) : renderTreeDump();
 
508
 
 
509
    if (gTestRunner->dumpBackForwardList())
 
510
        data = data + dumpBackForwardListForWebView();
 
511
 
 
512
    String result = "Content-Type: " + resultMimeType + "\n" + data;
 
513
 
 
514
    dumpToFile(result);
 
515
 
 
516
    if (!runFromCommandLine) {
 
517
        // signal end of text block
 
518
        fputs("#EOF\n", stdout);
 
519
 
 
520
        // There are two scenarios for dumping pixels:
 
521
        // 1. When the test case explicitly asks for it by calling dumpAsText(true) with that extra true passed as a parameter value, from JavaScript
 
522
        bool explicitPixelResults = gTestRunner->dumpAsText() && gTestRunner->generatePixelResults();
 
523
        // 2. When the test case implicitly allows it by not calling dumpAsText() at all (with no parameters).
 
524
        bool implicitPixelResults = !gTestRunner->dumpAsText();
 
525
 
 
526
        // But only if m_enablePixelTests is set, to say that the user wants to run pixel tests at all.
 
527
        bool generatePixelResults = m_enablePixelTests && (explicitPixelResults || implicitPixelResults);
 
528
        if (generatePixelResults)
 
529
            dumpWebViewAsPixelsAndCompareWithExpected(gTestRunner->expectedPixelHash());
 
530
 
 
531
        String crashFile = dumpFile + ".crash";
 
532
        unlink(crashFile.utf8().data());
 
533
 
 
534
        String doneFile =  m_resultsDir + *m_currentTest + ".done";
 
535
        createFile(doneFile);
 
536
    }
 
537
    testDone = true;
 
538
    runRemainingTests();
 
539
}
 
540
 
 
541
void DumpRenderTree::setWaitToDumpWatchdog(double interval)
 
542
{
 
543
    invalidateAnyPreviousWaitToDumpWatchdog();
 
544
    m_waitToDumpWatchdogTimer.startOneShot(interval);
 
545
}
 
546
 
 
547
void DumpRenderTree::waitToDumpWatchdogTimerFired(WebCore::Timer<DumpRenderTree>*)
 
548
{
 
549
    gTestRunner->waitToDumpWatchdogTimerFired();
 
550
}
 
551
 
 
552
void DumpRenderTree::processWork(WebCore::Timer<DumpRenderTree>*)
 
553
{
 
554
    if (topLoadingFrame)
 
555
        return;
 
556
 
 
557
    if (WorkQueue::shared()->processWork() && !gTestRunner->waitToDump())
 
558
        dump();
 
559
}
 
560
 
 
561
void DumpRenderTree::locationChangeForFrame(WebCore::Frame* frame)
 
562
{
 
563
    if (frame != topLoadingFrame)
 
564
        return;
 
565
 
 
566
    topLoadingFrame = 0;
 
567
    WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue
 
568
    if (gTestRunner->waitToDump())
 
569
        return;
 
570
 
 
571
    if (WorkQueue::shared()->count())
 
572
        m_workTimer.startOneShot(0);
 
573
    else
 
574
        dump();
 
575
}
 
576
 
 
577
// FrameLoadClient delegates.
 
578
void DumpRenderTree::didStartProvisionalLoadForFrame(WebCore::Frame* frame)
 
579
{
 
580
    if (!testDone && gTestRunner->dumpFrameLoadCallbacks())
 
581
        printf("%s - didStartProvisionalLoadForFrame\n", drtFrameDescription(frame).utf8().data());
 
582
 
 
583
    if (!testDone && gTestRunner->dumpUserGestureInFrameLoadCallbacks())
 
584
        printf("Frame with user gesture \"%s\" - in didStartProvisionalLoadForFrame\n", WebCore::ScriptController::processingUserGesture() ? "true" : "false");
 
585
 
 
586
    if (!topLoadingFrame && !testDone)
 
587
        topLoadingFrame = frame;
 
588
 
 
589
    if (!testDone && gTestRunner->stopProvisionalFrameLoads()) {
 
590
        printf("%s - stopping load in didStartProvisionalLoadForFrame callback\n", drtFrameDescription(frame).utf8().data());
 
591
        frame->loader()->stopForUserCancel();
 
592
    }
 
593
}
 
594
 
 
595
void DumpRenderTree::didCommitLoadForFrame(WebCore::Frame* frame)
 
596
{
 
597
    if (!testDone && gTestRunner->dumpFrameLoadCallbacks())
 
598
        printf("%s - didCommitLoadForFrame\n", drtFrameDescription(frame).utf8().data());
 
599
 
 
600
    gTestRunner->setWindowIsKey(true);
 
601
}
 
602
 
 
603
void DumpRenderTree::didFailProvisionalLoadForFrame(WebCore::Frame* frame)
 
604
{
 
605
    if (!testDone && gTestRunner->dumpFrameLoadCallbacks())
 
606
        printf("%s - didFailProvisionalLoadWithError\n", drtFrameDescription(frame).utf8().data());
 
607
 
 
608
    locationChangeForFrame(frame);
 
609
}
 
610
 
 
611
void DumpRenderTree::didFailLoadForFrame(WebCore::Frame* frame)
 
612
{
 
613
    if (!testDone && gTestRunner->dumpFrameLoadCallbacks())
 
614
        printf("%s - didFailLoadWithError\n", drtFrameDescription(frame).utf8().data());
 
615
 
 
616
    locationChangeForFrame(frame);
 
617
}
 
618
 
 
619
void DumpRenderTree::didFinishLoadForFrame(WebCore::Frame* frame)
 
620
{
 
621
    if (!testDone && gTestRunner->dumpFrameLoadCallbacks())
 
622
        printf("%s - didFinishLoadForFrame\n", drtFrameDescription(frame).utf8().data());
 
623
 
 
624
    if (frame == topLoadingFrame)
 
625
        m_loadFinished = true;
 
626
    locationChangeForFrame(frame);
 
627
}
 
628
 
 
629
void DumpRenderTree::didFinishDocumentLoadForFrame(WebCore::Frame* frame)
 
630
{
 
631
    if (!testDone) {
 
632
        if (gTestRunner->dumpFrameLoadCallbacks())
 
633
            printf("%s - didFinishDocumentLoadForFrame\n", drtFrameDescription(frame).utf8().data());
 
634
        else {
 
635
            unsigned pendingFrameUnloadEvents = frame->document()->domWindow()->pendingUnloadEventListeners();
 
636
            if (pendingFrameUnloadEvents)
 
637
                printf("%s - has %u onunload handler(s)\n", drtFrameDescription(frame).utf8().data(), pendingFrameUnloadEvents);
 
638
        }
 
639
    }
 
640
}
 
641
 
 
642
void DumpRenderTree::didClearWindowObjectInWorld(WebCore::DOMWrapperWorld*, JSGlobalContextRef context, JSObjectRef windowObject)
 
643
{
 
644
    JSValueRef exception = 0;
 
645
 
 
646
    gTestRunner->makeWindowObject(context, windowObject, &exception);
 
647
    ASSERT(!exception);
 
648
 
 
649
    m_gcController->makeWindowObject(context, windowObject, &exception);
 
650
    ASSERT(!exception);
 
651
 
 
652
    m_accessibilityController->makeWindowObject(context, windowObject, &exception);
 
653
    ASSERT(!exception);
 
654
 
 
655
    JSStringRef eventSenderStr = JSStringCreateWithUTF8CString("eventSender");
 
656
    JSValueRef eventSender = makeEventSender(context);
 
657
    JSObjectSetProperty(context, windowObject, eventSenderStr, eventSender, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0);
 
658
    JSStringRelease(eventSenderStr);
 
659
    WebCoreTestSupport::injectInternalsObject(context);
 
660
}
 
661
 
 
662
void DumpRenderTree::didReceiveTitleForFrame(const String& title, WebCore::Frame* frame)
 
663
{
 
664
    if (!testDone && gTestRunner->dumpFrameLoadCallbacks())
 
665
        printf("%s - didReceiveTitle: %s\n", drtFrameDescription(frame).utf8().data(), title.utf8().data());
 
666
 
 
667
    if (gTestRunner->dumpTitleChanges())
 
668
        printf("TITLE CHANGED: %s\n", title.utf8().data());
 
669
}
 
670
 
 
671
// ChromeClient delegates.
 
672
void DumpRenderTree::addMessageToConsole(const String& message, unsigned lineNumber, const String& sourceID)
 
673
{
 
674
    printf("CONSOLE MESSAGE: ");
 
675
    if (lineNumber)
 
676
        printf("line %d: ", lineNumber);
 
677
    String newMessage = message;
 
678
    int pos = message.find("file://");
 
679
    if (pos >= 0) {
 
680
        newMessage = message.substring(0, pos);
 
681
        String remaining = message.substring(pos);
 
682
        String fileName;
 
683
        int indexFile = remaining.reverseFind('/') + 1;
 
684
        if (indexFile > 0 && unsigned(indexFile) < remaining.length())
 
685
            fileName = remaining.substring(indexFile);
 
686
        else
 
687
            fileName = "file:";
 
688
        newMessage.append(fileName);
 
689
    }
 
690
    printf("%s\n", newMessage.utf8().data());
 
691
}
 
692
 
 
693
void DumpRenderTree::runJavaScriptAlert(const String& message)
 
694
{
 
695
    if (!testDone)
 
696
        printf("ALERT: %s\n", message.utf8().data());
 
697
}
 
698
 
 
699
bool DumpRenderTree::runJavaScriptConfirm(const String& message)
 
700
{
 
701
    if (!testDone)
 
702
        printf("CONFIRM: %s\n", message.utf8().data());
 
703
    return true;
 
704
}
 
705
 
 
706
String DumpRenderTree::runJavaScriptPrompt(const String& message, const String& defaultValue)
 
707
{
 
708
    if (!testDone)
 
709
        printf("PROMPT: %s, default text: %s\n", message.utf8().data(), defaultValue.utf8().data());
 
710
    return defaultValue;
 
711
}
 
712
 
 
713
bool DumpRenderTree::runBeforeUnloadConfirmPanel(const String& message)
 
714
{
 
715
    if (!testDone)
 
716
        printf("CONFIRM NAVIGATION: %s\n", message.utf8().data());
 
717
    return true;
 
718
}
 
719
 
 
720
void DumpRenderTree::setStatusText(const String& status)
 
721
{
 
722
    if (gTestRunner->dumpStatusCallbacks())
 
723
        printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", status.utf8().data());
 
724
}
 
725
 
 
726
void DumpRenderTree::exceededDatabaseQuota(WebCore::SecurityOrigin* origin, const String& name)
 
727
{
 
728
    if (!testDone && gTestRunner->dumpDatabaseCallbacks())
 
729
        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());
 
730
 
 
731
    WebCore::DatabaseTracker::tracker().setQuota(mainFrame->document()->securityOrigin(), 5 * 1024 * 1024);
 
732
}
 
733
 
 
734
bool DumpRenderTree::allowsOpeningWindow()
 
735
{
 
736
    return gTestRunner->canOpenWindows();
 
737
}
 
738
 
 
739
void DumpRenderTree::windowCreated(BlackBerry::WebKit::WebPage* page)
 
740
{
 
741
    page->settings()->setJavaScriptOpenWindowsAutomatically(true);
 
742
}
 
743
 
 
744
// EditorClient delegates.
 
745
void DumpRenderTree::didBeginEditing()
 
746
{
 
747
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
748
        printf("EDITING DELEGATE: webViewDidBeginEditing:%s\n", "WebViewDidBeginEditingNotification");
 
749
}
 
750
 
 
751
void DumpRenderTree::didEndEditing()
 
752
{
 
753
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
754
        printf("EDITING DELEGATE: webViewDidEndEditing:%s\n", "WebViewDidEndEditingNotification");
 
755
}
 
756
 
 
757
void DumpRenderTree::didChange()
 
758
{
 
759
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
760
        printf("EDITING DELEGATE: webViewDidChange:%s\n", "WebViewDidChangeNotification");
 
761
}
 
762
 
 
763
void DumpRenderTree::didChangeSelection()
 
764
{
 
765
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
766
        printf("EDITING DELEGATE: webViewDidChangeSelection:%s\n", "WebViewDidChangeSelectionNotification");
 
767
}
 
768
 
 
769
bool DumpRenderTree::shouldBeginEditingInDOMRange(WebCore::Range* range)
 
770
{
 
771
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
772
        printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", drtRangeDescription(range).utf8().data());
 
773
    return m_acceptsEditing;
 
774
}
 
775
 
 
776
bool DumpRenderTree::shouldEndEditingInDOMRange(WebCore::Range* range)
 
777
{
 
778
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
779
        printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", drtRangeDescription(range).utf8().data());
 
780
    return m_acceptsEditing;
 
781
}
 
782
 
 
783
bool DumpRenderTree::shouldDeleteDOMRange(WebCore::Range* range)
 
784
{
 
785
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
786
        printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", drtRangeDescription(range).utf8().data());
 
787
    return m_acceptsEditing;
 
788
}
 
789
 
 
790
bool DumpRenderTree::shouldChangeSelectedDOMRangeToDOMRangeAffinityStillSelecting(WebCore::Range* fromRange, WebCore::Range* toRange, int affinity, bool stillSelecting)
 
791
{
 
792
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
793
        printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n", drtRangeDescription(fromRange).utf8().data(), drtRangeDescription(toRange).utf8().data(), drtAffinityDescription(static_cast<WebCore::EAffinity>(affinity)).utf8().data(), stillSelecting ? "TRUE" : "FALSE");
 
794
    return m_acceptsEditing;
 
795
}
 
796
 
 
797
static const char* insertActionString(WebCore::EditorInsertAction action)
 
798
{
 
799
    switch (action) {
 
800
    case WebCore::EditorInsertActionTyped:
 
801
        return "WebViewInsertActionTyped";
 
802
    case WebCore::EditorInsertActionPasted:
 
803
        return "WebViewInsertActionPasted";
 
804
    case WebCore::EditorInsertActionDropped:
 
805
        return "WebViewInsertActionDropped";
 
806
    }
 
807
    ASSERT_NOT_REACHED();
 
808
    return "WebViewInsertActionTyped";
 
809
}
 
810
 
 
811
bool DumpRenderTree::shouldInsertNode(WebCore::Node* node, WebCore::Range* range, int action)
 
812
{
 
813
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
814
        printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n", drtDumpPath(node).utf8().data(), drtRangeDescription(range).utf8().data(), insertActionString((WebCore::EditorInsertAction)action));
 
815
    return m_acceptsEditing;
 
816
}
 
817
 
 
818
bool DumpRenderTree::shouldInsertText(const String& text, WebCore::Range* range, int action)
 
819
{
 
820
    if (!testDone && gTestRunner->dumpEditingCallbacks())
 
821
        printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n", text.utf8().data(), drtRangeDescription(range).utf8().data(), insertActionString((WebCore::EditorInsertAction)action));
 
822
    return m_acceptsEditing;
 
823
}
 
824
 
 
825
void DumpRenderTree::didDecidePolicyForNavigationAction(const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request)
 
826
{
 
827
    if (!waitForPolicy)
 
828
        return;
 
829
 
 
830
    const char* typeDescription;
 
831
    switch (action.type()) {
 
832
    case WebCore::NavigationTypeLinkClicked:
 
833
        typeDescription = "link clicked";
 
834
        break;
 
835
    case WebCore::NavigationTypeFormSubmitted:
 
836
        typeDescription = "form submitted";
 
837
        break;
 
838
    case WebCore::NavigationTypeBackForward:
 
839
        typeDescription = "back/forward";
 
840
        break;
 
841
    case WebCore::NavigationTypeReload:
 
842
        typeDescription = "reload";
 
843
        break;
 
844
    case WebCore::NavigationTypeFormResubmitted:
 
845
        typeDescription = "form resubmitted";
 
846
        break;
 
847
    case WebCore::NavigationTypeOther:
 
848
        typeDescription = "other";
 
849
        break;
 
850
    default:
 
851
        typeDescription = "illegal value";
 
852
    }
 
853
 
 
854
    printf("Policy delegate: attempt to load %s with navigation type '%s'\n", request.url().string().utf8().data(), typeDescription);
 
855
    // FIXME: do originating part.
 
856
 
 
857
    gTestRunner->notifyDone();
 
858
}
 
859
 
 
860
void DumpRenderTree::didDispatchWillPerformClientRedirect()
 
861
{
 
862
    if (!testDone && gTestRunner->dumpUserGestureInFrameLoadCallbacks())
 
863
        printf("Frame with user gesture \"%s\" - in willPerformClientRedirect\n", WebCore::ScriptController::processingUserGesture() ? "true" : "false");
 
864
}
 
865
 
 
866
void DumpRenderTree::didHandleOnloadEventsForFrame(WebCore::Frame* frame)
 
867
{
 
868
    if (!testDone && gTestRunner->dumpFrameLoadCallbacks())
 
869
        printf("%s - didHandleOnloadEventsForFrame\n", drtFrameDescription(frame).utf8().data());
 
870
}
 
871
 
 
872
void DumpRenderTree::didReceiveResponseForFrame(WebCore::Frame* frame, const WebCore::ResourceResponse& response)
 
873
{
 
874
    if (!testDone && gTestRunner->dumpResourceResponseMIMETypes())
 
875
        printf("%s has MIME type %s\n", response.url().lastPathComponent().utf8().data(), response.mimeType().utf8().data());
 
876
}
 
877
 
 
878
bool DumpRenderTree::didReceiveAuthenticationChallenge(WebCore::Credential& credential)
 
879
{
 
880
    if (!gTestRunner->handlesAuthenticationChallenges()) {
 
881
        credential = WebCore::Credential();
 
882
        printf("%s - didReceiveAuthenticationChallenge - Simulating cancelled authentication\n", drtCredentialDescription(credential).utf8().data());
 
883
        return false;
 
884
    }
 
885
    const char* user = gTestRunner->authenticationUsername().c_str();
 
886
    const char* password = gTestRunner->authenticationPassword().c_str();
 
887
    credential = WebCore::Credential(user, password, WebCore::CredentialPersistenceForSession);
 
888
    printf("%s - didReceiveAuthenticationChallenge - Responding with %s:%s\n", drtCredentialDescription(credential).utf8().data(), user, password);
 
889
    return true;
 
890
}
 
891
 
 
892
}
 
893
}
 
894
 
 
895
// Static dump() function required by cross-platform DRT code.
 
896
void dump()
 
897
{
 
898
    BlackBerry::WebKit::DumpRenderTree* dumper = BlackBerry::WebKit::DumpRenderTree::currentInstance();
 
899
    if (!dumper)
 
900
        return;
 
901
 
 
902
    dumper->dump();
 
903
}