WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED INVALID
29489
[Qt] WebKit bug resizing a plugin with JavaScript
https://bugs.webkit.org/show_bug.cgi?id=29489
Summary
[Qt] WebKit bug resizing a plugin with JavaScript
Tor Arne Vestbø
Reported
2009-09-18 08:58:38 PDT
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.
Attachments
Testcase
(10.09 KB, text/x-c++src)
2010-03-12 07:29 PST
,
Kent Hansen
no flags
Details
View All
Add attachment
proposed patch, testcase, etc.
Tor Arne Vestbø
Comment 1
2009-09-18 08:59:08 PDT
/* 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"
Kent Hansen
Comment 2
2010-03-12 07:29:30 PST
Created
attachment 50596
[details]
Testcase
Kent Hansen
Comment 3
2010-03-12 07:31:05 PST
Reproduced with
r55658
.
Caio Marcelo de Oliveira Filho
Comment 4
2011-02-23 08:29:33 PST
Reproduced with
r79439
.
Jocelyn Turcotte
Comment 5
2014-02-03 03:15:46 PST
=== 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.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug