[Qt] Wait for the UI process before re-enabling rendering during page load
authorjocelyn.turcotte@digia.com <jocelyn.turcotte@digia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Oct 2012 11:17:39 +0000 (11:17 +0000)
committerjocelyn.turcotte@digia.com <jocelyn.turcotte@digia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Oct 2012 11:17:39 +0000 (11:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=97773

Reviewed by Kenneth Rohde Christiansen.

During page navigation, WebCore might ask asynchronously the UI process to
scroll to an anchor or restored history position and the UI process will
return the corresponding visible rect to be rendered by the web process.

To avoid rendering tiles for the invalidated area by the new page layout at
the wrong position, we should do an extra message round-trip to the UI
process before resuming the rendering.
Assuming that all messages are handled in order by both the web and UI process,
sending the round-trip request in the web process once we sent all scroll
requests, contents size and viewport attributes updates and then handling
the round-trip response, we make sure that final visible rect request have
been handled already.

* UIProcess/API/qt/raw/qrawwebview.cpp:
(QRawWebViewPrivate::pageTransitionViewportReady):
* UIProcess/API/qt/raw/qrawwebview_p_p.h:
(QRawWebViewPrivate):
* UIProcess/PageClient.h:
(PageClient):
* UIProcess/PageViewportController.cpp:
(WebKit::PageViewportController::pageTransitionViewportReady):
(WebKit):
* UIProcess/PageViewportController.h:
(PageViewportController):
* UIProcess/WebPageProxy.h:
(WebPageProxy):
* UIProcess/WebPageProxy.messages.in:
* UIProcess/qt/QtPageClient.cpp:
(WebKit::QtPageClient::pageTransitionViewportReady):
(WebKit):
* UIProcess/qt/QtPageClient.h:
(QtPageClient):
* UIProcess/qt/WebPageProxyQt.cpp:
(WebKit::WebPageProxy::commitPageTransitionViewport):
(WebKit):
(WebKit::WebPageProxy::pageTransitionViewportReady):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::WebFrameLoaderClient):
(WebKit::WebFrameLoaderClient::dispatchDidLayout):
(WebKit::WebFrameLoaderClient::frameLoadCompleted):
(WebKit::WebFrameLoaderClient::provisionalLoadStarted):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
(WebFrameLoaderClient):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::didStartPageTransition):
(WebKit):
(WebKit::WebPage::didCompletePageTransition):
* WebProcess/WebPage/WebPage.h:
(WebPage):
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/qt/WebPageQt.cpp:
(WebKit::WebPage::commitPageTransitionViewport):
(WebKit):

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

17 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/qt/raw/qrawwebview.cpp
Source/WebKit2/UIProcess/API/qt/raw/qrawwebview_p_p.h
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/PageViewportController.cpp
Source/WebKit2/UIProcess/PageViewportController.h
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/qt/QtPageClient.cpp
Source/WebKit2/UIProcess/qt/QtPageClient.h
Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/qt/WebPageQt.cpp

index 739395d..20309af 100644 (file)
@@ -1,3 +1,64 @@
+2012-09-27  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
+
+        [Qt] Wait for the UI process before re-enabling rendering during page load
+        https://bugs.webkit.org/show_bug.cgi?id=97773
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        During page navigation, WebCore might ask asynchronously the UI process to
+        scroll to an anchor or restored history position and the UI process will
+        return the corresponding visible rect to be rendered by the web process.
+
+        To avoid rendering tiles for the invalidated area by the new page layout at
+        the wrong position, we should do an extra message round-trip to the UI
+        process before resuming the rendering.
+        Assuming that all messages are handled in order by both the web and UI process,
+        sending the round-trip request in the web process once we sent all scroll
+        requests, contents size and viewport attributes updates and then handling
+        the round-trip response, we make sure that final visible rect request have
+        been handled already.
+
+        * UIProcess/API/qt/raw/qrawwebview.cpp:
+        (QRawWebViewPrivate::pageTransitionViewportReady):
+        * UIProcess/API/qt/raw/qrawwebview_p_p.h:
+        (QRawWebViewPrivate):
+        * UIProcess/PageClient.h:
+        (PageClient):
+        * UIProcess/PageViewportController.cpp:
+        (WebKit::PageViewportController::pageTransitionViewportReady):
+        (WebKit):
+        * UIProcess/PageViewportController.h:
+        (PageViewportController):
+        * UIProcess/WebPageProxy.h:
+        (WebPageProxy):
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/qt/QtPageClient.cpp:
+        (WebKit::QtPageClient::pageTransitionViewportReady):
+        (WebKit):
+        * UIProcess/qt/QtPageClient.h:
+        (QtPageClient):
+        * UIProcess/qt/WebPageProxyQt.cpp:
+        (WebKit::WebPageProxy::commitPageTransitionViewport):
+        (WebKit):
+        (WebKit::WebPageProxy::pageTransitionViewportReady):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::WebFrameLoaderClient):
+        (WebKit::WebFrameLoaderClient::dispatchDidLayout):
+        (WebKit::WebFrameLoaderClient::frameLoadCompleted):
+        (WebKit::WebFrameLoaderClient::provisionalLoadStarted):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
+        (WebFrameLoaderClient):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::didStartPageTransition):
+        (WebKit):
+        (WebKit::WebPage::didCompletePageTransition):
+        * WebProcess/WebPage/WebPage.h:
+        (WebPage):
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/qt/WebPageQt.cpp:
+        (WebKit::WebPage::commitPageTransitionViewport):
+        (WebKit):
+
 2012-10-01  Alberto Garcia  <agarcia@igalia.com>
 
         WebPrintOperationGtk destructor should be virtual
index 531e57d..5f6c16d 100644 (file)
@@ -167,6 +167,11 @@ void QRawWebViewPrivate::toolTipChanged(const String&, const String& newTooltip)
     notImplemented();
 }
 
+void QRawWebViewPrivate::pageTransitionViewportReady()
+{
+    m_webPageProxy->commitPageTransitionViewport();
+}
+
 void QRawWebViewPrivate::startDrag(const WebCore::DragData& dragData, PassRefPtr<WebKit::ShareableBitmap> dragImage)
 {
     notImplemented();
index 55bc85b..b00d467 100644 (file)
@@ -82,6 +82,7 @@ public:
 
     virtual void setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves);
     virtual void toolTipChanged(const String&, const String& newTooltip);
+    virtual void pageTransitionViewportReady();
 
     virtual void startDrag(const WebCore::DragData& dragData, PassRefPtr<WebKit::ShareableBitmap> dragImage);
 
index ebf5cd1..a3f47a9 100644 (file)
@@ -118,6 +118,7 @@ public:
     virtual void pageDidRequestScroll(const WebCore::IntPoint&) = 0;
 #endif
 #if PLATFORM(QT)
+    virtual void pageTransitionViewportReady() = 0;
     virtual void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&) = 0;
     virtual void didReceiveMessageFromNavigatorQtObject(const String&) = 0;
     virtual void updateTextInputState() = 0;
index e42006a..29cf6de 100644 (file)
@@ -120,6 +120,15 @@ void PageViewportController::didChangeContentsSize(const IntSize& newSize)
     m_client->didChangeContentsSize();
 }
 
+void PageViewportController::pageTransitionViewportReady()
+{
+    // At this point we should already have received the first viewport arguments and the requested scroll
+    // position for the newly loaded page and sent our reactions to the web process. It's now safe to tell
+    // the web process to start rendering the new page contents and possibly re-use the current tiles.
+    // This assumes that all messages have been handled in order and that nothing has been pushed back on the event loop.
+    m_webPageProxy->commitPageTransitionViewport();
+}
+
 void PageViewportController::pageDidRequestScroll(const IntPoint& cssPosition)
 {
     // Ignore the request if suspended. Can only happen due to delay in event delivery.
index acbb22a..a35d933 100644 (file)
@@ -97,6 +97,7 @@ public:
     // Notifications from the WebProcess.
     void didChangeContentsSize(const WebCore::IntSize& newSize);
     void didChangeViewportAttributes(const WebCore::ViewportAttributes&);
+    void pageTransitionViewportReady();
     void pageDidRequestScroll(const WebCore::IntPoint& cssPosition);
 
 private:
index 97e1ba2..e61d881 100644 (file)
@@ -418,6 +418,7 @@ public:
 #endif
 #if USE(TILED_BACKING_STORE)
     void setViewportSize(const WebCore::IntSize&);
+    void commitPageTransitionViewport();
 #endif
 
     void handleMouseEvent(const NativeWebMouseEvent&);
@@ -849,6 +850,7 @@ private:
 #endif
 
 #if PLATFORM(QT)
+    void pageTransitionViewportReady();
     void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&);
 #endif
 
index 05cbb23..588c7d2 100644 (file)
@@ -73,6 +73,7 @@ messages -> WebPageProxy {
     PageDidRequestScroll(WebCore::IntPoint point)
 #endif
 #if PLATFORM(QT)
+    PageTransitionViewportReady()
     DidFindZoomableArea(WebCore::IntPoint target, WebCore::IntRect area)
     AuthenticationRequiredRequest(WTF::String hostname, WTF::String realm, WTF::String prefilledUsername) -> (WTF::String username, WTF::String password)
     CertificateVerificationRequest(WTF::String hostname) -> (bool ignoreErrors)
index d5a5f7e..bd932b7 100644 (file)
@@ -220,6 +220,11 @@ void QtPageClient::flashBackingStoreUpdates(const Vector<IntRect>&)
     notImplemented();
 }
 
+void QtPageClient::pageTransitionViewportReady()
+{
+    QQuickWebViewPrivate::get(m_webView)->viewportController()->pageTransitionViewportReady();
+}
+
 void QtPageClient::didFindZoomableArea(const IntPoint& target, const IntRect& area)
 {
     ASSERT(m_eventHandler);
index 2e36757..bb42580 100644 (file)
@@ -99,6 +99,7 @@ public:
     virtual void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects);
     virtual void findStringInCustomRepresentation(const String&, WebKit::FindOptions, unsigned maxMatchCount) { }
     virtual void countStringMatchesInCustomRepresentation(const String&, WebKit::FindOptions, unsigned maxMatchCount) { }
+    virtual void pageTransitionViewportReady();
     virtual void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&);
     virtual void updateTextInputState();
     virtual void doneWithGestureEvent(const WebGestureEvent&, bool wasEventHandled);
index ef6d547..549fc28 100644 (file)
@@ -60,6 +60,14 @@ void WebPageProxy::loadRecentSearches(const String&, Vector<String>&)
     notImplemented();
 }
 
+void WebPageProxy::commitPageTransitionViewport()
+{
+    if (!isValid())
+        return;
+
+    process()->send(Messages::WebPage::CommitPageTransitionViewport(), m_pageID);
+}
+
 void WebPageProxy::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd)
 {
     // FIXME: We need to find out how to proper handle the crashes case.
@@ -116,6 +124,11 @@ void WebPageProxy::setUserScripts(const Vector<String>& scripts)
     process()->send(Messages::WebPage::SetUserScripts(scripts), m_pageID);
 }
 
+void WebPageProxy::pageTransitionViewportReady()
+{
+    m_pageClient->pageTransitionViewportReady();
+}
+
 #if PLUGIN_ARCHITECTURE(X11)
 void WebPageProxy::createPluginContainer(uint64_t& windowID)
 {
index 1398ff0..876234f 100644 (file)
@@ -92,6 +92,7 @@ namespace WebKit {
 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame* frame)
     : m_frame(frame)
     , m_hasSentResponseToPluginView(false)
+    , m_didCompletePageTransitionAlready(false)
     , m_frameHasCustomRepresentation(false)
     , m_frameCameFromPageCache(false)
 {
@@ -563,8 +564,10 @@ void WebFrameLoaderClient::dispatchDidLayout(LayoutMilestones milestones)
         webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
 
         if (m_frame == m_frame->page()->mainWebFrame()) {
-            if (!webPage->corePage()->settings()->suppressesIncrementalRendering())
-                webPage->drawingArea()->setLayerTreeStateIsFrozen(false);
+            if (!webPage->corePage()->settings()->suppressesIncrementalRendering() && !m_didCompletePageTransitionAlready) {
+                webPage->didCompletePageTransition();
+                m_didCompletePageTransitionAlready = true;
+            }
         }
     
 #if USE(TILED_BACKING_STORE)
@@ -1121,12 +1124,15 @@ String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLSc
 
 void WebFrameLoaderClient::frameLoadCompleted()
 {
+    // Note: Can be called multiple times.
     WebPage* webPage = m_frame->page();
     if (!webPage)
         return;
 
-    if (m_frame == m_frame->page()->mainWebFrame())
-        webPage->drawingArea()->setLayerTreeStateIsFrozen(false);
+    if (m_frame == m_frame->page()->mainWebFrame() && !m_didCompletePageTransitionAlready) {
+        webPage->didCompletePageTransition();
+        m_didCompletePageTransitionAlready = true;
+    }
 }
 
 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem*)
@@ -1156,8 +1162,10 @@ void WebFrameLoaderClient::provisionalLoadStarted()
     if (!webPage)
         return;
 
-    if (m_frame == m_frame->page()->mainWebFrame())
-        webPage->drawingArea()->setLayerTreeStateIsFrozen(true);
+    if (m_frame == m_frame->page()->mainWebFrame()) {
+        webPage->didStartPageTransition();
+        m_didCompletePageTransitionAlready = false;
+    }
 }
 
 void WebFrameLoaderClient::didFinishLoad()
index b5a3045..866ad3f 100644 (file)
@@ -241,6 +241,7 @@ private:
     WebFrame* m_frame;
     RefPtr<PluginView> m_pluginView;
     bool m_hasSentResponseToPluginView;
+    bool m_didCompletePageTransitionAlready;
     bool m_frameHasCustomRepresentation;
     bool m_frameCameFromPageCache;
 };
index 6bd3c8d..3d39db2 100644 (file)
@@ -1780,6 +1780,22 @@ void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, ui
     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
 }
 
+void WebPage::didStartPageTransition()
+{
+    m_drawingArea->setLayerTreeStateIsFrozen(true);
+}
+
+void WebPage::didCompletePageTransition()
+{
+#if PLATFORM(QT)
+    if (m_mainFrame->coreFrame()->view()->delegatesScrolling())
+        // Wait until the UI process sent us the visible rect it wants rendered.
+        send(Messages::WebPageProxy::PageTransitionViewportReady());
+    else
+#endif
+        m_drawingArea->setLayerTreeStateIsFrozen(false);
+}
+
 void WebPage::show()
 {
     send(Messages::WebPageProxy::ShowPage());
index 883d8a5..9d4dd46 100644 (file)
@@ -213,6 +213,8 @@ public:
     bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*);
 #endif
 
+    void didStartPageTransition();
+    void didCompletePageTransition();
     void show();
     String userAgent() const { return m_userAgent; }
     WebCore::IntRect windowResizerRect() const;
@@ -416,6 +418,7 @@ public:
 #endif
 
 #if PLATFORM(QT)
+    void commitPageTransitionViewport();
     void setComposition(const String& text, Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd);
     void confirmComposition(const String& text, int64_t selectionStart, int64_t selectionLength);
     void cancelComposition();
index f113fc2..d97ad31 100644 (file)
@@ -244,6 +244,7 @@ messages -> WebPage {
 #endif
 
 #if PLATFORM(QT)
+    CommitPageTransitionViewport()
     SetComposition(WTF::String text, WTF::Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd)
     ConfirmComposition(WTF::String text, int64_t selectionStart, int64_t selectionLength)
     CancelComposition()
index 76fb074..08b5021 100644 (file)
@@ -308,6 +308,11 @@ PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&)
     return 0;
 }
 
+void WebPage::commitPageTransitionViewport()
+{
+    m_drawingArea->setLayerTreeStateIsFrozen(false);
+}
+
 static Frame* targetFrameForEditing(WebPage* page)
 {
     Frame* targetFrame = page->corePage()->focusController()->focusedOrMainFrame();