<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>179220</bug_id>
          
          <creation_ts>2017-11-02 17:37:18 -0700</creation_ts>
          <short_desc>mediaDevices.enumerateDevices(), device ids change on page refresh</short_desc>
          <delta_ts>2021-02-09 02:47:57 -0800</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>WebRTC</component>
          <version>WebKit Nightly Build</version>
          <rep_platform>Mac</rep_platform>
          <op_sys>macOS 10.12</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>CONFIGURATION CHANGED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Chad Phillips">webkit</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>eric.carlson</cc>
    
    <cc>jake</cc>
    
    <cc>jonlee</cc>
    
    <cc>matthias.rauch</cc>
    
    <cc>philipp.weissensteiner</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>youennf</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1367657</commentid>
    <comment_count>0</comment_count>
    <who name="Chad Phillips">webkit</who>
    <bug_when>2017-11-02 17:37:18 -0700</bug_when>
    <thetext>I&apos;ve used the following Javascript as a test on Firefox, Chrome, and Safari:

      var constraints = {
        audio: false,
        video: true,
      };
      navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
        navigator.mediaDevices.enumerateDevices().then(function(devices) {
          devices.forEach(function(device) {
            console.log(device.kind + &quot;: &quot; + device.label + &quot; id = &quot; + device.deviceId);
          });
        });
      }).catch(function(err) {
        console.error(&quot;Device access checks failed: &quot;, err, constraints);
      });

Both Firefox and Chrome preserve device ids across page refreshes (further testing with Chrome shows they are preserved even across machine reboots).

However, Safari does not preserve the device ids at all -- they are completely different across page refreshes.

This is problematic, as it makes it much more difficult for applications to &apos;remember&apos; which devices a user prefers, having to fall back to matching on device.label, which isn&apos;t fully reliable.

Confirmed this issue still exists as of r224308.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1369896</commentid>
    <comment_count>1</comment_count>
    <who name="">philipp.weissensteiner</who>
    <bug_when>2017-11-09 09:12:20 -0800</bug_when>
    <thetext>I can reproduce this on the iOS (11.1) but it seems to be working as expected on macOS.
Running Version 11.0.1 (12604.3.5.1.1).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1370598</commentid>
    <comment_count>2</comment_count>
    <who name="Chad Phillips">webkit</who>
    <bug_when>2017-11-10 16:54:58 -0800</bug_when>
    <thetext>@philipp, I can replicate the issue on latest stable desktop Safari for OS X Sierra (Version 11.0.1 (12604.3.5.1.1)), and also on latest Webkit build (r224711) on Sierra, so I don&apos;t think the desktop version is working properly.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1370601</commentid>
    <comment_count>3</comment_count>
      <attachid>326661</attachid>
    <who name="Chad Phillips">webkit</who>
    <bug_when>2017-11-10 16:56:46 -0800</bug_when>
    <thetext>Created attachment 326661
Test case #1

Here&apos;s a fully working test case which illustrates the issue.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1371332</commentid>
    <comment_count>4</comment_count>
    <who name="">philipp.weissensteiner</who>
    <bug_when>2017-11-14 01:08:16 -0800</bug_when>
    <thetext>My bad. Yes I can also reproduce it the desktop version of Safari.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1374949</commentid>
    <comment_count>5</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2017-11-27 08:58:04 -0800</bug_when>
    <thetext>&lt;rdar://problem/35698762&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1374959</commentid>
    <comment_count>6</comment_count>
    <who name="youenn fablet">youennf</who>
    <bug_when>2017-11-27 09:16:42 -0800</bug_when>
    <thetext>These ids are very close to cookies and some restrictions have been put in place to ensure privacy.
We can try to relax some constraints but we should be very cautious here.

Can you detail how you are using these ids? Is it as part of getUserMedia constraints?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1374999</commentid>
    <comment_count>7</comment_count>
    <who name="Chad Phillips">webkit</who>
    <bug_when>2017-11-27 10:43:57 -0800</bug_when>
    <thetext>The use case is quite simple: device IDs are stored (in my app, in browser localstorage) so they can be passed to gUM requests, such that a specific device is used.

