Title: [288894] trunk
Revision
288894
Author
[email protected]
Date
2022-02-01 10:34:18 -0800 (Tue, 01 Feb 2022)

Log Message

[macOS] Expose screen and window capture state to WKWebView
https://bugs.webkit.org/show_bug.cgi?id=235838
<rdar://problem/88207924>

Reviewed by Youenn Fablet.

Source/WebCore:

Updated GetDisplayMediaWindowAndScreen API test.

* Modules/mediastream/MediaDevices.cpp:
(WebCore::toMediaDeviceInfoKind): Add SystemAudio.

* Modules/mediastream/MediaStreamTrack.cpp:
(WebCore::sourceCaptureState): Differentiate state of window and screen capture tracks.
(WebCore::MediaStreamTrack::updateToPageMutedState): New.
(WebCore::trackTypeForMediaProducerCaptureKind):
(WebCore::trackMatchesKind): Deleted.
* Modules/mediastream/MediaStreamTrack.h:

* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::mediaStreamDidFail): Include new source types.

* Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
(WebCore::LibWebRTCMediaEndpoint::addTrack): Ditto.
(WebCore::LibWebRTCMediaEndpoint::createSourceAndRTCTrack):

* page/MediaProducer.h:

* platform/mediarecorder/MediaRecorderPrivate.cpp:
(WebCore::MediaRecorderPrivate::selectTracks): Include new track types.

* platform/mediastream/CaptureDevice.h:
* platform/mediastream/RealtimeMediaSource.h:
* platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp:
(WebCore::DisplayCaptureSourceCocoa::create): Ditto.

* platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp:
(WebCore::DisplayCaptureManagerCocoa::captureDeviceWithPersistentID): Ditto.

* platform/mediastream/mac/ScreenCaptureKitCaptureSource.mm:
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
* testing/Internals.cpp:
(WebCore::Internals::pageMediaState): Update with new and changed type names.
(WebCore::Internals::stopObservingRealtimeMediaSource): Include new track types.
(WebCore::Internals::observeMediaStreamTrack): Ditto.

Source/WebKit:

* GPUProcess/GPUConnectionToWebProcess.cpp:
* UIProcess/API/C/WKPage.cpp:
(WKPageGetMediaState): Rename *DisplayCaptureDevice to *ScreenCaptureDevice. Add enums
for window capture.

* UIProcess/API/C/WKPagePrivate.h:
* UIProcess/API/Cocoa/WKWebView.h: Drive by: fix typo in header doc.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView setMicrophoneCaptureState:completionHandler:]): MediaProducerMediaCaptureKind::Audio
was renamed to MediaProducerMediaCaptureKind::Microphone.
(-[WKWebView setCameraCaptureState:completionHandler:]): MediaProducerMediaCaptureKind::Video
was renamed to MediaProducerMediaCaptureKind::Camera.
(-[WKWebView _stopMediaCapture]): stopMediaCapture takes an optionSet.
(-[WKWebView _displayCaptureSurfaces]): Expose the type(s) of displays surfaces
being captured.
(-[WKWebView _displayCaptureState]): Expose the display capture state.
(-[WKWebView _systemAudioCaptureState]): Expose the system audio capture state.
(-[WKWebView _setDisplayCaptureState:completionHandler:]): Change the display
capture state.
(-[WKWebView _setSystemAudioCaptureState:completionHandler:]): Change the system
audio capture state.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:

* UIProcess/API/glib/WebKitWebView.cpp:
(webkitWebViewMediaCaptureStateDidChange): MediaProducer::AudioCaptureMask ->
MediaProducer::MicrophoneCaptureMask.
(webkitWebViewConfigureMediaCapture): Update for MediaProducerMediaCaptureKind changes.
(webkit_web_view_set_microphone_capture_state): Ditto.
(webkit_web_view_set_camera_capture_state): MediaProducerMediaCaptureKind::Video ->
MediaProducerMediaCaptureKind::Camera
(webkit_web_view_set_display_capture_state): Ditto.
(webkit_web_view_get_display_capture_state): MediaState::HasActiveDisplayCaptureDevice ->
MediaState::HasActiveScreenCaptureDevice. MediaState::HasMutedDisplayCaptureDevice ->
MediaState::HasMutedScreenCaptureDevice

* UIProcess/Cocoa/PageClientImplCocoa.h:
* UIProcess/Cocoa/PageClientImplCocoa.mm:
(WebKit::PageClientImplCocoa::displayCaptureWillChange): KVO support.
(WebKit::PageClientImplCocoa::displayCaptureSurfacesWillChange): Ditto.
(WebKit::PageClientImplCocoa::systemAudioCaptureWillChange): Ditto.
(WebKit::PageClientImplCocoa::displayCaptureChanged): Ditto.
(WebKit::PageClientImplCocoa::displayCaptureSurfacesChanged): Ditto.
(WebKit::PageClientImplCocoa::systemAudioCaptureChanged): Ditto.

* UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::SourceProxy): Support new types.
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::~SourceProxy): Ditto.
(WebKit::UserMediaCaptureManagerProxy::createMediaSourceForCaptureDeviceWithConstraints): Ditto.

* UIProcess/PageClient.h:
(WebKit::PageClient::displayCaptureWillChange):
(WebKit::PageClient::displayCaptureSurfacesWillChange):
(WebKit::PageClient::systemAudioCaptureWillChange):
(WebKit::PageClient::displayCaptureChanged):
(WebKit::PageClient::displayCaptureSurfacesChanged):
(WebKit::PageClient::systemAudioCaptureChanged):

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::UserMediaPermissionRequestManagerProxy::~UserMediaPermissionRequestManagerProxy):
MediaProducerMediaCaptureKind::AudioVideo -> MediaProducerMediaCaptureKind::EveryKind.
(WebKit::UserMediaPermissionRequestManagerProxy::stopCapture): Ditto.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::updateReportedMediaCaptureState): Deal with new types.
* UIProcess/WebPageProxy.h:

* WebProcess/WebProcess.cpp:
(WebKit::checkDocumentsCaptureStateConsistency):

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/xcshareddata/xcschemes/TestWebKitAPI.xcscheme:
* TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMediaWindowAndScreen.mm:
(-[DisplayCaptureObserver observeValueForKeyPath:ofObject:change:context:]):
(-[DisplayCaptureObserver waitForDisplayCaptureState:]):
(-[DisplayCaptureObserver waitForDisplayCaptureSurfaces:]):
(TestWebKitAPI::TEST):
* TestWebKitAPI/glib/TestExpectations.json: Skip /webkit/WebKitWebView/display-usermedia-permission-request
until someone has a chance to figure out why it times out.

LayoutTests:

* fast/mediastream/get-display-media-muted.html: Update for new and renamed states.
* fast/mediastream/media-stream-page-muted-expected.txt: Ditto.
* fast/mediastream/media-stream-page-muted.html: Ditto.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (288893 => 288894)


--- trunk/LayoutTests/ChangeLog	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/LayoutTests/ChangeLog	2022-02-01 18:34:18 UTC (rev 288894)
@@ -1,3 +1,15 @@
+2022-02-01  Eric Carlson  <[email protected]>
+
+        [macOS] Expose screen and window capture state to WKWebView
+        https://bugs.webkit.org/show_bug.cgi?id=235838
+        <rdar://problem/88207924>
+
+        Reviewed by Youenn Fablet.
+
+        * fast/mediastream/get-display-media-muted.html: Update for new and renamed states.
+        * fast/mediastream/media-stream-page-muted-expected.txt: Ditto.
+        * fast/mediastream/media-stream-page-muted.html: Ditto.
+
 2022-02-01  Gabriel Nava Marino  <[email protected]>
 
         null ptr deref in LayoutIntegrationLineLayout LineLayout::adjustForPagination and LineLayout::visualOverflowBoundingBoxRectFor

Modified: trunk/LayoutTests/fast/mediastream/get-display-media-muted.html (288893 => 288894)


--- trunk/LayoutTests/fast/mediastream/get-display-media-muted.html	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/LayoutTests/fast/mediastream/get-display-media-muted.html	2022-02-01 18:34:18 UTC (rev 288894)
@@ -41,7 +41,7 @@
             let stream = await callGetDisplayMedia({ video: true });
             let pageMediaState = internals.pageMediaState();
 
-            assert_false(pageMediaState.includes('HasMutedDisplayCaptureDevice'), 'page state does not include HasMutedDisplayCaptureDevice');
+            assert_false(pageMediaState.includes('HasMutedScreenCaptureDevice'), 'page state does not include HasMutedScreenCaptureDevice');
             assert_false(pageMediaState.includes('HasMutedVideoCaptureDevice'), 'page state does not include HasMutedVideoCaptureDevice');
             assert_false(pageMediaState.includes('HasMutedAudioCaptureDevice'), 'page state does not include HasMutedAudioCaptureDevice');
 
@@ -58,14 +58,14 @@
                         assert_unreached(`Page state did not change from ${pageMediaState}`);
 
                     pageMediaState = internals.pageMediaState();
-                    assert_false(pageMediaState.includes('HasMutedDisplayCaptureDevice'), 'page state does not include HasMutedDisplayCaptureDevice');
-                    assert_true(pageMediaState.includes('HasActiveDisplayCaptureDevice'), 'page state includes HasActiveDisplayCaptureDevice');
+                    assert_false(pageMediaState.includes('HasMutedScreenCaptureDevice'), 'page state does not include HasMutedScreenCaptureDevice');
+                    assert_true(pageMediaState.includes('HasActiveScreenCaptureDevice'), 'page state includes HasActiveScreenCaptureDevice');
                     resolve()
                 }
 
                 pageMediaState = internals.pageMediaState();
-                assert_true(pageMediaState.includes('HasMutedDisplayCaptureDevice'), 'page state includes HasMutedDisplayCaptureDevice');
-                assert_false(pageMediaState.includes('HasActiveDisplayCaptureDevice'), 'page state does not include HasActiveDisplayCaptureDevice');
+                assert_true(pageMediaState.includes('HasMutedScreenCaptureDevice'), 'page state includes HasMutedScreenCaptureDevice');
+                assert_false(pageMediaState.includes('HasActiveScreenCaptureDevice'), 'page state does not include HasActiveScreenCaptureDevice');
                 internals.setMediaStreamTrackMuted(track, false)
             }
 

Modified: trunk/LayoutTests/fast/mediastream/media-stream-page-muted-expected.txt (288893 => 288894)


--- trunk/LayoutTests/fast/mediastream/media-stream-page-muted-expected.txt	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/LayoutTests/fast/mediastream/media-stream-page-muted-expected.txt	2022-02-01 18:34:18 UTC (rev 288894)
@@ -16,8 +16,8 @@
 PASS screenCaptureTrack.muted is true
 PASS microphoneCaptureTrack.muted is false
 PASS cameraCaptureTrack.muted is false
-PASS window.internals.pageMediaState().includes(HasMutedDisplayCaptureDevice) became true
-PASS window.internals.pageMediaState().includes(HasActiveDisplayCaptureDevice) became false
+PASS window.internals.pageMediaState().includes(HasMutedScreenCaptureDevice) became true
+PASS window.internals.pageMediaState().includes(HasActiveScreenCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasActiveAudioCaptureDevice) became true
 PASS window.internals.pageMediaState().includes(HasMutedAudioCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasActiveAudioCaptureDevice) became true
@@ -29,8 +29,8 @@
 PASS screenCaptureTrack.muted is true
 PASS microphoneCaptureTrack.muted is true
 PASS cameraCaptureTrack.muted is true
-PASS window.internals.pageMediaState().includes(HasMutedDisplayCaptureDevice) became true
-PASS window.internals.pageMediaState().includes(HasActiveDisplayCaptureDevice) became false
+PASS window.internals.pageMediaState().includes(HasMutedScreenCaptureDevice) became true
+PASS window.internals.pageMediaState().includes(HasActiveScreenCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasMutedAudioCaptureDevice) became true
 PASS window.internals.pageMediaState().includes(HasActiveAudioCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasMutedVideoCaptureDevice) became true
@@ -42,8 +42,8 @@
 PASS screenCaptureTrack.muted is true
 PASS microphoneCaptureTrack.muted is false
 PASS cameraCaptureTrack.muted is false
-PASS window.internals.pageMediaState().includes(HasMutedDisplayCaptureDevice) became true
-PASS window.internals.pageMediaState().includes(HasActiveDisplayCaptureDevice) became false
+PASS window.internals.pageMediaState().includes(HasMutedScreenCaptureDevice) became true
+PASS window.internals.pageMediaState().includes(HasActiveScreenCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasActiveAudioCaptureDevice) became true
 PASS window.internals.pageMediaState().includes(HasMutedAudioCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasActiveAudioCaptureDevice) became true
@@ -54,8 +54,8 @@
 PASS screenCaptureTrack.muted is false
 PASS microphoneCaptureTrack.muted is false
 PASS cameraCaptureTrack.muted is false
-PASS window.internals.pageMediaState().includes(HasActiveDisplayCaptureDevice) became true
-PASS window.internals.pageMediaState().includes(HasMutedDisplayCaptureDevice) became false
+PASS window.internals.pageMediaState().includes(HasActiveScreenCaptureDevice) became true
+PASS window.internals.pageMediaState().includes(HasMutedScreenCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasActiveAudioCaptureDevice) became true
 PASS window.internals.pageMediaState().includes(HasMutedAudioCaptureDevice) became false
 PASS window.internals.pageMediaState().includes(HasActiveAudioCaptureDevice) became true

Modified: trunk/LayoutTests/fast/mediastream/media-stream-page-muted.html (288893 => 288894)


--- trunk/LayoutTests/fast/mediastream/media-stream-page-muted.html	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/LayoutTests/fast/mediastream/media-stream-page-muted.html	2022-02-01 18:34:18 UTC (rev 288894)
@@ -114,7 +114,7 @@
             shouldBeFalse("microphoneCaptureTrack.muted");
             shouldBeFalse("cameraCaptureTrack.muted");
 
-            await checkPageState("HasMutedDisplayCaptureDevice", "HasActiveDisplayCaptureDevice");
+            await checkPageState("HasMutedScreenCaptureDevice", "HasActiveScreenCaptureDevice");
             await checkPageState("HasActiveAudioCaptureDevice", "HasMutedAudioCaptureDevice");
             await checkPageState("HasActiveAudioCaptureDevice", "HasMutedAudioCaptureDevice");
         }
@@ -133,7 +133,7 @@
             shouldBeTrue("microphoneCaptureTrack.muted");
             shouldBeTrue("cameraCaptureTrack.muted");
 
-            await checkPageState("HasMutedDisplayCaptureDevice", "HasActiveDisplayCaptureDevice");
+            await checkPageState("HasMutedScreenCaptureDevice", "HasActiveScreenCaptureDevice");
             await checkPageState("HasMutedAudioCaptureDevice", "HasActiveAudioCaptureDevice");
             await checkPageState("HasMutedVideoCaptureDevice", "HasActiveVideoCaptureDevice");
         }
@@ -152,7 +152,7 @@
             shouldBeFalse("microphoneCaptureTrack.muted");
             shouldBeFalse("cameraCaptureTrack.muted");
 
-            await checkPageState("HasMutedDisplayCaptureDevice", "HasActiveDisplayCaptureDevice");
+            await checkPageState("HasMutedScreenCaptureDevice", "HasActiveScreenCaptureDevice");
             await checkPageState("HasActiveAudioCaptureDevice", "HasMutedAudioCaptureDevice");
             await checkPageState("HasActiveAudioCaptureDevice", "HasMutedAudioCaptureDevice");
         }
@@ -170,7 +170,7 @@
             shouldBeFalse("microphoneCaptureTrack.muted");
             shouldBeFalse("cameraCaptureTrack.muted");
 
-            await checkPageState("HasActiveDisplayCaptureDevice", "HasMutedDisplayCaptureDevice");
+            await checkPageState("HasActiveScreenCaptureDevice", "HasMutedScreenCaptureDevice");
             await checkPageState("HasActiveAudioCaptureDevice", "HasMutedAudioCaptureDevice");
             await checkPageState("HasActiveAudioCaptureDevice", "HasMutedAudioCaptureDevice");
         }

Modified: trunk/Source/WebCore/ChangeLog (288893 => 288894)


--- trunk/Source/WebCore/ChangeLog	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/ChangeLog	2022-02-01 18:34:18 UTC (rev 288894)
@@ -1,3 +1,50 @@
+2022-02-01  Eric Carlson  <[email protected]>
+
+        [macOS] Expose screen and window capture state to WKWebView
+        https://bugs.webkit.org/show_bug.cgi?id=235838
+        <rdar://problem/88207924>
+
+        Reviewed by Youenn Fablet.
+
+        Updated GetDisplayMediaWindowAndScreen API test.
+
+        * Modules/mediastream/MediaDevices.cpp:
+        (WebCore::toMediaDeviceInfoKind): Add SystemAudio.
+
+        * Modules/mediastream/MediaStreamTrack.cpp:
+        (WebCore::sourceCaptureState): Differentiate state of window and screen capture tracks.
+        (WebCore::MediaStreamTrack::updateToPageMutedState): New.
+        (WebCore::trackTypeForMediaProducerCaptureKind): 
+        (WebCore::trackMatchesKind): Deleted.
+        * Modules/mediastream/MediaStreamTrack.h:
+
+        * Modules/mediastream/UserMediaRequest.cpp:
+        (WebCore::UserMediaRequest::mediaStreamDidFail): Include new source types.
+
+        * Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp:
+        (WebCore::LibWebRTCMediaEndpoint::addTrack): Ditto.
+        (WebCore::LibWebRTCMediaEndpoint::createSourceAndRTCTrack):
+
+        * page/MediaProducer.h:
+
+        * platform/mediarecorder/MediaRecorderPrivate.cpp:
+        (WebCore::MediaRecorderPrivate::selectTracks): Include new track types.
+
+        * platform/mediastream/CaptureDevice.h:
+        * platform/mediastream/RealtimeMediaSource.h:
+        * platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp:
+        (WebCore::DisplayCaptureSourceCocoa::create): Ditto.
+
+        * platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp:
+        (WebCore::DisplayCaptureManagerCocoa::captureDeviceWithPersistentID): Ditto.
+
+        * platform/mediastream/mac/ScreenCaptureKitCaptureSource.mm:
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        * testing/Internals.cpp:
+        (WebCore::Internals::pageMediaState): Update with new and changed type names.
+        (WebCore::Internals::stopObservingRealtimeMediaSource): Include new track types.
+        (WebCore::Internals::observeMediaStreamTrack): Ditto.
+
 2022-02-01  Gabriel Nava Marino  <[email protected]>
 
         null ptr deref in LayoutIntegrationLineLayout LineLayout::adjustForPagination and LineLayout::visualOverflowBoundingBoxRectFor

Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp (288893 => 288894)


--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -281,6 +281,7 @@
     case CaptureDevice::DeviceType::Screen:
     case CaptureDevice::DeviceType::Window:
         return MediaDeviceInfo::Kind::Videoinput;
+    case CaptureDevice::DeviceType::SystemAudio:
     case CaptureDevice::DeviceType::Unknown:
         ASSERT_NOT_REACHED();
     }

Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp (288893 => 288894)


--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -436,14 +436,22 @@
             return MediaProducerMediaState::HasActiveVideoCaptureDevice;
         break;
     case CaptureDevice::DeviceType::Screen:
+        if (source.muted())
+            return MediaProducerMediaState::HasMutedScreenCaptureDevice;
+        if (source.interrupted())
+            return MediaProducerMediaState::HasInterruptedScreenCaptureDevice;
+        if (source.isProducingData())
+            return MediaProducerMediaState::HasActiveScreenCaptureDevice;
+        break;
     case CaptureDevice::DeviceType::Window:
         if (source.muted())
-            return MediaProducerMediaState::HasMutedDisplayCaptureDevice;
+            return MediaProducerMediaState::HasMutedWindowCaptureDevice;
         if (source.interrupted())
-            return MediaProducerMediaState::HasInterruptedDisplayCaptureDevice;
+            return MediaProducerMediaState::HasInterruptedWindowCaptureDevice;
         if (source.isProducingData())
-            return MediaProducerMediaState::HasActiveDisplayCaptureDevice;
+            return MediaProducerMediaState::HasActiveWindowCaptureDevice;
         break;
+    case CaptureDevice::DeviceType::SystemAudio:
     case CaptureDevice::DeviceType::Speaker:
     case CaptureDevice::DeviceType::Unknown:
         ASSERT_NOT_REACHED();
@@ -521,6 +529,7 @@
     case CaptureDevice::DeviceType::Window:
         m_private->setMuted(page->mutedState().contains(MediaProducerMutedState::ScreenCaptureIsMuted));
         break;
+    case CaptureDevice::DeviceType::SystemAudio:
     case CaptureDevice::DeviceType::Speaker:
     case CaptureDevice::DeviceType::Unknown:
         ASSERT_NOT_REACHED();
@@ -528,15 +537,20 @@
     }
 }
 
