Bug 171877 - [MediaStream] deviceId constraint doesn't work with getUserMedia
Summary: [MediaStream] deviceId constraint doesn't work with getUserMedia
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: Other
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Eric Carlson
URL:
Keywords: InRadar
Depends on: 171889
Blocks:
  Show dependency treegraph
 
Reported: 2017-05-09 12:41 PDT by Eric Carlson
Modified: 2017-05-15 09:05 PDT (History)
8 users (show)

See Also:


Attachments
Proposed patch. (51.31 KB, patch)
2017-05-09 13:44 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Patch for landing. (51.27 KB, patch)
2017-05-09 14:25 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ews104 for mac-elcapitan-wk2 (910.65 KB, application/zip)
2017-05-09 14:57 PDT, Build Bot
no flags Details
Update patch. (51.45 KB, patch)
2017-05-09 20:24 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Another patch. (73.50 KB, patch)
2017-05-11 09:40 PDT, Eric Carlson
buildbot: commit-queue-
Details | Formatted Diff | Diff
Archive of layout-test-results from ews106 for mac-elcapitan-wk2 (1.16 MB, application/zip)
2017-05-11 10:55 PDT, Build Bot
no flags Details
Updated patch. (73.35 KB, patch)
2017-05-11 12:03 PDT, Eric Carlson
buildbot: commit-queue-
Details | Formatted Diff | Diff
Archive of layout-test-results from ews107 for mac-elcapitan-wk2 (1.54 MB, application/zip)
2017-05-11 13:32 PDT, Build Bot
no flags Details
Updated patch. (73.58 KB, patch)
2017-05-11 13:44 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Patch for landing. (78.79 KB, patch)
2017-05-12 14:12 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Patch for landing. (78.86 KB, patch)
2017-05-12 15:15 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Patch for landing. (78.50 KB, patch)
2017-05-13 20:29 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Carlson 2017-05-09 12:41:36 PDT
deviceId constraint doesn't work with getUserMedia
Comment 1 Eric Carlson 2017-05-09 12:42:31 PDT
<rdar://problem/31899730>
Comment 2 Eric Carlson 2017-05-09 13:44:12 PDT
Created attachment 309533 [details]
Proposed patch.
Comment 3 Jer Noble 2017-05-09 14:22:21 PDT
Comment on attachment 309533 [details]
Proposed patch.

View in context: https://bugs.webkit.org/attachment.cgi?id=309533&action=review

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:319
> +        MediaConstraintsData localAudioConstraintsData = MediaConstraintsData(audioConstraintsData);
> +        localAudioConstraintsData.deviceIDHashSalt = deviceIdentifierHashSalt;
> +
> +        MediaConstraintsData localVideoConstraintsData = MediaConstraintsData(videoConstraintsData);
> +        localVideoConstraintsData.deviceIDHashSalt = deviceIdentifierHashSalt;
> +
> +        auto audioConstraints = MediaConstraintsImpl::create(WTFMove(localAudioConstraintsData));
> +        auto videoConstraints = MediaConstraintsImpl::create(WTFMove(localVideoConstraintsData));

Nit: this is really wordy. Could we maybe add some way of creating an Impl with just a MediaConstraintsData and a salt?
Comment 4 Eric Carlson 2017-05-09 14:25:28 PDT
Comment on attachment 309533 [details]
Proposed patch.

View in context: https://bugs.webkit.org/attachment.cgi?id=309533&action=review

>> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:319
>> +        auto videoConstraints = MediaConstraintsImpl::create(WTFMove(localVideoConstraintsData));
> 
> Nit: this is really wordy. Could we maybe add some way of creating an Impl with just a MediaConstraintsData and a salt?

Good idea, fixed.
Comment 5 Eric Carlson 2017-05-09 14:25:55 PDT
Created attachment 309540 [details]
Patch for landing.
Comment 6 youenn fablet 2017-05-09 14:39:51 PDT
Looks good to me too.
Main question is I am not sure why we need both a userMediaDocumentSecurityOrigin and a topLevelDocumentSecurityOrigin.
Some nits below that could be addressed as follow-ups.

View in context: https://bugs.webkit.org/attachment.cgi?id=309533&action=review

> Source/WebCore/ChangeLog:31
> +        (WebCore::RealtimeMediaSource::selectSettings): Special case DeviceId because it

s/it//

> Source/WebKit2/UIProcess/UserMediaPermissionCheckProxy.cpp:42
> +    , m_topLevelDocumentSecurityOrigin(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier)->securityOrigin())

We have these two security origins. Why isn't it sufficient to have one?

