[iOS] When viewing an MJPEG stream as the main resource, only the first
authorjhoneycutt@apple.com <jhoneycutt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 May 2015 07:34:21 +0000 (07:34 +0000)
committerjhoneycutt@apple.com <jhoneycutt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 May 2015 07:34:21 +0000 (07:34 +0000)
frame paints

<https://bugs.webkit.org/show_bug.cgi?id=145185>
<rdar://problem/20124694>

Source/WebCore:

This bug is caused by state not being restored between successive loads
of multipart/x-mixed-replace content. Each part of the stream is not
treated as a wholly new load, so if state is cleared as part of the
previous page being destroyed, it may not be restored when loading
the next stream part.

On WK1, tile cache updates are disabled in FrameView::clear(), which is
called as the previous page is destroyed, but were not being
reenabled when loading new replacement content from the stream.

On WK2, the exposed content rect was being reset to an empty rect as
the previous page was destroyed, but it was not being reset by loading
replacement content.

To fix these issues, I added two WebFrameLoaderClient callbacks;
willReplaceMultipartContent() and didReplaceMultipartContent(). These
are used to save and restore state between successive loads.

Reviewed by Darin Adler.

* loader/DocumentLoader.cpp:
Call the new client callbacks.
(WebCore::DocumentLoader::commitLoad):
If replacing content in a multipart/x-mixed-replace stream, call the
WebFrameLoaderClient's didReplaceMultipartContent().

(WebCore::DocumentLoader::setupForReplace):
Call the WebFrameLoaderClient's willReplaceMultipartContent().

* loader/EmptyClients.h:

* loader/FrameLoaderClient.h:

* page/FrameView.cpp:
(WebCore::FrameView::didReplaceMultipartContent):
Re-enable tile cache updates that were disabled in FrameView::clear().
This fixes the issue for WK1.

* page/FrameView.h:
Declare an exported function, didReplaceMultipartContent(), that WebKit
can call.

Source/WebKit/mac:

Reviewed by Darin Adler.

* WebCoreSupport/WebFrameLoaderClient.h:

* WebCoreSupport/WebFrameLoaderClient.mm:
(WebFrameLoaderClient::didReplaceMultipartContent):
Call the FrameView's didReplaceMultipartContent().

Source/WebKit/win:

Reviewed by Darin Adler.

* WebCoreSupport/WebFrameLoaderClient.h:
Stubbed new functions that aren't used on Windows.

Source/WebKit2:

Reviewed by Darin Adler.

* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::willReplaceMultipartContent):
Tell the WebPage that we will replace multipart content.

(WebKit::WebFrameLoaderClient::didReplaceMultipartContent):
Tell the WebPage that we did replace multipart content.

* WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
* WebProcess/WebPage/DrawingArea.h:

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::willReplaceMultipartContent):
Save the exposed content rect.
(WebKit::WebPage::didReplaceMultipartContent):
Restore the exposed content rect that was saved before this load. This
fixes the issue for WK2.

* WebProcess/WebPage/WebPage.h:

* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::exposedContentRect):

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

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/EmptyClients.h
Source/WebCore/loader/FrameLoaderClient.h
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h
Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.h
Source/WebKit2/WebProcess/WebPage/DrawingArea.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm

index af44b26..74b676d 100644 (file)
@@ -1,3 +1,53 @@
+2015-05-19  Jon Honeycutt  <jhoneycutt@apple.com>
+
+        [iOS] When viewing an MJPEG stream as the main resource, only the first
+        frame paints
+
+        <https://bugs.webkit.org/show_bug.cgi?id=145185>
+        <rdar://problem/20124694>
+
+        This bug is caused by state not being restored between successive loads
+        of multipart/x-mixed-replace content. Each part of the stream is not
+        treated as a wholly new load, so if state is cleared as part of the
+        previous page being destroyed, it may not be restored when loading
+        the next stream part.
+
+        On WK1, tile cache updates are disabled in FrameView::clear(), which is
+        called as the previous page is destroyed, but were not being
+        reenabled when loading new replacement content from the stream.
+
+        On WK2, the exposed content rect was being reset to an empty rect as
+        the previous page was destroyed, but it was not being reset by loading
+        replacement content.
+
+        To fix these issues, I added two WebFrameLoaderClient callbacks;
+        willReplaceMultipartContent() and didReplaceMultipartContent(). These
+        are used to save and restore state between successive loads.
+
+        Reviewed by Darin Adler.
+
+        * loader/DocumentLoader.cpp:
+        Call the new client callbacks.
+        (WebCore::DocumentLoader::commitLoad):
+        If replacing content in a multipart/x-mixed-replace stream, call the
+        WebFrameLoaderClient's didReplaceMultipartContent().
+
+        (WebCore::DocumentLoader::setupForReplace):
+        Call the WebFrameLoaderClient's willReplaceMultipartContent().
+
+        * loader/EmptyClients.h:
+
+        * loader/FrameLoaderClient.h:
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::didReplaceMultipartContent):
+        Re-enable tile cache updates that were disabled in FrameView::clear().
+        This fixes the issue for WK1.
+
+        * page/FrameView.h:
+        Declare an exported function, didReplaceMultipartContent(), that WebKit
+        can call.
+
 2015-05-27  Brady Eidson  <beidson@apple.com>
 
         Remove unused ResourceRequest "user initiated" flag.
index 9a0f3af..fdcebe8 100644 (file)
@@ -762,6 +762,9 @@ void DocumentLoader::commitLoad(const char* data, int length)
         return;
 #endif
     frameLoader->client().committedLoad(this, data, length);
+
+    if (isMultipartReplacingLoad())
+        frameLoader->client().didReplaceMultipartContent();
 }
 
 ResourceError DocumentLoader::interruptedForPolicyChangeError() const
