1 /* 2 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2009 Girish Ramakrishnan <girish (at) forwardbias.in> 4 * Copyright (C) 2006 George Staikos <staikos (at) kde.org> 5 * Copyright (C) 2006 Dirk Mueller <mueller (at) kde.org> 6 * Copyright (C) 2006 Zack Rusin <zack (at) kde.org> 7 * Copyright (C) 2006 Simon Hausmann <hausmann (at) 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. 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 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); 115 QStringList urls() const { return m_urls; } 116 bool isRobotized() const { return m_isRobotized; } 117 int robotTimeout() const { return m_robotTimeoutSeconds; } 118 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 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 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 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 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 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