> Source/WebKit2/UIProcess/UserMediaPermissionCheckProxy.h:55
> +    WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin() { return &m_topLevelDocumentSecurityOrigin.get(); }

We should return references.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:68
> +void FrameAuthorizationState::ensureSecurityOriginsAreEqual(WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin, WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin)

Is it ok to pass null pointers for both of these?
Probably should pass as const.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:87
> +FrameAuthorizationState& UserMediaPermissionRequestManagerProxy::stateForRequest(RequestType& request)

Pass a const RequestType&?

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:188
> +    auto frameState = stateForRequest(*request);

auto&?

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:309
> +    auto validateConstraintsHandler = [this, userMediaID, validHandler, invalidHandler, audioConstraintsData, videoConstraintsData](const String& deviceIdentifierHashSalt) {

In theory, we should probably do something like validHandler = WTFMove(validHandler) and ditto for invalidHander.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:321
> +        RealtimeMediaSourceCenter::singleton().validateRequestConstraints(validHandler, invalidHandler, audioConstraints, videoConstraints);

Then we should move validHandler and validHandler. Might need mark  validateConstraintsHandler as mutable.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:324
> +    auto haveDeviceSaltHandler = [this, userMediaID, frameID, validateConstraintsHandler](uint64_t userMediaID, const String& deviceIdentifierHashSalt, bool originHasPersistentAccess) {

Ditto for moving validateConstraintsHandler I think.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:357
> +void UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&& handler, const String&& userMediaDocumentOriginIdentifier, const String&& topLevelDocumentOriginIdentifier)

Why const String&&?

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:379
> +void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, String userMediaDocumentOriginIdentifier, String topLevelDocumentOriginIdentifier)

Should be String&& probably

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h:49
> +    void setDeviceIdentifierHashSalt(const String& hashSalt) { m_deviceIdentifierHashSalt = hashSalt; }

Should be String&&.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h:50
> +    String deviceIdentifierHashSalt() const { return m_deviceIdentifierHashSalt; }

Can we make it a const String&?

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h:94
> +    void getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&&, const String&&userMediaDocumentOriginIdentifier, const String&& topLevelDocumentOriginIdentifier);

String&& and space
Comment 7 Build Bot 2017-05-09 14:57:53 PDT
Comment on attachment 309533 [details]
Proposed patch.

Attachment 309533 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.webkit.org/results/3707616

New failing tests:
fast/mediastream/MediaDevices-enumerateDevices.html
Comment 8 Build Bot 2017-05-09 14:57:54 PDT
Created attachment 309547 [details]
Archive of layout-test-results from ews104 for mac-elcapitan-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: ews104  Port: mac-elcapitan-wk2  Platform: Mac OS X 10.11.6
Comment 9 WebKit Commit Bot 2017-05-09 15:06:17 PDT
Comment on attachment 309540 [details]
Patch for landing.

Clearing flags on attachment: 309540

Committed r216545: <http://trac.webkit.org/changeset/216545>
Comment 10 Eric Carlson 2017-05-09 20:24:00 PDT
Patch was rolled out in r216550.
Comment 11 Eric Carlson 2017-05-09 20:24:34 PDT
Created attachment 309575 [details]
Update patch.
Comment 12 WebKit Commit Bot 2017-05-09 21:42:22 PDT
Comment on attachment 309575 [details]
Update patch.

Clearing flags on attachment: 309575

