Home | History | Annotate | Download | only in QtTestBrowser
      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