2 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
3 Copyright (C) 2009 Torch Mobile Inc.
4 Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
28 #include <qnetworkrequest.h>
29 #include <qdiriterator.h>
30 #include <qwebkitversion.h>
31 #include <qwebelement.h>
32 #include <qwebframe.h>
35 #define VERIFY_INPUTMETHOD_HINTS(actual, expect) \
36 QVERIFY(actual & Qt::ImhNoAutoUppercase); \
37 QVERIFY(actual & Qt::ImhNoPredictiveText); \
38 QVERIFY(actual & expect);
40 #define VERIFY_INPUTMETHOD_HINTS(actual, expect) \
41 QVERIFY(actual == expect);
44 class tst_QWebView : public QObject
50 void cleanupTestCase();
55 void renderingAfterMaxAndBack();
57 void getWebKitVersion();
59 void reusePage_data();
61 void microFocusCoordinates();
62 void focusInputTypes();
65 #if !(defined(WTF_USE_QT_MOBILE_THEME) && WTF_USE_QT_MOBILE_THEME)
66 void setPalette_data();
71 // This will be called before the first test function is executed.
72 // It is only called once.
73 void tst_QWebView::initTestCase()
77 // This will be called after the last test function is executed.
78 // It is only called once.
79 void tst_QWebView::cleanupTestCase()
83 // This will be called before each test function is executed.
84 void tst_QWebView::init()
88 // This will be called after every test function.
89 void tst_QWebView::cleanup()
93 void tst_QWebView::renderHints()
97 // default is only text antialiasing + smooth pixmap transform
98 QVERIFY(!(webView.renderHints() & QPainter::Antialiasing));
99 QVERIFY(webView.renderHints() & QPainter::TextAntialiasing);
100 QVERIFY(webView.renderHints() & QPainter::SmoothPixmapTransform);
101 QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing));
103 webView.setRenderHint(QPainter::Antialiasing, true);
104 QVERIFY(webView.renderHints() & QPainter::Antialiasing);
105 QVERIFY(webView.renderHints() & QPainter::TextAntialiasing);
106 QVERIFY(webView.renderHints() & QPainter::SmoothPixmapTransform);
107 QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing));
109 webView.setRenderHint(QPainter::Antialiasing, false);
110 QVERIFY(!(webView.renderHints() & QPainter::Antialiasing));
111 QVERIFY(webView.renderHints() & QPainter::TextAntialiasing);
112 QVERIFY(webView.renderHints() & QPainter::SmoothPixmapTransform);
113 QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing));
115 webView.setRenderHint(QPainter::SmoothPixmapTransform, true);
116 QVERIFY(!(webView.renderHints() & QPainter::Antialiasing));
117 QVERIFY(webView.renderHints() & QPainter::TextAntialiasing);
118 QVERIFY(webView.renderHints() & QPainter::SmoothPixmapTransform);
119 QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing));
121 webView.setRenderHint(QPainter::SmoothPixmapTransform, false);
122 QVERIFY(webView.renderHints() & QPainter::TextAntialiasing);
123 QVERIFY(!(webView.renderHints() & QPainter::SmoothPixmapTransform));
124 QVERIFY(!(webView.renderHints() & QPainter::HighQualityAntialiasing));
127 void tst_QWebView::getWebKitVersion()
129 QVERIFY(qWebKitVersion().toDouble() > 0);
132 void tst_QWebView::reusePage_data()
134 QTest::addColumn<QString>("html");
135 QTest::newRow("WithoutPlugin") << "<html><body id='b'>text</body></html>";
136 QTest::newRow("WindowedPlugin") << QString("<html><body id='b'>text<embed src='resources/test.swf'></embed></body></html>");
137 QTest::newRow("WindowlessPlugin") << QString("<html><body id='b'>text<embed src='resources/test.swf' wmode=\"transparent\"></embed></body></html>");
140 void tst_QWebView::reusePage()
142 if (!QDir(TESTS_SOURCE_DIR).exists())
143 QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll);
145 QDir::setCurrent(TESTS_SOURCE_DIR);
147 QFETCH(QString, html);
148 QWebView* view1 = new QWebView;
149 QWeakPointer<QWebPage> page = new QWebPage;
150 view1->setPage(page.data());
151 page.data()->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
152 QWebFrame* mainFrame = page.data()->mainFrame();
153 mainFrame->setHtml(html, QUrl::fromLocalFile(TESTS_SOURCE_DIR));
154 if (html.contains("</embed>")) {
155 // some reasonable time for the PluginStream to feed test.swf to flash and start painting
156 waitForSignal(view1, SIGNAL(loadFinished(bool)), 2000);
160 QTest::qWaitForWindowShown(view1);
162 QVERIFY(page != 0); // deleting view must not have deleted the page, since it's not a child of view
164 QWebView *view2 = new QWebView;
165 view2->setPage(page.data());
166 view2->show(); // in Windowless mode, you should still be able to see the plugin here
167 QTest::qWaitForWindowShown(view2);
170 delete page.data(); // must not crash
172 QDir::setCurrent(QApplication::applicationDirPath());
175 // Class used in crashTests
176 class WebViewCrashTest : public QObject {
183 WebViewCrashTest(QWebView* view)
187 view->connect(view, SIGNAL(loadProgress(int)), this, SLOT(loading(int)));
191 void loading(int progress)
193 if (progress >= 20 && progress < 90) {
194 QVERIFY(!m_executed);
203 void tst_QWebView::crashTests()
205 // Test if loading can be stopped in loadProgress handler without crash.
206 // Test page should have frames.
208 WebViewCrashTest tester(&view);
209 QUrl url("qrc:///resources/index.html");
211 QTRY_VERIFY(tester.m_executed); // If fail it means that the test wasn't executed.
214 void tst_QWebView::microFocusCoordinates()
216 QWebPage* page = new QWebPage;
217 QWebView* webView = new QWebView;
218 webView->setPage( page );
220 page->mainFrame()->setHtml("<html><body>" \
221 "<input type='text' id='input1' style='font--family: serif' value='' maxlength='20'/><br>" \
222 "<canvas id='canvas1' width='500' height='500'></canvas>" \
223 "<input type='password'/><br>" \
224 "<canvas id='canvas2' width='500' height='500'></canvas>" \
227 page->mainFrame()->setFocus();
229 QVariant initialMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus);
230 QVERIFY(initialMicroFocus.isValid());
232 page->mainFrame()->scroll(0,50);
234 QVariant currentMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus);
235 QVERIFY(currentMicroFocus.isValid());
237 QCOMPARE(initialMicroFocus.toRect().translated(QPoint(0,-50)), currentMicroFocus.toRect());
240 void tst_QWebView::focusInputTypes()
244 QTest::qWaitForWindowShown(&webView);
246 QUrl url("qrc:///resources/input_types.html");
247 QWebFrame* const mainFrame = webView.page()->mainFrame();
248 mainFrame->load(url);
249 mainFrame->setFocus();
251 QVERIFY(waitForSignal(&webView, SIGNAL(loadFinished(bool))));
254 QWebElement inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=text]"));
255 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
256 #if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || defined(Q_OS_SYMBIAN)
257 QVERIFY(webView.inputMethodHints() & Qt::ImhNoAutoUppercase);
258 QVERIFY(webView.inputMethodHints() & Qt::ImhNoPredictiveText);
260 QVERIFY(webView.inputMethodHints() == Qt::ImhNone);
262 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
265 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=password]"));
266 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
267 VERIFY_INPUTMETHOD_HINTS(webView.inputMethodHints(), Qt::ImhHiddenText);
268 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
271 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=tel]"));
272 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
273 VERIFY_INPUTMETHOD_HINTS(webView.inputMethodHints(), Qt::ImhDialableCharactersOnly);
274 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
277 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=number]"));
278 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
279 VERIFY_INPUTMETHOD_HINTS(webView.inputMethodHints(), Qt::ImhDigitsOnly);
280 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
283 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=email]"));
284 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
285 VERIFY_INPUTMETHOD_HINTS(webView.inputMethodHints(), Qt::ImhEmailCharactersOnly);
286 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
289 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=url]"));
290 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
291 VERIFY_INPUTMETHOD_HINTS(webView.inputMethodHints(), Qt::ImhUrlCharactersOnly);
292 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
295 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=password]"));
296 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
297 VERIFY_INPUTMETHOD_HINTS(webView.inputMethodHints(), Qt::ImhHiddenText);
298 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
301 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=text]"));
302 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
303 #if defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) || defined(Q_OS_SYMBIAN)
304 QVERIFY(webView.inputMethodHints() & Qt::ImhNoAutoUppercase);
305 QVERIFY(webView.inputMethodHints() & Qt::ImhNoPredictiveText);
307 QVERIFY(webView.inputMethodHints() == Qt::ImhNone);
309 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
312 inputElement = mainFrame->documentElement().findFirst(QLatin1String("input[type=password]"));
313 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
314 VERIFY_INPUTMETHOD_HINTS(webView.inputMethodHints(), Qt::ImhHiddenText);
315 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
318 inputElement = mainFrame->documentElement().findFirst(QLatin1String("textarea"));
319 QTest::mouseClick(&webView, Qt::LeftButton, 0, inputElement.geometry().center());
320 #if defined(Q_OS_SYMBIAN)
321 QVERIFY(webView.inputMethodHints() & Qt::ImhNoAutoUppercase);
322 QVERIFY(webView.inputMethodHints() & Qt::ImhNoPredictiveText);
324 QVERIFY(webView.inputMethodHints() == Qt::ImhNone);
326 QVERIFY(webView.testAttribute(Qt::WA_InputMethodEnabled));
329 #if !(defined(WTF_USE_QT_MOBILE_THEME) && WTF_USE_QT_MOBILE_THEME)
330 void tst_QWebView::setPalette_data()
332 QTest::addColumn<bool>("active");
333 QTest::addColumn<bool>("background");
334 QTest::newRow("activeBG") << true << true;
335 QTest::newRow("activeFG") << true << false;
336 QTest::newRow("inactiveBG") << false << true;
337 QTest::newRow("inactiveFG") << false << false;
340 // Render a QWebView to a QImage twice, each time with a different palette set,
341 // verify that images rendered are not the same, confirming WebCore usage of
342 // custom palette on selections.
343 void tst_QWebView::setPalette()
345 QString html = "<html><head></head>"
351 QFETCH(bool, active);
352 QFETCH(bool, background);
354 QWidget* activeView = 0;
356 // Use controlView to manage active/inactive state of test views by raising
357 // or lowering their position in the window stack.
358 QWebView controlView;
359 controlView.setHtml(html);
364 QBrush brush1(Qt::red);
365 brush1.setStyle(Qt::SolidPattern);
366 if (active && background) {
367 // Rendered image must have red background on an active QWebView.
368 palette1.setBrush(QPalette::Active, QPalette::Highlight, brush1);
369 } else if (active && !background) {
370 // Rendered image must have red foreground on an active QWebView.
371 palette1.setBrush(QPalette::Active, QPalette::HighlightedText, brush1);
372 } else if (!active && background) {
373 // Rendered image must have red background on an inactive QWebView.
374 palette1.setBrush(QPalette::Inactive, QPalette::Highlight, brush1);
375 } else if (!active && !background) {
376 // Rendered image must have red foreground on an inactive QWebView.
377 palette1.setBrush(QPalette::Inactive, QPalette::HighlightedText, brush1);
380 view1.setPalette(palette1);
382 view1.page()->setViewportSize(view1.page()->currentFrame()->contentsSize());
385 QTest::qWaitForWindowShown(&view1);
389 QTest::qWaitForWindowShown(&controlView);
390 activeView = &controlView;
391 controlView.activateWindow();
393 view1.activateWindow();
397 QTRY_COMPARE(QApplication::activeWindow(), activeView);
399 view1.page()->triggerAction(QWebPage::SelectAll);
401 QImage img1(view1.page()->viewportSize(), QImage::Format_ARGB32);
402 QPainter painter1(&img1);
403 view1.page()->currentFrame()->render(&painter1);
411 QBrush brush2(Qt::blue);
412 brush2.setStyle(Qt::SolidPattern);
413 if (active && background) {
414 // Rendered image must have blue background on an active QWebView.
415 palette2.setBrush(QPalette::Active, QPalette::Highlight, brush2);
416 } else if (active && !background) {
417 // Rendered image must have blue foreground on an active QWebView.
418 palette2.setBrush(QPalette::Active, QPalette::HighlightedText, brush2);
419 } else if (!active && background) {
420 // Rendered image must have blue background on an inactive QWebView.
421 palette2.setBrush(QPalette::Inactive, QPalette::Highlight, brush2);
422 } else if (!active && !background) {
423 // Rendered image must have blue foreground on an inactive QWebView.
424 palette2.setBrush(QPalette::Inactive, QPalette::HighlightedText, brush2);
427 view2.setPalette(palette2);
429 view2.page()->setViewportSize(view2.page()->currentFrame()->contentsSize());
432 QTest::qWaitForWindowShown(&view2);
436 QTest::qWaitForWindowShown(&controlView);
437 activeView = &controlView;
438 controlView.activateWindow();
440 view2.activateWindow();
444 QTRY_COMPARE(QApplication::activeWindow(), activeView);
446 view2.page()->triggerAction(QWebPage::SelectAll);
448 QImage img2(view2.page()->viewportSize(), QImage::Format_ARGB32);
449 QPainter painter2(&img2);
450 view2.page()->currentFrame()->render(&painter2);
456 QVERIFY(img1 != img2);
460 void tst_QWebView::renderingAfterMaxAndBack()
462 QUrl url = QUrl("data:text/html,<html><head></head>"
463 "<body width=1024 height=768 bgcolor=red>"
468 view.page()->mainFrame()->load(url);
469 QVERIFY(waitForSignal(&view, SIGNAL(loadFinished(bool))));
472 view.page()->settings()->setMaximumPagesInCache(3);
474 QTest::qWaitForWindowShown(&view);
476 QPixmap reference(view.page()->viewportSize());
477 reference.fill(Qt::red);
479 QPixmap image(view.page()->viewportSize());
480 QPainter painter(&image);
481 view.page()->currentFrame()->render(&painter);
483 QCOMPARE(image, reference);
485 QUrl url2 = QUrl("data:text/html,<html><head></head>"
486 "<body width=1024 height=768 bgcolor=blue>"
489 view.page()->mainFrame()->load(url2);
491 QVERIFY(waitForSignal(&view, SIGNAL(loadFinished(bool))));
493 view.showMaximized();
495 QTest::qWaitForWindowShown(&view);
497 QPixmap reference2(view.page()->viewportSize());
498 reference2.fill(Qt::blue);
500 QPixmap image2(view.page()->viewportSize());
501 QPainter painter2(&image2);
502 view.page()->currentFrame()->render(&painter2);
504 QCOMPARE(image2, reference2);
508 QPixmap reference3(view.page()->viewportSize());
509 reference3.fill(Qt::red);
510 QPixmap image3(view.page()->viewportSize());
511 QPainter painter3(&image3);
512 view.page()->currentFrame()->render(&painter3);
514 QCOMPARE(image3, reference3);
517 QTEST_MAIN(tst_QWebView)
518 #include "tst_qwebview.moc"