@@ -870,6 +873,8 @@ void DocumentLoader::setupForReplace()
 {
     if (!mainResourceData())
         return;
+
+    frameLoader()->client().willReplaceMultipartContent();
     
     maybeFinishLoadingMultipartContent();
     maybeCreateArchive();
index 87d14a7..ddee4a6 100644 (file)
@@ -317,6 +317,9 @@ public:
     virtual void willChangeTitle(DocumentLoader*) override { }
     virtual void didChangeTitle(DocumentLoader*) override { }
 
+    virtual void willReplaceMultipartContent() override { }
+    virtual void didReplaceMultipartContent() override { }
+
     virtual void committedLoad(DocumentLoader*, const char*, int) override { }
     virtual void finishedLoading(DocumentLoader*) override { }
 
index 13e362a..afaba6a 100644 (file)
@@ -199,6 +199,9 @@ namespace WebCore {
         virtual void willChangeTitle(DocumentLoader*) = 0;
         virtual void didChangeTitle(DocumentLoader*) = 0;
 
+        virtual void willReplaceMultipartContent() = 0;
+        virtual void didReplaceMultipartContent() = 0;
+
         virtual void committedLoad(DocumentLoader*, const char*, int) = 0;
         virtual void finishedLoading(DocumentLoader*) = 0;
         
index 294a4ba..f2f49f7 100644 (file)
@@ -419,6 +419,15 @@ void FrameView::clear()
 #endif
 }
 
+#if PLATFORM(IOS)
+void FrameView::didReplaceMultipartContent()
+{
+    // Re-enable tile updates that were disabled in clear().
+    if (LegacyTileCache* tileCache = legacyTileCache())
+        tileCache->setTilingMode(LegacyTileCache::Normal);
+}
+#endif
+
 bool FrameView::didFirstLayout() const
 {
     return !m_firstLayout;
index 0d9b095..6a632e3 100644 (file)
@@ -345,6 +345,10 @@ public:
     void willPaintContents(GraphicsContext*, const IntRect& dirtyRect, PaintingState&);
     void didPaintContents(GraphicsContext*, const IntRect& dirtyRect, PaintingState&);
 
+#if PLATFORM(IOS)
+    WEBCORE_EXPORT void didReplaceMultipartContent();
+#endif
+
     WEBCORE_EXPORT void setPaintBehavior(PaintBehavior);
     WEBCORE_EXPORT PaintBehavior paintBehavior() const;
     bool isPainting() const;
index 86fef86..0b953c5 100644 (file)
@@ -1,3 +1,19 @@
+2015-05-19  Jon Honeycutt  <jhoneycutt@apple.com>
+
+        [iOS] When viewing an MJPEG stream as the main resource, only the first
+        frame paints
+
+        <https://bugs.webkit.org/show_bug.cgi?id=145185>
+        <rdar://problem/20124694>
+
+        Reviewed by Darin Adler.
+
+        * WebCoreSupport/WebFrameLoaderClient.h:
+
+        * WebCoreSupport/WebFrameLoaderClient.mm:
+        (WebFrameLoaderClient::didReplaceMultipartContent):
+        Call the FrameView's didReplaceMultipartContent().
+
 2015-05-22  Jon Lee  <jonlee@apple.com>
 
         Fix macros for wireless playback
index 6268b03..f6f94a2 100644 (file)
@@ -140,6 +140,9 @@ private:
     virtual void willChangeTitle(WebCore::DocumentLoader*) override;
     virtual void didChangeTitle(WebCore::DocumentLoader*) override;
 
+    virtual void willReplaceMultipartContent() override { }
+    virtual void didReplaceMultipartContent() override;
+
     virtual void committedLoad(WebCore::DocumentLoader*, const char*, int) override;
     virtual void finishedLoading(WebCore::DocumentLoader*) override;
     virtual void updateGlobalHistory() override;
index ce8f2d7..e2f0420 100644 (file)
@@ -999,6 +999,14 @@ void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
 #endif
 }
 
+void WebFrameLoaderClient::didReplaceMultipartContent()
+{
+#if PLATFORM(IOS)
+    if (FrameView *view = core(m_webFrame.get())->view())
+        view->didReplaceMultipartContent();
+#endif
+}
+
 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
 {
     NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
index 1a8a58e..42a5b54 100644 (file)
@@ -1,3 +1,16 @@
+2015-05-26  Jon Honeycutt  <jhoneycutt@apple.com>
+
+        [iOS] When viewing an MJPEG stream as the main resource, only the first
+        frame paints
+
+        <https://bugs.webkit.org/show_bug.cgi?id=145185>
+        <rdar://problem/20124694>
+
+        Reviewed by Darin Adler.
+
+        * WebCoreSupport/WebFrameLoaderClient.h:
+        Stubbed new functions that aren't used on Windows.
+
 2015-05-22  Jon Lee  <jonlee@apple.com>
 
         Rename MediaPlaybackAllowsInline
index ddc700d..c4acfc5 100644 (file)
@@ -127,6 +127,9 @@ public:
     virtual void willChangeTitle(WebCore::DocumentLoader*) override;
     virtual void didChangeTitle(WebCore::DocumentLoader*) override;
 
+    virtual void willReplaceMultipartContent() override { }
+    virtual void didReplaceMultipartContent() override { }
+
     virtual void updateGlobalHistory() override;
     virtual void updateGlobalHistoryRedirectLinks() override;
     virtual bool shouldGoToHistoryItem(WebCore::HistoryItem*) const override;
index 7b8ca8a..233f973 100644 (file)
@@ -1,3 +1,36 @@
+2015-05-19  Jon Honeycutt  <jhoneycutt@apple.com>
+
+        [iOS] When viewing an MJPEG stream as the main resource, only the first
+        frame paints
+
+        <https://bugs.webkit.org/show_bug.cgi?id=145185>
+        <rdar://problem/20124694>
+
+        Reviewed by Darin Adler.
+
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::willReplaceMultipartContent):
+        Tell the WebPage that we will replace multipart content.
+
+        (WebKit::WebFrameLoaderClient::didReplaceMultipartContent):
+        Tell the WebPage that we did replace multipart content.
+
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
+        * WebProcess/WebPage/DrawingArea.h:
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::willReplaceMultipartContent):
+        Save the exposed content rect.
+        (WebKit::WebPage::didReplaceMultipartContent):
+        Restore the exposed content rect that was saved before this load. This
+        fixes the issue for WK2.
+
+        * WebProcess/WebPage/WebPage.h:
+
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::exposedContentRect):
+
 2015-05-22  Jon Lee  <jonlee@apple.com>
 
         Fix macros for wireless playback
index 00dd895..d65b105 100644 (file)
@@ -913,6 +913,22 @@ void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
     notImplemented();
 }
 