-static inline bool trackMatchesKind(RealtimeMediaSource::Type type, MediaProducerMediaCaptureKind kind)
+static MediaProducerMediaCaptureKind trackTypeForMediaProducerCaptureKind(RealtimeMediaSource::Type type)
 {
-    switch (kind) {
-    case MediaProducerMediaCaptureKind::Audio:
-        return type == RealtimeMediaSource::Type::Audio;
-    case MediaProducerMediaCaptureKind::AudioVideo:
-        return type != RealtimeMediaSource::Type::None;
-    case MediaProducerMediaCaptureKind::Video:
-        return type == RealtimeMediaSource::Type::Video;
+    switch (type) {
+    case RealtimeMediaSource::Type::Audio:
+        return MediaProducerMediaCaptureKind::Microphone;
+    case RealtimeMediaSource::Type::SystemAudio:
+        return MediaProducerMediaCaptureKind::SystemAudio;
+    case RealtimeMediaSource::Type::Video:
+        return MediaProducerMediaCaptureKind::Camera;
+    case RealtimeMediaSource::Type::Screen:
+    case RealtimeMediaSource::Type::Window:
+        return MediaProducerMediaCaptureKind::Display;
+    case RealtimeMediaSource::Type::None:
+        break;
     }
     RELEASE_ASSERT_NOT_REACHED();
 }
@@ -545,8 +559,10 @@
 {
     bool didEndCapture = false;
     for (auto* captureTrack : allCaptureTracks()) {
-        if (captureTrack->document() != &document || !trackMatchesKind(captureTrack->privateTrack().type(), kind))
+        if (captureTrack->document() != &document)
             continue;
+        if (kind != MediaProducerMediaCaptureKind::EveryKind && kind != trackTypeForMediaProducerCaptureKind(captureTrack->privateTrack().type()))
+            continue;
         captureTrack->stopTrack(MediaStreamTrack::StopMode::PostEvent);
         didEndCapture = true;
     }

Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp (288893 => 288894)


--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -271,6 +271,15 @@
     case RealtimeMediaSource::Type::Video:
         typeDescription = "video";
         break;
+    case RealtimeMediaSource::Type::Screen:
+        typeDescription = "screen";
+        break;
+    case RealtimeMediaSource::Type::Window:
+        typeDescription = "window";
+        break;
+    case RealtimeMediaSource::Type::SystemAudio:
+        typeDescription = "system audio";
+        break;
     case RealtimeMediaSource::Type::None:
         typeDescription = "unknown";
         break;

Modified: trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp (288893 => 288894)


--- trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCMediaEndpoint.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -204,6 +204,9 @@
         source = WTFMove(videoSource);
         break;
     }
+    case RealtimeMediaSource::Type::Screen:
+    case RealtimeMediaSource::Type::Window:
+    case RealtimeMediaSource::Type::SystemAudio:
     case RealtimeMediaSource::Type::None:
         ASSERT_NOT_REACHED();
         return false;
@@ -416,6 +419,7 @@
     case RealtimeMediaSource::Type::None:
         ASSERT_NOT_REACHED();
         break;
+    case RealtimeMediaSource::Type::SystemAudio:
     case RealtimeMediaSource::Type::Audio: {
         auto audioSource = RealtimeOutgoingAudioSource::create(track.privateTrack());
         rtcTrack = m_peerConnectionFactory->CreateAudioTrack(track.id().utf8().data(), audioSource.ptr());
@@ -422,6 +426,8 @@
         source = WTFMove(audioSource);
         break;
     }
+    case RealtimeMediaSource::Type::Screen:
+    case RealtimeMediaSource::Type::Window:
     case RealtimeMediaSource::Type::Video: {
         auto videoSource = RealtimeOutgoingVideoSource::create(track.privateTrack());
         rtcTrack = m_peerConnectionFactory->CreateVideoTrack(track.id().utf8().data(), videoSource.ptr());

Modified: trunk/Source/WebCore/PAL/pal/mac/ScreenCaptureKitSoftLink.h (288893 => 288894)


--- trunk/Source/WebCore/PAL/pal/mac/ScreenCaptureKitSoftLink.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/PAL/pal/mac/ScreenCaptureKitSoftLink.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -37,7 +37,7 @@
 SOFT_LINK_CLASS_FOR_HEADER_WITH_AVAILABILITY(PAL, SCStreamConfiguration, API_AVAILABLE(macos(12.3)))
 SOFT_LINK_CLASS_FOR_HEADER_WITH_AVAILABILITY(PAL, SCStream, API_AVAILABLE(macos(12.3)))
 
-SOFT_LINK_CONSTANT_MAY_FAIL_FOR_HEADER(PAL, ScreenCaptureKit, SCStreamFrameInfoStatusKey, NSString *)
+SOFT_LINK_CONSTANT_FOR_HEADER(PAL, ScreenCaptureKit, SCStreamFrameInfoStatusKey, NSString *)
 #define SCStreamFrameInfoStatusKey get_ScreenCaptureKit_SCStreamFrameInfoStatusKey()
 
 #endif // HAVE(SCREEN_CAPTURE_KIT)

Modified: trunk/Source/WebCore/PAL/pal/mac/ScreenCaptureKitSoftLink.mm (288893 => 288894)


--- trunk/Source/WebCore/PAL/pal/mac/ScreenCaptureKitSoftLink.mm	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/PAL/pal/mac/ScreenCaptureKitSoftLink.mm	2022-02-01 18:34:18 UTC (rev 288894)
@@ -37,6 +37,6 @@
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT_AND_AVAILABILITY(PAL, ScreenCaptureKit, SCStreamConfiguration, PAL_EXPORT, API_AVAILABLE(macos(12.3)))
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT_AND_AVAILABILITY(PAL, ScreenCaptureKit, SCStream, PAL_EXPORT, API_AVAILABLE(macos(12.3)))
 
-SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE_WITH_EXPORT(PAL, ScreenCaptureKit, SCStreamFrameInfoStatusKey, NSString *, PAL_EXPORT)
+SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, ScreenCaptureKit, SCStreamFrameInfoStatusKey, NSString *, PAL_EXPORT)
 
 #endif // PLATFORM(MAC)

Modified: trunk/Source/WebCore/page/MediaProducer.h (288893 => 288894)


--- trunk/Source/WebCore/page/MediaProducer.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/page/MediaProducer.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -50,16 +50,24 @@
     HasInterruptedAudioCaptureDevice = 1 << 15,
     HasInterruptedVideoCaptureDevice = 1 << 16,
     HasUserInteractedWithMediaElement = 1 << 17,
-    HasActiveDisplayCaptureDevice = 1 << 18,
-    HasMutedDisplayCaptureDevice = 1 << 19,
-    HasInterruptedDisplayCaptureDevice = 1 << 20,
+    HasActiveScreenCaptureDevice = 1 << 18,
+    HasMutedScreenCaptureDevice = 1 << 19,
+    HasInterruptedScreenCaptureDevice = 1 << 20,
+    HasActiveWindowCaptureDevice = 1 << 21,
+    HasMutedWindowCaptureDevice = 1 << 22,
+    HasInterruptedWindowCaptureDevice = 1 << 23,
+    HasActiveSystemAudioCaptureDevice = 1 << 24,
+    HasMutedSystemAudioCaptureDevice = 1 << 25,
+    HasInterruptedSystemAudioCaptureDevice = 1 << 26,
 };
 using MediaProducerMediaStateFlags = OptionSet<MediaProducerMediaState>;
 
 enum class MediaProducerMediaCaptureKind : uint8_t {
-    Audio,
-    Video,
-    AudioVideo
+    Microphone,
+    Camera,
+    Display,
+    SystemAudio,
+    EveryKind,
 };
 
 enum class MediaProducerMutedState : uint8_t {
@@ -67,6 +75,8 @@
     AudioCaptureIsMuted = 1 << 1,
     VideoCaptureIsMuted = 1 << 2,
     ScreenCaptureIsMuted = 1 << 3,
+    WindowCaptureIsMuted = 1 << 4,
+    SystemAudioCaptureIsMuted = 1 << 4,
 };
 using MediaProducerMutedStateFlags = OptionSet<MediaProducerMutedState>;
 
@@ -78,19 +88,46 @@
     using MutedStateFlags = MediaProducerMutedStateFlags;
 
     static constexpr MediaStateFlags IsNotPlaying = { };
-    static constexpr MediaStateFlags AudioCaptureMask = { MediaState::HasActiveAudioCaptureDevice, MediaState::HasMutedAudioCaptureDevice, MediaState::HasInterruptedAudioCaptureDevice };
+    static constexpr MediaStateFlags MicrophoneCaptureMask = { MediaState::HasActiveAudioCaptureDevice, MediaState::HasMutedAudioCaptureDevice, MediaState::HasInterruptedAudioCaptureDevice };
     static constexpr MediaStateFlags VideoCaptureMask = { MediaState::HasActiveVideoCaptureDevice, MediaState::HasMutedVideoCaptureDevice, MediaState::HasInterruptedVideoCaptureDevice };
-    static constexpr MediaStateFlags DisplayCaptureMask = { MediaState::HasActiveDisplayCaptureDevice, MediaState::HasMutedDisplayCaptureDevice, MediaState::HasInterruptedDisplayCaptureDevice };
-    static constexpr MediaStateFlags ActiveCaptureMask = { MediaState::HasActiveAudioCaptureDevice, MediaState::HasActiveVideoCaptureDevice, MediaState::HasActiveDisplayCaptureDevice };
-    static constexpr MediaStateFlags MutedCaptureMask = { MediaState::HasMutedAudioCaptureDevice, MediaState::HasMutedVideoCaptureDevice, MediaState::HasMutedDisplayCaptureDevice };
-    static constexpr MediaStateFlags MediaCaptureMask = { MediaState::HasActiveAudioCaptureDevice, MediaState::HasMutedAudioCaptureDevice, MediaState::HasInterruptedAudioCaptureDevice, MediaState::HasActiveVideoCaptureDevice, MediaState::HasMutedVideoCaptureDevice, MediaState::HasInterruptedVideoCaptureDevice, MediaState::HasActiveDisplayCaptureDevice, MediaState::HasMutedDisplayCaptureDevice, MediaState::HasInterruptedDisplayCaptureDevice };
 
+    static constexpr MediaStateFlags ScreenCaptureMask = { MediaState::HasActiveScreenCaptureDevice, MediaState::HasMutedScreenCaptureDevice, MediaState::HasInterruptedScreenCaptureDevice };
+    static constexpr MediaStateFlags WindowCaptureMask = { MediaState::HasActiveWindowCaptureDevice, MediaState::HasMutedWindowCaptureDevice, MediaState::HasInterruptedWindowCaptureDevice };
+    static constexpr MediaStateFlags ActiveDisplayCaptureMask = { MediaState::HasActiveScreenCaptureDevice, MediaState::HasActiveWindowCaptureDevice };
+    static constexpr MediaStateFlags MutedDisplayCaptureMask = { MediaState::HasMutedScreenCaptureDevice, MediaState::HasMutedWindowCaptureDevice };
+    static constexpr MediaStateFlags DisplayCaptureMask = { ActiveDisplayCaptureMask | MutedDisplayCaptureMask };
+
+    static constexpr MediaStateFlags SystemAudioCaptureMask = { MediaState::HasActiveSystemAudioCaptureDevice, MediaState::HasMutedSystemAudioCaptureDevice, MediaState::HasInterruptedSystemAudioCaptureDevice };
+
+    static constexpr MediaStateFlags ActiveCaptureMask = { MediaState::HasActiveAudioCaptureDevice, MediaState::HasActiveVideoCaptureDevice, MediaState::HasActiveScreenCaptureDevice, MediaState::HasActiveWindowCaptureDevice, MediaState::HasActiveSystemAudioCaptureDevice };
+    static constexpr MediaStateFlags MutedCaptureMask = { MediaState::HasMutedAudioCaptureDevice, MediaState::HasMutedVideoCaptureDevice, MediaState::HasMutedScreenCaptureDevice, MediaState::HasMutedWindowCaptureDevice, MediaState::HasMutedSystemAudioCaptureDevice };
+
+    static constexpr MediaStateFlags MediaCaptureMask = {
+        MediaState::HasActiveAudioCaptureDevice,
+        MediaState::HasMutedAudioCaptureDevice,
+        MediaState::HasInterruptedAudioCaptureDevice,
+        MediaState::HasActiveVideoCaptureDevice,
+        MediaState::HasMutedVideoCaptureDevice,
+        MediaState::HasInterruptedVideoCaptureDevice,
+        MediaState::HasActiveScreenCaptureDevice,
+        MediaState::HasMutedScreenCaptureDevice,
+        MediaState::HasInterruptedScreenCaptureDevice,
+        MediaState::HasActiveWindowCaptureDevice,
+        MediaState::HasMutedWindowCaptureDevice,
+        MediaState::HasInterruptedWindowCaptureDevice,
+        MediaState::HasActiveSystemAudioCaptureDevice,
+        MediaState::HasMutedSystemAudioCaptureDevice,
+        MediaState::HasInterruptedSystemAudioCaptureDevice
+    };
+    static constexpr MediaStateFlags IsCapturingAudioMask = { MicrophoneCaptureMask | SystemAudioCaptureMask };
+    static constexpr MediaStateFlags IsCapturingVideoMask = { VideoCaptureMask | DisplayCaptureMask };
+
     static bool isCapturing(MediaStateFlags state) { return state.containsAny(ActiveCaptureMask) || state.containsAny(MutedCaptureMask); }
 
     virtual MediaStateFlags mediaState() const = 0;
 
     static constexpr MutedStateFlags AudioAndVideoCaptureIsMuted = { MutedState::AudioCaptureIsMuted, MutedState::VideoCaptureIsMuted };
