Changeset 209008 in webkit


Ignore:
Timestamp:
Nov 28, 2016 12:45:12 PM (7 years ago)
Author:
eric.carlson@apple.com
Message:

[MediaStream] Don't request user permission for a device if it has already been granted in the current browsing context
https://bugs.webkit.org/show_bug.cgi?id=164760
Source/WebKit2:

<rdar://problem/29261266>

Reviewed by Youenn Fablet.

  • UIProcess/UserMediaPermissionRequestManagerProxy.cpp:

(WebKit::FrameAuthorizationState::FrameAuthorizationState):
(WebKit::FrameAuthorizationState::hasPermissionToUseCaptureDevice):
(WebKit::FrameAuthorizationState::setHasPermissionToUseCaptureDevice):
(WebKit::FrameAuthorizationState::reset):
(WebKit::FrameAuthorizationState::securityOriginsAreEqual):
(WebKit::UserMediaPermissionRequestManagerProxy::stateForRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::invalidateRequests):
(WebKit::UserMediaPermissionRequestManagerProxy::createRequest):
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasDenied):
(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted):
(WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):

  • UIProcess/UserMediaPermissionRequestManagerProxy.h:

(WebKit::FrameAuthorizationState::~FrameAuthorizationState):
(WebKit::FrameAuthorizationState::frameID):

  • UIProcess/UserMediaPermissionRequestProxy.cpp:

(WebKit::UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy):

  • UIProcess/UserMediaPermissionRequestProxy.h:

(WebKit::UserMediaPermissionRequestProxy::create):
(WebKit::UserMediaPermissionRequestProxy::frameID):
(WebKit::UserMediaPermissionRequestProxy::userMediaDocumentSecurityOrigin):
(WebKit::UserMediaPermissionRequestProxy::topLevelDocumentSecurityOrigin):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::didCommitLoadForFrame):

  • WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:

(WebKit::UserMediaPermissionRequestManager::removeMediaRequestFromMaps):

Tools:

<rdar://problem/29261266>

Reviewed by Youenn Fablet.

Allow scripts to determine the number of times the user has been prompted for capture device access.

  • WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
  • WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:

(WTR::InjectedBundle::setUserMediaPersistentPermissionForOrigin):
(WTR::InjectedBundle::userMediaPermissionRequestCountForOrigin):
(WTR::InjectedBundle::resetUserMediaPermissionRequestCountForOrigin):
(WTR::InjectedBundle::setUserMediaPermissionForOrigin): Deleted.

  • WebKitTestRunner/InjectedBundle/InjectedBundle.h:
  • WebKitTestRunner/InjectedBundle/TestRunner.cpp:

(WTR::TestRunner::setUserMediaPersistentPermissionForOrigin):
(WTR::TestRunner::userMediaPermissionRequestCountForOrigin):
(WTR::TestRunner::resetUserMediaPermissionRequestCountForOrigin):
(WTR::TestRunner::setUserMediaPermissionForOrigin): Deleted.

  • WebKitTestRunner/InjectedBundle/TestRunner.h:
  • WebKitTestRunner/TestController.cpp:

(WTR::TestController::resetStateToConsistentValues):
(WTR::OriginSettings::incrementRequestCount):
(WTR::OriginSettings::resetRequestCount):
(WTR::OriginSettings::requestCount):
(WTR::TestController::saltForOrigin):
(WTR::TestController::setUserMediaPersistentPermissionForOrigin):
(WTR::TestController::handleCheckOfUserMediaPermissionForOrigin):
(WTR::TestController::settingsForOrigin):
(WTR::TestController::userMediaPermissionRequestCountForOrigin):
(WTR::TestController::resetUserMediaPermissionRequestCountForOrigin):
(WTR::TestController::decidePolicyForUserMediaPermissionRequestIfPossible):
(WTR::TestController::setUserMediaPermissionForOrigin): Deleted.

  • WebKitTestRunner/TestController.h:
  • WebKitTestRunner/TestInvocation.cpp:

