ASSERT at PlatformCALayerCocoa::avPlayerLayer(): [platformLayer() sublayers].count...
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Nov 2019 01:04:57 +0000 (01:04 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Nov 2019 01:04:57 +0000 (01:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204077
<rdar://problem/56640423>

Reviewed by Simon Fraser.

Make PlatformCALayerCocoa::avPlayer() more robust against underlying layer changes.

Promote WebVideoContainerLayer to its own header file and give the class a "playerLayer" property. In
PlatformCALayerCocoa::avPlayer(), use that new property to retrieve the AVPlayerLayer.

Drive-by fix: Make PlatformCALayerCocoa::create() return a Ref<PlatformCALayerCocoa> rather than its parent class type.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/avfoundation/objc/VideoFullscreenLayerManagerObjC.h:
* platform/graphics/avfoundation/objc/VideoFullscreenLayerManagerObjC.mm:
(WebCore::VideoFullscreenLayerManagerObjC::setVideoLayer):
(-[WebVideoContainerLayer setBounds:]): Deleted.
(-[WebVideoContainerLayer setPosition:]): Deleted.
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
(WebCore::PlatformCALayerCocoa::create):
(WebCore::PlatformCALayerCocoa::layerTypeForPlatformLayer):
(WebCore::PlatformCALayerCocoa::clone const):
(WebCore::PlatformCALayerCocoa::avPlayerLayer const):
* platform/graphics/ca/cocoa/WebVideoContainerLayer.h: Added.
* platform/graphics/ca/cocoa/WebVideoContainerLayer.mm: Added.
(-[WebVideoContainerLayer initWithPlayerLayer:]):
(-[WebVideoContainerLayer playerLayer]):
(-[WebVideoContainerLayer setBounds:]):
(-[WebVideoContainerLayer setPosition:]):

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

Source/WebCore/ChangeLog
Source/WebCore/SourcesCocoa.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManagerObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManagerObjC.mm
Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h
Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm
Source/WebCore/platform/graphics/ca/cocoa/WebVideoContainerLayer.h [new file with mode: 0644]
Source/WebCore/platform/graphics/ca/cocoa/WebVideoContainerLayer.mm [new file with mode: 0644]

index 3e78225..061d102 100644 (file)
@@ -1,3 +1,38 @@
+2019-11-11  Jer Noble  <jer.noble@apple.com>
+
+        ASSERT at PlatformCALayerCocoa::avPlayerLayer(): [platformLayer() sublayers].count == 1
+        https://bugs.webkit.org/show_bug.cgi?id=204077
+        <rdar://problem/56640423>
+
+        Reviewed by Simon Fraser.
+
+        Make PlatformCALayerCocoa::avPlayer() more robust against underlying layer changes.
+
+        Promote WebVideoContainerLayer to its own header file and give the class a "playerLayer" property. In
+        PlatformCALayerCocoa::avPlayer(), use that new property to retrieve the AVPlayerLayer.
+
+        Drive-by fix: Make PlatformCALayerCocoa::create() return a Ref<PlatformCALayerCocoa> rather than its parent class type.
+
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/avfoundation/objc/VideoFullscreenLayerManagerObjC.h:
+        * platform/graphics/avfoundation/objc/VideoFullscreenLayerManagerObjC.mm:
+        (WebCore::VideoFullscreenLayerManagerObjC::setVideoLayer):
+        (-[WebVideoContainerLayer setBounds:]): Deleted.
+        (-[WebVideoContainerLayer setPosition:]): Deleted.
+        * platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
+        * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
+        (WebCore::PlatformCALayerCocoa::create):
+        (WebCore::PlatformCALayerCocoa::layerTypeForPlatformLayer):
+        (WebCore::PlatformCALayerCocoa::clone const):
+        (WebCore::PlatformCALayerCocoa::avPlayerLayer const):
+        * platform/graphics/ca/cocoa/WebVideoContainerLayer.h: Added.
+        * platform/graphics/ca/cocoa/WebVideoContainerLayer.mm: Added.
+        (-[WebVideoContainerLayer initWithPlayerLayer:]):
+        (-[WebVideoContainerLayer playerLayer]):
+        (-[WebVideoContainerLayer setBounds:]):
+        (-[WebVideoContainerLayer setPosition:]):
+
 2019-11-11  Antti Koivisto  <antti@apple.com>
 
         Always use matched declarations cache fully when parent inherited style matches
index 7f6e21b..f1c3346 100644 (file)
@@ -278,6 +278,7 @@ platform/graphics/ca/cocoa/PlatformCAFiltersCocoa.mm
 platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm
 platform/graphics/ca/cocoa/WebSystemBackdropLayer.mm
 platform/graphics/ca/cocoa/WebTiledBackingLayer.mm
+platform/graphics/ca/cocoa/WebVideoContainerLayer.mm
 
 platform/graphics/cg/ColorCG.cpp
 platform/graphics/cg/FloatPointCG.cpp
index 7104321..82215f7 100644 (file)
                CD8ACA871D237AA200ECC59E /* RemoteCommandListenerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteCommandListenerMac.h; sourceTree = "<group>"; };
                CD8ACA8C1D23971900ECC59E /* MediaRemoteSoftLink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRemoteSoftLink.cpp; sourceTree = "<group>"; };
                CD8ACA8D1D23971900ECC59E /* MediaRemoteSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRemoteSoftLink.h; sourceTree = "<group>"; };
+               CD8B31A12379DC8300883FDE /* WebVideoContainerLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebVideoContainerLayer.h; sourceTree = "<group>"; };
+               CD8B31A22379DC8300883FDE /* WebVideoContainerLayer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebVideoContainerLayer.mm; sourceTree = "<group>"; };
                CD8B5A40180D149A008B8E65 /* VideoTrackPrivateMediaSourceAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = VideoTrackPrivateMediaSourceAVFObjC.mm; sourceTree = "<group>"; };
                CD8B5A41180D149A008B8E65 /* VideoTrackPrivateMediaSourceAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoTrackPrivateMediaSourceAVFObjC.h; sourceTree = "<group>"; };
                CD8B5A44180DD8D6008B8E65 /* VideoTrackMediaSource.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = VideoTrackMediaSource.idl; sourceTree = "<group>"; };
                                31DEA4531B39F4D900F77178 /* WebSystemBackdropLayer.mm */,
                                0F580FA11496939100FB5BD8 /* WebTiledBackingLayer.h */,
                                0F580FA21496939100FB5BD8 /* WebTiledBackingLayer.mm */,
+                               CD8B31A12379DC8300883FDE /* WebVideoContainerLayer.h */,
+                               CD8B31A22379DC8300883FDE /* WebVideoContainerLayer.mm */,
                        );
                        path = cocoa;
                        sourceTree = "<group>";
index db87edc..df03f24 100644 (file)
 #include "IntSize.h"
 #include "PlatformLayer.h"
 #include "VideoFullscreenLayerManager.h"
+#include "WebVideoContainerLayer.h"
 #include <wtf/Function.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/RetainPtr.h>
 
+OBJC_CLASS AVPlayerLayer;
+
 namespace WebCore {
 
 class VideoFullscreenLayerManagerObjC final : public VideoFullscreenLayerManager {
@@ -55,7 +58,7 @@ public:
 
 private:
     RetainPtr<PlatformLayer> m_textTrackRepresentationLayer;
-    RetainPtr<PlatformLayer> m_videoInlineLayer;
+    RetainPtr<WebVideoContainerLayer> m_videoInlineLayer;
     RetainPtr<PlatformLayer> m_videoFullscreenLayer;
     RetainPtr<PlatformLayer> m_videoLayer;
     FloatRect m_videoFullscreenFrame;
index 83b8125..81a3bae 100644 (file)
 #import <wtf/BlockPtr.h>
 #import <wtf/MachSendRight.h>
 
-@interface WebVideoContainerLayer : CALayer
-@end
-
-@implementation WebVideoContainerLayer
-
-- (void)setBounds:(CGRect)bounds
-{
-    [super setBounds:bounds];
-    for (CALayer* layer in self.sublayers)
-        layer.frame = bounds;
-}
-
-- (void)setPosition:(CGPoint)position
-{
-    if (!CATransform3DIsIdentity(self.transform)) {
-        // Pre-apply the transform added in the WebProcess to fix <rdar://problem/18316542> to the position.
-        position = CGPointApplyAffineTransform(position, CATransform3DGetAffineTransform(self.transform));
-    }
-    [super setPosition:position];
-}
-@end
+#include <pal/cocoa/AVFoundationSoftLink.h>
 
 namespace WebCore {
 
@@ -76,6 +56,8 @@ void VideoFullscreenLayerManagerObjC::setVideoLayer(PlatformLayer *videoLayer, I
 #endif
     [m_videoInlineLayer setFrame:m_videoInlineFrame];
     [m_videoInlineLayer setContentsGravity:kCAGravityResizeAspect];
+    if ([videoLayer isKindOfClass:PAL::getAVPlayerLayerClass()])
+        [m_videoInlineLayer setPlayerLayer:(AVPlayerLayer *)videoLayer];
 
     if (m_videoFullscreenLayer) {
         [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
index 198fa99..5d9669b 100644 (file)
@@ -33,11 +33,11 @@ namespace WebCore {
 
 class PlatformCALayerCocoa final : public PlatformCALayer {
 public:
-    static Ref<PlatformCALayer> create(LayerType, PlatformCALayerClient*);
+    static Ref<PlatformCALayerCocoa> create(LayerType, PlatformCALayerClient*);
     
     // This function passes the layer as a void* rather than a PlatformLayer because PlatformLayer
     // is defined differently for Obj C and C++. This allows callers from both languages.
-    static Ref<PlatformCALayer> create(void* platformLayer, PlatformCALayerClient*);
+    static Ref<PlatformCALayerCocoa> create(void* platformLayer, PlatformCALayerClient*);
 
     WEBCORE_EXPORT static LayerType layerTypeForPlatformLayer(PlatformLayer*);
 
index 78e3518..4657428 100644 (file)
@@ -39,6 +39,7 @@
 #import "WebActionDisablingCALayerDelegate.h"
 #import "WebCoreCALayerExtras.h"
 #import "WebGLLayer.h"
+#import "WebVideoContainerLayer.h"
 #import <pal/spi/cocoa/QuartzCoreSPI.h>
 #import <wtf/SoftLinking.h>
 #import "WebLayer.h"
 
 namespace WebCore {
 
-Ref<PlatformCALayer> PlatformCALayerCocoa::create(LayerType layerType, PlatformCALayerClient* owner)
+Ref<PlatformCALayerCocoa> PlatformCALayerCocoa::create(LayerType layerType, PlatformCALayerClient* owner)
 {
     return adoptRef(*new PlatformCALayerCocoa(layerType, owner));
 }
 
-Ref<PlatformCALayer> PlatformCALayerCocoa::create(void* platformLayer, PlatformCALayerClient* owner)
+Ref<PlatformCALayerCocoa> PlatformCALayerCocoa::create(void* platformLayer, PlatformCALayerClient* owner)
 {
     return adoptRef(*new PlatformCALayerCocoa((__bridge CALayer *)platformLayer, owner));
 }
@@ -200,9 +201,8 @@ PlatformCALayer::LayerType PlatformCALayerCocoa::layerTypeForPlatformLayer(Platf
     if ([layer isKindOfClass:PAL::getAVPlayerLayerClass()])
         return LayerTypeAVPlayerLayer;
 
-    if ([layer isKindOfClass:objc_getClass("WebVideoContainerLayer")]
-        && layer.sublayers.count == 1
-        && [layer.sublayers[0] isKindOfClass:PAL::getAVPlayerLayerClass()])
+    if ([layer isKindOfClass:WebVideoContainerLayer.class]
+        && [(WebVideoContainerLayer*)layer playerLayer])
         return LayerTypeAVPlayerLayer;
 
     if ([layer isKindOfClass:[WebGLLayer class]])
@@ -361,7 +361,7 @@ Ref<PlatformCALayer> PlatformCALayerCocoa::clone(PlatformCALayerClient* owner) c
     if (type == LayerTypeAVPlayerLayer) {
         ASSERT([newLayer->platformLayer() isKindOfClass:PAL::getAVPlayerLayerClass()]);
 
-        AVPlayerLayer *destinationPlayerLayer = static_cast<PlatformCALayerCocoa&>(newLayer.get()).avPlayerLayer();
+        AVPlayerLayer *destinationPlayerLayer = newLayer->avPlayerLayer();
         AVPlayerLayer *sourcePlayerLayer = avPlayerLayer();
         ASSERT(sourcePlayerLayer);
 
@@ -1273,11 +1273,8 @@ AVPlayerLayer *PlatformCALayerCocoa::avPlayerLayer() const
     if ([platformLayer() isKindOfClass:PAL::getAVPlayerLayerClass()])
         return static_cast<AVPlayerLayer *>(platformLayer());
 
-    if ([platformLayer() isKindOfClass:objc_getClass("WebVideoContainerLayer")]) {
-        ASSERT([platformLayer() sublayers].count == 1);
-        ASSERT([[platformLayer() sublayers][0] isKindOfClass:PAL::getAVPlayerLayerClass()]);
-        return static_cast<AVPlayerLayer *>([platformLayer() sublayers][0]);
-    }
+    if ([platformLayer() isKindOfClass:WebVideoContainerLayer.class])
+        return static_cast<WebVideoContainerLayer *>(platformLayer()).playerLayer;
 
     ASSERT_NOT_REACHED();
     return nil;
diff --git a/Source/WebCore/platform/graphics/ca/cocoa/WebVideoContainerLayer.h b/Source/WebCore/platform/graphics/ca/cocoa/WebVideoContainerLayer.h
new file mode 100644 (file)
index 0000000..7501791
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#import <QuartzCore/CALayer.h>
+#import <wtf/RetainPtr.h>
+
+@class AVPlayerLayer;
+
+@interface WebVideoContainerLayer : CALayer {
+    RetainPtr<AVPlayerLayer> _playerLayer;
+}
+@property (retain, nonatomic) AVPlayerLayer * playerLayer;
+@end
diff --git a/Source/WebCore/platform/graphics/ca/cocoa/WebVideoContainerLayer.mm b/Source/WebCore/platform/graphics/ca/cocoa/WebVideoContainerLayer.mm
new file mode 100644 (file)
index 0000000..807f542
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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"
+#import "WebVideoContainerLayer.h"
+
+@implementation WebVideoContainerLayer
+- (void)setPlayerLayer:(AVPlayerLayer *)playerLayer
+{
+    _playerLayer = playerLayer;
+}
+
+- (AVPlayerLayer *)playerLayer
+{
+    return _playerLayer.get();
+}
+
+- (void)setBounds:(CGRect)bounds
+{
+    [super setBounds:bounds];
+    for (CALayer* layer in self.sublayers)
+        layer.frame = bounds;
+}
+
+- (void)setPosition:(CGPoint)position
+{
+    if (!CATransform3DIsIdentity(self.transform)) {
+        // Pre-apply the transform added in the WebProcess to fix <rdar://problem/18316542> to the position.
+        position = CGPointApplyAffineTransform(position, CATransform3DGetAffineTransform(self.transform));
+    }
+    [super setPosition:position];
+}
+
+@end
+