Changeset 251639 in webkit


Ignore:
Timestamp:
Oct 26, 2019 1:50:40 PM (5 years ago)
Author:
youenn@apple.com
Message:

Enforce user gesture for getUserMedia in case a previous getUserMedia call was denied
https://bugs.webkit.org/show_bug.cgi?id=203362

Reviewed by Eric Carlson.

Source/WebCore:

Compute whether a media request is user priviledged or not.
It is priviledged if it is created as part of a user gesture and no request of the same type
has been previously created for the same user gesture.
If getDisplayMedia is called twice as part of a single user gesture, getDisplaMedia will reject for the second call.

Test: fast/mediastream/getUserMedia-deny-persistency5.html and updated test.

  • Modules/mediastream/MediaDevices.cpp:

(WebCore::MediaDevices::computeUserGesturePriviledge):
(WebCore::MediaDevices::getUserMedia):
(WebCore::MediaDevices::getDisplayMedia):
(WebCore::MediaDevices::getUserMedia const): Deleted.
(WebCore::MediaDevices::getDisplayMedia const): Deleted.

  • Modules/mediastream/MediaDevices.h:
  • platform/mediastream/MediaStreamRequest.h:

(WebCore::MediaStreamRequest::encode const):
(WebCore::MediaStreamRequest::decode):

Source/WebKit:

In case the request has user gesture priviledge, do not look at denied request history.

  • UIProcess/UserMediaPermissionRequestManagerProxy.cpp:

(WebKit::UserMediaPermissionRequestManagerProxy::getRequestAction):

  • UIProcess/UserMediaPermissionRequestProxy.h:

(WebKit::UserMediaPermissionRequestProxy::isUserGesturePriviledged const):

Tools:

Update test to take into account the ability to reask permission.

  • TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm:

(TestWebKitAPI::TEST_F):

LayoutTests:

  • fast/mediastream/getUserMedia-deny-persistency5-expected.txt:
  • fast/mediastream/getUserMedia-deny-persistency5.html:
  • fast/mediastream/screencapture-user-gesture-expected.txt:
  • fast/mediastream/screencapture-user-gesture.html:
Location:
trunk
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r251637 r251639  
     12019-10-26  youenn fablet  <youenn@apple.com>
     2
     3        Enforce user gesture for getUserMedia in case a previous getUserMedia call was denied
     4        https://bugs.webkit.org/show_bug.cgi?id=203362
     5
     6        Reviewed by Eric Carlson.
     7
     8        * fast/mediastream/getUserMedia-deny-persistency5-expected.txt:
     9        * fast/mediastream/getUserMedia-deny-persistency5.html:
     10        * fast/mediastream/screencapture-user-gesture-expected.txt:
     11        * fast/mediastream/screencapture-user-gesture.html:
     12
    1132019-10-26  Rob Buis  <rbuis@igalia.com>
    214
  • trunk/LayoutTests/fast/mediastream/screencapture-user-gesture-expected.txt

    r244749 r251639  
    11
    22PASS Allow getDisplayMedia call in case of user gesture
     3PASS Disallow getDisplayMedia calls in case of user gesture if not the first call
    34PASS Deny getDisplayMedia call if no user gesture
    45
  • trunk/LayoutTests/fast/mediastream/screencapture-user-gesture.html

    r244749 r251639  
    1313}, "Allow getDisplayMedia call in case of user gesture");
    1414
     15promise_test(() => {
     16    let promise;
     17    internals.withUserGesture(() => {
     18        const promise1 = navigator.mediaDevices.getDisplayMedia({video : true});
     19        const promise2 = navigator.mediaDevices.getDisplayMedia({video : true}).then(() => {
     20            return Promise.reject("Second promise should reject");
     21        }, () => {
     22            return "Second promise rejected";
     23        });
     24        promise = Promise.all([promise1, promise2]);
     25    });
     26    return promise;
     27}, "Disallow getDisplayMedia calls in case of user gesture if not the first call");
     28
     29
    1530promise_test((test) => {
    1631    return promise_rejects(test, "InvalidAccessError", navigator.mediaDevices.getDisplayMedia({video : true}));
  • trunk/Source/WebCore/ChangeLog

    r251638 r251639  
     12019-10-26  youenn fablet  <youenn@apple.com>
     2
     3        Enforce user gesture for getUserMedia in case a previous getUserMedia call was denied
     4        https://bugs.webkit.org/show_bug.cgi?id=203362
     5
     6        Reviewed by Eric Carlson.
     7
     8        Compute whether a media request is user priviledged or not.
     9        It is priviledged if it is created as part of a user gesture and no request of the same type
     10        has been previously created for the same user gesture.
     11        If getDisplayMedia is called twice as part of a single user gesture, getDisplaMedia will reject for the second call.
     12
     13        Test: fast/mediastream/getUserMedia-deny-persistency5.html and updated test.
     14
     15        * Modules/mediastream/MediaDevices.cpp:
     16        (WebCore::MediaDevices::computeUserGesturePriviledge):
     17        (WebCore::MediaDevices::getUserMedia):
     18        (WebCore::MediaDevices::getDisplayMedia):
     19        (WebCore::MediaDevices::getUserMedia const): Deleted.
     20        (WebCore::MediaDevices::getDisplayMedia const): Deleted.
     21        * Modules/mediastream/MediaDevices.h:
     22        * platform/mediastream/MediaStreamRequest.h:
     23        (WebCore::MediaStreamRequest::encode const):
     24        (WebCore::MediaStreamRequest::decode):
     25
    1262019-10-26  Zalan Bujtas  <zalan@apple.com>
    227
  • trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp

    r251244 r251639  
    4242#include "MediaTrackSupportedConstraints.h"
    4343#include "RealtimeMediaSourceSettings.h"
     44#include "UserGestureIndicator.h"
    4445#include "UserMediaController.h"
    4546#include "UserMediaRequest.h"
     
    105106}
    106107
    107 void MediaDevices::getUserMedia(const StreamConstraints& constraints, Promise&& promise) const
     108bool MediaDevices::computeUserGesturePriviledge(GestureAllowedRequest requestType)
     109{
     110    auto* currentGestureToken = UserGestureIndicator::currentUserGesture().get();
     111    if (m_currentGestureToken != currentGestureToken) {
     112        m_currentGestureToken = currentGestureToken;
     113        m_requestTypesForCurrentGesture = { };
     114    }
     115
     116    bool isUserGesturePriviledged = m_currentGestureToken && !m_requestTypesForCurrentGesture.contains(requestType);
     117    m_requestTypesForCurrentGesture.add(requestType);
     118    return isUserGesturePriviledged;
     119}
     120
     121void MediaDevices::getUserMedia(const StreamConstraints& constraints, Promise&& promise)
    108122{
    109123    auto* document = this->document();
     
    113127    auto audioConstraints = createMediaConstraints(constraints.audio);
    114128    auto videoConstraints = createMediaConstraints(constraints.video);
    115     if (videoConstraints.isValid)
     129
     130    bool isUserGesturePriviledged = false;
     131
     132    if (audioConstraints.isValid)
     133        isUserGesturePriviledged |= computeUserGesturePriviledge(GestureAllowedRequest::Microphone);
     134
     135    if (videoConstraints.isValid) {
     136        isUserGesturePriviledged |= computeUserGesturePriviledge(GestureAllowedRequest::Camera);
    116137        videoConstraints.setDefaultVideoConstraints();
    117 
    118     auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::UserMedia, WTFMove(audioConstraints), WTFMove(videoConstraints) }, WTFMove(promise));
     138    }
     139
     140    auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::UserMedia, WTFMove(audioConstraints), WTFMove(videoConstraints), isUserGesturePriviledged }, WTFMove(promise));
    119141    request->start();
    120142}
    121143
    122 void MediaDevices::getDisplayMedia(const StreamConstraints& constraints, Promise&& promise) const
     144void MediaDevices::getDisplayMedia(const StreamConstraints& constraints, Promise&& promise)
    123145{
    124146    auto* document = this->document();
     
    126148        return;
    127149
    128     if (!m_disableGetDisplayMediaUserGestureConstraint && !UserGestureIndicator::processingUserGesture()) {
     150    bool isUserGesturePriviledged = computeUserGesturePriviledge(GestureAllowedRequest::Display);
     151    if (!m_disableGetDisplayMediaUserGestureConstraint && !isUserGesturePriviledged) {
    129152        promise.reject(Exception { InvalidAccessError, "getDisplayMedia must be called from a user gesture handler."_s });
    130153        return;
    131154    }
    132155
    133     auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, { }, createMediaConstraints(constraints.video) }, WTFMove(promise));
     156    auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, { }, createMediaConstraints(constraints.video), isUserGesturePriviledged }, WTFMove(promise));
    134157    request->start();
    135158}
  • trunk/Source/WebCore/Modules/mediastream/MediaDevices.h

    r251244 r251639  
    5050class MediaDeviceInfo;
    5151class MediaStream;
     52class UserGestureToken;
    5253
    5354struct MediaTrackSupportedConstraints;
     
    7879        Variant<bool, MediaTrackConstraints> audio;
    7980    };
    80     void getUserMedia(const StreamConstraints&, Promise&&) const;
    81     void getDisplayMedia(const StreamConstraints&, Promise&&) const;
     81    void getUserMedia(const StreamConstraints&, Promise&&);
     82    void getDisplayMedia(const StreamConstraints&, Promise&&);
    8283    void enumerateDevices(EnumerateDevicesPromise&&);
    8384    MediaTrackSupportedConstraints getSupportedConstraints();
     
    110111    void derefEventTarget() final { deref(); }
    111112
     113    enum class GestureAllowedRequest {
     114        Microphone = 1 << 0,
     115        Camera = 1 << 1,
     116        Display = 1 << 2,
     117    };
     118    bool computeUserGesturePriviledge(GestureAllowedRequest);
     119
    112120    Timer m_scheduledEventTimer;
    113121    UserMediaClient::DeviceChangeObserverToken m_deviceChangeToken;
     
    119127    bool m_canAccessCamera { false };
    120128    bool m_canAccessMicrophone { false };
     129
     130    OptionSet<GestureAllowedRequest> m_requestTypesForCurrentGesture;
     131    UserGestureToken* m_currentGestureToken { nullptr };
    121132};
    122133
  • trunk/Source/WebCore/platform/mediastream/MediaStreamRequest.h

    r243163 r251639  
    3434struct MediaStreamRequest {
    3535    enum class Type { UserMedia, DisplayMedia };
    36     Type type;
     36    Type type { Type::UserMedia };
    3737    MediaConstraints audioConstraints;
    3838    MediaConstraints videoConstraints;
     39    bool isUserGesturePriviledged { false };
    3940
    4041    template<class Encoder>
     
    4445        encoder << audioConstraints;
    4546        encoder << videoConstraints;
     47        encoder << isUserGesturePriviledged;
    4648    }
    4749
     
    4951    {
    5052        MediaStreamRequest request;
    51         if (decoder.decodeEnum(request.type) && decoder.decode(request.audioConstraints) && decoder.decode(request.videoConstraints))
     53        if (decoder.decodeEnum(request.type) && decoder.decode(request.audioConstraints) && decoder.decode(request.videoConstraints) && decoder.decode(request.isUserGesturePriviledged))
    5254            return request;
    5355
  • trunk/Source/WebKit/ChangeLog

    r251630 r251639  
     12019-10-26  youenn fablet  <youenn@apple.com>
     2
     3        Enforce user gesture for getUserMedia in case a previous getUserMedia call was denied
     4        https://bugs.webkit.org/show_bug.cgi?id=203362
     5
     6        Reviewed by Eric Carlson.
     7
     8        In case the request has user gesture priviledge, do not look at denied request history.
     9
     10        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
     11        (WebKit::UserMediaPermissionRequestManagerProxy::getRequestAction):
     12        * UIProcess/UserMediaPermissionRequestProxy.h:
     13        (WebKit::UserMediaPermissionRequestProxy::isUserGesturePriviledged const):
     14
    1152019-10-26  Chris Lord  <clord@igalia.com>
    216
  • trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp

    r250552 r251639  
    346346    ASSERT(!(requestingScreenCapture && requestingMicrophone));
    347347
    348     if (wasRequestDenied(request.frameID(), request.userMediaDocumentSecurityOrigin(), request.topLevelDocumentSecurityOrigin(), requestingMicrophone, requestingCamera, requestingScreenCapture))
     348    if (!request.isUserGesturePriviledged() && wasRequestDenied(request.frameID(), request.userMediaDocumentSecurityOrigin(), request.topLevelDocumentSecurityOrigin(), requestingMicrophone, requestingCamera, requestingScreenCapture))
    349349        return RequestAction::Deny;
    350350
  • trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h

    r248713 r251639  
    8585    WebCore::CaptureDevice videoDevice() const { return m_eligibleVideoDevices.isEmpty() ? WebCore::CaptureDevice { } : m_eligibleVideoDevices[0]; }
    8686
     87    bool isUserGesturePriviledged() const { return m_request.isUserGesturePriviledged; }
     88
    8789private:
    8890    UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy&, uint64_t userMediaID, WebCore::FrameIdentifier mainFrameID, WebCore::FrameIdentifier, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, WebCore::MediaStreamRequest&&);
  • trunk/Tools/ChangeLog

    r251630 r251639  
     12019-10-26  youenn fablet  <youenn@apple.com>
     2
     3        Enforce user gesture for getUserMedia in case a previous getUserMedia call was denied
     4        https://bugs.webkit.org/show_bug.cgi?id=203362
     5
     6        Reviewed by Eric Carlson.
     7
     8        Update test to take into account the ability to reask permission.
     9        * TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm:
     10        (TestWebKitAPI::TEST_F):
     11
    1122019-10-26  Chris Lord  <clord@igalia.com>
    213
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GetDisplayMedia.mm

    r244749 r251639  
    181181    promptForCapture(@"{ video: true }", false);
    182182    shouldDeny = false;
    183     promptForCapture(@"{ video: true }", false);
    184     promptForCapture(@"{ video: true }", false);
     183    promptForCapture(@"{ video: true }", true);
    185184}
    186185
Note: See TracChangeset for help on using the changeset viewer.