/*
 * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "DumpRenderTreeQt.h"
#include "DumpRenderTreeSupportQt.h"
#include "EventSenderQt.h"
#include "GCControllerQt.h"
#include "LayoutTestControllerQt.h"
#include "TextInputControllerQt.h"
#include "PlainTextControllerQt.h"
#include "testplugin.h"
#include "WorkQueue.h"

#include <QApplication>
#include <QBuffer>
#include <QCryptographicHash>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QFocusEvent>
#include <QFontDatabase>
#include <QLocale>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QPaintDevice>
#include <QPaintEngine>
#ifndef QT_NO_PRINTER
#include <QPrinter>
#endif
#include <QUndoStack>
#include <QUrl>

#include <qwebsettings.h>
#include <qwebsecurityorigin.h>

#ifndef QT_NO_UITOOLS
#include <QtUiTools/QUiLoader>
#endif

#ifdef Q_WS_X11
#include <fontconfig/fontconfig.h>
#endif

#include <limits.h>
#include <locale.h>

#ifndef Q_OS_WIN
#include <unistd.h>
#endif

#include <qdebug.h>

namespace WebCore {

const int databaseDefaultQuota = 5 * 1024 * 1024;

NetworkAccessManager::NetworkAccessManager(QObject* parent)
    : QNetworkAccessManager(parent)
{
#ifndef QT_NO_OPENSSL
    connect(this, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)),
            this, SLOT(sslErrorsEncountered(QNetworkReply*, const QList<QSslError>&)));
#endif
}

#ifndef QT_NO_OPENSSL
void NetworkAccessManager::sslErrorsEncountered(QNetworkReply* reply, const QList<QSslError>& errors)
{
    if (reply->url().host() == "127.0.0.1" || reply->url().host() == "localhost") {
        bool ignore = true;

        // Accept any HTTPS certificate.
        foreach (const QSslError& error, errors) {
            if (error.error() < QSslError::UnableToGetIssuerCertificate || error.error() > QSslError::HostNameMismatch) {
                ignore = false;
                break;
            }
        }

        if (ignore)
            reply->ignoreSslErrors();
    }
}
#endif


#ifndef QT_NO_PRINTER
class NullPrinter : public QPrinter {
public:
    class NullPaintEngine : public QPaintEngine {
    public:
        virtual bool begin(QPaintDevice*) { return true; }
        virtual bool end() { return true; }
        virtual QPaintEngine::Type type() const { return QPaintEngine::User; }
        virtual void drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr) { }
        virtual void updateState(const QPaintEngineState& state) { }
    };

    virtual QPaintEngine* paintEngine() const { return const_cast<NullPaintEngine*>(&m_engine); }

    NullPaintEngine m_engine;
};
#endif

WebPage::WebPage(QObject* parent, DumpRenderTree* drt)
    : QWebPage(parent)
    , m_webInspector(0)
    , m_drt(drt)
{
    QWebSettings* globalSettings = QWebSettings::globalSettings();

    globalSettings->setFontSize(QWebSettings::MinimumFontSize, 0);
    globalSettings->setFontSize(QWebSettings::MinimumLogicalFontSize, 5);
    globalSettings->setFontSize(QWebSettings::DefaultFontSize, 16);
    globalSettings->setFontSize(QWebSettings::DefaultFixedFontSize, 13);

    globalSettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
    globalSettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true);
    globalSettings->setAttribute(QWebSettings::LinksIncludedInFocusChain, false);
    globalSettings->setAttribute(QWebSettings::PluginsEnabled, true);
    globalSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
    globalSettings->setAttribute(QWebSettings::JavascriptEnabled, true);
    globalSettings->setAttribute(QWebSettings::PrivateBrowsingEnabled, false);
    globalSettings->setAttribute(QWebSettings::SpatialNavigationEnabled, false);

    connect(this, SIGNAL(geometryChangeRequested(const QRect &)),
            this, SLOT(setViewGeometry(const QRect & )));

    setNetworkAccessManager(m_drt->networkAccessManager());
    setPluginFactory(new TestPlugin(this));

    connect(this, SIGNAL(featurePermissionRequested(QWebFrame*, QWebPage::Feature)), this, SLOT(requestPermission(QWebFrame*, QWebPage::Feature)));
    connect(this, SIGNAL(featurePermissionRequestCanceled(QWebFrame*, QWebPage::Feature)), this, SLOT(cancelPermission(QWebFrame*, QWebPage::Feature)));
}

WebPage::~WebPage()
{
    delete m_webInspector;
}

QWebInspector* WebPage::webInspector()
{
    if (!m_webInspector) {
        m_webInspector = new QWebInspector;
        m_webInspector->setPage(this);
    }
    return m_webInspector;
}

void WebPage::resetSettings()
{
    // After each layout test, reset the settings that may have been changed by
    // layoutTestController.overridePreference() or similar.
    settings()->resetFontSize(QWebSettings::DefaultFontSize);
    settings()->resetAttribute(QWebSettings::JavascriptCanOpenWindows);
    settings()->resetAttribute(QWebSettings::JavascriptEnabled);
    settings()->resetAttribute(QWebSettings::PrivateBrowsingEnabled);
    settings()->resetAttribute(QWebSettings::SpatialNavigationEnabled);
    settings()->resetAttribute(QWebSettings::LinksIncludedInFocusChain);
    settings()->resetAttribute(QWebSettings::OfflineWebApplicationCacheEnabled);
    settings()->resetAttribute(QWebSettings::LocalContentCanAccessRemoteUrls);
    settings()->resetAttribute(QWebSettings::LocalContentCanAccessFileUrls);
    settings()->resetAttribute(QWebSettings::PluginsEnabled);
    settings()->resetAttribute(QWebSettings::JavascriptCanAccessClipboard);
    settings()->resetAttribute(QWebSettings::AutoLoadImages);

    m_drt->layoutTestController()->setCaretBrowsingEnabled(false);
    m_drt->layoutTestController()->setFrameFlatteningEnabled(false);
    m_drt->layoutTestController()->setSmartInsertDeleteEnabled(true);
    m_drt->layoutTestController()->setSelectTrailingWhitespaceEnabled(false);

    // globalSettings must be reset explicitly.
    m_drt->layoutTestController()->setXSSAuditorEnabled(false);

    QWebSettings::setMaximumPagesInCache(0); // reset to default
    settings()->setUserStyleSheetUrl(QUrl()); // reset to default

    DumpRenderTreeSupportQt::setMinimumTimerInterval(this, DumpRenderTreeSupportQt::defaultMinimumTimerInterval());

    m_pendingGeolocationRequests.clear();
}

QWebPage *WebPage::createWindow(QWebPage::WebWindowType)
{
    return m_drt->createWindow();
}

void WebPage::javaScriptAlert(QWebFrame*, const QString& message)
{
    if (!isTextOutputEnabled())
        return;

    fprintf(stdout, "ALERT: %s\n", message.toUtf8().constData());
}

void WebPage::requestPermission(QWebFrame* frame, QWebPage::Feature feature)
{
    switch (feature) {
    case Notifications:
        if (!m_drt->layoutTestController()->ignoreReqestForPermission())
            setFeaturePermission(frame, feature, PermissionGrantedByUser);
        break;
    case Geolocation:
        if (m_drt->layoutTestController()->isGeolocationPermissionSet())
            if (m_drt->layoutTestController()->geolocationPermission())
                setFeaturePermission(frame, feature, PermissionGrantedByUser);
            else
                setFeaturePermission(frame, feature, PermissionDeniedByUser);
        else
            m_pendingGeolocationRequests.append(frame);
        break;
    default:
        break;
    }
}

void WebPage::cancelPermission(QWebFrame* frame, QWebPage::Feature feature)
{
    switch (feature) {
    case Geolocation:
        m_pendingGeolocationRequests.removeOne(frame);
        break;
    default:
        break;
    }
}

void WebPage::permissionSet(QWebPage::Feature feature)
{
    switch (feature) {
    case Geolocation:
        {
        Q_ASSERT(m_drt->layoutTestController()->isGeolocationPermissionSet());
        foreach (QWebFrame* frame, m_pendingGeolocationRequests)
            if (m_drt->layoutTestController()->geolocationPermission())
                setFeaturePermission(frame, feature, PermissionGrantedByUser);
            else
                setFeaturePermission(frame, feature, PermissionDeniedByUser);

        m_pendingGeolocationRequests.clear();
        break;
        }
    default:
        break;
    }
}

static QString urlSuitableForTestResult(const QString& url)
{
    if (url.isEmpty() || !url.startsWith(QLatin1String("file://")))
        return url;

    return QFileInfo(url).fileName();
}

void WebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString&)
{
    if (!isTextOutputEnabled())
        return;

    QString newMessage;
    if (!message.isEmpty()) {
        newMessage = message;

        size_t fileProtocol = newMessage.indexOf(QLatin1String("file://"));
        if (fileProtocol != -1) {
            newMessage = newMessage.left(fileProtocol) + urlSuitableForTestResult(newMessage.mid(fileProtocol));
        }
    }

    fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, newMessage.toUtf8().constData());
}

bool WebPage::javaScriptConfirm(QWebFrame*, const QString& msg)
{
    if (!isTextOutputEnabled())
        return true;

    fprintf(stdout, "CONFIRM: %s\n", msg.toUtf8().constData());
    return true;
}

bool WebPage::javaScriptPrompt(QWebFrame*, const QString& msg, const QString& defaultValue, QString* result)
{
    if (!isTextOutputEnabled())
        return true;

    fprintf(stdout, "PROMPT: %s, default text: %s\n", msg.toUtf8().constData(), defaultValue.toUtf8().constData());
    *result = defaultValue;
    return true;
}

bool WebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, NavigationType type)
{
    if (m_drt->layoutTestController()->waitForPolicy()) {
        QString url = QString::fromUtf8(request.url().toEncoded());
        QString typeDescription;

        switch (type) {
        case NavigationTypeLinkClicked:
            typeDescription = "link clicked";
            break;
        case NavigationTypeFormSubmitted:
            typeDescription = "form submitted";
            break;
        case NavigationTypeBackOrForward:
            typeDescription = "back/forward";
            break;
        case NavigationTypeReload:
            typeDescription = "reload";
            break;
        case NavigationTypeFormResubmitted:
            typeDescription = "form resubmitted";
            break;
        case NavigationTypeOther:
            typeDescription = "other";
            break;
        default:
            typeDescription = "illegal value";
        }

        if (isTextOutputEnabled())
            fprintf(stdout, "Policy delegate: attempt to load %s with navigation type '%s'\n",
                    url.toUtf8().constData(), typeDescription.toUtf8().constData());

        m_drt->layoutTestController()->notifyDone();
    }
    return QWebPage::acceptNavigationRequest(frame, request, type);
}

bool WebPage::supportsExtension(QWebPage::Extension extension) const
{
    if (extension == QWebPage::ErrorPageExtension)
        return m_drt->layoutTestController()->shouldHandleErrorPages();

    return false;
}

bool WebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
{
    const QWebPage::ErrorPageExtensionOption* info = static_cast<const QWebPage::ErrorPageExtensionOption*>(option);

    // Lets handle error pages for the main frame for now.
    if (info->frame != mainFrame())
        return false;

    QWebPage::ErrorPageExtensionReturn* errorPage = static_cast<QWebPage::ErrorPageExtensionReturn*>(output);

    errorPage->content = QString("data:text/html,<body/>").toUtf8();

    return true;
}

QObject* WebPage::createPlugin(const QString& classId, const QUrl& url, const QStringList& paramNames, const QStringList& paramValues)
{
    Q_UNUSED(url);
    Q_UNUSED(paramNames);
    Q_UNUSED(paramValues);
#ifndef QT_NO_UITOOLS
    QUiLoader loader;
    return loader.createWidget(classId, view());
#else
    Q_UNUSED(classId);
    return 0;
#endif
}

void WebPage::setViewGeometry(const QRect& rect)
{
    if (WebViewGraphicsBased* v = qobject_cast<WebViewGraphicsBased*>(view()))
        v->scene()->setSceneRect(QRectF(rect));
    else if (QWidget *v = view())
        v->setGeometry(rect);
}

WebViewGraphicsBased::WebViewGraphicsBased(QWidget* parent)
    : m_item(new QGraphicsWebView)
{
    setScene(new QGraphicsScene(this));
    scene()->addItem(m_item);
}

DumpRenderTree::DumpRenderTree()
    : m_dumpPixels(false)
    , m_stdin(0)
    , m_enableTextOutput(false)
    , m_standAloneMode(false)
    , m_graphicsBased(false)
    , m_persistentStoragePath(QString(getenv("DUMPRENDERTREE_TEMP")))
{
    QByteArray viewMode = getenv("QT_DRT_WEBVIEW_MODE");
    if (viewMode == "graphics")
        setGraphicsBased(true);

    // Set running in DRT mode for qwebpage to create testable objects.
    DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(true);
    DumpRenderTreeSupportQt::overwritePluginDirectories();
    DumpRenderTreeSupportQt::activeMockDeviceOrientationClient(true);
    QWebSettings::enablePersistentStorage(m_persistentStoragePath);

    m_networkAccessManager = new NetworkAccessManager(this);
    // create our primary testing page/view.
    if (isGraphicsBased()) {
        WebViewGraphicsBased* view = new WebViewGraphicsBased(0);
        m_page = new WebPage(view, this);
        view->setPage(m_page);
        m_mainView = view;
    } else {
        QWebView* view = new QWebView(0);
        m_page = new WebPage(view, this);
        view->setPage(m_page);
        m_mainView = view;
    }
    // Use a frame group name for all pages created by DumpRenderTree to allow
    // testing of cross-page frame lookup.
    DumpRenderTreeSupportQt::webPageSetGroupName(m_page, "org.webkit.qt.DumpRenderTree");

    m_mainView->setContextMenuPolicy(Qt::NoContextMenu);
    m_mainView->resize(QSize(LayoutTestController::maxViewWidth, LayoutTestController::maxViewHeight));

    // clean up cache by resetting quota.
    qint64 quota = webPage()->settings()->offlineWebApplicationCacheQuota();
    webPage()->settings()->setOfflineWebApplicationCacheQuota(quota);

    // create our controllers. This has to be done before connectFrame,
    // as it exports there to the JavaScript DOM window.
    m_controller = new LayoutTestController(this);
    connect(m_controller, SIGNAL(showPage()), this, SLOT(showPage()));
    connect(m_controller, SIGNAL(hidePage()), this, SLOT(hidePage()));

    // async geolocation permission set by controller
    connect(m_controller, SIGNAL(geolocationPermissionSet()), this, SLOT(geolocationPermissionSet()));

    connect(m_controller, SIGNAL(done()), this, SLOT(dump()));
    m_eventSender = new EventSender(m_page);
    m_textInputController = new TextInputController(m_page);
    m_plainTextController = new PlainTextController(m_page);
    m_gcController = new GCController(m_page);

    // now connect our different signals
    connect(m_page, SIGNAL(frameCreated(QWebFrame *)),
            this, SLOT(connectFrame(QWebFrame *)));
    connectFrame(m_page->mainFrame());

    connect(m_page, SIGNAL(loadFinished(bool)),
            m_controller, SLOT(maybeDump(bool)));
    // We need to connect to loadStarted() because notifyDone should only
    // dump results itself when the last page loaded in the test has finished loading.
    connect(m_page, SIGNAL(loadStarted()),
            m_controller, SLOT(resetLoadFinished()));
    connect(m_page, SIGNAL(windowCloseRequested()), this, SLOT(windowCloseRequested()));
    connect(m_page, SIGNAL(printRequested(QWebFrame*)), this, SLOT(dryRunPrint(QWebFrame*)));

    connect(m_page->mainFrame(), SIGNAL(titleChanged(const QString&)),
            SLOT(titleChanged(const QString&)));
    connect(m_page, SIGNAL(databaseQuotaExceeded(QWebFrame*,QString)),
            this, SLOT(dumpDatabaseQuota(QWebFrame*,QString)));
    connect(m_page, SIGNAL(applicationCacheQuotaExceeded(QWebSecurityOrigin *, quint64)),
            this, SLOT(dumpApplicationCacheQuota(QWebSecurityOrigin *, quint64)));
    connect(m_page, SIGNAL(statusBarMessage(const QString&)),
            this, SLOT(statusBarMessage(const QString&)));

    QObject::connect(this, SIGNAL(quit()), qApp, SLOT(quit()), Qt::QueuedConnection);

    DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(true);
    QFocusEvent event(QEvent::FocusIn, Qt::ActiveWindowFocusReason);
    QApplication::sendEvent(m_mainView, &event);
}

DumpRenderTree::~DumpRenderTree()
{
    if (!m_redirectOutputFileName.isEmpty())
        fclose(stdout);
    if (!m_redirectErrorFileName.isEmpty())
        fclose(stderr);
    delete m_mainView;
    delete m_stdin;
    DumpRenderTreeSupportQt::removeMockDeviceOrientation();
}

static void clearHistory(QWebPage* page)
{
    // QWebHistory::clear() leaves current page, so remove it as well by setting
    // max item count to 0, and then setting it back to it's original value.

    QWebHistory* history = page->history();
    int itemCount = history->maximumItemCount();

    history->clear();
    history->setMaximumItemCount(0);
    history->setMaximumItemCount(itemCount);
}

void DumpRenderTree::dryRunPrint(QWebFrame* frame)
{
#ifndef QT_NO_PRINTER
    NullPrinter printer;
    frame->print(&printer);
#endif
}

void DumpRenderTree::resetToConsistentStateBeforeTesting(const QUrl& url)
{
    // reset so that any current loads are stopped
    // NOTE: that this has to be done before the layoutTestController is
    // reset or we get timeouts for some tests.
    m_page->blockSignals(true);
    m_page->triggerAction(QWebPage::Stop);
    m_page->blockSignals(false);

    QList<QWebSecurityOrigin> knownOrigins = QWebSecurityOrigin::allOrigins();
    for (int i = 0; i < knownOrigins.size(); ++i)
        knownOrigins[i].setDatabaseQuota(databaseDefaultQuota);

    // reset the layoutTestController at this point, so that we under no
    // circumstance dump (stop the waitUntilDone timer) during the reset
    // of the DRT.
    m_controller->reset();

    // reset mouse clicks counter
    m_eventSender->resetClickCount();

    closeRemainingWindows();

    m_page->resetSettings();
#ifndef QT_NO_UNDOSTACK
    m_page->undoStack()->clear();
#endif
    m_page->mainFrame()->setZoomFactor(1.0);
    clearHistory(m_page);
    DumpRenderTreeSupportQt::clearFrameName(m_page->mainFrame());

    m_page->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAsNeeded);
    m_page->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAsNeeded);

    if (url.scheme() == "http" || url.scheme() == "https") {
        // credentials may exist from previous tests.
        m_page->setNetworkAccessManager(0);
        delete m_networkAccessManager;
        m_networkAccessManager = new NetworkAccessManager(this);
        m_page->setNetworkAccessManager(m_networkAccessManager);
    }

    WorkQueue::shared()->clear();
    WorkQueue::shared()->setFrozen(false);

    DumpRenderTreeSupportQt::resetOriginAccessWhiteLists();

    // Qt defaults to Windows editing behavior.
    DumpRenderTreeSupportQt::setEditingBehavior(m_page, "win");

    QLocale::setDefault(QLocale::c());

    layoutTestController()->setDeveloperExtrasEnabled(true);
#ifndef Q_OS_WINCE
    setlocale(LC_ALL, "");
#endif

    DumpRenderTreeSupportQt::clearOpener(m_page->mainFrame());
}

static bool isGlobalHistoryTest(const QUrl& url)
{
    if (url.path().contains("globalhistory/"))
        return true;
    return false;
}

static bool isWebInspectorTest(const QUrl& url)
{
    if (url.path().contains("inspector/"))
        return true;
    return false;
}

static bool isDumpAsTextTest(const QUrl& url)
{
    if (url.path().contains("dumpAsText/"))
        return true;
    return false;
}


void DumpRenderTree::open(const QUrl& url)
{
    DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(QFileInfo(url.toString()).path());
    resetToConsistentStateBeforeTesting(url);

    if (isWebInspectorTest(m_page->mainFrame()->url()))
        layoutTestController()->closeWebInspector();

    if (isWebInspectorTest(url))
        layoutTestController()->showWebInspector();

    if (isDumpAsTextTest(url)) {
        layoutTestController()->dumpAsText();
        setDumpPixels(false);
    }

    if (isGlobalHistoryTest(url))
        layoutTestController()->dumpHistoryCallbacks();

    // W3C SVG tests expect to be 480x360
    bool isW3CTest = url.toString().contains("svg/W3C-SVG-1.1");
    int width = isW3CTest ? 480 : LayoutTestController::maxViewWidth;
    int height = isW3CTest ? 360 : LayoutTestController::maxViewHeight;
    m_mainView->resize(QSize(width, height));
    m_page->setPreferredContentsSize(QSize());
    m_page->setViewportSize(QSize(width, height));

    QFocusEvent ev(QEvent::FocusIn);
    m_page->event(&ev);

    QWebSettings::clearMemoryCaches();
#if !(defined(Q_OS_SYMBIAN) && QT_VERSION <= QT_VERSION_CHECK(4, 6, 2))
    QFontDatabase::removeAllApplicationFonts();
#endif
#if defined(Q_WS_X11)
    initializeFonts();
#endif

    DumpRenderTreeSupportQt::dumpFrameLoader(url.toString().contains("loading/"));
    setTextOutputEnabled(true);
    m_page->mainFrame()->load(url);
}

void DumpRenderTree::readLine()
{
    if (!m_stdin) {
        m_stdin = new QFile;
        m_stdin->open(stdin, QFile::ReadOnly);

        if (!m_stdin->isReadable()) {
            emit quit();
            return;
        }
    }

    QByteArray line = m_stdin->readLine().trimmed();

    if (line.isEmpty()) {
        emit quit();
        return;
    }

    processLine(QString::fromLocal8Bit(line.constData(), line.length()));
}

void DumpRenderTree::processArgsLine(const QStringList &args)
{
    setStandAloneMode(true);

    m_standAloneModeTestList = args;

    QFileInfo firstEntry(m_standAloneModeTestList.first());
    if (firstEntry.isDir()) {
        QDir folderEntry(m_standAloneModeTestList.first());
        QStringList supportedExt;
        // Check for all supported extensions (from Scripts/webkitpy/layout_tests/layout_package/test_files.py).
        supportedExt << "*.html" << "*.shtml" << "*.xml" << "*.xhtml" << "*.xhtmlmp" << "*.pl" << "*.php" << "*.svg";
        m_standAloneModeTestList = folderEntry.entryList(supportedExt, QDir::Files);
        for (int i = 0; i < m_standAloneModeTestList.size(); ++i)
            m_standAloneModeTestList[i] = folderEntry.absoluteFilePath(m_standAloneModeTestList[i]);
    }
    connect(this, SIGNAL(ready()), this, SLOT(loadNextTestInStandAloneMode()));

    if (!m_standAloneModeTestList.isEmpty()) {
        QString first = m_standAloneModeTestList.takeFirst();
        processLine(first);
    }
}

void DumpRenderTree::loadNextTestInStandAloneMode()
{
    if (m_standAloneModeTestList.isEmpty()) {
        emit quit();
        return;
    }
    QString first = m_standAloneModeTestList.takeFirst();
    processLine(first);
}

void DumpRenderTree::processLine(const QString &input)
{
    QString line = input;

    m_expectedHash = QString();
    if (m_dumpPixels) {
        // single quote marks the pixel dump hash
        int i = line.indexOf('\'');
        if (i > -1) {
            m_expectedHash = line.mid(i + 1, line.length());
            line.remove(i, line.length());
        }
    }

    if (line.startsWith(QLatin1String("http:"))
            || line.startsWith(QLatin1String("https:"))
            || line.startsWith(QLatin1String("file:"))) {
        open(QUrl(line));
    } else {
        QFileInfo fi(line);

        if (!fi.exists()) {
            QDir currentDir = QDir::currentPath();

            // Try to be smart about where the test is located
            if (currentDir.dirName() == QLatin1String("LayoutTests"))
                fi = QFileInfo(currentDir, line.replace(QRegExp(".*?LayoutTests/(.*)"), "\\1"));
            else if (!line.contains(QLatin1String("LayoutTests")))
                fi = QFileInfo(currentDir, line.prepend(QLatin1String("LayoutTests/")));

            if (!fi.exists()) {
                emit ready();
                return;
            }
        }

        open(QUrl::fromLocalFile(fi.absoluteFilePath()));
    }

    fflush(stdout);
}

void DumpRenderTree::setDumpPixels(bool dump)
{
    m_dumpPixels = dump;
}

void DumpRenderTree::closeRemainingWindows()
{
    foreach (QObject* widget, windows)
        delete widget;
    windows.clear();
}

void DumpRenderTree::initJSObjects()
{
    QWebFrame *frame = qobject_cast<QWebFrame*>(sender());
    Q_ASSERT(frame);
    frame->addToJavaScriptWindowObject(QLatin1String("layoutTestController"), m_controller);
    frame->addToJavaScriptWindowObject(QLatin1String("eventSender"), m_eventSender);
    frame->addToJavaScriptWindowObject(QLatin1String("textInputController"), m_textInputController);
    frame->addToJavaScriptWindowObject(QLatin1String("GCController"), m_gcController);
    frame->addToJavaScriptWindowObject(QLatin1String("plainText"), m_plainTextController);
}

void DumpRenderTree::showPage()
{
    m_mainView->show();
    // we need a paint event but cannot process all the events
    QPixmap pixmap(m_mainView->size());
    m_mainView->render(&pixmap);
}

void DumpRenderTree::hidePage()
{
    m_mainView->hide();
}

QString DumpRenderTree::dumpFrameScrollPosition(QWebFrame* frame)
{
    if (!frame || !DumpRenderTreeSupportQt::hasDocumentElement(frame))
        return QString();

    QString result;
    QPoint pos = frame->scrollPosition();
    if (pos.x() > 0 || pos.y() > 0) {
        QWebFrame* parent = qobject_cast<QWebFrame *>(frame->parent());
        if (parent)
            result.append(QString("frame '%1' ").arg(frame->title()));
        result.append(QString("scrolled to %1,%2\n").arg(pos.x()).arg(pos.y()));
    }

    if (m_controller->shouldDumpChildFrameScrollPositions()) {
        QList<QWebFrame*> children = frame->childFrames();
        for (int i = 0; i < children.size(); ++i)
            result += dumpFrameScrollPosition(children.at(i));
    }
    return result;
}

QString DumpRenderTree::dumpFramesAsText(QWebFrame* frame)
{
    if (!frame || !DumpRenderTreeSupportQt::hasDocumentElement(frame))
        return QString();

    QString result;
    QWebFrame* parent = qobject_cast<QWebFrame*>(frame->parent());
    if (parent) {
        result.append(QLatin1String("\n--------\nFrame: '"));
        result.append(frame->frameName());
        result.append(QLatin1String("'\n--------\n"));
    }

    QString innerText = frame->toPlainText();
    result.append(innerText);
    result.append(QLatin1String("\n"));

    if (m_controller->shouldDumpChildrenAsText()) {
        QList<QWebFrame *> children = frame->childFrames();
        for (int i = 0; i < children.size(); ++i)
            result += dumpFramesAsText(children.at(i));
    }

    return result;
}

static QString dumpHistoryItem(const QWebHistoryItem& item, int indent, bool current)
{
    QString result;

    int start = 0;
    if (current) {
        result.append(QLatin1String("curr->"));
        start = 6;
    }
    for (int i = start; i < indent; i++)
        result.append(' ');

    QString url = item.url().toEncoded();
    if (url.contains("file://")) {
        static QString layoutTestsString("/LayoutTests/");
        static QString fileTestString("(file test):");

        QString res = url.mid(url.indexOf(layoutTestsString) + layoutTestsString.length());
        if (res.isEmpty())
            return result;

        result.append(fileTestString);
        result.append(res);
    } else {
        result.append(url);
    }

    QString target = DumpRenderTreeSupportQt::historyItemTarget(item);
    if (!target.isEmpty())
        result.append(QString(QLatin1String(" (in frame \"%1\")")).arg(target));

    if (DumpRenderTreeSupportQt::isTargetItem(item))
        result.append(QLatin1String("  **nav target**"));
    result.append(QLatin1String("\n"));

    QMap<QString, QWebHistoryItem> children = DumpRenderTreeSupportQt::getChildHistoryItems(item);
    foreach (QWebHistoryItem item, children)
        result += dumpHistoryItem(item, 12, false);

    return result;
}

QString DumpRenderTree::dumpBackForwardList(QWebPage* page)
{
    QWebHistory* history = page->history();

    QString result;
    result.append(QLatin1String("\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**"

    int maxItems = history->maximumItemCount();

    foreach (const QWebHistoryItem item, history->backItems(maxItems)) {
        if (!item.isValid())
            continue;
        result.append(dumpHistoryItem(item, 8, false));
    }

    QWebHistoryItem item = history->currentItem();
    if (item.isValid())
        result.append(dumpHistoryItem(item, 8, true));

    foreach (const QWebHistoryItem item, history->forwardItems(maxItems)) {
        if (!item.isValid())
            continue;
        result.append(dumpHistoryItem(item, 8, false));
    }

    result.append(QLatin1String("===============================================\n"));
    return result;
}

static const char *methodNameStringForFailedTest(LayoutTestController *controller)
{
    const char *errorMessage;
    if (controller->shouldDumpAsText())
        errorMessage = "[documentElement innerText]";
    // FIXME: Add when we have support
    //else if (controller->dumpDOMAsWebArchive())
    //    errorMessage = "[[mainFrame DOMDocument] webArchive]";
    //else if (controller->dumpSourceAsWebArchive())
    //    errorMessage = "[[mainFrame dataSource] webArchive]";
    else
        errorMessage = "[mainFrame renderTreeAsExternalRepresentation]";

    return errorMessage;
}

void DumpRenderTree::dump()
{
    // Prevent any further frame load or resource load callbacks from appearing after we dump the result.
    DumpRenderTreeSupportQt::dumpFrameLoader(false);
    DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(false);

    QWebFrame *mainFrame = m_page->mainFrame();

    if (isStandAloneMode()) {
        QString markup = mainFrame->toHtml();
        fprintf(stdout, "Source:\n\n%s\n", markup.toUtf8().constData());
    }

    QString mimeType = DumpRenderTreeSupportQt::responseMimeType(mainFrame);
    if (mimeType == "text/plain")
        m_controller->dumpAsText();

    // Dump render text...
    QString resultString;
    if (m_controller->shouldDumpAsText())
        resultString = dumpFramesAsText(mainFrame);
    else {
        resultString = mainFrame->renderTreeDump();
        resultString += dumpFrameScrollPosition(mainFrame);
    }
    if (!resultString.isEmpty()) {
        fprintf(stdout, "Content-Type: text/plain\n");
        fprintf(stdout, "%s", resultString.toUtf8().constData());

        if (m_controller->shouldDumpBackForwardList()) {
            fprintf(stdout, "%s", dumpBackForwardList(webPage()).toUtf8().constData());
            foreach (QObject* widget, windows) {
                QWebPage* page = qobject_cast<QWebPage*>(widget->findChild<QWebPage*>());
                fprintf(stdout, "%s", dumpBackForwardList(page).toUtf8().constData());
            }
        }

    } else
        printf("ERROR: nil result from %s", methodNameStringForFailedTest(m_controller));

    // signal end of text block
    fputs("#EOF\n", stdout);
    fputs("#EOF\n", stderr);

    // FIXME: All other ports don't dump pixels, if generatePixelResults is false.
    if (m_dumpPixels) {
        QImage image(m_page->viewportSize(), QImage::Format_ARGB32);
        image.fill(Qt::white);
        QPainter painter(&image);
        mainFrame->render(&painter);
        painter.end();

        QCryptographicHash hash(QCryptographicHash::Md5);
        for (int row = 0; row < image.height(); ++row)
            hash.addData(reinterpret_cast<const char*>(image.scanLine(row)), image.width() * 4);
        QString actualHash = hash.result().toHex();

        fprintf(stdout, "\nActualHash: %s\n", qPrintable(actualHash));

        bool dumpImage = true;

        if (!m_expectedHash.isEmpty()) {
            Q_ASSERT(m_expectedHash.length() == 32);
            fprintf(stdout, "\nExpectedHash: %s\n", qPrintable(m_expectedHash));

            if (m_expectedHash == actualHash)
                dumpImage = false;
        }

        if (dumpImage) {
            image.setText("checksum", actualHash);

            QBuffer buffer;
            buffer.open(QBuffer::WriteOnly);
            image.save(&buffer, "PNG");
            buffer.close();
            const QByteArray &data = buffer.data();

            printf("Content-Type: %s\n", "image/png");
            printf("Content-Length: %lu\n", static_cast<unsigned long>(data.length()));

            const quint32 bytesToWriteInOneChunk = 1 << 15;
            quint32 dataRemainingToWrite = data.length();
            const char *ptr = data.data();
            while (dataRemainingToWrite) {
                quint32 bytesToWriteInThisChunk = qMin(dataRemainingToWrite, bytesToWriteInOneChunk);
                quint32 bytesWritten = fwrite(ptr, 1, bytesToWriteInThisChunk, stdout);
                if (bytesWritten != bytesToWriteInThisChunk)
                    break;
                dataRemainingToWrite -= bytesWritten;
                ptr += bytesWritten;
            }
        }

        fflush(stdout);
    }

    puts("#EOF");   // terminate the (possibly empty) pixels block

    fflush(stdout);
    fflush(stderr);

     emit ready();
}

void DumpRenderTree::titleChanged(const QString &s)
{
    if (m_controller->shouldDumpTitleChanges())
        printf("TITLE CHANGED: %s\n", s.toUtf8().data());
}

void DumpRenderTree::connectFrame(QWebFrame *frame)
{
    connect(frame, SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(initJSObjects()));
    connect(frame, SIGNAL(provisionalLoad()),
            layoutTestController(), SLOT(provisionalLoad()));
}

void DumpRenderTree::dumpDatabaseQuota(QWebFrame* frame, const QString& dbName)
{
    if (!m_controller->shouldDumpDatabaseCallbacks())
        return;
    QWebSecurityOrigin origin = frame->securityOrigin();
    printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n",
           origin.scheme().toUtf8().data(),
           origin.host().toUtf8().data(),
           origin.port(),
           dbName.toUtf8().data());
    origin.setDatabaseQuota(databaseDefaultQuota);
}

void DumpRenderTree::dumpApplicationCacheQuota(QWebSecurityOrigin* origin, quint64 defaultOriginQuota)
{
    if (!m_controller->shouldDumpApplicationCacheDelegateCallbacks())
        return;

    printf("UI DELEGATE APPLICATION CACHE CALLBACK: exceededApplicationCacheOriginQuotaForSecurityOrigin:{%s, %s, %i}\n",
           origin->scheme().toUtf8().data(),
           origin->host().toUtf8().data(),
           origin->port()
           );
    origin->setApplicationCacheQuota(defaultOriginQuota);
}

void DumpRenderTree::statusBarMessage(const QString& message)
{
    if (!m_controller->shouldDumpStatusCallbacks())
        return;

    printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", message.toUtf8().constData());
}

QWebPage *DumpRenderTree::createWindow()
{
    if (!m_controller->canOpenWindows())
        return 0;

    // Create a dummy container object to track the page in DRT.
    // QObject is used instead of QWidget to prevent DRT from
    // showing the main view when deleting the container.

    QObject* container = new QObject(m_mainView);
    // create a QWebPage we want to return
    QWebPage* page = static_cast<QWebPage*>(new WebPage(container, this));
    // gets cleaned up in closeRemainingWindows()
    windows.append(container);

    // connect the needed signals to the page
    connect(page, SIGNAL(frameCreated(QWebFrame*)), this, SLOT(connectFrame(QWebFrame*)));
    connectFrame(page->mainFrame());
    connect(page, SIGNAL(loadFinished(bool)), m_controller, SLOT(maybeDump(bool)));
    connect(page, SIGNAL(windowCloseRequested()), this, SLOT(windowCloseRequested()));

    // Use a frame group name for all pages created by DumpRenderTree to allow
    // testing of cross-page frame lookup.
    DumpRenderTreeSupportQt::webPageSetGroupName(page, "org.webkit.qt.DumpRenderTree");

    return page;
}

void DumpRenderTree::windowCloseRequested()
{
    QWebPage* page = qobject_cast<QWebPage*>(sender());
    QObject* container = page->parent();
    windows.removeAll(container);
    container->deleteLater();
}

int DumpRenderTree::windowCount() const
{
// include the main view in the count
    return windows.count() + 1;
}

void DumpRenderTree::geolocationPermissionSet() 
{
    m_page->permissionSet(QWebPage::Geolocation);
}

void DumpRenderTree::switchFocus(bool focused)
{
    QFocusEvent event((focused) ? QEvent::FocusIn : QEvent::FocusOut, Qt::ActiveWindowFocusReason);
    if (!isGraphicsBased())
        QApplication::sendEvent(m_mainView, &event);
    else {
        if (WebViewGraphicsBased* view = qobject_cast<WebViewGraphicsBased*>(m_mainView))
            view->scene()->sendEvent(view->graphicsView(), &event);
    }

}

QList<WebPage*> DumpRenderTree::getAllPages() const
{
    QList<WebPage*> pages;
    pages.append(m_page);
    foreach (QObject* widget, windows) {
        if (WebPage* page = widget->findChild<WebPage*>())
            pages.append(page);
    }
    return pages;
}

#if defined(Q_WS_X11)
void DumpRenderTree::initializeFonts()
{
    static int numFonts = -1;

    // Some test cases may add or remove application fonts (via @font-face).
    // Make sure to re-initialize the font set if necessary.
    FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication);
    if (appFontSet && numFonts >= 0 && appFontSet->nfont == numFonts)
        return;

    QByteArray fontDir = getenv("WEBKIT_TESTFONTS");
    if (fontDir.isEmpty() || !QDir(fontDir).exists()) {
        fprintf(stderr,
                "\n\n"
                "----------------------------------------------------------------------\n"
                "WEBKIT_TESTFONTS environment variable is not set correctly.\n"
                "This variable has to point to the directory containing the fonts\n"
                "you can clone from git://gitorious.org/qtwebkit/testfonts.git\n"
                "----------------------------------------------------------------------\n"
               );
        exit(1);
    }
    char currentPath[PATH_MAX+1];
    if (!getcwd(currentPath, PATH_MAX))
        qFatal("Couldn't get current working directory");
    QByteArray configFile = currentPath;
    FcConfig *config = FcConfigCreate();
    configFile += "/Tools/DumpRenderTree/qt/fonts.conf";
    if (!FcConfigParseAndLoad (config, (FcChar8*) configFile.data(), true))
        qFatal("Couldn't load font configuration file");
    if (!FcConfigAppFontAddDir (config, (FcChar8*) fontDir.data()))
        qFatal("Couldn't add font dir!");
    FcConfigSetCurrent(config);

    appFontSet = FcConfigGetFonts(config, FcSetApplication);
    numFonts = appFontSet->nfont;
}
#endif

}
