Title: [288087] trunk
Revision
288087
Author
you...@apple.com
Date
2022-01-16 22:44:44 -0800 (Sun, 16 Jan 2022)

Log Message

Enforce focus check for getUserMedia
https://bugs.webkit.org/show_bug.cgi?id=235026

Source/WebCore:

Reviewed by Eric Carlson.

Add infrastructure to register a callback so that a task is executed when the document is visible.
Use this to delay getUserMedia requests until document is visible.
The spec currently defines that we should wait for the current document to have focus but this is about to be changed and is not aligned with other browser implementations.

The patch also moves some getUserMedia checks earlier so as to respect order provided by the specs.
Add a check to validate getDisplayMedia is called on a visible document as the user gesture is now time based.

Covered by API test.

* Modules/mediastream/MediaDevices.cpp:
* Modules/mediastream/UserMediaRequest.cpp:
* Modules/mediastream/UserMediaRequest.h:
* dom/Document.cpp:
* dom/Document.h:
* editing/FrameSelection.cpp:

Source/WebKit:

Reviewed by Eric Carlson.

Add setters/getters for the getUserMedia focus settings.

* UIProcess/API/C/WKPreferences.cpp:
(WKPreferencesSetGetUserMediaRequiresFocus):
(WKPreferencesGetGetUserMediaRequiresFocus):
* UIProcess/API/C/WKPreferencesRefPrivate.h:
* UIProcess/API/Cocoa/WKPreferences.mm:
(-[WKPreferences _getUserMediaRequiresFocus]):
(-[WKPreferences _setGetUserMediaRequiresFocus:]):
* UIProcess/API/Cocoa/WKPreferencesPrivate.h:
* UIProcess/API/glib/WebKitSettings.cpp:
(webkitSettingsSetGetUserMediaRequiresFocus):
* UIProcess/API/glib/WebKitSettingsPrivate.h:
* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseMap): Always add the WindowIsActive flag under xvfb.
(webkitWebViewBaseIsFocused): Always consider the view focused when WindowIsActive flag is present under xvfb.

Source/WTF:

Reviewed by Eric Carlson.

* Scripts/Preferences/WebPreferencesInternal.yaml:

Tools:

Reviewed by Eric Carlson.

Disable focus flag for testing to not require to focus the window.

* TestWebKitAPI/Tests/WebKit/GetUserMedia.mm:
(TestWebKitAPI::initializeMediaCaptureConfiguration):
(TestWebKitAPI::doCaptureMuteTest):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKit/GetUserMediaNavigation.mm:
(TestWebKitAPI::initializeMediaCaptureConfiguration):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm:
(TestWebKitAPI::initializeMediaCaptureConfiguration):
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKit/MediaStreamTrackDetached.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKit/UserMedia.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/AudioBufferSize.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
(TEST):
* TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm:
(TestWebKitAPI::GetDisplayMediaTest::SetUp):
* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
* TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/UserMediaDisabled.mm:
(MediaCaptureDisabledTest::SetUp):
* TestWebKitAPI/Tests/WebKitCocoa/UserMediaSimulateFailedSandbox.mm:
(MediaCaptureSimulateFailedSandbox::SetUp):
* TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp:
(testWebViewUserMediaEnumerateDevicesPermissionCheck):
(testWebViewUserMediaPermissionRequests):
(testWebViewAudioOnlyUserMediaPermissionRequests):

LayoutTests:

Reviewed by Eric Carlson.

* fast/mediastream/MediaDevices-getUserMedia-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (288086 => 288087)


--- trunk/LayoutTests/ChangeLog	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/LayoutTests/ChangeLog	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1,5 +1,14 @@
 2022-01-16  Youenn Fablet  <you...@apple.com>
 
+        Enforce focus check for getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=235026
+
+        Reviewed by Eric Carlson.
+
+        * fast/mediastream/MediaDevices-getUserMedia-expected.txt:
+
+2022-01-16  Youenn Fablet  <you...@apple.com>
+
         Queue a task to fire MediaStreamTrack ended event
         https://bugs.webkit.org/show_bug.cgi?id=235227
 

Modified: trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt (288086 => 288087)


--- trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt	2022-01-17 06:44:44 UTC (rev 288087)
@@ -6,8 +6,8 @@
 PASS typeof navigator.mediaDevices.webkitGetUserMedia is 'undefined'
 
 PASS navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1); did not throw exception.
-PASS navigator.mediaDevices.getUserMedia() rejected with error: TypeError: Type error
-PASS navigator.mediaDevices.getUserMedia({}) rejected with error: TypeError: Type error
+PASS navigator.mediaDevices.getUserMedia() rejected with error: TypeError: No constraints provided
+PASS navigator.mediaDevices.getUserMedia({}) rejected with error: TypeError: No constraints provided
 PASS navigator.mediaDevices.getUserMedia.apply(undefined) rejected with error: TypeError: Can only call MediaDevices.getUserMedia on instances of MediaDevices
 PASS Stream 1 generated.
 PASS stream.getAudioTracks().length is 1

Modified: trunk/Source/WTF/ChangeLog (288086 => 288087)


--- trunk/Source/WTF/ChangeLog	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WTF/ChangeLog	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1,3 +1,12 @@
+2022-01-16  Youenn Fablet  <you...@apple.com>
+
+        Enforce focus check for getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=235026
+
+        Reviewed by Eric Carlson.
+
+        * Scripts/Preferences/WebPreferencesInternal.yaml:
+
 2022-01-16  Lauro Moura  <lmo...@igalia.com>
 
         Fix C++20 build warnings with GCC

Modified: trunk/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml (288086 => 288087)


--- trunk/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml	2022-01-17 06:44:44 UTC (rev 288087)
@@ -293,6 +293,19 @@
     WebCore:
       default: false
 
+GetUserMediaRequiresFocus:
+  type: bool
+  humanReadableName: "Require focus to start getUserMedia"
+  humanReadableDescription: "Require focus to start getUserMedia"
+  condition: ENABLE(MEDIA_STREAM)
+  defaultValue:
+    WebKitLegacy:
+      default: true
+    WebKit:
+      default: true
+    WebCore:
+      default: true
+
 ICECandidateFilteringEnabled:
   type: bool
   webcoreOnChange: iceCandidateFilteringEnabledChanged

Modified: trunk/Source/WebCore/ChangeLog (288086 => 288087)


--- trunk/Source/WebCore/ChangeLog	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebCore/ChangeLog	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1,5 +1,28 @@
 2022-01-16  Youenn Fablet  <you...@apple.com>
 
+        Enforce focus check for getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=235026
+
+        Reviewed by Eric Carlson.
+
+        Add infrastructure to register a callback so that a task is executed when the document is visible.
+        Use this to delay getUserMedia requests until document is visible.
+        The spec currently defines that we should wait for the current document to have focus but this is about to be changed and is not aligned with other browser implementations.
+
+        The patch also moves some getUserMedia checks earlier so as to respect order provided by the specs.
+        Add a check to validate getDisplayMedia is called on a visible document as the user gesture is now time based.
+
+        Covered by API test.
+
+        * Modules/mediastream/MediaDevices.cpp:
+        * Modules/mediastream/UserMediaRequest.cpp:
+        * Modules/mediastream/UserMediaRequest.h:
+        * dom/Document.cpp:
+        * dom/Document.h:
+        * editing/FrameSelection.cpp:
+
+2022-01-16  Youenn Fablet  <you...@apple.com>
+
         Queue a task to fire MediaStreamTrack ended event
         https://bugs.webkit.org/show_bug.cgi?id=235227
 

Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp (288086 => 288087)


--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -118,6 +118,14 @@
 
 void MediaDevices::getUserMedia(const StreamConstraints& constraints, Promise&& promise)
 {
+    auto audioConstraints = createMediaConstraints(constraints.audio);
+    auto videoConstraints = createMediaConstraints(constraints.video);
+
+    if (!audioConstraints.isValid && !videoConstraints.isValid) {
+        promise.reject(TypeError, "No constraints provided"_s);
+        return;
+    }
+
     auto* document = this->document();
     if (!document || !document->isFullyActive()) {
         promise.reject(Exception { InvalidStateError, "Document is not fully active"_s });
@@ -124,9 +132,6 @@
         return;
     }
 
-    auto audioConstraints = createMediaConstraints(constraints.audio);
-    auto videoConstraints = createMediaConstraints(constraints.video);
-
     bool isUserGesturePriviledged = false;
 
     if (audioConstraints.isValid)
@@ -138,9 +143,88 @@
     }
 
     auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::UserMedia, WTFMove(audioConstraints), WTFMove(videoConstraints), isUserGesturePriviledged }, WTFMove(promise));
-    request->start();
+
+    if (!document->settings().getUserMediaRequiresFocus()) {
+        request->start();
+        return;
+    }
+
+    // FIXME: We use hidden while the spec is using focus, let's revisit when when spec is made clearer.
+    document->whenVisible([request = WTFMove(request)] {
+        if (request->isContextStopped())
+            return;
+        request->start();
+    });
 }
 