Committed r216563: <http://trac.webkit.org/changeset/216563>
Comment 13 Ryan Haddad 2017-05-10 09:50:08 PDT
(In reply to WebKit Commit Bot from comment #12)
> Comment on attachment 309575 [details]
> Update patch.
> 
> Clearing flags on attachment: 309575
> 
> Committed r216563: <http://trac.webkit.org/changeset/216563>

This change caused 2 API test failures as well as an assertion failure:

WebKit2.UserMediaBasic and MediaCaptureDisabledTest.EnableAndDisable
https://build.webkit.org/builders/Apple%20El%20Capitan%20Release%20WK2%20%28Tests%29/builds/1389/steps/run-api-tests/logs/stdio

fast/mediastream/apply-constraints-video.html
https://build.webkit.org/results/Apple%20El%20Capitan%20Debug%20WK2%20(Tests)/r216581%20(1025)/results.html
Comment 14 Matt Lewis 2017-05-10 10:30:24 PDT
Reverted r216563 for reason:

Revision caused 2 api failures

Committed r216596: <http://trac.webkit.org/changeset/216596>
Comment 15 Eric Carlson 2017-05-11 09:40:27 PDT
Created attachment 309717 [details]
Another patch.
Comment 16 Eric Carlson 2017-05-11 10:16:47 PDT
The GTK breakage looks unrelated:
gtk-wk2-ews/WebKit/Source/WebKit2/WebKit2Prefix.h -Wno-unused-parameter -MMD -MT Source/WebKit2/CMakeFiles/WebKit2.dir/UIProcess/API/gtk/WebKitInstallMissingMediaPluginsPermissionRequest.cpp.o -MF Source/WebKit2/CMakeFiles/WebKit2.dir/UIProcess/API/gtk/WebKitInstallMissingMediaPluginsPermissionRequest.cpp.o.d -o Source/WebKit2/CMakeFiles/WebKit2.dir/UIProcess/API/gtk/WebKitInstallMissingMediaPluginsPermissionRequest.cpp.o -c ../../Source/WebKit2/UIProcess/API/gtk/WebKitInstallMissingMediaPluginsPermissionRequest.cpp
g++: internal compiler error: Killed (program cc1plus)
libbacktrace could not find executable to open
Please submit a full bug report,
Comment 17 Build Bot 2017-05-11 10:55:35 PDT
Comment on attachment 309717 [details]
Another patch.

Attachment 309717 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.webkit.org/results/3718906

New failing tests:
fast/mediastream/get-user-media-device-id.html
fast/mediastream/MediaDevices-getUserMedia.html
Comment 18 Build Bot 2017-05-11 10:55:37 PDT
Created attachment 309727 [details]
Archive of layout-test-results from ews106 for mac-elcapitan-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: ews106  Port: mac-elcapitan-wk2  Platform: Mac OS X 10.11.6
Comment 19 Eric Carlson 2017-05-11 12:03:49 PDT
Created attachment 309744 [details]
Updated patch.
Comment 20 Build Bot 2017-05-11 13:32:40 PDT
Comment on attachment 309744 [details]
Updated patch.

Attachment 309744 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.webkit.org/results/3719927

New failing tests:
fast/mediastream/MediaDevices-getUserMedia.html
Comment 21 Build Bot 2017-05-11 13:32:41 PDT
Created attachment 309766 [details]
Archive of layout-test-results from ews107 for mac-elcapitan-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: ews107  Port: mac-elcapitan-wk2  Platform: Mac OS X 10.11.6
Comment 22 Eric Carlson 2017-05-11 13:44:43 PDT
Created attachment 309770 [details]
Updated patch.
Comment 23 youenn fablet 2017-05-11 14:05:02 PDT
Some ideas for code improvements as a follow-up patch.
There is one straightfroward issue that needs to be fixed though (moving a variable and reusing it afterwards).

View in context: https://bugs.webkit.org/attachment.cgi?id=309744&action=review

> Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h:49
> +    MediaConstraintsData(const MediaConstraints& constraints)

Shouldn't it be marked explicit?

> Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h:56
> +    MediaConstraintsData(const MediaConstraintsData& constraints, const String& hashSalt)

hashSalt should be a String&&, and we could do something like String&& = { } to remove the above constructor.
I am not sure where it is used by the way.
Maybe we should just beef up MediaConstraintsData(MediaTrackConstraintSetMap&&, Vector<MediaTrackConstraintSetMap>&&, bool) to take a String&& instead?

> Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h:85
> +    String deviceIDHashSalt() const final { return m_data.deviceIDHashSalt; }

Should be a const String& I think.

> Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h:86
> +    void setDeviceIDHashSalt(const String& salt) final { m_data.deviceIDHashSalt = salt; }

Should be taking a String&&

> Source/WebCore/Modules/mediastream/MediaDevices.h:85
> +    std::optional<RealtimeMediaSourceCenter::DevicesChangedObserverToken> m_deviceChangedToken;

I do not understand that change. Having 0 as a special 'unset' value seems fine with me.
What is the issue with the previous code?

> Source/WebCore/Modules/mediastream/UserMediaRequest.cpp:159
>      m_allowedVideoDeviceUID = videoDeviceUID;

audioDeviceUID and videoDeviceUID should be String&&.

> Source/WebCore/platform/mediastream/MediaConstraints.h:814
> +    virtual String deviceIDHashSalt() const = 0;

Ditto on changes the signature here.

> Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp:502
> +bool RealtimeMediaSource::selectSettings(const MediaConstraints& constraints, FlattenedConstraint& candidates, String& failedConstraint, SelectType type)

I guess the alternative approach would be for selectSettings to remove deviceId constraints when not being useful.
But this conflicts with const& signature. Seems fine.

> Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp:552
> +            double constraintDistance = downcast<StringConstraint>(constraint).fitnessDistance(hashedID);

If we have several downcast<> like this, maybe we should encapsulate this in MediaConstraint, for instance constraint.asStringConstraint().
Or a templated fitnessDistance, but maybe that would cause more harm.

> Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp:183
> +    static NeverDestroyed<HashMap<unsigned, std::function<void()>>> map;

I am not sure this is healthy to add more static variables.
We should at least move this code closer to RealtimeMediaSourceCenter::singleton() so that if want to attach RealtimeMediaSourceCenter to the page, or to the process later on, we do not forget about this one.

> Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp:202
> +    auto callbacks = observerMap();

Do we want to make a separate copy of the map? Should it be auto&.

> Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp:203
>      for (auto it : callbacks)

Probably want auto& here? and use iterator instead of it.

> Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp:253
> +            audioSourceIds.uncheckedAppend(info.id);

Nit: since we do not reuse audioDeviceInfo, we could probably take a for(auto& info..) and do audioSourceIds.uncheckedAppend(WTFMove(info.id))

> Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp:261
> +            videoSourceIds.uncheckedAppend(info.id);

Ditto here.

> Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:169
> +    invalidConstraint = emptyString();

Are we adding that for safety reasons? Since sourceUIDs is not empty, the value should be ignored, right?
The new pattern would be to add a VectorOfStringOrErrorMessage.

Btw, if we fail to create several sources on several devices, we will only pick the last invalid constraint. Is it ok?

> Source/WebKit2/UIProcess/UserMediaPermissionCheckProxy.cpp:42
> +    , m_topLevelDocumentSecurityOrigin(SecurityOriginData::fromDatabaseIdentifier(topLevelDocumentOriginIdentifier)->securityOrigin())

Should probably directly take Ref<SecurityOrigin>&& instead of strings here.
Future refactoring probably.

> Source/WebKit2/UIProcess/UserMediaPermissionCheckProxy.h:55
> +    WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin() { return &m_topLevelDocumentSecurityOrigin.get(); }

Should return references.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:44
> +    , m_topLevelDocumentSecurityOrigin(topLevelDocumentSecurityOrigin)

These might well be references and not pointers.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:68
> +void FrameAuthorizationState::ensureSecurityOriginsAreEqual(WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin, WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin)

Probably here as well. Should take const& as well.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:87
> +FrameAuthorizationState& UserMediaPermissionRequestManagerProxy::stateForRequest(RequestType& request)

Can probably take a const RequestType&

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:275
> +        auto userMediaOrigin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(userMediaDocumentOriginIdentifier).value_or(SecurityOriginData()).securityOrigin());

