summaryrefslogtreecommitdiffstats
path: root/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/qt/tests/qwebpage/tst_qwebpage.cpp')
-rw-r--r--WebKit/qt/tests/qwebpage/tst_qwebpage.cpp688
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"