+static bool hasInvalidGetDisplayMediaConstraint(const MediaConstraints& constraints)
+{
+    // https://w3c.github.io/mediacapture-screen-share/#navigator-additions
+    // 1. Let constraints be the method's first argument.
+    // 2. For each member present in constraints whose value, value, is a dictionary, run the following steps:
+    //     1. If value contains a member named advanced, return a promise rejected with a newly created TypeError.
+    //     2. If value contains a member which in turn is a dictionary containing a member named either min or
+    //        exact, return a promise rejected with a newly created TypeError.
+    if (!constraints.isValid)
+        return false;
+
+    if (!constraints.advancedConstraints.isEmpty())
+        return true;
+
+    bool invalid = false;
+    constraints.mandatoryConstraints.filter([&invalid] (const MediaConstraint& constraint) mutable {
+        switch (constraint.constraintType()) {
+        case MediaConstraintType::Width:
+        case MediaConstraintType::Height: {
+            auto& intConstraint = downcast<IntConstraint>(constraint);
+            int value;
+            invalid = intConstraint.getExact(value) || intConstraint.getMin(value);
+            break;
+        }
+
+        case MediaConstraintType::AspectRatio:
+        case MediaConstraintType::FrameRate: {
+            auto& doubleConstraint = downcast<DoubleConstraint>(constraint);
+            double value;
+            invalid = doubleConstraint.getExact(value) || doubleConstraint.getMin(value);
+            break;
+        }
+
+        case MediaConstraintType::DisplaySurface:
+        case MediaConstraintType::LogicalSurface: {
+            auto& boolConstraint = downcast<BooleanConstraint>(constraint);
+            bool value;
+            invalid = boolConstraint.getExact(value);
+            break;
+        }
+
+        case MediaConstraintType::FacingMode:
+        case MediaConstraintType::DeviceId:
+        case MediaConstraintType::GroupId: {
+            auto& stringConstraint = downcast<StringConstraint>(constraint);
+            Vector<String> values;
+            invalid = stringConstraint.getExact(values);
+            break;
+        }
+
+        case MediaConstraintType::SampleRate:
+        case MediaConstraintType::SampleSize:
+        case MediaConstraintType::Volume:
+        case MediaConstraintType::EchoCancellation:
+            // Ignored.
+            break;
+
+        case MediaConstraintType::Unknown:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+
+        return invalid;
+    });
+
+    return invalid;
+}
+
 void MediaDevices::getDisplayMedia(const DisplayMediaStreamConstraints& constraints, Promise&& promise)
 {
     auto* document = this->document();
@@ -153,7 +237,19 @@
         return;
     }
 
-    auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, { }, createMediaConstraints(constraints.video), isUserGesturePriviledged }, WTFMove(promise));
+    auto videoConstraints = createMediaConstraints(constraints.video);
+    if (hasInvalidGetDisplayMediaConstraint(videoConstraints)) {
+        promise.reject(Exception { TypeError, "getDisplayMedia must be called with valid constraints."_s });
+        return;
+    }
+
+    // FIXME: We use hidden while the spec is using focus, let's revisit when when spec is made clearer.
+    if (!document->isFullyActive() || document->topDocument().hidden()) {
+        promise.reject(Exception { InvalidStateError, "Document is not fully active or does not have focus"_s });
+        return;
+    }
+
+    auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, { }, WTFMove(videoConstraints), isUserGesturePriviledged }, WTFMove(promise));
     request->start();
 }
 

Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp (288086 => 288087)


--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -85,74 +85,6 @@
     return context ? &context->topOrigin() : nullptr;
 }
 
-static bool hasInvalidGetDisplayMediaConstraint(const MediaConstraints& constraints)
-{
-    // https://w3c.github.io/mediacapture-screen-share/#navigator-additions
-    // 1. Let constraints be the method's first argument.
-    // 2. For each member present in constraints whose value, value, is a dictionary, run the following steps:
-    //     1. If value contains a member named advanced, return a promise rejected with a newly created TypeError.
-    //     2. If value contains a member which in turn is a dictionary containing a member named either min or
-    //        exact, return a promise rejected with a newly created TypeError.
-    if (!constraints.isValid)
-        return false;
-
-    if (!constraints.advancedConstraints.isEmpty())
-        return true;
-
-    bool invalid = false;
-    constraints.mandatoryConstraints.filter([&invalid] (const MediaConstraint& constraint) mutable {
-        switch (constraint.constraintType()) {
-        case MediaConstraintType::Width:
-        case MediaConstraintType::Height: {
-            auto& intConstraint = downcast<IntConstraint>(constraint);
-            int value;
-            invalid = intConstraint.getExact(value) || intConstraint.getMin(value);
-            break;
-        }
-
-        case MediaConstraintType::AspectRatio:
-        case MediaConstraintType::FrameRate: {
-            auto& doubleConstraint = downcast<DoubleConstraint>(constraint);
-            double value;
-            invalid = doubleConstraint.getExact(value) || doubleConstraint.getMin(value);
-            break;
-        }
-
-        case MediaConstraintType::DisplaySurface:
-        case MediaConstraintType::LogicalSurface: {
-            auto& boolConstraint = downcast<BooleanConstraint>(constraint);
-            bool value;
-            invalid = boolConstraint.getExact(value);
-            break;
-        }
-
-        case MediaConstraintType::FacingMode:
-        case MediaConstraintType::DeviceId:
-        case MediaConstraintType::GroupId: {
-            auto& stringConstraint = downcast<StringConstraint>(constraint);
-            Vector<String> values;
-            invalid = stringConstraint.getExact(values);
-            break;
-        }
-
-        case MediaConstraintType::SampleRate:
-        case MediaConstraintType::SampleSize:
-        case MediaConstraintType::Volume:
-        case MediaConstraintType::EchoCancellation:
-            // Ignored.
-            break;
-
-        case MediaConstraintType::Unknown:
-            ASSERT_NOT_REACHED();
-            break;
-        }
-
-        return invalid;
-    });
-
-    return invalid;
-}
-
 void UserMediaRequest::start()
 {
     auto* context = scriptExecutionContext();
@@ -162,25 +94,6 @@
         return;
     }
 
-    if (m_request.type == MediaStreamRequest::Type::DisplayMedia) {
-        if (hasInvalidGetDisplayMediaConstraint(m_request.videoConstraints)) {
-            deny(MediaAccessDenialReason::IllegalConstraint);
-            return;
-        }
-    }
-
-    // https://w3c.github.io/mediacapture-main/getusermedia.html#dom-mediadevices-getusermedia()
-    // 1. Let constraints be the method's first argument.
-    // 2. Let requestedMediaTypes be the set of media types in constraints with either a dictionary
-    //    value or a value of "true".
-    // 3. If requestedMediaTypes is the empty set, return a promise rejected with a TypeError. The word
-    //    "optional" occurs in the WebIDL due to WebIDL rules, but the argument must be supplied in order
-    //    for the call to succeed.
-    if (!m_request.audioConstraints.isValid && !m_request.videoConstraints.isValid) {
-        deny(MediaAccessDenialReason::NoConstraints);
-        return;
-    }
-
     // 4. If the current settings object's responsible document is NOT allowed to use the feature indicated by
     //    attribute name allowusermedia, return a promise rejected with a DOMException object whose name
     //    attribute has the value SecurityError.