-    static constexpr MutedStateFlags MediaStreamCaptureIsMuted = { MutedState::AudioCaptureIsMuted, MutedState::VideoCaptureIsMuted, MutedState::ScreenCaptureIsMuted };
+    static constexpr MutedStateFlags MediaStreamCaptureIsMuted = { MutedState::AudioCaptureIsMuted, MutedState::VideoCaptureIsMuted, MutedState::ScreenCaptureIsMuted, MutedState::WindowCaptureIsMuted, MutedState::SystemAudioCaptureIsMuted };
 
     virtual void pageMutedStateDidChange() = 0;
 
@@ -105,9 +142,11 @@
 template<> struct EnumTraits<WebCore::MediaProducerMediaCaptureKind> {
     using values = EnumValues<
         WebCore::MediaProducerMediaCaptureKind,
-        WebCore::MediaProducerMediaCaptureKind::Audio,
-        WebCore::MediaProducerMediaCaptureKind::Video,
-        WebCore::MediaProducerMediaCaptureKind::AudioVideo
+        WebCore::MediaProducerMediaCaptureKind::Microphone,
+        WebCore::MediaProducerMediaCaptureKind::Camera,
+        WebCore::MediaProducerMediaCaptureKind::Display,
+        WebCore::MediaProducerMediaCaptureKind::SystemAudio,
+        WebCore::MediaProducerMediaCaptureKind::EveryKind
     >;
 };
 
@@ -132,9 +171,15 @@
         WebCore::MediaProducerMediaState::HasInterruptedAudioCaptureDevice,
         WebCore::MediaProducerMediaState::HasInterruptedVideoCaptureDevice,
         WebCore::MediaProducerMediaState::HasUserInteractedWithMediaElement,
-        WebCore::MediaProducerMediaState::HasActiveDisplayCaptureDevice,
-        WebCore::MediaProducerMediaState::HasMutedDisplayCaptureDevice,
-        WebCore::MediaProducerMediaState::HasInterruptedDisplayCaptureDevice
+        WebCore::MediaProducerMediaState::HasActiveScreenCaptureDevice,
+        WebCore::MediaProducerMediaState::HasMutedScreenCaptureDevice,
+        WebCore::MediaProducerMediaState::HasInterruptedScreenCaptureDevice,
+        WebCore::MediaProducerMediaState::HasActiveWindowCaptureDevice,
+        WebCore::MediaProducerMediaState::HasMutedWindowCaptureDevice,
+        WebCore::MediaProducerMediaState::HasInterruptedWindowCaptureDevice,
+        WebCore::MediaProducerMediaState::HasActiveSystemAudioCaptureDevice,
+        WebCore::MediaProducerMediaState::HasMutedSystemAudioCaptureDevice,
+        WebCore::MediaProducerMediaState::HasInterruptedSystemAudioCaptureDevice
     >;
 };
 
@@ -144,7 +189,9 @@
         WebCore::MediaProducerMutedState::AudioIsMuted,
         WebCore::MediaProducerMutedState::AudioCaptureIsMuted,
         WebCore::MediaProducerMutedState::VideoCaptureIsMuted,
-        WebCore::MediaProducerMutedState::ScreenCaptureIsMuted
+        WebCore::MediaProducerMutedState::ScreenCaptureIsMuted,
+        WebCore::MediaProducerMutedState::WindowCaptureIsMuted,
+        WebCore::MediaProducerMutedState::SystemAudioCaptureIsMuted
     >;
 };
 

Modified: trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp (288893 => 288894)


--- trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -44,6 +44,8 @@
         if (track.ended())
             return;
         switch (track.type()) {
+        case RealtimeMediaSource::Type::Screen:
+        case RealtimeMediaSource::Type::Window:
         case RealtimeMediaSource::Type::Video: {
             auto& settings = track.settings();
             if (!selectedTracks.videoTrack && settings.supportsWidth() && settings.supportsHeight())
@@ -51,6 +53,7 @@
             break;
         }
         case RealtimeMediaSource::Type::Audio:
+        case RealtimeMediaSource::Type::SystemAudio:
             if (!selectedTracks.audioTrack)
                 selectedTracks.audioTrack = &track;
             break;

Modified: trunk/Source/WebCore/platform/mediastream/CaptureDevice.h (288893 => 288894)


--- trunk/Source/WebCore/platform/mediastream/CaptureDevice.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDevice.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -31,7 +31,7 @@
 
 class CaptureDevice {
 public:
-    enum class DeviceType { Unknown, Microphone, Speaker, Camera, Screen, Window };
+    enum class DeviceType { Unknown, Microphone, Speaker, Camera, Screen, Window, SystemAudio };
 
     CaptureDevice(const String& persistentId, DeviceType type, const String& label, const String& groupId = emptyString(), bool isEnabled = false, bool isDefault = false, bool isMock = false)
         : m_persistentId(persistentId)
@@ -191,7 +191,8 @@
         WebCore::CaptureDevice::DeviceType::Speaker,
         WebCore::CaptureDevice::DeviceType::Camera,
         WebCore::CaptureDevice::DeviceType::Screen,
-        WebCore::CaptureDevice::DeviceType::Window
+        WebCore::CaptureDevice::DeviceType::Window,
+        WebCore::CaptureDevice::DeviceType::SystemAudio
     >;
 };
 

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (288893 => 288894)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -115,7 +115,7 @@
 
     const String& persistentID() const { return m_persistentID; }
 
-    enum class Type { None, Audio, Video };
+    enum class Type { None, Audio, Video, Screen, Window, SystemAudio };
     Type type() const { return m_type; }
 
     virtual void whenReady(CompletionHandler<void(String)>&&);

Modified: trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp (288893 => 288894)


--- trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/platform/mediastream/cocoa/DisplayCaptureSourceCocoa.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -78,6 +78,7 @@
             return create(ScreenCaptureKitCaptureSource::create(device, constraints), device, WTFMove(hashSalt), constraints);
 #endif
         break;
+    case CaptureDevice::DeviceType::SystemAudio:
     case CaptureDevice::DeviceType::Microphone:
     case CaptureDevice::DeviceType::Speaker:
     case CaptureDevice::DeviceType::Camera:

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


--- trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -129,6 +129,7 @@
         return windowCaptureDeviceWithPersistentID(id);
         break;
 
+    case CaptureDevice::DeviceType::SystemAudio:
     case CaptureDevice::DeviceType::Camera:
     case CaptureDevice::DeviceType::Microphone:
     case CaptureDevice::DeviceType::Speaker:

Modified: trunk/Source/WebCore/platform/mediastream/mac/ScreenCaptureKitCaptureSource.mm (288893 => 288894)


--- trunk/Source/WebCore/platform/mediastream/mac/ScreenCaptureKitCaptureSource.mm	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/platform/mediastream/mac/ScreenCaptureKitCaptureSource.mm	2022-02-01 18:34:18 UTC (rev 288894)
@@ -55,10 +55,6 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
 
-@interface SCStream (SCStream_Deprecated)
-- (void)startCaptureWithCFrameHandler:(SCStreamBufferFrameAvailableHandler)frameHandler completionHandler:(void (^)(NSError *error))completionHandler;
-@end
-
 using namespace WebCore;
 @interface WebCoreScreenCaptureKitHelper : NSObject<SCStreamDelegate> {
     WeakPtr<ScreenCaptureKitCaptureSource> _callback;

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (288893 => 288894)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -196,6 +196,7 @@
         case CaptureDevice::DeviceType::Microphone:
         case CaptureDevice::DeviceType::Speaker:
         case CaptureDevice::DeviceType::Camera:
+        case CaptureDevice::DeviceType::SystemAudio:
         case CaptureDevice::DeviceType::Unknown:
             ASSERT_NOT_REACHED();
             break;

Modified: trunk/Source/WebCore/testing/Internals.cpp (288893 => 288894)


--- trunk/Source/WebCore/testing/Internals.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebCore/testing/Internals.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -4736,21 +4736,43 @@
         string.append("HasPlaybackTargetAvailabilityListener,");
     if (state.containsAny(MediaProducerMediaState::HasAudioOrVideo))
         string.append("HasAudioOrVideo,");
+
     if (state.containsAny(MediaProducerMediaState::HasActiveAudioCaptureDevice))
         string.append("HasActiveAudioCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasMutedAudioCaptureDevice))
+        string.append("HasMutedAudioCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasInterruptedAudioCaptureDevice))
+        string.append("HasInterruptedAudioCaptureDevice,");
+
     if (state.containsAny(MediaProducerMediaState::HasActiveVideoCaptureDevice))
         string.append("HasActiveVideoCaptureDevice,");
-    if (state.containsAny(MediaProducerMediaState::HasMutedAudioCaptureDevice))
-        string.append("HasMutedAudioCaptureDevice,");
     if (state.containsAny(MediaProducerMediaState::HasMutedVideoCaptureDevice))
         string.append("HasMutedVideoCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasInterruptedVideoCaptureDevice))
+        string.append("HasInterruptedVideoCaptureDevice,");
+
     if (state.containsAny(MediaProducerMediaState::HasUserInteractedWithMediaElement))
         string.append("HasUserInteractedWithMediaElement,");
-    if (state.containsAny(MediaProducerMediaState::HasActiveDisplayCaptureDevice))
-        string.append("HasActiveDisplayCaptureDevice,");
-    if (state.containsAny(MediaProducerMediaState::HasMutedDisplayCaptureDevice))
-        string.append("HasMutedDisplayCaptureDevice,");
 
+    if (state.containsAny(MediaProducerMediaState::HasActiveScreenCaptureDevice))
+        string.append("HasActiveScreenCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasMutedScreenCaptureDevice))
+        string.append("HasMutedScreenCaptureDevice,");
+
+    if (state.containsAny(MediaProducerMediaState::HasActiveWindowCaptureDevice))
+        string.append("HasActiveWindowCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasMutedWindowCaptureDevice))
+        string.append("HasMutedWindowCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasInterruptedWindowCaptureDevice))
+        string.append("HasInterruptedWindowCaptureDevice,");
+
+    if (state.containsAny(MediaProducerMediaState::HasActiveSystemAudioCaptureDevice))
+        string.append("HasActiveSystemAudioCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasMutedSystemAudioCaptureDevice))
+        string.append("HasMutedSystemAudioCaptureDevice,");
+    if (state.containsAny(MediaProducerMediaState::HasInterruptedSystemAudioCaptureDevice))
+        string.append("HasInterruptedSystemAudioCaptureDevice,");
+
     if (string.isEmpty())
         string.append("IsNotPlaying");
     else
@@ -5442,9 +5464,12 @@
 
     switch (m_trackSource->type()) {
     case RealtimeMediaSource::Type::Audio:
+    case RealtimeMediaSource::Type::SystemAudio:
         m_trackSource->removeAudioSampleObserver(*this);
         break;
     case RealtimeMediaSource::Type::Video:
+    case RealtimeMediaSource::Type::Screen:
+    case RealtimeMediaSource::Type::Window:
         m_trackSource->removeVideoSampleObserver(*this);
         break;
     case RealtimeMediaSource::Type::None:
@@ -5465,9 +5490,12 @@
     m_trackSource->addObserver(*this);
     switch (m_trackSource->type()) {
     case RealtimeMediaSource::Type::Audio:
+    case RealtimeMediaSource::Type::SystemAudio:
         m_trackSource->addAudioSampleObserver(*this);
         break;
     case RealtimeMediaSource::Type::Video:
+    case RealtimeMediaSource::Type::Screen:
+    case RealtimeMediaSource::Type::Window:
         m_trackSource->addVideoSampleObserver(*this);
         break;
     case RealtimeMediaSource::Type::None:

Modified: trunk/Source/WebKit/ChangeLog (288893 => 288894)


--- trunk/Source/WebKit/ChangeLog	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/ChangeLog	2022-02-01 18:34:18 UTC (rev 288894)
@@ -1,3 +1,81 @@
+2022-02-01  Eric Carlson  <[email protected]>
+
+        [macOS] Expose screen and window capture state to WKWebView
+        https://bugs.webkit.org/show_bug.cgi?id=235838
+        <rdar://problem/88207924>
+
+        Reviewed by Youenn Fablet.
+
+        * GPUProcess/GPUConnectionToWebProcess.cpp:
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageGetMediaState): Rename *DisplayCaptureDevice to *ScreenCaptureDevice. Add enums
+        for window capture.
+
+        * UIProcess/API/C/WKPagePrivate.h:
+        * UIProcess/API/Cocoa/WKWebView.h: Drive by: fix typo in header doc.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView setMicrophoneCaptureState:completionHandler:]): MediaProducerMediaCaptureKind::Audio 
+        was renamed to MediaProducerMediaCaptureKind::Microphone.
+        (-[WKWebView setCameraCaptureState:completionHandler:]): MediaProducerMediaCaptureKind::Video 
+        was renamed to MediaProducerMediaCaptureKind::Camera.
+        (-[WKWebView _stopMediaCapture]): stopMediaCapture takes an optionSet.
+        (-[WKWebView _displayCaptureSurfaces]): Expose the type(s) of displays surfaces
+        being captured.
+        (-[WKWebView _displayCaptureState]): Expose the display capture state.
+        (-[WKWebView _systemAudioCaptureState]): Expose the system audio capture state.
+        (-[WKWebView _setDisplayCaptureState:completionHandler:]): Change the display
+        capture state.
+        (-[WKWebView _setSystemAudioCaptureState:completionHandler:]): Change the system 
+        audio capture state.
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+
+        * UIProcess/API/glib/WebKitWebView.cpp:
+        (webkitWebViewMediaCaptureStateDidChange): MediaProducer::AudioCaptureMask -> 
+        MediaProducer::MicrophoneCaptureMask.
+        (webkitWebViewConfigureMediaCapture): Update for MediaProducerMediaCaptureKind changes.
+        (webkit_web_view_set_microphone_capture_state): Ditto.
+        (webkit_web_view_set_camera_capture_state): MediaProducerMediaCaptureKind::Video -> 
+        MediaProducerMediaCaptureKind::Camera
+        (webkit_web_view_set_display_capture_state): Ditto.
+        (webkit_web_view_get_display_capture_state): MediaState::HasActiveDisplayCaptureDevice ->
+        MediaState::HasActiveScreenCaptureDevice. MediaState::HasMutedDisplayCaptureDevice ->
+        MediaState::HasMutedScreenCaptureDevice
+
+        * UIProcess/Cocoa/PageClientImplCocoa.h:
+        * UIProcess/Cocoa/PageClientImplCocoa.mm:
+        (WebKit::PageClientImplCocoa::displayCaptureWillChange): KVO support.
+        (WebKit::PageClientImplCocoa::displayCaptureSurfacesWillChange): Ditto.
+        (WebKit::PageClientImplCocoa::systemAudioCaptureWillChange): Ditto.
+        (WebKit::PageClientImplCocoa::displayCaptureChanged): Ditto.
+        (WebKit::PageClientImplCocoa::displayCaptureSurfacesChanged): Ditto.
+        (WebKit::PageClientImplCocoa::systemAudioCaptureChanged): Ditto.
+
+        * UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
+        (WebKit::UserMediaCaptureManagerProxy::SourceProxy::SourceProxy): Support new types.
+        (WebKit::UserMediaCaptureManagerProxy::SourceProxy::~SourceProxy): Ditto.
+        (WebKit::UserMediaCaptureManagerProxy::createMediaSourceForCaptureDeviceWithConstraints): Ditto.
+
+        * UIProcess/PageClient.h:
+        (WebKit::PageClient::displayCaptureWillChange):
+        (WebKit::PageClient::displayCaptureSurfacesWillChange):
+        (WebKit::PageClient::systemAudioCaptureWillChange):
+        (WebKit::PageClient::displayCaptureChanged):
+        (WebKit::PageClient::displayCaptureSurfacesChanged):
+        (WebKit::PageClient::systemAudioCaptureChanged):
+
+        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+        (WebKit::UserMediaPermissionRequestManagerProxy::~UserMediaPermissionRequestManagerProxy):
+        MediaProducerMediaCaptureKind::AudioVideo -> MediaProducerMediaCaptureKind::EveryKind.
+        (WebKit::UserMediaPermissionRequestManagerProxy::stopCapture): Ditto.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::updateReportedMediaCaptureState): Deal with new types.
+        * UIProcess/WebPageProxy.h:
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::checkDocumentsCaptureStateConsistency):
+
 2022-02-01  Simon Fraser  <[email protected]>
 
         Minor cleanup in RemoteLayerBackingStoreCollection

Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp (288893 => 288894)


--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -173,6 +173,7 @@
     bool willStartCapture(CaptureDevice::DeviceType type) const final
     {
         switch (type) {
+        case CaptureDevice::DeviceType::SystemAudio:
         case CaptureDevice::DeviceType::Unknown:
         case CaptureDevice::DeviceType::Speaker:
             return false;

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -2966,10 +2966,14 @@
         state |= kWKMediaHasMutedAudioCaptureDevice;
     if (coreState & WebCore::MediaProducerMediaState::HasMutedVideoCaptureDevice)
         state |= kWKMediaHasMutedVideoCaptureDevice;
-    if (coreState & WebCore::MediaProducerMediaState::HasActiveDisplayCaptureDevice)
-        state |= kWKMediaHasActiveDisplayCaptureDevice;
-    if (coreState & WebCore::MediaProducerMediaState::HasMutedDisplayCaptureDevice)
-        state |= kWKMediaHasMutedDisplayCaptureDevice;
+    if (coreState & WebCore::MediaProducerMediaState::HasActiveScreenCaptureDevice)
+        state |= kWKMediaHasActiveScreenCaptureDevice;
+    if (coreState & WebCore::MediaProducerMediaState::HasMutedScreenCaptureDevice)
+        state |= kWKMediaHasMutedScreenCaptureDevice;
+    if (coreState & WebCore::MediaProducerMediaState::HasActiveWindowCaptureDevice)
+        state |= kWKMediaHasActiveWindowCaptureDevice;
+    if (coreState & WebCore::MediaProducerMediaState::HasMutedWindowCaptureDevice)
+        state |= kWKMediaHasMutedWindowCaptureDevice;
 
     return state;
 }

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -146,8 +146,12 @@
     kWKMediaHasActiveVideoCaptureDevice = 1 << 3,
     kWKMediaHasMutedAudioCaptureDevice = 1 << 4,
     kWKMediaHasMutedVideoCaptureDevice = 1 << 5,
-    kWKMediaHasActiveDisplayCaptureDevice = 1 << 6,
-    kWKMediaHasMutedDisplayCaptureDevice = 1 << 7,
+    kWKMediaHasActiveScreenCaptureDevice = 1 << 6,
+    kWKMediaHasActiveDisplayCaptureDevice = kWKMediaHasActiveScreenCaptureDevice,
+    kWKMediaHasMutedScreenCaptureDevice = 1 << 7,
+    kWKMediaHasMutedDisplayCaptureDevice = kWKMediaHasMutedScreenCaptureDevice,
+    kWKMediaHasActiveWindowCaptureDevice = 1 << 8,
+    kWKMediaHasMutedWindowCaptureDevice = 1 << 9,
 };
 typedef uint32_t WKMediaState;
 

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -406,7 +406,7 @@
 
 /*! @abstract Set microphone capture state of a WKWebView.
  @param state state to apply for capture.
- @param completionHandler A block to invoke after the camera state has been changed.
+ @param completionHandler A block to invoke after the microphone state has been changed.
  @discussion
  If value is WKMediaCaptureStateNone, this will stop any microphone capture.
  If value is WKMediaCaptureStateMuted, any active microphone capture will become muted.

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2022-02-01 18:34:18 UTC (rev 288894)
@@ -1069,7 +1069,7 @@
         completionHandler = [] { };
 
     if (state == WKMediaCaptureStateNone) {
-        _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::Audio, [completionHandler = makeBlockPtr(completionHandler)] {
+        _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::Microphone, [completionHandler = makeBlockPtr(completionHandler)] {
             completionHandler();
         });
         return;
@@ -1091,7 +1091,7 @@
         completionHandler = [] { };
 
     if (state == WKMediaCaptureStateNone) {
-        _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::Video, [completionHandler = makeBlockPtr(completionHandler)] {
+        _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::Camera, [completionHandler = makeBlockPtr(completionHandler)] {
             completionHandler();
         });
         return;
@@ -2332,7 +2332,7 @@
 - (void)_stopMediaCapture
 {
     THROW_IF_SUSPENDED;
-    _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::AudioVideo);
+    _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::EveryKind);
 }
 
 - (void)_stopAllMediaPlayback
@@ -3706,6 +3706,83 @@
     [self _internalDoAfterNextPresentationUpdate:updateBlock withoutWaitingForPainting:YES withoutWaitingForAnimatedResize:NO];
 }
 
+- (WKDisplayCaptureSurfaces) _displayCaptureSurfaces
+{
+    auto pageState = _page->reportedMediaState();
+    WKDisplayCaptureSurfaces state = WKDisplayCaptureSurfaceNone;
+    if (pageState.containsAny(WebCore::MediaProducer::ScreenCaptureMask))
+        state |= WKDisplayCaptureSurfaceScreen;
+    if (pageState.containsAny(WebCore::MediaProducer::WindowCaptureMask))
+        state |= WKDisplayCaptureSurfaceWindow;
+    return state;
+}
+
+- (WKDisplayCaptureState) _displayCaptureState
+{
+    auto state = _page->reportedMediaState();
+    if (state & WebCore::MediaProducer::ActiveDisplayCaptureMask)
+        return WKDisplayCaptureStateActive;
+    if (state & WebCore::MediaProducer::MutedDisplayCaptureMask)
+        return WKDisplayCaptureStateMuted;
+    return WKDisplayCaptureStateNone;
+}
+
+- (WKSystemAudioCaptureState)_systemAudioCaptureState
+{
+    auto state = _page->reportedMediaState();
+    if (state & WebCore::MediaProducerMediaState::HasActiveSystemAudioCaptureDevice)
+        return WKSystemAudioCaptureStateActive;
+    if (state & WebCore::MediaProducerMediaState::HasMutedSystemAudioCaptureDevice)
+        return WKSystemAudioCaptureStateMuted;
+    return WKSystemAudioCaptureStateNone;
+}
+
+- (void)_setDisplayCaptureState:(WKDisplayCaptureState)state completionHandler:(void (^)(void))completionHandler
+{
+    THROW_IF_SUSPENDED;
+    if (!completionHandler)
+        completionHandler = [] { };
+
+    if (state == WKDisplayCaptureStateNone) {
+        _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::Display, [completionHandler = makeBlockPtr(completionHandler)] {
+            completionHandler();
+        });
+        return;
+    }
+
+    constexpr WebCore::MediaProducer::MutedStateFlags displayMutedFlags = { WebCore::MediaProducer::MutedState::ScreenCaptureIsMuted, WebCore::MediaProducer::MutedState::WindowCaptureIsMuted };
+    auto mutedState = _page->mutedStateFlags();
+    if (state == WKDisplayCaptureStateActive)
+        mutedState.remove(displayMutedFlags);
+    else if (state == WKDisplayCaptureStateMuted)
+        mutedState.add(displayMutedFlags);
+    _page->setMuted(mutedState, [completionHandler = makeBlockPtr(completionHandler)] {
+        completionHandler();
+    });
+}
+
+- (void)_setSystemAudioCaptureState:(WKSystemAudioCaptureState)state completionHandler:(void (^)(void))completionHandler
+{
+    THROW_IF_SUSPENDED;
+    if (!completionHandler)
+        completionHandler = [] { };
+
+    if (state == WKSystemAudioCaptureStateNone) {
+        _page->stopMediaCapture(WebCore::MediaProducerMediaCaptureKind::SystemAudio, [completionHandler = makeBlockPtr(completionHandler)] {
+            completionHandler();
+        });
+        return;
+    }
+    auto mutedState = _page->mutedStateFlags();
+    if (state == WKSystemAudioCaptureStateActive)
+        mutedState.remove(WebCore::MediaProducerMutedState::WindowCaptureIsMuted);
+    else if (state == WKSystemAudioCaptureStateMuted)
+        mutedState.add(WebCore::MediaProducerMutedState::WindowCaptureIsMuted);
+    _page->setMuted(mutedState, [completionHandler = makeBlockPtr(completionHandler)] {
+        completionHandler();
+    });
+}
+
 @end
 
 @implementation WKWebView (WKDeprecated)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -427,6 +427,65 @@
 
 - (void)_requestResource:(NSURLRequest *)request completionHandler:(void(^)(NSData *, NSURLResponse *, NSError *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+typedef NS_ENUM(NSInteger, WKDisplayCaptureState) {
+    WKDisplayCaptureStateNone,
+    WKDisplayCaptureStateActive,
+    WKDisplayCaptureStateMuted,
+} WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+typedef NS_ENUM(NSInteger, WKSystemAudioCaptureState) {
+    WKSystemAudioCaptureStateNone,
+    WKSystemAudioCaptureStateActive,
+    WKSystemAudioCaptureStateMuted,
+} WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+typedef NS_OPTIONS(NSUInteger, WKDisplayCaptureSurfaces) {
+    WKDisplayCaptureSurfaceNone = 0,
+    WKDisplayCaptureSurfaceScreen = 0x1,
+    WKDisplayCaptureSurfaceWindow = 0x2,
+};
+
+/*! @abstract The type(s) of displays being captured on a web page.
+ @discussion @link WKWebView @/link is key-value observing (KVO) compliant
+ for this property.
+ */
+@property (nonatomic, readonly) WKDisplayCaptureSurfaces _displayCaptureSurfaces WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+/*! @abstract The state of display capture on a web page.
+ @discussion @link WKWebView @/link is key-value observing (KVO) compliant
+ for this property.
+ */
+@property (nonatomic, readonly) WKDisplayCaptureState _displayCaptureState WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+/*! @abstract The state of system audio capture on a web page.
+ @discussion @link WKWebView @/link is key-value observing (KVO) compliant
+ for this property.
+ */
+@property (nonatomic, readonly) WKSystemAudioCaptureState _systemAudioCaptureState WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+/*! @abstract Set display capture state of a WKWebView.
+ @param state State to apply for capture.
+ @param completionHandler A block to invoke after the screen state has been changed.
+ @discussion
+ If value is WKDisplayCaptureStateNone, this will stop all display capture.
+ If value is WKDisplayCaptureStateMuted, all active display captures will become muted.
+ If value is WKDisplayCaptureStateActive, all muted display captures will become active.
+ */
+- (void)_setDisplayCaptureState:(WKDisplayCaptureState)state completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+/*! @abstract Set system audio capture state of a WKWebView.
+ @param state State to apply for system audio capture.
+ @param completionHandler A block to invoke after the system audio state has been changed.
+ @discussion
+ If value is WKSystemAudioCaptureStateNone, this will stop any system audio capture.
+ If value is WKSystemAudioCaptureStateMuted, any active system audio capture will become muted.
+ If value is WKSystemAudioCaptureStateActive, any muted system audio capture will become active.
+ @note When system audio capture is active, if screenCaptureState is active, all system audio will be captured.
+ Otherwise, if windowCaptureState is active, only the application whose window being is captured will have its audio captured.
+ If both screenCaptureState and windowCaptureState are None or Muted, no system audio will be captured.
+ */
+- (void)_setSystemAudioCaptureState:(WKSystemAudioCaptureState)state completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
 
 #if TARGET_OS_IPHONE

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -364,7 +364,7 @@
         g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_MICROPHONE_CAPTURE_STATE]);
         return;
     }
-    if (mediaStateFlags.containsAny(WebCore::MediaProducer::AudioCaptureMask))
+    if (mediaStateFlags.containsAny(WebCore::MediaProducer::MicrophoneCaptureMask))
         g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_MICROPHONE_CAPTURE_STATE]);
     if (mediaStateFlags.containsAny(WebCore::MediaProducer::VideoCaptureMask))
         g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_CAMERA_CAPTURE_STATE]);
