Title: [284295] trunk/Source
Revision
284295
Author
[email protected]
Date
2021-10-15 17:34:25 -0700 (Fri, 15 Oct 2021)

Log Message

[iOS] Support getDisplayMedia
https://bugs.webkit.org/show_bug.cgi?id=231455
<rdar://problem/84044495>

Reviewed by Youenn Fablet and Jer Noble.

Source/WebCore:

Implement screen capture for iOS using ReplayKit. ReplayKit only captures when the
host application is in the foreground, so the MediaStream track is muted when the
app is backgrounded.

getDisplayMedia availability to _javascript_ is controlled by the `ScreenCaptureEnabled`
setting, which is disabled by default on iOS.

I haven't figured out how to test this automatically yet because ReplayKit always
shows its own modal user prompt before it allows capture to begin.

* SourcesCocoa.txt: Add ReplayKitCaptureSource.mm. Rename DisplayCaptureSourceMac.cpp
to DisplayCaptureSourceCocoa.cpp.

* WebCore.xcodeproj/project.pbxproj: Add new files.

* en.lproj/Localizable.strings: Add localizable strings for getDisplayMedia prompt.

* platform/graphics/cv/ImageTransferSessionVT.h:
* platform/graphics/cv/ImageTransferSessionVT.mm:
(WebCore::ImageTransferSessionVT::convertCMSampleBuffer): Add an optional MediaTime parameter.
(WebCore::ImageTransferSessionVT::createMediaSample): Add a MediaTime parameter.

* platform/mediastream/ios/ReplayKitCaptureSource.h: Added.
* platform/mediastream/ios/ReplayKitCaptureSource.mm: Added.
(-[WebCoreReplayKitScreenRecorderHelper initWithCallback:]):
(-[WebCoreReplayKitScreenRecorderHelper disconnect]):
(-[WebCoreReplayKitScreenRecorderHelper observeValueForKeyPath:ofObject:change:context:]):
(WebCore::ReplayKitCaptureSource::isAvailable): Check ReplayKit availability.
(WebCore::ReplayKitCaptureSource::create):
(WebCore::ReplayKitCaptureSource::ReplayKitCaptureSource):
(WebCore::ReplayKitCaptureSource::~ReplayKitCaptureSource):
(WebCore::ReplayKitCaptureSource::start): Start screen capture only.
(WebCore::ReplayKitCaptureSource::screenRecorderDidOutputVideoSample): Retain the
the new frame, set intrinsic size to the image size.
(WebCore::ReplayKitCaptureSource::captureStateDidChange): Update observer if interruption
state or recorder state changes so it can update the track's 'muted' state.
(WebCore::ReplayKitCaptureSource::stop): Stop capture.
(WebCore::ReplayKitCaptureSource::generateFrame):
(WebCore::ReplayKitCaptureSource::verifyCaptureIsActive): ReplayKit doesn't notify
when capture is paused, so watch for changes by monitoring the frame count.
(WebCore::ReplayKitCaptureSource::startCaptureWatchdogTimer): Start the timer that
will monitor for capture pausing/resuming.
(WebCore::screenDeviceUUID):
(WebCore::screenDevice):
(WebCore::ReplayKitCaptureSource::screenCaptureDeviceWithPersistentID):
(WebCore::ReplayKitCaptureSource::screenCaptureDevices):

* platform/mediastream/mac/CGDisplayStreamCaptureSource.cpp:
(WebCore::CGDisplayStreamCaptureSource::generateFrame): DisplayCaptureSourceMac was
renamed DisplayCaptureSourceCocoa.
(WebCore::CGDisplayStreamCaptureSource::newFrame): Take a RetainPtr<IOSurfaceRef>
instead of a DisplaySurface.
(WebCore::CGDisplayStreamCaptureSource::frameAvailableHandler): Ditto.
* platform/mediastream/mac/CGDisplayStreamCaptureSource.h:
(WebCore::CGDisplayStreamCaptureSource::DisplaySurface::DisplaySurface): Deleted.
(WebCore::CGDisplayStreamCaptureSource::DisplaySurface::~DisplaySurface): Deleted.
(WebCore::CGDisplayStreamCaptureSource::DisplaySurface::operator=): Deleted.
(WebCore::CGDisplayStreamCaptureSource::DisplaySurface::ioSurface const): Deleted.

* platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.h:
* platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.mm:
(WebCore::CGDisplayStreamScreenCaptureSource::create): DisplayCaptureSourceMac was
renamed DisplayCaptureSourceCocoa.

* platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp:
(WebCore::DisplayCaptureManagerCocoa::updateDisplayCaptureDevices): Use
ReplayKitCaptureSource on iOS.

* platform/mediastream/mac/DisplayCaptureSourceCocoa.cpp: Renamed from Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.cpp.
(WebCore::DisplayCaptureSourceCocoa::create):
(WebCore::DisplayCaptureSourceCocoa::DisplayCaptureSourceCocoa):
(WebCore::DisplayCaptureSourceCocoa::~DisplayCaptureSourceCocoa):
(WebCore::DisplayCaptureSourceCocoa::capabilities):
(WebCore::DisplayCaptureSourceCocoa::settings):
(WebCore::DisplayCaptureSourceCocoa::settingsDidChange):
(WebCore::DisplayCaptureSourceCocoa::startProducingData):
(WebCore::DisplayCaptureSourceCocoa::stopProducingData):
(WebCore::DisplayCaptureSourceCocoa::elapsedTime):
(WebCore::DisplayCaptureSourceCocoa::updateFrameSize):
(WebCore::DisplayCaptureSourceCocoa::emitFrame): Support capturer returning a CMSampleBuffer.
(WebCore::DisplayCaptureSourceCocoa::setLogger):
(WebCore::DisplayCaptureSourceCocoa::Capturer::setLogger): Set the capturer's logger.
(WebCore::DisplayCaptureSourceCocoa::Capturer::logChannel const):
(WebCore::DisplayCaptureSourceCocoa::Capturer::Observer::~Observer):
(WebCore::DisplayCaptureSourceCocoa::Capturer::setObserver):
(WebCore::DisplayCaptureSourceCocoa::Capturer::capturerIsRunningChanged):
* platform/mediastream/mac/DisplayCaptureSourceCocoa.h: Renamed from Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.h.

* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::DisplayCaptureSourceFactoryMac::createDisplayCaptureSource): DisplayCaptureSourceMac
renamed to DisplayCaptureSourceCocoa.

* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockDisplayCapturer::generateFrame): Ditto.

Source/WebCore/PAL:

* PAL.xcodeproj/project.pbxproj:
* pal/ios/ReplayKitSoftLink.h: Added.
* pal/ios/ReplayKitSoftLink.mm: Added.

Source/WebKit:

* UIProcess/Cocoa/MediaPermissionUtilities.mm:
(WebKit::alertMessageText): Add text for default screen capture prompt.
(WebKit::allowButtonText): Ditto.
(WebKit::doNotAllowButtonText): Ditto.

* UIProcess/Cocoa/UIDelegate.mm:
(WebKit::UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest): Call
default getDisplayMedia prompt if the delegate doesn't implement the private
prompt selector.

* UIProcess/MediaPermissionUtilities.h:
* UIProcess/UserMediaPermissionRequestProxy.cpp:
(WebKit::UserMediaPermissionRequestProxy::promptForGetDisplayMedia): New default
getDisplayMedia prompt.
(WebKit::UserMediaPermissionRequestProxy::promptForGetUserMedia):
(WebKit::UserMediaPermissionRequestProxy::doDefaultAction): Call promptForGetDisplayMedia
or promptForGetUserMedia according to the request type.
(WebKit::UserMediaPermissionRequestProxy::canPromptForGetDisplayMedia):
(WebKit::UserMediaPermissionRequestProxy::prompt): Deleted.
* UIProcess/UserMediaPermissionRequestProxy.h:
(WebKit::UserMediaPermissionRequestProxy::doDefaultAction): Deleted.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (284294 => 284295)


--- trunk/Source/WebCore/ChangeLog	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/ChangeLog	2021-10-16 00:34:25 UTC (rev 284295)
@@ -1,3 +1,106 @@
+2021-10-15  Eric Carlson  <[email protected]>
+
+        [iOS] Support getDisplayMedia
+        https://bugs.webkit.org/show_bug.cgi?id=231455
+        <rdar://problem/84044495>
+
+        Reviewed by Youenn Fablet and Jer Noble.
+
+        Implement screen capture for iOS using ReplayKit. ReplayKit only captures when the 
+        host application is in the foreground, so the MediaStream track is muted when the
+        app is backgrounded.
+
+        getDisplayMedia availability to _javascript_ is controlled by the `ScreenCaptureEnabled`
+        setting, which is disabled by default on iOS.
+
+        I haven't figured out how to test this automatically yet because ReplayKit always
+        shows its own modal user prompt before it allows capture to begin.
+
+        * SourcesCocoa.txt: Add ReplayKitCaptureSource.mm. Rename DisplayCaptureSourceMac.cpp
+        to DisplayCaptureSourceCocoa.cpp.
+
+        * WebCore.xcodeproj/project.pbxproj: Add new files.
+
+        * en.lproj/Localizable.strings: Add localizable strings for getDisplayMedia prompt.
+
+        * platform/graphics/cv/ImageTransferSessionVT.h:
+        * platform/graphics/cv/ImageTransferSessionVT.mm:
+        (WebCore::ImageTransferSessionVT::convertCMSampleBuffer): Add an optional MediaTime parameter.
+        (WebCore::ImageTransferSessionVT::createMediaSample): Add a MediaTime parameter.
+
+        * platform/mediastream/ios/ReplayKitCaptureSource.h: Added.
+        * platform/mediastream/ios/ReplayKitCaptureSource.mm: Added.
+        (-[WebCoreReplayKitScreenRecorderHelper initWithCallback:]):
+        (-[WebCoreReplayKitScreenRecorderHelper disconnect]):
+        (-[WebCoreReplayKitScreenRecorderHelper observeValueForKeyPath:ofObject:change:context:]):
+        (WebCore::ReplayKitCaptureSource::isAvailable): Check ReplayKit availability.
+        (WebCore::ReplayKitCaptureSource::create):
+        (WebCore::ReplayKitCaptureSource::ReplayKitCaptureSource):
+        (WebCore::ReplayKitCaptureSource::~ReplayKitCaptureSource):
+        (WebCore::ReplayKitCaptureSource::start): Start screen capture only.
+        (WebCore::ReplayKitCaptureSource::screenRecorderDidOutputVideoSample): Retain the
+        the new frame, set intrinsic size to the image size.
+        (WebCore::ReplayKitCaptureSource::captureStateDidChange): Update observer if interruption
+        state or recorder state changes so it can update the track's 'muted' state.
+        (WebCore::ReplayKitCaptureSource::stop): Stop capture.
+        (WebCore::ReplayKitCaptureSource::generateFrame):
+        (WebCore::ReplayKitCaptureSource::verifyCaptureIsActive): ReplayKit doesn't notify 
+        when capture is paused, so watch for changes by monitoring the frame count.
+        (WebCore::ReplayKitCaptureSource::startCaptureWatchdogTimer): Start the timer that
+        will monitor for capture pausing/resuming.
+        (WebCore::screenDeviceUUID):
+        (WebCore::screenDevice):
+        (WebCore::ReplayKitCaptureSource::screenCaptureDeviceWithPersistentID):
+        (WebCore::ReplayKitCaptureSource::screenCaptureDevices):
+
+        * platform/mediastream/mac/CGDisplayStreamCaptureSource.cpp:
+        (WebCore::CGDisplayStreamCaptureSource::generateFrame): DisplayCaptureSourceMac was
+        renamed DisplayCaptureSourceCocoa.
+        (WebCore::CGDisplayStreamCaptureSource::newFrame): Take a RetainPtr<IOSurfaceRef>
+        instead of a DisplaySurface.
+        (WebCore::CGDisplayStreamCaptureSource::frameAvailableHandler): Ditto.
+        * platform/mediastream/mac/CGDisplayStreamCaptureSource.h:
+        (WebCore::CGDisplayStreamCaptureSource::DisplaySurface::DisplaySurface): Deleted.
+        (WebCore::CGDisplayStreamCaptureSource::DisplaySurface::~DisplaySurface): Deleted.
+        (WebCore::CGDisplayStreamCaptureSource::DisplaySurface::operator=): Deleted.
+        (WebCore::CGDisplayStreamCaptureSource::DisplaySurface::ioSurface const): Deleted.
+
+        * platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.h:
+        * platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.mm:
+        (WebCore::CGDisplayStreamScreenCaptureSource::create): DisplayCaptureSourceMac was
+        renamed DisplayCaptureSourceCocoa.
+
+        * platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp:
+        (WebCore::DisplayCaptureManagerCocoa::updateDisplayCaptureDevices): Use 
+        ReplayKitCaptureSource on iOS.
+
+        * platform/mediastream/mac/DisplayCaptureSourceCocoa.cpp: Renamed from Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.cpp.
+        (WebCore::DisplayCaptureSourceCocoa::create):
+        (WebCore::DisplayCaptureSourceCocoa::DisplayCaptureSourceCocoa):
+        (WebCore::DisplayCaptureSourceCocoa::~DisplayCaptureSourceCocoa):
+        (WebCore::DisplayCaptureSourceCocoa::capabilities):
+        (WebCore::DisplayCaptureSourceCocoa::settings):
+        (WebCore::DisplayCaptureSourceCocoa::settingsDidChange):
+        (WebCore::DisplayCaptureSourceCocoa::startProducingData):
+        (WebCore::DisplayCaptureSourceCocoa::stopProducingData):
+        (WebCore::DisplayCaptureSourceCocoa::elapsedTime):
+        (WebCore::DisplayCaptureSourceCocoa::updateFrameSize):
+        (WebCore::DisplayCaptureSourceCocoa::emitFrame): Support capturer returning a CMSampleBuffer.
+        (WebCore::DisplayCaptureSourceCocoa::setLogger):
+        (WebCore::DisplayCaptureSourceCocoa::Capturer::setLogger): Set the capturer's logger.
+        (WebCore::DisplayCaptureSourceCocoa::Capturer::logChannel const):
+        (WebCore::DisplayCaptureSourceCocoa::Capturer::Observer::~Observer):
+        (WebCore::DisplayCaptureSourceCocoa::Capturer::setObserver):
+        (WebCore::DisplayCaptureSourceCocoa::Capturer::capturerIsRunningChanged):
+        * platform/mediastream/mac/DisplayCaptureSourceCocoa.h: Renamed from Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.h.
+
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::DisplayCaptureSourceFactoryMac::createDisplayCaptureSource): DisplayCaptureSourceMac
+        renamed to DisplayCaptureSourceCocoa.
+
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockDisplayCapturer::generateFrame): Ditto.
+
 2021-10-15  Aditya Keerthi  <[email protected]>
 
         [iOS] Support accent-color for button-like controls

