Crash under RemoteLayerTreePropertyApplier::applyProperties when reattaching to old...
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Feb 2019 21:34:26 +0000 (21:34 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Feb 2019 21:34:26 +0000 (21:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194845
<rdar://problem/47944579>

Reviewed by Antti Koivisto.

Source/WebKit:

New test: ProcessSwap.PageOverlayLayerPersistence

* Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::LayerProperties::notePropertiesChanged):
Keep track of all properties that have ever changed on a layer, so we
can re-send them if a layer moves between contexts.

* WebProcess/WebPage/DrawingArea.cpp:
(WebKit::DrawingArea::~DrawingArea):
(WebKit::DrawingArea::removeMessageReceiverIfNeeded):
* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::layerHostDidFlushLayers):
Make it possible to tear down DrawingArea's MessageReceiver before it is destroyed,
so that we can keep two DrawingAreas alive in a single process for a short time.

(WebKit::DrawingArea::adoptLayersFromDrawingArea):
Add adoptLayersFromDrawingArea; see below for its only useful implementation.

* WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.cpp:
(WebKit::GraphicsLayerCARemote::GraphicsLayerCARemote):
(WebKit::GraphicsLayerCARemote::~GraphicsLayerCARemote):
(WebKit::GraphicsLayerCARemote::createPlatformCALayer):
(WebKit::GraphicsLayerCARemote::createPlatformCALayerForEmbeddedView):
(WebKit::GraphicsLayerCARemote::moveToContext):
* WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.h:
Make it possible to move a GraphicsLayerCARemote between RemoteLayerTreeContexts.

* WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp:
(WebKit::PlatformCALayerRemote::create):
(WebKit::PlatformCALayerRemote::createForEmbeddedView):
(WebKit::PlatformCALayerRemote::~PlatformCALayerRemote):
(WebKit::PlatformCALayerRemote::moveToContext):
* WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h:
* WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemoteCustom.mm:
(WebKit::PlatformCALayerRemoteCustom::create):
(WebKit::PlatformCALayerRemoteCustom::clone const):
Make it possible to move a PlatformCALayerRemote between RemoteLayerTreeContexts.

* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.mm:
(WebKit::RemoteLayerTreeContext::~RemoteLayerTreeContext):
(WebKit::RemoteLayerTreeContext::adoptLayersFromContext):
(WebKit::RemoteLayerTreeContext::layerDidEnterContext):
(WebKit::RemoteLayerTreeContext::layerWillLeaveContext):
(WebKit::RemoteLayerTreeContext::graphicsLayerDidEnterContext):
(WebKit::RemoteLayerTreeContext::graphicsLayerWillLeaveContext):
(WebKit::RemoteLayerTreeContext::layerWasCreated): Deleted.
(WebKit::RemoteLayerTreeContext::layerWillBeDestroyed): Deleted.
Keep track of all GraphicsLayerCARemote instances in the context, like we
do for PlatformCALayerRemote, so that we can update their context backpointers if needed.

Also make it possible to move all outstanding layers to a new context.

* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::adoptLayersFromDrawingArea):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::reinitializeWebPage):
When doing a DrawingArea swap, transition all layers from the old context
to the new one. In order to do this, we temporarily keep both DrawingAreas
alive, but make use of the new mechanism to remove the old one's MessageReceiver
before installing the new one, so that destroying the old one later doesn't
remove it (avoiding re-introducing bug 189481).

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:

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