@@ -4868,7 +4868,7 @@
     getPage(webView).setCORSDisablingPatterns(WTFMove(allowListVector));
 }
 
-static void webkitWebViewConfigureMediaCapture(WebKitWebView* webView, WebCore::MediaProducerMediaCaptureKind captureKind, WebKitMediaCaptureState captureState, bool isFromDisplayCapture = false)
+static void webkitWebViewConfigureMediaCapture(WebKitWebView* webView, WebCore::MediaProducerMediaCaptureKind captureKind, WebKitMediaCaptureState captureState)
 {
     auto& page = getPage(webView);
     auto mutedState = page.mutedStateFlags();
@@ -4877,13 +4877,15 @@
     case WEBKIT_MEDIA_CAPTURE_STATE_NONE:
         page.stopMediaCapture(captureKind, [webView, captureKind] {
             switch (captureKind) {
-            case WebCore::MediaProducerMediaCaptureKind::Audio:
+            case WebCore::MediaProducerMediaCaptureKind::Microphone:
                 g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_MICROPHONE_CAPTURE_STATE]);
                 break;
-            case WebCore::MediaProducerMediaCaptureKind::Video:
+            case WebCore::MediaProducerMediaCaptureKind::Display:
+            case WebCore::MediaProducerMediaCaptureKind::Camera:
                 g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_CAMERA_CAPTURE_STATE]);
                 break;
-            case WebCore::MediaProducerMediaCaptureKind::AudioVideo:
+            case WebCore::MediaProducerMediaCaptureKind::SystemAudio:
+            case WebCore::MediaProducerMediaCaptureKind::EveryKind:
                 ASSERT_NOT_REACHED();
                 return;
             }
@@ -4891,16 +4893,17 @@
         break;
     case WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE:
         switch (captureKind) {
-        case WebCore::MediaProducerMediaCaptureKind::Audio:
+        case WebCore::MediaProducerMediaCaptureKind::Microphone:
             mutedState.remove(WebCore::MediaProducer::MutedState::AudioCaptureIsMuted);
             break;
-        case WebCore::MediaProducerMediaCaptureKind::Video:
-            if (isFromDisplayCapture)
-                mutedState.remove(WebCore::MediaProducer::MutedState::ScreenCaptureIsMuted);
-            else
-                mutedState.remove(WebCore::MediaProducer::MutedState::VideoCaptureIsMuted);
+        case WebCore::MediaProducerMediaCaptureKind::Camera:
+            mutedState.remove(WebCore::MediaProducer::MutedState::VideoCaptureIsMuted);
             break;
-        case WebCore::MediaProducerMediaCaptureKind::AudioVideo:
+        case WebCore::MediaProducerMediaCaptureKind::Display:
+            mutedState.remove(WebCore::MediaProducer::MutedState::ScreenCaptureIsMuted);
+            break;
+        case WebCore::MediaProducerMediaCaptureKind::SystemAudio:
+        case WebCore::MediaProducerMediaCaptureKind::EveryKind:
             ASSERT_NOT_REACHED();
             return;
         }
@@ -4908,16 +4911,17 @@
         break;
     case WEBKIT_MEDIA_CAPTURE_STATE_MUTED:
         switch (captureKind) {
-        case WebCore::MediaProducerMediaCaptureKind::Audio:
+        case WebCore::MediaProducerMediaCaptureKind::Microphone:
             mutedState.add(WebCore::MediaProducer::MutedState::AudioCaptureIsMuted);
             break;
-        case WebCore::MediaProducerMediaCaptureKind::Video:
-            if (isFromDisplayCapture)
-                mutedState.add(WebCore::MediaProducer::MutedState::ScreenCaptureIsMuted);
-            else
-                mutedState.add(WebCore::MediaProducer::MutedState::VideoCaptureIsMuted);
+        case WebCore::MediaProducerMediaCaptureKind::Camera:
+            mutedState.add(WebCore::MediaProducer::MutedState::VideoCaptureIsMuted);
             break;
-        case WebCore::MediaProducerMediaCaptureKind::AudioVideo:
+        case WebCore::MediaProducerMediaCaptureKind::Display:
+            mutedState.add(WebCore::MediaProducer::MutedState::ScreenCaptureIsMuted);
+            break;
+        case WebCore::MediaProducerMediaCaptureKind::SystemAudio:
+        case WebCore::MediaProducerMediaCaptureKind::EveryKind:
             ASSERT_NOT_REACHED();
             return;
         }
@@ -4965,7 +4969,7 @@
     if (webkit_web_view_get_camera_capture_state(webView) == WEBKIT_MEDIA_CAPTURE_STATE_NONE)
         return;
 
