[iOS][WK2] Black web view after un-suspending process
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Jul 2014 07:10:10 +0000 (07:10 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Jul 2014 07:10:10 +0000 (07:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=134623
<rdar://problem/17513223>

Reviewed by Simon Fraser.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::viewStateDidChange):
Add an argument to viewStateDidChange that allows callers (-[WKContentView _applicationWillEnterForeground:])
to force us to wait for a synchronous reply from the Web process after performing a view state change.

(WebKit::WebPageProxy::dispatchViewStateChange):
Move the has-been-in-window-and-now-is-newly-in-window check into dispatchViewStateChange.
Adjust the logic surrounding going into/out of window by factoring out the IsInWindow-did-change check, for clarity.

* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _applicationWillEnterForeground:]):
As previously mentioned, wait for a reply when foregrounding.

* WebProcess/WebPage/DrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::scheduleCompositingLayerFlushImmediately):
(WebKit::RemoteLayerTreeDrawingArea::scheduleCompositingLayerFlush):
(WebKit::RemoteLayerTreeDrawingArea::viewStateDidChange):
Make sure to schedule a commit immediately if the UI process is waiting for a reply.
Previously we assumed that a commit would be scheduled anyway because we would have to reparent the
layer tree, but that doesn't happen in the suspension-without-unparenting case. Also, we want to skip
all throttling in this case.

* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::scheduleCompositingLayerFlushImmediately):

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/ios/WKContentView.mm
Source/WebKit2/WebProcess/WebPage/DrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm
Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

index 0c189caccca48a6d4c188282402fc2e1484c961b..361c15b55e444b6ba3a246e88ed5c50a38aaa9c6 100644 (file)
@@ -1,3 +1,40 @@
+2014-07-04  Timothy Horton  <timothy_horton@apple.com>
+
+        [iOS][WK2] Black web view after un-suspending process
+        https://bugs.webkit.org/show_bug.cgi?id=134623
+        <rdar://problem/17513223>
+
+        Reviewed by Simon Fraser.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::viewStateDidChange):
+        Add an argument to viewStateDidChange that allows callers (-[WKContentView _applicationWillEnterForeground:])
+        to force us to wait for a synchronous reply from the Web process after performing a view state change.
+
+        (WebKit::WebPageProxy::dispatchViewStateChange):
+        Move the has-been-in-window-and-now-is-newly-in-window check into dispatchViewStateChange.
+        Adjust the logic surrounding going into/out of window by factoring out the IsInWindow-did-change check, for clarity.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView _applicationWillEnterForeground:]):
+        As previously mentioned, wait for a reply when foregrounding.
+
+        * WebProcess/WebPage/DrawingArea.h:
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::scheduleCompositingLayerFlushImmediately):
+        (WebKit::RemoteLayerTreeDrawingArea::scheduleCompositingLayerFlush):
+        (WebKit::RemoteLayerTreeDrawingArea::viewStateDidChange):
+        Make sure to schedule a commit immediately if the UI process is waiting for a reply.
+        Previously we assumed that a commit would be scheduled anyway because we would have to reparent the
+        layer tree, but that doesn't happen in the suspension-without-unparenting case. Also, we want to skip
+        all throttling in this case.
+
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::scheduleCompositingLayerFlushImmediately):
+
 2014-07-03  Gavin Barraclough  <baraclough@apple.com>
 
         Should not take background task assertion for NetworkProcess
index 212a3d48b6ad7532fd6c2f817567ed4064c16243..0c0ab2e6034a87d51793d54200b40ff1b61c46a1 100644 (file)
@@ -366,7 +366,7 @@ WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uin
     , m_navigationID(0)
     , m_configurationPreferenceValues(configuration.preferenceValues)
     , m_potentiallyChangedViewStateFlags(ViewState::NoFlags)
