2011-03-28 Andreas Kling <kling@webkit.org>
authorandreas.kling@nokia.com <andreas.kling@nokia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Mar 2011 19:32:19 +0000 (19:32 +0000)
committerandreas.kling@nokia.com <andreas.kling@nokia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 28 Mar 2011 19:32:19 +0000 (19:32 +0000)
        Reviewed by Benjamin Poulain.

        [Qt] Crash when calling QWebFrame::render() in response to QWebPage::repaintRequested()
        https://bugs.webkit.org/show_bug.cgi?id=52629

        * WebCoreSupport/ChromeClientQt.cpp:
        (WebCore::ChromeClientQt::invalidateContentsAndWindow): Make the emission of
        QWebPage::repaintRequested() use a Qt::QueuedConnection.

        * tests/qwebpage/tst_qwebpage.cpp:
        (RepaintRequestedRenderer::RepaintRequestedRenderer):
        (RepaintRequestedRenderer::onRepaintRequested):
        (tst_QWebPage::renderOnRepaintRequestedShouldNotRecurse): Test that calling
        QWebFrame::render() in a slot connected to to QWebPage::repaintRequested()
        doesn't cause recursive signal emissions.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@82142 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/qt/ChangeLog
Source/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp
Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp

index 19cbc1f8eb19900efd93e7d8e5b087229eb61daf..16587c1b3462f51e76318997f6e23c478a012f50 100644 (file)
@@ -1,3 +1,21 @@
+2011-03-28  Andreas Kling  <kling@webkit.org>
+
+        Reviewed by Benjamin Poulain.
+
+        [Qt] Crash when calling QWebFrame::render() in response to QWebPage::repaintRequested()
+        https://bugs.webkit.org/show_bug.cgi?id=52629
+
+        * WebCoreSupport/ChromeClientQt.cpp:
+        (WebCore::ChromeClientQt::invalidateContentsAndWindow): Make the emission of
+        QWebPage::repaintRequested() use a Qt::QueuedConnection.
+
+        * tests/qwebpage/tst_qwebpage.cpp:
+        (RepaintRequestedRenderer::RepaintRequestedRenderer):
+        (RepaintRequestedRenderer::onRepaintRequested):
+        (tst_QWebPage::renderOnRepaintRequestedShouldNotRecurse): Test that calling
+        QWebFrame::render() in a slot connected to to QWebPage::repaintRequested()
+        doesn't cause recursive signal emissions.
+
 2011-03-28  Benjamin Poulain  <benjamin.poulain@nokia.com>
 
         Reviewed by Andreas Kling.
 2011-03-28  Benjamin Poulain  <benjamin.poulain@nokia.com>
 
         Reviewed by Andreas Kling.
index acfa6644fa0c32606440ebbcaccedd228b4419f5..bec4bc4c3abdb5f3099680d963e0ad1e1fc06906 100644 (file)
@@ -411,7 +411,7 @@ void ChromeClientQt::invalidateContentsAndWindow(const IntRect& windowRect, bool
         if (!rect.isEmpty())
             platformPageClient()->update(rect);
     }
         if (!rect.isEmpty())
             platformPageClient()->update(rect);
     }
-    emit m_webPage->repaintRequested(windowRect);
+    QMetaObject::invokeMethod(m_webPage, "repaintRequested", Qt::QueuedConnection, Q_ARG(QRect, windowRect));
 
     // FIXME: There is no "immediate" support for window painting.  This should be done always whenever the flag
     // is set.
 
     // FIXME: There is no "immediate" support for window painting.  This should be done always whenever the flag
     // is set.
index 2b0ab98e2408c2d1f5501db4c6baf12c5584ce07..cfc181dfba78bbfde0adce6a283243ce607b49e7 100644 (file)
@@ -140,6 +140,7 @@ private slots:
     void infiniteLoopJS();
     void navigatorCookieEnabled();
     void deleteQWebViewTwice();
     void infiniteLoopJS();
     void navigatorCookieEnabled();
     void deleteQWebViewTwice();
+    void renderOnRepaintRequestedShouldNotRecurse();
 
 #ifdef Q_OS_MAC
     void macCopyUnicodeToClipboard();
 
 #ifdef Q_OS_MAC
     void macCopyUnicodeToClipboard();
@@ -2798,5 +2799,54 @@ void tst_QWebPage::deleteQWebViewTwice()
     }
 }
 
     }
 }
 
+class RepaintRequestedRenderer : public QObject {
+    Q_OBJECT
+public:
+    RepaintRequestedRenderer(QWebPage* page, QPainter* painter)
+        : m_page(page)
+        , m_painter(painter)
+        , m_recursionCount(0)
+    {
+        connect(m_page, SIGNAL(repaintRequested(QRect)), this, SLOT(onRepaintRequested(QRect)));
+    }
+
+signals:
+    void finished();
+
+private slots:
+    void onRepaintRequested(const QRect& rect)
+    {
+        QCOMPARE(m_recursionCount, 0);
+
+        m_recursionCount++;
+        m_page->mainFrame()->render(m_painter, rect);
+        m_recursionCount--;
+
+        QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+    }
+
+private:
+    QWebPage* m_page;
+    QPainter* m_painter;
+    int m_recursionCount;
+};
+
+void tst_QWebPage::renderOnRepaintRequestedShouldNotRecurse()
+{
+    QSize viewportSize(720, 576);
+    QWebPage page;
+
+    QImage image(viewportSize, QImage::Format_ARGB32);
+    QPainter painter(&image);
+
+    page.setPreferredContentsSize(viewportSize);
+    page.setViewportSize(viewportSize);
+    RepaintRequestedRenderer r(&page, &painter);
+
+    page.mainFrame()->setHtml("zalan loves trunk", QUrl());
+
+    QVERIFY(::waitForSignal(&r, SIGNAL(finished())));
+}
+
 QTEST_MAIN(tst_QWebPage)
 #include "tst_qwebpage.moc"
 QTEST_MAIN(tst_QWebPage)
 #include "tst_qwebpage.moc"