1/*
2 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
3 * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#include "config.h"
30#include "LayoutTestControllerQt.h"
31#include "DumpRenderTreeSupportQt.h"
32
33#include "DumpRenderTreeQt.h"
34#include "WorkQueue.h"
35#include "WorkQueueItemQt.h"
36#include <QDir>
37#include <QLocale>
38#include <qwebsettings.h>
39
40LayoutTestController::LayoutTestController(WebCore::DumpRenderTree* drt)
41    : QObject()
42    , m_drt(drt)
43{
44    qRegisterMetaType<QWebElement>("QWebElement");
45    reset();
46    DumpRenderTreeSupportQt::dumpNotification(true);
47}
48
49void LayoutTestController::reset()
50{
51    m_hasDumped = false;
52    m_loadFinished = false;
53    m_textDump = false;
54    m_dumpBackForwardList = false;
55    m_dumpChildrenAsText = false;
56    m_dumpChildFrameScrollPositions = false;
57    m_canOpenWindows = false;
58    m_waitForDone = false;
59    m_dumpTitleChanges = false;
60    m_dumpDatabaseCallbacks = false;
61    m_dumpApplicationCacheDelegateCallbacks = false;
62    m_dumpStatusCallbacks = false;
63    m_timeoutTimer.stop();
64    m_topLoadingFrame = 0;
65    m_waitForPolicy = false;
66    m_handleErrorPages = false;
67    m_webHistory = 0;
68    m_globalFlag = false;
69    m_userStyleSheetEnabled = false;
70    m_desktopNotificationAllowedOrigins.clear();
71    m_ignoreDesktopNotification = false;
72    m_isGeolocationPermissionSet = false;
73    m_isPrinting = false;
74    m_geolocationPermission = false;
75
76    DumpRenderTreeSupportQt::dumpEditingCallbacks(false);
77    DumpRenderTreeSupportQt::dumpFrameLoader(false);
78    DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(false);
79    DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(false);
80    DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(false);
81    DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(true);
82    DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(false);
83    DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(false);
84    DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(QStringList());
85    DumpRenderTreeSupportQt::clearScriptWorlds();
86    DumpRenderTreeSupportQt::setCustomPolicyDelegate(false, false);
87    DumpRenderTreeSupportQt::dumpHistoryCallbacks(false);
88    DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(false);
89    DumpRenderTreeSupportQt::resetGeolocationMock(m_drt->webPage());
90    setIconDatabaseEnabled(false);
91    clearAllDatabases();
92
93    emit hidePage();
94}
95
96void LayoutTestController::processWork()
97{
98    // qDebug() << ">>>processWork";
99
100    // if we didn't start a new load, then we finished all the commands, so we're ready to dump state
101    if (WorkQueue::shared()->processWork() && !shouldWaitUntilDone()) {
102        emit done();
103        m_hasDumped = true;
104    }
105}
106
107// Called on loadFinished on WebPage
108void LayoutTestController::maybeDump(bool success)
109{
110
111    // This can happen on any of the http/tests/security/window-events-*.html tests, where the test opens
112    // a new window, calls the unload and load event handlers on the window's page, and then immediately
113    // issues a notifyDone. Needs investigation.
114    if (!m_topLoadingFrame)
115        return;
116
117    // It is possible that we get called by windows created from the main page that have finished
118    // loading, so we don't ASSERT here. At the moment we do not gather results from such windows,
119    // but may need to in future.
120    if (sender() != m_topLoadingFrame->page())
121        return;
122
123    m_loadFinished = true;
124    // as the function is called on loadFinished, the test might
125    // already have dumped and thus no longer be active, thus
126    // bail out here.
127    if (m_hasDumped)
128        return;
129
130    WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
131    if (WorkQueue::shared()->count())
132        QTimer::singleShot(0, this, SLOT(processWork()));
133    else if (!shouldWaitUntilDone()) {
134        if (success)
135            emit done();
136        m_hasDumped = true;
137    }
138}
139
140void LayoutTestController::waitUntilDone()
141{
142    //qDebug() << ">>>>waitForDone";
143    m_waitForDone = true;
144    m_timeoutTimer.start(30000, this);
145}
146
147QString LayoutTestController::counterValueForElementById(const QString& id)
148{
149    return DumpRenderTreeSupportQt::counterValueForElementById(m_drt->webPage()->mainFrame(), id);
150}
151
152void LayoutTestController::setViewModeMediaFeature(const QString& mode)
153{
154    m_drt->webPage()->setProperty("_q_viewMode", mode);
155}
156
157int LayoutTestController::webHistoryItemCount()
158{
159    if (!m_webHistory)
160        return -1;
161
162    // Subtract one here as our QWebHistory::count() includes the actual page,
163    // which is not considered in the DRT tests.
164    return m_webHistory->count() - 1;
165}
166
167void LayoutTestController::keepWebHistory()
168{
169    m_webHistory = m_drt->webPage()->history();
170}
171
172void LayoutTestController::notifyDone()
173{
174    qDebug() << ">>>>notifyDone";
175
176    if (!m_timeoutTimer.isActive())
177        return;
178
179    m_timeoutTimer.stop();
180    m_waitForDone = false;
181
182    // If the page has not finished loading (i.e. loadFinished() has not been emitted) then
183    // content created by the likes of document.write() JS methods will not be available yet.
184    // When the page has finished loading, maybeDump above will dump the results now that we have
185    // just set shouldWaitUntilDone to false.
186    if (!m_loadFinished)
187        return;
188
189    emit done();
190
191    // FIXME: investigate why always resetting these result in timeouts
192    m_hasDumped = true;
193    m_waitForPolicy = false;
194}
195
196int LayoutTestController::windowCount()
197{
198    return m_drt->windowCount();
199}
200
201void LayoutTestController::grantDesktopNotificationPermission(const QString& origin)
202{
203    QWebFrame* frame = m_drt->webPage()->mainFrame();
204    m_drt->webPage()->setFeaturePermission(frame, QWebPage::Notifications, QWebPage::PermissionGrantedByUser);
205    m_desktopNotificationAllowedOrigins.append(origin);
206}
207
208void LayoutTestController::ignoreDesktopNotificationPermissionRequests()
209{
210    m_ignoreDesktopNotification = true;
211}
212
213bool LayoutTestController::checkDesktopNotificationPermission(const QString& origin)
214{
215    return !m_ignoreDesktopNotification && m_desktopNotificationAllowedOrigins.contains(origin);
216}
217
218void LayoutTestController::simulateDesktopNotificationClick(const QString& title)
219{
220    DumpRenderTreeSupportQt::simulateDesktopNotificationClick(title);
221}
222
223void LayoutTestController::display()
224{
225    emit showPage();
226}
227
228void LayoutTestController::clearBackForwardList()
229{
230    m_drt->webPage()->history()->clear();
231}
232
233QString LayoutTestController::pathToLocalResource(const QString& url)
234{
235    // Function introduced in r28690.
236    return QDir::toNativeSeparators(url);
237}
238
239void LayoutTestController::dumpConfigurationForViewport(int deviceDPI, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight)
240{
241    QString res = DumpRenderTreeSupportQt::viewportAsText(m_drt->webPage(), deviceDPI, QSize(deviceWidth, deviceHeight), QSize(availableWidth, availableHeight));
242    fputs(qPrintable(res), stdout);
243}
244
245void LayoutTestController::dumpEditingCallbacks()
246{
247    qDebug() << ">>>dumpEditingCallbacks";
248    DumpRenderTreeSupportQt::dumpEditingCallbacks(true);
249}
250
251void LayoutTestController::dumpFrameLoadCallbacks()
252{
253    DumpRenderTreeSupportQt::dumpFrameLoader(true);
254}
255
256void LayoutTestController::dumpUserGestureInFrameLoadCallbacks()
257{
258    DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(true);
259}
260
261void LayoutTestController::dumpResourceLoadCallbacks()
262{
263    DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(true);
264}
265
266void LayoutTestController::dumpResourceResponseMIMETypes()
267{
268    DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(true);
269}
270
271void LayoutTestController::dumpHistoryCallbacks()
272{
273    DumpRenderTreeSupportQt::dumpHistoryCallbacks(true);
274}
275
276void LayoutTestController::setWillSendRequestReturnsNullOnRedirect(bool enabled)
277{
278    DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(enabled);
279}
280
281void LayoutTestController::setWillSendRequestReturnsNull(bool enabled)
282{
283    DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(enabled);
284}
285
286void LayoutTestController::setWillSendRequestClearHeader(const QStringList& headers)
287{
288    DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(headers);
289}
290
291void LayoutTestController::setDeferMainResourceDataLoad(bool defer)
292{
293    DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(defer);
294}
295
296void LayoutTestController::queueBackNavigation(int howFarBackward)
297{
298    //qDebug() << ">>>queueBackNavigation" << howFarBackward;
299    for (int i = 0; i != howFarBackward; ++i)
300        WorkQueue::shared()->queue(new BackItem(1, m_drt->webPage()));
301}
302
303void LayoutTestController::queueForwardNavigation(int howFarForward)
304{
305    //qDebug() << ">>>queueForwardNavigation" << howFarForward;
306    for (int i = 0; i != howFarForward; ++i)
307        WorkQueue::shared()->queue(new ForwardItem(1, m_drt->webPage()));
308}
309
310void LayoutTestController::queueLoad(const QString& url, const QString& target)
311{
312    //qDebug() << ">>>queueLoad" << url << target;
313    QUrl mainResourceUrl = m_drt->webPage()->mainFrame()->url();
314    QString absoluteUrl = mainResourceUrl.resolved(QUrl(url)).toEncoded();
315    WorkQueue::shared()->queue(new LoadItem(absoluteUrl, target, m_drt->webPage()));
316}
317
318void LayoutTestController::queueLoadHTMLString(const QString& content, const QString& baseURL, const QString& failingURL)
319{
320    if (failingURL.isEmpty())
321        WorkQueue::shared()->queue(new LoadHTMLStringItem(content, baseURL, m_drt->webPage()));
322    else
323        WorkQueue::shared()->queue(new LoadAlternateHTMLStringItem(content, baseURL, failingURL, m_drt->webPage()));
324}
325
326void LayoutTestController::queueReload()
327{
328    //qDebug() << ">>>queueReload";
329    WorkQueue::shared()->queue(new ReloadItem(m_drt->webPage()));
330}
331
332void LayoutTestController::queueLoadingScript(const QString& script)
333{
334    //qDebug() << ">>>queueLoadingScript" << script;
335    WorkQueue::shared()->queue(new LoadingScriptItem(script, m_drt->webPage()));
336}
337
338void LayoutTestController::queueNonLoadingScript(const QString& script)
339{
340    //qDebug() << ">>>queueNonLoadingScript" << script;
341    WorkQueue::shared()->queue(new NonLoadingScriptItem(script, m_drt->webPage()));
342}
343
344void LayoutTestController::provisionalLoad()
345{
346    QWebFrame* frame = qobject_cast<QWebFrame*>(sender());
347    if (!m_topLoadingFrame && !m_hasDumped)
348        m_topLoadingFrame = frame;
349}
350
351void LayoutTestController::timerEvent(QTimerEvent *ev)
352{
353    if (ev->timerId() == m_timeoutTimer.timerId()) {
354        const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
355        fprintf(stderr, "%s", message);
356        fprintf(stdout, "%s", message);
357        notifyDone();
358    } else
359        QObject::timerEvent(ev);
360}
361
362QString LayoutTestController::encodeHostName(const QString& host)
363{
364    QString encoded = QString::fromLatin1(QUrl::toAce(host + QLatin1String(".no")));
365    encoded.truncate(encoded.length() - 3); // strip .no
366    return encoded;
367}
368
369QString LayoutTestController::decodeHostName(const QString& host)
370{
371    QString decoded = QUrl::fromAce(host.toLatin1() + QByteArray(".no"));
372    decoded.truncate(decoded.length() - 3);
373    return decoded;
374}
375
376void LayoutTestController::setMediaType(const QString& type)
377{
378    DumpRenderTreeSupportQt::setMediaType(m_drt->webPage()->mainFrame(), type);
379}
380
381void LayoutTestController::closeWebInspector()
382{
383    DumpRenderTreeSupportQt::webInspectorClose(m_drt->webPage());
384    m_drt->webPage()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, false);
385}
386
387void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
388{
389    m_drt->webPage()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, enabled);
390}
391
392void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
393{
394    // FIXME: Implement this.
395}
396
397void LayoutTestController::showWebInspector()
398{
399    m_drt->webPage()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
400    DumpRenderTreeSupportQt::webInspectorShow(m_drt->webPage());
401}
402
403void LayoutTestController::evaluateInWebInspector(long callId, const QString& script)
404{
405    DumpRenderTreeSupportQt::webInspectorExecuteScript(m_drt->webPage(), callId, script);
406}
407
408void LayoutTestController::setFrameFlatteningEnabled(bool enabled)
409{
410    DumpRenderTreeSupportQt::setFrameFlatteningEnabled(m_drt->webPage(), enabled);
411}
412
413void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled)
414{
415    m_drt->webPage()->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, enabled);
416}
417
418void LayoutTestController::setAllowFileAccessFromFileURLs(bool enabled)
419{
420    m_drt->webPage()->settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, enabled);
421}
422
423void LayoutTestController::setAppCacheMaximumSize(unsigned long long quota)
424{
425    m_drt->webPage()->settings()->setOfflineWebApplicationCacheQuota(quota);
426}
427
428void LayoutTestController::setJavaScriptProfilingEnabled(bool enable)
429{
430    setDeveloperExtrasEnabled(enable);
431    DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(m_topLoadingFrame, enable);
432}
433
434void LayoutTestController::setTimelineProfilingEnabled(bool enable)
435{
436    DumpRenderTreeSupportQt::setTimelineProfilingEnabled(m_drt->webPage(), enable);
437}
438
439void LayoutTestController::setFixedContentsSize(int width, int height)
440{
441    m_topLoadingFrame->page()->setPreferredContentsSize(QSize(width, height));
442}
443
444void LayoutTestController::setPrivateBrowsingEnabled(bool enable)
445{
446    m_drt->webPage()->settings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, enable);
447}
448
449void LayoutTestController::setSpatialNavigationEnabled(bool enable)
450{
451    m_drt->webPage()->settings()->setAttribute(QWebSettings::SpatialNavigationEnabled, enable);
452}
453
454void LayoutTestController::setPopupBlockingEnabled(bool enable)
455{
456    m_drt->webPage()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, !enable);
457}
458
459void LayoutTestController::setPluginsEnabled(bool flag)
460{
461    // FIXME: Implement
462}
463
464void LayoutTestController::setPOSIXLocale(const QString& locale)
465{
466    QLocale qlocale(locale);
467    QLocale::setDefault(qlocale);
468}
469
470void LayoutTestController::setWindowIsKey(bool isKey)
471{
472    m_drt->switchFocus(isKey);
473}
474
475void LayoutTestController::setMainFrameIsFirstResponder(bool isFirst)
476{
477    //FIXME: only need this for the moment: https://bugs.webkit.org/show_bug.cgi?id=32990
478}
479
480void LayoutTestController::setJavaScriptCanAccessClipboard(bool enable)
481{
482    m_drt->webPage()->settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, enable);
483}
484
485void LayoutTestController::setXSSAuditorEnabled(bool enable)
486{
487    // Set XSSAuditingEnabled globally so that windows created by the test inherit it too.
488    // resetSettings() will call this to reset the page and global setting to false again.
489    // Needed by http/tests/security/xssAuditor/link-opens-new-window.html
490    QWebSettings* globalSettings = QWebSettings::globalSettings();
491    globalSettings->setAttribute(QWebSettings::XSSAuditingEnabled, enable);
492    m_drt->webPage()->settings()->setAttribute(QWebSettings::XSSAuditingEnabled, enable);
493}
494
495bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(const QString& animationName,
496                                                               double time,
497                                                               const QString& elementId)
498{
499    QWebFrame* frame = m_drt->webPage()->mainFrame();
500    Q_ASSERT(frame);
501    return DumpRenderTreeSupportQt::pauseAnimation(frame, animationName, time, elementId);
502}
503
504bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(const QString& propertyName,
505                                                                double time,
506                                                                const QString& elementId)
507{
508    QWebFrame* frame = m_drt->webPage()->mainFrame();
509    Q_ASSERT(frame);
510    return DumpRenderTreeSupportQt::pauseTransitionOfProperty(frame, propertyName, time, elementId);
511}
512
513bool LayoutTestController::sampleSVGAnimationForElementAtTime(const QString& animationId,
514                                                              double time,
515                                                              const QString& elementId)
516{
517    QWebFrame* frame = m_drt->webPage()->mainFrame();
518    Q_ASSERT(frame);
519    return DumpRenderTreeSupportQt::pauseSVGAnimation(frame, animationId, time, elementId);
520}
521
522unsigned LayoutTestController::numberOfActiveAnimations() const
523{
524    QWebFrame* frame = m_drt->webPage()->mainFrame();
525    Q_ASSERT(frame);
526    return DumpRenderTreeSupportQt::numberOfActiveAnimations(frame);
527}
528
529void LayoutTestController::suspendAnimations() const
530{
531    QWebFrame* frame = m_drt->webPage()->mainFrame();
532    Q_ASSERT(frame);
533    DumpRenderTreeSupportQt::suspendAnimations(frame);
534}
535
536void LayoutTestController::resumeAnimations() const
537{
538    QWebFrame* frame = m_drt->webPage()->mainFrame();
539    Q_ASSERT(frame);
540    DumpRenderTreeSupportQt::resumeAnimations(frame);
541}
542
543void LayoutTestController::disableImageLoading()
544{
545    m_drt->webPage()->settings()->setAttribute(QWebSettings::AutoLoadImages, false);
546}
547
548void LayoutTestController::dispatchPendingLoadRequests()
549{
550    // FIXME: Implement for testing fix for 6727495
551}
552
553void LayoutTestController::clearAllApplicationCaches()
554{
555    DumpRenderTreeSupportQt::clearAllApplicationCaches();
556}
557
558void LayoutTestController::clearApplicationCacheForOrigin(const QString& url)
559{
560    // FIXME: Implement to support deleting all application caches for an origin.
561}
562
563void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long quota)
564{
565    if (!m_topLoadingFrame)
566        return;
567    m_topLoadingFrame->securityOrigin().setApplicationCacheQuota(quota);
568}
569
570QStringList LayoutTestController::originsWithApplicationCache()
571{
572    // FIXME: Implement to get origins that have application caches.
573    return QStringList();
574}
575
576void LayoutTestController::setDatabaseQuota(int size)
577{
578    if (!m_topLoadingFrame)
579        return;
580    m_topLoadingFrame->securityOrigin().setDatabaseQuota(size);
581}
582
583void LayoutTestController::clearAllDatabases()
584{
585    QWebDatabase::removeAllDatabases();
586}
587
588void LayoutTestController::addOriginAccessWhitelistEntry(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains)
589{
590    DumpRenderTreeSupportQt::whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains);
591}
592
593void LayoutTestController::removeOriginAccessWhitelistEntry(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains)
594{
595    DumpRenderTreeSupportQt::removeWhiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains);
596}
597
598void LayoutTestController::setCustomPolicyDelegate(bool enabled, bool permissive)
599{
600    DumpRenderTreeSupportQt::setCustomPolicyDelegate(enabled, permissive);
601}
602
603void LayoutTestController::waitForPolicyDelegate()
604{
605    m_waitForPolicy = true;
606    waitUntilDone();
607}
608
609void LayoutTestController::overridePreference(const QString& name, const QVariant& value)
610{
611    QWebSettings* settings = m_topLoadingFrame->page()->settings();
612
613    if (name == "WebKitJavaScriptEnabled")
614        settings->setAttribute(QWebSettings::JavascriptEnabled, value.toBool());
615    else if (name == "WebKitTabToLinksPreferenceKey")
616        settings->setAttribute(QWebSettings::LinksIncludedInFocusChain, value.toBool());
617    else if (name == "WebKitOfflineWebApplicationCacheEnabled")
618        settings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, value.toBool());
619    else if (name == "WebKitDefaultFontSize")
620        settings->setFontSize(QWebSettings::DefaultFontSize, value.toInt());
621    else if (name == "WebKitUsesPageCachePreferenceKey")
622        QWebSettings::setMaximumPagesInCache(value.toInt());
623    else if (name == "WebKitEnableCaretBrowsing")
624        setCaretBrowsingEnabled(value.toBool());
625    else if (name == "WebKitPluginsEnabled")
626        settings->setAttribute(QWebSettings::PluginsEnabled, value.toBool());
627    else if (name == "WebKitWebGLEnabled")
628        settings->setAttribute(QWebSettings::WebGLEnabled, value.toBool());
629    else if (name == "WebKitHyperlinkAuditingEnabled")
630        settings->setAttribute(QWebSettings::HyperlinkAuditingEnabled, value.toBool());
631    else
632        printf("ERROR: LayoutTestController::overridePreference() does not support the '%s' preference\n",
633            name.toLatin1().data());
634}
635
636void LayoutTestController::setUserStyleSheetLocation(const QString& url)
637{
638    m_userStyleSheetLocation = QUrl::fromEncoded(url.toAscii(), QUrl::StrictMode);
639
640    if (m_userStyleSheetEnabled)
641        setUserStyleSheetEnabled(true);
642}
643
644void LayoutTestController::setCaretBrowsingEnabled(bool value)
645{
646    DumpRenderTreeSupportQt::setCaretBrowsingEnabled(m_drt->webPage(), value);
647}
648
649void LayoutTestController::setUserStyleSheetEnabled(bool enabled)
650{
651    m_userStyleSheetEnabled = enabled;
652
653    if (enabled)
654        m_drt->webPage()->settings()->setUserStyleSheetUrl(m_userStyleSheetLocation);
655    else
656        m_drt->webPage()->settings()->setUserStyleSheetUrl(QUrl());
657}
658
659void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme)
660{
661    DumpRenderTreeSupportQt::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme);
662}
663
664int LayoutTestController::workerThreadCount()
665{
666    return DumpRenderTreeSupportQt::workerThreadCount();
667}
668
669int LayoutTestController::pageNumberForElementById(const QString& id, float width, float height)
670{
671    // If no size specified, webpage viewport size is used
672    if (!width && !height) {
673        width = m_drt->webPage()->viewportSize().width();
674        height = m_drt->webPage()->viewportSize().height();
675    }
676
677    return DumpRenderTreeSupportQt::pageNumberForElementById(m_drt->webPage()->mainFrame(), id, width, height);
678}
679
680int LayoutTestController::numberOfPages(float width, float height)
681{
682    return DumpRenderTreeSupportQt::numberOfPages(m_drt->webPage()->mainFrame(), width, height);
683}
684
685bool LayoutTestController::callShouldCloseOnWebView()
686{
687    return DumpRenderTreeSupportQt::shouldClose(m_drt->webPage()->mainFrame());
688}
689
690void LayoutTestController::setScrollbarPolicy(const QString& orientation, const QString& policy)
691{
692    Qt::Orientation o;
693    Qt::ScrollBarPolicy p;
694
695    if (orientation == "vertical")
696        o = Qt::Vertical;
697    else if (orientation == "horizontal")
698        o = Qt::Horizontal;
699    else
700        return;
701
702    if (policy == "on")
703        p = Qt::ScrollBarAlwaysOn;
704    else if (policy == "auto")
705        p = Qt::ScrollBarAsNeeded;
706    else if (policy == "off")
707        p = Qt::ScrollBarAlwaysOff;
708    else
709        return;
710
711    m_drt->webPage()->mainFrame()->setScrollBarPolicy(o, p);
712}
713
714void LayoutTestController::setSmartInsertDeleteEnabled(bool enable)
715{
716    DumpRenderTreeSupportQt::setSmartInsertDeleteEnabled(m_drt->webPage(), enable);
717}
718
719void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool enable)
720{
721    DumpRenderTreeSupportQt::setSelectTrailingWhitespaceEnabled(m_drt->webPage(), enable);
722}
723
724void LayoutTestController::execCommand(const QString& name, const QString& value)
725{
726    DumpRenderTreeSupportQt::executeCoreCommandByName(m_drt->webPage(), name, value);
727}
728
729bool LayoutTestController::isCommandEnabled(const QString& name) const
730{
731    return DumpRenderTreeSupportQt::isCommandEnabled(m_drt->webPage(), name);
732}
733
734bool LayoutTestController::findString(const QString& string, const QStringList& optionArray)
735{
736    return DumpRenderTreeSupportQt::findString(m_drt->webPage(), string, optionArray);
737}
738
739QString LayoutTestController::markerTextForListItem(const QWebElement& listItem)
740{
741    return DumpRenderTreeSupportQt::markerTextForListItem(listItem);
742}
743
744QVariantMap LayoutTestController::computedStyleIncludingVisitedInfo(const QWebElement& element) const
745{
746    return DumpRenderTreeSupportQt::computedStyleIncludingVisitedInfo(element);
747}
748
749bool LayoutTestController::elementDoesAutoCompleteForElementWithId(const QString& elementId)
750{
751    return DumpRenderTreeSupportQt::elementDoesAutoCompleteForElementWithId(m_drt->webPage()->mainFrame(), elementId);
752}
753
754void LayoutTestController::authenticateSession(const QString&, const QString&, const QString&)
755{
756    // FIXME: If there is a concept per-session (per-process) credential storage, the credentials should be added to it for later use.
757}
758
759void LayoutTestController::setIconDatabaseEnabled(bool enable)
760{
761    if (enable && !m_drt->persistentStoragePath().isEmpty())
762        QWebSettings::setIconDatabasePath(m_drt->persistentStoragePath());
763    else
764        QWebSettings::setIconDatabasePath(QString());
765}
766
767void LayoutTestController::setEditingBehavior(const QString& editingBehavior)
768{
769    DumpRenderTreeSupportQt::setEditingBehavior(m_drt->webPage(), editingBehavior);
770}
771
772void LayoutTestController::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
773{
774    DumpRenderTreeSupportQt::setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
775}
776
777void LayoutTestController::setGeolocationPermission(bool allow)
778{
779    setGeolocationPermissionCommon(allow);
780    DumpRenderTreeSupportQt::setMockGeolocationPermission(m_drt->webPage(), allow);
781}
782
783QVariant LayoutTestController::shadowRoot(const QWebElement& element)
784{
785    return DumpRenderTreeSupportQt::shadowRoot(element);
786}
787
788int LayoutTestController::numberOfPendingGeolocationPermissionRequests()
789{
790    int pendingPermissionCount = 0;
791    QList<WebCore::WebPage*> pages = m_drt->getAllPages();
792    foreach (WebCore::WebPage* page, pages)
793        pendingPermissionCount += DumpRenderTreeSupportQt::numberOfPendingGeolocationPermissionRequests(page);
794
795    return pendingPermissionCount;
796}
797
798void LayoutTestController::setGeolocationPermissionCommon(bool allow)
799{
800     m_isGeolocationPermissionSet = true;
801     m_geolocationPermission = allow;
802}
803
804void LayoutTestController::setMockGeolocationError(int code, const QString& message)
805{
806    DumpRenderTreeSupportQt::setMockGeolocationError(m_drt->webPage(), code, message);
807}
808
809void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
810{
811    DumpRenderTreeSupportQt::setMockGeolocationPosition(m_drt->webPage(), latitude, longitude, accuracy);
812}
813
814void LayoutTestController::addMockSpeechInputResult(const QString& result, double confidence, const QString& language)
815{
816    // FIXME: Implement for speech input layout tests.
817    // See https://bugs.webkit.org/show_bug.cgi?id=39485.
818}
819
820void LayoutTestController::evaluateScriptInIsolatedWorld(int worldID, const QString& script)
821{
822    DumpRenderTreeSupportQt::evaluateScriptInIsolatedWorld(m_drt->webPage()->mainFrame(), worldID, script);
823}
824
825bool LayoutTestController::isPageBoxVisible(int pageIndex)
826{
827    return DumpRenderTreeSupportQt::isPageBoxVisible(m_drt->webPage()->mainFrame(), pageIndex);
828}
829
830QString LayoutTestController::pageSizeAndMarginsInPixels(int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
831{
832    return DumpRenderTreeSupportQt::pageSizeAndMarginsInPixels(m_drt->webPage()->mainFrame(), pageIndex,
833                                                               width, height, marginTop, marginRight, marginBottom, marginLeft);
834}
835
836QString LayoutTestController::pageProperty(const QString& propertyName, int pageNumber)
837{
838    return DumpRenderTreeSupportQt::pageProperty(m_drt->webPage()->mainFrame(), propertyName, pageNumber);
839}
840
841void LayoutTestController::addUserStyleSheet(const QString& sourceCode)
842{
843    DumpRenderTreeSupportQt::addUserStyleSheet(m_drt->webPage(), sourceCode);
844}
845
846void LayoutTestController::removeAllVisitedLinks()
847{
848    QWebHistory* history = m_drt->webPage()->history();
849    history->clear();
850    DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(true);
851}
852
853bool LayoutTestController::hasSpellingMarker(int, int)
854{
855    // FIXME: Implement.
856    return false;
857}
858
859QVariantList LayoutTestController::nodesFromRect(const QWebElement& document, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping)
860{
861    return DumpRenderTreeSupportQt::nodesFromRect(document, x, y, top, right, bottom, left, ignoreClipping);
862}
863
864void LayoutTestController::addURLToRedirect(const QString& origin, const QString& destination)
865{
866    DumpRenderTreeSupportQt::addURLToRedirect(origin, destination);
867}
868
869void LayoutTestController::setMinimumTimerInterval(double minimumTimerInterval)
870{
871    DumpRenderTreeSupportQt::setMinimumTimerInterval(m_drt->webPage(), minimumTimerInterval);
872}
873
874void LayoutTestController::originsWithLocalStorage()
875{
876    // FIXME: Implement.
877}
878
879void LayoutTestController::deleteAllLocalStorage()
880{
881    // FIXME: Implement.
882}
883
884void LayoutTestController::deleteLocalStorageForOrigin(const QString& originIdentifier)
885{
886    // FIXME: Implement.
887}
888
889void LayoutTestController::observeStorageTrackerNotifications(unsigned number)
890{
891    // FIXME: Implement.
892}
893
894void LayoutTestController::syncLocalStorage()
895{
896    // FIXME: Implement.
897}
898
899const unsigned LayoutTestController::maxViewWidth = 800;
900const unsigned LayoutTestController::maxViewHeight = 600;
901