18 files changed:
Source/WebKit/ChangeLog
Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h
Source/WebKit/WebProcess/WebPage/DrawingArea.cpp
Source/WebKit/WebProcess/WebPage/DrawingArea.h
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.cpp
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.h
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemoteCustom.mm
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.h
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.mm
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h
Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/PageOverlayPlugin.mm [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

index 4cfd434..45fd995 100644 (file)
@@ -1,3 +1,75 @@
+2019-02-21  Tim Horton  <timothy_horton@apple.com>
+
+        Crash under RemoteLayerTreePropertyApplier::applyProperties when reattaching to old process
+        https://bugs.webkit.org/show_bug.cgi?id=194845
+        <rdar://problem/47944579>
+
+        Reviewed by Antti Koivisto.
+
+        New test: ProcessSwap.PageOverlayLayerPersistence
+
+        * Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h:
+        (WebKit::RemoteLayerTreeTransaction::LayerProperties::notePropertiesChanged):
+        Keep track of all properties that have ever changed on a layer, so we
+        can re-send them if a layer moves between contexts.
+
+        * WebProcess/WebPage/DrawingArea.cpp:
+        (WebKit::DrawingArea::~DrawingArea):
+        (WebKit::DrawingArea::removeMessageReceiverIfNeeded):
+        * WebProcess/WebPage/DrawingArea.h:
+        (WebKit::DrawingArea::layerHostDidFlushLayers):
+        Make it possible to tear down DrawingArea's MessageReceiver before it is destroyed,
+        so that we can keep two DrawingAreas alive in a single process for a short time.
+
+        (WebKit::DrawingArea::adoptLayersFromDrawingArea):
+        Add adoptLayersFromDrawingArea; see below for its only useful implementation.
+
+        * WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.cpp:
+        (WebKit::GraphicsLayerCARemote::GraphicsLayerCARemote):
+        (WebKit::GraphicsLayerCARemote::~GraphicsLayerCARemote):
+        (WebKit::GraphicsLayerCARemote::createPlatformCALayer):
+        (WebKit::GraphicsLayerCARemote::createPlatformCALayerForEmbeddedView):
+        (WebKit::GraphicsLayerCARemote::moveToContext):
+        * WebProcess/WebPage/RemoteLayerTree/GraphicsLayerCARemote.h:
+        Make it possible to move a GraphicsLayerCARemote between RemoteLayerTreeContexts.
+
+        * WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp:
+        (WebKit::PlatformCALayerRemote::create):
+        (WebKit::PlatformCALayerRemote::createForEmbeddedView):
+        (WebKit::PlatformCALayerRemote::~PlatformCALayerRemote):
+        (WebKit::PlatformCALayerRemote::moveToContext):
+        * WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h:
+        * WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemoteCustom.mm:
+        (WebKit::PlatformCALayerRemoteCustom::create):
+        (WebKit::PlatformCALayerRemoteCustom::clone const):
+        Make it possible to move a PlatformCALayerRemote between RemoteLayerTreeContexts.
+
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.h:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeContext.mm:
+        (WebKit::RemoteLayerTreeContext::~RemoteLayerTreeContext):
+        (WebKit::RemoteLayerTreeContext::adoptLayersFromContext):
+        (WebKit::RemoteLayerTreeContext::layerDidEnterContext):
+        (WebKit::RemoteLayerTreeContext::layerWillLeaveContext):
+        (WebKit::RemoteLayerTreeContext::graphicsLayerDidEnterContext):
+        (WebKit::RemoteLayerTreeContext::graphicsLayerWillLeaveContext):
+        (WebKit::RemoteLayerTreeContext::layerWasCreated): Deleted.
+        (WebKit::RemoteLayerTreeContext::layerWillBeDestroyed): Deleted.
+        Keep track of all GraphicsLayerCARemote instances in the context, like we
+        do for PlatformCALayerRemote, so that we can update their context backpointers if needed.
+
+        Also make it possible to move all outstanding layers to a new context.
+
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::adoptLayersFromDrawingArea):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::reinitializeWebPage):
+        When doing a DrawingArea swap, transition all layers from the old context
+        to the new one. In order to do this, we temporarily keep both DrawingAreas
+        alive, but make use of the new mechanism to remove the old one's MessageReceiver
+        before installing the new one, so that destroying the old one later doesn't
+        remove it (avoiding re-introducing bug 189481).
+
 2019-02-21  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed API test fix after r241855.
index c7acbbc..54d99ca 100644 (file)
@@ -119,6 +119,7 @@ public:
         void notePropertiesChanged(OptionSet<LayerChange> changeFlags)
         {
             changedProperties.add(changeFlags);
+            everChangedProperties.add(changeFlags);
         }
 
         void resetChangedProperties()
@@ -127,6 +128,7 @@ public:
         }
 
         OptionSet<LayerChange> changedProperties;
+        OptionSet<LayerChange> everChangedProperties;
 
         String name;
         std::unique_ptr<WebCore::TransformationMatrix> transform;
index a45abfd..2087d13 100644 (file)
@@ -78,7 +78,7 @@ DrawingArea::DrawingArea(DrawingAreaType type, WebPage& webPage)
 
 DrawingArea::~DrawingArea()
 {
-    WebProcess::singleton().removeMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_webPage.pageID());
+    removeMessageReceiverIfNeeded();
 }
 
 void DrawingArea::dispatchAfterEnsuringUpdatedScrollPosition(WTF::Function<void ()>&& function)
