Diff
Modified: trunk/LayoutTests/ChangeLog (236464 => 236465)
--- trunk/LayoutTests/ChangeLog 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/LayoutTests/ChangeLog 2018-09-25 18:37:29 UTC (rev 236465)
@@ -1,3 +1,13 @@
+2018-09-25 Eric Carlson <[email protected]>
+
+ [MediaStream] Update constraints supported by getDisplayMedia
+ https://bugs.webkit.org/show_bug.cgi?id=189930
+
+ Reviewed by Youenn Fablet.
+
+ * http/tests/media/media-stream/get-display-media-prompt-expected.txt:
+ * http/tests/media/media-stream/get-display-media-prompt.html:
+
2018-09-25 Ryan Haddad <[email protected]>
[resource-timing] imported/w3c/web-platform-tests/resource-timing/resource_timing.worker.html times out on WK1
Modified: trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt-expected.txt (236464 => 236465)
--- trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt-expected.txt 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt-expected.txt 2018-09-25 18:37:29 UTC (rev 236465)
@@ -5,26 +5,49 @@
PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 0
-** Request an audio-only stream, the user should be prompted **
+** Request an audio-only stream, the user should not be prompted **
+PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 0
+PASS stream is undefined.
+PASS err instanceof Error is true
+PASS err.name is "TypeError"
+
+** Request an video-only stream, the user should be prompted **
PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 1
-PASS stream.getAudioTracks().length is 1
-PASS stream.getVideoTracks().length is 0
+PASS stream.getAudioTracks().length is 0
+PASS stream.getVideoTracks().length is 1
-** Request an video-only stream, the user should be prompted **
+** Request a stream with audio and video, the user should be prompted but no audio track should be created **
PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
PASS stream.getAudioTracks().length is 0
PASS stream.getVideoTracks().length is 1
-** Request a stream with audio and video, the user should be prompted **
+** Request a stream with 'max' constraints, the user should not be prompted **
+PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
+PASS stream is undefined.
+PASS err instanceof Error is true
+PASS err.name is "TypeError"
+
+** Request a stream with 'min' constraints, the user should not be prompted **
+PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
+PASS stream is undefined.
+PASS err instanceof Error is true
+PASS err.name is "TypeError"
+
+** Request a stream with 'advanced' constraints, the user should not be prompted **
+PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
+PASS stream is undefined.
+PASS err instanceof Error is true
+PASS err.name is "TypeError"
+
+** Request a stream with valid constraints, the user should be prompted **
PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 3
-PASS stream.getAudioTracks().length is 1
+PASS stream.getAudioTracks().length is 0
PASS stream.getVideoTracks().length is 1
-** Request a stream with invalid constraints, the user should not be prompted **
-PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 3
-PASS stream is null
-PASS err instanceof Error is true
-PASS err.name is "InvalidAccessError"
+** Request a stream with an exact audio constraint, it should be ignored **
+PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 4
+PASS stream.getAudioTracks().length is 0
+PASS stream.getVideoTracks().length is 1
PASS successfullyParsed is true
Modified: trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt.html (236464 => 236465)
--- trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt.html 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt.html 2018-09-25 18:37:29 UTC (rev 236465)
@@ -18,44 +18,90 @@
}
async function promptForAudioOnly() {
- debug("<br>** Request an audio-only stream, the user should be prompted **");
- stream = await navigator.mediaDevices.getDisplayMedia({ audio: true });
- shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "1");
- shouldBe("stream.getAudioTracks().length", "1");
- shouldBe("stream.getVideoTracks().length", "0");
+ debug("<br>** Request an audio-only stream, the user should not be prompted **");
+ stream = await navigator.mediaDevices.getDisplayMedia({ audio: true })
+ .catch((e) => { err = e; });
+ shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "0");
+ shouldBeUndefined("stream");
+ shouldBeTrue("err instanceof Error ");
+ shouldBeEqualToString("err.name", "TypeError");
}
async function promptForVideoOnly() {
debug("<br>** Request an video-only stream, the user should be prompted **");
stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
- shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
+ shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "1");
shouldBe("stream.getAudioTracks().length", "0");
shouldBe("stream.getVideoTracks().length", "1");
}
async function promptForAudioAndVideo() {
- debug("<br>** Request a stream with audio and video, the user should be prompted **");
+ debug("<br>** Request a stream with audio and video, the user should be prompted but no audio track should be created **");
stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });
- shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "3");
- shouldBe("stream.getAudioTracks().length", "1");
+ shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
+ shouldBe("stream.getAudioTracks().length", "0");
shouldBe("stream.getVideoTracks().length", "1");
}
- async function promptWithMediaTrackConstraints() {
- debug("<br>** Request a stream with invalid constraints, the user should not be prompted **");
+ async function promptWithExactVideoConstraints() {
+ debug("<br>** Request a stream with 'max' constraints, the user should not be prompted **");
+
stream = null;
- try {
- stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: {exact: 640}, height: {exact: 480}} });
- } catch (e) {
- err = e;
- }
+ stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: {exact: 640}, height: {exact: 480}} })
+ .catch((e) => { err = e; });
+ shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
+ shouldBeUndefined("stream");
+ shouldBeTrue("err instanceof Error ");
+ shouldBeEqualToString("err.name", "TypeError");
+ }
+
+ async function promptWithMinVideoConstraints() {
+ debug("<br>** Request a stream with 'min' constraints, the user should not be prompted **");
+
+ stream = null;
+ stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: {min: 640}, height: {min: 480}} })
+ .catch((e) => { err = e; });
+ shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
+ shouldBeUndefined("stream");
+ shouldBeTrue("err instanceof Error ");
+ shouldBeEqualToString("err.name", "TypeError");
+ }
+
+ async function promptWithAdvancedVideoConstraints() {
+ debug("<br>** Request a stream with 'advanced' constraints, the user should not be prompted **");
+
+ stream = null;
+ stream = await navigator.mediaDevices.getDisplayMedia({ video: { width: 640, height: 480, advanced: [ { width: 1920, height: 1280 } ] } })
+ .catch((e) => { err = e; });
+ shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
+ shouldBeUndefined("stream");
+ shouldBeTrue("err instanceof Error ");
+ shouldBeEqualToString("err.name", "TypeError");
+ }
+
+ async function promptWithValidVideoConstraints() {
+ debug("<br>** Request a stream with valid constraints, the user should be prompted **");
+
+ stream = null;
+ stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: 640, height: 480} })
+ .catch((e) => { err = e; });
+
shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "3");
- shouldBeNull("stream");
- shouldBeTrue("err instanceof Error ");
- shouldBeEqualToString("err.name", "InvalidAccessError");
+ shouldBe("stream.getAudioTracks().length", "0");
+ shouldBe("stream.getVideoTracks().length", "1");
}
+ async function promptWithInvalidAudioConstraint() {
+ debug("<br>** Request a stream with an exact audio constraint, it should be ignored **");
+
+ stream = null;
+ stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: { volume: { exact: 0.5 } } });
+ shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "4");
+ shouldBe("stream.getAudioTracks().length", "0");
+ shouldBe("stream.getVideoTracks().length", "1");
+ }
+
(async function() {
description('Test basic getDisplayMedia prompting behavior');
jsTestIsAsync = true;
@@ -68,7 +114,11 @@
await promptForAudioOnly();
await promptForVideoOnly();
await promptForAudioAndVideo();
- await promptWithMediaTrackConstraints();
+ await promptWithExactVideoConstraints();
+ await promptWithMinVideoConstraints();
+ await promptWithAdvancedVideoConstraints();
+ await promptWithValidVideoConstraints();
+ await promptWithInvalidAudioConstraint();
debug("");
finishJSTest();
Modified: trunk/Source/WebCore/ChangeLog (236464 => 236465)
--- trunk/Source/WebCore/ChangeLog 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/Source/WebCore/ChangeLog 2018-09-25 18:37:29 UTC (rev 236465)
@@ -1,3 +1,24 @@
+2018-09-25 Eric Carlson <[email protected]>
+
+ [MediaStream] Update constraints supported by getDisplayMedia
+ https://bugs.webkit.org/show_bug.cgi?id=189930
+
+ Reviewed by Youenn Fablet.
+
+ No new tests, updated http/tests/media/media-stream/get-display-media-prompt.html.
+
+ * Modules/mediastream/MediaDevices.cpp:
+ (WebCore::MediaDevices::getDisplayMedia const): Ignore audio constraints.
+
+ * Modules/mediastream/UserMediaRequest.cpp:
+ (WebCore::hasInvalidGetDisplayMediaConstraint): Check for invalid constraints.
+ (WebCore::UserMediaRequest::start): Check for invalid constraints.
+ (WebCore::UserMediaRequest::deny): Support new error.
+ * Modules/mediastream/UserMediaRequest.h:
+
+ * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+ (WebCore::RealtimeMediaSourceCenter::validateRequestConstraints):
+
2018-09-25 Xabier Rodriguez Calvar <[email protected]>
[EME] Fix variable name that should have gone in r236317
Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp (236464 => 236465)
--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp 2018-09-25 18:37:29 UTC (rev 236465)
@@ -120,7 +120,7 @@
if (!document)
return Exception { InvalidStateError };
- auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, createMediaConstraints(constraints.audio), createMediaConstraints(constraints.video) }, WTFMove(promise));
+ auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, { }, createMediaConstraints(constraints.video) }, WTFMove(promise));
if (request)
request->start();
Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp (236464 => 236465)
--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp 2018-09-25 18:37:29 UTC (rev 236465)
@@ -156,6 +156,74 @@
return true;
}
+static bool hasInvalidGetDisplayMediaConstraint(const MediaConstraints& constraints)
+{
+ // https://w3c.github.io/mediacapture-screen-share/#navigator-additions
+ // 1. Let constraints be the method's first argument.
+ // 2. For each member present in constraints whose value, value, is a dictionary, run the following steps:
+ // 1. If value contains a member named advanced, return a promise rejected with a newly created TypeError.
+ // 2. If value contains a member which in turn is a dictionary containing a member named either min or
+ // exact, return a promise rejected with a newly created TypeError.
+ if (!constraints.isValid)
+ return false;
+
+ if (!constraints.advancedConstraints.isEmpty())
+ return true;
+
+ bool invalid = false;
+ constraints.mandatoryConstraints.filter([&invalid] (const MediaConstraint& constraint) mutable {
+ switch (constraint.constraintType()) {
+ case MediaConstraintType::Width:
+ case MediaConstraintType::Height: {
+ auto& intConstraint = downcast<IntConstraint>(constraint);
+ int value;
+ invalid = intConstraint.getExact(value) || intConstraint.getMin(value);
+ break;
+ }
+
+ case MediaConstraintType::AspectRatio:
+ case MediaConstraintType::FrameRate: {
+ auto& doubleConstraint = downcast<DoubleConstraint>(constraint);
+ double value;
+ invalid = doubleConstraint.getExact(value) || doubleConstraint.getMin(value);
+ break;
+ }
+
+ case MediaConstraintType::DisplaySurface:
+ case MediaConstraintType::LogicalSurface: {
+ auto& boolConstraint = downcast<BooleanConstraint>(constraint);
+ bool value;
+ invalid = boolConstraint.getExact(value);
+ break;
+ }
+
+ case MediaConstraintType::FacingMode:
+ case MediaConstraintType::DeviceId:
+ case MediaConstraintType::GroupId: {
+ auto& stringConstraint = downcast<StringConstraint>(constraint);
+ Vector<String> values;
+ invalid = stringConstraint.getExact(values);
+ break;
+ }
+
+ case MediaConstraintType::SampleRate:
+ case MediaConstraintType::SampleSize:
+ case MediaConstraintType::Volume:
+ case MediaConstraintType::EchoCancellation:
+ // Ignored.
+ break;
+
+ case MediaConstraintType::Unknown:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ return invalid;
+ });
+
+ return invalid;
+}
+
void UserMediaRequest::start()
{
ASSERT(m_scriptExecutionContext);
@@ -165,21 +233,10 @@
}
if (m_request.type == MediaStreamRequest::Type::DisplayMedia) {
- // https://w3c.github.io/mediacapture-screen-share/#constraints
- // 5.2 Constraining Display Surface Selection
- // The getDisplayMedia function does not permit the use of constraints for selection of a source as described
- // in the getUserMedia() algorithm. Prior to invoking the getUserMedia() algorithm, if either of the video
- // and audio attributes are set to a MediaTrackConstraints value (as opposed to being absent or set to a
- // Boolean value), reject the promise with a InvalidAccessError and abort.
- if (m_request.videoConstraints.isValid && !(m_request.videoConstraints.mandatoryConstraints.isEmpty() && m_request.videoConstraints.advancedConstraints.isEmpty())) {
- deny(MediaAccessDenialReason::InvalidAccess);
+ if (hasInvalidGetDisplayMediaConstraint(m_request.videoConstraints)) {
+ deny(MediaAccessDenialReason::IllegalConstraint);
return;
}
-
- if (m_request.audioConstraints.isValid && !(m_request.audioConstraints.mandatoryConstraints.isEmpty() && m_request.audioConstraints.advancedConstraints.isEmpty())) {
- deny(MediaAccessDenialReason::InvalidAccess);
- return;
- }
}
// https://w3c.github.io/mediacapture-main/getusermedia.html#dom-mediadevices-getusermedia()
@@ -265,6 +322,10 @@
ExceptionCode code;
switch (reason) {
+ case MediaAccessDenialReason::IllegalConstraint:
+ RELEASE_LOG(MediaStream, "UserMediaRequest::deny - invalid constraints");
+ code = TypeError;
+ break;
case MediaAccessDenialReason::NoConstraints:
RELEASE_LOG(MediaStream, "UserMediaRequest::deny - no constraints");
code = TypeError;
Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h (236464 => 236465)
--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h 2018-09-25 18:37:29 UTC (rev 236465)
@@ -56,7 +56,7 @@
WEBCORE_EXPORT void setAllowedMediaDeviceUIDs(const String& audioDeviceUID, const String& videoDeviceUID);
WEBCORE_EXPORT void allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt);
- enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, InvalidAccess, OtherFailure };
+ enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, InvalidAccess, IllegalConstraint, OtherFailure };
WEBCORE_EXPORT void deny(MediaAccessDenialReason, const String& errorMessage = emptyString());
const Vector<String>& audioDeviceUIDs() const { return m_audioDeviceUIDs; }
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp (236464 => 236465)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp 2018-09-25 18:37:29 UTC (rev 236465)
@@ -207,72 +207,75 @@
m_deviceChangedObserver();
}
-void RealtimeMediaSourceCenter::validateRequestConstraints(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt)
+void RealtimeMediaSourceCenter::getDisplayMediaDevices(const MediaStreamRequest& request, Vector<DeviceInfo>& diaplayDeviceInfo, String& firstInvalidConstraint)
{
- struct DeviceInfo {
- unsigned fitnessScore;
- CaptureDevice device;
- };
+ if (!request.videoConstraints.isValid)
+ return;
- struct {
- bool operator()(const DeviceInfo& a, const DeviceInfo& b)
- {
- return a.fitnessScore < b.fitnessScore;
- }
- } sortBasedOnFitnessScore;
+ String invalidConstraint;
+ for (auto& device : displayCaptureDeviceManager().captureDevices()) {
+ if (!device.enabled())
+ return;
- Vector<DeviceInfo> audioDeviceInfo;
- Vector<DeviceInfo> videoDeviceInfo;
+ auto sourceOrError = videoFactory().createVideoCaptureSource(device, { });
+ if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.videoConstraints, invalidConstraint))
+ diaplayDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
- String firstInvalidConstraint;
- for (auto& device : getMediaStreamDevices()) {
- if (!device.enabled())
- continue;
+ if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
+ firstInvalidConstraint = invalidConstraint;
+ }
+}
- String invalidConstraint;
- CaptureSourceOrError sourceOrError;
- switch (device.type()) {
- case CaptureDevice::DeviceType::Camera: {
- if (request.type != MediaStreamRequest::Type::UserMedia || !request.videoConstraints.isValid)
+void RealtimeMediaSourceCenter::getUserMediaDevices(const MediaStreamRequest& request, Vector<DeviceInfo>& audioDeviceInfo, Vector<DeviceInfo>& videoDeviceInfo, String& firstInvalidConstraint)
+{
+ String invalidConstraint;
+ if (request.audioConstraints.isValid) {
+ for (auto& device : audioCaptureDeviceManager().captureDevices()) {
+ if (!device.enabled())
continue;
- auto sourceOrError = videoFactory().createVideoCaptureSource(device, { });
- if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.videoConstraints, invalidConstraint))
- videoDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
- break;
+ auto sourceOrError = audioFactory().createAudioCaptureSource(device, { });
+ if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.audioConstraints, invalidConstraint))
+ audioDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
+
+ if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
+ firstInvalidConstraint = invalidConstraint;
}
- case CaptureDevice::DeviceType::Microphone:
- if (request.audioConstraints.isValid) {
- auto sourceOrError = audioFactory().createAudioCaptureSource(device, { });
- if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.audioConstraints, invalidConstraint))
- audioDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
- }
- break;
- case CaptureDevice::DeviceType::Screen:
- case CaptureDevice::DeviceType::Application:
- case CaptureDevice::DeviceType::Window:
- case CaptureDevice::DeviceType::Browser: {
- if (request.type != MediaStreamRequest::Type::DisplayMedia)
+ }
+
+ if (request.videoConstraints.isValid) {
+ for (auto& device : videoCaptureDeviceManager().captureDevices()) {
+ if (!device.enabled())
continue;
- ASSERT(request.audioConstraints.mandatoryConstraints.isEmpty());
- ASSERT(request.videoConstraints.advancedConstraints.isEmpty());
- if (!request.videoConstraints.isValid || !request.videoConstraints.advancedConstraints.isEmpty() || !request.videoConstraints.mandatoryConstraints.isEmpty())
- continue;
auto sourceOrError = videoFactory().createVideoCaptureSource(device, { });
if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.videoConstraints, invalidConstraint))
videoDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
- break;
+
+ if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
+ firstInvalidConstraint = invalidConstraint;
}
- case CaptureDevice::DeviceType::Unknown:
- ASSERT_NOT_REACHED();
- break;
+ }
+}
+
+void RealtimeMediaSourceCenter::validateRequestConstraints(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt)
+{
+ struct {
+ bool operator()(const DeviceInfo& a, const DeviceInfo& b)
+ {
+ return a.fitnessScore < b.fitnessScore;
}
+ } sortBasedOnFitnessScore;
- if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
- firstInvalidConstraint = invalidConstraint;
- }
+ Vector<DeviceInfo> audioDeviceInfo;
+ Vector<DeviceInfo> videoDeviceInfo;
+ String firstInvalidConstraint;
+ if (request.type == MediaStreamRequest::Type::DisplayMedia)
+ getDisplayMediaDevices(request, videoDeviceInfo, firstInvalidConstraint);
+ else
+ getUserMediaDevices(request, audioDeviceInfo, videoDeviceInfo, firstInvalidConstraint);
+
if ((request.audioConstraints.isValid && audioDeviceInfo.isEmpty()) || (request.videoConstraints.isValid && videoDeviceInfo.isEmpty())) {
invalidHandler(firstInvalidConstraint);
return;
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h (236464 => 236465)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h 2018-09-25 18:31:21 UTC (rev 236464)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h 2018-09-25 18:37:29 UTC (rev 236465)
@@ -100,6 +100,15 @@
CaptureDeviceManager* m_audioCaptureDeviceManager { nullptr };
CaptureDeviceManager* m_videoCaptureDeviceManager { nullptr };
+private:
+ struct DeviceInfo {
+ unsigned fitnessScore;
+ CaptureDevice device;
+ };
+
+ void getDisplayMediaDevices(const MediaStreamRequest&, Vector<DeviceInfo>&, String&);
+ void getUserMediaDevices(const MediaStreamRequest&, Vector<DeviceInfo>& audioDevices, Vector<DeviceInfo>& videoDevices, String&);
+
WTF::Function<void()> m_deviceChangedObserver;
};