(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

Reviewed by Youenn Fablet.

  • fast/mediastream/MediaDevices-getUserMedia-expected.txt:
  • fast/mediastream/MediaDevices-getUserMedia.html:
Location:
trunk
Files:
2 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208998 r209008  
     12016-11-28  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [MediaStream] Don't request user permission for a device if it has already been granted in the current browsing context
     4        https://bugs.webkit.org/show_bug.cgi?id=164760
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * fast/mediastream/MediaDevices-getUserMedia-expected.txt:
     9        * fast/mediastream/MediaDevices-getUserMedia.html:
     10
    1112016-11-28  Antti Koivisto  <antti@apple.com>
    212
  • trunk/LayoutTests/fast/mediastream/MediaDevices-enumerateDevices.html

    r197114 r209008  
    5959                if (window.testRunner) {
    6060                    testRunner.setUserMediaPermission(true);
    61                     testRunner.setUserMediaPermissionForOrigin(false, document.location.href, "");
     61                    testRunner.setUserMediaPersistentPermissionForOrigin(false, document.location.href, "");
    6262                }
    6363
     
    7878            {
    7979                if (window.testRunner)
    80                     testRunner.setUserMediaPermissionForOrigin(true, document.location.href, "");
     80                    testRunner.setUserMediaPersistentPermissionForOrigin(true, document.location.href, "");
    8181
    8282                debug(`<br>*** Calling mediaDevices.enumerateDevices with persistent access, and without a media stream track<br>`);
  • trunk/LayoutTests/http/tests/media/media-stream/enumerate-devices-source-id-persistent.html

    r197114 r209008  
    1212            if (window.testRunner) {
    1313                testRunner.setUserMediaPermission(true);
    14                 testRunner.setUserMediaPermissionForOrigin(true, "http://localhost:8000", location.href);
     14                testRunner.setUserMediaPersistentPermissionForOrigin(true, "http://localhost:8000", location.href);
    1515            }
    1616
  • trunk/Source/WebKit2/ChangeLog

    r208992 r209008  
     12016-11-28  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [MediaStream] Don't request user permission for a device if it has already been granted in the current browsing context
     4        https://bugs.webkit.org/show_bug.cgi?id=164760
     5        <rdar://problem/29261266>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
     10        (WebKit::FrameAuthorizationState::FrameAuthorizationState):
     11        (WebKit::FrameAuthorizationState::hasPermissionToUseCaptureDevice):
     12        (WebKit::FrameAuthorizationState::setHasPermissionToUseCaptureDevice):
     13        (WebKit::FrameAuthorizationState::reset):
     14        (WebKit::FrameAuthorizationState::securityOriginsAreEqual):
     15        (WebKit::UserMediaPermissionRequestManagerProxy::stateForRequest):
     16        (WebKit::UserMediaPermissionRequestManagerProxy::invalidateRequests):
     17        (WebKit::UserMediaPermissionRequestManagerProxy::createRequest):
     18        (WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasDenied):
     19        (WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted):
     20        (WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame):
     21        * UIProcess/UserMediaPermissionRequestManagerProxy.h:
     22        (WebKit::FrameAuthorizationState::~FrameAuthorizationState):
     23        (WebKit::FrameAuthorizationState::frameID):
     24        * UIProcess/UserMediaPermissionRequestProxy.cpp:
     25        (WebKit::UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy):
     26        * UIProcess/UserMediaPermissionRequestProxy.h:
     27        (WebKit::UserMediaPermissionRequestProxy::create):
     28        (WebKit::UserMediaPermissionRequestProxy::frameID):
     29        (WebKit::UserMediaPermissionRequestProxy::userMediaDocumentSecurityOrigin):
     30        (WebKit::UserMediaPermissionRequestProxy::topLevelDocumentSecurityOrigin):
     31        * UIProcess/WebPageProxy.cpp:
     32        (WebKit::WebPageProxy::didCommitLoadForFrame):
     33        * WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
     34        (WebKit::UserMediaPermissionRequestManager::removeMediaRequestFromMaps):
     35
    1362016-11-27  Dean Jackson  <dino@apple.com>
    237
  • trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp

    r208985 r209008  
    3535namespace WebKit {
    3636
     37FrameAuthorizationState::FrameAuthorizationState(UserMediaPermissionRequestProxy& request)
     38    : m_userMediaDocumentSecurityOrigin(request.userMediaDocumentSecurityOrigin())
     39    , m_topLevelDocumentSecurityOrigin(request.topLevelDocumentSecurityOrigin())
     40{
     41}
     42
     43bool FrameAuthorizationState::hasPermissionToUseCaptureDevice(const String& deviceUID)
     44{
     45    return m_authorizedDeviceUIDs.find(deviceUID) != notFound;
     46}
     47
     48void FrameAuthorizationState::setHasPermissionToUseCaptureDevice(const String& deviceUID, bool hasPermission)
     49{
     50    if (deviceUID.isEmpty())
     51        return;
     52
     53    size_t index = m_authorizedDeviceUIDs.find(deviceUID);
     54    if (hasPermission == (index != notFound))
     55        return;
     56
     57    if (hasPermission)
     58        m_authorizedDeviceUIDs.append(deviceUID);
     59    else
     60        m_authorizedDeviceUIDs.remove(index);
     61}
     62
     63void FrameAuthorizationState::ensureSecurityOriginsAreEqual(UserMediaPermissionRequestProxy& request)
     64{
     65    do {
     66        if (!m_userMediaDocumentSecurityOrigin || !m_userMediaDocumentSecurityOrigin->equal(request.userMediaDocumentSecurityOrigin()))
     67            break;
     68
     69        if (!m_topLevelDocumentSecurityOrigin || !m_topLevelDocumentSecurityOrigin->equal(request.topLevelDocumentSecurityOrigin()))
     70            break;
     71
     72        return;
     73    } while (0);
     74
     75    m_userMediaDocumentSecurityOrigin = request.userMediaDocumentSecurityOrigin();
     76    m_topLevelDocumentSecurityOrigin = request.topLevelDocumentSecurityOrigin();
     77    m_authorizedDeviceUIDs.clear();
     78}
     79
     80FrameAuthorizationState& UserMediaPermissionRequestManagerProxy::stateForRequest(UserMediaPermissionRequestProxy& request)
     81{
     82    auto& state = m_frameStates.add(request.frameID(), nullptr).iterator->value;
     83    if (state) {
     84        state->ensureSecurityOriginsAreEqual(request);
     85        return *state;
     86    }
     87
     88    state = std::make_unique<FrameAuthorizationState>(request);
     89    return *state;
     90}
     91
    3792UserMediaPermissionRequestManagerProxy::UserMediaPermissionRequestManagerProxy(WebPageProxy& page)
    3893    : m_page(page)
     
    50105    m_pendingDeviceRequests.clear();
    51106
    52     m_pageSandboxExtensionsGranted.clear();
    53 }
    54 
    55 Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs)
    56 {
    57     Ref<UserMediaPermissionRequestProxy> request = UserMediaPermissionRequestProxy::create(*this, userMediaID, audioDeviceUIDs, videoDeviceUIDs);
    58     m_pendingUserMediaRequests.add(userMediaID, request.ptr());
    59     return request;
    60 }
    61 
    62 Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID)
    63 {
    64     Ref<UserMediaPermissionRequestProxy> request = UserMediaPermissionRequestProxy::create(*this, userMediaID, Vector<String>(), Vector<String>());
     107    m_frameStates.clear();
     108}
     109
     110Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID, uint64_t frameID, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs)
     111{
     112    auto request = UserMediaPermissionRequestProxy::create(*this, userMediaID, frameID, userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier, audioDeviceUIDs, videoDeviceUIDs);
    65113    m_pendingUserMediaRequests.add(userMediaID, request.ptr());
    66114    return request;
     
    104152        return;
    105153
    106     if (!m_pendingUserMediaRequests.take(userMediaID))
    107         return;
    108 
    109     denyRequest(userMediaID, reason, "");
     154    auto request = m_pendingUserMediaRequests.take(userMediaID);
     155    if (!request)
     156        return;
     157
     158    auto fameState = stateForRequest(*request);
     159    for (const auto& deviceUID : request->videoDeviceUIDs())
     160        fameState.setHasPermissionToUseCaptureDevice(deviceUID, false);
     161    for (const auto& deviceUID : request->audioDeviceUIDs())
     162        fameState.setHasPermissionToUseCaptureDevice(deviceUID, false);
     163
     164    denyRequest(userMediaID, reason, emptyString());
    110165}
    111166
     
    129184        return;
    130185
    131     if (!m_pendingUserMediaRequests.take(userMediaID))
    132         return;
    133 
    134 #if ENABLE(MEDIA_STREAM)
     186#if ENABLE(MEDIA_STREAM)
     187    auto request = m_pendingUserMediaRequests.take(userMediaID);
     188    if (!request)
     189        return;
     190
     191    auto& fameState = stateForRequest(*request);
     192    fameState.setHasPermissionToUseCaptureDevice(audioDeviceUID, true);
     193    fameState.setHasPermissionToUseCaptureDevice(videoDeviceUID, true);
     194
    135195    size_t extensionCount = 0;
    136196    unsigned requiredExtensions = SandboxExtensionsGranted::None;
     
    144204    }
    145205
    146     unsigned currentExtensions = m_pageSandboxExtensionsGranted.get(m_page.pageID());
     206    unsigned currentExtensions = m_pageSandboxExtensionsGranted;
    147207    if (!(requiredExtensions & currentExtensions)) {
    148208        ASSERT(extensionCount);
    149         m_pageSandboxExtensionsGranted.set(m_page.pageID(), requiredExtensions | currentExtensions);
     209        m_pageSandboxExtensionsGranted = requiredExtensions | currentExtensions;
    150210        SandboxExtension::HandleArray handles;
    151211        handles.allocate(extensionCount);
     
    159219    m_page.process().send(Messages::WebPage::UserMediaAccessWasGranted(userMediaID, audioDeviceUID, videoDeviceUID), m_page.pageID());
    160220#else
     221    UNUSED_PARAM(userMediaID);
    161222    UNUSED_PARAM(audioDeviceUID);
    162223    UNUSED_PARAM(videoDeviceUID);
     
    179240
    180241        if (videoDeviceUIDs.isEmpty() && audioDeviceUIDs.isEmpty()) {
    181             denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints, "");
     242            denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints, emptyString());
    182243            return;
    183244        }
     
    185246        auto userMediaOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(userMediaDocumentOriginIdentifier)->securityOrigin());
    186247        auto topLevelOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier)->securityOrigin());
    187         auto request = createRequest(userMediaID, audioDeviceUIDs, videoDeviceUIDs);
    188 
    189         if (!m_page.uiClient().decidePolicyForUserMediaPermissionRequest(m_page, *m_page.process().webFrame(frameID), *userMediaOrigin.get(), *topLevelOrigin.get(), request.get())) {
    190             m_pendingUserMediaRequests.take(userMediaID);
    191             request->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
     248        auto request = createRequest(userMediaID, frameID, userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier, audioDeviceUIDs, videoDeviceUIDs);
     249
     250        String authorizedAudioDevice;
     251        String authorizedVideoDevice;
     252        auto& fameState = stateForRequest(request);
     253        for (auto deviceUID : audioDeviceUIDs) {
     254            if (fameState.hasPermissionToUseCaptureDevice(deviceUID)) {
     255                authorizedAudioDevice = deviceUID;
     256                break;
     257            }
    192258        }
     259        for (auto deviceUID : videoDeviceUIDs) {
     260            if (fameState.hasPermissionToUseCaptureDevice(deviceUID)) {
     261                authorizedVideoDevice = deviceUID;
     262                break;
     263            }
     264        }
     265
     266        if (audioDeviceUIDs.isEmpty() == authorizedAudioDevice.isEmpty() && videoDeviceUIDs.isEmpty() == authorizedVideoDevice.isEmpty()) {
     267            userMediaAccessWasGranted(userMediaID, authorizedAudioDevice, authorizedVideoDevice);
     268            return;
     269        }
     270
     271        if (!m_page.uiClient().decidePolicyForUserMediaPermissionRequest(m_page, *m_page.process().webFrame(frameID), *userMediaOrigin.get(), *topLevelOrigin.get(), request.get()))
     272            userMediaAccessWasDenied(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
     273       
    193274    };
    194275
  • trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h

    r207704 r209008  
    2323#include "UserMediaPermissionCheckProxy.h"
    2424#include "UserMediaPermissionRequestProxy.h"
     25#include <WebCore/SecurityOrigin.h>
    2526#include <WebCore/UserMediaRequest.h>
    2627#include <wtf/HashMap.h>
     
    3536class WebPageProxy;
    3637
     38class FrameAuthorizationState {
     39public:
     40    explicit FrameAuthorizationState(UserMediaPermissionRequestProxy&);
     41
     42    bool hasPermissionToUseCaptureDevice(const String& deviceUID);
     43    void setHasPermissionToUseCaptureDevice(const String&, bool);
     44
     45    void ensureSecurityOriginsAreEqual(UserMediaPermissionRequestProxy&);
     46
     47private:
     48    RefPtr<WebCore::SecurityOrigin> m_userMediaDocumentSecurityOrigin;
     49    RefPtr<WebCore::SecurityOrigin> m_topLevelDocumentSecurityOrigin;
     50    Vector<String> m_authorizedDeviceUIDs;
     51};
     52
    3753class UserMediaPermissionRequestManagerProxy {
    3854public:
     
    4561    void userMediaAccessWasGranted(uint64_t, const String& audioDeviceUID, const String& videoDeviceUID);
    4662    void userMediaAccessWasDenied(uint64_t, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason);
     63    FrameAuthorizationState& stateForRequest(UserMediaPermissionRequestProxy&);
    4764
    4865    void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, String userMediaDocumentOriginIdentifier, String topLevelDocumentOriginIdentifier);
     
    5168
    5269private:
    53     Ref<UserMediaPermissionRequestProxy> createRequest(uint64_t, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs);
    54     Ref<UserMediaPermissionRequestProxy> createRequest(uint64_t userMediaID);
     70    Ref<UserMediaPermissionRequestProxy> createRequest(uint64_t userMediaID, uint64_t frameID, const String&userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs);
    5571    void denyRequest(uint64_t userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason, const String& invalidConstraint);
    5672    Ref<UserMediaPermissionCheckProxy> createUserMediaPermissionCheck(uint64_t userMediaID);
     
    6581        Audio = 1 << 1
    6682    };
    67     HashMap<uint64_t, unsigned> m_pageSandboxExtensionsGranted;
     83    unsigned m_pageSandboxExtensionsGranted;
     84
     85    HashMap<uint64_t, std::unique_ptr<FrameAuthorizationState>> m_frameStates;
    6886
    6987    WebPageProxy& m_page;
  • trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.cpp

    r207463 r209008  
    2323#include "UserMediaPermissionRequestManagerProxy.h"
    2424#include <WebCore/RealtimeMediaSourceCenter.h>
     25#include <WebCore/SecurityOrigin.h>
     26#include <WebCore/SecurityOriginData.h>
    2527#include <wtf/text/StringHash.h>
     28
     29using namespace WebCore;
    2630
    2731namespace WebKit {
    2832
    29 UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs)
     33UserMediaPermissionRequestProxy::UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, uint64_t frameID, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs)
    3034    : m_manager(&manager)
    3135    , m_userMediaID(userMediaID)
     36    , m_frameID(frameID)
     37    , m_userMediaDocumentSecurityOrigin((SecurityOriginData::fromDatabaseIdentifier(userMediaDocumentOriginIdentifier)->securityOrigin()))
     38    , m_topLevelDocumentSecurityOrigin(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier)->securityOrigin())
    3239    , m_videoDeviceUIDs(videoDeviceUIDs)
    3340    , m_audioDeviceUIDs(audioDeviceUIDs)
  • trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestProxy.h

    r207463 r209008  
    2626#include <wtf/text/WTFString.h>
    2727
     28namespace WebCore {
     29class SecurityOrigin;
     30}
     31
    2832namespace WebKit {
    2933
     
    3236class UserMediaPermissionRequestProxy : public API::ObjectImpl<API::Object::Type::UserMediaPermissionRequest> {
    3337public:
    34     static Ref<UserMediaPermissionRequestProxy> create(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, const Vector<String>& videoDeviceUIDs, const Vector<String>& audioDeviceUIDs)
     38    static Ref<UserMediaPermissionRequestProxy> create(UserMediaPermissionRequestManagerProxy& manager, uint64_t userMediaID, uint64_t frameID, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier, const Vector<String>& videoDeviceUIDs, const Vector<String>& audioDeviceUIDs)
    3539    {
    36         return adoptRef(*new UserMediaPermissionRequestProxy(manager, userMediaID, videoDeviceUIDs, audioDeviceUIDs));
     40        return adoptRef(*new UserMediaPermissionRequestProxy(manager, userMediaID, frameID, userMediaDocumentOriginIdentifier, topLevelDocumentOriginIdentifier, videoDeviceUIDs, audioDeviceUIDs));
    3741    }
    3842
     
    5054    const Vector<String>& audioDeviceUIDs() const { return m_audioDeviceUIDs; }
    5155
     56    uint64_t frameID() const { return m_frameID; }
     57    WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin() { return &m_userMediaDocumentSecurityOrigin.get(); }
     58    WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin() { return &m_topLevelDocumentSecurityOrigin.get(); }
     59
    5260private:
    53     UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy&, uint64_t userMediaID, const Vector<String>& videoDeviceUIDs, const Vector<String>& audioDeviceUIDs);
     61    UserMediaPermissionRequestProxy(UserMediaPermissionRequestManagerProxy&, uint64_t userMediaID, uint64_t frameID, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier, const Vector<String>& videoDeviceUIDs, const Vector<String>& audioDeviceUIDs);
    5462
    5563    UserMediaPermissionRequestManagerProxy* m_manager;
    5664    uint64_t m_userMediaID;
     65    uint64_t m_frameID;
     66    Ref<WebCore::SecurityOrigin> m_userMediaDocumentSecurityOrigin;
     67    Ref<WebCore::SecurityOrigin> m_topLevelDocumentSecurityOrigin;
    5768    Vector<String> m_videoDeviceUIDs;
    5869    Vector<String> m_audioDeviceUIDs;
  • trunk/Tools/ChangeLog

    r208999 r209008  
     12016-11-28  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [MediaStream] Don't request user permission for a device if it has already been granted in the current browsing context
     4        https://bugs.webkit.org/show_bug.cgi?id=164760
     5        <rdar://problem/29261266>
     6
     7        Reviewed by Youenn Fablet.
     8       
     9        Allow scripts to determine the number of times the user has been prompted for capture device access.
     10
     11        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
     12        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
     13        (WTR::InjectedBundle::setUserMediaPersistentPermissionForOrigin):
     14        (WTR::InjectedBundle::userMediaPermissionRequestCountForOrigin):
     15        (WTR::InjectedBundle::resetUserMediaPermissionRequestCountForOrigin):
     16        (WTR::InjectedBundle::setUserMediaPermissionForOrigin): Deleted.
     17        * WebKitTestRunner/InjectedBundle/InjectedBundle.h:
     18        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
     19        (WTR::TestRunner::setUserMediaPersistentPermissionForOrigin):
     20        (WTR::TestRunner::userMediaPermissionRequestCountForOrigin):
     21        (WTR::TestRunner::resetUserMediaPermissionRequestCountForOrigin):
     22        (WTR::TestRunner::setUserMediaPermissionForOrigin): Deleted.
     23        * WebKitTestRunner/InjectedBundle/TestRunner.h:
     24        * WebKitTestRunner/TestController.cpp:
     25        (WTR::TestController::resetStateToConsistentValues):
     26        (WTR::OriginSettings::incrementRequestCount):
     27        (WTR::OriginSettings::resetRequestCount):
     28        (WTR::OriginSettings::requestCount):
     29        (WTR::TestController::saltForOrigin):
     30        (WTR::TestController::setUserMediaPersistentPermissionForOrigin):
     31        (WTR::TestController::handleCheckOfUserMediaPermissionForOrigin):
     32        (WTR::TestController::settingsForOrigin):
     33        (WTR::TestController::userMediaPermissionRequestCountForOrigin):
     34        (WTR::TestController::resetUserMediaPermissionRequestCountForOrigin):
     35        (WTR::TestController::decidePolicyForUserMediaPermissionRequestIfPossible):
     36        (WTR::TestController::setUserMediaPermissionForOrigin): Deleted.
     37        * WebKitTestRunner/TestController.h:
     38        * WebKitTestRunner/TestInvocation.cpp:
     39        (WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
     40        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
     41
    1422016-11-18  Jer Noble  <jer.noble@apple.com>
    243
  • trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl

    r208522 r209008  
    186186    // MediaStream
    187187    void setUserMediaPermission(boolean value);
    188     void setUserMediaPermissionForOrigin(boolean permission, DOMString origin, DOMString parentOrigin);
     188    void setUserMediaPersistentPermissionForOrigin(boolean permission, DOMString origin, DOMString parentOrigin);
     189    unsigned long userMediaPermissionRequestCountForOrigin(DOMString origin, DOMString parentOrigin);
     190    void resetUserMediaPermissionRequestCountForOrigin(DOMString origin, DOMString parentOrigin);
    189191
    190192    // Audio testing.
  • trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp

    r208939 r209008  
    583583}
    584584
    585 void InjectedBundle::setUserMediaPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin)
    586 {
    587     auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermissionForOrigin"));
     585void InjectedBundle::setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin)
     586{
     587    auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPersistentPermissionForOrigin"));
    588588    WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
    589589
     
    591591    WKRetainPtr<WKBooleanRef> permissionWK(AdoptWK, WKBooleanCreate(permission));
    592592    WKDictionarySetItem(messageBody.get(), permissionKeyWK.get(), permissionWK.get());
     593
     594    WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin"));
     595    WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
     596
     597    WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
     598    WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
     599
     600    WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
     601}
     602
     603unsigned InjectedBundle::userMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) const
     604{
     605    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("UserMediaPermissionRequestCountForOrigin"));
     606    WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
     607
     608    WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin"));
     609    WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin);
     610
     611    WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
     612    WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin);
     613
     614    WKTypeRef resultToPass = 0;
     615    WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), &resultToPass);
     616    WKRetainPtr<WKUInt64Ref> count(AdoptWK, static_cast<WKUInt64Ref>(resultToPass));
     617
     618    return static_cast<unsigned>(WKUInt64GetValue(count.get()));
     619}
     620
     621void InjectedBundle::resetUserMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin)
     622{
     623    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ResetUserMediaPermissionRequestCountForOrigin"));
     624    WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
    593625
    594626    WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin"));
  • trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h

    r208338 r209008  
    102102    // MediaStream.
    103103    void setUserMediaPermission(bool);
    104     void setUserMediaPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin);
     104    void setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin);
     105    unsigned userMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) const;
     106    void resetUserMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin);
    105107
    106108    // Policy delegate.
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp

    r208939 r209008  
    890890}
    891891
    892 void TestRunner::setUserMediaPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
     892void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin)
    893893{
    894894    WKRetainPtr<WKStringRef> originWK = toWK(origin);
    895895    WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
    896     InjectedBundle::singleton().setUserMediaPermissionForOrigin(permission, originWK.get(), parentOriginWK.get());
     896    InjectedBundle::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK.get(), parentOriginWK.get());
     897}
     898
     899unsigned TestRunner::userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const
     900{
     901    WKRetainPtr<WKStringRef> originWK = toWK(origin);
     902    WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
     903    return InjectedBundle::singleton().userMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
     904}
     905
     906void TestRunner::resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin)
     907{
     908    WKRetainPtr<WKStringRef> originWK = toWK(origin);
     909    WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin);
     910    InjectedBundle::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get());
    897911}
    898912
  • trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h

    r208939 r209008  
    287287    // MediaStream
    288288    void setUserMediaPermission(bool);
    289     void setUserMediaPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin);
     289    void setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin);
     290    unsigned userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const;
     291    void resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin);
    290292
    291293    void setPageVisibility(JSStringRef state);
     
    401403    WKRetainPtr<WKArrayRef> m_allowedHosts;
    402404
     405    size_t m_userMediaPermissionRequestCount { 0 };
     406
    403407    PlatformTimerRef m_waitToDumpWatchdogTimer;
    404408};
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r208983 r209008  
    766766    // Reset UserMedia permissions.
    767767    m_userMediaPermissionRequests.clear();
    768     m_cahcedUserMediaPermissions.clear();
     768    m_cachedUserMediaPermissions.clear();
    769769    m_isUserMediaPermissionSet = false;
    770770    m_isUserMediaPermissionAllowed = false;
     
    18861886    HashMap<uint64_t, String>& ephemeralSalts() { return m_ephemeralSalts; }
    18871887
     1888    void incrementRequestCount() { ++m_requestCount; }
     1889    void resetRequestCount() { m_requestCount = 0; }
     1890    unsigned requestCount() const { return m_requestCount; }
     1891
    18881892private:
    18891893    HashMap<uint64_t, String> m_ephemeralSalts;
    18901894    String m_persistentSalt;
     1895    unsigned m_requestCount { 0 };
    18911896    bool m_persistentPermission { false };
    18921897};
     
    18941899String TestController::saltForOrigin(WKFrameRef frame, String originHash)
    18951900{
    1896     RefPtr<OriginSettings> settings = m_cahcedUserMediaPermissions.get(originHash);
    1897     if (!settings) {
    1898         settings = adoptRef(*new OriginSettings());
    1899         m_cahcedUserMediaPermissions.add(originHash, settings);
    1900     }
    1901 
    1902     auto& ephemeralSalts = settings->ephemeralSalts();
     1901    auto& settings = settingsForOrigin(originHash);
     1902    auto& ephemeralSalts = settings.ephemeralSalts();
    19031903    auto frameInfo = adoptWK(WKFrameCreateFrameInfo(frame));
    19041904    auto frameHandle = WKFrameInfoGetFrameHandleRef(frameInfo.get());
     
    19061906    String frameSalt = ephemeralSalts.get(frameIdentifier);
    19071907
    1908     if (settings->persistentPermission()) {
     1908    if (settings.persistentPermission()) {
    19091909        if (frameSalt.length())
    19101910            return frameSalt;
    19111911
    1912         if (!settings->persistentSalt().length())
    1913             settings->setPersistentSalt(createCanonicalUUIDString());
    1914 
    1915         return settings->persistentSalt();
     1912        if (!settings.persistentSalt().length())
     1913            settings.setPersistentSalt(createCanonicalUUIDString());
     1914
     1915        return settings.persistentSalt();
    19161916    }
    19171917
     
    19241924}
    19251925
    1926 void TestController::setUserMediaPermissionForOrigin(bool permission, WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString)
     1926void TestController::setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString)
    19271927{
    19281928    auto originHash = userMediaOriginHash(userMediaDocumentOriginString, topLevelDocumentOriginString);
    1929     RefPtr<OriginSettings> settings = m_cahcedUserMediaPermissions.get(originHash);
    1930     if (!settings) {
    1931         settings = adoptRef(*new OriginSettings());
    1932         m_cahcedUserMediaPermissions.add(originHash, settings);
    1933     }
    1934 
    1935     settings->setPersistentPermission(permission);
     1929    auto& settings = settingsForOrigin(originHash);
     1930    settings.setPersistentPermission(permission);
    19361931}
    19371932
     
    19411936    auto salt = saltForOrigin(frame, originHash);
    19421937
    1943     WKUserMediaPermissionCheckSetUserMediaAccessInfo(checkRequest, WKStringCreateWithUTF8CString(salt.utf8().data()), m_cahcedUserMediaPermissions.get(originHash)->persistentPermission());
     1938    WKUserMediaPermissionCheckSetUserMediaAccessInfo(checkRequest, WKStringCreateWithUTF8CString(salt.utf8().data()), settingsForOrigin(originHash).persistentPermission());
    19441939}
    19451940
     
    19511946}
    19521947
     1948OriginSettings& TestController::settingsForOrigin(const String& originHash)
     1949{
     1950    RefPtr<OriginSettings> settings = m_cachedUserMediaPermissions.get(originHash);
     1951    if (!settings) {
     1952        settings = adoptRef(*new OriginSettings());
     1953        m_cachedUserMediaPermissions.add(originHash, settings);
     1954    }
     1955
     1956    return *settings;
     1957}
     1958
     1959unsigned TestController::userMediaPermissionRequestCountForOrigin(WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString)
     1960{
     1961    auto originHash = userMediaOriginHash(userMediaDocumentOriginString, topLevelDocumentOriginString);
     1962    return settingsForOrigin(originHash).requestCount();
     1963}
     1964
     1965void TestController::resetUserMediaPermissionRequestCountForOrigin(WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString)
     1966{
     1967    auto originHash = userMediaOriginHash(userMediaDocumentOriginString, topLevelDocumentOriginString);
     1968    settingsForOrigin(originHash).resetRequestCount();
     1969}
     1970
    19531971void TestController::decidePolicyForUserMediaPermissionRequestIfPossible()
    19541972{
     
    19601978        auto request = pair.second.get();
    19611979
    1962         bool persistentPermission = false;
    1963         RefPtr<OriginSettings> settings = m_cahcedUserMediaPermissions.get(originHash);
    1964         if (settings)
    1965             persistentPermission = settings->persistentPermission();
    1966 
    1967         if (!m_isUserMediaPermissionAllowed && !persistentPermission) {
     1980        auto& settings = settingsForOrigin(originHash);
     1981        settings.incrementRequestCount();
     1982
     1983        if (!m_isUserMediaPermissionAllowed && !settings.persistentPermission()) {
    19681984            WKUserMediaPermissionRequestDeny(request, kWKPermissionDenied);
    19691985            continue;
  • trunk/Tools/WebKitTestRunner/TestController.h

    r208522 r209008  
    102102    WKStringRef getUserMediaSaltForOrigin(WKFrameRef, WKStringRef originKey);
    103103    void setUserMediaPermission(bool);
    104     void setUserMediaPermissionForOrigin(bool, WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString);
     104    void setUserMediaPersistentPermissionForOrigin(bool, WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString);
    105105    void handleUserMediaPermissionRequest(WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionRequestRef);
    106106    void handleCheckOfUserMediaPermissionForOrigin(WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, const WKUserMediaPermissionCheckRef&);
     107    OriginSettings& settingsForOrigin(const String&);
     108    unsigned userMediaPermissionRequestCountForOrigin(WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString);
     109    void resetUserMediaPermissionRequestCountForOrigin(WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString);
    107110
    108111    // Policy delegate.
     
    317320    bool m_isGeolocationPermissionAllowed { false };
    318321
    319     HashMap<String, RefPtr<OriginSettings>> m_cahcedUserMediaPermissions;
     322    HashMap<String, RefPtr<OriginSettings>> m_cachedUserMediaPermissions;
    320323
    321324    typedef Vector<std::pair<String, WKRetainPtr<WKUserMediaPermissionRequestRef>>> PermissionRequestList;
  • trunk/Tools/WebKitTestRunner/TestInvocation.cpp

    r208522 r209008  
    497497    }
    498498
    499     if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermissionForOrigin")) {
     499    if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPersistentPermissionForOrigin")) {
    500500        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
    501501        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
     
    511511        WKStringRef parentOriginWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, parentOriginKey.get()));
    512512
    513         TestController::singleton().setUserMediaPermissionForOrigin(permission, originWK, parentOriginWK);
     513        TestController::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK, parentOriginWK);
     514        return;
     515    }
     516
     517    if (WKStringIsEqualToUTF8CString(messageName, "ResetUserMediaPermissionRequestCountForOrigin")) {
     518        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
     519        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
     520
     521        WKRetainPtr<WKStringRef> originKey(AdoptWK, WKStringCreateWithUTF8CString("origin"));
     522        WKStringRef originWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, originKey.get()));
     523
     524        WKRetainPtr<WKStringRef> parentOriginKey(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
     525        WKStringRef parentOriginWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, parentOriginKey.get()));
     526       
     527        TestController::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK, parentOriginWK);
    514528        return;
    515529    }
     
    847861#endif // PLATFORM(MAC)
    848862
     863    if (WKStringIsEqualToUTF8CString(messageName, "UserMediaPermissionRequestCountForOrigin")) {
     864        ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
     865        WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
     866
     867        WKRetainPtr<WKStringRef> originKey(AdoptWK, WKStringCreateWithUTF8CString("origin"));
     868        WKStringRef originWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, originKey.get()));
     869
     870        WKRetainPtr<WKStringRef> parentOriginKey(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin"));
     871        WKStringRef parentOriginWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, parentOriginKey.get()));
     872       
     873        unsigned count = TestController::singleton().userMediaPermissionRequestCountForOrigin(originWK, parentOriginWK);
     874        WKRetainPtr<WKUInt64Ref> result(AdoptWK, WKUInt64Create(count));
     875        return result;
     876    }
     877
     878
    849879    ASSERT_NOT_REACHED();
    850880    return nullptr;
Note: See TracChangeset for help on using the changeset viewer.