1 /*
2 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
3 * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
4 * Copyright (C) 2006 George Staikos <staikos@kde.org>
5 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
7 * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "launcherwindow.h"
34 #include "urlloader.h"
35
36 WindowOptions windowOptions;
37
38
39 #include <QDir>
40 #include <QFile>
41 #include <QFileInfo>
42 #include <QFontDatabase>
43
44
45 #if defined(Q_WS_X11)
46 #include <fontconfig/fontconfig.h>
47 #endif
48
49
50 #if defined(Q_WS_X11)
51 // Very similar to WebCore::DumpRenderTree::initializeFonts();
52 // Duplicated here so that QtTestBrowser would display contents
53 // with the same fonts as run-webkit-tests/DumpRenderTree.
initTestFonts()54 static void initTestFonts()
55 {
56 static int numFonts = -1;
57
58 // Some test cases may add or remove application fonts (via @font-face).
59 // Make sure to re-initialize the font set if necessary.
60 FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication);
61 if (appFontSet && numFonts >= 0 && appFontSet->nfont == numFonts)
62 return;
63
64 QByteArray fontDir = getenv("WEBKIT_TESTFONTS");
65 if (fontDir.isEmpty() || !QDir(fontDir).exists()) {
66 fprintf(stderr,
67 "\n\n"
68 "----------------------------------------------------------------------\n"
69 "WEBKIT_TESTFONTS environment variable is not set correctly.\n"
70 "This variable has to point to the directory containing the fonts\n"
71 "you can clone from git://gitorious.org/qtwebkit/testfonts.git\n"
72 "----------------------------------------------------------------------\n"
73 );
74 exit(1);
75 }
76 // Looks for qt/fonts.conf relative to the directory of the QtTestBrowser
77 // executable.
78 QString configFileString = QCoreApplication::applicationDirPath();
79 configFileString += "/../../../Tools/DumpRenderTree/qt/fonts.conf";
80 QByteArray configFileArray = configFileString.toUtf8();
81 FcConfig* config = FcConfigCreate();
82 if (!FcConfigParseAndLoad (config, (FcChar8*) configFileArray.data(), true))
83 qFatal("Couldn't load font configuration file");
84 if (!FcConfigAppFontAddDir (config, (FcChar8*) fontDir.data()))
85 qFatal("Couldn't add font dir!");
86 FcConfigSetCurrent(config);
87
88 appFontSet = FcConfigGetFonts(config, FcSetApplication);
89 numFonts = appFontSet->nfont;
90 }
91 #endif
92
launcherMain(const QApplication & app)93 int launcherMain(const QApplication& app)
94 {
95 #ifdef Q_WS_X11
96 if (windowOptions.useTestFonts)
97 initTestFonts();
98 #endif
99
100 #ifndef NDEBUG
101 int retVal = app.exec();
102 DumpRenderTreeSupportQt::garbageCollectorCollect();
103 QWebSettings::clearMemoryCaches();
104 return retVal;
105 #else
106 return app.exec();
107 #endif
108 }
109
110 class LauncherApplication : public QApplication {
111 Q_OBJECT
112
113 public:
114 LauncherApplication(int& argc, char** argv);
urls() const115 QStringList urls() const { return m_urls; }
isRobotized() const116 bool isRobotized() const { return m_isRobotized; }
robotTimeout() const117 int robotTimeout() const { return m_robotTimeoutSeconds; }
robotExtraTime() const118 int robotExtraTime() const { return m_robotExtraTimeSeconds; }
119
120 private:
121 void handleUserOptions();
122 void applyDefaultSettings();
123
124 private:
125 bool m_isRobotized;
126 int m_robotTimeoutSeconds;
127 int m_robotExtraTimeSeconds;
128 QStringList m_urls;
129 };
130
applyDefaultSettings()131 void LauncherApplication::applyDefaultSettings()
132 {
133 QWebSettings::setMaximumPagesInCache(4);
134
135 QWebSettings::setObjectCacheCapacities((16*1024*1024) / 8, (16*1024*1024) / 8, 16*1024*1024);
136
137 QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);
138 QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
139 QWebSettings::enablePersistentStorage();
140 }
141
LauncherApplication(int & argc,char ** argv)142 LauncherApplication::LauncherApplication(int& argc, char** argv)
143 : QApplication(argc, argv, QApplication::GuiServer)
144 , m_isRobotized(false)
145 , m_robotTimeoutSeconds(0)
146 , m_robotExtraTimeSeconds(0)
147 {
148 // To allow QWebInspector's configuration persistence
149 setOrganizationName("Nokia");
150 setApplicationName("QtTestBrowser");
151 setApplicationVersion("0.1");
152
153 applyDefaultSettings();
154
155 handleUserOptions();
156 }
157
requiresGraphicsView(const QString & option)158 static void requiresGraphicsView(const QString& option)
159 {
160 if (windowOptions.useGraphicsView)
161 return;
162 appQuit(1, QString("%1 only works in combination with the -graphicsbased option").arg(option));
163 }
164
handleUserOptions()165 void LauncherApplication::handleUserOptions()
166 {
167 QStringList args = arguments();
168 QFileInfo program(args.at(0));
169 QString programName("QtTestBrowser");
170 if (program.exists())
171 programName = program.baseName();
172
173 QList<QString> updateModes(enumToKeys(QGraphicsView::staticMetaObject,
174 "ViewportUpdateMode", "ViewportUpdate"));
175
176 if (args.contains("-help")) {
177 qDebug() << "Usage:" << programName.toLatin1().data()
178 << "[-graphicsbased]"
179 << "[-no-compositing]"
180 #if defined(QT_CONFIGURED_WITH_OPENGL)
181 << "[-gl-viewport]"
182 << "[-webgl]"
183 #endif
184 << QString("[-viewport-update-mode %1]").arg(formatKeys(updateModes)).toLatin1().data()
185 << "[-cache-webview]"
186 << "[-maximize]"
187 << "[-show-fps]"
188 << "[-r list]"
189 << "[-robot-timeout seconds]"
190 << "[-robot-extra-time seconds]"
191 << "[-inspector-url location]"
192 << "[-tiled-backing-store]"
193 << "[-resizes-to-contents]"
194 << "[-local-storage-enabled]"
195 << "[-offline-storage-database-enabled]"
196 << "[-offline-web-application-cache-enabled]"
197 << "[-set-offline-storage-default-quota maxSize]"
198 #if defined(Q_WS_X11)
199 << "[-use-test-fonts]"
200 #endif
201 << "[-print-loaded-urls]"
202 << "URLs";
203 appQuit(0);
204 }
205
206 const bool defaultForAnimations = args.contains("-default-animations");
207 if (args.contains("-graphicsbased") || defaultForAnimations)
208 windowOptions.useGraphicsView = true;
209
210 if (args.contains("-no-compositing")) {
211 requiresGraphicsView("-no-compositing");
212 windowOptions.useCompositing = false;
213 }
214
215 if (args.contains("-show-fps")) {
216 requiresGraphicsView("-show-fps");
217 windowOptions.showFrameRate = true;
218 }
219
220 if (args.contains("-cache-webview") || defaultForAnimations) {
221 requiresGraphicsView("-cache-webview");
222 windowOptions.cacheWebView = true;
223 }
224
225 if (args.contains("-tiled-backing-store")) {
226 requiresGraphicsView("-tiled-backing-store");
227 windowOptions.useTiledBackingStore = true;
228 }
229
230 if (args.contains("-resizes-to-contents")) {
231 requiresGraphicsView("-resizes-to-contents");
232 windowOptions.resizesToContents = true;
233 }
234
235 if (args.contains("-local-storage-enabled"))
236 windowOptions.useLocalStorage = true;
237
238 if (args.contains("-maximize"))
239 windowOptions.startMaximized = true;
240
241 if (args.contains("-offline-storage-database-enabled"))
242 windowOptions.useOfflineStorageDatabase = true;
243
244 if (args.contains("-offline-web-application-cache-enabled"))
245 windowOptions.useOfflineWebApplicationCache = true;
246
247 int setOfflineStorageDefaultQuotaIndex = args.indexOf("-set-offline-storage-default-quota");
248 if (setOfflineStorageDefaultQuotaIndex != -1) {
249 unsigned int maxSize = takeOptionValue(&args, setOfflineStorageDefaultQuotaIndex).toUInt();
250 windowOptions.offlineStorageDefaultQuotaSize = maxSize;
251 }
252
253 if (defaultForAnimations)
254 windowOptions.viewportUpdateMode = QGraphicsView::BoundingRectViewportUpdate;
255
256 QString arg1("-viewport-update-mode");
257 int modeIndex = args.indexOf(arg1);
258 if (modeIndex != -1) {
259 requiresGraphicsView(arg1);
260
261 QString mode = takeOptionValue(&args, modeIndex);
262 if (mode.isEmpty())
263 appQuit(1, QString("%1 needs a value of one of [%2]").arg(arg1).arg(formatKeys(updateModes)));
264 int idx = updateModes.indexOf(mode);
265 if (idx == -1)
266 appQuit(1, QString("%1 value has to be one of [%2]").arg(arg1).arg(formatKeys(updateModes)));
267
268 windowOptions.viewportUpdateMode = static_cast<QGraphicsView::ViewportUpdateMode>(idx);
269 }
270 #ifdef QT_CONFIGURED_WITH_OPENGL
271 if (args.contains("-gl-viewport") || defaultForAnimations) {
272 requiresGraphicsView("-gl-viewport");
273 windowOptions.useQGLWidgetViewport = true;
274 }
275
276 if (args.contains("-webgl")) {
277 requiresGraphicsView("-webgl");
278 windowOptions.useWebGL = true;
279 }
280 #endif
281
282 #if defined(Q_WS_X11)
283 if (args.contains("-use-test-fonts"))
284 windowOptions.useTestFonts = true;
285 #endif
286
287 if (args.contains("-print-loaded-urls"))
288 windowOptions.printLoadedUrls = true;
289
290 QString inspectorUrlArg("-inspector-url");
291 int inspectorUrlIndex = args.indexOf(inspectorUrlArg);
292 if (inspectorUrlIndex != -1)
293 windowOptions.inspectorUrl = takeOptionValue(&args, inspectorUrlIndex);
294
295 QString remoteInspectorPortArg("-remote-inspector-port");
296 int remoteInspectorPortIndex = args.indexOf(remoteInspectorPortArg);
297 if (remoteInspectorPortIndex != -1)
298 windowOptions.remoteInspectorPort = takeOptionValue(&args, remoteInspectorPortIndex).toInt();
299
300 int robotIndex = args.indexOf("-r");
301 if (robotIndex != -1) {
302 QString listFile = takeOptionValue(&args, robotIndex);
303 if (listFile.isEmpty())
304 appQuit(1, "-r needs a list file to start in robotized mode");
305 if (!QFile::exists(listFile))
306 appQuit(1, "The list file supplied to -r does not exist.");
307
308 m_isRobotized = true;
309 m_urls = QStringList(listFile);
310 } else {
311 int lastArg = args.lastIndexOf(QRegExp("^-.*"));
312 m_urls = (lastArg != -1) ? args.mid(++lastArg) : args.mid(1);
313 }
314
315 int robotTimeoutIndex = args.indexOf("-robot-timeout");
316 if (robotTimeoutIndex != -1)
317 m_robotTimeoutSeconds = takeOptionValue(&args, robotTimeoutIndex).toInt();
318
319 int robotExtraTimeIndex = args.indexOf("-robot-extra-time");
320 if (robotExtraTimeIndex != -1)
321 m_robotExtraTimeSeconds = takeOptionValue(&args, robotExtraTimeIndex).toInt();
322 }
323
324
main(int argc,char ** argv)325 int main(int argc, char **argv)
326 {
327 LauncherApplication app(argc, argv);
328
329 if (app.isRobotized()) {
330 LauncherWindow* window = new LauncherWindow();
331 UrlLoader loader(window->page()->mainFrame(), app.urls().at(0), app.robotTimeout(), app.robotExtraTime());
332 loader.loadNext();
333 window->show();
334 return launcherMain(app);
335 }
336
337 QStringList urls = app.urls();
338
339 if (urls.isEmpty()) {
340 QString defaultIndexFile = QString("%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html"));
341 if (QFile(defaultIndexFile).exists())
342 urls.append(QString("file://") + defaultIndexFile);
343 else
344 urls.append("");
345 }
346
347 LauncherWindow* window = 0;
348 foreach (QString url, urls) {
349 LauncherWindow* newWindow;
350 if (!window)
351 newWindow = window = new LauncherWindow(&windowOptions);
352 else
353 newWindow = window->newWindow();
354
355 newWindow->load(url);
356 }
357
358 window->show();
359 return launcherMain(app);
360 }
361
362 #include "main.moc"
363