This bug report originated from issue QTBUG-3503 http://bugreports.qt.nokia.com/browse/QTBUG-3503 --- Description --- The attached test cases will show two WebKit bugs. Tests have been performed with both Qt 4.5.0-beta1 and the latest available snapshot (20090130). Test 1: tst_QWebPage::resizeJS() This will add both a <img> and a <object> tag to the web page, the latter used to embed a QWidget. The test shows that WebKit won't allow changing the width or height attributes of the <object> tag using JavaScript, while it will allow to change other attributes (or the image size). Test 2: tst_QWebPage::resizeWidgetNoRepaint() and tst_QWebPage::resizeWidgetWithRepaint() The tests will embed a QWidget as in the previous test but resize the QWidget. Both will actually run the same code, except the latter adds a call to QWebView::repaint(). The tests show that the <object> width and height are updated correctly right after the widget is resized but that a paint event will cause the widget size to be reset back to the initial size. Looking at RenderWidget::paint() in webcore\rendering\renderwidget.cpp I can see that m_widget->move() is being executed. This will, unfortunately, use the size stored in WebCore::Widget::IntRect, which is no longer the correct size.
/* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <QtTest/QtTest> #include <qwebpage.h> #include <qwidget.h> #include <qwebview.h> #include <qwebframe.h> #include <QDebug> #include <QPushButton> // Will try to wait for the condition while allowing event processing #define QTRY_COMPARE(__expr, __expected) \ do { \ const int __step = 50; \ const int __timeout = 5000; \ if ((__expr) != (__expected)) { \ QTest::qWait(0); \ } \ for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ QTest::qWait(__step); \ } \ QCOMPARE(__expr, __expected); \ } while(0) //TESTED_CLASS= //TESTED_FILES= class tst_QWebPage : public QObject { Q_OBJECT public: tst_QWebPage(); virtual ~tst_QWebPage(); public slots: void init(); void cleanup(); private slots: void resizeJS(); void resizeWidgetNoRepaint(); void resizeWidgetWithRepaint(); private: void resizeWidget(bool resize); QWebView* m_view; QWebPage* m_page; }; tst_QWebPage::tst_QWebPage() { } tst_QWebPage::~tst_QWebPage() { } void tst_QWebPage::init() { m_view = new QWebView(); m_page = m_view->page(); } void tst_QWebPage::cleanup() { delete m_view; } class PluginPage : public QWebPage { public: PluginPage(QObject *parent = 0) : QWebPage(parent) {} ~PluginPage() { } struct CallInfo { CallInfo(const QString &c, const QUrl &u, const QStringList &pn, const QStringList &pv, QObject *r) : classid(c), url(u), paramNames(pn), paramValues(pv), returnValue(r) {} QString classid; QUrl url; QStringList paramNames; QStringList paramValues; QObject *returnValue; }; QList<CallInfo> calls; protected: virtual QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) { QObject *result = 0; if (classid == "pushbutton") result = new QPushButton(); if (result) { result->setObjectName(classid); } calls.append(CallInfo(classid, url, paramNames, paramValues, result)); return result; } }; void tst_QWebPage::resizeJS() { QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); PluginPage* newPage = new PluginPage(m_view); m_view->setPage(newPage); m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true); m_view->settings()->setAttribute(QWebSettings::JavascriptEnabled, true); // add an image and a widget to the page using <img> and <object>. m_view->setHtml(QString("<html><body><img id='qtlogo' src='http://www.qtsoftware.com/logo.png' width='71' height='174'/><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton' width='100' height='100' foo='bar'/></body></html>")); // wait for the page to load QTRY_COMPARE(loadSpy.count(), 1); // ensure the widget has been created correctly QCOMPARE(newPage->calls.count(), 1); { PluginPage::CallInfo ci = newPage->calls.first(); QCOMPARE(ci.classid, QString::fromLatin1("pushbutton")); QVERIFY(ci.returnValue != 0); QVERIFY(ci.returnValue->inherits("QPushButton")); const int w_index = ci.paramNames.indexOf("width"); const int h_index = ci.paramNames.indexOf("height"); QVERIFY(w_index != -1); QVERIFY(h_index != -1); QVERIFY(ci.paramValues.value(w_index) == "100"); QVERIFY(ci.paramValues.value(h_index) == "100"); // test widget size QPushButton* pb = dynamic_cast<QPushButton*>(ci.returnValue); QVERIFY(pb); QVERIFY(pb->size() == QSize(100, 100)); // test widget size (JS) { QString js = QLatin1String("document.getElementById('mybutton').width + 'x' + document.getElementById('mybutton').height"); QString js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("100x100")); } // test image size (JS) { QString js = QLatin1String("document.getElementById('qtlogo').width + 'x' + document.getElementById('qtlogo').height"); QString js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("71x174")); } } // resize image (JS) { QString js = QLatin1String("document.getElementById('qtlogo').width = '142';"); QString js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("142")); js = QLatin1String("document.getElementById('qtlogo').height = '348';"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("348")); // check image size js = QLatin1String("document.getElementById('qtlogo').width + 'x' + document.getElementById('qtlogo').height"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("142x348")); } // resize widget (JS) { QString js, js_res; // test custom attribute (this works!) js = QLatin1String("document.getElementById('mybutton').foo = 'bar2';"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("bar2")); js = QLatin1String("document.getElementById('mybutton').foo"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("bar2")); // test width and height attributes js = QLatin1String("document.getElementById('mybutton').width = 200;"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("200")); js = QLatin1String("document.getElementById('mybutton').height = 200;"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("200")); // check widget size js = QLatin1String("document.getElementById('mybutton').width + 'x' + document.getElementById('mybutton').height"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("200x200")); } // ensure the plugin has been resized as well { PluginPage::CallInfo ci = newPage->calls.first(); QPushButton* pb = dynamic_cast<QPushButton*>(ci.returnValue); QVERIFY(pb); QVERIFY(pb->size() == QSize(200, 200)); } } void tst_QWebPage::resizeWidgetNoRepaint() { resizeWidget(false); } void tst_QWebPage::resizeWidgetWithRepaint() { resizeWidget(true); } void tst_QWebPage::resizeWidget(bool repaint) { QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); PluginPage* newPage = new PluginPage(m_view); m_view->setPage(newPage); m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true); m_view->settings()->setAttribute(QWebSettings::JavascriptEnabled, true); // add a 100x100 widget m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton' width='100' height='100'/></body></html>")); // wait for the page to load QTRY_COMPARE(loadSpy.count(), 1); m_view->show(); // ensure the widget has been created correctly QCOMPARE(newPage->calls.count(), 1); { PluginPage::CallInfo ci = newPage->calls.first(); QCOMPARE(ci.classid, QString::fromLatin1("pushbutton")); QVERIFY(ci.returnValue != 0); QVERIFY(ci.returnValue->inherits("QPushButton")); const int w_index = ci.paramNames.indexOf("width"); const int h_index = ci.paramNames.indexOf("height"); QVERIFY(w_index != -1); QVERIFY(h_index != -1); QVERIFY(ci.paramValues.value(w_index) == "100"); QVERIFY(ci.paramValues.value(h_index) == "100"); // test widget size QPushButton* pb = dynamic_cast<QPushButton*>(ci.returnValue); QVERIFY(pb); QVERIFY(pb->size() == QSize(100, 100)); // now resize the widget pb->resize(QSize(300, 300)); QVERIFY(pb->size() == QSize(300, 300)); } // check <object> size { QString js, js_res; js = QLatin1String("document.getElementById('mybutton').width + 'x' + document.getElementById('mybutton').height"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("300x300")); } if (repaint) m_view->repaint(); { QString js, js_res; js = QLatin1String("document.getElementById('mybutton').width + 'x' + document.getElementById('mybutton').height"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("300x300")); } // re-check <object> size { QString js, js_res; js = QLatin1String("document.getElementById('mybutton').width + 'x' + document.getElementById('mybutton').height"); js_res = newPage->mainFrame()->evaluateJavaScript(js).toString(); QVERIFY(js_res == QString("300x300")); } // re-check the plugin size { PluginPage::CallInfo ci = newPage->calls.first(); QPushButton* pb = dynamic_cast<QPushButton*>(ci.returnValue); QVERIFY(pb); QVERIFY(pb->size() == QSize(300, 300)); } } QTEST_MAIN(tst_QWebPage) #include "tst_qwebpage.moc"
Created attachment 50596 [details] Testcase
Reproduced with r55658.
Reproduced with r79439.
=== Bulk closing of Qt bugs === If you believe that this bug report is still relevant for a non-Qt port of webkit.org, please re-open it and remove [Qt] from the summary. If you believe that this is still an important QtWebKit bug, please fill a new report at https://bugreports.qt-project.org and add a link to this issue. See http://qt-project.org/wiki/ReportingBugsInQt for additional guidelines.