<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[204516] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/204516">204516</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-08-16 12:04:06 -0700 (Tue, 16 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>⛱ : Implement parsing of Media Constraints for getUserMedia algorithm in Media Capture and Streaming Spec
https://bugs.webkit.org/show_bug.cgi?id=160533
&lt;rdar://problem/27688483&gt;

Patch by George Ruan &lt;gruan@apple.com&gt; on 2016-08-16
Reviewed by Chris Dumez.

Source/WebCore:

Two getUserMedia tests have been updated to reflect changes and cover limited
testing of the parsing of media constraints when given to getUserMedia().
Current testing infrastructure doesn't support full testing of the parsing
of media constraints. Either a mock needs to be created or the selectSettings()
algorithm will need to be implemented so we can see the constraints reflected
by the settings of media stream tracks. See https://bugs.webkit.org/show_bug.cgi?id=160791.

The specification on media constraints and how they are provided to getUserMedia() and
applyConstraints() has changed. These constraints are parsed in the bindings and are
stored in a new class MediaConstraint with derived classes LongConstraint, DoubleConstraint,
BooleanConstraint, and StringConstraint, each holding their respective type of constraint
value.

* CMakeLists.txt: Add JSMediaDevicesCustom.cpp and MediaConstraints.cpp.
* Modules/mediastream/CaptureDeviceManager.cpp:
(CaptureDeviceManager::verifyConstraintsForMediaType): Make changes according
to how format of MediaConstraint was changed.
(CaptureDeviceManager::sessionSupportsConstraint): Ditto.
(CaptureDeviceManager::isSupportedFrameRate): Ditto. Also for the time being
support constraint validation with a static acceptable frame rate range of 0-60.
See relevant https://bugs.webkit.org/show_bug.cgi?id=160794 for supporting
constraint validation of frame rate dynamically.
* Modules/mediastream/CaptureDeviceManager.h: Make changes according to how
format of MediaConstraint was changed.
* Modules/mediastream/MediaConstraintsImpl.cpp: Remove code for parsing media
constraints in the legacy format with keys 'mandatory' and 'optional'. Removal
of legacy code is fine since MEDIA_STREAM feature flag is not enabled for any port.
(WebCore::MediaConstraintsImpl::create): Ditto
(WebCore::MediaConstraintsImpl::initialize): Still used by applyConstraints().
Added FIXME to remove after applyConstraints implementation is changed according
to w3c spec changes.
(WebCore::MediaConstraintsImpl::mandatoryConstraints): Make changes according to
how media constraint data is now stored.
(WebCore::MediaConstraintsImpl::advancedConstraints): Ditto.
(WebCore::MediaConstraintsImpl::getMandatoryConstraints): Deleted.
(WebCore::MediaConstraintsImpl::getOptionalConstraints): Deleted.
(WebCore::MediaConstraintsImpl::getMandatoryConstraintValue): Deleted.
(WebCore::MediaConstraintsImpl::getOptionalConstraintValue): Deleted.
* Modules/mediastream/MediaConstraintsImpl.h:
(WebCore::MediaConstraintsImpl::MediaConstraintsImpl): Add a constructor to allow
construction of MediaConstraintsImpl object based on how the custom binding code
for MediaDevices would parse the media constraints given to getUserMedia().
* Modules/mediastream/MediaDevices.cpp:
(WebCore::MediaDevices::getUserMedia): Make changes according to how media constraint
data is now stored.
* Modules/mediastream/MediaDevices.h: Ditto.
* Modules/mediastream/MediaDevices.idl: Add custom binding to parse media constraints,
since we do not have support for automatic binding generation of sequence of dictionaries,
dictionary inheritance, dictionaries inside of dictionaries, disjunctions, or dictionaries
without an interface.
* Modules/mediastream/MediaStreamTrack.cpp: Add FIXME with related bug.
(WebCore::MediaStreamTrack::applyConstraints): Ditto.
* Modules/mediastream/UserMediaRequest.cpp: Make changes according to how media constraint
data is now parsed and stored.
(WebCore::UserMediaRequest::start): Ditto.
(WebCore::UserMediaRequest::UserMediaRequest): Ditto.
(WebCore::UserMediaRequest::didCreateStream): Ditto.
(WebCore::parseOptions): Deleted.
* Modules/mediastream/UserMediaRequest.h: Ditto.
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSBindingsAllInOne.cpp: Added JSMediaDevicesCustom.cpp.
* bindings/js/JSMediaDevicesCustom.cpp: Added. Custom bindings to parse media constraints.
(WebCore::initializeStringConstraintWithList): Initialize string constraint 'exact' or 'ideal'
value according to an ArrayValue.
(WebCore::createStringConstraint): Given a dictionary acting as a 'MediaTrackConstraintSet'
and a string constraint key (e.g for facingMode), creates a native StringConstraint class to hold
the data.
(WebCore::createBooleanConstraint): Ditto but for constraints of type boolean.
(WebCore::createDoubleConstraint): Ditto but for constraints of type double.
(WebCore::createIntConstraint): Ditto but for constraints of type long.
(WebCore::parseMediaTrackConstraintSetForKey): Parses a given dictionary acting as a
'MediaTrackConstraintSet' for a constraint as the key and creates the correct native object to hold
the data.
(WebCore::parseAdvancedConstraints): Parses the advanced constraints.
(WebCore::parseConstraints): Parses the constraints of a Dictionary acting as a
'MediaTrackConstraints'.
(WebCore::JSMediaDevices::getUserMedia): Parses the constraint input to getUserMedia.
* platform/mediastream/MediaConstraints.cpp: Added. Add MediaConstraint classes with derived
classes IntConstraint, DoubleConstraint, BooleanConstraint, and StringConstraint to act as
containers for the parsed data from getUserMedia().
(WebCore::MediaConstraint::create): Factory that creates the correct derived class based on the
name of a media constraint.
(WebCore::MediaConstraint::getMin): Interface for getting the min value for a constraint.
ASSERT checks are in place to prevent calling getMin with the incorrect constraint type.
(WebCore::MediaConstraint::getMax): Ditto but for max value of constraint.
(WebCore::MediaConstraint::getExact): Ditto but for exact value of constraint.
(WebCore::MediaConstraint::getIdeal): Ditto but for ideal value of constraint.
(WebCore::IntConstraint::create): Creates a long constraint.
(WebCore::IntConstraint::setMin): Sets min value of constraint.
(WebCore::IntConstraint::setMax): Sets max value of constraint.
(WebCore::IntConstraint::setExact): Sets exact value of constraint.
(WebCore::IntConstraint::setIdeal): Sets ideal value of constraint.
(WebCore::IntConstraint::getMin): Overrides interface function and gets min value of constraint.
(WebCore::IntConstraint::getMax): Ditto but for max value of constraint.
(WebCore::IntConstraint::getExact): Ditto but for exact value of constraint.
(WebCore::IntConstraint::getIdeal): Ditto but for ideal value of constraint.
(WebCore::DoubleConstraint::create): Ditto, DoubleConstraint instead of IntConstraint.
(WebCore::DoubleConstraint::setMin): Ditto.
(WebCore::DoubleConstraint::setMax): Ditto.
(WebCore::DoubleConstraint::setExact): Ditto.
(WebCore::DoubleConstraint::setIdeal): Ditto.
(WebCore::DoubleConstraint::getMin): Ditto.
(WebCore::DoubleConstraint::getMax): Ditto.
(WebCore::DoubleConstraint::getExact): Ditto.
(WebCore::DoubleConstraint::getIdeal): Ditto.
(WebCore::BooleanConstraint::create): Ditto, BooleanConstraint instead of IntConstraint.
(WebCore::BooleanConstraint::setExact): Ditto.
(WebCore::BooleanConstraint::setIdeal): Ditto.
(WebCore::BooleanConstraint::getExact): Ditto.
(WebCore::BooleanConstraint::getIdeal): Ditto.
(WebCore::StringConstraint::create): Ditto, StringConstraint instead of IntConstraint.
(WebCore::StringConstraint::setExact): Ditto.
(WebCore::StringConstraint::appendExact): Appends string to 'exact' value of StringConstraint.
(WebCore::StringConstraint::setIdeal): Ditto.
(WebCore::StringConstraint::appendIdeal): Appends string to 'ideal' value of StringConstraint.
(WebCore::StringConstraint::getExact): Ditto.
(WebCore::StringConstraint::getIdeal): Ditto.
* platform/mediastream/MediaConstraints.h: Add MediaConstraint classes with derived
classes IntConstraint, DoubleConstraint, BooleanConstraint, and StringConstraint to act as
containers for the parsed data from getUserMedia().
(WebCore::MediaConstraint::~MediaConstraint):
(WebCore::MediaConstraint::name): Get name of constraint.
(WebCore::MediaConstraint::MediaConstraint): Constructor.
(WebCore::NumericConstraint::NumericConstraint): Base class of DoubleConstraint and IntConstraint.
(WebCore::NumericConstraint::setHasMin): Sets whether object has min vlaue.
(WebCore::NumericConstraint::setHasMax): Ditto but for max.
(WebCore::NumericConstraint::setHasExact): Ditto but for exact.
(WebCore::NumericConstraint::setHasIdeal): Ditto but for ideal.
(WebCore::NumericConstraint::hasMin): Gets whether object has min value.
(WebCore::NumericConstraint::hasMax): Ditto but for max.
(WebCore::NumericConstraint::hasExact): Ditto but for exact.
(WebCore::NumericConstraint::hasIdeal): Ditto but for ideal.
* platform/mediastream/RealtimeMediaSourceCenter.h: Parameters can be reference since
lifetime is guaranteed and ownership is not taken.
* platform/mediastream/mac/AVCaptureDeviceManager.h: Ditto.
* platform/mediastream/mac/AVCaptureDeviceManager.mm: Ditto.
(WebCore::AVCaptureDeviceManager::verifyConstraintsForMediaType): Ditto.
(WebCore::AVCaptureDeviceManager::sessionSupportsConstraint): Make changes according to
how media constraint data is stored.
(WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints):
Ditto.
(WebCore::AVCaptureDeviceManager::isSupportedFrameRate): Ditto.
* platform/mediastream/mac/AVVideoCaptureSource.h: Change frame rate from 'float' to 'double'.
* platform/mediastream/mac/AVVideoCaptureSource.mm:
(WebCore::AVVideoCaptureSource::setFrameRateConstraint): Ditto.
(WebCore::AVVideoCaptureSource::applyConstraints): Make changes according to how media constraint
data is stored. The implementation of applyConstraints has also drastically changed, and a FIXME
is associated.
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
The bindings will always pass a non-null MediaConstraints object to
getUserMedia() so a pointer MediaConstraints parameter is not necessary.
(WebCore::RealtimeMediaSourceCenterMac::createMediaStream): Ditto.
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.h: Change 'override' to 'final'
since RealtimeMediaSourceCenterMac is a 'final' class.
* platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.cpp: Ditto to
RealtimeMediaSourceCenterMac.
(WebCore::RealtimeMediaSourceCenterOwr::createMediaStream): Ditto.
(WebCore::RealtimeMediaSourceCenterOwr::validateRequestConstraints):
* platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.h: Ditto.
* platform/mock/MediaConstraintsMock.cpp: Change how constraint validation is mocked.
(WebCore::isLongMediaConstraintSatisfiable): Sets arbitrary min and max supported value to be 0 and 10,
respectively. Then checks if constraint is satisfiable.
(WebCore::isDoubleMediaConstraintSatisfiable): Ditto but with double.
(WebCore::isBooleanMediaConstraintSatisfiable): Mock a boolean constraint to only be satisfiable if the
'exact' value is true.
(WebCore::isStringMediaConstraintSatisfiable): Mock a string constraint to only be satisfiable if the
'exact' value has the string 'valid'
(WebCore::isSatisfiable): Checks if a certain constraint is satisfiable.
(WebCore::MediaConstraintsMock::verifyConstraints): Verifies if the constraints are satisfiable.
(WebCore::isSupported): Deleted.
(WebCore::isValid): Deleted.
* platform/mock/MediaConstraintsMock.h: Change argument of MediaConstraints to raw pointer.
* platform/mock/MockRealtimeMediaSourceCenter.cpp: Change arguments of MediaConstraints to a raw pointer
and make changes according to how the MediaConstraint was changed.
(WebCore::MockRealtimeMediaSourceCenter::validateRequestConstraints):
(WebCore::MockRealtimeMediaSourceCenter::createMediaStream):
* platform/mock/MockRealtimeMediaSourceCenter.h: Change argument of MediaConstraints to raw pointer.

LayoutTests:

Implementation of parsing of media constraints passed to getUserMedia has changed to meet
the current w3c standards. Three major changes have been introduced
- If the parameter in getUserMedia is missing a TypeError is thrown, according to the IDL spec
- Given a Dictionary value with neither 'audio' nor 'video' keys having dictionary values
or 'true', the promise is rejected with a TypeError
- If the constraints cannot be satisfied the promise is rejected with a DataError. This should
be changed to an OverConstrainedError in the future. See
https://bugs.webkit.org/show_bug.cgi?id=160790

