Reviewed by Mitz. Landed by Niko.
[WebKit-https.git] / WebKitTools / DumpRenderTree / DumpRenderTree.qtproj / DumpRenderTree.cpp
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 "config.h"
31 #include "DumpRenderTree.h"
32
33 #include "Page.h"
34 #include "markup.h"
35 #include "Document.h"
36 #include "FrameView.h"
37 #include "KURL.h"
38 #include "FrameLoader.h"
39 #include "RenderTreeAsText.h"
40 #include "ChromeClientQt.h"
41 #include "ContextMenuClientQt.h"
42
43 #include <QDir>
44 #include <QFile>
45 #include <QTimer>
46 #include <QBoxLayout>
47 #include <QScrollArea>
48 #include <QApplication>
49
50 #include <unistd.h>
51
52 namespace WebCore {
53
54 // Choose some default values.
55 const unsigned int maxViewWidth = 800;
56 const unsigned int maxViewHeight = 600;
57
58 DumpRenderTree::DumpRenderTree()
59     : m_frame(0)
60     , m_client(new DumpRenderTreeClient())
61     , m_stdin(0)
62     , m_notifier()
63 {
64     // Initialize WebCore in Qt platform mode...
65     Page* page = new Page(new ChromeClientQt(), new ContextMenuClientQt());
66     m_frame = new FrameQt(page, 0, m_client);
67
68     FrameView* view = new FrameView(m_frame);
69     view->setScrollbarsMode(ScrollbarAlwaysOff);
70
71     m_frame->setView(view);
72     view->setParentWidget(0 /* no toplevel widget */);
73
74     // Reverse calculations in QAbstractScrollArea::maximumViewportSize()
75     QScrollArea* area = qobject_cast<QScrollArea*>(m_frame->view()->qwidget());
76
77     unsigned int viewWidth = maxViewWidth + 2 * area->frameWidth();
78     unsigned int viewHeight = maxViewHeight + 2 * area->frameWidth();
79
80     area->resize(viewWidth, viewHeight);
81
82     // Read file containing to be skipped tests...
83     readSkipFile();
84 }
85
86 DumpRenderTree::~DumpRenderTree()
87 {
88     delete m_frame;
89     delete m_client;
90
91     delete m_stdin;
92     delete m_notifier;
93 }
94
95 void DumpRenderTree::open()
96 {
97     if (!m_stdin)
98         m_stdin = new QTextStream(stdin, IO_ReadOnly);
99     
100     if (!m_notifier) {
101         m_notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read);
102         connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readStdin(int)));
103     }
104 }
105
106 void DumpRenderTree::open(const KURL& url)
107 {
108     Q_ASSERT(url.isLocalFile());
109
110     // Ignore skipped tests
111     if (m_skipped.indexOf(url.path()) != -1) { 
112         fprintf(stdout, "#EOF\n");
113         fflush(stdout);
114         return;
115     }
116
117     m_frame->client()->openURL(url);
118
119     // Simple poll mechanism, to find out when the page is loaded...
120     checkLoaded();
121 }
122
123 void DumpRenderTree::readStdin(int /* socket */)
124 {
125     // Read incoming data from stdin...
126     QString line = m_stdin->readLine(); 
127     if (!line.isEmpty()) 
128         open(KURL(line.toLatin1()));
129 }
130
131 void DumpRenderTree::readSkipFile()
132 {
133     Q_ASSERT(m_skipped.isEmpty());
134
135     QFile file("WebKitTools/DumpRenderTree/DumpRenderTree.qtproj/tests-skipped.txt");
136     if (!file.exists()) {
137         qFatal("Run DumpRenderTree from the source root directory!\n");
138         return;
139     }
140
141     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
142         qFatal("Couldn't read skip file!\n");
143         return;
144     }
145
146     QString testsPath = QDir::currentPath() + "/LayoutTests/";
147     while (!file.atEnd()) {
148         QByteArray line = file.readLine();
149
150         // Remove trailing line feed
151         line.chop(1);
152
153         // Ignore comments
154         if (line.isEmpty() || line.startsWith('#'))
155             continue;
156
157         m_skipped.append(testsPath + line);
158     }
159 }
160
161 void DumpRenderTree::checkLoaded()
162 {
163     if (m_frame->loader()->isComplete()) {
164         if (!m_notifier) {
165             // Dump markup in single file mode...
166             DeprecatedString markup = createMarkup(m_frame->document());
167             fprintf(stdout, "Source:\n\n%s\n", markup.ascii());
168         }
169
170         // Dump render text...
171         DeprecatedString renderDump = externalRepresentation(m_frame->renderer());
172         fprintf(stdout, "%s#EOF\n", renderDump.ascii());
173         fflush(stdout);
174
175         if (!m_notifier) {
176             // Exit now in single file mode...
177             QApplication::exit();
178         }
179     } else
180         QTimer::singleShot(10, this, SLOT(checkLoaded()));
181 }
182
183 FrameQt* DumpRenderTree::frame() const
184 {
185     return m_frame;
186 }
187
188 }
189
190 #include "DumpRenderTree.moc"