@@ -94,4 +94,12 @@ RefPtr<WebCore::DisplayRefreshMonitor> DrawingArea::createDisplayRefreshMonitor(
 }
 #endif
 
+void DrawingArea::removeMessageReceiverIfNeeded()
+{
+    if (m_hasRemovedMessageReceiver)
+        return;
+    m_hasRemovedMessageReceiver = true;
+    WebProcess::singleton().removeMessageReceiver(Messages::DrawingArea::messageReceiverName(), m_webPage.pageID());
+}
+
 } // namespace WebKit
index 7ee228c..347c845 100644 (file)
@@ -140,7 +140,7 @@ public:
     virtual void updateGeometry(const WebCore::IntSize& viewSize, bool flushSynchronously, const WTF::MachSendRight& fencePort) { }
 #endif
 
-    virtual void layerHostDidFlushLayers() { };
+    virtual void layerHostDidFlushLayers() { }
 
 #if USE(COORDINATED_GRAPHICS)
     virtual void didChangeViewportAttributes(WebCore::ViewportAttributes&&) = 0;
@@ -150,6 +150,10 @@ public:
     virtual void deviceOrPageScaleFactorChanged() = 0;
 #endif
 
+    virtual void adoptLayersFromDrawingArea(DrawingArea&) { }
+
+    void removeMessageReceiverIfNeeded();
+
 protected:
     DrawingArea(DrawingAreaType, WebPage&);
 
@@ -186,6 +190,8 @@ private:
     virtual void setNativeSurfaceHandleForCompositing(uint64_t) = 0;
     virtual void destroyNativeSurfaceHandleForCompositing(bool&) = 0;
 #endif
+
+    bool m_hasRemovedMessageReceiver { false };
 };
 
 } // namespace WebKit
index 95afd86..8c21d15 100644 (file)
 
 #include "PlatformCAAnimationRemote.h"
 #include "PlatformCALayerRemote.h"