This allows an app to &apos;remember&apos; a user&apos;s preference for camera/mic/speakers across visits. This is particularly important in two cases:

 1. The user has an additional hardware camera that they prefer to use as their camera for the app in question.

 2. Some multi-camera devices (most notably Microsoft Surface) have the rear-facing camera as its default, and no easy way in the device settings to change that. Therefore it falls on the app to provide a decent default user experience.

To quote from https://webkit.org/blog/7763/a-closer-look-into-webrtc/

&quot;navigator.mediaDevices.enumerateDevices exposes the list of capture devices available, and can be queried by websites even when access to those devices is not granted. For users that have custom camera and microphone setups, this can add to a user’s fingerprinting surface. When access hasn’t yet been requested or is explicitly denied, WebKit avoids exposing this additional information by returning a default list of devices that may not correspond to the actual set of devices available.&quot;

From a security perspective, it makes perfect sense that dummy/random device IDs would be provided prior to a user granting device access. This makes much less sense once the user has granted access -- especially in the examples above, it makes for a worse experience for the user and the developer.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1376877</commentid>
    <comment_count>8</comment_count>
    <who name="youenn fablet">youennf</who>
    <bug_when>2017-12-01 10:16:59 -0800</bug_when>
    <thetext>I wonder whether we could not provide the functionality you want without the fingerprinting issue.

Would it be fine if:
- WebKit stores persistently which capture devices were last selected by a web site, at least if changed from the default selected ones.
- Reuse those devices for subsequent selections

That way, you would probably get what you want without having to handle device ids.
If you do not get what you want, you might be able to use label/kind attributes after getting camera/microphone access to further refine selection.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1383859</commentid>
    <comment_count>9</comment_count>
    <who name="Chad Phillips">webkit</who>
    <bug_when>2017-12-20 15:33:32 -0800</bug_when>
    <thetext>@youenn, that sounds awfully complicated.

How would I, in Javascript, know that Safari has &apos;remembered&apos; a device, and that device matches the one selected by a user?

This also creates a split between Safari handling the picking of the device, and my own code having to maybe, sometimes, handle it. I think it would be cleaner if the developer always did it, and in this case, the most accurate way to always pick the right device is a reliable machine ID.

I&apos;ve already built code that looks up the previous device based on the device label, and it&apos;s an OK workaround for now, but definitely not as accurate or reliable as a machine ID.