Modified: trunk/Source/WebCore/PAL/ChangeLog (284294 => 284295)


--- trunk/Source/WebCore/PAL/ChangeLog	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/PAL/ChangeLog	2021-10-16 00:34:25 UTC (rev 284295)
@@ -1,3 +1,15 @@
+2021-10-15  Eric Carlson  <[email protected]>
+
+        [iOS] Support getDisplayMedia
+        https://bugs.webkit.org/show_bug.cgi?id=231455
+        <rdar://problem/84044495>
+
+        Reviewed by Youenn Fablet and Jer Noble.
+
+        * PAL.xcodeproj/project.pbxproj:
+        * pal/ios/ReplayKitSoftLink.h: Added.
+        * pal/ios/ReplayKitSoftLink.mm: Added.
+
 2021-10-14  Alex Christensen  <[email protected]>
 
         Fix non-internal iOS builds after r284220

Modified: trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj (284294 => 284295)


--- trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj	2021-10-16 00:34:25 UTC (rev 284295)
@@ -21,6 +21,8 @@
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
+		071C00372707EDF000D027C7 /* ReplayKitSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 071C00352707EDF000D027C7 /* ReplayKitSoftLink.mm */; };
+		071C00382707EDF000D027C7 /* ReplayKitSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 071C00362707EDF000D027C7 /* ReplayKitSoftLink.h */; };
 		07611DB6243FA5BF00D80704 /* UsageTrackingSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 07611DB4243FA5BE00D80704 /* UsageTrackingSoftLink.h */; };
 		07611DB7243FA5BF00D80704 /* UsageTrackingSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07611DB5243FA5BF00D80704 /* UsageTrackingSoftLink.mm */; };
 		077E87B1226A460200A2AFF0 /* AVFoundationSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 077E87AF226A460200A2AFF0 /* AVFoundationSoftLink.mm */; };
@@ -236,6 +238,8 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+		071C00352707EDF000D027C7 /* ReplayKitSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ReplayKitSoftLink.mm; sourceTree = "<group>"; };
+		071C00362707EDF000D027C7 /* ReplayKitSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReplayKitSoftLink.h; sourceTree = "<group>"; };
 		07611DB4243FA5BE00D80704 /* UsageTrackingSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UsageTrackingSoftLink.h; sourceTree = "<group>"; };
 		07611DB5243FA5BF00D80704 /* UsageTrackingSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UsageTrackingSoftLink.mm; sourceTree = "<group>"; };
 		077E87AF226A460200A2AFF0 /* AVFoundationSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AVFoundationSoftLink.mm; sourceTree = "<group>"; };
@@ -774,6 +778,8 @@
 				5C7C787223AC3E770065F47E /* ManagedConfigurationSoftLink.mm */,
 				4450FC9E21F5F602004DFA56 /* QuickLookSoftLink.h */,
 				4450FC9D21F5F602004DFA56 /* QuickLookSoftLink.mm */,
+				071C00362707EDF000D027C7 /* ReplayKitSoftLink.h */,
+				071C00352707EDF000D027C7 /* ReplayKitSoftLink.mm */,
 				079D1D9526950DD700883577 /* SystemStatusSoftLink.h */,
 				079D1D9626950DD700883577 /* SystemStatusSoftLink.mm */,
 				2E1342CA215AA10A007199D2 /* UIKitSoftLink.h */,
@@ -995,6 +1001,7 @@
 				4450FCA021F5F602004DFA56 /* QuickLookSoftLink.h in Headers */,
 				0C5AF9201F43A4C7002EAC02 /* QuickLookSPI.h in Headers */,
 				F4C85A4F2658551A005B89CC /* QuickLookUISoftLink.h in Headers */,
+				071C00382707EDF000D027C7 /* ReplayKitSoftLink.h in Headers */,
 				F4974EA3265EEA2200B49B8C /* RevealSoftLink.h in Headers */,
 				442956CD218A72DF0080DB54 /* RevealSPI.h in Headers */,
 				570AB8F120AE2E8D00B8BE87 /* SecKeyProxySPI.h in Headers */,
@@ -1140,6 +1147,7 @@
 				A1175B4F1F6B337300C4B9F0 /* PopupMenu.mm in Sources */,
 				4450FC9F21F5F602004DFA56 /* QuickLookSoftLink.mm in Sources */,
 				F4C85A4E2658551A005B89CC /* QuickLookUISoftLink.mm in Sources */,
+				071C00372707EDF000D027C7 /* ReplayKitSoftLink.mm in Sources */,
 				F4974EA4265EEA2200B49B8C /* RevealSoftLink.mm in Sources */,
 				A3C66CDC1F462D6A009E6EE9 /* SessionID.cpp in Sources */,
 				A3AB6E521F3D1DC5009C14B1 /* SleepDisabler.cpp in Sources */,

Added: trunk/Source/WebCore/PAL/pal/ios/ReplayKitSoftLink.h (0 => 284295)


--- trunk/Source/WebCore/PAL/pal/ios/ReplayKitSoftLink.h	                        (rev 0)
+++ trunk/Source/WebCore/PAL/pal/ios/ReplayKitSoftLink.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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
+
+#if PLATFORM(IOS)
+
+#import <ReplayKit/ReplayKit.h>
+#import <wtf/SoftLinking.h>
+
+SOFT_LINK_FRAMEWORK_FOR_HEADER(PAL, ReplayKit)
+
+SOFT_LINK_CLASS_FOR_HEADER(PAL, RPScreenRecorder)
+
+#endif

Added: trunk/Source/WebCore/PAL/pal/ios/ReplayKitSoftLink.mm (0 => 284295)


--- trunk/Source/WebCore/PAL/pal/ios/ReplayKitSoftLink.mm	                        (rev 0)
+++ trunk/Source/WebCore/PAL/pal/ios/ReplayKitSoftLink.mm	2021-10-16 00:34:25 UTC (rev 284295)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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 PLATFORM(IOS)
+
+#import <ReplayKit/ReplayKit.h>
+#import <wtf/SoftLinking.h>
+
+SOFT_LINK_FRAMEWORK_FOR_SOURCE(PAL, ReplayKit)
+
+SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, ReplayKit, RPScreenRecorder, PAL_EXPORT)
+
+#endif

Modified: trunk/Source/WebCore/PAL/pal/spi/cf/CoreAudioSPI.h (284294 => 284295)


--- trunk/Source/WebCore/PAL/pal/spi/cf/CoreAudioSPI.h	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/PAL/pal/spi/cf/CoreAudioSPI.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -27,6 +27,8 @@
 
 #if PLATFORM(COCOA)
 
+#include <CoreAudio/CoreAudioTypes.h>
+
 #if USE(APPLE_INTERNAL_SDK)
 #include <CoreAudio/AudioHardwarePriv.h>
 #else

Modified: trunk/Source/WebCore/SourcesCocoa.txt (284294 => 284295)


--- trunk/Source/WebCore/SourcesCocoa.txt	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2021-10-16 00:34:25 UTC (rev 284295)
@@ -522,9 +522,11 @@
 platform/mediastream/cocoa/AudioMediaStreamTrackRendererCocoa.cpp
 platform/mediastream/cocoa/AudioMediaStreamTrackRendererInternalUnit.cpp
 platform/mediastream/cocoa/AudioMediaStreamTrackRendererUnit.cpp
+platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp
 platform/mediastream/ios/AVAudioSessionCaptureDevice.mm
 platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm @no-unify
 platform/mediastream/ios/CoreAudioCaptureSourceIOS.mm
+platform/mediastream/ios/ReplayKitCaptureSource.mm @no-unify
 platform/mediastream/libwebrtc/LibWebRTCProviderCocoa.cpp
 platform/mediastream/mac/AVCaptureDeviceManager.mm
 platform/mediastream/mac/AVVideoCaptureSource.mm @no-unify
@@ -535,7 +537,6 @@
 platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp
 platform/mediastream/mac/CoreAudioCaptureSource.cpp
 platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp
-platform/mediastream/mac/DisplayCaptureSourceMac.cpp
 platform/mediastream/mac/MediaStreamTrackAudioSourceProviderCocoa.cpp
 platform/mediastream/mac/MockAudioSharedUnit.mm
 platform/mediastream/mac/MockRealtimeVideoSourceMac.mm

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (284294 => 284295)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-16 00:34:25 UTC (rev 284295)
@@ -98,6 +98,8 @@
 		070E81D11BF27656001FDA48 /* VideoTrackPrivateMediaStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 070E81D01BF27656001FDA48 /* VideoTrackPrivateMediaStream.h */; };
 		070F549817F12F6B00169E04 /* MediaStreamConstraintsValidationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 070F549717F12F6B00169E04 /* MediaStreamConstraintsValidationClient.h */; };
 		071A9EC3168FBC55002629F9 /* TextTrackCueGeneric.h in Headers */ = {isa = PBXBuildFile; fileRef = 071A9EC1168FB56C002629F9 /* TextTrackCueGeneric.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		071C00342707D95500D027C7 /* ReplayKitCaptureSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071C00332707D94400D027C7 /* ReplayKitCaptureSource.h */; };
+		071C004B270B864900D027C7 /* ReplayKitCaptureSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 071C00322707D94300D027C7 /* ReplayKitCaptureSource.mm */; };
 		071E49701AD5AB5E008A50B4 /* MediaPlaybackTargetCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 071E496F1AD5AB5E008A50B4 /* MediaPlaybackTargetCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0725EFA9239AD79300A538A9 /* MediaPlayerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 079F5E4B0F3BEBEA005E0782 /* MediaPlayerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07277E4D17D018CC0015534D /* JSMediaStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 07277E4117D018CC0015534D /* JSMediaStream.h */; };
