diff options
Diffstat (limited to 'WebKit/qt/tests/qwebpage/tst_qwebpage.cpp')
| -rw-r--r-- | WebKit/qt/tests/qwebpage/tst_qwebpage.cpp | 688 |
1 files changed, 656 insertions, 32 deletions
diff --git a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index 966f049..2a52631 100644 --- a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -1,5 +1,6 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -20,8 +21,13 @@ #include <QtTest/QtTest> +#include <qgraphicsscene.h> +#include <qgraphicsview.h> +#include <qgraphicswebview.h> +#include <qwebelement.h> #include <qwebpage.h> #include <qwidget.h> +#include <QGraphicsWidget> #include <qwebview.h> #include <qwebframe.h> #include <qwebhistory.h> @@ -32,6 +38,11 @@ #include <qwebsecurityorigin.h> #include <qwebdatabase.h> #include <QPushButton> +#include <QDir> + +#if defined(Q_OS_SYMBIAN) +# define SRCDIR "" +#endif // Will try to wait for the condition while allowing event processing #define QTRY_COMPARE(__expr, __expected) \ @@ -59,7 +70,7 @@ * \return \p true if the requested signal was received * \p false on timeout */ -static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0) +static bool waitForSignal(QObject* obj, const char* signal, int timeout = 10000) { QEventLoop loop; QObject::connect(obj, signal, &loop, SLOT(quit())); @@ -74,6 +85,22 @@ static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0) return timeoutSpy.isEmpty(); } +class EventSpy : public QObject, public QList<QEvent::Type> +{ + Q_OBJECT +public: + EventSpy(QObject* objectToSpy) + { + objectToSpy->installEventFilter(this); + } + + virtual bool eventFilter(QObject* receiver, QEvent* event) + { + append(event->type()); + return false; + } +}; + class tst_QWebPage : public QObject { Q_OBJECT @@ -100,7 +127,9 @@ private slots: void contextMenuCrash(); void database(); void createPlugin(); + void destroyPlugin_data(); void destroyPlugin(); + void createViewlessPlugin_data(); void createViewlessPlugin(); void multiplePageGroupsAndLocalStorage(); void cursorMovements(); @@ -110,9 +139,23 @@ private slots: void frameAt(); void requestCache(); void protectBindingsRuntimeObjectsFromCollector(); + void localURLSchemes(); + void testOptionalJSObjects(); + void testEnablePersistentStorage(); + void consoleOutput(); + void inputMethods_data(); + void inputMethods(); + void defaultTextEncoding(); + void errorPageExtension(); + void errorPageExtensionInIFrames(); + void errorPageExtensionInFrameset(); -private: + void crashTests_LazyInitializationOfMainFrame(); + + void screenshot_data(); + void screenshot(); + void originatingObjectInNetworkRequests(); private: QWebView* m_view; @@ -217,6 +260,8 @@ void tst_QWebPage::infiniteLoopJS() void tst_QWebPage::loadFinished() { + qRegisterMetaType<QWebFrame*>("QWebFrame*"); + qRegisterMetaType<QNetworkRequest*>("QNetworkRequest*"); QSignalSpy spyLoadStarted(m_view, SIGNAL(loadStarted())); QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); @@ -238,6 +283,31 @@ void tst_QWebPage::loadFinished() QCOMPARE(spyLoadFinished.count(), 1); } +class ConsolePage : public QWebPage +{ +public: + ConsolePage(QObject* parent = 0) : QWebPage(parent) {} + + virtual void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID) + { + messages.append(message); + lineNumbers.append(lineNumber); + sourceIDs.append(sourceID); + } + + QStringList messages; + QList<int> lineNumbers; + QStringList sourceIDs; +}; + +void tst_QWebPage::consoleOutput() +{ + ConsolePage page; + page.mainFrame()->evaluateJavaScript("this is not valid JavaScript"); + QCOMPARE(page.messages.count(), 1); + QCOMPARE(page.lineNumbers.at(0), 1); +} + class TestPage : public QWebPage { public: @@ -302,9 +372,11 @@ public: TestNetworkManager(QObject* parent) : QNetworkAccessManager(parent) {} QList<QUrl> requestedUrls; + QList<QNetworkRequest> requests; protected: virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest &request, QIODevice* outgoingData) { + requests.append(request); requestedUrls.append(request.url()); return QNetworkAccessManager::createRequest(op, request, outgoingData); } @@ -316,13 +388,13 @@ void tst_QWebPage::userStyleSheet() m_page->setNetworkAccessManager(networkManager); networkManager->requestedUrls.clear(); - m_page->settings()->setUserStyleSheetUrl(QUrl("data:text/css,p { background-image: url('http://does.not/exist.png');}")); + m_page->settings()->setUserStyleSheetUrl(QUrl("data:text/css;charset=utf-8;base64," + + QByteArray("p { background-image: url('http://does.not/exist.png');}").toBase64())); m_view->setHtml("<p>hello world</p>"); QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); - QVERIFY(networkManager->requestedUrls.count() >= 2); - QCOMPARE(networkManager->requestedUrls.at(0), QUrl("data:text/css,p { background-image: url('http://does.not/exist.png');}")); - QCOMPARE(networkManager->requestedUrls.at(1), QUrl("http://does.not/exist.png")); + QVERIFY(networkManager->requestedUrls.count() >= 1); + QCOMPARE(networkManager->requestedUrls.at(0), QUrl("http://does.not/exist.png")); } void tst_QWebPage::modified() @@ -378,7 +450,7 @@ void tst_QWebPage::modified() m_page->mainFrame()->setUrl(QUrl("data:text/html,<body>This is fourth page")); QVERIFY(m_page->history()->count() == 2); m_page->mainFrame()->setUrl(QUrl("data:text/html,<body>This is fifth page")); - QVERIFY(::waitForSignal(m_page, SIGNAL(saveFrameStateRequested(QWebFrame*, QWebHistoryItem*)))); + QVERIFY(::waitForSignal(m_page, SIGNAL(saveFrameStateRequested(QWebFrame*,QWebHistoryItem*)))); } void tst_QWebPage::contextMenuCrash() @@ -405,13 +477,16 @@ void tst_QWebPage::database() QWebSettings::setOfflineStorageDefaultQuota(1024 * 1024); QVERIFY(QWebSettings::offlineStorageDefaultQuota() == 1024 * 1024); + m_page->settings()->setAttribute(QWebSettings::LocalStorageEnabled, true); + m_page->settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true); + QString dbFileName = path + "Databases.db"; if (QFile::exists(dbFileName)) QFile::remove(dbFileName); qRegisterMetaType<QWebFrame*>("QWebFrame*"); - QSignalSpy spy(m_page, SIGNAL(databaseQuotaExceeded(QWebFrame *, QString))); + QSignalSpy spy(m_page, SIGNAL(databaseQuotaExceeded(QWebFrame*,QString))); m_view->setHtml(QString("<html><head><script>var db; db=openDatabase('testdb', '1.0', 'test database API', 50000); </script></head><body><div></div></body></html>"), QUrl("http://www.myexample.com")); QTRY_COMPARE(spy.count(), 1); m_page->mainFrame()->evaluateJavaScript("var db2; db2=openDatabase('testdb', '1.0', 'test database API', 50000);"); @@ -432,14 +507,19 @@ void tst_QWebPage::database() m_page->mainFrame()->evaluateJavaScript("var db3; db3=openDatabase('testdb', '1.0', 'test database API', 50000);db3.transaction(function(tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS Test (text TEXT)', []); }, function(tx, result) { }, function(tx, error) { });"); QTest::qWait(200); + // Remove all databases. QWebSecurityOrigin origin = m_page->mainFrame()->securityOrigin(); QList<QWebDatabase> dbs = origin.databases(); - if (dbs.count() > 0) { - QString fileName = dbs[0].fileName(); + for (int i = 0; i < dbs.count(); i++) { + QString fileName = dbs[i].fileName(); QVERIFY(QFile::exists(fileName)); - QWebDatabase::removeDatabase(dbs[0]); + QWebDatabase::removeDatabase(dbs[i]); QVERIFY(!QFile::exists(fileName)); } + QVERIFY(!origin.databases().size()); + // Remove removed test :-) + QWebDatabase::removeAllDatabases(); + QVERIFY(!origin.databases().size()); QTest::qWait(1000); } @@ -578,56 +658,121 @@ void tst_QWebPage::createPlugin() QCOMPARE(newPage->calls.count(), 0); } -class PluginTrackedPage : public QWebPage -{ + +// Standard base class for template PluginTracerPage. In tests it is used as interface. +class PluginCounterPage : public QWebPage { public: + int m_count; + QPointer<QObject> m_widget; + QObject* m_pluginParent; + PluginCounterPage(QObject* parent = 0) + : QWebPage(parent) + , m_count(0) + , m_widget(0) + , m_pluginParent(0) + { + settings()->setAttribute(QWebSettings::PluginsEnabled, true); + } + ~PluginCounterPage() + { + if (m_pluginParent) + m_pluginParent->deleteLater(); + } +}; - int count; - QPointer<QWidget> widget; +template<class T> +class PluginTracerPage : public PluginCounterPage { +public: + PluginTracerPage(QObject* parent = 0) + : PluginCounterPage(parent) + { + // this is a dummy parent object for the created plugin + m_pluginParent = new T; + } + virtual QObject* createPlugin(const QString&, const QUrl&, const QStringList&, const QStringList&) + { + m_count++; + m_widget = new T; + // need a cast to the specific type, as QObject::setParent cannot be called, + // because it is not virtual. Instead it is necesary to call QWidget::setParent, + // which also takes a QWidget* instead of a QObject*. Therefore we need to + // upcast to T*, which is a QWidget. + static_cast<T*>(m_widget.data())->setParent(static_cast<T*>(m_pluginParent)); + return m_widget; + } +}; - PluginTrackedPage(QWidget *parent = 0) : QWebPage(parent), count(0) { - settings()->setAttribute(QWebSettings::PluginsEnabled, true); +class PluginFactory { +public: + enum FactoredType {QWidgetType, QGraphicsWidgetType}; + static PluginCounterPage* create(FactoredType type, QObject* parent = 0) + { + PluginCounterPage* result = 0; + switch (type) { + case QWidgetType: + result = new PluginTracerPage<QWidget>(parent); + break; + case QGraphicsWidgetType: + result = new PluginTracerPage<QGraphicsWidget>(parent); + break; + default: {/*Oops*/}; + } + return result; } - virtual QObject* createPlugin(const QString&, const QUrl&, const QStringList&, const QStringList&) { - count++; - QWidget *w = new QWidget; - widget = w; - return w; + static void prepareTestData() + { + QTest::addColumn<int>("type"); + QTest::newRow("QWidget") << (int)PluginFactory::QWidgetType; + QTest::newRow("QGraphicsWidget") << (int)PluginFactory::QGraphicsWidgetType; } }; +void tst_QWebPage::destroyPlugin_data() +{ + PluginFactory::prepareTestData(); +} + void tst_QWebPage::destroyPlugin() { - PluginTrackedPage* page = new PluginTrackedPage(m_view); + QFETCH(int, type); + PluginCounterPage* page = PluginFactory::create((PluginFactory::FactoredType)type, m_view); m_view->setPage(page); // we create the plugin, so the widget should be constructed QString content("<html><body><object type=\"application/x-qt-plugin\" classid=\"QProgressBar\"></object></body></html>"); m_view->setHtml(content); - QVERIFY(page->widget != 0); - QCOMPARE(page->count, 1); + QVERIFY(page->m_widget); + QCOMPARE(page->m_count, 1); // navigate away, the plugin widget should be destructed m_view->setHtml("<html><body>Hi</body></html>"); QTestEventLoop::instance().enterLoop(1); - QVERIFY(page->widget == 0); + QVERIFY(!page->m_widget); +} + +void tst_QWebPage::createViewlessPlugin_data() +{ + PluginFactory::prepareTestData(); } void tst_QWebPage::createViewlessPlugin() { - PluginTrackedPage* page = new PluginTrackedPage; + QFETCH(int, type); + PluginCounterPage* page = PluginFactory::create((PluginFactory::FactoredType)type); QString content("<html><body><object type=\"application/x-qt-plugin\" classid=\"QProgressBar\"></object></body></html>"); page->mainFrame()->setHtml(content); - QCOMPARE(page->count, 1); - QVERIFY(page->widget != 0); + QCOMPARE(page->m_count, 1); + QVERIFY(page->m_widget); + QVERIFY(page->m_pluginParent); + QVERIFY(page->m_widget->parent() == page->m_pluginParent); delete page; + } // import private API void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName); QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page); -void QWEBKIT_EXPORT qt_websettings_setLocalStorageDatabasePath(QWebSettings* settings, const QString& path); void tst_QWebPage::multiplePageGroupsAndLocalStorage() { @@ -638,9 +783,11 @@ void tst_QWebPage::multiplePageGroupsAndLocalStorage() QWebView view1; QWebView view2; - qt_websettings_setLocalStorageDatabasePath(view1.page()->settings(), QDir::toNativeSeparators(QDir::currentPath() + "/path1")); + view1.page()->settings()->setAttribute(QWebSettings::LocalStorageEnabled, true); + view1.page()->settings()->setLocalStoragePath(QDir::toNativeSeparators(QDir::currentPath() + "/path1")); qt_webpage_setGroupName(view1.page(), "group1"); - qt_websettings_setLocalStorageDatabasePath(view2.page()->settings(), QDir::toNativeSeparators(QDir::currentPath() + "/path2")); + view2.page()->settings()->setAttribute(QWebSettings::LocalStorageEnabled, true); + view2.page()->settings()->setLocalStoragePath(QDir::toNativeSeparators(QDir::currentPath() + "/path2")); qt_webpage_setGroupName(view2.page(), "group2"); QCOMPARE(qt_webpage_groupName(view1.page()), QString("group1")); QCOMPARE(qt_webpage_groupName(view2.page()), QString("group2")); @@ -1165,6 +1312,200 @@ void tst_QWebPage::frameAt() frameAtHelper(webPage, webPage->mainFrame(), webPage->mainFrame()->pos()); } +void tst_QWebPage::inputMethods_data() +{ + QTest::addColumn<QString>("viewType"); + QTest::newRow("QWebView") << "QWebView"; +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + QTest::newRow("QGraphicsWebView") << "QGraphicsWebView"; +#endif +} + +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) +static Qt::InputMethodHints inputMethodHints(QObject* object) +{ + if (QGraphicsObject* o = qobject_cast<QGraphicsObject*>(object)) + return o->inputMethodHints(); + if (QWidget* w = qobject_cast<QWidget*>(object)) + return w->inputMethodHints(); + return Qt::InputMethodHints(); +} +#endif + +static bool inputMethodEnabled(QObject* object) +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + if (QGraphicsObject* o = qobject_cast<QGraphicsObject*>(object)) + return o->flags() & QGraphicsItem::ItemAcceptsInputMethod; +#endif + if (QWidget* w = qobject_cast<QWidget*>(object)) + return w->testAttribute(Qt::WA_InputMethodEnabled); + return false; +} + +void tst_QWebPage::inputMethods() +{ + QFETCH(QString, viewType); + QWebPage* page = new QWebPage; + QObject* view = 0; + QObject* container = 0; + if (viewType == "QWebView") { + QWebView* wv = new QWebView; + wv->setPage(page); + view = wv; + container = view; + } +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + else if (viewType == "QGraphicsWebView") { + QGraphicsWebView* wv = new QGraphicsWebView; + wv->setPage(page); + view = wv; + + QGraphicsView* gv = new QGraphicsView; + QGraphicsScene* scene = new QGraphicsScene(gv); + gv->setScene(scene); + scene->addItem(wv); + wv->setGeometry(QRect(0, 0, 500, 500)); + + container = gv; + } +#endif + else + QVERIFY2(false, "Unknown view type"); + + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input1' style='font-family: serif' value='' maxlength='20'/><br>" \ + "<input type='password'/>" \ + "</body></html>"); + page->mainFrame()->setFocus(); + + EventSpy viewEventSpy(container); + + QWebElementCollection inputs = page->mainFrame()->documentElement().findAll("input"); + + QMouseEvent evpres(QEvent::MouseButtonPress, inputs.at(0).geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + page->event(&evpres); + QMouseEvent evrel(QEvent::MouseButtonRelease, inputs.at(0).geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + page->event(&evrel); + +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + QVERIFY(!viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); +#endif + viewEventSpy.clear(); + + page->event(&evpres); + page->event(&evrel); + +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + QVERIFY(viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); +#endif + + //ImMicroFocus + QVariant variant = page->inputMethodQuery(Qt::ImMicroFocus); + QRect focusRect = variant.toRect(); + QVERIFY(inputs.at(0).geometry().contains(variant.toRect().topLeft())); + + //ImFont + variant = page->inputMethodQuery(Qt::ImFont); + QFont font = variant.value<QFont>(); + QCOMPARE(QString("-webkit-serif"), font.family()); + + QList<QInputMethodEvent::Attribute> inputAttributes; + + //Insert text. + { + QInputMethodEvent eventText("QtWebKit", inputAttributes); + QSignalSpy signalSpy(page, SIGNAL(microFocusChanged())); + page->event(&eventText); + QCOMPARE(signalSpy.count(), 0); + } + + { + QInputMethodEvent eventText("", inputAttributes); + eventText.setCommitString(QString("QtWebKit"), 0, 0); + page->event(&eventText); + } + +#if QT_VERSION >= 0x040600 + //ImMaximumTextLength + variant = page->inputMethodQuery(Qt::ImMaximumTextLength); + QCOMPARE(20, variant.toInt()); + + //Set selection + inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 3, 2, QVariant()); + QInputMethodEvent eventSelection("",inputAttributes); + page->event(&eventSelection); + + //ImAnchorPosition + variant = page->inputMethodQuery(Qt::ImAnchorPosition); + int anchorPosition = variant.toInt(); + QCOMPARE(anchorPosition, 3); + + //ImCursorPosition + variant = page->inputMethodQuery(Qt::ImCursorPosition); + int cursorPosition = variant.toInt(); + QCOMPARE(cursorPosition, 5); + + //ImCurrentSelection + variant = page->inputMethodQuery(Qt::ImCurrentSelection); + QString selectionValue = variant.value<QString>(); + QCOMPARE(selectionValue, QString("eb")); +#endif + + //ImSurroundingText + variant = page->inputMethodQuery(Qt::ImSurroundingText); + QString value = variant.value<QString>(); + QCOMPARE(value, QString("QtWebKit")); + +#if QT_VERSION >= 0x040600 + { + QList<QInputMethodEvent::Attribute> attributes; + // Clear the selection, so the next test does not clear any contents. + QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant()); + attributes.append(newSelection); + QInputMethodEvent event("composition", attributes); + page->event(&event); + } + + // A ongoing composition should not change the surrounding text before it is committed. + variant = page->inputMethodQuery(Qt::ImSurroundingText); + value = variant.value<QString>(); + QCOMPARE(value, QString("QtWebKit")); +#endif + + //ImhHiddenText + QMouseEvent evpresPassword(QEvent::MouseButtonPress, inputs.at(1).geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + page->event(&evpresPassword); + QMouseEvent evrelPassword(QEvent::MouseButtonRelease, inputs.at(1).geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + page->event(&evrelPassword); + + QVERIFY(inputMethodEnabled(view)); +#if QT_VERSION >= 0x040600 + QVERIFY(inputMethodHints(view) & Qt::ImhHiddenText); + + page->event(&evpres); + page->event(&evrel); + QVERIFY(!(inputMethodHints(view) & Qt::ImhHiddenText)); +#endif + + page->mainFrame()->setHtml("<html><body><p>nothing to input here"); + viewEventSpy.clear(); + + QWebElement para = page->mainFrame()->findFirstElement("p"); + { + QMouseEvent evpres(QEvent::MouseButtonPress, para.geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + page->event(&evpres); + QMouseEvent evrel(QEvent::MouseButtonRelease, para.geometry().center(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + page->event(&evrel); + } + +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + QVERIFY(!viewEventSpy.contains(QEvent::RequestSoftwareInputPanel)); +#endif + + delete container; +} + // import a little DRT helper function to trigger the garbage collector void QWEBKIT_EXPORT qt_drt_garbageCollector_collect(); @@ -1190,5 +1531,288 @@ void tst_QWebPage::protectBindingsRuntimeObjectsFromCollector() newPage->mainFrame()->evaluateJavaScript("testme('bar')"); } +void tst_QWebPage::localURLSchemes() +{ + int i = QWebSecurityOrigin::localSchemes().size(); + + QWebSecurityOrigin::removeLocalScheme("file"); + QTRY_COMPARE(QWebSecurityOrigin::localSchemes().size(), i); + QWebSecurityOrigin::addLocalScheme("file"); + QTRY_COMPARE(QWebSecurityOrigin::localSchemes().size(), i); + + QWebSecurityOrigin::removeLocalScheme("qrc"); + QTRY_COMPARE(QWebSecurityOrigin::localSchemes().size(), i - 1); + QWebSecurityOrigin::addLocalScheme("qrc"); + QTRY_COMPARE(QWebSecurityOrigin::localSchemes().size(), i); + + QString myscheme = "myscheme"; + QWebSecurityOrigin::addLocalScheme(myscheme); + QTRY_COMPARE(QWebSecurityOrigin::localSchemes().size(), i + 1); + QVERIFY(QWebSecurityOrigin::localSchemes().contains(myscheme)); + QWebSecurityOrigin::removeLocalScheme(myscheme); + QTRY_COMPARE(QWebSecurityOrigin::localSchemes().size(), i); + QWebSecurityOrigin::removeLocalScheme(myscheme); + QTRY_COMPARE(QWebSecurityOrigin::localSchemes().size(), i); +} + +static inline bool testFlag(QWebPage& webPage, QWebSettings::WebAttribute settingAttribute, const QString& jsObjectName, bool settingValue) +{ + webPage.settings()->setAttribute(settingAttribute, settingValue); + return webPage.mainFrame()->evaluateJavaScript(QString("(window.%1 != undefined)").arg(jsObjectName)).toBool(); +} + +void tst_QWebPage::testOptionalJSObjects() +{ + // Once a feature is enabled and the JS object is accessed turning off the setting will not turn off + // the visibility of the JS object any more. For this reason this test uses two QWebPage instances. + // Part of the test is to make sure that the QWebPage instances do not interfere with each other so turning on + // a feature for one instance will not turn it on for another. + + QWebPage webPage1; + QWebPage webPage2; + + webPage1.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl()); + webPage2.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl()); + + QEXPECT_FAIL("","Feature enabled/disabled checking problem. Look at bugs.webkit.org/show_bug.cgi?id=29867", Continue); + QCOMPARE(testFlag(webPage1, QWebSettings::OfflineWebApplicationCacheEnabled, "applicationCache", false), false); + QCOMPARE(testFlag(webPage2, QWebSettings::OfflineWebApplicationCacheEnabled, "applicationCache", true), true); + QEXPECT_FAIL("","Feature enabled/disabled checking problem. Look at bugs.webkit.org/show_bug.cgi?id=29867", Continue); + QCOMPARE(testFlag(webPage1, QWebSettings::OfflineWebApplicationCacheEnabled, "applicationCache", false), false); + QCOMPARE(testFlag(webPage2, QWebSettings::OfflineWebApplicationCacheEnabled, "applicationCache", false), true); + + QCOMPARE(testFlag(webPage1, QWebSettings::LocalStorageEnabled, "localStorage", false), false); + QCOMPARE(testFlag(webPage2, QWebSettings::LocalStorageEnabled, "localStorage", true), true); + QCOMPARE(testFlag(webPage1, QWebSettings::LocalStorageEnabled, "localStorage", false), false); + QCOMPARE(testFlag(webPage2, QWebSettings::LocalStorageEnabled, "localStorage", false), true); +} + +void tst_QWebPage::testEnablePersistentStorage() +{ + QWebPage webPage; + + // By default all persistent options should be disabled + QCOMPARE(webPage.settings()->testAttribute(QWebSettings::LocalStorageEnabled), false); + QCOMPARE(webPage.settings()->testAttribute(QWebSettings::OfflineStorageDatabaseEnabled), false); + QCOMPARE(webPage.settings()->testAttribute(QWebSettings::OfflineWebApplicationCacheEnabled), false); + QVERIFY(webPage.settings()->iconDatabasePath().isEmpty()); + + QWebSettings::enablePersistentStorage(); + + // Give it some time to initialize - icon database needs it + QTest::qWait(1000); + + QCOMPARE(webPage.settings()->testAttribute(QWebSettings::LocalStorageEnabled), true); + QCOMPARE(webPage.settings()->testAttribute(QWebSettings::OfflineStorageDatabaseEnabled), true); + QCOMPARE(webPage.settings()->testAttribute(QWebSettings::OfflineWebApplicationCacheEnabled), true); + + QVERIFY(!webPage.settings()->offlineStoragePath().isEmpty()); + QVERIFY(!webPage.settings()->offlineWebApplicationCachePath().isEmpty()); + QVERIFY(!webPage.settings()->iconDatabasePath().isEmpty()); +} + +void tst_QWebPage::defaultTextEncoding() +{ + QWebFrame* mainFrame = m_page->mainFrame(); + + QString defaultCharset = mainFrame->evaluateJavaScript("document.defaultCharset").toString(); + QVERIFY(!defaultCharset.isEmpty()); + QCOMPARE(QWebSettings::globalSettings()->defaultTextEncoding(), defaultCharset); + + m_page->settings()->setDefaultTextEncoding(QString("utf-8")); + QString charset = mainFrame->evaluateJavaScript("document.defaultCharset").toString(); + QCOMPARE(charset, QString("utf-8")); + QCOMPARE(m_page->settings()->defaultTextEncoding(), charset); + + m_page->settings()->setDefaultTextEncoding(QString()); + charset = mainFrame->evaluateJavaScript("document.defaultCharset").toString(); + QVERIFY(!charset.isEmpty()); + QCOMPARE(charset, defaultCharset); + + QWebSettings::globalSettings()->setDefaultTextEncoding(QString("utf-8")); + charset = mainFrame->evaluateJavaScript("document.defaultCharset").toString(); + QCOMPARE(charset, QString("utf-8")); + QCOMPARE(QWebSettings::globalSettings()->defaultTextEncoding(), charset); +} + +class ErrorPage : public QWebPage +{ +public: + + ErrorPage(QWidget* parent = 0): QWebPage(parent) + { + } + + virtual bool supportsExtension(Extension extension) const + { + return extension == ErrorPageExtension; + } + + virtual bool extension(Extension, const ExtensionOption* option, ExtensionReturn* output) + { + ErrorPageExtensionReturn* errorPage = static_cast<ErrorPageExtensionReturn*>(output); + + errorPage->content = "data:text/html,error"; + return true; + } +}; + +void tst_QWebPage::errorPageExtension() +{ + ErrorPage* page = new ErrorPage; + m_view->setPage(page); + + QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); + + m_view->setUrl(QUrl("data:text/html,foo")); + QTRY_COMPARE(spyLoadFinished.count(), 1); + + page->mainFrame()->setUrl(QUrl("http://non.existent/url")); + QTRY_COMPARE(spyLoadFinished.count(), 2); + QCOMPARE(page->mainFrame()->toPlainText(), QString("data:text/html,error")); + QCOMPARE(page->history()->count(), 2); + QCOMPARE(page->history()->currentItem().url(), QUrl("http://non.existent/url")); + QCOMPARE(page->history()->canGoBack(), true); + QCOMPARE(page->history()->canGoForward(), false); + + page->triggerAction(QWebPage::Back); + QTest::qWait(2000); + QCOMPARE(page->history()->canGoBack(), false); + QCOMPARE(page->history()->canGoForward(), true); + + page->triggerAction(QWebPage::Forward); + QTest::qWait(2000); + QCOMPARE(page->history()->canGoBack(), true); + QCOMPARE(page->history()->canGoForward(), false); + + page->triggerAction(QWebPage::Back); + QTest::qWait(2000); + QCOMPARE(page->history()->canGoBack(), false); + QCOMPARE(page->history()->canGoForward(), true); + QCOMPARE(page->history()->currentItem().url(), QUrl("data:text/html,foo")); + + m_view->setPage(0); +} + +void tst_QWebPage::errorPageExtensionInIFrames() +{ + ErrorPage* page = new ErrorPage; + m_view->setPage(page); + + m_view->setHtml(QString("data:text/html," + "<h1>h1</h1>" + "<iframe src='data:text/html,<p/>p'></iframe>" + "<iframe src='non-existent.html'></iframe>")); + QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); + QTRY_COMPARE(spyLoadFinished.count(), 1); + + QCOMPARE(page->mainFrame()->childFrames()[1]->toPlainText(), QString("data:text/html,error")); + + m_view->setPage(0); +} + +void tst_QWebPage::errorPageExtensionInFrameset() +{ + ErrorPage* page = new ErrorPage; + m_view->setPage(page); + + m_view->load(QUrl("qrc:///frametest/index.html")); + + QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool))); + QTRY_COMPARE(spyLoadFinished.count(), 1); + QCOMPARE(page->mainFrame()->childFrames()[1]->toPlainText(), QString("data:text/html,error")); + + m_view->setPage(0); +} + +void tst_QWebPage::crashTests_LazyInitializationOfMainFrame() +{ + { + QWebPage webPage; + } + { + QWebPage webPage; + webPage.selectedText(); + } + { + QWebPage webPage; + webPage.triggerAction(QWebPage::Back, true); + } + { + QWebPage webPage; + QPoint pos(10,10); + webPage.updatePositionDependentActions(pos); + } +} + +static void takeScreenshot(QWebPage* page) +{ + QWebFrame* mainFrame = page->mainFrame(); + page->setViewportSize(mainFrame->contentsSize()); + QImage image(page->viewportSize(), QImage::Format_ARGB32); + QPainter painter(&image); + mainFrame->render(&painter); + painter.end(); +} + +void tst_QWebPage::screenshot_data() +{ + QTest::addColumn<QString>("html"); + QTest::newRow("WithoutPlugin") << "<html><body id='b'>text</body></html>"; + QTest::newRow("WindowedPlugin") << QString("<html><body id='b'>text<embed src='resources/test.swf'></embed></body></html>"); + QTest::newRow("WindowlessPlugin") << QString("<html><body id='b'>text<embed src='resources/test.swf' wmode='transparent'></embed></body></html>"); +} + +void tst_QWebPage::screenshot() +{ + QDir::setCurrent(SRCDIR); + + QFETCH(QString, html); + QWebPage* page = new QWebPage; + page->settings()->setAttribute(QWebSettings::PluginsEnabled, true); + QWebFrame* mainFrame = page->mainFrame(); + mainFrame->setHtml(html, QUrl::fromLocalFile(QDir::currentPath())); + if (html.contains("</embed>")) { + // some reasonable time for the PluginStream to feed test.swf to flash and start painting + QTest::qWait(2000); + } + + // take screenshot without a view + takeScreenshot(page); + + QWebView* view = new QWebView; + view->setPage(page); + + // take screenshot when attached to a view + takeScreenshot(page); + + delete page; + delete view; + + QDir::setCurrent(QApplication::applicationDirPath()); +} + +void tst_QWebPage::originatingObjectInNetworkRequests() +{ + TestNetworkManager* networkManager = new TestNetworkManager(m_page); + m_page->setNetworkAccessManager(networkManager); + networkManager->requests.clear(); + + m_view->setHtml(QString("data:text/html,<frameset cols=\"25%,75%\"><frame src=\"data:text/html," + "<head><meta http-equiv='refresh' content='1'></head>foo \">" + "<frame src=\"data:text/html,bar\"></frameset>"), QUrl()); + QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); + + QCOMPARE(networkManager->requests.count(), 2); + + QList<QWebFrame*> childFrames = m_page->mainFrame()->childFrames(); + QCOMPARE(childFrames.count(), 2); + +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + for (int i = 0; i < 2; ++i) + QVERIFY(qobject_cast<QWebFrame*>(networkManager->requests.at(i).originatingObject()) == childFrames.at(i)); +#endif +} + QTEST_MAIN(tst_QWebPage) #include "tst_qwebpage.moc" |