-    , m_viewStateChangeWantsReply(WantsReplyOrNot::DoesNotWantReply)
+    , m_viewStateChangeWantsReply(false)
 {
     if (m_process->state() == WebProcessProxy::State::Running) {
         if (m_userContentController)
@@ -1101,15 +1101,13 @@ void WebPageProxy::updateViewState(ViewState::Flags flagsToUpdate)
         m_viewState |= ViewState::IsVisuallyIdle;
 }
 
-void WebPageProxy::viewStateDidChange(ViewState::Flags mayHaveChanged)
+void WebPageProxy::viewStateDidChange(ViewState::Flags mayHaveChanged, bool wantsReply)
 {
-    bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ViewState::IsInWindow) && m_pageClient.isViewInWindow();
-
     m_potentiallyChangedViewStateFlags |= mayHaveChanged;
-    m_viewStateChangeWantsReply = ((m_viewWasEverInWindow && isNewlyInWindow) || m_viewStateChangeWantsReply == WantsReplyOrNot::DoesWantReply) ? WantsReplyOrNot::DoesWantReply : WantsReplyOrNot::DoesNotWantReply;
+    m_viewStateChangeWantsReply = m_viewStateChangeWantsReply || wantsReply;
 
 #if PLATFORM(COCOA)
-    if (isNewlyInWindow) {
+    if (!isInWindow() && (mayHaveChanged & ViewState::IsInWindow) && m_pageClient.isViewInWindow()) {
         dispatchViewStateChange();
         return;
     }
@@ -1119,6 +1117,29 @@ void WebPageProxy::viewStateDidChange(ViewState::Flags mayHaveChanged)
 #endif
 }
 
+void WebPageProxy::viewDidLeaveWindow()
+{
+#if ENABLE(INPUT_TYPE_COLOR_POPOVER)
+    // When leaving the current page, close the popover color well.
+    if (m_colorPicker)
+        endColorPicker();
+#endif
+#if PLATFORM(IOS)
+    // When leaving the current page, close the video fullscreen.
+    if (m_videoFullscreenManager)
+        m_videoFullscreenManager->requestHideAndExitFullscreen();
+#endif
+}
+
+void WebPageProxy::viewDidEnterWindow()
+{
+    LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
+    if (m_layerHostingMode != layerHostingMode) {
+        m_layerHostingMode = layerHostingMode;
+        m_process->send(Messages::WebPage::SetLayerHostingMode(static_cast<unsigned>(layerHostingMode)), m_pageID);
+    }
+}
+
 void WebPageProxy::dispatchViewStateChange()
 {
 #if PLATFORM(COCOA)
@@ -1138,8 +1159,12 @@ void WebPageProxy::dispatchViewStateChange()
     updateViewState(m_potentiallyChangedViewStateFlags);
     ViewState::Flags changed = m_viewState ^ previousViewState;
 
+    // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
+    if (m_viewWasEverInWindow && (changed & ViewState::IsInWindow) && isInWindow())
+        m_viewStateChangeWantsReply = true;
+
     if (changed)
-        m_process->send(Messages::WebPage::SetViewState(m_viewState, m_viewStateChangeWantsReply == WantsReplyOrNot::DoesWantReply), m_pageID);
+        m_process->send(Messages::WebPage::SetViewState(m_viewState, m_viewStateChangeWantsReply), m_pageID);
 
     // This must happen after the SetViewState message is sent, to ensure the page visibility event can fire.
     updateActivityToken();
@@ -1153,34 +1178,20 @@ void WebPageProxy::dispatchViewStateChange()
     if ((changed & ViewState::IsVisible) && !isViewVisible())
         m_process->responsivenessTimer()->stop();
 
-    if ((m_potentiallyChangedViewStateFlags & ViewState::IsInWindow) && (m_viewState & ViewState::IsInWindow)) {
-        LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
-        if (m_layerHostingMode != layerHostingMode) {
-            m_layerHostingMode = layerHostingMode;
-            m_process->send(Messages::WebPage::SetLayerHostingMode(static_cast<unsigned>(layerHostingMode)), m_pageID);
-        }
-    }
-
-    if ((m_potentiallyChangedViewStateFlags & ViewState::IsInWindow) && !(m_viewState & ViewState::IsInWindow)) {
-#if ENABLE(INPUT_TYPE_COLOR_POPOVER)
-        // When leaving the current page, close the popover color well.
-        if (m_colorPicker)
-            endColorPicker();
-#endif
-#if PLATFORM(IOS)
-        // When leaving the current page, close the video fullscreen.
-        if (m_videoFullscreenManager)
-            m_videoFullscreenManager->requestHideAndExitFullscreen();
-#endif
+    if (changed & ViewState::IsInWindow) {
+        if (isInWindow())
+            viewDidEnterWindow();
+        else
+            viewDidLeaveWindow();
     }
 
     updateBackingStoreDiscardableState();
 
-    if (m_viewStateChangeWantsReply == WantsReplyOrNot::DoesWantReply)
+    if (m_viewStateChangeWantsReply)
         waitForDidUpdateViewState();
 
     m_potentiallyChangedViewStateFlags = ViewState::NoFlags;
-    m_viewStateChangeWantsReply = WantsReplyOrNot::DoesNotWantReply;
+    m_viewStateChangeWantsReply = false;
 }
 
 void WebPageProxy::updateActivityToken()
index ecf5d6e03f78f2a7dd4023d0ca0d1a8b27427325..eee6dc18aa051f1503fca78bdfe2227085ed7a47 100644 (file)
@@ -360,8 +360,7 @@ public:
     void setDelegatesScrolling(bool delegatesScrolling) { m_delegatesScrolling = delegatesScrolling; }
     bool delegatesScrolling() const { return m_delegatesScrolling; }
 
-    enum class WantsReplyOrNot { DoesNotWantReply, DoesWantReply };
-    void viewStateDidChange(WebCore::ViewState::Flags mayHaveChanged);
+    void viewStateDidChange(WebCore::ViewState::Flags mayHaveChanged, bool wantsReply = false);
     bool isInWindow() const { return m_viewState & WebCore::ViewState::IsInWindow; }
     void waitForDidUpdateViewState();
     void didUpdateViewState() { m_waitingForDidUpdateViewState = false; }
@@ -1266,6 +1265,8 @@ private:
     WebPreferencesStore preferencesStore() const;
 
     void dispatchViewStateChange();
+    void viewDidLeaveWindow();
+    void viewDidEnterWindow();
 
     PageClient& m_pageClient;
     std::unique_ptr<API::LoaderClient> m_loaderClient;
@@ -1513,7 +1514,7 @@ private:
 
     WebPreferencesStore::ValueMap m_configurationPreferenceValues;
     WebCore::ViewState::Flags m_potentiallyChangedViewStateFlags;
-    WantsReplyOrNot m_viewStateChangeWantsReply;
+    bool m_viewStateChangeWantsReply;
 };
 
 } // namespace WebKit