+#include "RemoteLayerTreeContext.h"
 #include <WebCore/PlatformScreen.h>
 
 namespace WebKit {
 using namespace WebCore;
 
+GraphicsLayerCARemote::GraphicsLayerCARemote(Type layerType, GraphicsLayerClient& client, RemoteLayerTreeContext& context)
+    : GraphicsLayerCA(layerType, client)
+    , m_context(&context)
+{
+    context.graphicsLayerDidEnterContext(*this);
+}
+
 GraphicsLayerCARemote::~GraphicsLayerCARemote()
 {
+    if (m_context)
+        m_context->graphicsLayerWillLeaveContext(*this);
 }
 
 bool GraphicsLayerCARemote::filtersCanBeComposited(const FilterOperations& filters)
@@ -44,7 +54,7 @@ bool GraphicsLayerCARemote::filtersCanBeComposited(const FilterOperations& filte
 
 Ref<PlatformCALayer> GraphicsLayerCARemote::createPlatformCALayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* owner)
 {
-    auto result = PlatformCALayerRemote::create(layerType, owner, m_context);
+    auto result = PlatformCALayerRemote::create(layerType, owner, *m_context);
 
     if (result->canHaveBackingStore())
         result->setWantsDeepColorBackingStore(screenSupportsExtendedColor());
@@ -54,12 +64,12 @@ Ref<PlatformCALayer> GraphicsLayerCARemote::createPlatformCALayer(PlatformCALaye
 
 Ref<PlatformCALayer> GraphicsLayerCARemote::createPlatformCALayer(PlatformLayer* platformLayer, PlatformCALayerClient* owner)
 {
-    return PlatformCALayerRemote::create(platformLayer, owner, m_context);
+    return PlatformCALayerRemote::create(platformLayer, owner, *m_context);
 }
 
 Ref<PlatformCALayer> GraphicsLayerCARemote::createPlatformCALayerForEmbeddedView(PlatformCALayer::LayerType layerType, GraphicsLayer::EmbeddedViewID embeddedViewID, PlatformCALayerClient* owner)
 {
-    return PlatformCALayerRemote::createForEmbeddedView(layerType, embeddedViewID, owner, m_context);
+    return PlatformCALayerRemote::createForEmbeddedView(layerType, embeddedViewID, owner, *m_context);
 }
 
 Ref<PlatformCAAnimation> GraphicsLayerCARemote::createPlatformCAAnimation(PlatformCAAnimation::AnimationType type, const String& keyPath)
@@ -67,4 +77,14 @@ Ref<PlatformCAAnimation> GraphicsLayerCARemote::createPlatformCAAnimation(Platfo
     return PlatformCAAnimationRemote::create(type, keyPath);
 }
 
+void GraphicsLayerCARemote::moveToContext(RemoteLayerTreeContext& context)
+{
+    if (m_context)
+        m_context->graphicsLayerWillLeaveContext(*this);
+
+    m_context = &context;
+
+    context.graphicsLayerDidEnterContext(*this);
+}
+
 } // namespace WebKit
index db56c85..5c11881 100644 (file)
@@ -34,16 +34,14 @@ class RemoteLayerTreeContext;
 
 class GraphicsLayerCARemote final : public WebCore::GraphicsLayerCA {
 public:
-    GraphicsLayerCARemote(Type layerType, WebCore::GraphicsLayerClient& client, RemoteLayerTreeContext& context)
-        : GraphicsLayerCA(layerType, client)
-        , m_context(context)
-    {
-    }
-
+    GraphicsLayerCARemote(Type layerType, WebCore::GraphicsLayerClient&, RemoteLayerTreeContext&);
     virtual ~GraphicsLayerCARemote();
 
     bool filtersCanBeComposited(const WebCore::FilterOperations& filters) override;
 
+    void moveToContext(RemoteLayerTreeContext&);
+    void clearContext() { m_context = nullptr; }
+
 private:
     bool isGraphicsLayerCARemote() const override { return true; }
 
@@ -55,7 +53,7 @@ private:
     // PlatformCALayerRemote can't currently proxy directly composited image contents, so opt out of this optimization.
     bool shouldDirectlyCompositeImage(WebCore::Image*) const override { return false; }
     
-    RemoteLayerTreeContext& m_context;
+    RemoteLayerTreeContext* m_context;
 };
 
 } // namespace WebKit
index eca95e7..86bcaec 100644 (file)
@@ -51,7 +51,7 @@ Ref<PlatformCALayerRemote> PlatformCALayerRemote::create(LayerType layerType, Pl
     else
         layer = adoptRef(new PlatformCALayerRemote(layerType, owner, context));
 
-    context.layerWasCreated(*layer, layerType);
+    context.layerDidEnterContext(*layer, layerType);
 
     return layer.releaseNonNull();
 }
@@ -64,7 +64,7 @@ Ref<PlatformCALayerRemote> PlatformCALayerRemote::create(PlatformLayer *platform
 Ref<PlatformCALayerRemote> PlatformCALayerRemote::createForEmbeddedView(LayerType layerType, GraphicsLayer::EmbeddedViewID embeddedViewID, PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
 {
     RefPtr<PlatformCALayerRemote> layer = adoptRef(new PlatformCALayerRemote(layerType, embeddedViewID, owner, context));
-    context.layerWasCreated(*layer, layerType);
+    context.layerDidEnterContext(*layer, layerType);
     return layer.releaseNonNull();
 }
 
@@ -72,7 +72,7 @@ Ref<PlatformCALayerRemote> PlatformCALayerRemote::create(const PlatformCALayerRe
 {
     auto layer = adoptRef(*new PlatformCALayerRemote(other, owner, context));
 
-    context.layerWasCreated(layer.get(), other.layerType());
+    context.layerDidEnterContext(layer.get(), other.layerType());
 
     return layer;
 }
@@ -116,7 +116,19 @@ PlatformCALayerRemote::~PlatformCALayerRemote()
         downcast<PlatformCALayerRemote>(*layer).m_superlayer = nullptr;
 
     if (m_context)
-        m_context->layerWillBeDestroyed(*this);
+        m_context->layerWillLeaveContext(*this);
+}
+
+void PlatformCALayerRemote::moveToContext(RemoteLayerTreeContext& context)
+{
+    if (m_context)
+        m_context->layerWillLeaveContext(*this);
+
+    m_context = &context;
+
+    context.layerDidEnterContext(*this, layerType());
+
+    m_properties.notePropertiesChanged(m_properties.everChangedProperties);
 }
 
 void PlatformCALayerRemote::updateClonedLayerProperties(PlatformCALayerRemote& clone, bool copyContents) const
index c28c403..6ddd1ed 100644 (file)
@@ -195,6 +195,7 @@ public:
 
     void didCommit();
 
+    void moveToContext(RemoteLayerTreeContext&);
     void clearContext() { m_context = nullptr; }
     RemoteLayerTreeContext* context() const { return m_context; }
 
index 583614a..5bdfb6d 100644 (file)
@@ -48,7 +48,7 @@ static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
 Ref<PlatformCALayerRemote> PlatformCALayerRemoteCustom::create(PlatformLayer *platformLayer, PlatformCALayerClient* owner, RemoteLayerTreeContext& context)
 {
     auto layer = adoptRef(*new PlatformCALayerRemoteCustom(PlatformCALayerCocoa::layerTypeForPlatformLayer(platformLayer), platformLayer, owner, context));
-    context.layerWasCreated(layer.get(), layer->layerType());
+    context.layerDidEnterContext(layer.get(), layer->layerType());
     return WTFMove(layer);
 }
 
@@ -126,7 +126,7 @@ Ref<WebCore::PlatformCALayer> PlatformCALayerRemoteCustom::clone(PlatformCALayer
     }
 
     auto clone = adoptRef(*new PlatformCALayerRemoteCustom(layerType(), clonedLayer.get(), owner, *context()));
-    context()->layerWasCreated(clone.get(), clone->layerType());
+    context()->layerDidEnterContext(clone.get(), clone->layerType());
 
     updateClonedLayerProperties(clone.get(), copyContents);
 
index 9a413f3..d408057 100644 (file)
@@ -35,6 +35,7 @@
 
 namespace WebKit {
 
+class GraphicsLayerCARemote;
 class PlatformCALayerRemote;
 class WebPage;
 
@@ -44,8 +45,11 @@ public:
     explicit RemoteLayerTreeContext(WebPage&);
     ~RemoteLayerTreeContext();
 
-    void layerWasCreated(PlatformCALayerRemote&, WebCore::PlatformCALayer::LayerType);
-    void layerWillBeDestroyed(PlatformCALayerRemote&);
+    void layerDidEnterContext(PlatformCALayerRemote&, WebCore::PlatformCALayer::LayerType);
+    void layerWillLeaveContext(PlatformCALayerRemote&);
+
+    void graphicsLayerDidEnterContext(GraphicsLayerCARemote&);
+    void graphicsLayerWillLeaveContext(GraphicsLayerCARemote&);
 
     void backingStoreWasCreated(RemoteLayerBackingStore&);
     void backingStoreWillBeDestroyed(RemoteLayerBackingStore&);
@@ -72,6 +76,8 @@ public:
     void setNextFlushIsForImmediatePaint(bool nextFlushIsForImmediatePaint) { m_nextFlushIsForImmediatePaint = nextFlushIsForImmediatePaint; }
     bool nextFlushIsForImmediatePaint() const { return m_nextFlushIsForImmediatePaint; }
 
+    void adoptLayersFromContext(RemoteLayerTreeContext&);
+
 private:
     // WebCore::GraphicsLayerFactory
     Ref<WebCore::GraphicsLayer> createGraphicsLayer(WebCore::GraphicsLayer::Type, WebCore::GraphicsLayerClient&) override;
@@ -81,9 +87,11 @@ private:
     HashMap<WebCore::GraphicsLayer::PlatformLayerID, RemoteLayerTreeTransaction::LayerCreationProperties> m_createdLayers;
     Vector<WebCore::GraphicsLayer::PlatformLayerID> m_destroyedLayers;
 
-    HashMap<WebCore::GraphicsLayer::PlatformLayerID, PlatformCALayerRemote*> m_liveLayers;
+    HashMap<WebCore::GraphicsLayer::PlatformLayerID, PlatformCALayerRemote*> m_livePlatformLayers;
     HashMap<WebCore::GraphicsLayer::PlatformLayerID, PlatformCALayerRemote*> m_layersWithAnimations;
 
+    HashSet<GraphicsLayerCARemote*> m_liveGraphicsLayers;
+
     RemoteLayerBackingStoreCollection m_backingStoreCollection;
     
     RemoteLayerTreeTransaction* m_currentTransaction;
index 9dca45b..68b157a 100644 (file)
@@ -49,8 +49,23 @@ RemoteLayerTreeContext::RemoteLayerTreeContext(WebPage& webPage)
 
 RemoteLayerTreeContext::~RemoteLayerTreeContext()
 {
-    for (auto& layer : m_liveLayers.values())
+    for (auto& layer : m_livePlatformLayers.values())
         layer->clearContext();
+
+    auto graphicsLayers = m_liveGraphicsLayers;
+    for (auto& layer : graphicsLayers)
+        layer->clearContext();
+}
+
+void RemoteLayerTreeContext::adoptLayersFromContext(RemoteLayerTreeContext& oldContext)
+{
+    auto& platformLayers = oldContext.m_livePlatformLayers;
+    while (!platformLayers.isEmpty())
+        platformLayers.begin()->value->moveToContext(*this);
+
+    auto& graphicsLayers = oldContext.m_liveGraphicsLayers;
+    while (!graphicsLayers.isEmpty())
+        (*graphicsLayers.begin())->moveToContext(*this);
 }
 
 float RemoteLayerTreeContext::deviceScaleFactor() const
@@ -63,7 +78,7 @@ LayerHostingMode RemoteLayerTreeContext::layerHostingMode() const
     return m_webPage.layerHostingMode();
 }
 
-void RemoteLayerTreeContext::layerWasCreated(PlatformCALayerRemote& layer, PlatformCALayer::LayerType type)
+void RemoteLayerTreeContext::layerDidEnterContext(PlatformCALayerRemote& layer, PlatformCALayer::LayerType type)
 {
     GraphicsLayer::PlatformLayerID layerID = layer.layerID();
 
@@ -78,16 +93,16 @@ void RemoteLayerTreeContext::layerWasCreated(PlatformCALayerRemote& layer, Platf
     }
 
     m_createdLayers.add(layerID, WTFMove(creationProperties));
-    m_liveLayers.add(layerID, &layer);
+    m_livePlatformLayers.add(layerID, &layer);
 }
 
-void RemoteLayerTreeContext::layerWillBeDestroyed(PlatformCALayerRemote& layer)
+void RemoteLayerTreeContext::layerWillLeaveContext(PlatformCALayerRemote& layer)
 {
     ASSERT(layer.layerID());
     GraphicsLayer::PlatformLayerID layerID = layer.layerID();
 
     m_createdLayers.remove(layerID);
-    m_liveLayers.remove(layerID);
+    m_livePlatformLayers.remove(layerID);
 
     ASSERT(!m_destroyedLayers.contains(layerID));
     m_destroyedLayers.append(layerID);
@@ -95,6 +110,16 @@ void RemoteLayerTreeContext::layerWillBeDestroyed(PlatformCALayerRemote& layer)
     m_layersWithAnimations.remove(layerID);
 }
 
+void RemoteLayerTreeContext::graphicsLayerDidEnterContext(GraphicsLayerCARemote& layer)
+{
+    m_liveGraphicsLayers.add(&layer);
+}
+
+void RemoteLayerTreeContext::graphicsLayerWillLeaveContext(GraphicsLayerCARemote& layer)
+{
+    m_liveGraphicsLayers.remove(&layer);
+}
+
 void RemoteLayerTreeContext::backingStoreWasCreated(RemoteLayerBackingStore& backingStore)
 {
     m_backingStoreCollection.backingStoreWasCreated(backingStore);
index 711e258..b923bf3 100644 (file)
@@ -123,6 +123,8 @@ private:
 
     bool markLayersVolatileImmediatelyIfPossible() override;
 
+    void adoptLayersFromDrawingArea(DrawingArea&) override;
+
     class BackingStoreFlusher : public ThreadSafeRefCounted<BackingStoreFlusher> {
     public:
         static Ref<BackingStoreFlusher> create(IPC::Connection*, std::unique_ptr<IPC::Encoder>, Vector<RetainPtr<CGContextRef>>);
index 8e961e0..5798351 100644 (file)
@@ -532,4 +532,13 @@ bool RemoteLayerTreeDrawingArea::dispatchDidReachLayoutMilestone(OptionSet<WebCo
     return true;
 }
 
+void RemoteLayerTreeDrawingArea::adoptLayersFromDrawingArea(DrawingArea& oldDrawingArea)
+{
+    RELEASE_ASSERT(oldDrawingArea.type() == type());
+
+    RemoteLayerTreeDrawingArea& oldRemoteDrawingArea = static_cast<RemoteLayerTreeDrawingArea&>(oldDrawingArea);
+
+    m_remoteLayerTreeContext->adoptLayersFromContext(*oldRemoteDrawingArea.m_remoteLayerTreeContext);
+}
+
 } // namespace WebKit
index 085d82a..727e01e 100644 (file)
@@ -695,9 +695,8 @@ void WebPage::reinitializeWebPage(WebPageCreationParameters&& parameters)
     setSize(parameters.viewSize);
 
     if (m_shouldResetDrawingAreaAfterSuspend) {
-        // Make sure we destroy the previous drawing area before constructing the new one as DrawingArea registers / unregisters
-        // itself as an IPC::MesssageReceiver in its constructor / destructor.
-        m_drawingArea = nullptr;
+        auto oldDrawingArea = std::exchange(m_drawingArea, nullptr);
+        oldDrawingArea->removeMessageReceiverIfNeeded();
         m_shouldResetDrawingAreaAfterSuspend = false;
 
         m_drawingArea = DrawingArea::create(*this, parameters);
@@ -705,6 +704,9 @@ void WebPage::reinitializeWebPage(WebPageCreationParameters&& parameters)
         m_drawingArea->setShouldScaleViewToFitDocument(parameters.shouldScaleViewToFitDocument);
         m_drawingArea->updatePreferences(parameters.store);
         m_drawingArea->setPaintingEnabled(true);
+
+        m_drawingArea->adoptLayersFromDrawingArea(*oldDrawingArea);
+
         unfreezeLayerTree(LayerTreeFreezeReason::PageSuspended);
     }
 
index e178f87..44db442 100644 (file)
@@ -1,3 +1,14 @@
+2019-02-21  Tim Horton  <timothy_horton@apple.com>
+
+        Crash under RemoteLayerTreePropertyApplier::applyProperties when reattaching to old process
+        https://bugs.webkit.org/show_bug.cgi?id=194845
+        <rdar://problem/47944579>
+
+        Reviewed by Antti Koivisto.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+
 2019-02-21  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][Floats] Add support for placing formatting roots in-between floats.
index fe8571a..ad6c509 100644 (file)
@@ -92,6 +92,7 @@
                2D1646E21D1862CD00015A1A /* DeferredViewInWindowStateChange.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D1646E11D1862CD00015A1A /* DeferredViewInWindowStateChange.mm */; };
                2D1C04A71D76298B000A6816 /* TestNavigationDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D1C04A61D76298B000A6816 /* TestNavigationDelegate.mm */; };
                2D21FE591F04642900B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D21FE581F04642800B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm */; };