+void WebFrameLoaderClient::willReplaceMultipartContent()
+{
+    WebPage* webPage = m_frame->page();
+    if (!webPage)
+        return;
+    webPage->willReplaceMultipartContent(*m_frame);
+}
+
+void WebFrameLoaderClient::didReplaceMultipartContent()
+{
+    WebPage* webPage = m_frame->page();
+    if (!webPage)
+        return;
+    webPage->didReplaceMultipartContent(*m_frame);
+}
+
 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
 {
     if (!m_pluginView)
index 9be255e..4665e84 100644 (file)
@@ -123,7 +123,10 @@ private:
     
     virtual void willChangeTitle(WebCore::DocumentLoader*) override;
     virtual void didChangeTitle(WebCore::DocumentLoader*) override;
-    
+
+    virtual void willReplaceMultipartContent() override;
+    virtual void didReplaceMultipartContent() override;
+
     virtual void committedLoad(WebCore::DocumentLoader*, const char*, int) override;
     virtual void finishedLoading(WebCore::DocumentLoader*) override;
     
index eff4346..547a961 100644 (file)
@@ -94,6 +94,7 @@ public:
     virtual void addFence(const WebCore::MachSendRight&) { }
 #endif
 #if PLATFORM(IOS)
+    virtual WebCore::FloatRect exposedContentRect() const = 0;
     virtual void setExposedContentRect(const WebCore::FloatRect&) = 0;
 #endif
     virtual void mainFrameScrollabilityChanged(bool) { }
index 82353f4..d564bb7 100644 (file)
@@ -4571,6 +4571,28 @@ void WebPage::didCancelCheckingText(uint64_t requestID)
     request->didCancel();
 }
 
+void WebPage::willReplaceMultipartContent(const WebFrame& frame)
+{
+#if PLATFORM(IOS)
+    if (!frame.isMainFrame())
+        return;
+
+    m_previousExposedContentRect = m_drawingArea->exposedContentRect();
+#endif
+}
+
+void WebPage::didReplaceMultipartContent(const WebFrame& frame)
+{
+#if PLATFORM(IOS)
+    if (!frame.isMainFrame())
+        return;
+
+    // Restore the previous exposed content rect so that it remains fixed when replacing content
+    // from multipart/x-mixed-replace streams.
+    m_drawingArea->setExposedContentRect(m_previousExposedContentRect);
+#endif
+}
+
 void WebPage::didCommitLoad(WebFrame* frame)
 {
     if (!frame->isMainFrame())
index 65a7174..9e1e794 100644 (file)
@@ -253,6 +253,8 @@ public:
     void didStartPageTransition();
     void didCompletePageTransition();
     void didCommitLoad(WebFrame*);
+    void willReplaceMultipartContent(const WebFrame&);
+    void didReplaceMultipartContent(const WebFrame&);
     void didFinishLoad(WebFrame*);
     void show();
     String userAgent(const WebCore::URL&) const;
@@ -1337,6 +1339,7 @@ private:
     HashMap<std::pair<WebCore::IntSize, double>, WebCore::IntPoint> m_dynamicSizeUpdateHistory;
     RefPtr<WebCore::Node> m_pendingSyntheticClickNode;
     WebCore::FloatPoint m_pendingSyntheticClickLocation;
+    WebCore::FloatRect m_previousExposedContentRect;
 #endif
 
     WebInspectorClient* m_inspectorClient;
index 870d5e3..96378fa 100644 (file)
@@ -92,6 +92,7 @@ private:
     virtual void acceleratedAnimationDidEnd(uint64_t layerID, const String& key) override;
 
 #if PLATFORM(IOS)
+    virtual WebCore::FloatRect exposedContentRect() const override;
     virtual void setExposedContentRect(const WebCore::FloatRect&) override;
 #endif
 
index 2fdf886..982ae85 100644 (file)
@@ -235,6 +235,15 @@ void RemoteLayerTreeDrawingArea::setExposedRect(const FloatRect& exposedRect)
 }
 
 #if PLATFORM(IOS)
+WebCore::FloatRect RemoteLayerTreeDrawingArea::exposedContentRect() const
+{
+    FrameView* frameView = m_webPage.mainFrameView();
+    if (!frameView)
+        return FloatRect();
+
+    return frameView->exposedContentRect();
+}
+
 void RemoteLayerTreeDrawingArea::setExposedContentRect(const FloatRect& exposedContentRect)
 {
     FrameView* frameView = m_webPage.mainFrameView();