index 748f8e05c17882a1931a914a19be85db128232ba..4dc4c221c7e977987398d43761957e275a30f85f 100644 (file)
@@ -760,7 +760,7 @@ static void layerPath(CAShapeLayer *layer, const FloatQuad& outerQuad)
 - (void)_applicationWillEnterForeground:(NSNotification*)notification
 {
     _page->applicationWillEnterForeground();
-    _page->viewStateDidChange(ViewState::AllFlags & ~ViewState::IsInWindow);
+    _page->viewStateDidChange(ViewState::AllFlags & ~ViewState::IsInWindow, true);
 }
 
 - (void)_applicationDidBecomeActive:(NSNotification*)notification
index f24b0994a6c7100c5664b9005fee4c0d806e5872..06528eaee9ac35bfa80be8aa24104a08e186be0d 100644 (file)
@@ -101,6 +101,7 @@ public:
     virtual WebCore::GraphicsLayerFactory* graphicsLayerFactory() { return nullptr; }
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) = 0;
     virtual void scheduleCompositingLayerFlush() = 0;
+    virtual void scheduleCompositingLayerFlushImmediately() = 0;
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     virtual PassRefPtr<WebCore::DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID);
index c21187df3b17e8f75085f4d685aee11deef8fecf..f2646b3a485c76222134722bad362d7dc93823d5 100644 (file)
@@ -66,6 +66,7 @@ private:
     virtual WebCore::GraphicsLayerFactory* graphicsLayerFactory() override;
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) override;
     virtual void scheduleCompositingLayerFlush() override;
+    virtual void scheduleCompositingLayerFlushImmediately() override;
 
     virtual void addTransactionCallbackID(uint64_t callbackID) override;
 
index 17a574de4323f9bde2de56d548d06bf2eba78c4c..b47065c9d03030854353409b2e440f3b3fdb9498 100644 (file)
@@ -239,6 +239,11 @@ TiledBacking* RemoteLayerTreeDrawingArea::mainFrameTiledBacking() const
     return frameView ? frameView->tiledBacking() : nullptr;
 }
 
+void RemoteLayerTreeDrawingArea::scheduleCompositingLayerFlushImmediately()
+{
+    m_layerFlushTimer.startOneShot(0_ms);
+}
+
 void RemoteLayerTreeDrawingArea::scheduleCompositingLayerFlush()
 {
     if (m_isFlushingSuspended) {
@@ -248,7 +253,7 @@ void RemoteLayerTreeDrawingArea::scheduleCompositingLayerFlush()
     }
     if (m_isLayerFlushThrottlingTemporarilyDisabledForInteraction) {
         m_isLayerFlushThrottlingTemporarilyDisabledForInteraction = false;
-        m_layerFlushTimer.startOneShot(0_ms);
+        scheduleCompositingLayerFlushImmediately();
         return;
     }
 
@@ -427,6 +432,9 @@ void RemoteLayerTreeDrawingArea::BackingStoreFlusher::flush()
 void RemoteLayerTreeDrawingArea::viewStateDidChange(ViewState::Flags, bool wantsDidUpdateViewState)
 {
     // FIXME: Should we suspend painting while not visible, like TiledCoreAnimationDrawingArea? Probably.
+
+    if (wantsDidUpdateViewState)
+        scheduleCompositingLayerFlushImmediately();
 }
 
 void RemoteLayerTreeDrawingArea::addTransactionCallbackID(uint64_t callbackID)
index db02f4b134c78dccc6483c0baa328e6a4e2fc257..c31fc24aea8a3f7a97039a68198d1a34324a5aaa 100644 (file)
@@ -67,6 +67,7 @@ private:
     virtual bool layerTreeStateIsFrozen() const override;
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) override;
     virtual void scheduleCompositingLayerFlush() override;
+    virtual void scheduleCompositingLayerFlushImmediately() override;
 
     virtual void updatePreferences(const WebPreferencesStore&) override;
     virtual void mainFrameContentSizeChanged(const WebCore::IntSize&) override;
index 263f3275c43503dfa159077fa0967d51bbf0e68b..94f479027b442349234c3128454c1816a693ddcc 100644 (file)
@@ -174,6 +174,11 @@ void TiledCoreAnimationDrawingArea::scheduleCompositingLayerFlush()
     m_layerFlushScheduler.schedule();
 }
 
+void TiledCoreAnimationDrawingArea::scheduleCompositingLayerFlushImmediately()
+{
+    scheduleCompositingLayerFlush();
+}
+
 void TiledCoreAnimationDrawingArea::updatePreferences(const WebPreferencesStore&)
 {
     Settings& settings = m_webPage.corePage()->settings();