+               2D3CA3A8221DF4B40088E803 /* PageOverlayPlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D3CA3A4221DF2390088E803 /* PageOverlayPlugin.mm */; };
                2D4CF8BD1D8360CC0001CE8D /* WKThumbnailView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D4CF8BC1D8360CC0001CE8D /* WKThumbnailView.mm */; };
                2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */; };
                2D70059621EDA0C6003463CB /* TabOutOfWebView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */; };
                2D1C04A61D76298B000A6816 /* TestNavigationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestNavigationDelegate.mm; path = cocoa/TestNavigationDelegate.mm; sourceTree = "<group>"; };
                2D1FE0AF1AD465C1006CD9E6 /* FixedLayoutSize.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FixedLayoutSize.mm; sourceTree = "<group>"; };
                2D21FE581F04642800B58E7D /* WKPDFViewStablePresentationUpdateCallback.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKPDFViewStablePresentationUpdateCallback.mm; sourceTree = "<group>"; };
+               2D3CA3A4221DF2390088E803 /* PageOverlayPlugin.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PageOverlayPlugin.mm; sourceTree = "<group>"; };
                2D4CF8BC1D8360CC0001CE8D /* WKThumbnailView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WKThumbnailView.mm; path = WebKit/WKThumbnailView.mm; sourceTree = "<group>"; };
                2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMHTMLVideoElementWrapper.mm; sourceTree = "<group>"; };
                2D61EC3021B0B75C00A7D1CB /* PencilKitTestSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PencilKitTestSPI.h; sourceTree = "<group>"; };
                                37A22AA51DCAA27200AFBFC4 /* ObservedRenderingProgressEventsAfterCrash.mm */,
                                CEA6CF2219CCF5BD0064F5A7 /* OpenAndCloseWindow.mm */,
                                CEBCA12E1E3A660100C73293 /* OverrideContentSecurityPolicy.mm */,