@@ -289,10 +202,6 @@
 
     ExceptionCode code;
     switch (reason) {
-    case MediaAccessDenialReason::IllegalConstraint:
-        RELEASE_LOG(MediaStream, "UserMediaRequest::deny - invalid constraints");
-        code = TypeError;
-        break;
     case MediaAccessDenialReason::NoConstraints:
         RELEASE_LOG(MediaStream, "UserMediaRequest::deny - no constraints");
         code = TypeError;

Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h (288086 => 288087)


--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h	2022-01-17 06:44:44 UTC (rev 288087)
@@ -63,7 +63,7 @@
     WEBCORE_EXPORT void setAllowedMediaDeviceUIDs(const String& audioDeviceUID, const String& videoDeviceUID);
     WEBCORE_EXPORT void allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt, CompletionHandler<void()>&&);
 
-    enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, InvalidAccess, IllegalConstraint, OtherFailure };
+    enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, InvalidAccess, OtherFailure };
     WEBCORE_EXPORT void deny(MediaAccessDenialReason, const String& errorMessage = emptyString());
 
     const Vector<String>& audioDeviceUIDs() const { return m_audioDeviceUIDs; }

Modified: trunk/Source/WebCore/dom/Document.cpp (288086 => 288087)


--- trunk/Source/WebCore/dom/Document.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebCore/dom/Document.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1872,6 +1872,12 @@
             MediaStreamTrack::updateCaptureAccordingToMutedState(*this);
     }
 #endif
+
+    if (!hidden()) {
+        auto callbacks = std::exchange(m_whenIsVisibleHandlers, { });
+        for (auto& callback : callbacks)
+            callback();
+    }
 }
 
 VisibilityState Document::visibilityState() const
@@ -9095,6 +9101,15 @@
     return ts;
 }
 
+void Document::whenVisible(Function<void()>&& callback)
+{
+    if (hidden()) {
+        m_whenIsVisibleHandlers.append(WTFMove(callback));
+        return;
+    }
+    callback();
+}
+
 } // namespace WebCore
 
 #undef DOCUMENT_RELEASE_LOG

Modified: trunk/Source/WebCore/dom/Document.h (288086 => 288087)


--- trunk/Source/WebCore/dom/Document.h	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebCore/dom/Document.h	2022-01-17 06:44:44 UTC (rev 288087)
@@ -429,6 +429,7 @@
 
     WEBCORE_EXPORT Element* activeElement();
     WEBCORE_EXPORT bool hasFocus() const;
+    void whenVisible(Function<void()>&&);
 
     bool hasManifest() const;
     
@@ -2261,6 +2262,8 @@
 #endif
 
     std::unique_ptr<ModalContainerObserver> m_modalContainerObserver;
+
+    Vector<Function<void()>> m_whenIsVisibleHandlers;
 };
 
 Element* eventTargetElementForDocument(Document*);

Modified: trunk/Source/WebKit/ChangeLog (288086 => 288087)


--- trunk/Source/WebKit/ChangeLog	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/ChangeLog	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1,3 +1,27 @@
+2022-01-16  Youenn Fablet  <you...@apple.com> and Carlos Garcia Campos  <cgar...@igalia.com>
+
+        Enforce focus check for getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=235026
+
+        Reviewed by Eric Carlson.
+
+        Add setters/getters for the getUserMedia focus settings.
+
+        * UIProcess/API/C/WKPreferences.cpp:
+        (WKPreferencesSetGetUserMediaRequiresFocus):
+        (WKPreferencesGetGetUserMediaRequiresFocus):
+        * UIProcess/API/C/WKPreferencesRefPrivate.h:
+        * UIProcess/API/Cocoa/WKPreferences.mm:
+        (-[WKPreferences _getUserMediaRequiresFocus]):
+        (-[WKPreferences _setGetUserMediaRequiresFocus:]):
+        * UIProcess/API/Cocoa/WKPreferencesPrivate.h:
+        * UIProcess/API/glib/WebKitSettings.cpp:
+        (webkitSettingsSetGetUserMediaRequiresFocus):
+        * UIProcess/API/glib/WebKitSettingsPrivate.h:
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (webkitWebViewBaseMap): Always add the WindowIsActive flag under xvfb.
+        (webkitWebViewBaseIsFocused): Always consider the view focused when WindowIsActive flag is present under xvfb.
+
 2022-01-16  Lauro Moura  <lmo...@igalia.com>
 
         Fix C++20 build warnings with GCC

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp (288086 => 288087)


--- trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1526,6 +1526,16 @@
     return toImpl(preferencesRef)->mockCaptureDevicesEnabled();
 }
 