RequestUserMediaPermissionForFrame should take WebCore::SecurityOriginData as input parameter not strings.
This would remove the need for conversions.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:315
> +        RealtimeMediaSourceCenter::singleton().validateRequestConstraints(WTFMove(validHandler), WTFMove(invalidHandler), audioConstraints, videoConstraints);

I don't know if this is always the case, but here we could move the constraints so that the underlying implementation would be fine modifying these constraints.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:325
> +            return;

Should we do this check before taking the request?
If so, can request be null in some cases? Probably but asking the question anyway.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:350
> +    UserMediaPermissionCheckProxy::CompletionHandler failureHandler = handler;

Since you move handler in the request, failureHandler will be empty here.
Probably not good.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:354
> +        failureHandler(userMediaID, String(), false);

Can you do something like request->reportFailure(...) to handle the case above?

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:368
> +            return;

Same question/comment as above.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:374
> +        auto deviceInfo = RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();

We are creating a Vector for each call to getMediaStreamDevices.
DidCompleteMediaDeviceEnumeration expecting a const&, this Vector allocation seems unnecessary.
Might be worth changing the signature in the future.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h:47
> +    void ensureSecurityOriginsAreEqual(WebCore::SecurityOrigin* userMediaDocumentSecurityOrigin, WebCore::SecurityOrigin* topLevelDocumentSecurityOrigin);

Probably want references here and Ref<SecurityOrigin> below.

> Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h:49
> +    void setDeviceIdentifierHashSalt(const String& hashSalt) { m_deviceIdentifierHashSalt = hashSalt; }

Should be String&&
Comment 24 Eric Carlson 2017-05-12 14:12:20 PDT
Created attachment 309942 [details]
Patch for landing.
Comment 25 Eric Carlson 2017-05-12 15:15:29 PDT
Created attachment 309954 [details]
Patch for landing.
Comment 26 Eric Carlson 2017-05-13 20:29:30 PDT
Created attachment 310056 [details]
Patch for landing.
Comment 27 WebKit Commit Bot 2017-05-13 22:27:22 PDT
Comment on attachment 310056 [details]
Patch for landing.

Clearing flags on attachment: 310056

Committed r216836: <http://trac.webkit.org/changeset/216836>