If we can&apos;t have consistent IDs, I&apos;d favor what I&apos;m doing now over what you&apos;re suggesting.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1383861</commentid>
    <comment_count>10</comment_count>
    <who name="youenn fablet">youennf</who>
    <bug_when>2017-12-20 15:40:34 -0800</bug_when>
    <thetext>(In reply to Chad Phillips from comment #9)
&gt; @youenn, that sounds awfully complicated.
&gt; 
&gt; How would I, in Javascript, know that Safari has &apos;remembered&apos; a device, and
&gt; that device matches the one selected by a user?
&gt; 
&gt; This also creates a split between Safari handling the picking of the device,
&gt; and my own code having to maybe, sometimes, handle it. I think it would be
&gt; cleaner if the developer always did it, and in this case, the most accurate
&gt; way to always pick the right device is a reliable machine ID.
&gt; 
&gt; I&apos;ve already built code that looks up the previous device based on the
&gt; device label, and it&apos;s an OK workaround for now, but definitely not as
&gt; accurate or reliable as a machine ID.
&gt; 
&gt; If we can&apos;t have consistent IDs, I&apos;d favor what I&apos;m doing now over what
&gt; you&apos;re suggesting.

Good to hear the label workaround is working fine.

What I am proposing should allow the browser to do what your application is doing right now.
When in Safari, you would disable the automatic device selection and would only implement explicit user device selection.
If it does not work as is, I agree we should not bother implementing it.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1617853</commentid>
    <comment_count>11</comment_count>
    <who name="Jake">jake</who>
    <bug_when>2020-02-11 20:38:38 -0800</bug_when>
    <thetext>What is the status of this?
I can&apos;t reproduce this on Safari 13.0.4 and the last comment was over two years ago.
It seems other browsers are taking the approach of treating deviceId like cookies and persisting until the user clears.
Should this bug be marked as resolved?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1617951</commentid>
    <comment_count>12</comment_count>
    <who name="youenn fablet">youennf</who>
    <bug_when>2020-02-12 06:38:19 -0800</bug_when>
    <thetext>Right, this is now fixed.
Device ids should persist but be available after a getUserMedia successful call in usual cases.</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>326661</attachid>
            <date>2017-11-10 16:56:46 -0800</date>
            <delta_ts>2017-11-10 16:56:46 -0800</delta_ts>
            <desc>Test case #1</desc>
            <filename>enumerate-devices.html</filename>
            <type>text/html</type>
            <size>1062</size>
            <attacher name="Chad Phillips">webkit</attacher>
            
              <data encoding="base64">PCFET0NUWVBFIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0iVVRGLTgi
PgogICAgPHRpdGxlPkVudW1lcmF0ZSBkZXZpY2VzPC90aXRsZT4KICA8L2hlYWQ+CiAgPGJvZHk+
CiAgICA8ZGl2IGlkPSJkZXZpY2UtbGlzdCI+CiAgICA8L2Rpdj4KICAgIDxzY3JpcHQgdHlwZT0i
dGV4dC9qYXZhc2NyaXB0Ij4KICAgICAgdmFyIGRldmljZV9saXN0ID0gZG9jdW1lbnQuZ2V0RWxl
bWVudEJ5SWQoJ2RldmljZS1saXN0Jyk7CiAgICAgIHZhciBjb25zdHJhaW50cyA9IHsKICAgICAg
ICBhdWRpbzogdHJ1ZSwKICAgICAgICB2aWRlbzogdHJ1ZSwKICAgICAgfTsKICAgICAgbmF2aWdh
dG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHMpLnRoZW4oZnVuY3Rpb24o
c3RyZWFtKSB7CiAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2Vz
KCkudGhlbihmdW5jdGlvbihkZXZpY2VzKSB7CiAgICAgICAgICBkZXZpY2VzLmZvckVhY2goZnVu
Y3Rpb24oZGV2aWNlKSB7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKGRldmljZSk7CiAgICAgICAg
ICAgIHZhciBkZXZpY2VfdGV4dCA9IGRldmljZS5raW5kICsgIjogIiArIGRldmljZS5kZXZpY2VJ
ZDsKICAgICAgICAgICAgdmFyIGxhYmVsID0gZGV2aWNlLmxhYmVsID8gJyAoJyArIGRldmljZS5s
YWJlbCArICcpJyA6ICcnOwogICAgICAgICAgICBkZXZpY2VfbGlzdC5pbnNlcnRBZGphY2VudEhU
TUwoJ2JlZm9yZWVuZCcsICc8ZGl2PicgKyBkZXZpY2VfdGV4dCArIGxhYmVsICsgJzwvZGl2Picp
OwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgc3RyZWFtLmdldFRyYWNrcygpLmZv
ckVhY2goZnVuY3Rpb24odHJhY2spIHsKICAgICAgICAgIHRyYWNrLnN0b3AoKTsKICAgICAgICB9
KTsKICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oZXJyKSB7CiAgICAgICAgY29uc29sZS5lcnJvcigi
RGV2aWNlIGFjY2VzcyBjaGVja3MgZmFpbGVkOiAiLCBlcnIsIGNvbnN0cmFpbnRzKTsKICAgICAg
fSk7CiAgICA8L3NjcmlwdD4KICA8L2JvZHk+CjwvaHRtbD4K
</data>

          </attachment>
      

    </bug>

</bugzilla>