+void WKPreferencesSetGetUserMediaRequiresFocus(WKPreferencesRef preferencesRef, bool enabled)
+{
+    toImpl(preferencesRef)->setGetUserMediaRequiresFocus(enabled);
+}
+
+bool WKPreferencesGetGetUserMediaRequiresFocus(WKPreferencesRef preferencesRef)
+{
+    return toImpl(preferencesRef)->getUserMediaRequiresFocus();
+}
+
 void WKPreferencesSetICECandidateFilteringEnabled(WKPreferencesRef preferencesRef, bool enabled)
 {
     toImpl(preferencesRef)->setICECandidateFilteringEnabled(enabled);

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h (288086 => 288087)


--- trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h	2022-01-17 06:44:44 UTC (rev 288087)
@@ -399,6 +399,10 @@
 WK_EXPORT bool WKPreferencesGetMockCaptureDevicesEnabled(WKPreferencesRef);
 
 // Defaults to true.
+WK_EXPORT void WKPreferencesSetGetUserMediaRequiresFocus(WKPreferencesRef, bool);
+WK_EXPORT bool WKPreferencesGetGetUserMediaRequiresFocus(WKPreferencesRef);
+
+// Defaults to true.
 WK_EXPORT void WKPreferencesSetICECandidateFilteringEnabled(WKPreferencesRef, bool);
 WK_EXPORT bool WKPreferencesGetICECandidateFilteringEnabled(WKPreferencesRef);
 

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm (288086 => 288087)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -650,6 +650,16 @@
     _preferences->setMediaDevicesEnabled(enabled);
 }
 
+- (BOOL)_getUserMediaRequiresFocus
+{
+    return _preferences->getUserMediaRequiresFocus();
+}
+
+- (void)_setGetUserMediaRequiresFocus:(BOOL)enabled
+{
+    _preferences->setGetUserMediaRequiresFocus(enabled);
+}
+
 - (BOOL)_screenCaptureEnabled
 {
     return _preferences->screenCaptureEnabled();

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h (288086 => 288087)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h	2022-01-17 06:44:44 UTC (rev 288087)
@@ -117,6 +117,7 @@
 
 @property (nonatomic, setter=_setPeerConnectionEnabled:) BOOL _peerConnectionEnabled WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
 @property (nonatomic, setter=_setMediaDevicesEnabled:) BOOL _mediaDevicesEnabled WK_API_AVAILABLE(macos(10.13), ios(11.0));
+@property (nonatomic, setter=_setGetUserMediaRequiresFocus:) BOOL _getUserMediaRequiresFocus WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 @property (nonatomic, setter=_setScreenCaptureEnabled:) BOOL _screenCaptureEnabled WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
 @property (nonatomic, setter=_setMockCaptureDevicesEnabled:) BOOL _mockCaptureDevicesEnabled WK_API_AVAILABLE(macos(10.13), ios(11.0));
 @property (nonatomic, setter=_setMockCaptureDevicesPromptEnabled:) BOOL _mockCaptureDevicesPromptEnabled WK_API_AVAILABLE(macos(10.13.4), ios(11.3));

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp (288086 => 288087)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitSettings.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -3827,6 +3827,12 @@
     priv->preferences->setMediaCaptureRequiresSecureConnection(required);
 }
 