+                               2D3CA3A4221DF2390088E803 /* PageOverlayPlugin.mm */,
                                F44C79FB20F9E50C0014478C /* ParserYieldTokenPlugIn.mm */,
                                F44C79FD20F9E8710014478C /* ParserYieldTokenTests.h */,
                                F44C79FE20F9E8710014478C /* ParserYieldTokenTests.mm */,
                                5CB5B3C21FFC55CF00C27BB0 /* FrameHandleSerialization.mm in Sources */,
                                0E404A8C2166DE0A008271BA /* InjectedBundleNodeHandleIsSelectElement.mm in Sources */,
                                79C5D431209D768300F1E7CA /* InjectedBundleNodeHandleIsTextField.mm in Sources */,
+                               2D3CA3A8221DF4B40088E803 /* PageOverlayPlugin.mm in Sources */,
                                F44C7A0020F9EEBF0014478C /* ParserYieldTokenPlugIn.mm in Sources */,
                                A13EBBAB1B87434600097110 /* PlatformUtilitiesCocoa.mm in Sources */,
                                1A4F81CF1BDFFD53004E672E /* RemoteObjectRegistryPlugIn.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/PageOverlayPlugin.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/PageOverlayPlugin.mm
new file mode 100644 (file)
index 0000000..e3ee4e0
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if WK_API_ENABLED
+
+#import "PlatformUtilities.h"
+#import <WebKit/WKBundlePage.h>
+#import <WebKit/WKBundlePageOverlay.h>
+#import <WebKit/WKWebProcessPlugIn.h>
+#import <WebKit/WKWebProcessPlugInBrowserContextControllerPrivate.h>
+#import <WebKit/WKWebProcessPlugInFrame.h>
+#import <WebKit/WKWebProcessPlugInLoadDelegate.h>
+#import <wtf/RetainPtr.h>
+
+@interface PageOverlayPlugIn : NSObject <WKWebProcessPlugIn>
+@end
+
+@implementation PageOverlayPlugIn
+
+- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
+{
+    WKBundlePageOverlayClientV1 overlayClient = {
+        { 1, 0 },
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+    };
+
+    WKBundlePageRef page = browserContextController._bundlePageRef;
+
+    WKBundlePageOverlayRef pageOverlay = WKBundlePageOverlayCreate((WKBundlePageOverlayClientBase*)&overlayClient);
+    WKBundlePageInstallPageOverlay(page, pageOverlay);
+}
+
+@end
+
+#endif // WK_API_ENABLED
index 37f6773..499d2b6 100644 (file)
@@ -5136,4 +5136,66 @@ TEST(ProcessSwap, GetUserMediaCaptureState)
     EXPECT_FALSE(pid1 == pid2);
 }
 
+static void traverseLayerTree(CALayer *layer, void(^block)(CALayer *))
+{
+    for (CALayer *child in layer.sublayers)
+        traverseLayerTree(child, block);
+    block(layer);
+}
+
+static bool hasOverlay(CALayer *layer)
+{
+    __block bool hasViewOverlay = false;
+    traverseLayerTree(layer, ^(CALayer *layer) {
+        if ([layer.name isEqualToString:@"View overlay container"])
+            hasViewOverlay = true;
+    });
+    return hasViewOverlay;
+}
+
+TEST(ProcessSwap, PageOverlayLayerPersistence)
+{
+    auto processPoolConfiguration = psonProcessPoolConfiguration();
+    [processPoolConfiguration setInjectedBundleURL:[[NSBundle mainBundle] URLForResource:@"TestWebKitAPI" withExtension:@"wkbundle"]];
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+    [processPool _setObject:@"PageOverlayPlugIn" forBundleParameter:TestWebKitAPI::Util::TestPlugInClassNameParameter];
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson://www.webkit.org/page-overlay" toData:""];
+    [handler addMappingFromURLString:@"pson://www.apple.com/page-overlay" toData:""];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    auto request = adoptNS([NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/page-overlay"]]);
+    [webView loadRequest:request.get()];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    [webView waitForNextPresentationUpdate];
+
+    EXPECT_TRUE(hasOverlay([webView layer]));
+
+    request = adoptNS([NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/page-overlay"]]);
+    [webView loadRequest:request.get()];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    [webView waitForNextPresentationUpdate];
+
+    [webView goBack]; // Back to webkit.org.
+
+    [webView waitForNextPresentationUpdate];
+
+    EXPECT_TRUE(hasOverlay([webView layer]));
+}
+
 #endif // WK_API_ENABLED