-    webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducerMediaCaptureKind::Video, state);
+    webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducerMediaCaptureKind::Camera, state);
 }
 
 /**
@@ -5007,7 +5011,7 @@
     if (webkit_web_view_get_microphone_capture_state(webView) == WEBKIT_MEDIA_CAPTURE_STATE_NONE)
         return;
 
-    webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducerMediaCaptureKind::Audio, state);
+    webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducerMediaCaptureKind::Microphone, state);
 }
 
 /**
@@ -5024,9 +5028,9 @@
 WebKitMediaCaptureState webkit_web_view_get_display_capture_state(WebKitWebView* webView)
 {
     auto state = getPage(webView).reportedMediaState();
-    if (state & WebCore::MediaProducer::MediaState::HasActiveDisplayCaptureDevice)
+    if (state & WebCore::MediaProducer::MediaState::HasActiveScreenCaptureDevice)
         return WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE;
-    if (state & WebCore::MediaProducer::MediaState::HasMutedDisplayCaptureDevice)
+    if (state & WebCore::MediaProducer::MediaState::HasMutedScreenCaptureDevice)
         return WEBKIT_MEDIA_CAPTURE_STATE_MUTED;
     return WEBKIT_MEDIA_CAPTURE_STATE_NONE;
 }
@@ -5049,5 +5053,5 @@
     if (webkit_web_view_get_display_capture_state(webView) == WEBKIT_MEDIA_CAPTURE_STATE_NONE)
         return;
 
-    webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducerMediaCaptureKind::Video, state, true);
+    webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducerMediaCaptureKind::Display, state);
 }

Modified: trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -84,8 +84,15 @@
 
     void microphoneCaptureWillChange() final;
     void cameraCaptureWillChange() final;
+    void displayCaptureWillChange() final;
+    void displayCaptureSurfacesWillChange() final;
+    void systemAudioCaptureWillChange() final;
+
     void microphoneCaptureChanged() final;
     void cameraCaptureChanged() final;
+    void displayCaptureChanged() final;
+    void displayCaptureSurfacesChanged() final;
+    void systemAudioCaptureChanged() final;
 
     WindowKind windowKind() final;
 

Modified: trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2022-02-01 18:34:18 UTC (rev 288894)
@@ -183,6 +183,21 @@
     [m_webView willChangeValueForKey:@"cameraCaptureState"];
 }
 
+void PageClientImplCocoa::displayCaptureWillChange()
+{
+    [m_webView willChangeValueForKey:@"_displayCaptureState"];
+}
+
+void PageClientImplCocoa::displayCaptureSurfacesWillChange()
+{
+    [m_webView willChangeValueForKey:@"_displayCaptureSurfaces"];
+}
+
+void PageClientImplCocoa::systemAudioCaptureWillChange()
+{
+    [m_webView willChangeValueForKey:@"_systemAudioCaptureState"];
+}
+
 void PageClientImplCocoa::microphoneCaptureChanged()
 {
     [m_webView didChangeValueForKey:@"microphoneCaptureState"];
@@ -193,6 +208,21 @@
     [m_webView didChangeValueForKey:@"cameraCaptureState"];
 }
 
+void PageClientImplCocoa::displayCaptureChanged()
+{
+    [m_webView didChangeValueForKey:@"_displayCaptureState"];
+}
+
+void PageClientImplCocoa::displayCaptureSurfacesChanged()
+{
+    [m_webView didChangeValueForKey:@"_displayCaptureSurfaces"];
+}
+
+void PageClientImplCocoa::systemAudioCaptureChanged()
+{
+    [m_webView didChangeValueForKey:@"_systemAudioCaptureState"];
+}
+
 WindowKind PageClientImplCocoa::windowKind()
 {
     auto window = [m_webView window];

Modified: trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -66,9 +66,12 @@
         m_source->addObserver(*this);
         switch (m_source->type()) {
         case RealtimeMediaSource::Type::Audio:
+        case RealtimeMediaSource::Type::SystemAudio:
             m_source->addAudioSampleObserver(*this);
             break;
         case RealtimeMediaSource::Type::Video:
+        case RealtimeMediaSource::Type::Screen:
+        case RealtimeMediaSource::Type::Window:
             m_source->addVideoSampleObserver(*this);
             break;
         case RealtimeMediaSource::Type::None:
@@ -83,9 +86,12 @@
 
         switch (m_source->type()) {
         case RealtimeMediaSource::Type::Audio:
+        case RealtimeMediaSource::Type::SystemAudio:
             m_source->removeAudioSampleObserver(*this);
             break;
         case RealtimeMediaSource::Type::Video:
+        case RealtimeMediaSource::Type::Screen:
+        case RealtimeMediaSource::Type::Window:
             m_source->removeVideoSampleObserver(*this);
             break;
         case RealtimeMediaSource::Type::None:
@@ -288,6 +294,7 @@
     case WebCore::CaptureDevice::DeviceType::Window:
         sourceOrError = RealtimeMediaSourceCenter::singleton().displayCaptureFactory().createDisplayCaptureSource(device, WTFMove(hashSalt), constraints);
         break;
+    case WebCore::CaptureDevice::DeviceType::SystemAudio:
     case WebCore::CaptureDevice::DeviceType::Speaker:
     case WebCore::CaptureDevice::DeviceType::Unknown:
         ASSERT_NOT_REACHED();

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -565,8 +565,14 @@
 
     virtual void microphoneCaptureWillChange() { }
     virtual void cameraCaptureWillChange() { }
+    virtual void displayCaptureWillChange() { }
+    virtual void displayCaptureSurfacesWillChange() { }
+    virtual void systemAudioCaptureWillChange() { }
     virtual void microphoneCaptureChanged() { }
     virtual void cameraCaptureChanged() { }
+    virtual void displayCaptureChanged() { }
+    virtual void displayCaptureSurfacesChanged() { }
+    virtual void systemAudioCaptureChanged() { }
 
     virtual void videoControlsManagerDidChange() { }
 

Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -99,7 +99,7 @@
 
 UserMediaPermissionRequestManagerProxy::~UserMediaPermissionRequestManagerProxy()
 {
-    m_page.sendWithAsyncReply(Messages::WebPage::StopMediaCapture { MediaProducerMediaCaptureKind::AudioVideo }, [] { });
+    m_page.sendWithAsyncReply(Messages::WebPage::StopMediaCapture { MediaProducerMediaCaptureKind::EveryKind }, [] { });
 #if ENABLE(MEDIA_STREAM)
     UserMediaProcessManager::singleton().revokeSandboxExtensionsIfNeeded(page().process());
     proxies().remove(this);
@@ -133,7 +133,7 @@
 {
     ALWAYS_LOG(LOGIDENTIFIER);
     invalidatePendingRequests();
-    m_page.stopMediaCapture(MediaProducerMediaCaptureKind::AudioVideo);
+    m_page.stopMediaCapture(MediaProducerMediaCaptureKind::EveryKind);
 }
 
 void UserMediaPermissionRequestManagerProxy::captureDevicesChanged()

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -9636,13 +9636,25 @@
 
     WEBPAGEPROXY_RELEASE_LOG(WebRTC, "updateReportedMediaCaptureState: from %d to %d", m_reportedMediaCaptureState.toRaw(), activeCaptureState.toRaw());
 
-    bool microphoneCaptureChanged = (m_reportedMediaCaptureState & MediaProducer::AudioCaptureMask) != (activeCaptureState & MediaProducer::AudioCaptureMask);
+    bool microphoneCaptureChanged = (m_reportedMediaCaptureState & MediaProducer::MicrophoneCaptureMask) != (activeCaptureState & MediaProducer::MicrophoneCaptureMask);
     bool cameraCaptureChanged = (m_reportedMediaCaptureState & MediaProducer::VideoCaptureMask) != (activeCaptureState & MediaProducer::VideoCaptureMask);
+    bool displayCaptureChanged = (m_reportedMediaCaptureState & MediaProducer::DisplayCaptureMask) != (activeCaptureState & MediaProducer::DisplayCaptureMask);
+    bool systemAudioCaptureChanged = (m_reportedMediaCaptureState & MediaProducer::SystemAudioCaptureMask) != (activeCaptureState & MediaProducer::SystemAudioCaptureMask);
 
+    auto reportedDisplayCaptureSurfaces = m_reportedMediaCaptureState & (MediaProducer::ScreenCaptureMask | MediaProducer::WindowCaptureMask);
+    auto activeDisplayCaptureSurfaces = activeCaptureState & (MediaProducer::ScreenCaptureMask | MediaProducer::WindowCaptureMask);
+    auto displayCaptureSurfacesChanged = reportedDisplayCaptureSurfaces != activeDisplayCaptureSurfaces;
+
     if (microphoneCaptureChanged)
         pageClient().microphoneCaptureWillChange();
     if (cameraCaptureChanged)
         pageClient().cameraCaptureWillChange();
+    if (displayCaptureChanged)
+        pageClient().displayCaptureWillChange();
+    if (displayCaptureSurfacesChanged)
+        pageClient().displayCaptureSurfacesWillChange();
+    if (systemAudioCaptureChanged)
+        pageClient().systemAudioCaptureWillChange();
 
     m_reportedMediaCaptureState = activeCaptureState;
     m_uiClient->mediaCaptureStateDidChange(m_mediaState);
@@ -9651,6 +9663,12 @@
         pageClient().microphoneCaptureChanged();
     if (cameraCaptureChanged)
         pageClient().cameraCaptureChanged();
+    if (displayCaptureChanged)
+        pageClient().displayCaptureChanged();
+    if (displayCaptureSurfacesChanged)
+        pageClient().displayCaptureSurfacesChanged();
+    if (systemAudioCaptureChanged)
+        pageClient().systemAudioCaptureChanged();
 }
 
 void WebPageProxy::videoControlsManagerDidChange()

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (288893 => 288894)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2022-02-01 18:34:18 UTC (rev 288894)
@@ -1555,8 +1555,8 @@
 
     enum class CanDelayNotification { No, Yes };
     void updatePlayingMediaDidChange(WebCore::MediaProducerMediaStateFlags, CanDelayNotification = CanDelayNotification::No);
-    bool isCapturingAudio() const { return m_mediaState.containsAny(WebCore::MediaProducer::AudioCaptureMask); }
-    bool isCapturingVideo() const { return m_mediaState.containsAny(WebCore::MediaProducer::VideoCaptureMask); }
+    bool isCapturingAudio() const { return m_mediaState.containsAny(WebCore::MediaProducer::IsCapturingAudioMask); }
+    bool isCapturingVideo() const { return m_mediaState.containsAny(WebCore::MediaProducer::IsCapturingVideoMask); }
     bool hasActiveAudioStream() const { return m_mediaState.containsAny(WebCore::MediaProducerMediaState::HasActiveAudioCaptureDevice); }
     bool hasActiveVideoStream() const { return m_mediaState.containsAny(WebCore::MediaProducerMediaState::HasActiveVideoCaptureDevice); }
     WebCore::MediaProducerMediaStateFlags reportedMediaState() const { return m_reportedMediaCaptureState | (m_mediaState - WebCore::MediaProducer::MediaCaptureMask); }

Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (288893 => 288894)


--- trunk/Source/WebKit/WebProcess/WebProcess.cpp	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp	2022-02-01 18:34:18 UTC (rev 288894)
@@ -1976,7 +1976,7 @@
 {
 #if ASSERT_ENABLED
     bool isCapturingAudio = WTF::anyOf(Document::allDocumentsMap().values(), [](auto* document) {
-        return document->mediaState() & MediaProducer::AudioCaptureMask;
+        return document->mediaState() & MediaProducer::MicrophoneCaptureMask;
     });
     bool isCapturingVideo = WTF::anyOf(Document::allDocumentsMap().values(), [](auto* document) {
         return document->mediaState() & MediaProducer::VideoCaptureMask;

Modified: trunk/Tools/ChangeLog (288893 => 288894)


--- trunk/Tools/ChangeLog	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Tools/ChangeLog	2022-02-01 18:34:18 UTC (rev 288894)
@@ -1,3 +1,20 @@
+2022-02-01  Eric Carlson  <[email protected]>
+
+        [macOS] Expose screen and window capture state to WKWebView
+        https://bugs.webkit.org/show_bug.cgi?id=235838
+        <rdar://problem/88207924>
+
+        Reviewed by Youenn Fablet.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/xcshareddata/xcschemes/TestWebKitAPI.xcscheme:
+        * TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMediaWindowAndScreen.mm:
+        (-[DisplayCaptureObserver observeValueForKeyPath:ofObject:change:context:]):
+        (-[DisplayCaptureObserver waitForDisplayCaptureState:]):
+        (-[DisplayCaptureObserver waitForDisplayCaptureSurfaces:]):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/glib/TestExpectations.json: Skip /webkit/WebKitWebView/display-usermedia-permission-request
+        until someone has a chance to figure out why it times out.
+
 2022-02-01  Sam Sneddon  <[email protected]>
 
         Migrate LayoutTestFinder tests from FileSystemMock to pyfakefs

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMediaWindowAndScreen.mm (288893 => 288894)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMediaWindowAndScreen.mm	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMediaWindowAndScreen.mm	2022-02-01 18:34:18 UTC (rev 288894)
@@ -33,9 +33,9 @@
 #import "UserMediaCaptureUIDelegate.h"
 #import <WebKit/WKPreferencesPrivate.h>
 #import <WebKit/WKUIDelegatePrivate.h>
-#import <WebKit/WKWebView.h>
 #import <WebKit/WKWebViewConfiguration.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/WKWebViewPrivateForTesting.h>
 
 @interface WindowAndScreenCaptureTestView : TestWKWebView
@@ -58,6 +58,62 @@
 }
 @end
 
+@interface DisplayCaptureObserver : NSObject {
+    WKDisplayCaptureSurfaces _displayCaptureSurfaces;
+    WKDisplayCaptureState _displayCaptureState;
+}
+
+@property WKDisplayCaptureState displayCaptureState;
+@property WKDisplayCaptureSurfaces displayCaptureSurfaces;
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context;
+- (BOOL)waitForDisplayCaptureState:(WKDisplayCaptureState)expectedState;
+- (BOOL)waitForDisplayCaptureSurfaces:(WKDisplayCaptureSurfaces)expectedState;
+@end
+
+@implementation DisplayCaptureObserver
+
+@synthesize displayCaptureSurfaces = _displayCaptureSurfaces;
+@synthesize displayCaptureState = _displayCaptureState;
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context
+{
+    EXPECT_TRUE([keyPath isEqualToString:NSStringFromSelector(@selector(_displayCaptureSurfaces))] || [keyPath isEqualToString:NSStringFromSelector(@selector(_displayCaptureState))]);
+
+    if ([keyPath isEqualToString:NSStringFromSelector(@selector(_displayCaptureSurfaces))]) {
+        _displayCaptureSurfaces = (WKDisplayCaptureSurfaces)[[change objectForKey:NSKeyValueChangeNewKey] unsignedIntegerValue];
+        return;
+    }
+    _displayCaptureState = (WKDisplayCaptureState)[[change objectForKey:NSKeyValueChangeNewKey] unsignedIntegerValue];
+}
+
+static constexpr unsigned stateChangeQueryMaxCount = 30;
+
+- (BOOL)waitForDisplayCaptureState:(WKDisplayCaptureState)expectedState
+{
+    unsigned tries = 0;
+    do {
+        if (expectedState == _displayCaptureState)
+            return YES;
+        TestWebKitAPI::Util::sleep(0.1);
+    } while (++tries <= stateChangeQueryMaxCount);
+
+    return expectedState == _displayCaptureState;
+}
+
+- (BOOL)waitForDisplayCaptureSurfaces:(WKDisplayCaptureSurfaces)expectedState
+{
+    unsigned tries = 0;
+    do {
+        if (expectedState == _displayCaptureSurfaces)
+            return YES;
+        TestWebKitAPI::Util::sleep(0.1);
+    } while (++tries <= stateChangeQueryMaxCount);
+
+    return expectedState == _displayCaptureSurfaces;
+}
+@end
+
 namespace TestWebKitAPI {
 
 TEST(WebKit2, GetDisplayMediaWindowAndScreenPrompt)
@@ -77,7 +133,15 @@
     auto webView = adoptNS([[WindowAndScreenCaptureTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
     [webView setUIDelegate:delegate.get()];
 
+    auto observer = adoptNS([[DisplayCaptureObserver alloc] init]);
+    [webView addObserver:observer.get() forKeyPath:@"_displayCaptureSurfaces" options:NSKeyValueObservingOptionNew context:nil];
+    [webView addObserver:observer.get() forKeyPath:@"_displayCaptureState" options:NSKeyValueObservingOptionNew context:nil];
+
     [webView synchronouslyLoadTestPageNamed:@"getDisplayMedia"];
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateNone);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceNone);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateNone);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceNone);
 
     // Check "Don’t Allow"
     [delegate setGetDisplayMediaDecision:WKDisplayCapturePermissionDecisionDeny];
@@ -84,6 +148,8 @@
     [webView stringByEvaluatingJavaScript:@"promptForCapture({ video : true })"];
     [delegate waitUntilPrompted];
     EXPECT_TRUE([webView haveStream:NO]);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateNone);
+    EXPECT_TRUE([webView _displayCaptureSurfaces] == WKDisplayCaptureSurfaceNone);
 
     // Check "Allow Screen"
     [webView stringByEvaluatingJavaScript:@"stop()"];
@@ -95,9 +161,42 @@
     EXPECT_TRUE([webView haveStream:YES]);
     auto label = [webView stringByEvaluatingJavaScript:@"stream.getVideoTracks()[0].label"];
     EXPECT_WK_STREQ(label, @"Mock screen device 1");
+    EXPECT_TRUE([observer waitForDisplayCaptureState:WKDisplayCaptureStateActive]);
+    EXPECT_TRUE([observer waitForDisplayCaptureSurfaces:WKDisplayCaptureSurfaceScreen]);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([observer displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([webView _displayCaptureSurfaces] == WKDisplayCaptureSurfaceScreen);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceScreen);
 
+    // Mute and unmute screen capture
+    __block bool completionCalled = false;
+    [webView _setDisplayCaptureState:WKDisplayCaptureStateMuted completionHandler:^() {
+        completionCalled = true;
+    }];
+    TestWebKitAPI::Util::run(&completionCalled);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateMuted);
+    EXPECT_TRUE([observer displayCaptureState] == WKDisplayCaptureStateMuted);
+    EXPECT_TRUE([webView _displayCaptureSurfaces] == WKDisplayCaptureSurfaceScreen);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceScreen);
+
+    completionCalled = false;
+    [webView _setDisplayCaptureState:WKDisplayCaptureStateActive completionHandler:^() {
+        completionCalled = true;
+    }];
+    TestWebKitAPI::Util::run(&completionCalled);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([observer displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([webView _displayCaptureSurfaces] == WKDisplayCaptureSurfaceScreen);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceScreen);
+
+    // Stop all capture
+    [webView stringByEvaluatingJavaScript:@"stop()"];
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateNone);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceNone);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateNone);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceNone);
+
     // Check "Allow Window"
-    [webView stringByEvaluatingJavaScript:@"stop()"];
     [delegate resetWasPrompted];
     [webView _setIndexOfGetDisplayMediaDeviceSelectedForTesting:@0];
     [delegate setGetDisplayMediaDecision:WKDisplayCapturePermissionDecisionWindowPrompt];
@@ -106,9 +205,39 @@
     EXPECT_TRUE([webView haveStream:YES]);
     label = [webView stringByEvaluatingJavaScript:@"stream.getVideoTracks()[0].label"];
     EXPECT_WK_STREQ(label, @"Mock window device 1");
+    EXPECT_TRUE([observer waitForDisplayCaptureState:WKDisplayCaptureStateActive]);
+    EXPECT_TRUE([observer waitForDisplayCaptureSurfaces:WKDisplayCaptureSurfaceWindow]);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([observer displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([webView _displayCaptureSurfaces] == WKDisplayCaptureSurfaceWindow);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceWindow);
 
+    // Mute and unmute
+    completionCalled = false;
+    [webView _setDisplayCaptureState:WKDisplayCaptureStateMuted completionHandler:^() {
+        completionCalled = true;
+    }];
+    TestWebKitAPI::Util::run(&completionCalled);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateMuted);
+    EXPECT_TRUE([observer displayCaptureState] == WKDisplayCaptureStateMuted);
+    EXPECT_TRUE([webView _displayCaptureSurfaces] == WKDisplayCaptureSurfaceWindow);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceWindow);
+
+    completionCalled = false;
+    [webView _setDisplayCaptureState:WKDisplayCaptureStateActive completionHandler:^() {
+        completionCalled = true;
+    }];
+    TestWebKitAPI::Util::run(&completionCalled);
+    EXPECT_TRUE([webView _displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([observer displayCaptureState] == WKDisplayCaptureStateActive);
+    EXPECT_TRUE([webView _displayCaptureSurfaces] == WKDisplayCaptureSurfaceWindow);
+    EXPECT_TRUE([observer displayCaptureSurfaces] == WKDisplayCaptureSurfaceWindow);
+
     [webView stringByEvaluatingJavaScript:@"stop()"];
     [webView _setIndexOfGetDisplayMediaDeviceSelectedForTesting:nil];
+
+    [webView removeObserver:observer.get() forKeyPath:@"_displayCaptureSurfaces"];
+    [webView removeObserver:observer.get() forKeyPath:@"_displayCaptureState"];
 }
 
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/glib/TestExpectations.json (288893 => 288894)


--- trunk/Tools/TestWebKitAPI/glib/TestExpectations.json	2022-02-01 18:29:59 UTC (rev 288893)
+++ trunk/Tools/TestWebKitAPI/glib/TestExpectations.json	2022-02-01 18:34:18 UTC (rev 288894)
@@ -50,7 +50,10 @@
                 "expected": {"gtk": {"status": ["TIMEOUT"], "bug": "webkit.org/b/205266"}}
             },
             "/webkit/WebKitWebView/geolocation-permission-requests": {
-                "expected": {"gtk": {"status": ["TIMEOUT", "PASS"], "bug": "webkit.org/b/213786"}}
+                "expected": {"gtk": {"status": ["TIMEOUT", "PASS"], "bug": "webkit.org/b/235955"}}
+            },
+            "/webkit/WebKitWebView/display-usermedia-permission-request": {
+                "expected": {"gtk": {"status": ["TIMEOUT", "FAIL"], "bug": "webkit.org/b/235955"}}
             }
         }
     },
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to