+void webkitSettingsSetGetUserMediaRequiresFocus(WebKitSettings* settings, bool required)
+{
+    WebKitSettingsPrivate* priv = settings->priv;
+    priv->preferences->setGetUserMediaRequiresFocus(required);
+}
+
 /**
  * webkit_settings_get_media_content_types_requiring_hardware_support:
  * @settings: a #WebKitSettings

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitSettingsPrivate.h (288086 => 288087)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitSettingsPrivate.h	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitSettingsPrivate.h	2022-01-17 06:44:44 UTC (rev 288087)
@@ -33,5 +33,6 @@
 WebKit::WebPreferences* webkitSettingsGetPreferences(WebKitSettings*);
 
 WK_EXPORT void webkitSettingsSetMediaCaptureRequiresSecureConnection(WebKitSettings*, bool required);
+WK_EXPORT void webkitSettingsSetGetUserMediaRequiresFocus(WebKitSettings*, bool required);
 
 #endif // WebKitSettingsPrivate_h

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp (288086 => 288087)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -911,6 +911,16 @@
     if (priv->toplevelOnScreenWindow) {
         if (!(priv->activityState & ActivityState::IsInWindow))
             flagsToUpdate.add(ActivityState::IsInWindow);
+
+#if ENABLE(DEVELOPER_MODE)
+        // Xvfb doesn't support toplevel focus, so gtk_window_is_active() always returns false. We consider
+        // toplevel window to be always active since it's the only one.
+        if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::X11) {
+            if (!g_strcmp0(g_getenv("UNDER_XVFB"), "yes"))
+                flagsToUpdate.add(ActivityState::WindowIsActive);
+        }
+#endif
+
         if (gtk_window_is_active(GTK_WINDOW(priv->toplevelOnScreenWindow)) && !(priv->activityState & ActivityState::WindowIsActive))
             flagsToUpdate.add(ActivityState::WindowIsActive);
     }
@@ -2429,6 +2439,14 @@
 
 bool webkitWebViewBaseIsFocused(WebKitWebViewBase* webViewBase)
 {
+#if ENABLE(DEVELOPER_MODE)
+    // Xvfb doesn't support toplevel focus, so the view is never focused. We consider it to tbe focused when
+    // its window is marked as active.
+    if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::X11) {
+        if (!g_strcmp0(g_getenv("UNDER_XVFB"), "yes") && webViewBase->priv->activityState.contains(ActivityState::WindowIsActive))
+            return true;
+    }
+#endif
     return webViewBase->priv->activityState.contains(ActivityState::IsFocused);
 }
 

Modified: trunk/Tools/ChangeLog (288086 => 288087)


--- trunk/Tools/ChangeLog	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/ChangeLog	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1,3 +1,44 @@
+2022-01-16  Youenn Fablet  <you...@apple.com>
+
+        Enforce focus check for getUserMedia
+        https://bugs.webkit.org/show_bug.cgi?id=235026
+
+        Reviewed by Eric Carlson.
+
+        Disable focus flag for testing to not require to focus the window.
+
+        * TestWebKitAPI/Tests/WebKit/GetUserMedia.mm:
+        (TestWebKitAPI::initializeMediaCaptureConfiguration):
+        (TestWebKitAPI::doCaptureMuteTest):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKit/GetUserMediaNavigation.mm:
+        (TestWebKitAPI::initializeMediaCaptureConfiguration):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm:
+        (TestWebKitAPI::initializeMediaCaptureConfiguration):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKit/MediaStreamTrackDetached.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKit/UserMedia.cpp:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/AudioBufferSize.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
+        (TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm:
+        (TestWebKitAPI::GetDisplayMediaTest::SetUp):
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        * TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/UserMediaDisabled.mm:
+        (MediaCaptureDisabledTest::SetUp):
+        * TestWebKitAPI/Tests/WebKitCocoa/UserMediaSimulateFailedSandbox.mm:
+        (MediaCaptureSimulateFailedSandbox::SetUp):
+        * TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp:
+        (testWebViewUserMediaEnumerateDevicesPermissionCheck):
+        (testWebViewUserMediaPermissionRequests):
+        (testWebViewAudioOnlyUserMediaPermissionRequests):
+
 2022-01-15  Sam Weinig  <wei...@apple.com>
 
         CSS Gradients: interpolation mode should default to OKLab if any non-legacy color syntax colors are used in the stops

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -152,14 +152,21 @@
     return false;
 }
 
+static void initializeMediaCaptureConfiguration(WKWebViewConfiguration* configuration)
+{
+    auto preferences = [configuration preferences];
+
+    configuration._mediaCaptureEnabled = YES;
+    preferences._mediaCaptureRequiresSecureConnection = NO;
+    preferences._mockCaptureDevicesEnabled = YES;
+    preferences._getUserMediaRequiresFocus = NO;
+}
+
 void doCaptureMuteTest(const Function<void(TestWKWebView*, _WKMediaMutedState)>& setPageMuted)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];
@@ -235,10 +242,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];
@@ -340,10 +344,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration.get() userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -378,10 +379,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration.get() userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -414,10 +412,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration.get() userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -442,10 +437,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration.get() userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -473,10 +465,7 @@
     [configuration setAllowsInlineMediaPlayback:YES];
 #endif
 
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -532,10 +521,7 @@
     [configuration setAllowsInlineMediaPlayback:YES];
 #endif
 
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     done = false;
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
@@ -555,10 +541,7 @@
     configuration.get().processPool = (WKProcessPool *)context.get();
     configuration.get().processPool._configuration.shouldCaptureAudioInUIProcess = NO;
 
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration.get() userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -591,9 +574,7 @@
             [preferences _setEnabled:YES forInternalDebugFeature:feature];
     }
 
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -666,9 +647,7 @@
         if ([feature.key isEqualToString:@"CaptureVideoInGPUProcessEnabled"])
             [preferences _setEnabled:YES forInternalDebugFeature:feature];
     }
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
 #if PLATFORM(IOS_FAMILY)
     [configuration setAllowsInlineMediaPlayback:YES];
@@ -746,9 +725,7 @@
             [preferences _setEnabled:YES forFeature:feature];
     }
 
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
@@ -867,10 +844,7 @@
     auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
     [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
 
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
 
     done = false;
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
@@ -898,6 +872,70 @@
     [webView stringByEvaluatingJavaScript:@"doTest()"];
     TestWebKitAPI::Util::run(&done);
 }
+
+static const char* getUserMediaFocusText = R"DOCDOCDOC(
+<html><body>
+<script>
+_onload_ = () => {
+    document._onvisibilitychange_ = () => window.webkit.messageHandlers.gum.postMessage("PASS");
+    window.webkit.messageHandlers.gum.postMessage("PASS");
+}
+
+function capture()
+{
+    navigator.mediaDevices.getUserMedia({video : true}).then(stream => {
+        window.webkit.messageHandlers.gum.postMessage(document.hasFocus() ? "PASS" : "FAIL");
+    });
+}
+</script>
+</body></html>
+)DOCDOCDOC";
+
+TEST(WebKit, GetUserMediaFocus)
+{
+    TestWebKitAPI::HTTPServer server({
+        { "/", { getUserMediaFocusText } }
+    }, TestWebKitAPI::HTTPServer::Protocol::Http, nullptr, nullptr, 9090);
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+    auto context = adoptWK(TestWebKitAPI::Util::createContextForInjectedBundleTest("InternalsInjectedBundleTest"));
+    configuration.get().processPool = (WKProcessPool *)context.get();
+
+    auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"];
+
+    initializeMediaCaptureConfiguration(configuration.get());
+    auto preferences = [configuration preferences];
+    preferences._getUserMediaRequiresFocus = YES;
+
+    done = false;
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
+
+    auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);
+    webView.get().UIDelegate = delegate.get();
+
+    // Load page.
+    [webView loadRequest:server.request()];
+    TestWebKitAPI::Util::run(&done);
+
+    // Minimize
+    done = false;
+    auto *hostWindow = [webView hostWindow];
+    [hostWindow miniaturize:hostWindow];
+    TestWebKitAPI::Util::run(&done);
+
+    // We call capture while minimizing.
+    done = false;
+    [webView stringByEvaluatingJavaScript:@"capture()"];
+
+    // Make sure that getUserMedia does not resolve too soon.
+    TestWebKitAPI::Util::spinRunLoop(100);
+    EXPECT_FALSE(done);
+
+    [hostWindow deminiaturize:hostWindow];
+    TestWebKitAPI::Util::run(&done);
+}
 #endif // PLATFORM(MAC)
 
 TEST(WebKit, InvalidDeviceIdHashSalts)
@@ -924,10 +962,7 @@
 
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     [configuration setWebsiteDataStore:adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]).get()];
-    auto preferences = [configuration preferences];
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get()]);
     auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaNavigation.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaNavigation.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaNavigation.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -67,6 +67,16 @@
 
 namespace TestWebKitAPI {
 
+static void initializeMediaCaptureConfiguration(WKWebViewConfiguration* configuration)
+{
+    auto preferences = [configuration preferences];
+
+    configuration._mediaCaptureEnabled = YES;
+    preferences._mediaCaptureRequiresSecureConnection = NO;
+    preferences._mockCaptureDevicesEnabled = YES;
+    preferences._getUserMediaRequiresFocus = NO;
+}
+
 TEST(WebKit, NavigateDuringGetUserMediaPrompt)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
@@ -88,10 +98,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[NavigationWhileGetUserMediaPromptDisplayedUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];
@@ -117,10 +124,7 @@
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     [configuration setWebsiteDataStore:adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]).get()];
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[NavigationWhileGetUserMediaPromptDisplayedUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];
@@ -147,10 +151,7 @@
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     [configuration setWebsiteDataStore:adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]).get()];
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[NavigationWhileGetUserMediaPromptDisplayedUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -60,14 +60,22 @@
 
 namespace TestWebKitAPI {
 
+static void initializeMediaCaptureConfiguration(WKWebViewConfiguration* configuration)
+{
+    auto preferences = [configuration preferences];
+
+    configuration._mediaCaptureEnabled = YES;
+    preferences._mediaCaptureRequiresSecureConnection = NO;
+    preferences._mockCaptureDevicesEnabled = YES;
+    preferences._getUserMediaRequiresFocus = NO;
+}
+
 TEST(WebKit2, GetUserMediaReprompt)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
     auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[GetUserMediaRepromptTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];
@@ -100,10 +108,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[GetUserMediaRepromptTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);
     [delegate setAudioDecision:WKPermissionDecisionGrant];
@@ -123,10 +128,7 @@
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
-    auto preferences = [configuration preferences];
-    preferences._mediaCaptureRequiresSecureConnection = NO;
-    configuration.get()._mediaCaptureEnabled = YES;
-    preferences._mockCaptureDevicesEnabled = YES;
+    initializeMediaCaptureConfiguration(configuration.get());
     auto webView = adoptNS([[GetUserMediaRepromptTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);
     [webView setUIDelegate:delegate.get()];

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaStreamTrackDetached.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaStreamTrackDetached.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaStreamTrackDetached.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -61,6 +61,7 @@
     preferences._mediaCaptureRequiresSecureConnection = NO;
     configuration.get()._mediaCaptureEnabled = YES;
     preferences._mockCaptureDevicesEnabled = YES;
+    preferences._getUserMediaRequiresFocus = NO;
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
     auto delegate = adoptNS([[MediaStreamTrackDetachedUIDelegate alloc] init]);
     webView.get().UIDelegate = delegate.get();

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/UserMedia.cpp (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit/UserMedia.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/UserMedia.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -77,6 +77,7 @@
     WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
     WKPreferencesSetMediaCaptureRequiresSecureConnection(preferences, false);
     WKPreferencesSetMockCaptureDevicesEnabled(preferences, true);
+    WKPreferencesSetGetUserMediaRequiresFocus(preferences, false);
 
     WKPageUIClientV6 uiClient;
     memset(&uiClient, 0, sizeof(uiClient));
@@ -113,6 +114,7 @@
     WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
     WKPreferencesSetMediaCaptureRequiresSecureConnection(preferences, false);
     WKPreferencesSetMockCaptureDevicesEnabled(preferences, true);
+    WKPreferencesSetGetUserMediaRequiresFocus(preferences, false);
 
     WKPageUIClientV6 uiClient;
     memset(&uiClient, 0, sizeof(uiClient));
@@ -173,6 +175,7 @@
     WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
     WKPreferencesSetMediaCaptureRequiresSecureConnection(preferences, false);
     WKPreferencesSetMockCaptureDevicesEnabled(preferences, true);
+    WKPreferencesSetGetUserMediaRequiresFocus(preferences, false);
 
     WKPageUIClientV6 uiClient;
     // We want uiClient.checkUserMediaPermissionForOrigin to be null.

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AudioBufferSize.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AudioBufferSize.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AudioBufferSize.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -72,6 +72,7 @@
     auto preferences = [configuration preferences];
     preferences._mediaCaptureRequiresSecureConnection = NO;
     preferences._mockCaptureDevicesEnabled = YES;
+    preferences._getUserMediaRequiresFocus = NO;
 
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() addToWindow:YES]);
     auto delegate = adoptNS([[UserMediaCaptureUIDelegate alloc] init]);

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -696,6 +696,7 @@
         preferences._mediaCaptureRequiresSecureConnection = NO;
         configuration._mediaCaptureEnabled = YES;
         preferences._mockCaptureDevicesEnabled = YES;
+        preferences._getUserMediaRequiresFocus = NO;
     });
 }
 #endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -104,10 +104,11 @@
         preferences._mockCaptureDevicesEnabled = YES;
         preferences._screenCaptureEnabled = YES;
 
-        m_webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:m_configuration.get()]);
+        m_webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:m_configuration.get() addToWindow:YES]);
 
         m_uiDelegate = adoptNS([[GetDisplayMediaUIDelegate alloc] init]);
         m_webView.get().UIDelegate = m_uiDelegate.get();
+        [m_webView focus];
 
         [m_webView synchronouslyLoadTestPageNamed:@"getDisplayMedia"];
     }

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -6828,6 +6828,7 @@
     preferences._mediaCaptureRequiresSecureConnection = NO;
     webViewConfiguration.get()._mediaCaptureEnabled = YES;
     preferences._mockCaptureDevicesEnabled = YES;
+    preferences._getUserMediaRequiresFocus = NO;
 
     [webViewConfiguration setProcessPool:processPool.get()];
     auto handler = adoptNS([[PSONScheme alloc] init]);

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/SpeechRecognition.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -162,6 +162,7 @@
     preferences._mockCaptureDevicesEnabled = YES;
     preferences._speechRecognitionEnabled = YES;
     preferences._mediaCaptureRequiresSecureConnection = NO;
+    preferences._getUserMediaRequiresFocus = NO;
     auto delegate = adoptNS([[SpeechRecognitionUIDelegate alloc] init]);
     auto firstWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration.get()]);
     [firstWebView setUIDelegate:delegate.get()];

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserMediaDisabled.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserMediaDisabled.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserMediaDisabled.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -82,6 +82,7 @@
         auto preferences = [m_webView configuration].preferences;
         preferences._mockCaptureDevicesEnabled = YES;
         preferences._mediaCaptureRequiresSecureConnection = NO;
+        preferences._getUserMediaRequiresFocus = NO;
 
         m_uiDelegate = adoptNS([[UserMediaUIDelegate alloc] init]);
         [m_webView setUIDelegate:m_uiDelegate.get()];

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserMediaSimulateFailedSandbox.mm (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserMediaSimulateFailedSandbox.mm	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/UserMediaSimulateFailedSandbox.mm	2022-01-17 06:44:44 UTC (rev 288087)
@@ -83,6 +83,7 @@
         auto preferences = [m_webView configuration].preferences;
         preferences._mockCaptureDevicesEnabled = YES;
         preferences._mediaCaptureRequiresSecureConnection = NO;
+        preferences._getUserMediaRequiresFocus = NO;
 
         m_uiDelegate = adoptNS([[SimulateFailedSandboxUIDelegate alloc] init]);
         [m_webView setUIDelegate:m_uiDelegate.get()];

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp (288086 => 288087)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp	2022-01-17 06:41:57 UTC (rev 288086)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp	2022-01-17 06:44:44 UTC (rev 288087)
@@ -1002,6 +1002,7 @@
     gboolean enabled = webkit_settings_get_enable_media_stream(settings);
     webkit_settings_set_enable_media_stream(settings, TRUE);
     webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, FALSE);
+    webkitSettingsSetGetUserMediaRequiresFocus(settings, FALSE);
     webkit_settings_set_enable_mock_capture_devices(settings, TRUE);
 
     test->showInWindow();
@@ -1037,6 +1038,7 @@
     webkit_settings_set_enable_media_stream(settings, enabled);
     webkit_settings_set_enable_mock_capture_devices(settings, FALSE);
     webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, TRUE);
+    webkitSettingsSetGetUserMediaRequiresFocus(settings, TRUE);
 }
 
 static void testWebViewUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
@@ -1046,6 +1048,7 @@
     webkit_settings_set_enable_media_stream(settings, TRUE);
     webkit_settings_set_enable_mock_capture_devices(settings, TRUE);
     webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, FALSE);
+    webkitSettingsSetGetUserMediaRequiresFocus(settings, FALSE);
 
     test->showInWindow();
     static const char* userMediaRequestHTML = "<html>"
@@ -1105,6 +1108,7 @@
     webkit_settings_set_enable_media_stream(settings, enabled);
     webkit_settings_set_enable_mock_capture_devices(settings, FALSE);
     webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, TRUE);
+    webkitSettingsSetGetUserMediaRequiresFocus(settings, TRUE);
 }
 
 static void testWebViewAudioOnlyUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
@@ -1114,6 +1118,7 @@
     webkit_settings_set_enable_media_stream(settings, TRUE);
     webkit_settings_set_enable_mock_capture_devices(settings, TRUE);
     webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, FALSE);
+    webkitSettingsSetGetUserMediaRequiresFocus(settings, FALSE);
 
     test->showInWindow();
     static const char* userMediaRequestHTML = "<html>"
@@ -1144,6 +1149,7 @@
     webkit_settings_set_enable_media_stream(settings, enabled);
     webkit_settings_set_enable_mock_capture_devices(settings, FALSE);
     webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, TRUE);
+    webkitSettingsSetGetUserMediaRequiresFocus(settings, TRUE);
 }
 
 static void testWebViewDisplayUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to