⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 238724 in webkit


Ignore:
Timestamp:
Nov 29, 2018, 7:15:03 PM (8 years ago)
Author:
eric.carlson@apple.com
Message:

[MediaStream] DeviceIdHashSaltStorage should use iframe and top level documents
​https://bugs.webkit.org/show_bug.cgi?id=192182

Reviewed by Youenn Fablet.

Source/WebKit:

  • UIProcess/DeviceIdHashSaltStorage.cpp:

(WebKit::DeviceIdHashSaltStorage::deviceIdHashSaltForOrigin): Key off of request and top
level documents.
(WebKit::DeviceIdHashSaltStorage::deleteDeviceIdHashSaltForOrigins): Ditto.

  • UIProcess/DeviceIdHashSaltStorage.h:

(WebKit::DeviceIdHashSaltStorage::HashSaltForOrigin::HashSaltForOrigin):

  • UIProcess/UserMediaPermissionRequestManagerProxy.cpp:

(WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted): Pass both documents.
(WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame): Ditto.
(WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame): Ditto.

LayoutTests:

  • http/tests/media/media-stream/enumerate-devices-source-id-expected.txt:
  • http/tests/media/media-stream/enumerate-devices-source-id.html:
  • http/tests/media/media-stream/resources/enumerate-devices-source-id-frame.html:
Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r238723 r238724  
     12018-11-29  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [MediaStream] DeviceIdHashSaltStorage should use iframe and top level documents
     4        https://bugs.webkit.org/show_bug.cgi?id=192182
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * http/tests/media/media-stream/enumerate-devices-source-id-expected.txt:
     9        * http/tests/media/media-stream/enumerate-devices-source-id.html:
     10        * http/tests/media/media-stream/resources/enumerate-devices-source-id-frame.html:
     11
    1122018-11-29  Christopher Reid  <chris.reid@sony.com>
    213
  • trunk/LayoutTests/http/tests/media/media-stream/enumerate-devices-source-id-expected.txt

    r237988 r238724  
    22 
    33
    4 Tests that mediaDevices.enumerateDevices returns the same value for a device ID in all subframes.
     4Tests that mediaDevices.enumerateDevices returns the same ids for devices in the same frame/subframe .
    55
    66On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
    77
    88
    9 PASS : device id 1 is not unique
    10 PASS : device id 2 is not unique
    11 PASS : device id 3 is not unique
    12 PASS : device id 4 is not unique
    13 PASS : device id 5 is not unique
    14 PASS : device id 6 is not unique
    15 PASS : device id 7 is not unique
    16 PASS : device id 8 is not unique
    17 PASS : device id 9 is not unique
    18 PASS : device id 10 is not unique
    19 PASS : device id 11 is not unique
    20 PASS : device id 12 is not unique
    21 
    22 PASS : device IDs are not unique
    239
    2410PASS successfullyParsed is true
  • trunk/LayoutTests/http/tests/media/media-stream/enumerate-devices-source-id.html

    r237988 r238724  
    77        <script src="../../../../resources/js-test-pre.js"></script>
    88        <script>
    9             var frameInfos = [];
    10             var idCounts = { };
    119            window.jsTestIsAsync = true;
    1210
    … …  
    1614            function setup()
    1715            {
    18                 description("Tests that mediaDevices.enumerateDevices returns the same value for a device ID in all subframes.");
     16                description("Tests that mediaDevices.enumerateDevices returns the same ids for devices in the same frame/subframe .");
    1917            }
    2018
    21             function handler(event)
     19            let map = { };
     20            function checkID(origin, device)
    2221            {
    23                 event.data.deviceIds.forEach(function(id) {
    24                     frameInfos.push({origin : event.data.origin, deviceId : id});
    25                     let count = idCounts[id] || 0;
    26                     idCounts[id] = ++count;
    27                 });
     22                let origins = `${document.origin}-${origin}`;
    2823
    29                 if (frameInfos.length != 12)
     24                if (!map[origins])
     25                    map[origins] = { };
     26
     27                let originInfo = map[origins];
     28                if (!originInfo[device.deviceId])
     29                    originInfo[device.deviceId] = device.kind;
     30               
     31                if (originInfo[device.deviceId] != device.kind)
     32                    testFailed(`: duplicate device IDs for ${device.kind} and ${originInfo[device.deviceId]} in ${origin}/${document.origin}`);
     33
     34                if (Object.keys(originInfo).length > 4)
     35                    testFailed(`: more then four unique device IDs in ${origin}/${document.origin}`);
     36            }
     37
     38            let eventCount = 0;
     39            async function handler(event)
     40            {
     41                event.data.devices.forEach(device => { checkID(event.data.origin, device); });
     42
     43                if (++eventCount != 6)
    3044                    return;
    3145
    32                 var success = true;
    33                 for (var i = 0; i < frameInfos.length; i++) {
    34                     var deviceId = frameInfos[i].deviceId;
    35                     let count = idCounts[deviceId] || 0;
    36                     if (!count) {
    37                         testFailed(`: device id ${i + 1} is unique`);
    38                         success = false;
    39                     } else
    40                         testPassed(`: device id ${i + 1} is not unique`);
    41                 }
    42 
    43                 debug('');
    44                 if (success)
    45                     testPassed(`: device IDs are not unique`);
     46                await navigator.mediaDevices.getUserMedia({video: true, audio: true });
     47                let devices = await navigator.mediaDevices.enumerateDevices();
     48                devices.forEach(device => checkID(document.origin, device));
    4649
    4750                debug('');
    … …  
    5457    </head>
    5558    <body onload="setup()">
    56         <iframe allow="camera;microphone" src="http://localhost:8000/media/media-stream/resources/enumerate-devices-source-id-frame.html"></iframe>
     59        <iframe allow="camera;microphone" src="http://localhost:8000/media/media-stream/resources/enumerate-devices-source-id-frame.html?1"></iframe>
    5760        <br>
    58         <iframe allow="camera;microphone" src="http://127.0.0.1:8000/media/media-stream/resources/enumerate-devices-source-id-frame.html"></iframe>
     61        <iframe allow="camera;microphone" src="http://127.0.0.1:8000/media/media-stream/resources/enumerate-devices-source-id-frame.html?2"></iframe>
    5962        <br>
    60         <iframe allow="camera;microphone" src="http://localhost:8000/media/media-stream/resources/enumerate-devices-source-id-frame.html"></iframe>
     63        <iframe allow="camera;microphone" src="http://localhost:8000/media/media-stream/resources/enumerate-devices-source-id-frame.html?3"></iframe>
    6164        <div id="console"></div>
    6265        <script src="../../../../resources/js-test-post.js"></script>
  • trunk/LayoutTests/http/tests/media/media-stream/resources/enumerate-devices-source-id-frame.html

    r197114 r238724  
    1111            }
    1212
    13             function test(event)
     13            async function test(event)
    1414            {
    15                 navigator.mediaDevices.enumerateDevices()
    16                     .then(function(devices) {
    17                         var result = {
    18                             origin: document.origin,
    19                             deviceIds: [devices[0].deviceId, devices[1].deviceId]
    20                         };
     15                await navigator.mediaDevices.getUserMedia({video: true, audio: true });
     16                let devices = await navigator.mediaDevices.enumerateDevices();
     17                let result = {
     18                    origin: document.origin,
     19                    devices: devices.map(device => { return {deviceId: device.deviceId, kind: device.kind} }),
     20                };
    2121
    22                         parent.postMessage(result, "*");
    23                     })
    24                     .catch(function(err) {
    25                         log(`enumerateDevices failed: ${err.name} - ${err.message}`);
    26                     });
     22                parent.postMessage(result, "*");
    2723               
    28                 var parentPage = document.referrer.split('/').pop();
     24                let parentPage = document.referrer.split('/').pop();
    2925                if (parentPage != "enumerate-devices-source-id.html")
    3026                    return;
    3127
    32                 var iframe = document.createElement('iframe');
     28                let iframe = document.createElement('iframe');
    3329                iframe.src = location.href;
    3430                document.body.appendChild(iframe);
    … …  
    3733            function handler(event)
    3834            {
    39                 var result = {
    40                     origin: `${event.data.origin} in ${document.origin}`,
    41                     deviceIds: event.data.deviceIds
     35                let result = {
     36                    origin: `${event.data.origin}`,
     37                    devices: event.data.devices
    4238                };
    4339
  • trunk/Source/WebKit/ChangeLog

    r238722 r238724  
     12018-11-29  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [MediaStream] DeviceIdHashSaltStorage should use iframe and top level documents
     4        https://bugs.webkit.org/show_bug.cgi?id=192182
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * UIProcess/DeviceIdHashSaltStorage.cpp:
     9        (WebKit::DeviceIdHashSaltStorage::deviceIdHashSaltForOrigin): Key off of request and top
     10        level documents.
     11        (WebKit::DeviceIdHashSaltStorage::deleteDeviceIdHashSaltForOrigins): Ditto.
     12        * UIProcess/DeviceIdHashSaltStorage.h:
     13        (WebKit::DeviceIdHashSaltStorage::HashSaltForOrigin::HashSaltForOrigin):
     14
     15        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
     16        (WebKit::UserMediaPermissionRequestManagerProxy::userMediaAccessWasGranted): Pass both documents.
     17        (WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame): Ditto.
     18        (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame): Ditto.
     19
    1202018-11-29  Ryan Haddad  <ryanhaddad@apple.com>
    221
  • trunk/Source/WebKit/UIProcess/DeviceIdHashSaltStorage.cpp

    r237988 r238724  
    4747}
    4848
    49 const String& DeviceIdHashSaltStorage::deviceIdHashSaltForOrigin(const SecurityOrigin& documentOrigin)
     49const String& DeviceIdHashSaltStorage::deviceIdHashSaltForOrigin(const SecurityOrigin& documentOrigin, const SecurityOrigin& parentOrigin)
    5050{
    51     auto& deviceIdHashSalt = m_deviceIdHashSaltForOrigins.ensure(documentOrigin.toRawString(), [&documentOrigin] () {
     51    auto origins = makeString(documentOrigin.toRawString(), parentOrigin.toRawString());
     52    auto& deviceIdHashSalt = m_deviceIdHashSaltForOrigins.ensure(origins, [&documentOrigin, &parentOrigin] () {
    5253        uint64_t randomData[randomDataSize];
    5354        cryptographicallyRandomValues(reinterpret_cast<unsigned char*>(randomData), sizeof(randomData));
    … …  
    5657        builder.reserveCapacity(hashSaltSize);
    5758        for (int i = 0; i < randomDataSize; i++)
    58             appendUnsigned64AsHex(randomData[0], builder);
     59            appendUnsigned64AsHex(randomData[i], builder);
    5960
    6061        String deviceIdHashSalt = builder.toString();
    6162
    62         return std::make_unique<HashSaltForOrigin>(documentOrigin.data().isolatedCopy(), WTFMove(deviceIdHashSalt));
     63        return std::make_unique<HashSaltForOrigin>(documentOrigin.data().isolatedCopy(), parentOrigin.data().isolatedCopy(), WTFMove(deviceIdHashSalt));
    6364    }).iterator->value;
    6465
    … …  
    7273    HashSet<SecurityOriginData> origins;
    7374
    74     for (auto& hashSaltForOrigin : m_deviceIdHashSaltForOrigins)
     75    for (auto& hashSaltForOrigin : m_deviceIdHashSaltForOrigins) {
    7576        origins.add(hashSaltForOrigin.value->documentOrigin);
     77        origins.add(hashSaltForOrigin.value->parentOrigin);
     78    }
    7679
    7780    RunLoop::main().dispatch([origins = WTFMove(origins), completionHandler = WTFMove(completionHandler)]() mutable {
    … …  
    8386{
    8487    m_deviceIdHashSaltForOrigins.removeIf([&origins](auto& keyAndValue) {
    85         return origins.contains(keyAndValue.value->documentOrigin);
     88        return origins.contains(keyAndValue.value->documentOrigin) || origins.contains(keyAndValue.value->parentOrigin);
    8689    });
    8790
  • trunk/Source/WebKit/UIProcess/DeviceIdHashSaltStorage.h

    r237988 r238724  
    3939    ~DeviceIdHashSaltStorage() = default;
    4040
    41     const String& deviceIdHashSaltForOrigin(const WebCore::SecurityOrigin&);
     41    const String& deviceIdHashSaltForOrigin(const WebCore::SecurityOrigin& documentOrigin, const WebCore::SecurityOrigin& parentOrigin);
    4242
    4343    void getDeviceIdHashSaltOrigins(CompletionHandler<void(HashSet<WebCore::SecurityOriginData>&&)>&&);
    … …  
    4747private:
    4848    struct HashSaltForOrigin {
    49         HashSaltForOrigin(WebCore::SecurityOriginData&& securityOrigin, String&& deviceIdHashSalt)
    50             : documentOrigin(securityOrigin)
     49        HashSaltForOrigin(WebCore::SecurityOriginData&& documentOrigin, WebCore::SecurityOriginData&& parentOrigin, String&& deviceIdHashSalt)
     50            : documentOrigin(WTFMove(documentOrigin))
     51            , parentOrigin(WTFMove(parentOrigin))
    5152            , deviceIdHashSalt(WTFMove(deviceIdHashSalt))
    5253            , lastTimeUsed(WallTime::now())
    … …  
    5455
    5556        WebCore::SecurityOriginData documentOrigin;
     57        WebCore::SecurityOriginData parentOrigin;
    5658        String deviceIdHashSalt;
    5759        WallTime lastTimeUsed;
  • trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp

    r237988 r238724  
    164164        return;
    165165
    166     auto deviceIDHashSalt = m_page.websiteDataStore().deviceIdHashSaltStorage()->deviceIdHashSaltForOrigin(request->topLevelDocumentSecurityOrigin());
     166    auto deviceIDHashSalt = m_page.websiteDataStore().deviceIdHashSaltStorage()->deviceIdHashSaltForOrigin(request->userMediaDocumentSecurityOrigin(), request->topLevelDocumentSecurityOrigin());
    167167    if (grantAccess(userMediaID, WTFMove(audioDevice), WTFMove(videoDevice), WTFMove(deviceIDHashSalt)))
    168168        m_grantedRequests.append(request.releaseNonNull());
    … …  
    363363        syncWithWebCorePrefs();
    364364
    365         auto deviceIDHashSalt = m_page.websiteDataStore().deviceIdHashSaltStorage()->deviceIdHashSaltForOrigin(pendingRequest.value()->topLevelDocumentSecurityOrigin());
     365        auto deviceIDHashSalt = m_page.websiteDataStore().deviceIdHashSaltStorage()->deviceIdHashSaltForOrigin(pendingRequest.value()->userMediaDocumentSecurityOrigin(), pendingRequest.value()->topLevelDocumentSecurityOrigin());
    366366        RealtimeMediaSourceCenter::singleton().validateRequestConstraints(WTFMove(validHandler), WTFMove(invalidHandler), WTFMove(localUserRequest), WTFMove(deviceIDHashSalt));
    367367    };
    … …  
    400400{
    401401#if ENABLE(MEDIA_STREAM)
    402     auto completionHandler = [this, topOrigin = topLevelDocumentOrigin.copyRef()](uint64_t userMediaID, bool originHasPersistentAccess) {
     402    auto completionHandler = [this, requestOrigin = userMediaDocumentOrigin.copyRef(), topOrigin = topLevelDocumentOrigin.copyRef()](uint64_t userMediaID, bool originHasPersistentAccess) {
    403403        auto pendingRequest = m_pendingDeviceRequests.take(userMediaID);
    404404        if (!pendingRequest)
    … …  
    415415        });
    416416
    417         auto deviceIDHashSalt = m_page.websiteDataStore().deviceIdHashSaltStorage()->deviceIdHashSaltForOrigin(topOrigin.get());
     417        auto deviceIDHashSalt = m_page.websiteDataStore().deviceIdHashSaltStorage()->deviceIdHashSaltForOrigin(requestOrigin.get(), topOrigin.get());
    418418        m_page.process().send(Messages::WebPage::DidCompleteMediaDeviceEnumeration(userMediaID, WTFMove(devices), WTFMove(deviceIDHashSalt), WTFMove(originHasPersistentAccess)), m_page.pageID());
    419419    };
Note: See TracChangeset for help on using the changeset viewer.