@@ -207,6 +209,7 @@
 		07B7116D1D899E63009F0FFB /* CaptureDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B7116A1D899E63009F0FFB /* CaptureDevice.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07B7116F1D899E63009F0FFB /* CaptureDeviceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B7116C1D899E63009F0FFB /* CaptureDeviceManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07B93FFC23B94EC70036F8EA /* MIMETypeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B93FF923B92AAA0036F8EA /* MIMETypeCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		07BB1E7027176CD9001DF289 /* DisplayCaptureSourceCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 07BB1E6F27176CCA001DF289 /* DisplayCaptureSourceCocoa.h */; };
 		07C046C41E42508B007201E7 /* CAAudioStreamDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87581E40DCFD0071C0EC /* CAAudioStreamDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07C046CB1E426413007201E7 /* AudioStreamDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 073B87561E40DCE50071C0EC /* AudioStreamDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07C1482E2612A21F00775828 /* MediaSessionCoordinatorState.h in Headers */ = {isa = PBXBuildFile; fileRef = 077BA58826126D660072F19F /* MediaSessionCoordinatorState.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -5882,6 +5885,8 @@
 		0717765F26C303B700A63299 /* CGDisplayStreamScreenCaptureSource.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CGDisplayStreamScreenCaptureSource.mm; sourceTree = "<group>"; };
 		071A9EC0168FB56C002629F9 /* TextTrackCueGeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextTrackCueGeneric.cpp; sourceTree = "<group>"; };
 		071A9EC1168FB56C002629F9 /* TextTrackCueGeneric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextTrackCueGeneric.h; sourceTree = "<group>"; };
+		071C00322707D94300D027C7 /* ReplayKitCaptureSource.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ReplayKitCaptureSource.mm; sourceTree = "<group>"; };
+		071C00332707D94400D027C7 /* ReplayKitCaptureSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReplayKitCaptureSource.h; sourceTree = "<group>"; };
 		071E496D1AD5AA0D008A50B4 /* MediaPlaybackTargetCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaPlaybackTargetCocoa.mm; sourceTree = "<group>"; };
 		071E496F1AD5AB5E008A50B4 /* MediaPlaybackTargetCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlaybackTargetCocoa.h; sourceTree = "<group>"; };
 		07221B4C17CEC32700848E51 /* MediaStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStream.cpp; sourceTree = "<group>"; };
@@ -6070,10 +6075,8 @@
 		079F5E4B0F3BEBEA005E0782 /* MediaPlayerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlayerPrivate.h; sourceTree = "<group>"; };
 		07A6D1E91491137700051D0C /* MediaFragmentURIParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaFragmentURIParser.cpp; sourceTree = "<group>"; };
 		07A6D1EA1491137700051D0C /* MediaFragmentURIParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaFragmentURIParser.h; sourceTree = "<group>"; };
-		07A6D8471FEB700B006441DE /* DisplayCaptureSourceMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayCaptureSourceMac.cpp; sourceTree = "<group>"; };
 		07A6D8481FEB700B006441DE /* DisplayCaptureManagerCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayCaptureManagerCocoa.cpp; sourceTree = "<group>"; };
 		07A6D8491FEB700C006441DE /* DisplayCaptureManagerCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayCaptureManagerCocoa.h; sourceTree = "<group>"; };
-		07A6D84A1FEB700D006441DE /* DisplayCaptureSourceMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayCaptureSourceMac.h; sourceTree = "<group>"; };
 		07AA6B69166D019500D45671 /* InbandTextTrackPrivateAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateAVFObjC.h; sourceTree = "<group>"; };
 		07AA6B6A166D019500D45671 /* InbandTextTrackPrivateAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InbandTextTrackPrivateAVFObjC.mm; sourceTree = "<group>"; };
 		07AB996518DA3C010018771E /* RTCConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCConfiguration.h; sourceTree = "<group>"; };
@@ -6093,6 +6096,8 @@
 		07B7116C1D899E63009F0FFB /* CaptureDeviceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CaptureDeviceManager.h; sourceTree = "<group>"; };
 		07B93FF923B92AAA0036F8EA /* MIMETypeCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MIMETypeCache.h; sourceTree = "<group>"; };
 		07B93FFB23B92AAB0036F8EA /* MIMETypeCache.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MIMETypeCache.cpp; sourceTree = "<group>"; };
+		07BB1E6E27176CCA001DF289 /* DisplayCaptureSourceCocoa.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayCaptureSourceCocoa.cpp; sourceTree = "<group>"; };
+		07BB1E6F27176CCA001DF289 /* DisplayCaptureSourceCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayCaptureSourceCocoa.h; sourceTree = "<group>"; };
 		07C148292612955C00775828 /* JSMediaSessionReadyState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSMediaSessionReadyState.h; sourceTree = "<group>"; };
 		07C1482B2612955D00775828 /* JSMediaSessionReadyState.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaSessionReadyState.cpp; sourceTree = "<group>"; };
 		07C1482C2612955E00775828 /* JSMediaSessionCoordinatorState.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaSessionCoordinatorState.cpp; sourceTree = "<group>"; };
@@ -17837,8 +17842,6 @@
 				3F3BB5831E709EE400C701F2 /* CoreAudioCaptureSource.h */,
 				07A6D8481FEB700B006441DE /* DisplayCaptureManagerCocoa.cpp */,
 				07A6D8491FEB700C006441DE /* DisplayCaptureManagerCocoa.h */,
-				07A6D8471FEB700B006441DE /* DisplayCaptureSourceMac.cpp */,
-				07A6D84A1FEB700D006441DE /* DisplayCaptureSourceMac.h */,
 				4174E9202535DCDD00FE4202 /* MediaStreamTrackAudioSourceProviderCocoa.cpp */,
 				4174E91E2535DCD600FE4202 /* MediaStreamTrackAudioSourceProviderCocoa.h */,
 				0744ECEB1E0C4AE5000D0944 /* MockAudioSharedUnit.h */,
@@ -20154,6 +20157,8 @@
 				41C3B89F2649B1B7004ED4DE /* AudioMediaStreamTrackRendererInternalUnit.h */,
 				41C3B8A02649B1B7004ED4DE /* AudioMediaStreamTrackRendererUnit.cpp */,
 				41C3B89B2649B1B6004ED4DE /* AudioMediaStreamTrackRendererUnit.h */,
+				07BB1E6E27176CCA001DF289 /* DisplayCaptureSourceCocoa.cpp */,
+				07BB1E6F27176CCA001DF289 /* DisplayCaptureSourceCocoa.h */,
 			);
 			path = cocoa;
 			sourceTree = "<group>";
@@ -28851,6 +28856,8 @@
 				CDC675201EAEA9B700727C84 /* AVAudioSessionCaptureDeviceManager.mm */,
 				07AFF4201EFB144700B545B3 /* CoreAudioCaptureSourceIOS.h */,
 				07AFF4211EFB144700B545B3 /* CoreAudioCaptureSourceIOS.mm */,
+				071C00332707D94400D027C7 /* ReplayKitCaptureSource.h */,
+				071C00322707D94300D027C7 /* ReplayKitCaptureSource.mm */,
 			);
 			path = ios;
 			sourceTree = "<group>";
@@ -32516,6 +32523,7 @@
 				835D54C51F4DE53800E60671 /* DirectoryFileListCreator.h in Headers */,
 				F47A09D120A93A9700240FAE /* DisabledAdaptations.h in Headers */,
 				7EDAAFC919A2CCDC0034DFD1 /* DiskCacheMonitorCocoa.h in Headers */,
+				07BB1E7027176CD9001DF289 /* DisplayCaptureSourceCocoa.h in Headers */,
 				0FE5FBD31C3DD51E0007A2CA /* DisplayList.h in Headers */,
 				55AD09402408964000DE4D2F /* DisplayListDrawingContext.h in Headers */,
 				55AD093E2408963500DE4D2F /* DisplayListImageBuffer.h in Headers */,
@@ -35149,6 +35157,7 @@
 				A89CCC530F44E98100B5DA10 /* ReplaceNodeWithSpanCommand.h in Headers */,
 				2DF512CE1D873E47001D6780 /* ReplaceRangeWithTextCommand.h in Headers */,
 				93309E0A099E64920056E581 /* ReplaceSelectionCommand.h in Headers */,
+				071C00342707D95500D027C7 /* ReplayKitCaptureSource.h in Headers */,
 				46DD6E1F26E7DBE7008C1F4C /* ReportingEndpointsCache.h in Headers */,
 				4998AEC613F9D0EA0090B1AA /* RequestAnimationFrameCallback.h in Headers */,
 				F55B3DD01251F12D003EF269 /* ResetInputType.h in Headers */,
@@ -36913,6 +36922,7 @@
 				CDA29A301CBF74D400901CCF /* PlaybackSessionInterfaceAVKit.mm in Sources */,
 				CDA29A161CBDA56C00901CCF /* PlaybackSessionInterfaceMac.mm in Sources */,
 				419242492127B93E00634FCF /* RealtimeOutgoingVideoSourceCocoa.mm in Sources */,
+				071C004B270B864900D027C7 /* ReplayKitCaptureSource.mm in Sources */,
 				5C2B1AEC22397EBC00B91CF7 /* ResourceResponseCocoa.mm in Sources */,
 				BC51156E12B1749C00C96754 /* ScrollAnimatorMac.mm in Sources */,
 				0FEE371126F19529001B5184 /* ScrollbarsControllerMac.mm in Sources */,

Modified: trunk/Source/WebCore/en.lproj/Localizable.strings (284294 => 284295)


--- trunk/Source/WebCore/en.lproj/Localizable.strings	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/en.lproj/Localizable.strings	2021-10-16 00:34:25 UTC (rev 284295)
@@ -163,6 +163,9 @@
 /* Allow button title in user media prompt */
 "Allow (usermedia)" = "Allow";
 
+/* Allow button title in screen sharing prompt */
+"Allow (screensharing)" = "Allow";
+
 /* Message for requesting cross-site cookie and website data access. */
 "Allow “%@” and “%@” to use cookies and website data while browsing “%@”?" = "Allow “%@” and “%@” to use cookies and website data while browsing “%@”?";
 
@@ -184,6 +187,9 @@
 /* Message for user microphone access prompt */
 "Allow “%@” to use your microphone?" = "Allow “%@” to use your microphone?";
 
+/* Message for screen sharing prompt. */
+"Allow “%@” to observe your screen?" = "Allow “%@” to observe your screen?";
+
 /* WKErrorUnknown description */
 "An unknown error occurred" = "An unknown error occurred";
 
@@ -391,6 +397,9 @@
 /* Disallow button title in user media prompt */
 "Don’t Allow (usermedia)" = "Don’t Allow";
 
+/* Disallow button title in screen sharing prompt */
+"Don’t Allow (screensharing)" = "Don’t Allow";
+
 /* Download Audio To Disk context menu item */
 "Download Audio" = "Download Audio";
 

Modified: trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.h (284294 => 284295)


--- trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.h	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -49,7 +49,7 @@
 
     RefPtr<MediaSample> convertMediaSample(MediaSample&, const IntSize&);
     RefPtr<MediaSample> createMediaSample(CGImageRef, const MediaTime&, const IntSize&, MediaSample::VideoRotation = MediaSample::VideoRotation::None, bool mirrored = false);
-    RefPtr<MediaSample> createMediaSample(CMSampleBufferRef, const IntSize&, MediaSample::VideoRotation = MediaSample::VideoRotation::None, bool mirrored = false);
+    RefPtr<MediaSample> createMediaSample(CMSampleBufferRef, const MediaTime&, const IntSize&, MediaSample::VideoRotation = MediaSample::VideoRotation::None, bool mirrored = false);
 
 #if !PLATFORM(MACCATALYST)
     WEBCORE_EXPORT RefPtr<MediaSample> createMediaSample(IOSurfaceRef, const MediaTime&, const IntSize&, MediaSample::VideoRotation = MediaSample::VideoRotation::None, bool mirrored = false);
@@ -67,7 +67,7 @@
     RetainPtr<CMSampleBufferRef> createCMSampleBuffer(IOSurfaceRef, const MediaTime&, const IntSize&);
 #endif
 
-    RetainPtr<CMSampleBufferRef> convertCMSampleBuffer(CMSampleBufferRef, const IntSize&);
+    RetainPtr<CMSampleBufferRef> convertCMSampleBuffer(CMSampleBufferRef, const IntSize&, const MediaTime* = nullptr);
     RetainPtr<CMSampleBufferRef> createCMSampleBuffer(CVPixelBufferRef, const MediaTime&, const IntSize&);
     RetainPtr<CMSampleBufferRef> createCMSampleBuffer(CGImageRef, const MediaTime&, const IntSize&);
 

Modified: trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.mm (284294 => 284295)


--- trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.mm	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.mm	2021-10-16 00:34:25 UTC (rev 284295)
@@ -108,7 +108,7 @@
     return outputBuffer;
 }
 
