webengine/osswebengine/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
       
     3  * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
       
     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 
       
    30 #include "DumpRenderTree.h"
       
    31 #include "jsobjects.h"
       
    32 
       
    33 #include <QDir>
       
    34 #include <QFile>
       
    35 #include <QTimer>
       
    36 #include <QBoxLayout>
       
    37 #include <QScrollArea>
       
    38 #include <QApplication>
       
    39 #include <QUrl>
       
    40 
       
    41 #include <qwebpage.h>
       
    42 #include <qwebframe.h>
       
    43 #include <qwebsettings.h>
       
    44 
       
    45 #include <unistd.h>
       
    46 #include <qdebug.h>
       
    47 
       
    48 namespace WebCore {
       
    49 
       
    50 // Choose some default values.
       
    51 const unsigned int maxViewWidth = 800;
       
    52 const unsigned int maxViewHeight = 600;
       
    53 
       
    54 class WebFrame : public QWebFrame {
       
    55 public:
       
    56     WebFrame(QWebPage *parent, QWebFrameData *frameData)
       
    57         : QWebFrame(parent, frameData) {}
       
    58     WebFrame(QWebFrame *parent, QWebFrameData *frameData)
       
    59         : QWebFrame(parent, frameData) {}
       
    60 };
       
    61 
       
    62 class WebPage : public QWebPage {
       
    63 public:
       
    64     WebPage(QWidget *parent, DumpRenderTree *drt);
       
    65 
       
    66     QWebFrame *createFrame(QWebFrame *parentFrame, QWebFrameData *frameData);
       
    67     QWebPage *createWindow();
       
    68 
       
    69     void javaScriptAlert(QWebFrame *frame, const QString& message);
       
    70     void javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString& sourceID);
       
    71 
       
    72 private:
       
    73     DumpRenderTree *m_drt;
       
    74 };
       
    75 
       
    76 WebPage::WebPage(QWidget *parent, DumpRenderTree *drt)
       
    77     : QWebPage(parent), m_drt(drt)
       
    78 {
       
    79     QWebSettings s = settings();
       
    80     s.setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
       
    81     setSettings(s);
       
    82 }
       
    83 
       
    84 QWebFrame *WebPage::createFrame(QWebFrame *parentFrame, QWebFrameData *frameData)
       
    85 {
       
    86     if (parentFrame) {
       
    87         WebFrame *f = new WebFrame(parentFrame, frameData);
       
    88         connect(f, SIGNAL(cleared()), m_drt, SLOT(initJSObjects()));
       
    89         connect(f, SIGNAL(provisionalLoad()),
       
    90                 m_drt->layoutTestController(), SLOT(provisionalLoad()));
       
    91         return f;
       
    92     }
       
    93     WebFrame *f = new WebFrame(this, frameData);
       
    94 
       
    95     connect(f, SIGNAL(cleared()), m_drt, SLOT(initJSObjects()));
       
    96     connect(f, SIGNAL(provisionalLoad()),
       
    97             m_drt->layoutTestController(), SLOT(provisionalLoad()));
       
    98     connect(f, SIGNAL(loadDone(bool)),
       
    99             m_drt->layoutTestController(), SLOT(maybeDump(bool)));
       
   100 
       
   101     return f;
       
   102 }
       
   103 
       
   104 QWebPage *WebPage::createWindow()
       
   105 {
       
   106     return m_drt->createWindow();
       
   107 }
       
   108 
       
   109 void WebPage::javaScriptAlert(QWebFrame *frame, const QString& message)
       
   110 {
       
   111     fprintf(stdout, "ALERT: %s\n", message.toUtf8().constData());
       
   112 }
       
   113 
       
   114 void WebPage::javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString&)
       
   115 {
       
   116     fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.toUtf8().constData());
       
   117 }
       
   118 
       
   119 DumpRenderTree::DumpRenderTree()
       
   120     : m_stdin(0)
       
   121     , m_notifier(0)
       
   122 {
       
   123     m_controller = new LayoutTestController(this);
       
   124     connect(m_controller, SIGNAL(done()), this, SLOT(dump()), Qt::QueuedConnection);
       
   125 
       
   126     m_page = new WebPage(0, this);
       
   127     m_page->resize(maxViewWidth, maxViewHeight);
       
   128     m_page->mainFrame()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       
   129     m_page->mainFrame()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       
   130     connect(m_page, SIGNAL(titleChanged(const QString&)),
       
   131             SLOT(titleChanged(const QString&)));
       
   132 
       
   133     m_eventSender = new EventSender(m_page);
       
   134 
       
   135     QObject::connect(this, SIGNAL(quit()), qApp, SLOT(quit()), Qt::QueuedConnection);
       
   136 }
       
   137 
       
   138 DumpRenderTree::~DumpRenderTree()
       
   139 {
       
   140     delete m_page;
       
   141 
       
   142     delete m_stdin;
       
   143     delete m_notifier;
       
   144 }
       
   145 
       
   146 void DumpRenderTree::open()
       
   147 {
       
   148     if (!m_stdin) {
       
   149         m_stdin = new QFile;
       
   150         m_stdin->open(stdin, QFile::ReadOnly);
       
   151     }
       
   152 
       
   153     if (!m_notifier) {
       
   154         m_notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read);
       
   155         connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readStdin(int)));
       
   156     }
       
   157 }
       
   158 
       
   159 void DumpRenderTree::open(const QUrl& url)
       
   160 {
       
   161     resetJSObjects();
       
   162     m_page->open(url);
       
   163 }
       
   164 
       
   165 void DumpRenderTree::readStdin(int /* socket */)
       
   166 {
       
   167     // Read incoming data from stdin...
       
   168     QByteArray line = m_stdin->readLine();
       
   169     if (line.endsWith('\n'))
       
   170         line.truncate(line.size()-1);
       
   171     //fprintf(stderr, "\n    opening %s\n", line.constData());
       
   172     if (line.isEmpty())
       
   173         quit();
       
   174     QFileInfo fi(line);
       
   175     open(QUrl::fromLocalFile(fi.absoluteFilePath()));
       
   176     fflush(stdout);
       
   177 }
       
   178 
       
   179 void DumpRenderTree::resetJSObjects()
       
   180 {
       
   181     m_controller->reset();
       
   182     foreach(QWidget *widget, windows)
       
   183         delete widget;
       
   184     windows.clear();
       
   185 }
       
   186 
       
   187 void DumpRenderTree::initJSObjects()
       
   188 {
       
   189     QWebFrame *frame = qobject_cast<QWebFrame*>(sender());
       
   190     Q_ASSERT(frame);
       
   191     frame->addToJSWindowObject("layoutTestController", m_controller);
       
   192     frame->addToJSWindowObject("eventSender", m_eventSender);
       
   193 }
       
   194 
       
   195 
       
   196 QString DumpRenderTree::dumpFramesAsText(QWebFrame* frame)
       
   197 {
       
   198     if (!frame)
       
   199         return QString();
       
   200 
       
   201     QString result;
       
   202     QWebFrame *parent = qobject_cast<QWebFrame *>(frame->parent());
       
   203     if (parent) {
       
   204         result.append(QLatin1String("\n--------\nFrame: '"));
       
   205         result.append(frame->name());
       
   206         result.append(QLatin1String("'\n--------\n"));
       
   207     }
       
   208 
       
   209     result.append(frame->innerText());
       
   210     result.append(QLatin1String("\n"));
       
   211 
       
   212     if (m_controller->shouldDumpChildrenAsText()) {
       
   213         QList<QWebFrame *> children = frame->childFrames();
       
   214         for (int i = 0; i < children.size(); ++i)
       
   215             result += dumpFramesAsText(children.at(i));
       
   216     }
       
   217 
       
   218     return result;
       
   219 }
       
   220 
       
   221 void DumpRenderTree::dump()
       
   222 {
       
   223     QWebFrame *frame = m_page->mainFrame();
       
   224 
       
   225     //fprintf(stderr, "    Dumping\n");
       
   226     if (!m_notifier) {
       
   227         // Dump markup in single file mode...
       
   228         QString markup = frame->markup();
       
   229         fprintf(stdout, "Source:\n\n%s\n", markup.toUtf8().constData());
       
   230     }
       
   231 
       
   232     // Dump render text...
       
   233     QString renderDump;
       
   234     if (m_controller->shouldDumpAsText()) {
       
   235         renderDump = dumpFramesAsText(frame);
       
   236     } else {
       
   237         renderDump = frame->renderTreeDump();
       
   238     }
       
   239     if (renderDump.isEmpty()) {
       
   240         printf("ERROR: nil result from %s", m_controller->shouldDumpAsText() ? "[documentElement innerText]" : "[frame renderTreeAsExternalRepresentation]");
       
   241     } else {
       
   242         fprintf(stdout, "%s", renderDump.toUtf8().constData());
       
   243     }
       
   244 
       
   245     fprintf(stdout, "#EOF\n");
       
   246 
       
   247     fflush(stdout);
       
   248 
       
   249     if (!m_notifier) {
       
   250         // Exit now in single file mode...
       
   251         quit();
       
   252     }
       
   253 }
       
   254 
       
   255 void DumpRenderTree::titleChanged(const QString &s)
       
   256 {
       
   257     if (m_controller->shouldDumpTitleChanges())
       
   258         printf("TITLE CHANGED: %s\n", s.toUtf8().data());
       
   259 }
       
   260 
       
   261 
       
   262 QWebPage *DumpRenderTree::createWindow()
       
   263 {
       
   264     if (!m_controller->canOpenWindows())
       
   265         return 0;
       
   266     QWidget *container = new QWidget(0);
       
   267     container->resize(0, 0);
       
   268     container->move(-1, -1);
       
   269     container->hide();
       
   270     QWebPage *page = new WebPage(container, this);
       
   271     windows.append(container);
       
   272     return page;
       
   273 }
       
   274 
       
   275 int DumpRenderTree::windowCount() const
       
   276 {
       
   277     int count = 0;
       
   278     foreach(QWidget *w, windows) {
       
   279         if (w->children().count())
       
   280             ++count;
       
   281     }
       
   282     return count + 1;
       
   283 }
       
   284 
       
   285 }