* fast/mediastream/MediaDevices-getUserMedia-expected.txt:
* fast/mediastream/MediaDevices-getUserMedia.html: Added limited testing of parsing of
media constraints for getUserMedia(), this includes only testing of mandatory constraints
and whether the promise is rejected if the constraints cannot be satisfied.
* fast/mediastream/getusermedia-expected.txt:
* fast/mediastream/getusermedia.html: As format of media constraints have changed, the test
has been updated to reflect those changes.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamMediaDevicesgetUserMediaexpectedtxt">trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamMediaDevicesgetUserMediahtml">trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia.html</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamenumeratingcrashhtml">trunk/LayoutTests/fast/mediastream/enumerating-crash.html</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamgetusermediaexpectedtxt">trunk/LayoutTests/fast/mediastream/getusermedia-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamgetusermediahtml">trunk/LayoutTests/fast/mediastream/getusermedia.html</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamCaptureDeviceManagercpp">trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamCaptureDeviceManagerh">trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaConstraintsImplcpp">trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaConstraintsImplh">trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaDevicescpp">trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaDevicesh">trunk/Source/WebCore/Modules/mediastream/MediaDevices.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaDevicesidl">trunk/Source/WebCore/Modules/mediastream/MediaDevices.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaStreamTrackcpp">trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamUserMediaRequestcpp">trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamUserMediaRequesth">trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSBindingsAllInOnecpp">trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaConstraintsh">trunk/Source/WebCore/platform/mediastream/MediaConstraints.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceCenterh">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagerh">trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm">trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourceh">trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourcemm">trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacRealtimeMediaSourceCenterMaccpp">trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacRealtimeMediaSourceCenterMach">trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamopenwebrtcRealtimeMediaSourceCenterOwrcpp">trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamopenwebrtcRealtimeMediaSourceCenterOwrh">trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMediaConstraintsMockcpp">trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMediaConstraintsMockh">trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp">trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCenterh">trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorebindingsjsJSMediaDevicesCustomcpp">trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaConstraintscpp">trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/LayoutTests/ChangeLog        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2016-08-16  George Ruan  &lt;gruan@apple.com&gt;
+
+        ⛱ : Implement parsing of Media Constraints for getUserMedia algorithm in Media Capture and Streaming Spec
+        https://bugs.webkit.org/show_bug.cgi?id=160533
+        &lt;rdar://problem/27688483&gt;
+
+        Reviewed by Chris Dumez.
+
+        Implementation of parsing of media constraints passed to getUserMedia has changed to meet
+        the current w3c standards. Three major changes have been introduced
+        - If the parameter in getUserMedia is missing a TypeError is thrown, according to the IDL spec
+        - Given a Dictionary value with neither 'audio' nor 'video' keys having dictionary values
+        or 'true', the promise is rejected with a TypeError
+        - If the constraints cannot be satisfied the promise is rejected with a DataError. This should
+        be changed to an OverConstrainedError in the future. See
+        https://bugs.webkit.org/show_bug.cgi?id=160790
+
+        * fast/mediastream/MediaDevices-getUserMedia-expected.txt:
+        * fast/mediastream/MediaDevices-getUserMedia.html: Added limited testing of parsing of
+        media constraints for getUserMedia(), this includes only testing of mandatory constraints
+        and whether the promise is rejected if the constraints cannot be satisfied.
+        * fast/mediastream/getusermedia-expected.txt:
+        * fast/mediastream/getusermedia.html: As format of media constraints have changed, the test
+        has been updated to reflect those changes.
+
</ins><span class="cx"> 2016-08-15  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Conversion to sequence&lt;T&gt; is broken for iterable objects
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaDevicesgetUserMediaexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -3,10 +3,10 @@
</span><span class="cx"> On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+PASS navigator.mediaDevices.getUserMedia().then(invalidGotStream); threw exception TypeError: Not enough arguments.
</ins><span class="cx"> PASS typeof navigator.mediaDevices.webkitGetUserMedia is 'undefined'
</span><span class="cx"> PASS navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1); did not throw exception.
</span><del>-PASS navigator.mediaDevices.getUserMedia() rejected with error: TypeError: Not enough arguments
-PASS  navigator.mediaDevices.getUserMedia({}) rejected with error: NotSupportedError (DOM Exception 9): The operation is not supported.
</del><ins>+PASS  navigator.mediaDevices.getUserMedia({}) rejected with error: TypeError: Type error
</ins><span class="cx"> PASS Stream generated.
</span><span class="cx"> PASS stream.getAudioTracks().length is 1
</span><span class="cx"> PASS stream.getVideoTracks().length is 0
</span><span class="lines">@@ -22,6 +22,14 @@
</span><span class="cx"> PASS Stream generated.
</span><span class="cx"> PASS stream.getAudioTracks().length is 1
</span><span class="cx"> PASS stream.getVideoTracks().length is 1
</span><ins>+PASS navigator.mediaDevices.getUserMedia({audio:audioConstraints, video:false}).then(gotStreamWithConstraints1) did not throw exception.
+PASS Stream generated.
+PASS navigator.mediaDevices.getUserMedia({audio:false, video:videoConstraints}).then(gotStreamWithConstraints2) did not throw exception.
+PASS Stream generated.
+PASS navigator.mediaDevices.getUserMedia({audio:audioConstraints, video:false}).then(invalidGotStream).catch(errorWithConstraints1) did not throw exception.
+PASS Error callback called.
+PASS navigator.mediaDevices.getUserMedia({audio:false, video:videoConstraints}).then(invalidGotStream).catch(errorWithConstraints2) did not throw exception.
+PASS Error callback called.
</ins><span class="cx"> PASS navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream, error1); did not throw exception.
</span><span class="cx"> PASS Error callback called.
</span><span class="cx"> PASS errorArg.name is &quot;NotAllowedError&quot;
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamMediaDevicesgetUserMediahtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia.html (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia.html        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia.html        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -19,6 +19,9 @@
</span><span class="cx">             var stream;
</span><span class="cx">             var errorArg;
</span><span class="cx"> 
</span><ins>+            let audioConstraints;
+            let videoConstraints;
+
</ins><span class="cx">             function invalidGotStream() {
</span><span class="cx">                 testFailed(&quot;Stream generated when an error should have occurred.&quot;);
</span><span class="cx">                 finishJSTest();
</span><span class="lines">@@ -37,6 +40,57 @@
</span><span class="cx">                 shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream).catch(error2);&quot;);
</span><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            function errorWithConstraints2() {
+                testPassed(&quot;Error callback called.&quot;);
+                setUserMediaPermission(false);
+                shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream, error1);&quot;);
+            }
+
+            function errorWithConstraints1() {
+                testPassed(&quot;Error callback called.&quot;);
+
+                videoConstraints = {
+                    width: {
+                        max: -1,
+                        ideal: 2
+                    },
+                    height: 11
+                };
+                shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({audio:false, video:videoConstraints}).then(invalidGotStream).catch(errorWithConstraints2)&quot;);
+            }
+
+            function gotStreamWithConstraints2() {
+                testPassed(&quot;Stream generated.&quot;);
+
+                audioConstraints = {
+                    sampleRate: {
+                        min: 6,
+                        max: 5,
+                        ideal: 10
+                    },
+                    sampleSize: 11
+                };
+                shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({audio:audioConstraints, video:false}).then(invalidGotStream).catch(errorWithConstraints1)&quot;);
+            }
+
+            function gotStreamWithConstraints1() {
+                testPassed(&quot;Stream generated.&quot;);
+
+                videoConstraints = {
+                    width: {
+                        min: 5,
+                        exact: 5,
+                        max: 5,
+                        ideal: 2
+                    },
+                    height: 11,
+                    facingMode: {
+                        exact:['valid']
+                    }
+                };
+                shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({audio:false, video:videoConstraints}).then(gotStreamWithConstraints2)&quot;);
+            }
+
</ins><span class="cx">             function gotStream4(s) {
</span><span class="cx">                 stream = s;
</span><span class="cx">                 testPassed(&quot;Stream generated.&quot;);
</span><span class="lines">@@ -43,8 +97,16 @@
</span><span class="cx">                 shouldBe(&quot;stream.getAudioTracks().length&quot;, &quot;1&quot;);
</span><span class="cx">                 shouldBe(&quot;stream.getVideoTracks().length&quot;, &quot;1&quot;);
</span><span class="cx"> 
</span><del>-                setUserMediaPermission(false);
-                shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({audio:true}).then(invalidGotStream, error1);&quot;);
</del><ins>+                audioConstraints = {
+                    sampleRate: {
+                        min: 5,
+                        exact: 5,
+                        max: 5,
+                        ideal: 2
+                    },
+                    sampleSize: 11
+                };
+                shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({audio:audioConstraints, video:false}).then(gotStreamWithConstraints1)&quot;);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             function gotStream3(s) {
</span><span class="lines">@@ -74,9 +136,7 @@
</span><span class="cx">                 shouldNotThrow(&quot;navigator.mediaDevices.getUserMedia({video:true}).then(gotStream2);&quot;)
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            navigator.mediaDevices.getUserMedia().then(invalidGotStream, function(error) {
-                testPassed(&quot;navigator.mediaDevices.getUserMedia() rejected with error: &quot; + error);
-            });
</del><ins>+            shouldThrow(&quot;navigator.mediaDevices.getUserMedia().then(invalidGotStream);&quot;);
</ins><span class="cx">             navigator.mediaDevices.getUserMedia({}).then(invalidGotStream, function(error) {
</span><span class="cx">                 testPassed(&quot; navigator.mediaDevices.getUserMedia({}) rejected with error: &quot; + error);
</span><span class="cx">             });
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamenumeratingcrashhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/enumerating-crash.html (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/enumerating-crash.html        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/LayoutTests/fast/mediastream/enumerating-crash.html        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -16,7 +16,7 @@
</span><span class="cx">     document.addEventListener(&quot;webglcontextlost&quot;, function () {
</span><span class="cx">         var mediaDevices = window.navigator.mediaDevices;
</span><span class="cx">         mediaDevices.enumerateDevices();
</span><del>-        mediaDevices.getUserMedia(123456789.);
</del><ins>+        mediaDevices.getUserMedia({});
</ins><span class="cx">         if (window.testRunner)
</span><span class="cx">             testRunner.notifyDone();
</span><span class="cx">     }, true);
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamgetusermediaexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/getusermedia-expected.txt (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/getusermedia-expected.txt        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/LayoutTests/fast/mediastream/getusermedia-expected.txt        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -20,18 +20,17 @@
</span><span class="cx"> PASS Stream generated.
</span><span class="cx"> PASS stream.getAudioTracks().length is 1
</span><span class="cx"> PASS stream.getVideoTracks().length is 1
</span><del>-PASS navigator.webkitGetUserMedia({audio:{mandatory:{}, optional:[]}, video:true}, gotStream4, null); threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
-PASS navigator.webkitGetUserMedia({audio:{mandatory:{}, optional:[]}, video:true}, gotStream4, error); did not throw exception.
</del><ins>+PASS navigator.webkitGetUserMedia({audio:{}, video:true}, gotStream4, null); threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({audio:{}, video:true}, gotStream4, error); did not throw exception.
</ins><span class="cx"> PASS Stream generated.
</span><span class="cx"> PASS stream.getAudioTracks().length is 1
</span><span class="cx"> PASS stream.getVideoTracks().length is 1
</span><del>-PASS navigator.webkitGetUserMedia({audio:{mandatory:{'valid_but_unsupported_1':0}, optional:[]}, video:true}, gotStreamInError, null); threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
-PASS navigator.webkitGetUserMedia({audio:{mandatory:{'valid_but_unsupported_1':0}, optional:[]}, video:true}, gotStreamInError, error1); did not throw exception.
</del><ins>+PASS navigator.webkitGetUserMedia({audio:true, video:{width:{exact:11}}}, gotStreamInError, null); threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({audio:true, video:{width:{exact:11}}}, gotStreamInError, error1); did not throw exception.
</ins><span class="cx"> PASS Error callback called.
</span><del>-FAIL errorArg.name should be ConstraintNotSatisfiedError. Was DataError.
-FAIL errorArg.constraintName should be valid_but_unsupported_1 (of type string). Was undefined (of type undefined).
-PASS navigator.webkitGetUserMedia({audio:{mandatory:{'valid_and_supported_1':1}, optional:[{'valid_but_unsupported_1':0}]}, video:true}, gotStream5, 0); threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
-PASS navigator.webkitGetUserMedia({audio:{mandatory:{'valid_and_supported_1':1}, optional:[{'valid_but_unsupported_1':0}]}, video:true}, gotStream5, error); did not throw exception.
</del><ins>+FAIL errorArg.name should be OverConstrainedError. Was DataError.
+PASS navigator.webkitGetUserMedia({audio:{volume:{exact:1}}, video:true}, gotStream5, 0); threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({audio:{volume:{exact:1}}, video:true}, gotStream5, error); did not throw exception.
</ins><span class="cx"> PASS Stream generated.
</span><span class="cx"> PASS stream.getAudioTracks().length is 1
</span><span class="cx"> PASS stream.getVideoTracks().length is 1
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamgetusermediahtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/getusermedia.html (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/getusermedia.html        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/LayoutTests/fast/mediastream/getusermedia.html        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -44,11 +44,10 @@
</span><span class="cx">             function error1(e) {
</span><span class="cx">                 errorArg = e;
</span><span class="cx">                 testPassed('Error callback called.');
</span><del>-                shouldBeEqualToString('errorArg.name', 'ConstraintNotSatisfiedError');
-                shouldBeEqualToString('errorArg.constraintName', 'valid_but_unsupported_1');
</del><ins>+                shouldBeEqualToString('errorArg.name', 'OverConstrainedError');
</ins><span class="cx"> 
</span><del>-                shouldThrow(&quot;navigator.webkitGetUserMedia({audio:{mandatory:{'valid_and_supported_1':1}, optional:[{'valid_but_unsupported_1':0}]}, video:true}, gotStream5, 0);&quot;);
-                shouldNotThrow(&quot;navigator.webkitGetUserMedia({audio:{mandatory:{'valid_and_supported_1':1}, optional:[{'valid_but_unsupported_1':0}]}, video:true}, gotStream5, error);&quot;);
</del><ins>+                shouldThrow(&quot;navigator.webkitGetUserMedia({audio:{volume:{exact:1}}, video:true}, gotStream5, 0);&quot;);
+                shouldNotThrow(&quot;navigator.webkitGetUserMedia({audio:{volume:{exact:1}}, video:true}, gotStream5, error);&quot;);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             function gotStream4(s) {
</span><span class="lines">@@ -57,8 +56,8 @@
</span><span class="cx">                 shouldBe('stream.getAudioTracks().length', '1');
</span><span class="cx">                 shouldBe('stream.getVideoTracks().length', '1');
</span><span class="cx"> 
</span><del>-                shouldThrow(&quot;navigator.webkitGetUserMedia({audio:{mandatory:{'valid_but_unsupported_1':0}, optional:[]}, video:true}, gotStreamInError, null);&quot;);
-                shouldNotThrow(&quot;navigator.webkitGetUserMedia({audio:{mandatory:{'valid_but_unsupported_1':0}, optional:[]}, video:true}, gotStreamInError, error1);&quot;);
</del><ins>+                shouldThrow(&quot;navigator.webkitGetUserMedia({audio:true, video:{width:{exact:11}}}, gotStreamInError, null);&quot;);
+                shouldNotThrow(&quot;navigator.webkitGetUserMedia({audio:true, video:{width:{exact:11}}}, gotStreamInError, error1);&quot;);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             function gotStream3(s) {
</span><span class="lines">@@ -67,8 +66,8 @@
</span><span class="cx">                 shouldBe('stream.getAudioTracks().length', '1');
</span><span class="cx">                 shouldBe('stream.getVideoTracks().length', '1');
</span><span class="cx"> 
</span><del>-                shouldThrow(&quot;navigator.webkitGetUserMedia({audio:{mandatory:{}, optional:[]}, video:true}, gotStream4, null);&quot;);
-                shouldNotThrow(&quot;navigator.webkitGetUserMedia({audio:{mandatory:{}, optional:[]}, video:true}, gotStream4, error);&quot;);
</del><ins>+                shouldThrow(&quot;navigator.webkitGetUserMedia({audio:{}, video:true}, gotStream4, null);&quot;);
+                shouldNotThrow(&quot;navigator.webkitGetUserMedia({audio:{}, video:true}, gotStream4, error);&quot;);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             function gotStream2(s) {
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -1191,6 +1191,7 @@
</span><span class="cx">     bindings/js/JSLazyEventListener.cpp
</span><span class="cx">     bindings/js/JSLocationCustom.cpp
</span><span class="cx">     bindings/js/JSMainThreadExecState.cpp
</span><ins>+    bindings/js/JSMediaDevicesCustom.cpp
</ins><span class="cx">     bindings/js/JSMediaStreamTrackCustom.cpp
</span><span class="cx">     bindings/js/JSMediaTrackSupportedConstraintsCustom.cpp
</span><span class="cx">     bindings/js/JSMessageChannelCustom.cpp
</span><span class="lines">@@ -2314,10 +2315,12 @@
</span><span class="cx">     platform/graphics/transforms/TransformationMatrix.cpp
</span><span class="cx">     platform/graphics/transforms/TranslateTransformOperation.cpp
</span><span class="cx"> 
</span><ins>+    platform/mediastream/MediaConstraints.cpp
</ins><span class="cx">     platform/mediastream/MediaEndpoint.cpp
</span><span class="cx">     platform/mediastream/MediaEndpointConfiguration.cpp
</span><span class="cx">     platform/mediastream/MediaStreamPrivate.cpp
</span><span class="cx">     platform/mediastream/MediaStreamTrackPrivate.cpp
</span><ins>+    platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp
</ins><span class="cx">     platform/mediastream/RTCIceCandidateDescriptor.cpp
</span><span class="cx">     platform/mediastream/RTCPeerConnectionHandler.cpp
</span><span class="cx">     platform/mediastream/RTCSessionDescriptionDescriptor.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/ChangeLog        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -1,3 +1,190 @@
</span><ins>+2016-08-16  George Ruan  &lt;gruan@apple.com&gt;
+
+        ⛱ : Implement parsing of Media Constraints for getUserMedia algorithm in Media Capture and Streaming Spec
+        https://bugs.webkit.org/show_bug.cgi?id=160533
+        &lt;rdar://problem/27688483&gt;
+
+        Reviewed by Chris Dumez.
+
+        Two getUserMedia tests have been updated to reflect changes and cover limited
+        testing of the parsing of media constraints when given to getUserMedia().
+        Current testing infrastructure doesn't support full testing of the parsing
+        of media constraints. Either a mock needs to be created or the selectSettings()
+        algorithm will need to be implemented so we can see the constraints reflected
+        by the settings of media stream tracks. See https://bugs.webkit.org/show_bug.cgi?id=160791.
+
+        The specification on media constraints and how they are provided to getUserMedia() and 
+        applyConstraints() has changed. These constraints are parsed in the bindings and are
+        stored in a new class MediaConstraint with derived classes LongConstraint, DoubleConstraint,
+        BooleanConstraint, and StringConstraint, each holding their respective type of constraint
+        value.
+
+        * CMakeLists.txt: Add JSMediaDevicesCustom.cpp and MediaConstraints.cpp.
+        * Modules/mediastream/CaptureDeviceManager.cpp:
+        (CaptureDeviceManager::verifyConstraintsForMediaType): Make changes according
+        to how format of MediaConstraint was changed.
+        (CaptureDeviceManager::sessionSupportsConstraint): Ditto.
+        (CaptureDeviceManager::isSupportedFrameRate): Ditto. Also for the time being
+        support constraint validation with a static acceptable frame rate range of 0-60.
+        See relevant https://bugs.webkit.org/show_bug.cgi?id=160794 for supporting
+        constraint validation of frame rate dynamically.
+        * Modules/mediastream/CaptureDeviceManager.h: Make changes according to how
+        format of MediaConstraint was changed.
+        * Modules/mediastream/MediaConstraintsImpl.cpp: Remove code for parsing media
+        constraints in the legacy format with keys 'mandatory' and 'optional'. Removal
+        of legacy code is fine since MEDIA_STREAM feature flag is not enabled for any port.
+        (WebCore::MediaConstraintsImpl::create): Ditto
+        (WebCore::MediaConstraintsImpl::initialize): Still used by applyConstraints().
+        Added FIXME to remove after applyConstraints implementation is changed according
+        to w3c spec changes.
+        (WebCore::MediaConstraintsImpl::mandatoryConstraints): Make changes according to
+        how media constraint data is now stored.
+        (WebCore::MediaConstraintsImpl::advancedConstraints): Ditto.
+        (WebCore::MediaConstraintsImpl::getMandatoryConstraints): Deleted.
+        (WebCore::MediaConstraintsImpl::getOptionalConstraints): Deleted.
+        (WebCore::MediaConstraintsImpl::getMandatoryConstraintValue): Deleted.
+        (WebCore::MediaConstraintsImpl::getOptionalConstraintValue): Deleted.
+        * Modules/mediastream/MediaConstraintsImpl.h:
+        (WebCore::MediaConstraintsImpl::MediaConstraintsImpl): Add a constructor to allow
+        construction of MediaConstraintsImpl object based on how the custom binding code
+        for MediaDevices would parse the media constraints given to getUserMedia().
+        * Modules/mediastream/MediaDevices.cpp:
+        (WebCore::MediaDevices::getUserMedia): Make changes according to how media constraint
+        data is now stored.
+        * Modules/mediastream/MediaDevices.h: Ditto.
+        * Modules/mediastream/MediaDevices.idl: Add custom binding to parse media constraints,
+        since we do not have support for automatic binding generation of sequence of dictionaries,
+        dictionary inheritance, dictionaries inside of dictionaries, disjunctions, or dictionaries
+        without an interface.
+        * Modules/mediastream/MediaStreamTrack.cpp: Add FIXME with related bug.
+        (WebCore::MediaStreamTrack::applyConstraints): Ditto.
+        * Modules/mediastream/UserMediaRequest.cpp: Make changes according to how media constraint
+        data is now parsed and stored.
+        (WebCore::UserMediaRequest::start): Ditto.
+        (WebCore::UserMediaRequest::UserMediaRequest): Ditto.
+        (WebCore::UserMediaRequest::didCreateStream): Ditto.
+        (WebCore::parseOptions): Deleted.
+        * Modules/mediastream/UserMediaRequest.h: Ditto.
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSBindingsAllInOne.cpp: Added JSMediaDevicesCustom.cpp.
+        * bindings/js/JSMediaDevicesCustom.cpp: Added. Custom bindings to parse media constraints.
+        (WebCore::initializeStringConstraintWithList): Initialize string constraint 'exact' or 'ideal'
+        value according to an ArrayValue.
+        (WebCore::createStringConstraint): Given a dictionary acting as a 'MediaTrackConstraintSet'
+        and a string constraint key (e.g for facingMode), creates a native StringConstraint class to hold
+        the data.
+        (WebCore::createBooleanConstraint): Ditto but for constraints of type boolean.
+        (WebCore::createDoubleConstraint): Ditto but for constraints of type double.
+        (WebCore::createIntConstraint): Ditto but for constraints of type long.
+        (WebCore::parseMediaTrackConstraintSetForKey): Parses a given dictionary acting as a
+        'MediaTrackConstraintSet' for a constraint as the key and creates the correct native object to hold
+        the data.
+        (WebCore::parseAdvancedConstraints): Parses the advanced constraints.
+        (WebCore::parseConstraints): Parses the constraints of a Dictionary acting as a
+        'MediaTrackConstraints'.
+        (WebCore::JSMediaDevices::getUserMedia): Parses the constraint input to getUserMedia.
+        * platform/mediastream/MediaConstraints.cpp: Added. Add MediaConstraint classes with derived
+        classes IntConstraint, DoubleConstraint, BooleanConstraint, and StringConstraint to act as
+        containers for the parsed data from getUserMedia().
+        (WebCore::MediaConstraint::create): Factory that creates the correct derived class based on the
+        name of a media constraint.
+        (WebCore::MediaConstraint::getMin): Interface for getting the min value for a constraint.
+        ASSERT checks are in place to prevent calling getMin with the incorrect constraint type.
+        (WebCore::MediaConstraint::getMax): Ditto but for max value of constraint.
+        (WebCore::MediaConstraint::getExact): Ditto but for exact value of constraint.
+        (WebCore::MediaConstraint::getIdeal): Ditto but for ideal value of constraint.
+        (WebCore::IntConstraint::create): Creates a long constraint.
+        (WebCore::IntConstraint::setMin): Sets min value of constraint.
+        (WebCore::IntConstraint::setMax): Sets max value of constraint.
+        (WebCore::IntConstraint::setExact): Sets exact value of constraint.
+        (WebCore::IntConstraint::setIdeal): Sets ideal value of constraint.
+        (WebCore::IntConstraint::getMin): Overrides interface function and gets min value of constraint.
+        (WebCore::IntConstraint::getMax): Ditto but for max value of constraint.
+        (WebCore::IntConstraint::getExact): Ditto but for exact value of constraint.
+        (WebCore::IntConstraint::getIdeal): Ditto but for ideal value of constraint.
+        (WebCore::DoubleConstraint::create): Ditto, DoubleConstraint instead of IntConstraint.
+        (WebCore::DoubleConstraint::setMin): Ditto.
+        (WebCore::DoubleConstraint::setMax): Ditto.
+        (WebCore::DoubleConstraint::setExact): Ditto.
+        (WebCore::DoubleConstraint::setIdeal): Ditto.
+        (WebCore::DoubleConstraint::getMin): Ditto.
+        (WebCore::DoubleConstraint::getMax): Ditto.
+        (WebCore::DoubleConstraint::getExact): Ditto.
+        (WebCore::DoubleConstraint::getIdeal): Ditto.
+        (WebCore::BooleanConstraint::create): Ditto, BooleanConstraint instead of IntConstraint.
+        (WebCore::BooleanConstraint::setExact): Ditto.
+        (WebCore::BooleanConstraint::setIdeal): Ditto.
+        (WebCore::BooleanConstraint::getExact): Ditto.
+        (WebCore::BooleanConstraint::getIdeal): Ditto.
+        (WebCore::StringConstraint::create): Ditto, StringConstraint instead of IntConstraint.
+        (WebCore::StringConstraint::setExact): Ditto.
+        (WebCore::StringConstraint::appendExact): Appends string to 'exact' value of StringConstraint.
+        (WebCore::StringConstraint::setIdeal): Ditto.
+        (WebCore::StringConstraint::appendIdeal): Appends string to 'ideal' value of StringConstraint.
+        (WebCore::StringConstraint::getExact): Ditto.
+        (WebCore::StringConstraint::getIdeal): Ditto.
+        * platform/mediastream/MediaConstraints.h: Add MediaConstraint classes with derived
+        classes IntConstraint, DoubleConstraint, BooleanConstraint, and StringConstraint to act as
+        containers for the parsed data from getUserMedia().
+        (WebCore::MediaConstraint::~MediaConstraint):
+        (WebCore::MediaConstraint::name): Get name of constraint.
+        (WebCore::MediaConstraint::MediaConstraint): Constructor.
+        (WebCore::NumericConstraint::NumericConstraint): Base class of DoubleConstraint and IntConstraint.
+        (WebCore::NumericConstraint::setHasMin): Sets whether object has min vlaue.
+        (WebCore::NumericConstraint::setHasMax): Ditto but for max.
+        (WebCore::NumericConstraint::setHasExact): Ditto but for exact.
+        (WebCore::NumericConstraint::setHasIdeal): Ditto but for ideal.
+        (WebCore::NumericConstraint::hasMin): Gets whether object has min value.
+        (WebCore::NumericConstraint::hasMax): Ditto but for max.
+        (WebCore::NumericConstraint::hasExact): Ditto but for exact.
+        (WebCore::NumericConstraint::hasIdeal): Ditto but for ideal.
+        * platform/mediastream/RealtimeMediaSourceCenter.h: Parameters can be reference since
+        lifetime is guaranteed and ownership is not taken.
+        * platform/mediastream/mac/AVCaptureDeviceManager.h: Ditto.
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm: Ditto.
+        (WebCore::AVCaptureDeviceManager::verifyConstraintsForMediaType): Ditto.
+        (WebCore::AVCaptureDeviceManager::sessionSupportsConstraint): Make changes according to
+        how media constraint data is stored.
+        (WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints):
+        Ditto.
+        (WebCore::AVCaptureDeviceManager::isSupportedFrameRate): Ditto.
+        * platform/mediastream/mac/AVVideoCaptureSource.h: Change frame rate from 'float' to 'double'.
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        (WebCore::AVVideoCaptureSource::setFrameRateConstraint): Ditto.
+        (WebCore::AVVideoCaptureSource::applyConstraints): Make changes according to how media constraint
+        data is stored. The implementation of applyConstraints has also drastically changed, and a FIXME
+        is associated.
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
+        The bindings will always pass a non-null MediaConstraints object to
+        getUserMedia() so a pointer MediaConstraints parameter is not necessary.
+        (WebCore::RealtimeMediaSourceCenterMac::createMediaStream): Ditto.
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.h: Change 'override' to 'final'
+        since RealtimeMediaSourceCenterMac is a 'final' class.
+        * platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.cpp: Ditto to
+        RealtimeMediaSourceCenterMac.
+        (WebCore::RealtimeMediaSourceCenterOwr::createMediaStream): Ditto.
+        (WebCore::RealtimeMediaSourceCenterOwr::validateRequestConstraints):
+        * platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.h: Ditto.
+        * platform/mock/MediaConstraintsMock.cpp: Change how constraint validation is mocked.
+        (WebCore::isLongMediaConstraintSatisfiable): Sets arbitrary min and max supported value to be 0 and 10,
+        respectively. Then checks if constraint is satisfiable.
+        (WebCore::isDoubleMediaConstraintSatisfiable): Ditto but with double.
+        (WebCore::isBooleanMediaConstraintSatisfiable): Mock a boolean constraint to only be satisfiable if the
+        'exact' value is true.
+        (WebCore::isStringMediaConstraintSatisfiable): Mock a string constraint to only be satisfiable if the
+        'exact' value has the string 'valid'
+        (WebCore::isSatisfiable): Checks if a certain constraint is satisfiable.
+        (WebCore::MediaConstraintsMock::verifyConstraints): Verifies if the constraints are satisfiable.
+        (WebCore::isSupported): Deleted.
+        (WebCore::isValid): Deleted.
+        * platform/mock/MediaConstraintsMock.h: Change argument of MediaConstraints to raw pointer.
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp: Change arguments of MediaConstraints to a raw pointer
+        and make changes according to how the MediaConstraint was changed.
+        (WebCore::MockRealtimeMediaSourceCenter::validateRequestConstraints):
+        (WebCore::MockRealtimeMediaSourceCenter::createMediaStream):
+        * platform/mock/MockRealtimeMediaSourceCenter.h: Change argument of MediaConstraints to raw pointer.
+
</ins><span class="cx"> 2016-08-16  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix WinCairo build after r204512.
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamCaptureDeviceManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #import &quot;UUID.h&quot;
</span><span class="cx"> #import &lt;wtf/MainThread.h&gt;
</span><span class="cx"> #import &lt;wtf/NeverDestroyed.h&gt;
</span><ins>+#import &lt;wtf/text/StringHash.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="lines">@@ -70,18 +71,14 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool CaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, MediaConstraints* constraints, const CaptureSessionInfo* session, String&amp; invalidConstraint)
</del><ins>+bool CaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, const MediaConstraints&amp; constraints, const CaptureSessionInfo* session, String&amp; invalidConstraint)
</ins><span class="cx"> {
</span><del>-    if (!constraints)
-        return true;
-
-    Vector&lt;MediaConstraint&gt; mandatoryConstraints;
-    constraints-&gt;getMandatoryConstraints(mandatoryConstraints);
-    for (auto&amp; constraint : mandatoryConstraints) {
-        if (sessionSupportsConstraint(session, type, constraint.m_name, constraint.m_value))
</del><ins>+    auto&amp; mandatoryConstraints = constraints.mandatoryConstraints();
+    for (auto&amp; nameConstraintPair : mandatoryConstraints) {
+        if (sessionSupportsConstraint(session, type, *nameConstraintPair.value))
</ins><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        invalidConstraint = constraint.m_name;
</del><ins>+        invalidConstraint = nameConstraintPair.key;
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -154,14 +151,14 @@
</span><span class="cx">     return RealtimeMediaSourceSettings::Unknown;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool CaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type type, const String&amp; name, const String&amp; value)
</del><ins>+bool CaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type type, const MediaConstraint&amp; constraint)
</ins><span class="cx"> {
</span><span class="cx">     const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
</span><del>-    MediaConstraintType constraint = supportedConstraints.constraintFromName(name);
-    if (!supportedConstraints.supportsConstraint(constraint))
</del><ins>+    MediaConstraintType constraintType = supportedConstraints.constraintFromName(constraint.name());
+    if (!supportedConstraints.supportsConstraint(constraintType))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    switch (constraint) {
</del><ins>+    switch (constraintType) {
</ins><span class="cx">     case MediaConstraintType::Width:
</span><span class="cx">         return type == RealtimeMediaSource::Video;
</span><span class="cx"> 
</span><span class="lines">@@ -172,13 +169,18 @@
</span><span class="cx">         if (type == RealtimeMediaSource::Audio)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        return isSupportedFrameRate(value.toFloat());
</del><ins>+        return isSupportedFrameRate(constraint);
</ins><span class="cx">     }
</span><span class="cx">     case MediaConstraintType::FacingMode: {
</span><span class="cx">         if (type == RealtimeMediaSource::Audio)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        return bestDeviceForFacingMode(facingModeFromString(value));
</del><ins>+        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160793. Handle sequence of facingMode constraints.
+        Vector&lt;String&gt; exactFacingMode;
+        if (!constraint.getExact(exactFacingMode))
+            return false;
+
+        return bestDeviceForFacingMode(facingModeFromString(exactFacingMode[0]));
</ins><span class="cx">     }
</span><span class="cx">     default:
</span><span class="cx">         return false;
</span><span class="lines">@@ -185,9 +187,24 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool CaptureDeviceManager::isSupportedFrameRate(float frameRate) const
</del><ins>+bool CaptureDeviceManager::isSupportedFrameRate(const MediaConstraint&amp; constraint) const
</ins><span class="cx"> {
</span><del>-    return 0 &lt; frameRate &amp;&amp; frameRate &lt;= 60;
</del><ins>+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160794. Dynamically check media devices if frame rate is supported.
+    bool isSupported = true;
+
+    int min = 0;
+    if (constraint.getMin(min))
+        isSupported &amp;= min &gt; 60;
+
+    int max = 60;
+    if (constraint.getMax(max))
+        isSupported &amp;= max &lt; min;
+
+    int exact;
+    if (constraint.getExact(exact))
+        isSupported &amp;= (exact &lt; min || exact &gt; max);
+
+    return isSupported;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamCaptureDeviceManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx">     virtual Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, MediaConstraints&amp;);
</span><span class="cx">     virtual RefPtr&lt;RealtimeMediaSource&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*);
</span><span class="cx"> 
</span><del>-    virtual bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, MediaConstraints*, const CaptureSessionInfo*, String&amp;);
</del><ins>+    virtual bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, const MediaConstraints&amp;, const CaptureSessionInfo*, String&amp;);
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     virtual ~CaptureDeviceManager();
</span><span class="lines">@@ -50,8 +50,8 @@
</span><span class="cx">     virtual RealtimeMediaSource* createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&amp;, MediaConstraints*) = 0;
</span><span class="cx"> 
</span><span class="cx">     virtual CaptureSessionInfo defaultCaptureSession() const { return CaptureSessionInfo(); }
</span><del>-    virtual bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const String&amp; name, const String&amp; value);
-    virtual bool isSupportedFrameRate(float frameRate) const;
</del><ins>+    virtual bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const MediaConstraint&amp;);
+    virtual bool isSupportedFrameRate(const MediaConstraint&amp;) const;
</ins><span class="cx"> 
</span><span class="cx">     bool captureDeviceFromDeviceID(const String&amp; captureDeviceID, CaptureDeviceInfo&amp; source);
</span><span class="cx">     CaptureDeviceInfo* bestDeviceForFacingMode(RealtimeMediaSourceSettings::VideoFacingMode);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaConstraintsImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -37,121 +37,31 @@
</span><span class="cx"> #include &quot;ArrayValue.h&quot;
</span><span class="cx"> #include &quot;Dictionary.h&quot;
</span><span class="cx"> #include &quot;ExceptionCode.h&quot;
</span><del>-#include &lt;wtf/HashMap.h&gt;
</del><ins>+#include &quot;Logging.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-RefPtr&lt;MediaConstraintsImpl&gt; MediaConstraintsImpl::create(const Dictionary&amp; constraints)
-{
-    RefPtr&lt;MediaConstraintsImpl&gt; object = adoptRef(*new MediaConstraintsImpl());
-    if (!object-&gt;initialize(constraints))
-        return nullptr;
-    return object;
-}
-
</del><span class="cx"> Ref&lt;MediaConstraintsImpl&gt; MediaConstraintsImpl::create()
</span><span class="cx"> {
</span><span class="cx">     return adoptRef(*new MediaConstraintsImpl());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool MediaConstraintsImpl::initialize(const Dictionary&amp; constraints)
</del><ins>+// FIXME: Remove after https://bugs.webkit.org/show_bug.cgi?id=160579
+void MediaConstraintsImpl::initialize(const Dictionary&amp; constraints)
</ins><span class="cx"> {
</span><span class="cx">     if (constraints.isUndefinedOrNull())
</span><del>-        return true;
-
-    Vector&lt;String&gt; names;
-    constraints.getOwnPropertyNames(names);
-
-    String mandatory = ASCIILiteral(&quot;mandatory&quot;);
-    String optional = ASCIILiteral(&quot;optional&quot;);
-
-    for (auto&amp; name : names) {
-        if (name != mandatory &amp;&amp; name != optional)
-            return false;
-    }
-
-    if (names.contains(mandatory)) {
-        Dictionary mandatoryConstraints;
-        bool ok = constraints.get(mandatory, mandatoryConstraints);
-        if (!ok || mandatoryConstraints.isUndefinedOrNull())
-            return false;
-
-        ok = mandatoryConstraints.getOwnPropertiesAsStringHashMap(m_mandatoryConstraints);
-        if (!ok)
-            return false;
-    }
-
-    if (names.contains(optional)) {
-        ArrayValue optionalConstraints;
-        bool ok = constraints.get(optional, optionalConstraints);
-        if (!ok || optionalConstraints.isUndefinedOrNull())
-            return false;
-
-        size_t numberOfConstraints;
-        ok = optionalConstraints.length(numberOfConstraints);
-        if (!ok)
-            return false;
-
-        for (size_t i = 0; i &lt; numberOfConstraints; ++i) {
-            Dictionary constraint;
-            ok = optionalConstraints.get(i, constraint);
-            if (!ok || constraint.isUndefinedOrNull())
-                return false;
-            Vector&lt;String&gt; localNames;
-            constraint.getOwnPropertyNames(localNames);
-            if (localNames.size() != 1)
-                return false;
-            String key = localNames[0];
-            String value;
-            ok = constraint.get(key, value);
-            if (!ok)
-                return false;
-            m_optionalConstraints.append(MediaConstraint(key, value));
-        }
-    }
-
-    return true;
</del><ins>+        return;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MediaConstraintsImpl::~MediaConstraintsImpl()
</del><ins>+Ref&lt;MediaConstraintsImpl&gt; MediaConstraintsImpl::create(MediaTrackConstraintSetMap&amp;&amp; mandatoryConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp;&amp; advancedConstraints, bool isValid)
</ins><span class="cx"> {
</span><ins>+    return adoptRef(*new MediaConstraintsImpl(WTFMove(mandatoryConstraints), WTFMove(advancedConstraints), isValid));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaConstraintsImpl::getMandatoryConstraints(Vector&lt;MediaConstraint&gt;&amp; constraints) const
</del><ins>+MediaConstraintsImpl::~MediaConstraintsImpl()
</ins><span class="cx"> {
</span><del>-    constraints.clear();
-    for (auto&amp; constraint : m_mandatoryConstraints)
-        constraints.append(MediaConstraint(constraint.key, constraint.value));
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaConstraintsImpl::getOptionalConstraints(Vector&lt;MediaConstraint&gt;&amp; constraints) const
-{
-    constraints.clear();
-    constraints.appendRange(m_optionalConstraints.begin(), m_optionalConstraints.end());
-}
-
-bool MediaConstraintsImpl::getMandatoryConstraintValue(const String&amp; name, String&amp; value) const
-{
-    HashMap&lt;String, String&gt;::const_iterator i = m_mandatoryConstraints.find(name);
-    if (i == m_mandatoryConstraints.end())
-        return false;
-
-    value = i-&gt;value;
-    return true;
-}
-
-bool MediaConstraintsImpl::getOptionalConstraintValue(const String&amp; name, String&amp; value) const
-{
-    for (auto&amp; constraint : m_optionalConstraints) {
-        if (constraint.m_name == name) {
-            value = constraint.m_value;
-            return true;
-        }
-    }
-
-    return false;
-}
-
</del><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaConstraintsImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -35,31 +35,37 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ExceptionBase.h&quot;
</span><span class="cx"> #include &quot;MediaConstraints.h&quot;
</span><del>-#include &lt;wtf/HashMap.h&gt;
</del><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><ins>+
+class ArrayValue;
</ins><span class="cx"> class Dictionary;
</span><span class="cx"> 
</span><del>-class MediaConstraintsImpl : public MediaConstraints {
</del><ins>+class MediaConstraintsImpl final : public MediaConstraints {
</ins><span class="cx"> public:
</span><span class="cx">     static Ref&lt;MediaConstraintsImpl&gt; create();
</span><del>-    static RefPtr&lt;MediaConstraintsImpl&gt; create(const Dictionary&amp;);
</del><ins>+    static Ref&lt;MediaConstraintsImpl&gt; create(MediaTrackConstraintSetMap&amp;&amp; mandatoryConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp;&amp; advancedConstraints, bool isValid);
</ins><span class="cx"> 
</span><span class="cx">     virtual ~MediaConstraintsImpl();
</span><del>-    bool initialize(const Dictionary&amp;);
</del><ins>+    void initialize(const Dictionary&amp;);
</ins><span class="cx"> 
</span><del>-    void getMandatoryConstraints(Vector&lt;MediaConstraint&gt;&amp;) const override;
-    void getOptionalConstraints(Vector&lt;MediaConstraint&gt;&amp;) const override;
</del><ins>+    const MediaTrackConstraintSetMap&amp; mandatoryConstraints() const final { return m_mandatoryConstraints; }
+    const Vector&lt;MediaTrackConstraintSetMap&gt;&amp; advancedConstraints() const final { return m_advancedConstraints; }
+    bool isValid() const final { return m_isValid; }
</ins><span class="cx"> 
</span><del>-    bool getMandatoryConstraintValue(const String&amp; name, String&amp; value) const override;
-    bool getOptionalConstraintValue(const String&amp; name, String&amp; value) const override;
-
</del><span class="cx"> private:
</span><span class="cx">     MediaConstraintsImpl() { }
</span><ins>+    MediaConstraintsImpl(MediaTrackConstraintSetMap&amp;&amp; mandatoryConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp;&amp; advancedConstraints, bool isValid)
+        : m_mandatoryConstraints(WTFMove(mandatoryConstraints))
+        , m_advancedConstraints(WTFMove(advancedConstraints))
+        , m_isValid(isValid)
+    {
+    }
</ins><span class="cx"> 
</span><del>-    HashMap&lt;String, String&gt; m_mandatoryConstraints;
-    Vector&lt;MediaConstraint&gt; m_optionalConstraints;
</del><ins>+    MediaTrackConstraintSetMap m_mandatoryConstraints;
+    Vector&lt;MediaTrackConstraintSetMap&gt; m_advancedConstraints;
+    bool m_isValid;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaDevicescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -63,9 +63,9 @@
</span><span class="cx">     return downcast&lt;Document&gt;(scriptExecutionContext());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaDevices::getUserMedia(const Dictionary&amp; options, Promise&amp;&amp; promise, ExceptionCode&amp; ec) const
</del><ins>+void MediaDevices::getUserMedia(Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; audioConstraints, Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; videoConstraints, Promise&amp;&amp; promise, ExceptionCode&amp; ec) const
</ins><span class="cx"> {
</span><del>-    UserMediaRequest::start(document(), options, WTFMove(promise), ec);
</del><ins>+    UserMediaRequest::start(document(), WTFMove(audioConstraints), WTFMove(videoConstraints), WTFMove(promise), ec);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaDevices::enumerateDevices(EnumerateDevicesPromise&amp;&amp; promise, ExceptionCode&amp; ec) const
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaDevicesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> 
</span><span class="cx"> class Dictionary;
</span><span class="cx"> class Document;
</span><ins>+class MediaConstraintsImpl;
</ins><span class="cx"> class MediaStream;
</span><span class="cx"> class MediaTrackSupportedConstraints;
</span><span class="cx"> 
</span><span class="lines">@@ -60,7 +61,7 @@
</span><span class="cx">     typedef DOMPromise&lt;MediaStream&gt; Promise;
</span><span class="cx">     typedef DOMPromise&lt;MediaDeviceInfoVector&gt; EnumerateDevicesPromise;
</span><span class="cx"> 
</span><del>-    void getUserMedia(const Dictionary&amp;, Promise&amp;&amp;, ExceptionCode&amp;) const;
</del><ins>+    void getUserMedia(Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; audioConstraints, Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; videoConstraints, Promise&amp;&amp;, ExceptionCode&amp;) const;
</ins><span class="cx">     void enumerateDevices(EnumerateDevicesPromise&amp;&amp;, ExceptionCode&amp;) const;
</span><span class="cx">     RefPtr&lt;MediaTrackSupportedConstraints&gt; getSupportedConstraints();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaDevicesidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.idl (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.idl        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.idl        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -37,5 +37,5 @@
</span><span class="cx">     [JSBuiltin] Promise getUserMedia(Dictionary options);
</span><span class="cx">     [RaisesException] Promise enumerateDevices();
</span><span class="cx"> 
</span><del>-    [PrivateIdentifier, RaisesException, ImplementedAs=getUserMedia] Promise getUserMediaFromJS(Dictionary options);
</del><ins>+    [PrivateIdentifier, RaisesException, ImplementedAs=getUserMedia, Custom] Promise getUserMediaFromJS(Dictionary options);
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaStreamTrackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -169,6 +169,8 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaStreamTrack::applyConstraints(const Dictionary&amp; constraints)
</span><span class="cx"> {
</span><ins>+    // FIXME: Implement correctly. https://bugs.webkit.org/show_bug.cgi?id=160579
+
</ins><span class="cx">     m_constraints-&gt;initialize(constraints);
</span><span class="cx">     m_private-&gt;applyConstraints(*m_constraints);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamUserMediaRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -54,26 +54,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static RefPtr&lt;MediaConstraints&gt; parseOptions(const Dictionary&amp; options, const String&amp; mediaType)
</del><ins>+void UserMediaRequest::start(Document* document, Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; audioConstraints, Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; videoConstraints, MediaDevices::Promise&amp;&amp; promise, ExceptionCode&amp; ec)
</ins><span class="cx"> {
</span><del>-    Dictionary constraintsDictionary;
-    if (options.get(mediaType, constraintsDictionary) &amp;&amp; !constraintsDictionary.isUndefinedOrNull())
-        return MediaConstraintsImpl::create(constraintsDictionary);
-
-    bool mediaRequested = false;
-    if (!options.get(mediaType, mediaRequested) || !mediaRequested)
-        return nullptr;
-
-    return MediaConstraintsImpl::create();
-}
-
-void UserMediaRequest::start(Document* document, const Dictionary&amp; options, MediaDevices::Promise&amp;&amp; promise, ExceptionCode&amp; ec)
-{
-    if (!options.isObject()) {
-        ec = TypeError;
-        return;
-    }
-
</del><span class="cx">     UserMediaController* userMedia = UserMediaController::from(document ? document-&gt;page() : nullptr);
</span><span class="cx">     if (!userMedia) {
</span><span class="cx">         ec = NOT_SUPPORTED_ERR;
</span><span class="lines">@@ -80,11 +62,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto audioConstraints = parseOptions(options, AtomicString(&quot;audio&quot;, AtomicString::ConstructFromLiteral));
-    auto videoConstraints = parseOptions(options, AtomicString(&quot;video&quot;, AtomicString::ConstructFromLiteral));
-
-    if (!audioConstraints &amp;&amp; !videoConstraints) {
-        ec = NOT_SUPPORTED_ERR;
</del><ins>+    if (!audioConstraints-&gt;isValid() &amp;&amp; !videoConstraints-&gt;isValid()) {
+        promise.reject(TypeError);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -92,7 +71,7 @@
</span><span class="cx">     request-&gt;start();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-UserMediaRequest::UserMediaRequest(ScriptExecutionContext* context, UserMediaController* controller, RefPtr&lt;MediaConstraints&gt;&amp;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp;&amp; videoConstraints, MediaDevices::Promise&amp;&amp; promise)
</del><ins>+UserMediaRequest::UserMediaRequest(ScriptExecutionContext* context, UserMediaController* controller, Ref&lt;MediaConstraints&gt;&amp;&amp; audioConstraints, Ref&lt;MediaConstraints&gt;&amp;&amp; videoConstraints, MediaDevices::Promise&amp;&amp; promise)
</ins><span class="cx">     : ContextDestructionObserver(context)
</span><span class="cx">     , m_audioConstraints(WTFMove(audioConstraints))
</span><span class="cx">     , m_videoConstraints(WTFMove(videoConstraints))
</span><span class="lines">@@ -170,17 +149,15 @@
</span><span class="cx"> 
</span><span class="cx">     // 4 - Create the MediaStream and pass it to the success callback.
</span><span class="cx">     Ref&lt;MediaStream&gt; stream = MediaStream::create(*m_scriptExecutionContext, WTFMove(privateStream));
</span><del>-    if (m_audioConstraints) {
-        for (auto&amp; track : stream-&gt;getAudioTracks()) {
-            track-&gt;applyConstraints(*m_audioConstraints);
-            track-&gt;source().startProducingData();
-        }
</del><ins>+
+    for (auto&amp; track : stream-&gt;getAudioTracks()) {
+        track-&gt;applyConstraints(m_audioConstraints);
+        track-&gt;source().startProducingData();
</ins><span class="cx">     }
</span><del>-    if (m_videoConstraints) {
-        for (auto&amp; track : stream-&gt;getVideoTracks()) {
-            track-&gt;applyConstraints(*m_videoConstraints);
-            track-&gt;source().startProducingData();
-        }
</del><ins>+
+    for (auto&amp; track : stream-&gt;getVideoTracks()) {
+        track-&gt;applyConstraints(m_videoConstraints);
+        track-&gt;source().startProducingData();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_promise.resolve(stream);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamUserMediaRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx"> 
</span><span class="cx"> class UserMediaRequest : public MediaStreamCreationClient, public ContextDestructionObserver {
</span><span class="cx"> public:
</span><del>-    static void start(Document*, const Dictionary&amp;, MediaDevices::Promise&amp;&amp;, ExceptionCode&amp;);
</del><ins>+    static void start(Document*, Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; audioConstraints, Ref&lt;MediaConstraintsImpl&gt;&amp;&amp; videoConstraints, MediaDevices::Promise&amp;&amp;, ExceptionCode&amp;);
</ins><span class="cx"> 
</span><span class="cx">     ~UserMediaRequest();
</span><span class="cx"> 
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx">     const String&amp; allowedVideoDeviceUID() const { return m_allowedVideoDeviceUID; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    UserMediaRequest(ScriptExecutionContext*, UserMediaController*, RefPtr&lt;MediaConstraints&gt;&amp;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp;&amp; videoConstraints, MediaDevices::Promise&amp;&amp;);
</del><ins>+    UserMediaRequest(ScriptExecutionContext*, UserMediaController*, Ref&lt;MediaConstraints&gt;&amp;&amp; audioConstraints, Ref&lt;MediaConstraints&gt;&amp;&amp; videoConstraints, MediaDevices::Promise&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // MediaStreamCreationClient
</span><span class="cx">     void constraintsValidated(const Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt;&amp; audioTracks, const Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt;&amp; videoTracks) final;
</span><span class="lines">@@ -85,8 +85,8 @@
</span><span class="cx">     // ContextDestructionObserver
</span><span class="cx">     void contextDestroyed() final;
</span><span class="cx">     
</span><del>-    RefPtr&lt;MediaConstraints&gt; m_audioConstraints;
-    RefPtr&lt;MediaConstraints&gt; m_videoConstraints;
</del><ins>+    Ref&lt;MediaConstraints&gt; m_audioConstraints;
+    Ref&lt;MediaConstraints&gt; m_videoConstraints;
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;String&gt; m_videoDeviceUIDs;
</span><span class="cx">     Vector&lt;String&gt; m_audioDeviceUIDs;
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -1028,6 +1028,8 @@
</span><span class="cx">                 1AFFC4591D5E866100267A66 /* PluginBlacklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AFFC44F1D5E7EC700267A66 /* PluginBlacklist.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 1B124D8D1D380B7000ECDFB0 /* MediaSampleAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B124D8C1D380B7000ECDFB0 /* MediaSampleAVFObjC.h */; };
</span><span class="cx">                 1B124D8F1D380BB600ECDFB0 /* MediaSampleAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1B124D8E1D380BB600ECDFB0 /* MediaSampleAVFObjC.mm */; };
</span><ins>+                1B88DD131D5B9E5000E3B7A4 /* JSMediaDevicesCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1B88DD121D5AD3B200E3B7A4 /* JSMediaDevicesCustom.cpp */; };
+                1BE5BFC21D515715001666D9 /* MediaConstraints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1BE5BFC11D515715001666D9 /* MediaConstraints.cpp */; };
</ins><span class="cx">                 1BF9DB3C1D3973AD0026AEB7 /* MediaSample.h in Headers */ = {isa = PBXBuildFile; fileRef = CD641EC7181ED60100EE4C41 /* MediaSample.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 1C010700192594DF008A4201 /* InlineTextBoxStyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C0106FE192594DF008A4201 /* InlineTextBoxStyle.cpp */; };
</span><span class="cx">                 1C010701192594DF008A4201 /* InlineTextBoxStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C0106FF192594DF008A4201 /* InlineTextBoxStyle.h */; };
</span><span class="lines">@@ -8260,6 +8262,8 @@
</span><span class="cx">                 1AFFC4561D5E83A700267A66 /* CFUtilitiesSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFUtilitiesSPI.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 1B124D8C1D380B7000ECDFB0 /* MediaSampleAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MediaSampleAVFObjC.h; path = ../MediaSampleAVFObjC.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 1B124D8E1D380BB600ECDFB0 /* MediaSampleAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaSampleAVFObjC.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                1B88DD121D5AD3B200E3B7A4 /* JSMediaDevicesCustom.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaDevicesCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                1BE5BFC11D515715001666D9 /* MediaConstraints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaConstraints.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 1C0106FE192594DF008A4201 /* InlineTextBoxStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineTextBoxStyle.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 1C0106FF192594DF008A4201 /* InlineTextBoxStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineTextBoxStyle.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 1C0939E81A13E12900B788E5 /* CachedSVGFont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CachedSVGFont.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15255,6 +15259,7 @@
</span><span class="cx">                 07221B9217CF0AD400848E51 /* mediastream */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                1BE5BFC11D515715001666D9 /* MediaConstraints.cpp */,
</ins><span class="cx">                                 0729B14D17CFCCA0004F1D60 /* mac */,
</span><span class="cx">                                 07D6A4F61BF2307D00174146 /* AudioTrackPrivateMediaStream.h */,
</span><span class="cx">                                 5EBB89301C7777E100C65D41 /* IceCandidate.h */,
</span><span class="lines">@@ -22092,6 +22097,7 @@
</span><span class="cx">                 BC4EDEF70C08F414007EDD49 /* Custom */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                1B88DD121D5AD3B200E3B7A4 /* JSMediaDevicesCustom.cpp */,
</ins><span class="cx">                                 1221E0721C03E4C2006A1A00 /* JSAnimationTimelineCustom.cpp */,
</span><span class="cx">                                 1AE96A741D1A04D300B86768 /* JSApplePayPaymentAuthorizedEventCustom.cpp */,
</span><span class="cx">                                 1AE96A751D1A04D300B86768 /* JSApplePayPaymentMethodSelectedEventCustom.cpp */,
</span><span class="lines">@@ -29161,6 +29167,7 @@
</span><span class="cx">                                 FD677738195CAF3D0072E0D3 /* DOMCSSNamespace.cpp in Sources */,
</span><span class="cx">                                 85032DE00AA8C9BE007D3B7D /* DOMCSSPageRule.mm in Sources */,
</span><span class="cx">                                 858C382D0AA8E40500B187A4 /* DOMCSSPrimitiveValue.mm in Sources */,
</span><ins>+                                1B88DD131D5B9E5000E3B7A4 /* JSMediaDevicesCustom.cpp in Sources */,
</ins><span class="cx">                                 85032DE20AA8C9BE007D3B7D /* DOMCSSRule.mm in Sources */,
</span><span class="cx">                                 85032DE40AA8C9BE007D3B7D /* DOMCSSRuleList.mm in Sources */,
</span><span class="cx">                                 85032DE60AA8C9BE007D3B7D /* DOMCSSStyleDeclaration.mm in Sources */,
</span><span class="lines">@@ -31426,6 +31433,7 @@
</span><span class="cx">                                 B2227A4A0D00BF220071B782 /* SVGMetadataElement.cpp in Sources */,
</span><span class="cx">                                 1AFFC4541D5E81CB00267A66 /* BlacklistUpdater.mm in Sources */,
</span><span class="cx">                                 B2A1F2B00CEF0ABF00442F6A /* SVGMissingGlyphElement.cpp in Sources */,
</span><ins>+                                1BE5BFC21D515715001666D9 /* MediaConstraints.cpp in Sources */,
</ins><span class="cx">                                 B2227A4D0D00BF220071B782 /* SVGMPathElement.cpp in Sources */,
</span><span class="cx">                                 A833C7CA0A2CF06B00D57664 /* SVGNames.cpp in Sources */,
</span><span class="cx">                                 B2227A500D00BF220071B782 /* SVGNumberList.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSBindingsAllInOnecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -106,6 +106,7 @@
</span><span class="cx"> #include &quot;JSLazyEventListener.cpp&quot;
</span><span class="cx"> #include &quot;JSLocationCustom.cpp&quot;
</span><span class="cx"> #include &quot;JSMainThreadExecState.cpp&quot;
</span><ins>+#include &quot;JSMediaDevicesCustom.cpp&quot;
</ins><span class="cx"> #include &quot;JSMessageChannelCustom.cpp&quot;
</span><span class="cx"> #include &quot;JSMessageEventCustom.cpp&quot;
</span><span class="cx"> #include &quot;JSMessagePortCustom.cpp&quot;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMediaDevicesCustomcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp (0 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp                                (rev 0)
+++ trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -0,0 +1,399 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;JSMediaDevices.h&quot;
+
+#if ENABLE(MEDIA_STREAM)
+
+#include &quot;ArrayValue.h&quot;
+#include &quot;Dictionary.h&quot;
+#include &quot;ExceptionCode.h&quot;
+#include &quot;Logging.h&quot;
+#include &quot;MediaConstraints.h&quot;
+#include &quot;MediaConstraintsImpl.h&quot;
+#include &quot;RealtimeMediaSourceCenter.h&quot;
+#include &quot;RealtimeMediaSourceSupportedConstraints.h&quot;
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+using namespace JSC;
+
+namespace WebCore {
+
+enum class ConstraintSetType { Mandatory, Advanced };
+
+static void initializeStringConstraintWithList(StringConstraint&amp; constraint, void (StringConstraint::*appendValue)(const String&amp;), const ArrayValue&amp; list)
+{
+    size_t size;
+    if (!list.length(size))
+        return;
+
+    for (size_t i = 0; i &lt; size; ++i) {
+        String value;
+        if (list.get(i, value))
+            (constraint.*appendValue)(value);
+    }
+}
+
+static RefPtr&lt;StringConstraint&gt; createStringConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, ConstraintSetType constraintSetType)
+{
+    auto constraint = StringConstraint::create(name);
+
+    // Dictionary constraint value.
+    Dictionary dictionaryValue;
+    if (mediaTrackConstraintSet.get(name, dictionaryValue) &amp;&amp; !dictionaryValue.isUndefinedOrNull()) {
+        ArrayValue exactArrayValue;
+        if (dictionaryValue.get(&quot;exact&quot;, exactArrayValue) &amp;&amp; !exactArrayValue.isUndefinedOrNull())
+            initializeStringConstraintWithList(constraint, &amp;StringConstraint::appendExact, exactArrayValue);
+        else {
+            String exactStringValue;
+            if (dictionaryValue.get(&quot;exact&quot;, exactStringValue))
+                constraint-&gt;setExact(exactStringValue);
+        }
+
+        ArrayValue idealArrayValue;
+        if (dictionaryValue.get(&quot;ideal&quot;, idealArrayValue) &amp;&amp; !idealArrayValue.isUndefinedOrNull())
+            initializeStringConstraintWithList(constraint, &amp;StringConstraint::appendIdeal, idealArrayValue);
+        else {
+            String idealStringValue;
+            if (!dictionaryValue.get(&quot;ideal&quot;, idealStringValue))
+                constraint-&gt;setIdeal(idealStringValue);
+        }
+
+        if (constraint-&gt;isEmpty()) {
+            LOG(Media, &quot;createStringConstraint() - ignoring string constraint '%s' with dictionary value since it has no valid or supported key/value pairs.&quot;, name.utf8().data());
+            return nullptr;
+        }
+        
+        return WTFMove(constraint);
+    }
+
+    // Array constraint value.
+    ArrayValue arrayValue;
+    if (mediaTrackConstraintSet.get(name, arrayValue) &amp;&amp; !arrayValue.isUndefinedOrNull()) {
+        initializeStringConstraintWithList(constraint, &amp;StringConstraint::appendIdeal, arrayValue);
+
+        if (constraint-&gt;isEmpty()) {
+            LOG(Media, &quot;createStringConstraint() - ignoring string constraint '%s' with array value since it is empty.&quot;, name.utf8().data());
+            return nullptr;
+        }
+
+        return WTFMove(constraint);
+    }
+
+    // Scalar constraint value.
+    String value;
+    if (mediaTrackConstraintSet.get(name, value)) {
+        if (constraintSetType == ConstraintSetType::Mandatory)
+            constraint-&gt;setIdeal(value);
+        else
+            constraint-&gt;setExact(value);
+        
+        return WTFMove(constraint);
+    }
+
+    // Invalid constraint value.
+    LOG(Media, &quot;createStringConstraint() - ignoring string constraint '%s' since it has neither a dictionary nor sequence nor scalar value.&quot;, name.utf8().data());
+    return nullptr;
+}
+
+static RefPtr&lt;BooleanConstraint&gt; createBooleanConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, ConstraintSetType constraintSetType)
+{
+    auto constraint = BooleanConstraint::create(name);
+
+    // Dictionary constraint value.
+    Dictionary dictionaryValue;
+    if (mediaTrackConstraintSet.get(name, dictionaryValue) &amp;&amp; !dictionaryValue.isUndefinedOrNull()) {
+        bool exactValue;
+        if (dictionaryValue.get(&quot;exact&quot;, exactValue))
+            constraint-&gt;setExact(exactValue);
+
+        bool idealValue;
+        if (dictionaryValue.get(&quot;ideal&quot;, idealValue))
+            constraint-&gt;setIdeal(idealValue);
+
+        if (constraint-&gt;isEmpty()) {
+            LOG(Media, &quot;createBooleanConstraint() - ignoring boolean constraint '%s' with dictionary value since it has no valid or supported key/value pairs.&quot;, name.utf8().data());
+            return nullptr;
+        }
+
+        return WTFMove(constraint);
+    }
+
+    // Scalar constraint value.
+    bool value;
+    if (mediaTrackConstraintSet.get(name, value)) {
+        if (constraintSetType == ConstraintSetType::Mandatory)
+            constraint-&gt;setIdeal(value);
+        else
+            constraint-&gt;setExact(value);
+        
+        return WTFMove(constraint);
+    }
+
+    // Invalid constraint value.
+    LOG(Media, &quot;createBooleanConstraint() - ignoring boolean constraint '%s' since it has neither a dictionary nor scalar value.&quot;, name.utf8().data());
+    return nullptr;
+}
+
+static RefPtr&lt;DoubleConstraint&gt; createDoubleConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, ConstraintSetType constraintSetType)
+{
+    auto constraint = DoubleConstraint::create(name);
+
+    // Dictionary constraint value.
+    Dictionary dictionaryValue;
+    if (mediaTrackConstraintSet.get(name, dictionaryValue) &amp;&amp; !dictionaryValue.isUndefinedOrNull()) {
+        double minValue;
+        if (dictionaryValue.get(&quot;min&quot;, minValue))
+            constraint-&gt;setMin(minValue);
+
+        double maxValue;
+        if (dictionaryValue.get(&quot;max&quot;, maxValue))
+            constraint-&gt;setMax(maxValue);
+
+        double exactValue;
+        if (dictionaryValue.get(&quot;exact&quot;, exactValue))
+            constraint-&gt;setExact(exactValue);
+
+        double idealValue;
+        if (dictionaryValue.get(&quot;ideal&quot;, idealValue))
+            constraint-&gt;setIdeal(idealValue);
+
+        if (constraint-&gt;isEmpty()) {
+            LOG(Media, &quot;createDoubleConstraint() - ignoring double constraint '%s' with dictionary value since it has no valid or supported key/value pairs.&quot;, name.utf8().data());
+            return nullptr;
+        }
+
+        return WTFMove(constraint);
+    }
+
+    // Scalar constraint value.
+    double value;
+    if (mediaTrackConstraintSet.get(name, value)) {
+        if (constraintSetType == ConstraintSetType::Mandatory)
+            constraint-&gt;setIdeal(value);
+        else
+            constraint-&gt;setExact(value);
+        
+        return WTFMove(constraint);
+    }
+
+    // Invalid constraint value.
+    LOG(Media, &quot;createDoubleConstraint() - ignoring double constraint '%s' since it has neither a dictionary nor scalar value.&quot;, name.utf8().data());
+    return nullptr;
+}
+
+static RefPtr&lt;IntConstraint&gt; createIntConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, ConstraintSetType constraintSetType)
+{
+    auto constraint = IntConstraint::create(name);
+
+    // Dictionary constraint value.
+    Dictionary dictionaryValue;
+    if (mediaTrackConstraintSet.get(name, dictionaryValue) &amp;&amp; !dictionaryValue.isUndefinedOrNull()) {
+        int minValue;
+        if (dictionaryValue.get(&quot;min&quot;, minValue))
+            constraint-&gt;setMin(minValue);
+
+        int maxValue;
+        if (dictionaryValue.get(&quot;max&quot;, maxValue))
+            constraint-&gt;setMax(maxValue);
+
+        int exactValue;
+        if (dictionaryValue.get(&quot;exact&quot;, exactValue))
+            constraint-&gt;setExact(exactValue);
+
+        int idealValue;
+        if (dictionaryValue.get(&quot;ideal&quot;, idealValue))
+            constraint-&gt;setIdeal(idealValue);
+
+        if (constraint-&gt;isEmpty()) {
+            LOG(Media, &quot;createIntConstraint() - ignoring long constraint '%s' with dictionary value since it has no valid or supported key/value pairs.&quot;, name.utf8().data());
+            return nullptr;
+        }
+
+        return WTFMove(constraint);
+    }
+
+    // Scalar constraint value.
+    int value;
+    if (mediaTrackConstraintSet.get(name, value)) {
+        if (constraintSetType == ConstraintSetType::Mandatory)
+            constraint-&gt;setIdeal(value);
+        else
+            constraint-&gt;setExact(value);
+        
+        return WTFMove(constraint);
+    }
+
+    // Invalid constraint value.
+    LOG(Media, &quot;createIntConstraint() - ignoring long constraint '%s' since it has neither a dictionary nor scalar value.&quot;, name.utf8().data());
+    return nullptr;
+}
+
+static void parseMediaTrackConstraintSetForKey(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaTrackConstraintSetMap&amp; map, ConstraintSetType constraintSetType, RealtimeMediaSource::Type sourceType)
+{
+    auto&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    MediaConstraintType constraintType = supportedConstraints.constraintFromName(name);
+
+    RefPtr&lt;MediaConstraint&gt; mediaConstraint;
+    if (sourceType == RealtimeMediaSource::Audio) {
+        switch (constraintType) {
+        case MediaConstraintType::SampleRate:
+        case MediaConstraintType::SampleSize:
+            mediaConstraint = createIntConstraint(mediaTrackConstraintSet, name, constraintSetType);
+            break;
+        case MediaConstraintType::Volume:
+            mediaConstraint = createDoubleConstraint(mediaTrackConstraintSet, name, constraintSetType);
+            break;
+        case MediaConstraintType::EchoCancellation:
+            mediaConstraint = createBooleanConstraint(mediaTrackConstraintSet, name, constraintSetType);
+            break;
+        case MediaConstraintType::DeviceId:
+        case MediaConstraintType::GroupId:
+            mediaConstraint = createStringConstraint(mediaTrackConstraintSet, name, constraintSetType);
+            break;
+        default:
+            LOG(Media, &quot;parseMediaTrackConstraintSetForKey() - ignoring unsupported constraint '%s' for audio.&quot;, name.utf8().data());
+            mediaConstraint = nullptr;
+            break;
+        }
+    } else if (sourceType == RealtimeMediaSource::Video) {
+        switch (constraintType) {
+        case MediaConstraintType::Width:
+        case MediaConstraintType::Height:
+            mediaConstraint = createIntConstraint(mediaTrackConstraintSet, name, constraintSetType);
+            break;
+        case MediaConstraintType::AspectRatio:
+        case MediaConstraintType::FrameRate:
+            mediaConstraint = createDoubleConstraint(mediaTrackConstraintSet, name, constraintSetType);
+            break;
+        case MediaConstraintType::FacingMode:
+        case MediaConstraintType::DeviceId:
+        case MediaConstraintType::GroupId:
+            mediaConstraint = createStringConstraint(mediaTrackConstraintSet, name, constraintSetType);
+            break;
+        default:
+            LOG(Media, &quot;parseMediaTrackConstraintSetForKey() - ignoring unsupported constraint '%s' for video.&quot;, name.utf8().data());
+            mediaConstraint = nullptr;
+            break;
+        }
+    }
+
+    if (!mediaConstraint)
+        return;
+
+    map.add(name, WTFMove(mediaConstraint));
+}
+
+static void parseAdvancedConstraints(const Dictionary&amp; mediaTrackConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp; advancedConstraints, RealtimeMediaSource::Type sourceType)
+{
+    ArrayValue sequenceOfMediaTrackConstraintSets;
+    if (!mediaTrackConstraints.get(&quot;advanced&quot;, sequenceOfMediaTrackConstraintSets) || sequenceOfMediaTrackConstraintSets.isUndefinedOrNull()) {
+        LOG(Media, &quot;parseAdvancedConstraints() - value of advanced key is not a list.&quot;);
+        return;
+    }
+
+    size_t numberOfConstraintSets;
+    if (!sequenceOfMediaTrackConstraintSets.length(numberOfConstraintSets)) {
+        LOG(Media, &quot;parseAdvancedConstraints() - ignoring empty advanced sequence of MediaTrackConstraintSets.&quot;);
+        return;
+    }
+
+    for (size_t i = 0; i &lt; numberOfConstraintSets; ++i) {
+        Dictionary mediaTrackConstraintSet;
+        if (!sequenceOfMediaTrackConstraintSets.get(i, mediaTrackConstraintSet) || mediaTrackConstraintSet.isUndefinedOrNull()) {
+            LOG(Media, &quot;parseAdvancedConstraints() - ignoring constraint set with index '%zu' in advanced list.&quot;, i);
+            continue;
+        }
+
+        MediaTrackConstraintSetMap map;
+
+        Vector&lt;String&gt; localKeys;
+        mediaTrackConstraintSet.getOwnPropertyNames(localKeys);
+        for (auto&amp; localKey : localKeys)
+            parseMediaTrackConstraintSetForKey(mediaTrackConstraintSet, localKey, map, ConstraintSetType::Advanced, sourceType);
+
+        if (!map.isEmpty())
+            advancedConstraints.append(WTFMove(map));
+    }
+}
+
+static void parseConstraints(const Dictionary&amp; mediaTrackConstraints, MediaTrackConstraintSetMap&amp; mandatoryConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp; advancedConstraints, RealtimeMediaSource::Type sourceType)
+{
+    if (mediaTrackConstraints.isUndefinedOrNull())
+        return;
+
+    Vector&lt;String&gt; keys;
+    mediaTrackConstraints.getOwnPropertyNames(keys);
+
+    for (auto&amp; key : keys) {
+        if (key == &quot;advanced&quot;)
+            parseAdvancedConstraints(mediaTrackConstraints, advancedConstraints, sourceType);
+        else
+            parseMediaTrackConstraintSetForKey(mediaTrackConstraints, key, mandatoryConstraints, ConstraintSetType::Mandatory, sourceType);
+    }
+}
+
+JSValue JSMediaDevices::getUserMedia(ExecState&amp; state)
+{
+    if (UNLIKELY(state.argumentCount() &lt; 1))
+        return JSValue::decode(throwVMError(&amp;state, createNotEnoughArgumentsError(&amp;state)));
+    ExceptionCode ec = 0;
+    auto constraintsDictionary = Dictionary(&amp;state, state.uncheckedArgument(0));
+
+    MediaTrackConstraintSetMap mandatoryAudioConstraints;
+    Vector&lt;MediaTrackConstraintSetMap&gt; advancedAudioConstraints;
+    bool areAudioConstraintsValid = false;
+
+    Dictionary audioConstraintsDictionary;
+    if (constraintsDictionary.get(&quot;audio&quot;, audioConstraintsDictionary) &amp;&amp; !audioConstraintsDictionary.isUndefinedOrNull()) {
+        parseConstraints(audioConstraintsDictionary, mandatoryAudioConstraints, advancedAudioConstraints, RealtimeMediaSource::Audio);
+        areAudioConstraintsValid = true;
+    } else
+        constraintsDictionary.get(&quot;audio&quot;, areAudioConstraintsValid);
+
+    MediaTrackConstraintSetMap mandatoryVideoConstraints;
+    Vector&lt;MediaTrackConstraintSetMap&gt; advancedVideoConstraints;
+    bool areVideoConstraintsValid = false;
+
+    Dictionary videoConstraintsDictionary;
+    if (constraintsDictionary.get(&quot;video&quot;, videoConstraintsDictionary) &amp;&amp; !videoConstraintsDictionary.isUndefinedOrNull()) {
+        parseConstraints(videoConstraintsDictionary, mandatoryVideoConstraints, advancedVideoConstraints, RealtimeMediaSource::Video);
+        areVideoConstraintsValid = true;
+    } else
+        constraintsDictionary.get(&quot;video&quot;, areVideoConstraintsValid);
+
+    auto audioConstraints = MediaConstraintsImpl::create(WTFMove(mandatoryAudioConstraints), WTFMove(advancedAudioConstraints), areAudioConstraintsValid);
+    auto videoConstraints = MediaConstraintsImpl::create(WTFMove(mandatoryVideoConstraints), WTFMove(advancedVideoConstraints), areVideoConstraintsValid);
+    JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&amp;state, globalObject());
+    wrapped().getUserMedia(WTFMove(audioConstraints), WTFMove(videoConstraints), DeferredWrapper(&amp;state, globalObject(), promiseDeferred), ec);
+    setDOMException(&amp;state, ec);
+    return promiseDeferred-&gt;promise();
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaConstraintscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp (0 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp                                (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -0,0 +1,375 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;MediaConstraints.h&quot;
+
+#if ENABLE(MEDIA_STREAM)
+#include &quot;RealtimeMediaSourceCenter.h&quot;
+#include &quot;RealtimeMediaSourceSupportedConstraints.h&quot;
+
+namespace WebCore {
+
+RefPtr&lt;MediaConstraint&gt; MediaConstraint::create(const String&amp; name)
+{
+    auto&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    MediaConstraintType constraintType = supportedConstraints.constraintFromName(name);
+
+    switch (constraintType) {
+    case MediaConstraintType::Width:
+    case MediaConstraintType::Height:
+    case MediaConstraintType::SampleRate:
+    case MediaConstraintType::SampleSize:
+        return IntConstraint::create(name);
+    case MediaConstraintType::AspectRatio:
+    case MediaConstraintType::FrameRate:
+    case MediaConstraintType::Volume:
+        return DoubleConstraint::create(name);
+    case MediaConstraintType::EchoCancellation:
+        return BooleanConstraint::create(name);
+    case MediaConstraintType::FacingMode:
+    case MediaConstraintType::DeviceId:
+    case MediaConstraintType::GroupId:
+        return StringConstraint::create(name);
+    case MediaConstraintType::Unknown:
+        return nullptr;
+    }
+}
+
+bool MediaConstraint::getMin(int&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getMax(int&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getExact(int&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getIdeal(int&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getMin(double&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getMax(double&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getExact(double&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getIdeal(double&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getMin(bool&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getMax(bool&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getExact(bool&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getIdeal(bool&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getMin(Vector&lt;String&gt;&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getMax(Vector&lt;String&gt;&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getExact(Vector&lt;String&gt;&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool MediaConstraint::getIdeal(Vector&lt;String&gt;&amp;) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+Ref&lt;IntConstraint&gt; IntConstraint::create(const String&amp; name)
+{
+    return adoptRef(*new IntConstraint(name));
+}
+
+void IntConstraint::setMin(int value)
+{
+    m_min = value;
+    setHasMin(true);
+}
+
+void IntConstraint::setMax(int value)
+{
+    m_max = value;
+    setHasMax(true);
+}
+
+void IntConstraint::setExact(int value)
+{
+    m_exact = value;
+    setHasExact(true);
+}
+
+void IntConstraint::setIdeal(int value)
+{
+    m_ideal = value;
+    setHasIdeal(true);
+}
+
+bool IntConstraint::getMin(int&amp; min) const
+{
+    if (!hasMin())
+        return false;
+
+    min = m_min;
+    return true;
+}
+
+bool IntConstraint::getMax(int&amp; max) const
+{
+    if (!hasMax())
+        return false;
+
+    max = m_max;
+    return true;
+}
+
+bool IntConstraint::getExact(int&amp; exact) const
+{
+    if (!hasExact())
+        return false;
+
+    exact = m_exact;
+    return true;
+}
+
+bool IntConstraint::getIdeal(int&amp; ideal) const
+{
+    if (!hasIdeal())
+        return false;
+
+    ideal = m_ideal;
+    return true;
+}
+
+Ref&lt;DoubleConstraint&gt; DoubleConstraint::create(const String&amp; name)
+{
+    return adoptRef(*new DoubleConstraint(name));
+}
+
+void DoubleConstraint::setMin(double value)
+{
+    m_min = value;
+    setHasMin(true);
+}
+
+void DoubleConstraint::setMax(double value)
+{
+    m_max = value;
+    setHasMax(true);
+}
+
+void DoubleConstraint::setExact(double value)
+{
+    m_exact = value;
+    setHasExact(true);
+}
+
+void DoubleConstraint::setIdeal(double value)
+{
+    m_ideal = value;
+    setHasIdeal(true);
+}
+
+bool DoubleConstraint::getMin(double&amp; min) const
+{
+    if (!hasMin())
+        return false;
+    
+    min = m_min;
+    return true;
+}
+
+bool DoubleConstraint::getMax(double&amp; max) const
+{
+    if (!hasMax())
+        return false;
+    
+    max = m_max;
+    return true;
+}
+
+bool DoubleConstraint::getExact(double&amp; exact) const
+{
+    if (!hasExact())
+        return false;
+    
+    exact = m_exact;
+    return true;
+}
+
+bool DoubleConstraint::getIdeal(double&amp; ideal) const
+{
+    if (!hasIdeal())
+        return false;
+    
+    ideal = m_ideal;
+    return true;
+}
+
+Ref&lt;BooleanConstraint&gt; BooleanConstraint::create(const String&amp; name)
+{
+    return adoptRef(*new BooleanConstraint(name));
+}
+
+void BooleanConstraint::setExact(bool value)
+{
+    m_exact = value;
+    m_hasExact = true;
+}
+
+void BooleanConstraint::setIdeal(bool value)
+{
+    m_ideal = value;
+    m_hasIdeal = true;
+}
+
+bool BooleanConstraint::getExact(bool&amp; exact) const
+{
+    if (!m_hasExact)
+        return false;
+    
+    exact = m_exact;
+    return true;
+}
+
+bool BooleanConstraint::getIdeal(bool&amp; ideal) const
+{
+    if (!m_hasIdeal)
+        return false;
+    
+    ideal = m_ideal;
+    return true;
+}
+
+Ref&lt;StringConstraint&gt; StringConstraint::create(const String&amp; name)
+{
+    return adoptRef(*new StringConstraint(name));
+}
+
+void StringConstraint::setExact(const String&amp; value)
+{
+    m_exact.clear();
+    m_exact.append(value);
+}
+
+void StringConstraint::appendExact(const String&amp; value)
+{
+    m_exact.clear();
+    m_exact.append(value);
+}
+
+void StringConstraint::setIdeal(const String&amp; value)
+{
+    m_ideal.clear();
+    m_ideal.append(value);
+}
+
+void StringConstraint::appendIdeal(const String&amp; value)
+{
+    m_ideal.append(value);
+}
+
+bool StringConstraint::getExact(Vector&lt;String&gt;&amp; exact) const
+{
+    if (!m_exact.isEmpty())
+        return false;
+
+    exact = m_exact;
+    return true;
+}
+
+bool StringConstraint::getIdeal(Vector&lt;String&gt;&amp; ideal) const
+{
+    if (!m_ideal.isEmpty())
+        return false;
+
+    ideal = m_ideal;
+    return true;
+}
+
+}
+
+#endif // ENABLE(MEDIA_STREAM)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaConstraintsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaConstraints.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaConstraints.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/MediaConstraints.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><ins>+ * Copyright (C) 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,32 +34,192 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/HashMap.h&gt;
</ins><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-struct MediaConstraint {
-    MediaConstraint(String name, String value)
</del><ins>+class MediaConstraint : public RefCounted&lt;MediaConstraint&gt; {
+public:
+    static RefPtr&lt;MediaConstraint&gt; create(const String&amp; name);
+
+    virtual ~MediaConstraint() { };
+    virtual bool isEmpty() const = 0;
+    virtual bool isMandatory() const = 0;
+
+    virtual bool getMin(int&amp;) const;
+    virtual bool getMax(int&amp;) const;
+    virtual bool getExact(int&amp;) const;
+    virtual bool getIdeal(int&amp;) const;
+
+    virtual bool getMin(double&amp;) const;
+    virtual bool getMax(double&amp;) const;
+    virtual bool getExact(double&amp;) const;
+    virtual bool getIdeal(double&amp;) const;
+
+    virtual bool getMin(bool&amp;) const;
+    virtual bool getMax(bool&amp;) const;
+    virtual bool getExact(bool&amp;) const;
+    virtual bool getIdeal(bool&amp;) const;
+
+    virtual bool getMin(Vector&lt;String&gt;&amp;) const;
+    virtual bool getMax(Vector&lt;String&gt;&amp;) const;
+    virtual bool getExact(Vector&lt;String&gt;&amp;) const;
+    virtual bool getIdeal(Vector&lt;String&gt;&amp;) const;
+
+    String name() const { return m_name; }
+
+protected:
+    explicit MediaConstraint(const String&amp; name)
</ins><span class="cx">         : m_name(name)
</span><del>-        , m_value(value)
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+private:
</ins><span class="cx">     String m_name;
</span><del>-    String m_value;
</del><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class NumericConstraint : public MediaConstraint {
+public:
+    bool isEmpty() const override { return !m_hasMin &amp;&amp; !m_hasMax &amp;&amp; !m_hasExact &amp;&amp; !m_hasIdeal; }
+    bool isMandatory() const override { return m_hasMin || m_hasMax || m_hasExact; }
+
+protected:
+    explicit NumericConstraint(const String&amp; name)
+        : MediaConstraint(name)
+    {
+    }
+
+    void setHasMin(bool value) { m_hasMin = value; }
+    void setHasMax(bool value) { m_hasMax = value; }
+    void setHasExact(bool value) { m_hasExact = value; }
+    void setHasIdeal(bool value) { m_hasIdeal = value; }
+
+    bool hasMin() const { return m_hasMin; }
+    bool hasMax() const { return m_hasMax; }
+    bool hasExact() const { return m_hasExact; }
+    bool hasIdeal() const { return m_hasIdeal; }
+
+private:
+    bool m_hasMin { false };
+    bool m_hasMax { false };
+    bool m_hasExact { false };
+    bool m_hasIdeal { false };
+};
+
+class IntConstraint final : public NumericConstraint {
+public:
+    static Ref&lt;IntConstraint&gt; create(const String&amp; name);
+
+    void setMin(int value);
+    void setMax(int value);
+    void setExact(int value);
+    void setIdeal(int value);
+
+    bool getMin(int&amp;) const final;
+    bool getMax(int&amp;) const final;
+    bool getExact(int&amp;) const final;
+    bool getIdeal(int&amp;) const final;
+
+private:
+    explicit IntConstraint(const String&amp; name)
+        : WebCore::NumericConstraint(name)
+    {
+    }
+
+    int m_min;
+    int m_max;
+    int m_exact;
+    int m_ideal;
+};
+
+class DoubleConstraint final : public NumericConstraint {
+public:
+    static Ref&lt;DoubleConstraint&gt; create(const String&amp; name);
+
+    void setMin(double value);
+    void setMax(double value);
+    void setExact(double value);
+    void setIdeal(double value);
+
+    bool getMin(double&amp;) const final;
+    bool getMax(double&amp;) const final;
+    bool getExact(double&amp;) const final;
+    bool getIdeal(double&amp;) const final;
+
+private:
+    explicit DoubleConstraint(const String&amp; name)
+        : WebCore::NumericConstraint(name)
+    {
+    }
+
+    double m_min;
+    double m_max;
+    double m_exact;
+    double m_ideal;
+};
+
+class BooleanConstraint final : public MediaConstraint {
+public:
+    static Ref&lt;BooleanConstraint&gt; create(const String&amp; name);
+
+    void setExact(bool value);
+    void setIdeal(bool value);
+
+    bool getExact(bool&amp;) const final;
+    bool getIdeal(bool&amp;) const final;
+
+    bool isEmpty() const final { return !m_hasExact &amp;&amp; !m_hasIdeal; };
+    bool isMandatory() const final { return m_hasExact; }
+
+private:
+    explicit BooleanConstraint(const String&amp; name)
+        : MediaConstraint(name)
+    {
+    }
+
+    bool m_exact { false };
+    bool m_ideal { false };
+    bool m_hasExact { false };
+    bool m_hasIdeal { false };
+};
+
+class StringConstraint final : public MediaConstraint {
+public:
+    static Ref&lt;StringConstraint&gt; create(const String&amp; name);
+
+    void setExact(const String&amp;);
+    void appendExact(const String&amp;);
+    void setIdeal(const String&amp;);
+    void appendIdeal(const String&amp;);
+
+    bool getExact(Vector&lt;String&gt;&amp;) const final;
+    bool getIdeal(Vector&lt;String&gt;&amp;) const final;
+
+    bool isEmpty() const final { return m_exact.isEmpty() &amp;&amp; m_ideal.isEmpty(); }
+    bool isMandatory() const final { return !m_exact.isEmpty(); }
+
+private:
+    explicit StringConstraint(const String&amp; name)
+        : MediaConstraint(name)
+    {
+    }
+
+    Vector&lt;String&gt; m_exact;
+    Vector&lt;String&gt; m_ideal;
+};
+
+using MediaTrackConstraintSetMap = HashMap&lt;String, RefPtr&lt;MediaConstraint&gt;&gt;;
+
</ins><span class="cx"> class MediaConstraints : public RefCounted&lt;MediaConstraints&gt; {
</span><span class="cx"> public:
</span><span class="cx">     virtual ~MediaConstraints() { }
</span><span class="cx"> 
</span><del>-    virtual void getMandatoryConstraints(Vector&lt;MediaConstraint&gt;&amp;) const = 0;
-    virtual void getOptionalConstraints(Vector&lt;MediaConstraint&gt;&amp;) const = 0;
</del><ins>+    virtual const MediaTrackConstraintSetMap&amp; mandatoryConstraints() const = 0;
+    virtual const Vector&lt;MediaTrackConstraintSetMap&gt;&amp; advancedConstraints() const = 0;
+    virtual bool isValid() const = 0;
</ins><span class="cx"> 
</span><del>-    virtual bool getMandatoryConstraintValue(const String&amp; name, String&amp; value) const = 0;
-    virtual bool getOptionalConstraintValue(const String&amp; name, String&amp; value) const = 0;
-
</del><span class="cx"> protected:
</span><span class="cx">     MediaConstraints() { }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceCenterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -55,11 +55,11 @@
</span><span class="cx">     WEBCORE_EXPORT static RealtimeMediaSourceCenter&amp; singleton();
</span><span class="cx">     static void setSharedStreamCenterOverride(RealtimeMediaSourceCenter*);
</span><span class="cx"> 
</span><del>-    virtual void validateRequestConstraints(MediaStreamCreationClient*, RefPtr&lt;MediaConstraints&gt;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp; videoConstraints) = 0;
</del><ins>+    virtual void validateRequestConstraints(MediaStreamCreationClient*, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual void createMediaStream(MediaStreamCreationClient*, const String&amp; audioDeviceID, const String&amp; videoDeviceID) = 0;
</span><span class="cx"> 
</span><del>-    virtual void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, PassRefPtr&lt;MediaConstraints&gt; audioConstraints, PassRefPtr&lt;MediaConstraints&gt; videoConstraints) = 0;
</del><ins>+    virtual void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual bool getMediaStreamTrackSources(PassRefPtr&lt;MediaStreamTrackSourcesRequestClient&gt;) = 0;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, MediaConstraints&amp;) override;
</span><span class="cx"> 
</span><span class="cx">     TrackSourceInfoVector getSourcesInfo(const String&amp;) override;
</span><del>-    bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, MediaConstraints*, const CaptureSessionInfo*, String&amp;) override;
</del><ins>+    bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, const MediaConstraints&amp;, const CaptureSessionInfo*, String&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     void deviceConnected();
</span><span class="cx">     void deviceDisconnected(AVCaptureDevice*);
</span><span class="lines">@@ -76,11 +76,11 @@
</span><span class="cx"> 
</span><span class="cx">     AVCaptureDeviceManager();
</span><span class="cx">     ~AVCaptureDeviceManager() override;
</span><del>-    bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const String&amp; name, const String&amp; value) override;
</del><ins>+    bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const MediaConstraint&amp;) override;
</ins><span class="cx">     RealtimeMediaSource* createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&amp;, MediaConstraints*) override;
</span><span class="cx">     CaptureSessionInfo defaultCaptureSession() const override;
</span><span class="cx">     void refreshCaptureDeviceList() override;
</span><del>-    bool isSupportedFrameRate(float frameRate) const override;
</del><ins>+    bool isSupportedFrameRate(const MediaConstraint&amp;) const override;
</ins><span class="cx"> 
</span><span class="cx">     void registerForDeviceNotifications();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -248,7 +248,7 @@
</span><span class="cx">     return CaptureDeviceManager::getSourcesInfo(requestOrigin);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVCaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, MediaConstraints* constraints, const CaptureSessionInfo* session, String&amp; invalidConstraint)
</del><ins>+bool AVCaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, const MediaConstraints&amp; constraints, const CaptureSessionInfo* session, String&amp; invalidConstraint)
</ins><span class="cx"> {
</span><span class="cx">     if (!isAvailable())
</span><span class="cx">         return false;
</span><span class="lines">@@ -264,11 +264,11 @@
</span><span class="cx">     return AVCaptureSessionInfo([allocAVCaptureSessionInstance() init]);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVCaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo* session, RealtimeMediaSource::Type type, const String&amp; name, const String&amp; value)
</del><ins>+bool AVCaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo* session, RealtimeMediaSource::Type type, const MediaConstraint&amp; constraint)
</ins><span class="cx"> {
</span><span class="cx">     const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
</span><del>-    MediaConstraintType constraint = supportedConstraints.constraintFromName(name);
-    if (!supportedConstraints.supportsConstraint(constraint))
</del><ins>+    MediaConstraintType constraintType = supportedConstraints.constraintFromName(constraint.name());
+    if (!supportedConstraints.supportsConstraint(constraintType))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     CaptureSessionInfo defaultSession = defaultCaptureSession();
</span><span class="lines">@@ -276,13 +276,25 @@
</span><span class="cx">         session = &amp;defaultSession;
</span><span class="cx"> 
</span><span class="cx">     if (type == RealtimeMediaSource::Video) {
</span><del>-        if (constraint == MediaConstraintType::Width)
-            return session-&gt;bestSessionPresetForVideoDimensions(value.toInt(), 0) != emptyString();
</del><ins>+        if (constraintType == MediaConstraintType::Width) {
+            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160578. Support min, max constraints.
+            int exact;
+            if (!constraint.getExact(exact))
+                return false;
</ins><span class="cx"> 
</span><del>-        if (constraint == MediaConstraintType::Height)
-            return session-&gt;bestSessionPresetForVideoDimensions(0, value.toInt()) != emptyString();
</del><ins>+            return !session-&gt;bestSessionPresetForVideoDimensions(exact, 0).isEmpty();
+        }
+
+        if (constraintType == MediaConstraintType::Height) {
+            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160578. Support min, max constraints.
+            int exact;
+            if (!constraint.getExact(exact))
+                return false;
+
+            return !session-&gt;bestSessionPresetForVideoDimensions(0, exact).isEmpty();
+        }
</ins><span class="cx">     }
</span><del>-    return CaptureDeviceManager::sessionSupportsConstraint(session, type, name, value);
</del><ins>+    return CaptureDeviceManager::sessionSupportsConstraint(session, type, constraint);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RealtimeMediaSource* AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&amp; captureDevice, MediaConstraints* constraints)
</span><span class="lines">@@ -303,7 +315,7 @@
</span><span class="cx">             captureSession = AVCaptureSessionInfo(captureSource-&gt;session());
</span><span class="cx"> 
</span><span class="cx">         String ignoredInvalidConstraints;
</span><del>-        if (!verifyConstraintsForMediaType(captureDevice.m_sourceType, constraints, &amp;captureSession, ignoredInvalidConstraints))
</del><ins>+        if (!verifyConstraintsForMediaType(captureDevice.m_sourceType, *constraints, &amp;captureSession, ignoredInvalidConstraints))
</ins><span class="cx">             return nullptr;
</span><span class="cx">     }
</span><span class="cx">     return captureSource.leakRef();
</span><span class="lines">@@ -337,11 +349,11 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVCaptureDeviceManager::isSupportedFrameRate(float frameRate) const
</del><ins>+bool AVCaptureDeviceManager::isSupportedFrameRate(const MediaConstraint&amp; constraint) const
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: We should use [AVCaptureConnection videoMinFrameDuration] and [AVCaptureConnection videoMaxFrameDuration],
</span><span class="cx">     // but they only work with a &quot;live&quot; AVCaptureConnection. For now, just use the default platform-independent behavior.
</span><del>-    return CaptureDeviceManager::isSupportedFrameRate(frameRate);
</del><ins>+    return CaptureDeviceManager::isSupportedFrameRate(constraint);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const RealtimeMediaSourceSupportedConstraints&amp; AVCaptureDeviceManager::supportedConstraints()
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx">     void initializeSupportedConstraints(RealtimeMediaSourceSupportedConstraints&amp;) override;
</span><span class="cx"> 
</span><span class="cx">     bool applyConstraints(MediaConstraints*);
</span><del>-    bool setFrameRateConstraint(float minFrameRate, float maxFrameRate);
</del><ins>+    bool setFrameRateConstraint(double minFrameRate, double maxFrameRate);
</ins><span class="cx"> 
</span><span class="cx">     bool updateFramerate(CMSampleBufferRef);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx">     settings.setAspectRatio(static_cast&lt;float&gt;(m_width) / m_height);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVVideoCaptureSource::setFrameRateConstraint(float minFrameRate, float maxFrameRate)
</del><ins>+bool AVVideoCaptureSource::setFrameRateConstraint(double minFrameRate, double maxFrameRate)
</ins><span class="cx"> {
</span><span class="cx">     AVFrameRateRange *bestFrameRateRange = 0;
</span><span class="cx"> 
</span><span class="lines">@@ -173,41 +173,45 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(constraints);
</span><span class="cx"> 
</span><del>-    const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
-    String widthConstraintValue;
-    String heightConstraintValue;
</del><ins>+    // FIXME: Below needs to be refactored for https://bugs.webkit.org/show_bug.cgi?id=160579.
+
+    auto&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
</ins><span class="cx">     String widthConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::Width);
</span><span class="cx">     String heightConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::Height);
</span><span class="cx"> 
</span><del>-    constraints-&gt;getMandatoryConstraintValue(widthConstraintName, widthConstraintValue);
-    constraints-&gt;getMandatoryConstraintValue(heightConstraintName, heightConstraintValue);
</del><ins>+    auto&amp; mandatoryConstraints = constraints-&gt;mandatoryConstraints();
</ins><span class="cx"> 
</span><del>-    int width = widthConstraintValue.toInt();
-    int height = heightConstraintValue.toInt();
-    if (!width &amp;&amp; !height) {
-        constraints-&gt;getOptionalConstraintValue(widthConstraintName, widthConstraintValue);
-        constraints-&gt;getOptionalConstraintValue(heightConstraintName, heightConstraintValue);
-        width = widthConstraintValue.toInt();
-        height = heightConstraintValue.toInt();
-    }
</del><ins>+    RefPtr&lt;MediaConstraint&gt; widthConstraint = mandatoryConstraints.get(widthConstraintName);
+    RefPtr&lt;MediaConstraint&gt; heightConstraint = mandatoryConstraints.get(heightConstraintName);
+
+    int intValue;
+
+    Optional&lt;int&gt; width;
+    if (widthConstraint &amp;&amp; widthConstraint-&gt;getExact(intValue))
+        width = intValue;
+
+    Optional&lt;int&gt; height;
+    if (heightConstraint &amp;&amp; heightConstraint-&gt;getExact(intValue))
+        height = intValue;
</ins><span class="cx">     
</span><del>-    if (width || height) {
-        NSString *preset = AVCaptureSessionInfo(session()).bestSessionPresetForVideoDimensions(width, height);
</del><ins>+    if (width &amp;&amp; height) {
+        NSString *preset = AVCaptureSessionInfo(session()).bestSessionPresetForVideoDimensions(width.value(), height.value());
</ins><span class="cx">         if (!preset || ![session() canSetSessionPreset:preset])
</span><span class="cx">             return false;
</span><del>-        
</del><ins>+
</ins><span class="cx">         [session() setSessionPreset:preset];
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    String frameRateConstraintValue;
</del><span class="cx">     String frameRateConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::FrameRate);
</span><del>-    constraints-&gt;getMandatoryConstraintValue(frameRateConstraintName, frameRateConstraintValue);
-    float frameRate = frameRateConstraintValue.toFloat();
-    if (!frameRate) {
-        constraints-&gt;getOptionalConstraintValue(frameRateConstraintName, frameRateConstraintValue);
-        frameRate = frameRateConstraintValue.toFloat();
-    }
-    if (frameRate &amp;&amp; !setFrameRateConstraint(frameRate, 0))
</del><ins>+    RefPtr&lt;MediaConstraint&gt; frameRateConstraint = mandatoryConstraints.get(frameRateConstraintName);
+
+    double doubleValue;
+
+    Optional&lt;double&gt; frameRate;
+    if (frameRateConstraint &amp;&amp; frameRateConstraint-&gt;getExact(doubleValue))
+        frameRate = doubleValue;
+
+    if (frameRate &amp;&amp; !setFrameRateConstraint(frameRate.value(), 0))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     return true;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacRealtimeMediaSourceCenterMaccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RealtimeMediaSourceCenterMac::validateRequestConstraints(MediaStreamCreationClient* client, RefPtr&lt;MediaConstraints&gt;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp; videoConstraints)
</del><ins>+void RealtimeMediaSourceCenterMac::validateRequestConstraints(MediaStreamCreationClient* client, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(client);
</span><span class="cx"> 
</span><span class="lines">@@ -74,31 +74,31 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; audioSources;
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; videoSources;
</span><span class="cx"> 
</span><del>-    if (audioConstraints) {
</del><ins>+    if (audioConstraints.isValid()) {
</ins><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints.get(), nullptr, invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints, nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;constraintsInvalid(invalidConstraint);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        audioSources = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Audio, *audioConstraints);
</del><ins>+        audioSources = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Audio, audioConstraints);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (videoConstraints) {
</del><ins>+    if (videoConstraints.isValid()) {
</ins><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints.get(), nullptr, invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints, nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;constraintsInvalid(invalidConstraint);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        videoSources = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Video, *videoConstraints);
</del><ins>+        videoSources = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Video, videoConstraints);
</ins><span class="cx">     }
</span><span class="cx">     client-&gt;constraintsValidated(audioSources, videoSources);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RealtimeMediaSourceCenterMac::createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt; prpQueryClient, PassRefPtr&lt;MediaConstraints&gt; audioConstraints, PassRefPtr&lt;MediaConstraints&gt; videoConstraints)
</del><ins>+void RealtimeMediaSourceCenterMac::createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt; prpQueryClient, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr&lt;MediaStreamCreationClient&gt; client = prpQueryClient;
</span><span class="cx">     
</span><span class="lines">@@ -107,9 +107,9 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; audioSources;
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; videoSources;
</span><span class="cx">     
</span><del>-    if (audioConstraints) {
</del><ins>+    if (audioConstraints.isValid()) {
</ins><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints.get(), nullptr, invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints, nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;failedToCreateStreamWithConstraintsError(invalidConstraint);
</span><span class="cx">             return;
</span><span class="lines">@@ -116,15 +116,15 @@
</span><span class="cx">         }
</span><span class="cx">         // FIXME: Consider the constraints when choosing among multiple devices. For now just select the first available
</span><span class="cx">         // device of the appropriate type.
</span><del>-        auto audioSource = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Audio, *audioConstraints).at(0);
</del><ins>+        auto audioSource = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Audio, audioConstraints).at(0);
</ins><span class="cx">         ASSERT(audioSource);
</span><span class="cx">         
</span><span class="cx">         audioSources.append(WTFMove(audioSource));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (videoConstraints) {
</del><ins>+    if (videoConstraints.isValid()) {
</ins><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints.get(), nullptr, invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints, nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;failedToCreateStreamWithConstraintsError(invalidConstraint);
</span><span class="cx">             return;
</span><span class="lines">@@ -131,7 +131,7 @@
</span><span class="cx">         }
</span><span class="cx">         // FIXME: Consider the constraints when choosing among multiple devices. For now just select the first available
</span><span class="cx">         // device of the appropriate type.
</span><del>-        auto videoSource = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Video, *videoConstraints).at(0);
</del><ins>+        auto videoSource = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Video, videoConstraints).at(0);
</ins><span class="cx">         ASSERT(videoSource);
</span><span class="cx">         
</span><span class="cx">         videoSources.append(WTFMove(videoSource));
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacRealtimeMediaSourceCenterMach"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -47,11 +47,11 @@
</span><span class="cx"> private:
</span><span class="cx">     ~RealtimeMediaSourceCenterMac();
</span><span class="cx"> 
</span><del>-    void validateRequestConstraints(MediaStreamCreationClient*, RefPtr&lt;MediaConstraints&gt;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp; videoConstraints) override;
-    void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, PassRefPtr&lt;MediaConstraints&gt; audioConstraints, PassRefPtr&lt;MediaConstraints&gt; videoConstraints) override;
-    void createMediaStream(MediaStreamCreationClient*, const String&amp; audioDeviceID, const String&amp; videoDeviceID) override;
-    bool getMediaStreamTrackSources(PassRefPtr&lt;MediaStreamTrackSourcesRequestClient&gt;) override;
-    RefPtr&lt;TrackSourceInfo&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*) override;
</del><ins>+    void validateRequestConstraints(MediaStreamCreationClient*, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) final;
+    void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) final;
+    void createMediaStream(MediaStreamCreationClient*, const String&amp; audioDeviceID, const String&amp; videoDeviceID) final;
+    bool getMediaStreamTrackSources(PassRefPtr&lt;MediaStreamTrackSourcesRequestClient&gt;) final;
+    RefPtr&lt;TrackSourceInfo&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*) final;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamopenwebrtcRealtimeMediaSourceCenterOwrcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -78,7 +78,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RealtimeMediaSourceCenterOwr::validateRequestConstraints(MediaStreamCreationClient* client, RefPtr&lt;MediaConstraints&gt;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp; videoConstraints)
</del><ins>+void RealtimeMediaSourceCenterOwr::validateRequestConstraints(MediaStreamCreationClient* client, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints)
</ins><span class="cx"> {
</span><span class="cx">     m_client = client;
</span><span class="cx"> 
</span><span class="lines">@@ -86,15 +86,15 @@
</span><span class="cx">     // need to comply with the available audio/video device(s)
</span><span class="cx">     // capabilities. See bug #123345.
</span><span class="cx">     int types = OWR_MEDIA_TYPE_UNKNOWN;
</span><del>-    if (audioConstraints)
</del><ins>+    if (audioConstraints.isValid())
</ins><span class="cx">         types |= OWR_MEDIA_TYPE_AUDIO;
</span><del>-    if (videoConstraints)
</del><ins>+    if (videoConstraints.isValid())
</ins><span class="cx">         types |= OWR_MEDIA_TYPE_VIDEO;
</span><span class="cx"> 
</span><span class="cx">     owr_get_capture_sources(static_cast&lt;OwrMediaType&gt;(types), mediaSourcesAvailableCallback, this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RealtimeMediaSourceCenterOwr::createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt; prpQueryClient, PassRefPtr&lt;MediaConstraints&gt; audioConstraints, PassRefPtr&lt;MediaConstraints&gt; videoConstraints)
</del><ins>+void RealtimeMediaSourceCenterOwr::createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt; prpQueryClient, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr&lt;MediaStreamCreationClient&gt; client = prpQueryClient;
</span><span class="cx">     ASSERT(client);
</span><span class="lines">@@ -105,7 +105,7 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; audioSources;
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; videoSources;
</span><span class="cx"> 
</span><del>-    if (audioConstraints) {
</del><ins>+    if (audioConstraints.isValid()) {
</ins><span class="cx">         // TODO: verify constraints according to registered
</span><span class="cx">         // sources. For now, unconditionally pick the first source, see bug #123345.
</span><span class="cx">         RefPtr&lt;RealtimeMediaSource&gt; audioSource = firstSource(RealtimeMediaSource::Audio);
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (videoConstraints) {
</del><ins>+    if (videoConstraints.isValid()) {
</ins><span class="cx">         // TODO: verify constraints according to registered
</span><span class="cx">         // sources. For now, unconditionally pick the first source, see bug #123345.
</span><span class="cx">         RefPtr&lt;RealtimeMediaSource&gt; videoSource = firstSource(RealtimeMediaSource::Video);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamopenwebrtcRealtimeMediaSourceCenterOwrh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mediastream/openwebrtc/RealtimeMediaSourceCenterOwr.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -53,15 +53,15 @@
</span><span class="cx">     RealtimeMediaSourceCenterOwr();
</span><span class="cx">     ~RealtimeMediaSourceCenterOwr();
</span><span class="cx"> 
</span><del>-    void validateRequestConstraints(MediaStreamCreationClient*, RefPtr&lt;MediaConstraints&gt;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp; videoConstraints) override;
</del><ins>+    void validateRequestConstraints(MediaStreamCreationClient*, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) final;
</ins><span class="cx"> 
</span><del>-    void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, PassRefPtr&lt;MediaConstraints&gt; audioConstraints, PassRefPtr&lt;MediaConstraints&gt; videoConstraints) override;
-    void createMediaStream(MediaStreamCreationClient*, const String&amp; audioDeviceID, const String&amp; videoDeviceID) override;
</del><ins>+    void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) final;
+    void createMediaStream(MediaStreamCreationClient*, const String&amp; audioDeviceID, const String&amp; videoDeviceID) final;
</ins><span class="cx"> 
</span><del>-    bool getMediaStreamTrackSources(PassRefPtr&lt;MediaStreamTrackSourcesRequestClient&gt;) override;
</del><ins>+    bool getMediaStreamTrackSources(PassRefPtr&lt;MediaStreamTrackSourcesRequestClient&gt;) final;
</ins><span class="cx"> 
</span><span class="cx">     void mediaSourcesAvailable(GList* sources);
</span><del>-    RefPtr&lt;TrackSourceInfo&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*) override;
</del><ins>+    RefPtr&lt;TrackSourceInfo&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*) final;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     PassRefPtr&lt;RealtimeMediaSource&gt; firstSource(RealtimeMediaSource::Type);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMediaConstraintsMockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -31,43 +31,107 @@
</span><span class="cx"> #include &quot;MediaConstraintsMock.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;MediaConstraints.h&quot;
</span><ins>+#include &quot;RealtimeMediaSourceCenter.h&quot;
+#include &quot;RealtimeMediaSourceSupportedConstraints.h&quot;
+#include &lt;wtf/text/StringHash.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static bool isSupported(const String&amp; constraint)
</del><ins>+static bool isIntMediaConstraintSatisfiable(const MediaConstraint&amp; constraint)
</ins><span class="cx"> {
</span><del>-    return notFound != constraint.find(&quot;_and_supported_&quot;);
</del><ins>+    int ceiling = 10;
+    int floor = 0;
+
+    int min = floor;
+    if (constraint.getMin(min) &amp;&amp; min &gt; ceiling)
+        return false;
+
+    int max = ceiling;
+    if (constraint.getMax(max) &amp;&amp; max &lt; min)
+        return false;
+
+    int exact;
+    if (constraint.getExact(exact) &amp;&amp; (exact &lt; min || exact &gt; max))
+        return false;
+
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool isValid(const String&amp; constraint)
</del><ins>+static bool isDoubleMediaConstraintSatisfiable(const MediaConstraint&amp; constraint)
</ins><span class="cx"> {
</span><del>-    return isSupported(constraint) || notFound != constraint.find(&quot;valid_&quot;);
</del><ins>+    double ceiling = 10;
+    double floor = 0;
+
+    double min = floor;
+    if (constraint.getMin(min) &amp;&amp; min &gt; ceiling)
+        return false;
+
+    double max = ceiling;
+    if (constraint.getMax(max) &amp;&amp; max &lt; min)
+        return false;
+
+    double exact;
+    if (constraint.getExact(exact) &amp;&amp; (exact &lt; min || exact &gt; max))
+        return false;
+
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-String MediaConstraintsMock::verifyConstraints(PassRefPtr&lt;MediaConstraints&gt; prpConstraints)
</del><ins>+static bool isBooleanMediaConstraintSatisfiable(const MediaConstraint&amp; constraint)
</ins><span class="cx"> {
</span><del>-    RefPtr&lt;MediaConstraints&gt; constraints = prpConstraints;
</del><ins>+    bool exact;
+    if (constraint.getExact(exact))
+        return exact;
</ins><span class="cx"> 
</span><del>-    Vector&lt;MediaConstraint&gt; mandatoryConstraints;
-    constraints-&gt;getMandatoryConstraints(mandatoryConstraints);
-    if (mandatoryConstraints.size()) {
-        for (size_t i = 0; i &lt; mandatoryConstraints.size(); ++i) {
-            const MediaConstraint&amp; curr = mandatoryConstraints[i];
-            if (!isSupported(curr.m_name) || curr.m_value != &quot;1&quot;)
-                return curr.m_name;
</del><ins>+    return true;
+}
+
+static bool isStringMediaConstraintSatisfiable(const MediaConstraint&amp; constraint)
+{
+    Vector&lt;String&gt; exact;
+    if (constraint.getExact(exact)) {
+        for (auto&amp; constraintValue : exact) {
+            if (constraintValue.find(&quot;invalid&quot;) != notFound)
+                return false;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><ins>+    
+    return true;
+}
</ins><span class="cx"> 
</span><del>-    Vector&lt;MediaConstraint&gt; optionalConstraints;
-    constraints-&gt;getOptionalConstraints(optionalConstraints);
-    if (optionalConstraints.size()) {
-        for (size_t i = 0; i &lt; optionalConstraints.size(); ++i) {
-            const MediaConstraint&amp; curr = optionalConstraints[i];
-            if (!isValid(curr.m_name) || curr.m_value != &quot;0&quot;)
-                return curr.m_name;
-        }
</del><ins>+static bool isSatisfiable(RealtimeMediaSource::Type type, const MediaConstraint&amp; constraint)
+{
+    const String&amp; name = constraint.name();
+
+    if (type == RealtimeMediaSource::Audio) {
+        if (name == &quot;sampleRate&quot; || name == &quot;sampleSize&quot;)
+            return isIntMediaConstraintSatisfiable(constraint);
+        if (name == &quot;volume&quot;)
+            return isDoubleMediaConstraintSatisfiable(constraint);
+        if (name == &quot;echoCancellation&quot;)
+            return isBooleanMediaConstraintSatisfiable(constraint);
+        if (name == &quot;deviceId&quot; || name == &quot;groupId&quot;)
+            return isStringMediaConstraintSatisfiable(constraint);
+    } else if (type == RealtimeMediaSource::Video) {
+        if (name == &quot;width&quot; || name == &quot;height&quot;)
+            return isIntMediaConstraintSatisfiable(constraint);
+        if (name == &quot;aspectRatio&quot; || name == &quot;frameRate&quot;)
+            return isDoubleMediaConstraintSatisfiable(constraint);
+        if (name == &quot;facingMode&quot; || name == &quot;deviceId&quot; || name == &quot;groupId&quot;)
+            return isStringMediaConstraintSatisfiable(constraint);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    return false;
+}
+
+const String&amp; MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Type type, const MediaConstraints&amp; constraints)
+{
+    auto&amp; mandatoryConstraints = constraints.mandatoryConstraints();
+    for (auto&amp; nameConstraintPair : mandatoryConstraints) {
+        if (!isSatisfiable(type, *nameConstraintPair.value))
+            return nameConstraintPair.key;
+    }
+
</ins><span class="cx">     return emptyString();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMediaConstraintsMockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><ins>+#include &quot;RealtimeMediaSource.h&quot;
</ins><span class="cx"> #include &lt;wtf/PassRefPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -38,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> class MediaConstraintsMock {
</span><span class="cx"> public:
</span><del>-    static String verifyConstraints(PassRefPtr&lt;MediaConstraints&gt;);
</del><ins>+    static const String&amp; verifyConstraints(RealtimeMediaSource::Type, const MediaConstraints&amp;);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx">     m_supportedConstraints.setSupportsDeviceId(true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MockRealtimeMediaSourceCenter::validateRequestConstraints(MediaStreamCreationClient* client, RefPtr&lt;MediaConstraints&gt;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp; videoConstraints)
</del><ins>+void MockRealtimeMediaSourceCenter::validateRequestConstraints(MediaStreamCreationClient* client, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(client);
</span><span class="cx"> 
</span><span class="lines">@@ -74,8 +74,8 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; audioSources;
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; videoSources;
</span><span class="cx"> 
</span><del>-    if (audioConstraints) {
-        String invalidQuery = MediaConstraintsMock::verifyConstraints(audioConstraints);
</del><ins>+    if (audioConstraints.isValid()) {
+        String invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Audio, audioConstraints);
</ins><span class="cx">         if (!invalidQuery.isEmpty()) {
</span><span class="cx">             client-&gt;constraintsInvalid(invalidQuery);
</span><span class="cx">             return;
</span><span class="lines">@@ -85,8 +85,8 @@
</span><span class="cx">         audioSources.append(WTFMove(audioSource));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (videoConstraints) {
-        String invalidQuery = MediaConstraintsMock::verifyConstraints(videoConstraints);
</del><ins>+    if (videoConstraints.isValid()) {
+        String invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Video, videoConstraints);
</ins><span class="cx">         if (!invalidQuery.isEmpty()) {
</span><span class="cx">             client-&gt;constraintsInvalid(invalidQuery);
</span><span class="cx">             return;
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx">     client-&gt;constraintsValidated(audioSources, videoSources);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MockRealtimeMediaSourceCenter::createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt; prpQueryClient, PassRefPtr&lt;MediaConstraints&gt; audioConstraints, PassRefPtr&lt;MediaConstraints&gt; videoConstraints)
</del><ins>+void MockRealtimeMediaSourceCenter::createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt; prpQueryClient, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr&lt;MediaStreamCreationClient&gt; client = prpQueryClient;
</span><span class="cx"> 
</span><span class="lines">@@ -108,8 +108,8 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; audioSources;
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; videoSources;
</span><span class="cx"> 
</span><del>-    if (audioConstraints) {
-        String invalidQuery = MediaConstraintsMock::verifyConstraints(audioConstraints);
</del><ins>+    if (audioConstraints.isValid()) {
+        const String&amp; invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Audio, audioConstraints);
</ins><span class="cx">         if (!invalidQuery.isEmpty()) {
</span><span class="cx">             client-&gt;failedToCreateStreamWithConstraintsError(invalidQuery);
</span><span class="cx">             return;
</span><span class="lines">@@ -119,8 +119,8 @@
</span><span class="cx">         audioSources.append(WTFMove(audioSource));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (videoConstraints) {
-        String invalidQuery = MediaConstraintsMock::verifyConstraints(videoConstraints);
</del><ins>+    if (videoConstraints.isValid()) {
+        const String&amp; invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Video, videoConstraints);
</ins><span class="cx">         if (!invalidQuery.isEmpty()) {
</span><span class="cx">             client-&gt;failedToCreateStreamWithConstraintsError(invalidQuery);
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCenterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h (204515 => 204516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h        2016-08-16 18:11:55 UTC (rev 204515)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h        2016-08-16 19:04:06 UTC (rev 204516)
</span><span class="lines">@@ -41,8 +41,8 @@
</span><span class="cx">     friend NeverDestroyed&lt;MockRealtimeMediaSourceCenter&gt;;
</span><span class="cx">     MockRealtimeMediaSourceCenter();
</span><span class="cx"> 
</span><del>-    void validateRequestConstraints(MediaStreamCreationClient*, RefPtr&lt;MediaConstraints&gt;&amp; audioConstraints, RefPtr&lt;MediaConstraints&gt;&amp; videoConstraints) override;
-    void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, PassRefPtr&lt;MediaConstraints&gt; audioConstraints, PassRefPtr&lt;MediaConstraints&gt; videoConstraints) override;
</del><ins>+    void validateRequestConstraints(MediaStreamCreationClient*, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) override;
+    void createMediaStream(PassRefPtr&lt;MediaStreamCreationClient&gt;, MediaConstraints&amp; audioConstraints, MediaConstraints&amp; videoConstraints) override;
</ins><span class="cx">     bool getMediaStreamTrackSources(PassRefPtr&lt;MediaStreamTrackSourcesRequestClient&gt;) override;
</span><span class="cx">     void createMediaStream(MediaStreamCreationClient*, const String&amp; audioDeviceID, const String&amp; videoDeviceID) override;
</span><span class="cx">     RefPtr&lt;TrackSourceInfo&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*) override;
</span></span></pre>
</div>
</div>

</body>
</html>