-RetainPtr<CMSampleBufferRef> ImageTransferSessionVT::convertCMSampleBuffer(CMSampleBufferRef sourceBuffer, const IntSize& size)
+RetainPtr<CMSampleBufferRef> ImageTransferSessionVT::convertCMSampleBuffer(CMSampleBufferRef sourceBuffer, const IntSize& size, const MediaTime* sampleTime)
 {
     if (!sourceBuffer)
         return nullptr;
@@ -141,6 +141,14 @@
             RELEASE_LOG(Media, "ImageTransferSessionVT::convertCMSampleBuffer: CMSampleBufferGetSampleTimingInfoArray failed with error code: %d", static_cast<int>(status));
             return nullptr;
         }
+
+        if (sampleTime) {
+            auto cmTime = PAL::toCMTime(*sampleTime);
+            for (auto& timing : timingInfoArray) {
+                timing.presentationTimeStamp = cmTime;
+                timing.decodeTimeStamp = cmTime;
+            }
+        }
         timeingInfoPtr = timingInfoArray.data();
     }
 
@@ -287,9 +295,9 @@
     return MediaSampleAVFObjC::create(sampleBuffer.get(), rotation, mirrored);
 }
 
-RefPtr<MediaSample> ImageTransferSessionVT::createMediaSample(CMSampleBufferRef buffer, const IntSize& size, MediaSample::VideoRotation rotation, bool mirrored)
+RefPtr<MediaSample> ImageTransferSessionVT::createMediaSample(CMSampleBufferRef buffer, const MediaTime& sampleTime, const IntSize& size, MediaSample::VideoRotation rotation, bool mirrored)
 {
-    auto sampleBuffer = convertCMSampleBuffer(buffer, size);
+    auto sampleBuffer = convertCMSampleBuffer(buffer, size, &sampleTime);
     if (!sampleBuffer)
         return nullptr;
 

Copied: trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp (from rev 284294, trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.cpp) (0 => 284295)


--- trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp	2021-10-16 00:34:25 UTC (rev 284295)
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2017-2021 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. ``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
+ * 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.
+ */
+
+#include "config.h"
+#include "DisplayCaptureSourceCocoa.h"
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
+
+#include "CGDisplayStreamScreenCaptureSource.h"
+#include "ImageTransferSessionVT.h"
+#include "Logging.h"
+#include "MediaSampleAVFObjC.h"
+#include "PixelBufferConformerCV.h"
+#include "RealtimeMediaSource.h"
+#include "RealtimeMediaSourceCenter.h"
+#include "RealtimeMediaSourceSettings.h"
+#include "RealtimeVideoUtilities.h"
+#include "RemoteVideoSample.h"
+#include "ReplayKitCaptureSource.h"
+#include "Timer.h"
+#include <CoreMedia/CMSync.h>
+#include <IOSurface/IOSurfaceRef.h>
+#include <mach/mach_time.h>
+#include <pal/avfoundation/MediaTimeAVFoundation.h>
+#include <pal/spi/cf/CoreAudioSPI.h>
+#include <pal/spi/cg/CoreGraphicsSPI.h>
+#include <pal/spi/cocoa/IOSurfaceSPI.h>
+#include <sys/time.h>
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+
+#include "CoreVideoSoftLink.h"
+#include <pal/cf/CoreMediaSoftLink.h>
+
+namespace WebCore {
+
+CaptureSourceOrError DisplayCaptureSourceCocoa::create(const CaptureDevice& device, const MediaConstraints* constraints)
+{
+    switch (device.type()) {
+    case CaptureDevice::DeviceType::Screen:
+#if PLATFORM(IOS)
+        return create(ReplayKitCaptureSource::create(device.persistentId()), device, constraints);
+#else
+        return create(CGDisplayStreamScreenCaptureSource::create(device.persistentId()), device, constraints);
+#endif
+    case CaptureDevice::DeviceType::Window:
+    case CaptureDevice::DeviceType::Microphone:
+    case CaptureDevice::DeviceType::Speaker:
+    case CaptureDevice::DeviceType::Camera:
+    case CaptureDevice::DeviceType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+
+    return { };
+}
+
+CaptureSourceOrError DisplayCaptureSourceCocoa::create(Expected<UniqueRef<Capturer>, String>&& capturer, const CaptureDevice& device, const MediaConstraints* constraints)
+{
+    if (!capturer.has_value())
+        return CaptureSourceOrError { WTFMove(capturer.error()) };
+
+    auto source = adoptRef(*new DisplayCaptureSourceCocoa(WTFMove(capturer.value()), String { device.label() }));
+    if (constraints) {
+        auto result = source->applyConstraints(*constraints);
+        if (result)
+            return WTFMove(result.value().badConstraint);
+    }
+
+    return CaptureSourceOrError(WTFMove(source));
+}
+
+DisplayCaptureSourceCocoa::DisplayCaptureSourceCocoa(UniqueRef<Capturer>&& capturer, String&& name)
+    : RealtimeMediaSource(Type::Video, WTFMove(name))
+    , m_capturer(WTFMove(capturer))
+    , m_timer(RunLoop::current(), this, &DisplayCaptureSourceCocoa::emitFrame)
+    , m_capturerIsRunningObserver([weakThis = WeakPtr { *this }] (bool isRunning) { if (weakThis) weakThis->notifyMutedChange(!isRunning); })
+{
+    m_capturer->setIsRunningObserver(&m_capturerIsRunningObserver);
+}
+
+DisplayCaptureSourceCocoa::~DisplayCaptureSourceCocoa()
+{
+}
+
+const RealtimeMediaSourceCapabilities& DisplayCaptureSourceCocoa::capabilities()
+{
+    if (!m_capabilities) {
+        RealtimeMediaSourceCapabilities capabilities(settings().supportedConstraints());
+
+        auto intrinsicSize = m_capturer->intrinsicSize();
+        capabilities.setWidth(CapabilityValueOrRange(1, intrinsicSize.width()));
+        capabilities.setHeight(CapabilityValueOrRange(1, intrinsicSize.height()));
+        capabilities.setFrameRate(CapabilityValueOrRange(.01, 30.0));
+
+        m_capabilities = WTFMove(capabilities);
+    }
+    return m_capabilities.value();
+}
+
+const RealtimeMediaSourceSettings& DisplayCaptureSourceCocoa::settings()
+{
+    if (!m_currentSettings) {
+        RealtimeMediaSourceSettings settings;
+        settings.setFrameRate(frameRate());
+
+        auto size = this->size();
+        settings.setWidth(size.width());
+        settings.setHeight(size.height());
+
+        settings.setDisplaySurface(m_capturer->surfaceType());
+        settings.setLogicalSurface(false);
+
+        RealtimeMediaSourceSupportedConstraints supportedConstraints;
+        supportedConstraints.setSupportsFrameRate(true);
+        supportedConstraints.setSupportsWidth(true);
+        supportedConstraints.setSupportsHeight(true);
+        supportedConstraints.setSupportsDisplaySurface(true);
+        supportedConstraints.setSupportsLogicalSurface(true);
+
+        settings.setSupportedConstraints(supportedConstraints);
+
+        m_currentSettings = WTFMove(settings);
+    }
+    return m_currentSettings.value();
+}
+
+void DisplayCaptureSourceCocoa::settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag> settings)
+{
+    if (settings.contains(RealtimeMediaSourceSettings::Flag::FrameRate) && m_timer.isActive())
+        m_timer.startRepeating(1_s / frameRate());
+
+    m_currentSettings = { };
+}
+
+void DisplayCaptureSourceCocoa::startProducingData()
+{
+    m_startTime = MonotonicTime::now();
+    m_timer.startRepeating(1_s / frameRate());
+
+    commitConfiguration();
+    if (!m_capturer->start())
+        captureFailed();
+}
+
+void DisplayCaptureSourceCocoa::stopProducingData()
+{
+    m_timer.stop();
+    m_elapsedTime += MonotonicTime::now() - m_startTime;
+    m_startTime = MonotonicTime::nan();
+
+    m_capturer->stop();
+}
+
+Seconds DisplayCaptureSourceCocoa::elapsedTime()
+{
+    if (std::isnan(m_startTime))
+        return m_elapsedTime;
+
+    return m_elapsedTime + (MonotonicTime::now() - m_startTime);
+}
+
+// We keep the aspect ratio of the intrinsic size for the frame size as getDisplayMedia allows max constraints only.
+void DisplayCaptureSourceCocoa::updateFrameSize()
+{
+    auto intrinsicSize = this->intrinsicSize();
+
+    auto frameSize = size();
+    if (!frameSize.height())
+        frameSize.setHeight(intrinsicSize.height());
+    if (!frameSize.width())
+        frameSize.setWidth(intrinsicSize.width());
+
+    auto maxHeight = std::min(frameSize.height(), intrinsicSize.height());
+    auto maxWidth = std::min(frameSize.width(), intrinsicSize.width());
+
+    auto heightForMaxWidth = maxWidth * intrinsicSize.height() / intrinsicSize.width();
+    auto widthForMaxHeight = maxHeight * intrinsicSize.width() / intrinsicSize.height();
+
+    if (heightForMaxWidth <= maxHeight) {
+        setSize({ maxWidth, heightForMaxWidth });
+        return;
+    }
+    if (widthForMaxHeight <= maxWidth) {
+        setSize({ widthForMaxHeight, maxHeight });
+        return;
+    }
+    setSize(intrinsicSize);
+}
+
+void DisplayCaptureSourceCocoa::emitFrame()
+{
+    if (muted())
+        return;
+
+    if (!m_imageTransferSession)
+        m_imageTransferSession = ImageTransferSessionVT::create(preferedPixelBufferFormat());
+
+    auto sampleTime = MediaTime::createWithDouble((elapsedTime() + 100_ms).seconds());
+
+    auto frame = m_capturer->generateFrame();
+    auto imageSize = WTF::switchOn(frame,
+        [](RetainPtr<IOSurfaceRef>& surface) -> IntSize {
+            if (!surface)
+                return { };
+
+            return IntSize(IOSurfaceGetWidth(surface.get()), IOSurfaceGetHeight(surface.get()));
+        },
+        [](RefPtr<NativeImage>& image) -> IntSize {
+            if (!image)
+                return { };
+
+            return image->size();
+        },
+        [](RetainPtr<CMSampleBufferRef>& sample) -> IntSize {
+            if (!sample)
+                return { };
+
+            CMFormatDescriptionRef formatDescription = PAL::CMSampleBufferGetFormatDescription(sample.get());
+            if (PAL::CMFormatDescriptionGetMediaType(formatDescription) != kCMMediaType_Video)
+                return IntSize();
+
+            return IntSize(PAL::CMVideoFormatDescriptionGetPresentationDimensions(formatDescription, true, true));
+        }
+    );
+
+    if (imageSize.isEmpty())
+        return;
+
+    if (intrinsicSize() != imageSize) {
+        setIntrinsicSize(imageSize);
+        updateFrameSize();
+    }
+
+    auto sample = WTF::switchOn(frame,
+        [this, sampleTime](RetainPtr<IOSurfaceRef>& surface) -> RefPtr<MediaSample> {
+            if (!surface)
+                return nullptr;
+
+            return m_imageTransferSession->createMediaSample(surface.get(), sampleTime, size());
+        },
+        [this, sampleTime](RefPtr<NativeImage>& image) -> RefPtr<MediaSample> {
+            if (!image)
+                return nullptr;
+
+            return m_imageTransferSession->createMediaSample(image->platformImage().get(), sampleTime, size());
+        },
+        [this, sampleTime](RetainPtr<CMSampleBufferRef>& sample) -> RefPtr<MediaSample> {
+            if (!sample)
+                return nullptr;
+
+            return m_imageTransferSession->createMediaSample(sample.get(), sampleTime, size());
+        }
+    );
+
+    if (!sample) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    videoSampleAvailable(*sample.get());
+}
+
+void DisplayCaptureSourceCocoa::setLogger(const Logger& logger, const void* identifier)
+{
+    RealtimeMediaSource::setLogger(logger, identifier);
+    m_capturer->setLogger(logger, identifier);
+}
+
+void DisplayCaptureSourceCocoa::Capturer::setLogger(const Logger& newLogger, const void* newLogIdentifier)
+{
+    m_logger = &newLogger;
+    m_logIdentifier = newLogIdentifier;
+}
+
+WTFLogChannel& DisplayCaptureSourceCocoa::Capturer::logChannel() const
+{
+    return LogWebRTC;
+}
+
+void DisplayCaptureSourceCocoa::Capturer::capturerIsRunningChanged(bool running)
+{
+    if (m_observer)
+        (*m_observer)(running);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)

Copied: trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.h (from rev 284294, trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.h) (0 => 284295)


--- trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2017-2021 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. ``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
+ * 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
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
+
+#include "CaptureDevice.h"
+#include "RealtimeMediaSource.h"
+#include <wtf/Observer.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/RunLoop.h>
+#include <wtf/UniqueRef.h>
+#include <wtf/text/WTFString.h>
+
+
+typedef struct CGImage *CGImageRef;
+typedef struct __CVBuffer *CVPixelBufferRef;
+typedef struct __IOSurface *IOSurfaceRef;
+
+namespace WTF {
+class MediaTime;
+}
+
+namespace WebCore {
+
+class CaptureDeviceInfo;
+class ImageTransferSessionVT;
+class PixelBufferConformerCV;
+
+class DisplayCaptureSourceCocoa final : public RealtimeMediaSource, public CanMakeWeakPtr<DisplayCaptureSourceCocoa> {
+public:
+    using DisplayFrameType = std::variant<RefPtr<NativeImage>, RetainPtr<IOSurfaceRef>, RetainPtr<CMSampleBufferRef>>;
+
+    class Capturer : public LoggerHelper {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        virtual ~Capturer() = default;
+
+        virtual bool start() = 0;
+        virtual void stop() = 0;
+        virtual DisplayFrameType generateFrame() = 0;
+        virtual CaptureDevice::DeviceType deviceType() const = 0;
+        virtual RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const = 0;
+        virtual void commitConfiguration(const RealtimeMediaSourceSettings&) = 0;
+        virtual IntSize intrinsicSize() const = 0;
+
+        virtual void setLogger(const Logger&, const void*);
+        const Logger* loggerPtr() const { return m_logger.get(); }
+        const Logger& logger() const final { ASSERT(m_logger); return *m_logger.get(); }
+        const void* logIdentifier() const final { return m_logIdentifier; }
+        WTFLogChannel& logChannel() const final;
+
+        using IsRunningObserver = WTF::Observer<void(bool)>;
+        void setIsRunningObserver(IsRunningObserver* observer) { m_observer = observer; };
+
+    protected:
+        Capturer() = default;
+        void capturerIsRunningChanged(bool);
+
+    private:
+        WeakPtr<IsRunningObserver> m_observer;
+        RefPtr<const Logger> m_logger;
+        const void* m_logIdentifier;
+    };
+
+    static CaptureSourceOrError create(const CaptureDevice&, const MediaConstraints*);
+    static CaptureSourceOrError create(Expected<UniqueRef<Capturer>, String>&&, const CaptureDevice&, const MediaConstraints*);
+
+    Seconds elapsedTime();
+    void updateFrameSize();
+
+private:
+    DisplayCaptureSourceCocoa(UniqueRef<Capturer>&&, String&& name);
+    virtual ~DisplayCaptureSourceCocoa();
+
+    void startProducingData() final;
+    void stopProducingData() final;
+    void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) final;
+    bool isCaptureSource() const final { return true; }
+    const RealtimeMediaSourceCapabilities& capabilities() final;
+    const RealtimeMediaSourceSettings& settings() final;
+    CaptureDevice::DeviceType deviceType() const { return m_capturer->deviceType(); }
+    void commitConfiguration() final { m_capturer->commitConfiguration(settings()); }
+
+    const char* logClassName() const final { return "DisplayCaptureSourceCocoa"; }
+    void setLogger(const Logger&, const void*) final;
+
+    void emitFrame();
+
+    UniqueRef<Capturer> m_capturer;
+    std::optional<RealtimeMediaSourceCapabilities> m_capabilities;
+    std::optional<RealtimeMediaSourceSettings> m_currentSettings;
+    RealtimeMediaSourceSupportedConstraints m_supportedConstraints;
+
+    MonotonicTime m_startTime { MonotonicTime::nan() };
+    Seconds m_elapsedTime { 0_s };
+
+    RunLoop::Timer<DisplayCaptureSourceCocoa> m_timer;
+
+    std::unique_ptr<ImageTransferSessionVT> m_imageTransferSession;
+    WTF::Observer<void(bool)> m_capturerIsRunningObserver;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)

Added: trunk/Source/WebCore/platform/mediastream/ios/ReplayKitCaptureSource.h (0 => 284295)


--- trunk/Source/WebCore/platform/mediastream/ios/ReplayKitCaptureSource.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/ios/ReplayKitCaptureSource.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 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. ``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
+ * 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
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(IOS)
+
+#include "DisplayCaptureSourceCocoa.h"
+#include "Timer.h"
+#include <wtf/RetainPtr.h>
+
+OBJC_CLASS RPScreenRecorder;
+OBJC_CLASS WebCoreReplayKitScreenRecorderHelper;
+
+namespace WebCore {
+
+class ReplayKitCaptureSource final : public DisplayCaptureSourceCocoa::Capturer, public CanMakeWeakPtr<ReplayKitCaptureSource> {
+public:
+    static Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> create(const String&);
+
+    ReplayKitCaptureSource();
+    virtual ~ReplayKitCaptureSource();
+
+    static bool isAvailable();
+
+    static std::optional<CaptureDevice> screenCaptureDeviceWithPersistentID(const String&);
+    static void screenCaptureDevices(Vector<CaptureDevice>&);
+
+    void captureStateDidChange();
+
+private:
+
+    // DisplayCaptureSourceCocoa::Capturer
+    bool start() final;
+    void stop() final;
+    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
+    CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Screen; }
+    RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor; }
+    virtual void commitConfiguration(const RealtimeMediaSourceSettings&) { }
+    virtual IntSize intrinsicSize() const { return m_intrinsicSize; }
+
+    // LoggerHelper
+    const char* logClassName() const final { return "ReplayKitCaptureSource"; }
+
+    void screenRecorderDidOutputVideoSample(RetainPtr<CMSampleBufferRef>&&);
+    void startCaptureWatchdogTimer();
+    void verifyCaptureIsActive();
+
+    RetainPtr<CMSampleBufferRef> m_currentFrame;
+    RetainPtr<RPScreenRecorder> m_screenRecorder;
+    RetainPtr<WebCoreReplayKitScreenRecorderHelper> m_recorderHelper;
+
+    Timer m_captureWatchdogTimer;
+    uint64_t m_frameCount { 0 };
+    uint64_t m_lastFrameCount { 0 };
+    IntSize m_intrinsicSize;
+    bool m_isRunning { false };
+    bool m_interrupted { false };
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(IOS)

Added: trunk/Source/WebCore/platform/mediastream/ios/ReplayKitCaptureSource.mm (0 => 284295)


--- trunk/Source/WebCore/platform/mediastream/ios/ReplayKitCaptureSource.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/ios/ReplayKitCaptureSource.mm	2021-10-16 00:34:25 UTC (rev 284295)
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2021 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. ``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
+ * 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.
+ */
+
+#include "config.h"
+#include "ReplayKitCaptureSource.h"
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(IOS)
+
+#import "Logging.h"
+#import "RealtimeVideoUtilities.h"
+#import <wtf/BlockPtr.h>
+#import <wtf/NeverDestroyed.h>
+#import <wtf/UUID.h>
+#import <wtf/text/StringToIntegerConversion.h>
+
+#import <pal/cf/CoreMediaSoftLink.h>
+#import <pal/ios/ReplayKitSoftLink.h>
+
+using namespace WebCore;
+@interface WebCoreReplayKitScreenRecorderHelper : NSObject {
+    WeakPtr<ReplayKitCaptureSource> _callback;
+}
+
+- (instancetype)initWithCallback:(WeakPtr<ReplayKitCaptureSource>&&)callback;
+- (void)disconnect;
+- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context;
+@end
+
+@implementation WebCoreReplayKitScreenRecorderHelper
+- (instancetype)initWithCallback:(WeakPtr<ReplayKitCaptureSource>&&)callback
+{
+    self = [super init];
+    if (!self)
+        return self;
+
+    _callback = WTFMove(callback);
+    [[PAL::getRPScreenRecorderClass() sharedRecorder] addObserver:self forKeyPath:@"recording" options:NSKeyValueObservingOptionNew context:(void *)nil];
+
+    return self;
+}
+
+- (void)disconnect
+{
+    _callback = nullptr;
+    [[PAL::getRPScreenRecorderClass() sharedRecorder] removeObserver:self forKeyPath:@"recording"];
+}
+
+- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
+{
+    UNUSED_PARAM(object);
+    UNUSED_PARAM(context);
+
+    if (!_callback)
+        return;
+
+    id newValue = [change valueForKey:NSKeyValueChangeNewKey];
+    bool willChange = [[change valueForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
+
+#if !RELEASE_LOG_DISABLED
+    if (_callback->loggerPtr()) {
+        auto identifier = Logger::LogSiteIdentifier("ReplayKitCaptureSource", "observeValueForKeyPath", _callback->logIdentifier());
+        RetainPtr<NSString> valueString = adoptNS([[NSString alloc] initWithFormat:@"%@", newValue]);
+        _callback->logger().logAlways(_callback->logChannel(), identifier, willChange ? "will" : "did", " change '", [keyPath UTF8String], "' to ", [valueString.get() UTF8String]);
+    }
+#endif
+
+    if (willChange)
+        return;
+
+    if ([keyPath isEqualToString:@"recording"])
+        _callback->captureStateDidChange();
+}
+@end
+
+namespace WebCore {
+
+bool ReplayKitCaptureSource::isAvailable()
+{
+    return [PAL::getRPScreenRecorderClass() sharedRecorder].isAvailable;
+}
+
+Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> ReplayKitCaptureSource::create(const String&)
+{
+    if (!isAvailable())
+        return makeUnexpected("Screen capture unavailable"_s);
+
+    return UniqueRef<DisplayCaptureSourceCocoa::Capturer>(makeUniqueRef<ReplayKitCaptureSource>());
+}
+
+ReplayKitCaptureSource::ReplayKitCaptureSource()
+    : m_captureWatchdogTimer(*this, &ReplayKitCaptureSource::verifyCaptureIsActive)
+{
+}
+
+ReplayKitCaptureSource::~ReplayKitCaptureSource()
+{
+    [m_recorderHelper disconnect];
+    stop();
+    m_currentFrame = nullptr;
+}
+
+bool ReplayKitCaptureSource::start()
+{
+    ASSERT(isAvailable());
+
+    auto identifier = LOGIDENTIFIER;
+    ALWAYS_LOG_IF(loggerPtr(), identifier);
+
+    auto *screenRecorder = [PAL::getRPScreenRecorderClass() sharedRecorder];
+    if (screenRecorder.recording)
+        return true;
+
+    // FIXME: Add support for concurrent audio capture.
+    [screenRecorder setMicrophoneEnabled:NO];
+
+    if (!m_recorderHelper)
+        m_recorderHelper = ([[WebCoreReplayKitScreenRecorderHelper alloc] initWithCallback:this]);
+
+    auto captureHandler = makeBlockPtr([this, weakThis = WeakPtr { *this }, identifier](CMSampleBufferRef _Nonnull sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable error) {
+
+        if (bufferType != RPSampleBufferTypeVideo)
+            return;
+
+        ERROR_LOG_IF(error && loggerPtr(), identifier, "startCaptureWithHandler failed ", [error localizedDescription].UTF8String);
+
+        ++m_frameCount;
+
+        RunLoop::main().dispatch([weakThis, sampleBuffer = retainPtr(sampleBuffer)]() mutable {
+            if (!weakThis)
+                return;
+
+            weakThis->screenRecorderDidOutputVideoSample(WTFMove(sampleBuffer));
+        });
+    });
+
+    auto completionHandler = makeBlockPtr([this, weakThis = WeakPtr { *this }, identifier](NSError * _Nullable error) {
+        // FIXME: It should be safe to call `videoSampleAvailable` from any thread. Test this and get rid of this main thread hop.
+        RunLoop::main().dispatch([this, weakThis, error = retainPtr(error), identifier]() mutable {
+            if (!weakThis || !error)
+                return;
+
+            ERROR_LOG_IF(loggerPtr(), identifier, "completionHandler failed ", [error localizedDescription].UTF8String);
+            weakThis->stop();
+        });
+    });
+
+    [screenRecorder startCaptureWithHandler:captureHandler.get() completionHandler:completionHandler.get()];
+
+    return true;
+}
+
+void ReplayKitCaptureSource::screenRecorderDidOutputVideoSample(RetainPtr<CMSampleBufferRef>&& sampleBuffer)
+{
+    m_currentFrame = sampleBuffer.get();
+    m_intrinsicSize = IntSize(PAL::CMVideoFormatDescriptionGetPresentationDimensions(PAL::CMSampleBufferGetFormatDescription(m_currentFrame.get()), true, true));
+}
+
+void ReplayKitCaptureSource::captureStateDidChange()
+{
+    RunLoop::main().dispatch([this, weakThis = WeakPtr { *this }, identifier = LOGIDENTIFIER]() mutable {
+        if (!weakThis)
+            return;
+
+        bool isRecording = !![[PAL::getRPScreenRecorderClass() sharedRecorder] isRecording];
+        if (m_isRunning == (isRecording && !m_interrupted))
+            return;
+
+        m_isRunning = isRecording && !m_interrupted;
+        ALWAYS_LOG_IF(loggerPtr(), identifier, m_isRunning);
+        capturerIsRunningChanged(m_isRunning);
+    });
+}
+
+void ReplayKitCaptureSource::stop()
+{
+    auto identifier = LOGIDENTIFIER;
+    ALWAYS_LOG_IF(loggerPtr(), identifier);
+    m_captureWatchdogTimer.stop();
+    m_interrupted = false;
+    m_isRunning = false;
+
+    auto *screenRecorder = [PAL::getRPScreenRecorderClass() sharedRecorder];
+    if (screenRecorder.recording) {
+        [screenRecorder stopCaptureWithHandler:^(NSError * _Nullable error) {
+            ERROR_LOG_IF(error && loggerPtr(), identifier, "startCaptureWithHandler failed ", [error localizedDescription].UTF8String);
+        }];
+    }
+}
+
+DisplayCaptureSourceCocoa::DisplayFrameType ReplayKitCaptureSource::generateFrame()
+{
+    return m_currentFrame;
+}
+
+void ReplayKitCaptureSource::verifyCaptureIsActive()
+{
+    ASSERT(m_isRunning || m_interrupted);
+    auto identifier = LOGIDENTIFIER;
+    if (m_lastFrameCount != m_frameCount) {
+        m_lastFrameCount = m_frameCount;
+        if (m_interrupted) {
+            ALWAYS_LOG_IF(loggerPtr(), identifier, "frame received after interruption, unmuting");
+            m_interrupted = false;
+            captureStateDidChange();
+        }
+        return;
+    }
+
+    ALWAYS_LOG_IF(loggerPtr(), identifier, "no frame received in ", static_cast<int>(m_captureWatchdogTimer.repeatInterval().value()), " seconds, muting");
+    m_interrupted = true;
+    captureStateDidChange();
+}
+
+void ReplayKitCaptureSource::startCaptureWatchdogTimer()
+{
+    static constexpr Seconds verifyCaptureInterval = 2_s;
+    if (m_captureWatchdogTimer.isActive())
+        return;
+
+    m_captureWatchdogTimer.startRepeating(verifyCaptureInterval);
+    m_lastFrameCount = m_frameCount;
+}
+
+static String screenDeviceUUID()
+{
+    static NeverDestroyed<String> screenID = createCanonicalUUIDString();
+    return screenID;
+}
+
+static CaptureDevice& screenDevice()
+{
+    static NeverDestroyed<CaptureDevice> device = { screenDeviceUUID(), CaptureDevice::DeviceType::Screen, makeString("Screen 1"), emptyString(), true };
+    return device;
+}
+
+std::optional<CaptureDevice> ReplayKitCaptureSource::screenCaptureDeviceWithPersistentID(const String& displayID)
+{
+    if (!isAvailable()) {
+        RELEASE_LOG_ERROR(WebRTC, "ReplayKitCaptureSource::screenCaptureDeviceWithPersistentID: screen capture unavailable");
+        return std::nullopt;
+    }
+
+    if (displayID != screenDeviceUUID()) {
+        RELEASE_LOG_ERROR(WebRTC, "ReplayKitCaptureSource::screenCaptureDeviceWithPersistentID: invalid display ID");
+        return std::nullopt;
+    }
+
+    return screenDevice();
+}
+
+void ReplayKitCaptureSource::screenCaptureDevices(Vector<CaptureDevice>& displays)
+{
+    if (isAvailable())
+        displays.append(screenDevice());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(IOS)

Modified: trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamCaptureSource.cpp (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamCaptureSource.cpp	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamCaptureSource.cpp	2021-10-16 00:34:25 UTC (rev 284295)
@@ -71,9 +71,9 @@
     m_isRunning = false;
 }
 
-DisplayCaptureSourceMac::DisplayFrameType CGDisplayStreamCaptureSource::generateFrame()
+DisplayCaptureSourceCocoa::DisplayFrameType CGDisplayStreamCaptureSource::generateFrame()
 {
-    return RetainPtr { m_currentFrame.ioSurface() };
+    return m_currentFrame;
 }
 
 bool CGDisplayStreamCaptureSource::startDisplayStream()
@@ -134,7 +134,7 @@
         reinterpret_cast<CGDisplayStreamCaptureSource *>(userInfo)->displayWasReconfigured(display, flags);
 }
 
-void CGDisplayStreamCaptureSource::newFrame(CGDisplayStreamFrameStatus status, DisplaySurface&& newFrame)
+void CGDisplayStreamCaptureSource::newFrame(CGDisplayStreamFrameStatus status, RetainPtr<IOSurfaceRef>&& newFrame)
 {
     switch (status) {
     case kCGDisplayStreamFrameStatusFrameComplete:
@@ -171,7 +171,7 @@
         if (!rects || !count)
             return;
 
-        RunLoop::main().dispatch([weakThis, status, frame = DisplaySurface { frameSurface }]() mutable {
+        RunLoop::main().dispatch([weakThis, status, frame = retainPtr(frameSurface)]() mutable {
             if (!weakThis)
                 return;
             weakThis->newFrame(status, WTFMove(frame));

Modified: trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamCaptureSource.h (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamCaptureSource.h	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamCaptureSource.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -27,8 +27,7 @@
 
 #if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
 
-#include "DisplayCaptureSourceMac.h"
-#include "IOSurface.h"
+#include "DisplayCaptureSourceCocoa.h"
 #include <CoreGraphics/CGDisplayConfiguration.h>
 #include <CoreGraphics/CGDisplayStream.h>
 #include <wtf/BlockPtr.h>
@@ -40,10 +39,10 @@
 
 namespace WebCore {
 
-class CGDisplayStreamCaptureSource : public DisplayCaptureSourceMac::Capturer, public CanMakeWeakPtr<CGDisplayStreamCaptureSource> {
+class CGDisplayStreamCaptureSource : public DisplayCaptureSourceCocoa::Capturer, public CanMakeWeakPtr<CGDisplayStreamCaptureSource> {
 public:
     explicit CGDisplayStreamCaptureSource() = default;
-    ~CGDisplayStreamCaptureSource();
+    virtual ~CGDisplayStreamCaptureSource();
 
 protected:
     using FrameAvailableCallback = void (^)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef);
@@ -60,10 +59,10 @@
 private:
     static void displayReconfigurationCallBack(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*);
 
-    // DisplayCaptureSourceMac::Capturer
+    // DisplayCaptureSourceCocoa::Capturer
     bool start() final;
     void stop() final;
-    DisplayCaptureSourceMac::DisplayFrameType generateFrame() final;
+    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
     void commitConfiguration(const RealtimeMediaSourceSettings&) final;
 
     void displayWasReconfigured(CGDirectDisplayID, CGDisplayChangeSummaryFlags);
@@ -70,41 +69,9 @@
     bool startDisplayStream();
     FrameAvailableCallback frameAvailableHandler();
 
-    class DisplaySurface {
-    public:
-        DisplaySurface() = default;
-        explicit DisplaySurface(IOSurfaceRef surface)
-            : m_surface(surface)
-        {
-            if (m_surface)
-                IOSurfaceIncrementUseCount(m_surface.get());
-        }
+    void newFrame(CGDisplayStreamFrameStatus, RetainPtr<IOSurfaceRef>&&);
 
-        ~DisplaySurface()
-        {
-            if (m_surface)
-                IOSurfaceDecrementUseCount(m_surface.get());
-        }
-
-        DisplaySurface& operator=(IOSurfaceRef surface)
-        {
-            if (m_surface)
-                IOSurfaceDecrementUseCount(m_surface.get());
-            if (surface)
-                IOSurfaceIncrementUseCount(surface);
-            m_surface = surface;
-            return *this;
-        }
-
-        IOSurfaceRef ioSurface() const { return m_surface.get(); }
-
-    private:
-        RetainPtr<IOSurfaceRef> m_surface;
-    };
-
-    void newFrame(CGDisplayStreamFrameStatus, DisplaySurface&&);
-
-    DisplaySurface m_currentFrame;
+    RetainPtr<IOSurfaceRef> m_currentFrame;
     RetainPtr<CGDisplayStreamRef> m_displayStream;
     OSObjectPtr<dispatch_queue_t> m_captureQueue;
     BlockPtr<void(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef)> m_frameAvailableHandler;

Modified: trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.h (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.h	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -41,7 +41,7 @@
 
 class CGDisplayStreamScreenCaptureSource final : public CGDisplayStreamCaptureSource {
 public:
-    static Expected<UniqueRef<DisplayCaptureSourceMac::Capturer>, String> create(const String&);
+    static Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> create(const String&);
 
     explicit CGDisplayStreamScreenCaptureSource(uint32_t);
     ~CGDisplayStreamScreenCaptureSource() = default;
@@ -51,7 +51,7 @@
 
 private:
 
-    // DisplayCaptureSourceMac::Capturer
+    // DisplayCaptureSourceCocoa::Capturer
     CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Screen; }
     RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor; }
     IntSize intrinsicSize() const final;
@@ -63,38 +63,6 @@
     RetainPtr<CGDisplayStreamRef> createDisplayStream(FrameAvailableCallback, dispatch_queue_t) final;
     bool checkDisplayStream() final;
 
-    class DisplaySurface {
-    public:
-        DisplaySurface() = default;
-        explicit DisplaySurface(IOSurfaceRef surface)
-            : m_surface(surface)
-        {
-            if (m_surface)
-                IOSurfaceIncrementUseCount(m_surface.get());
-        }
-
-        ~DisplaySurface()
-        {
-            if (m_surface)
-                IOSurfaceDecrementUseCount(m_surface.get());
-        }
-
-        DisplaySurface& operator=(IOSurfaceRef surface)
-        {
-            if (m_surface)
-                IOSurfaceDecrementUseCount(m_surface.get());
-            if (surface)
-                IOSurfaceIncrementUseCount(surface);
-            m_surface = surface;
-            return *this;
-        }
-
-        IOSurfaceRef ioSurface() const { return m_surface.get(); }
-
-    private:
-        RetainPtr<IOSurfaceRef> m_surface;
-    };
-
     RetainPtr<CGDisplayStreamRef> m_displayStream;
 
     uint32_t m_displayID { 0 };

Modified: trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.mm (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.mm	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/CGDisplayStreamScreenCaptureSource.mm	2021-10-16 00:34:25 UTC (rev 284295)
@@ -75,7 +75,7 @@
     return std::nullopt;
 }
 
-Expected<UniqueRef<DisplayCaptureSourceMac::Capturer>, String> CGDisplayStreamScreenCaptureSource::create(const String& deviceID)
+Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> CGDisplayStreamScreenCaptureSource::create(const String& deviceID)
 {
     auto displayID = parseInteger<uint32_t>(deviceID);
     if (!displayID)
@@ -85,7 +85,7 @@
     if (!actualDisplayID)
         return makeUnexpected("Invalid display ID"_s);
 
-    return UniqueRef<DisplayCaptureSourceMac::Capturer>(makeUniqueRef<CGDisplayStreamScreenCaptureSource>(actualDisplayID.value()));
+    return UniqueRef<DisplayCaptureSourceCocoa::Capturer>(makeUniqueRef<CGDisplayStreamScreenCaptureSource>(actualDisplayID.value()));
 }
 
 CGDisplayStreamScreenCaptureSource::CGDisplayStreamScreenCaptureSource(uint32_t displayID)

Modified: trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp	2021-10-16 00:34:25 UTC (rev 284295)
@@ -34,10 +34,11 @@
 
 #if PLATFORM(MAC)
 #include "CGDisplayStreamScreenCaptureSource.h"
-#include <CoreGraphics/CGDirectDisplay.h>
 #endif
 
-#include "CoreVideoSoftLink.h"
+#if PLATFORM(IOS)
+#include "ReplayKitCaptureSource.h"
+#endif
 
 namespace WebCore {
 
@@ -61,6 +62,8 @@
 {
 #if PLATFORM(MAC)
     CGDisplayStreamScreenCaptureSource::screenCaptureDevices(m_devices);
+#elif PLATFORM(IOS)
+    ReplayKitCaptureSource::screenCaptureDevices(m_devices);
 #endif
 }
 

Deleted: trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.cpp (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.cpp	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.cpp	2021-10-16 00:34:25 UTC (rev 284295)
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2017-2021 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. ``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
- * 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.
- */
-
-#include "config.h"
-#include "DisplayCaptureSourceMac.h"
-
-#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
-
-#include "CGDisplayStreamScreenCaptureSource.h"
-#include "Logging.h"
-#include "MediaSampleAVFObjC.h"
-#include "PixelBufferConformerCV.h"
-#include "RealtimeMediaSource.h"
-#include "RealtimeMediaSourceCenter.h"
-#include "RealtimeMediaSourceSettings.h"
-#include "RealtimeVideoUtilities.h"
-#include "RemoteVideoSample.h"
-#include "Timer.h"
-#include <CoreMedia/CMSync.h>
-#include <mach/mach_time.h>
-#include <pal/avfoundation/MediaTimeAVFoundation.h>
-#include <pal/spi/cf/CoreAudioSPI.h>
-#include <pal/spi/cg/CoreGraphicsSPI.h>
-#include <pal/spi/cocoa/IOSurfaceSPI.h>
-#include <sys/time.h>
-#include <wtf/MainThread.h>
-#include <wtf/NeverDestroyed.h>
-
-#include "CoreVideoSoftLink.h"
-#include <pal/cf/CoreMediaSoftLink.h>
-
-namespace WebCore {
-
-CaptureSourceOrError DisplayCaptureSourceMac::create(const CaptureDevice& device, const MediaConstraints* constraints)
-{
-    switch (device.type()) {
-    case CaptureDevice::DeviceType::Screen:
-        return create(CGDisplayStreamScreenCaptureSource::create(device.persistentId()), device, constraints);
-    case CaptureDevice::DeviceType::Window:
-    case CaptureDevice::DeviceType::Microphone:
-    case CaptureDevice::DeviceType::Speaker:
-    case CaptureDevice::DeviceType::Camera:
-    case CaptureDevice::DeviceType::Unknown:
-        ASSERT_NOT_REACHED();
-        break;
-    }
-
-    return { };
-}
-
-CaptureSourceOrError DisplayCaptureSourceMac::create(Expected<UniqueRef<Capturer>, String>&& capturer, const CaptureDevice& device, const MediaConstraints* constraints)
-{
-    if (!capturer.has_value())
-        return CaptureSourceOrError { WTFMove(capturer.error()) };
-
-    auto source = adoptRef(*new DisplayCaptureSourceMac(WTFMove(capturer.value()), String { device.label() }));
-    if (constraints) {
-        auto result = source->applyConstraints(*constraints);
-        if (result)
-            return WTFMove(result.value().badConstraint);
-    }
-
-    return CaptureSourceOrError(WTFMove(source));
-}
-
-DisplayCaptureSourceMac::DisplayCaptureSourceMac(UniqueRef<Capturer>&& capturer, String&& name)
-    : RealtimeMediaSource(Type::Video, WTFMove(name))
-    , m_capturer(WTFMove(capturer))
-    , m_timer(RunLoop::current(), this, &DisplayCaptureSourceMac::emitFrame)
-{
-}
-
-DisplayCaptureSourceMac::~DisplayCaptureSourceMac()
-{
-}
-
-const RealtimeMediaSourceCapabilities& DisplayCaptureSourceMac::capabilities()
-{
-    if (!m_capabilities) {
-        RealtimeMediaSourceCapabilities capabilities(settings().supportedConstraints());
-
-        auto intrinsicSize = m_capturer->intrinsicSize();
-        capabilities.setWidth(CapabilityValueOrRange(1, intrinsicSize.width()));
-        capabilities.setHeight(CapabilityValueOrRange(1, intrinsicSize.height()));
-        capabilities.setFrameRate(CapabilityValueOrRange(.01, 30.0));
-
-        m_capabilities = WTFMove(capabilities);
-    }
-    return m_capabilities.value();
-}
-
-const RealtimeMediaSourceSettings& DisplayCaptureSourceMac::settings()
-{
-    if (!m_currentSettings) {
-        RealtimeMediaSourceSettings settings;
-        settings.setFrameRate(frameRate());
-
-        auto size = this->size();
-        settings.setWidth(size.width());
-        settings.setHeight(size.height());
-
-        settings.setDisplaySurface(m_capturer->surfaceType());
-        settings.setLogicalSurface(false);
-
-        RealtimeMediaSourceSupportedConstraints supportedConstraints;
-        supportedConstraints.setSupportsFrameRate(true);
-        supportedConstraints.setSupportsWidth(true);
-        supportedConstraints.setSupportsHeight(true);
-        supportedConstraints.setSupportsDisplaySurface(true);
-        supportedConstraints.setSupportsLogicalSurface(true);
-
-        settings.setSupportedConstraints(supportedConstraints);
-
-        m_currentSettings = WTFMove(settings);
-    }
-    return m_currentSettings.value();
-}
-
-void DisplayCaptureSourceMac::settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag> settings)
-{
-    if (settings.contains(RealtimeMediaSourceSettings::Flag::FrameRate) && m_timer.isActive())
-        m_timer.startRepeating(1_s / frameRate());
-
-    m_currentSettings = { };
-}
-
-void DisplayCaptureSourceMac::startProducingData()
-{
-    m_startTime = MonotonicTime::now();
-    m_timer.startRepeating(1_s / frameRate());
-
-    commitConfiguration();
-    if (!m_capturer->start())
-        captureFailed();
-}
-
-void DisplayCaptureSourceMac::stopProducingData()
-{
-    m_timer.stop();
-    m_elapsedTime += MonotonicTime::now() - m_startTime;
-    m_startTime = MonotonicTime::nan();
-
-    m_capturer->stop();
-}
-
-Seconds DisplayCaptureSourceMac::elapsedTime()
-{
-    if (std::isnan(m_startTime))
-        return m_elapsedTime;
-
-    return m_elapsedTime + (MonotonicTime::now() - m_startTime);
-}
-
-// We keep the aspect ratio of the intrinsic size for the frame size as getDisplayMedia allows max constraints only.
-void DisplayCaptureSourceMac::updateFrameSize()
-{
-    auto intrinsicSize = this->intrinsicSize();
-
-    auto frameSize = size();
-    if (!frameSize.height())
-        frameSize.setHeight(intrinsicSize.height());
-    if (!frameSize.width())
-        frameSize.setWidth(intrinsicSize.width());
-
-    auto maxHeight = std::min(frameSize.height(), intrinsicSize.height());
-    auto maxWidth = std::min(frameSize.width(), intrinsicSize.width());
-
-    auto heightForMaxWidth = maxWidth * intrinsicSize.height() / intrinsicSize.width();
-    auto widthForMaxHeight = maxHeight * intrinsicSize.width() / intrinsicSize.height();
-
-    if (heightForMaxWidth <= maxHeight) {
-        setSize({ maxWidth, heightForMaxWidth });
-        return;
-    }
-    if (widthForMaxHeight <= maxWidth) {
-        setSize({ widthForMaxHeight, maxHeight });
-        return;
-    }
-    setSize(intrinsicSize);
-}
-
-void DisplayCaptureSourceMac::emitFrame()
-{
-    if (muted())
-        return;
-
-    if (!m_imageTransferSession)
-        m_imageTransferSession = ImageTransferSessionVT::create(preferedPixelBufferFormat());
-
-    auto sampleTime = MediaTime::createWithDouble((elapsedTime() + 100_ms).seconds());
-
-    auto frame = m_capturer->generateFrame();
-    auto imageSize = WTF::switchOn(frame,
-        [](RetainPtr<IOSurfaceRef> surface) -> IntSize {
-            if (!surface)
-                return { };
-
-            return IntSize(IOSurfaceGetWidth(surface.get()), IOSurfaceGetHeight(surface.get()));
-        },
-        [](RefPtr<NativeImage> image) -> IntSize {
-            if (!image)
-                return { };
-
-            return image->size();
-        }
-    );
-
-    if (imageSize.isEmpty())
-        return;
-
-    if (intrinsicSize() != imageSize) {
-        setIntrinsicSize(imageSize);
-        updateFrameSize();
-    }
-
-    auto sample = WTF::switchOn(frame,
-        [this, sampleTime](RetainPtr<IOSurfaceRef> surface) -> RefPtr<MediaSample> {
-            if (!surface)
-                return nullptr;
-
-            return m_imageTransferSession->createMediaSample(surface.get(), sampleTime, size());
-        },
-        [this, sampleTime](RefPtr<NativeImage> image) -> RefPtr<MediaSample> {
-            if (!image)
-                return nullptr;
-
-            return m_imageTransferSession->createMediaSample(image->platformImage().get(), sampleTime, size());
-        }
-    );
-
-    if (!sample) {
-        ASSERT_NOT_REACHED();
-        return;
-    }
-
-    videoSampleAvailable(*sample.get());
-}
-
-void DisplayCaptureSourceMac::Capturer::setLogger(const Logger& newLogger, const void* newLogIdentifier)
-{
-    m_logger = &newLogger;
-    m_logIdentifier = newLogIdentifier;
-}
-
-WTFLogChannel& DisplayCaptureSourceMac::Capturer::logChannel() const
-{
-    return LogWebRTC;
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Deleted: trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.h (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.h	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceMac.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2017-2021 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. ``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
- * 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
-
-#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
-
-#include "CaptureDevice.h"
-#include "ImageTransferSessionVT.h"
-#include "RealtimeMediaSource.h"
-#include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
-#include <wtf/RunLoop.h>
-#include <wtf/UniqueRef.h>
-#include <wtf/text/WTFString.h>
-
-typedef struct CGImage *CGImageRef;
-typedef struct __CVBuffer *CVPixelBufferRef;
-typedef struct __IOSurface *IOSurfaceRef;
-
-namespace WTF {
-class MediaTime;
-}
-
-namespace WebCore {
-
-class CaptureDeviceInfo;
-class ImageTransferSessionVT;
-class PixelBufferConformerCV;
-
-class DisplayCaptureSourceMac final : public RealtimeMediaSource {
-public:
-    using DisplayFrameType = std::variant<RefPtr<NativeImage>, RetainPtr<IOSurfaceRef>>;
-
-    class Capturer : public LoggerHelper {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        virtual ~Capturer() = default;
-
-        virtual bool start() = 0;
-        virtual void stop() = 0;
-        virtual DisplayFrameType generateFrame() = 0;
-        virtual CaptureDevice::DeviceType deviceType() const = 0;
-        virtual RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const = 0;
-        virtual void commitConfiguration(const RealtimeMediaSourceSettings&) = 0;
-        virtual IntSize intrinsicSize() const = 0;
-
-        virtual void setLogger(const Logger&, const void*);
-        const Logger* loggerPtr() const { return m_logger.get(); }
-        const Logger& logger() const final { ASSERT(m_logger); return *m_logger.get(); }
-        const void* logIdentifier() const final { return m_logIdentifier; }
-        WTFLogChannel& logChannel() const final;
-
-    private:
-        RefPtr<const Logger> m_logger;
-        const void* m_logIdentifier;
-    };
-
-    static CaptureSourceOrError create(const CaptureDevice&, const MediaConstraints*);
-    static CaptureSourceOrError create(Expected<UniqueRef<Capturer>, String>&&, const CaptureDevice&, const MediaConstraints*);
-
-    Seconds elapsedTime();
-    void updateFrameSize();
-
-private:
-    DisplayCaptureSourceMac(UniqueRef<Capturer>&&, String&& name);
-    ~DisplayCaptureSourceMac();
-
-    void startProducingData() final;
-    void stopProducingData() final;
-    void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) final;
-    bool isCaptureSource() const final { return true; }
-    const RealtimeMediaSourceCapabilities& capabilities() final;
-    const RealtimeMediaSourceSettings& settings() final;
-    CaptureDevice::DeviceType deviceType() const { return m_capturer->deviceType(); }
-    void commitConfiguration() final { m_capturer->commitConfiguration(settings()); }
-
-    const char* logClassName() const final { return "DisplayCaptureSourceMac"; }
-
-    void emitFrame();
-
-    UniqueRef<Capturer> m_capturer;
-    std::optional<RealtimeMediaSourceCapabilities> m_capabilities;
-    std::optional<RealtimeMediaSourceSettings> m_currentSettings;
-    RealtimeMediaSourceSupportedConstraints m_supportedConstraints;
-
-    MonotonicTime m_startTime { MonotonicTime::nan() };
-    Seconds m_elapsedTime { 0_s };
-
-    RunLoop::Timer<DisplayCaptureSourceMac> m_timer;
-
-    std::unique_ptr<ImageTransferSessionVT> m_imageTransferSession;
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp (284294 => 284295)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp	2021-10-16 00:34:25 UTC (rev 284295)
@@ -36,7 +36,7 @@
 #include "AVVideoCaptureSource.h"
 #include "CoreAudioCaptureSource.h"
 #include "DisplayCaptureManagerCocoa.h"
-#include "DisplayCaptureSourceMac.h"
+#include "DisplayCaptureSourceCocoa.h"
 #include "Logging.h"
 #include "MediaStreamPrivate.h"
 #include <wtf/MainThread.h>
@@ -59,15 +59,7 @@
 public:
     CaptureSourceOrError createDisplayCaptureSource(const CaptureDevice& device, const MediaConstraints* constraints) final
     {
-#if PLATFORM(IOS_FAMILY)
-        UNUSED_PARAM(device);
-        UNUSED_PARAM(constraints);
-#endif
-#if PLATFORM(MAC)
-        return DisplayCaptureSourceMac::create(device, constraints);
-#else
-        return { };
-#endif
+        return DisplayCaptureSourceCocoa::create(device, constraints);
     }
 private:
     CaptureDeviceManager& displayCaptureDeviceManager() { return DisplayCaptureManagerCocoa::singleton(); }

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (284294 => 284295)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2021-10-16 00:34:25 UTC (rev 284295)
@@ -43,7 +43,7 @@
 
 #if PLATFORM(COCOA)
 #include "CoreAudioCaptureSource.h"
-#include "DisplayCaptureSourceMac.h"
+#include "DisplayCaptureSourceCocoa.h"
 #include "MockRealtimeVideoSourceMac.h"
 #endif
 
@@ -115,7 +115,7 @@
 };
 
 #if PLATFORM(MAC)
-class MockDisplayCapturer final : public DisplayCaptureSourceMac::Capturer {
+class MockDisplayCapturer final : public DisplayCaptureSourceCocoa::Capturer {
 public:
     explicit MockDisplayCapturer(const CaptureDevice&);
 
@@ -122,7 +122,7 @@
 private:
     bool start() final;
     void stop() final  { m_source->stop(); }
-    DisplayCaptureSourceMac::DisplayFrameType generateFrame() final;
+    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
     RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor; }
     void commitConfiguration(const RealtimeMediaSourceSettings&) final;
     CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Screen; }
@@ -152,7 +152,7 @@
     m_settings = settings;
 }
 
-DisplayCaptureSourceMac::DisplayFrameType MockDisplayCapturer::generateFrame()
+DisplayCaptureSourceCocoa::DisplayFrameType MockDisplayCapturer::generateFrame()
 {
     if (auto* imageBuffer = m_source->imageBuffer())
         return imageBuffer->copyNativeImage();
@@ -186,7 +186,7 @@
         case CaptureDevice::DeviceType::Screen:
         case CaptureDevice::DeviceType::Window:
 #if PLATFORM(MAC)
-            return DisplayCaptureSourceMac::create(UniqueRef<DisplayCaptureSourceMac::Capturer>(makeUniqueRef<MockDisplayCapturer>(device)), device, constraints);
+            return DisplayCaptureSourceCocoa::create(UniqueRef<DisplayCaptureSourceCocoa::Capturer>(makeUniqueRef<MockDisplayCapturer>(device)), device, constraints);
 #elif USE(GSTREAMER)
             return MockDisplayCaptureSourceGStreamer::create(device, constraints);
 #else

Modified: trunk/Source/WebKit/ChangeLog (284294 => 284295)


--- trunk/Source/WebKit/ChangeLog	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebKit/ChangeLog	2021-10-16 00:34:25 UTC (rev 284295)
@@ -1,3 +1,33 @@
+2021-10-15  Eric Carlson  <[email protected]>
+
+        [iOS] Support getDisplayMedia
+        https://bugs.webkit.org/show_bug.cgi?id=231455
+        <rdar://problem/84044495>
+
+        Reviewed by Youenn Fablet and Jer Noble.
+
+        * UIProcess/Cocoa/MediaPermissionUtilities.mm:
+        (WebKit::alertMessageText): Add text for default screen capture prompt.
+        (WebKit::allowButtonText): Ditto.
+        (WebKit::doNotAllowButtonText): Ditto.
+
+        * UIProcess/Cocoa/UIDelegate.mm:
+        (WebKit::UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest): Call
+        default getDisplayMedia prompt if the delegate doesn't implement the private
+        prompt selector.
+
+        * UIProcess/MediaPermissionUtilities.h:
+        * UIProcess/UserMediaPermissionRequestProxy.cpp:
+        (WebKit::UserMediaPermissionRequestProxy::promptForGetDisplayMedia): New default
+        getDisplayMedia prompt.
+        (WebKit::UserMediaPermissionRequestProxy::promptForGetUserMedia): 
+        (WebKit::UserMediaPermissionRequestProxy::doDefaultAction): Call promptForGetDisplayMedia
+        or promptForGetUserMedia according to the request type.
+        (WebKit::UserMediaPermissionRequestProxy::canPromptForGetDisplayMedia):
+        (WebKit::UserMediaPermissionRequestProxy::prompt): Deleted.
+        * UIProcess/UserMediaPermissionRequestProxy.h:
+        (WebKit::UserMediaPermissionRequestProxy::doDefaultAction): Deleted.
+
 2021-10-15  Jer Noble  <[email protected]>
 
         [iOS] Screen Sharing doesn't switch to AirPlay when <video> enters fullscreen mode

Modified: trunk/Source/WebKit/UIProcess/Cocoa/MediaPermissionUtilities.mm (284294 => 284295)


--- trunk/Source/WebKit/UIProcess/Cocoa/MediaPermissionUtilities.mm	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebKit/UIProcess/Cocoa/MediaPermissionUtilities.mm	2021-10-16 00:34:25 UTC (rev 284295)
@@ -141,6 +141,8 @@
         return [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to use your camera and microphone?", @"Message for user media prompt"), visibleOrigin];
     case MediaPermissionReason::Microphone:
         return [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to use your microphone?", @"Message for user microphone access prompt"), visibleOrigin];
+    case MediaPermissionReason::ScreenCapture:
+        return [NSString stringWithFormat:WEB_UI_NSSTRING(@"Allow “%@” to observe your screen?", @"Message for screen sharing prompt"), visibleOrigin];
     case MediaPermissionReason::DeviceOrientation:
         return [NSString stringWithFormat:WEB_UI_NSSTRING(@"“%@” Would Like to Access Motion and Orientation", @"Message for requesting access to the device motion and orientation"), visibleOrigin];
     case MediaPermissionReason::Geolocation:
@@ -157,6 +159,8 @@
     case MediaPermissionReason::CameraAndMicrophone:
     case MediaPermissionReason::Microphone:
         return WEB_UI_STRING_KEY(@"Allow", "Allow (usermedia)", @"Allow button title in user media prompt");
+    case MediaPermissionReason::ScreenCapture:
+        return WEB_UI_STRING_KEY(@"Allow", "Allow (screensharing)", @"Allow button title in screen sharing prompt");
     case MediaPermissionReason::DeviceOrientation:
         return WEB_UI_STRING_KEY(@"Allow", "Allow (device motion and orientation access)", @"Button title in Device Orientation Permission API prompt");
     case MediaPermissionReason::Geolocation:
@@ -173,6 +177,8 @@
     case MediaPermissionReason::CameraAndMicrophone:
     case MediaPermissionReason::Microphone:
         return WEB_UI_STRING_KEY(@"Don’t Allow", "Don’t Allow (usermedia)", @"Disallow button title in user media prompt");
+    case MediaPermissionReason::ScreenCapture:
+        return WEB_UI_STRING_KEY(@"Don’t Allow", "Don’t Allow (screensharing)", @"Disallow button title in screen sharing prompt");
     case MediaPermissionReason::DeviceOrientation:
         return WEB_UI_STRING_KEY(@"Cancel", "Cancel (device motion and orientation access)", @"Button title in Device Orientation Permission API prompt");
     case MediaPermissionReason::Geolocation:

Modified: trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm (284294 => 284295)


--- trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm	2021-10-16 00:34:25 UTC (rev 284295)
@@ -1117,6 +1117,11 @@
         return;
     }
 
+    if (request.requiresDisplayCapture() && request.canPromptForGetDisplayMedia()) {
+        request.promptForGetDisplayMedia();
+        return;
+    }
+
     // FIXME: Provide a specific delegate for display capture.
     if (!request.requiresDisplayCapture() && respondsToRequestMediaCapturePermission) {
         auto checker = CompletionHandlerCallChecker::create(delegate, @selector(webView:requestMediaCapturePermissionForOrigin:initiatedByFrame:type:decisionHandler:));
@@ -1127,7 +1132,7 @@
 
             switch (decision) {
             case WKPermissionDecisionPrompt:
-                protectedRequest->prompt();
+                protectedRequest->promptForGetUserMedia();
                 break;
             case WKPermissionDecisionGrant: {
                 const String& videoDeviceUID = protectedRequest->requiresVideoCapture() ? protectedRequest->videoDeviceUIDs().first() : String();

Modified: trunk/Source/WebKit/UIProcess/MediaPermissionUtilities.h (284294 => 284295)


--- trunk/Source/WebKit/UIProcess/MediaPermissionUtilities.h	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebKit/UIProcess/MediaPermissionUtilities.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -54,7 +54,8 @@
     Microphone,
     DeviceOrientation,
     Geolocation,
-    SpeechRecognition
+    SpeechRecognition,
+    ScreenCapture
 };
 
 #if PLATFORM(COCOA)

Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.cpp (284294 => 284295)


--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.cpp	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.cpp	2021-10-16 00:34:25 UTC (rev 284295)
@@ -140,17 +140,29 @@
     return values[static_cast<size_t>(enumerationValue)];
 }
 
-void UserMediaPermissionRequestProxy::prompt()
+void UserMediaPermissionRequestProxy::promptForGetDisplayMedia()
 {
 #if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
-    ASSERT(m_manager);
-    if (!m_manager) {
+    ASSERT(m_manager && canPromptForGetDisplayMedia());
+    if (!m_manager || !canPromptForGetDisplayMedia()) {
         deny(UserMediaAccessDenialReason::PermissionDenied);
         return;
     }
 
-    if (requiresDisplayCapture()) {
-        // FIXME: Implement getDisplayMedia prompt, for now deny.
+    alertForPermission(m_manager->page(), MediaPermissionReason::ScreenCapture, topLevelDocumentSecurityOrigin().data(), [this, protectedThis = Ref { *this }](bool granted) {
+        if (!granted)
+            deny(UserMediaAccessDenialReason::PermissionDenied);
+        else
+            allow();
+    });
+#endif
+}
+
+void UserMediaPermissionRequestProxy::promptForGetUserMedia()
+{
+#if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
+    ASSERT(m_manager);
+    if (!m_manager) {
         deny(UserMediaAccessDenialReason::PermissionDenied);
         return;
     }
@@ -158,6 +170,7 @@
     MediaPermissionReason reason = MediaPermissionReason::Camera;
     if (requiresAudioCapture())
         reason = requiresVideoCapture() ? MediaPermissionReason::CameraAndMicrophone : MediaPermissionReason::Microphone;
+
     alertForPermission(m_manager->page(), reason, topLevelDocumentSecurityOrigin().data(), [this, protectedThis = Ref { *this }](bool granted) {
         if (!granted)
             deny(UserMediaAccessDenialReason::PermissionDenied);
@@ -164,9 +177,33 @@
         else
             allow();
     });
+#endif
+}
+
+void UserMediaPermissionRequestProxy::doDefaultAction()
+{
+#if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
+    if (requiresDisplayCapture()) {
+        if (!canPromptForGetDisplayMedia()) {
+            deny(UserMediaAccessDenialReason::PermissionDenied);
+            return;
+        }
+
+        promptForGetDisplayMedia();
+    } else
+        promptForGetUserMedia();
 #else
     deny();
 #endif
 }
 
+bool UserMediaPermissionRequestProxy::canPromptForGetDisplayMedia()
+{
+#if ENABLE(MEDIA_STREAM) && PLATFORM(IOS)
+    return true;
+#else
+    return false;
+#endif
+}
+
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h (284294 => 284295)


--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h	2021-10-16 00:00:09 UTC (rev 284294)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h	2021-10-16 00:34:25 UTC (rev 284295)
@@ -45,8 +45,10 @@
 
     void allow(const String& audioDeviceUID, const String& videoDeviceUID);
     void allow();
-    void prompt();
-    void doDefaultAction() { prompt(); }
+    void promptForGetUserMedia();
+    void promptForGetDisplayMedia();
+    bool canPromptForGetDisplayMedia();
+    void doDefaultAction();
     enum class UserMediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, OtherFailure };
     void deny(UserMediaAccessDenialReason = UserMediaAccessDenialReason::UserMediaDisabled);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to