<!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>[206445] trunk/Source/WebCore</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/206445">206445</a></dd>
<dt>Author</dt> <dd>eric.carlson@apple.com</dd>
<dt>Date</dt> <dd>2016-09-27 10:58:44 -0700 (Tue, 27 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[MediaStream] Restructure MediaConstraints classes
https://bugs.webkit.org/show_bug.cgi?id=162571

Reviewed by Jer Noble.

No new tests, no functional changes.

* Modules/mediastream/MediaConstraintsImpl.cpp:
(WebCore::MediaConstraintsImpl::initialize): Deleted, no longer used.
* Modules/mediastream/MediaConstraintsImpl.h:

* bindings/js/JSMediaDevicesCustom.cpp:
(WebCore::createStringConstraint): Return Optional&lt;&gt; instead of RefPtr&lt;&gt;.
(WebCore::createBooleanConstraint): Ditto.
(WebCore::createDoubleConstraint): Ditto.
(WebCore::createIntConstraint): Ditto.
(WebCore::parseMediaTrackConstraintSetForKey): Deal with above change.

* platform/mediastream/CaptureDeviceManager.cpp:
(CaptureDeviceManager::verifyConstraintsForMediaType): Use constraints.mandatoryConstraints.filter
  instead of direct enumeration.
(CaptureDeviceManager::sessionSupportsConstraint): Use downcast&lt;&gt;.
(CaptureDeviceManager::isSupportedFrameRate): Ditto.

* platform/mediastream/MediaConstraints.cpp:
(WebCore::StringConstraint::find): Lose the ConstraintType parameter.
(WebCore::StringConstraint::merge): Use downcast&lt;&gt;.
(WebCore::FlattenedConstraint::set): Use ConstraintHolder.
(WebCore::FlattenedConstraint::merge): Ditto.
(WebCore::MediaTrackConstraintSetMap::forEach): New.
(WebCore::MediaTrackConstraintSetMap::filter): Ditto.
(WebCore::MediaTrackConstraintSetMap::isEmpty): Ditto.
(WebCore::MediaTrackConstraintSetMap::set): Ditto.
(WebCore::MediaConstraint::copy): Deleted.
(WebCore::IntConstraint::copy): Deleted.
(WebCore::DoubleConstraint::copy): Deleted.
(WebCore::BooleanConstraint::copy): Deleted.
(WebCore::StringConstraint::copy): Deleted.
* platform/mediastream/MediaConstraints.h:
(WebCore::MediaConstraint::MediaConstraint):
(WebCore::MediaConstraint::isEmpty):
(WebCore::MediaConstraint::isMandatory):
(WebCore::MediaConstraint::merge):
(WebCore::MediaConstraint::isInt):
(WebCore::MediaConstraint::isDouble):
(WebCore::MediaConstraint::isBoolean):
(WebCore::MediaConstraint::isString):
(WebCore::MediaConstraint::dataType):
(WebCore::MediaConstraint::constraintType):
(WebCore::NumericConstraint::getMin):
(WebCore::NumericConstraint::getMax):
(WebCore::NumericConstraint::getExact):
(WebCore::NumericConstraint::getIdeal):
(WebCore::NumericConstraint::fitnessDistance):
(WebCore::NumericConstraint::validForRange):
(WebCore::NumericConstraint::find):
(WebCore::NumericConstraint::NumericConstraint):
(WebCore::NumericConstraint::innerMerge):
(WebCore::FlattenedConstraint::isEmpty):
(WebCore::FlattenedConstraint::iterator::iterator):
(WebCore::FlattenedConstraint::iterator::operator*):
(WebCore::FlattenedConstraint::iterator::operator++):
(WebCore::FlattenedConstraint::iterator::operator==):
(WebCore::FlattenedConstraint::iterator::operator!=):
(WebCore::FlattenedConstraint::begin):
(WebCore::FlattenedConstraint::end):
(WebCore::FlattenedConstraint::ConstraintHolder::create):
(WebCore::FlattenedConstraint::ConstraintHolder::~ConstraintHolder):
(WebCore::FlattenedConstraint::ConstraintHolder::constraint):
(WebCore::FlattenedConstraint::ConstraintHolder::dataType):
(WebCore::FlattenedConstraint::ConstraintHolder::constraintType):
(WebCore::FlattenedConstraint::ConstraintHolder::ConstraintHolder):
(WebCore::MediaConstraint::getMin): Deleted.
(WebCore::MediaConstraint::getMax): Deleted.
(WebCore::MediaConstraint::getExact): Deleted.
(WebCore::MediaConstraint::getIdeal): Deleted.
(WebCore::MediaConstraint::validForRange): Deleted.
(WebCore::MediaConstraint::find): Deleted.
(WebCore::MediaConstraint::fitnessDistance): Deleted.
(WebCore::MediaConstraint::type): Deleted.

* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::fitnessDistance): Use downcast&lt;&gt;.
(WebCore::applyNumericConstraint):
(WebCore::RealtimeMediaSource::applyConstraint): Ditto.
(WebCore::RealtimeMediaSource::selectSettings): Ditto. Use constraints.mandatoryConstraints.filter
  instead of direct enumeration.
(WebCore::RealtimeMediaSource::applyConstraints):
(WebCore::RealtimeMediaSource::setSampleRate): Sample rate is an int, not a double.
(WebCore::RealtimeMediaSource::setSampleSize): Sample size is also an int.
* platform/mediastream/RealtimeMediaSource.h:

* platform/mediastream/mac/AVCaptureDeviceManager.mm:
(WebCore::AVCaptureDeviceManager::sessionSupportsConstraint): Use downcast&lt;&gt;.

* platform/mock/MediaConstraintsMock.cpp:
(WebCore::isIntMediaConstraintSatisfiable): Use downcast&lt;&gt;.
(WebCore::isDoubleMediaConstraintSatisfiable): Ditto.
(WebCore::isBooleanMediaConstraintSatisfiable): Ditto.
(WebCore::isStringMediaConstraintSatisfiable):
(WebCore::isSatisfiable):
(WebCore::MediaConstraintsMock::verifyConstraints): Use constraints.mandatoryConstraints.filter
  instead of direct enumeration.
* platform/mock/MediaConstraintsMock.h:

* platform/mock/MockRealtimeAudioSource.h:
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockRealtimeMediaSourceCenter::createMediaStream):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</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="#trunkSourceWebCorebindingsjsJSMediaDevicesCustomcpp">trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamCaptureDeviceManagercpp">trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaConstraintscpp">trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamMediaConstraintsh">trunk/Source/WebCore/platform/mediastream/MediaConstraints.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceh">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm">trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm</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="#trunkSourceWebCoreplatformmockMockRealtimeAudioSourceh">trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp">trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/ChangeLog        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -1,3 +1,114 @@
</span><ins>+2016-09-27  Eric Carlson  &lt;eric.carlson@apple.com&gt;
+
+        [MediaStream] Restructure MediaConstraints classes
+        https://bugs.webkit.org/show_bug.cgi?id=162571
+
+        Reviewed by Jer Noble.
+
+        No new tests, no functional changes.
+
+        * Modules/mediastream/MediaConstraintsImpl.cpp:
+        (WebCore::MediaConstraintsImpl::initialize): Deleted, no longer used.
+        * Modules/mediastream/MediaConstraintsImpl.h:
+
+        * bindings/js/JSMediaDevicesCustom.cpp:
+        (WebCore::createStringConstraint): Return Optional&lt;&gt; instead of RefPtr&lt;&gt;.
+        (WebCore::createBooleanConstraint): Ditto.
+        (WebCore::createDoubleConstraint): Ditto.
+        (WebCore::createIntConstraint): Ditto.
+        (WebCore::parseMediaTrackConstraintSetForKey): Deal with above change.
+
+        * platform/mediastream/CaptureDeviceManager.cpp:
+        (CaptureDeviceManager::verifyConstraintsForMediaType): Use constraints.mandatoryConstraints.filter
+          instead of direct enumeration.
+        (CaptureDeviceManager::sessionSupportsConstraint): Use downcast&lt;&gt;.
+        (CaptureDeviceManager::isSupportedFrameRate): Ditto.
+
+        * platform/mediastream/MediaConstraints.cpp:
+        (WebCore::StringConstraint::find): Lose the ConstraintType parameter.
+        (WebCore::StringConstraint::merge): Use downcast&lt;&gt;.
+        (WebCore::FlattenedConstraint::set): Use ConstraintHolder.
+        (WebCore::FlattenedConstraint::merge): Ditto.
+        (WebCore::MediaTrackConstraintSetMap::forEach): New.
+        (WebCore::MediaTrackConstraintSetMap::filter): Ditto.
+        (WebCore::MediaTrackConstraintSetMap::isEmpty): Ditto.
+        (WebCore::MediaTrackConstraintSetMap::set): Ditto.
+        (WebCore::MediaConstraint::copy): Deleted.
+        (WebCore::IntConstraint::copy): Deleted.
+        (WebCore::DoubleConstraint::copy): Deleted.
+        (WebCore::BooleanConstraint::copy): Deleted.
+        (WebCore::StringConstraint::copy): Deleted.
+        * platform/mediastream/MediaConstraints.h:
+        (WebCore::MediaConstraint::MediaConstraint):
+        (WebCore::MediaConstraint::isEmpty):
+        (WebCore::MediaConstraint::isMandatory):
+        (WebCore::MediaConstraint::merge):
+        (WebCore::MediaConstraint::isInt):
+        (WebCore::MediaConstraint::isDouble):
+        (WebCore::MediaConstraint::isBoolean):
+        (WebCore::MediaConstraint::isString):
+        (WebCore::MediaConstraint::dataType):
+        (WebCore::MediaConstraint::constraintType):
+        (WebCore::NumericConstraint::getMin):
+        (WebCore::NumericConstraint::getMax):
+        (WebCore::NumericConstraint::getExact):
+        (WebCore::NumericConstraint::getIdeal):
+        (WebCore::NumericConstraint::fitnessDistance):
+        (WebCore::NumericConstraint::validForRange):
+        (WebCore::NumericConstraint::find):
+        (WebCore::NumericConstraint::NumericConstraint):
+        (WebCore::NumericConstraint::innerMerge):
+        (WebCore::FlattenedConstraint::isEmpty):
+        (WebCore::FlattenedConstraint::iterator::iterator):
+        (WebCore::FlattenedConstraint::iterator::operator*):
+        (WebCore::FlattenedConstraint::iterator::operator++):
+        (WebCore::FlattenedConstraint::iterator::operator==):
+        (WebCore::FlattenedConstraint::iterator::operator!=):
+        (WebCore::FlattenedConstraint::begin):
+        (WebCore::FlattenedConstraint::end):
+        (WebCore::FlattenedConstraint::ConstraintHolder::create):
+        (WebCore::FlattenedConstraint::ConstraintHolder::~ConstraintHolder):
+        (WebCore::FlattenedConstraint::ConstraintHolder::constraint):
+        (WebCore::FlattenedConstraint::ConstraintHolder::dataType):
+        (WebCore::FlattenedConstraint::ConstraintHolder::constraintType):
+        (WebCore::FlattenedConstraint::ConstraintHolder::ConstraintHolder):
+        (WebCore::MediaConstraint::getMin): Deleted.
+        (WebCore::MediaConstraint::getMax): Deleted.
+        (WebCore::MediaConstraint::getExact): Deleted.
+        (WebCore::MediaConstraint::getIdeal): Deleted.
+        (WebCore::MediaConstraint::validForRange): Deleted.
+        (WebCore::MediaConstraint::find): Deleted.
+        (WebCore::MediaConstraint::fitnessDistance): Deleted.
+        (WebCore::MediaConstraint::type): Deleted.
+
+        * platform/mediastream/RealtimeMediaSource.cpp:
+        (WebCore::RealtimeMediaSource::fitnessDistance): Use downcast&lt;&gt;.
+        (WebCore::applyNumericConstraint):
+        (WebCore::RealtimeMediaSource::applyConstraint): Ditto.
+        (WebCore::RealtimeMediaSource::selectSettings): Ditto. Use constraints.mandatoryConstraints.filter
+          instead of direct enumeration.
+        (WebCore::RealtimeMediaSource::applyConstraints):
+        (WebCore::RealtimeMediaSource::setSampleRate): Sample rate is an int, not a double.
+        (WebCore::RealtimeMediaSource::setSampleSize): Sample size is also an int.
+        * platform/mediastream/RealtimeMediaSource.h:
+
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::AVCaptureDeviceManager::sessionSupportsConstraint): Use downcast&lt;&gt;.
+
+        * platform/mock/MediaConstraintsMock.cpp:
+        (WebCore::isIntMediaConstraintSatisfiable): Use downcast&lt;&gt;.
+        (WebCore::isDoubleMediaConstraintSatisfiable): Ditto.
+        (WebCore::isBooleanMediaConstraintSatisfiable): Ditto.
+        (WebCore::isStringMediaConstraintSatisfiable):
+        (WebCore::isSatisfiable):
+        (WebCore::MediaConstraintsMock::verifyConstraints): Use constraints.mandatoryConstraints.filter
+          instead of direct enumeration.
+        * platform/mock/MediaConstraintsMock.h:
+
+        * platform/mock/MockRealtimeAudioSource.h:
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockRealtimeMediaSourceCenter::createMediaStream):
+
</ins><span class="cx"> 2016-09-27  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Some Now Playing behavior is broken after r206315
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaConstraintsImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.cpp        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -46,13 +46,6 @@
</span><span class="cx">     return adoptRef(*new MediaConstraintsImpl());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// FIXME: Remove after https://bugs.webkit.org/show_bug.cgi?id=160579
-void MediaConstraintsImpl::initialize(const Dictionary&amp; constraints)
-{
-    if (constraints.isUndefinedOrNull())
-        return;
-}
-
</del><span class="cx"> Ref&lt;MediaConstraintsImpl&gt; MediaConstraintsImpl::create(MediaTrackConstraintSetMap&amp;&amp; mandatoryConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp;&amp; advancedConstraints, bool isValid)
</span><span class="cx"> {
</span><span class="cx">     return adoptRef(*new MediaConstraintsImpl(WTFMove(mandatoryConstraints), WTFMove(advancedConstraints), isValid));
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaConstraintsImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/Modules/mediastream/MediaConstraintsImpl.h        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -48,7 +48,6 @@
</span><span class="cx">     static Ref&lt;MediaConstraintsImpl&gt; create(MediaTrackConstraintSetMap&amp;&amp; mandatoryConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp;&amp; advancedConstraints, bool isValid);
</span><span class="cx"> 
</span><span class="cx">     virtual ~MediaConstraintsImpl();
</span><del>-    void initialize(const Dictionary&amp;);
</del><span class="cx"> 
</span><span class="cx">     const MediaTrackConstraintSetMap&amp; mandatoryConstraints() const final { return m_mandatoryConstraints; }
</span><span class="cx">     const Vector&lt;MediaTrackConstraintSetMap&gt;&amp; advancedConstraints() const final { return m_advancedConstraints; }
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMediaDevicesCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -58,9 +58,9 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static RefPtr&lt;StringConstraint&gt; createStringConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</del><ins>+static Optional&lt;StringConstraint&gt; createStringConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</ins><span class="cx"> {
</span><del>-    auto constraint = StringConstraint::create(name, type);
</del><ins>+    auto constraint = StringConstraint(name, type);
</ins><span class="cx"> 
</span><span class="cx">     // Dictionary constraint value.
</span><span class="cx">     Dictionary dictionaryValue;
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">         else {
</span><span class="cx">             String exactStringValue;
</span><span class="cx">             if (dictionaryValue.get(&quot;exact&quot;, exactStringValue))
</span><del>-                constraint-&gt;setExact(exactStringValue);
</del><ins>+                constraint.setExact(exactStringValue);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         ArrayValue idealArrayValue;
</span><span class="lines">@@ -80,12 +80,12 @@
</span><span class="cx">         else {
</span><span class="cx">             String idealStringValue;
</span><span class="cx">             if (!dictionaryValue.get(&quot;ideal&quot;, idealStringValue))
</span><del>-                constraint-&gt;setIdeal(idealStringValue);
</del><ins>+                constraint.setIdeal(idealStringValue);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (constraint-&gt;isEmpty()) {
</del><ins>+        if (constraint.isEmpty()) {
</ins><span class="cx">             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());
</span><del>-            return nullptr;
</del><ins>+            return Nullopt;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         return WTFMove(constraint);
</span><span class="lines">@@ -96,9 +96,9 @@
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, arrayValue) &amp;&amp; !arrayValue.isUndefinedOrNull()) {
</span><span class="cx">         initializeStringConstraintWithList(constraint, &amp;StringConstraint::appendIdeal, arrayValue);
</span><span class="cx"> 
</span><del>-        if (constraint-&gt;isEmpty()) {
</del><ins>+        if (constraint.isEmpty()) {
</ins><span class="cx">             LOG(Media, &quot;createStringConstraint() - ignoring string constraint '%s' with array value since it is empty.&quot;, name.utf8().data());
</span><del>-            return nullptr;
</del><ins>+            return Nullopt;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return WTFMove(constraint);
</span><span class="lines">@@ -108,9 +108,9 @@
</span><span class="cx">     String value;
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, value)) {
</span><span class="cx">         if (constraintSetType == ConstraintSetType::Mandatory)
</span><del>-            constraint-&gt;setIdeal(value);
</del><ins>+            constraint.setIdeal(value);
</ins><span class="cx">         else
</span><del>-            constraint-&gt;setExact(value);
</del><ins>+            constraint.setExact(value);
</ins><span class="cx">         
</span><span class="cx">         return WTFMove(constraint);
</span><span class="cx">     }
</span><span class="lines">@@ -117,12 +117,12 @@
</span><span class="cx"> 
</span><span class="cx">     // Invalid constraint value.
</span><span class="cx">     LOG(Media, &quot;createStringConstraint() - ignoring string constraint '%s' since it has neither a dictionary nor sequence nor scalar value.&quot;, name.utf8().data());
</span><del>-    return nullptr;
</del><ins>+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static RefPtr&lt;BooleanConstraint&gt; createBooleanConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</del><ins>+static Optional&lt;BooleanConstraint&gt; createBooleanConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</ins><span class="cx"> {
</span><del>-    auto constraint = BooleanConstraint::create(name, type);
</del><ins>+    auto constraint = BooleanConstraint(name, type);
</ins><span class="cx"> 
</span><span class="cx">     // Dictionary constraint value.
</span><span class="cx">     Dictionary dictionaryValue;
</span><span class="lines">@@ -129,15 +129,15 @@
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, dictionaryValue) &amp;&amp; !dictionaryValue.isUndefinedOrNull()) {
</span><span class="cx">         bool exactValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;exact&quot;, exactValue))
</span><del>-            constraint-&gt;setExact(exactValue);
</del><ins>+            constraint.setExact(exactValue);
</ins><span class="cx"> 
</span><span class="cx">         bool idealValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;ideal&quot;, idealValue))
</span><del>-            constraint-&gt;setIdeal(idealValue);
</del><ins>+            constraint.setIdeal(idealValue);
</ins><span class="cx"> 
</span><del>-        if (constraint-&gt;isEmpty()) {
</del><ins>+        if (constraint.isEmpty()) {
</ins><span class="cx">             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());
</span><del>-            return nullptr;
</del><ins>+            return Nullopt;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return WTFMove(constraint);
</span><span class="lines">@@ -147,9 +147,9 @@
</span><span class="cx">     bool value;
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, value)) {
</span><span class="cx">         if (constraintSetType == ConstraintSetType::Mandatory)
</span><del>-            constraint-&gt;setIdeal(value);
</del><ins>+            constraint.setIdeal(value);
</ins><span class="cx">         else
</span><del>-            constraint-&gt;setExact(value);
</del><ins>+            constraint.setExact(value);
</ins><span class="cx">         
</span><span class="cx">         return WTFMove(constraint);
</span><span class="cx">     }
</span><span class="lines">@@ -156,12 +156,12 @@
</span><span class="cx"> 
</span><span class="cx">     // Invalid constraint value.
</span><span class="cx">     LOG(Media, &quot;createBooleanConstraint() - ignoring boolean constraint '%s' since it has neither a dictionary nor scalar value.&quot;, name.utf8().data());
</span><del>-    return nullptr;
</del><ins>+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static RefPtr&lt;DoubleConstraint&gt; createDoubleConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</del><ins>+static Optional&lt;DoubleConstraint&gt; createDoubleConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</ins><span class="cx"> {
</span><del>-    auto constraint = DoubleConstraint::create(name, type);
</del><ins>+    auto constraint = DoubleConstraint(name, type);
</ins><span class="cx"> 
</span><span class="cx">     // Dictionary constraint value.
</span><span class="cx">     Dictionary dictionaryValue;
</span><span class="lines">@@ -168,23 +168,23 @@
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, dictionaryValue) &amp;&amp; !dictionaryValue.isUndefinedOrNull()) {
</span><span class="cx">         double minValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;min&quot;, minValue))
</span><del>-            constraint-&gt;setMin(minValue);
</del><ins>+            constraint.setMin(minValue);
</ins><span class="cx"> 
</span><span class="cx">         double maxValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;max&quot;, maxValue))
</span><del>-            constraint-&gt;setMax(maxValue);
</del><ins>+            constraint.setMax(maxValue);
</ins><span class="cx"> 
</span><span class="cx">         double exactValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;exact&quot;, exactValue))
</span><del>-            constraint-&gt;setExact(exactValue);
</del><ins>+            constraint.setExact(exactValue);
</ins><span class="cx"> 
</span><span class="cx">         double idealValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;ideal&quot;, idealValue))
</span><del>-            constraint-&gt;setIdeal(idealValue);
</del><ins>+            constraint.setIdeal(idealValue);
</ins><span class="cx"> 
</span><del>-        if (constraint-&gt;isEmpty()) {
</del><ins>+        if (constraint.isEmpty()) {
</ins><span class="cx">             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());
</span><del>-            return nullptr;
</del><ins>+            return Nullopt;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return WTFMove(constraint);
</span><span class="lines">@@ -194,9 +194,9 @@
</span><span class="cx">     double value;
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, value)) {
</span><span class="cx">         if (constraintSetType == ConstraintSetType::Mandatory)
</span><del>-            constraint-&gt;setIdeal(value);
</del><ins>+            constraint.setIdeal(value);
</ins><span class="cx">         else
</span><del>-            constraint-&gt;setExact(value);
</del><ins>+            constraint.setExact(value);
</ins><span class="cx">         
</span><span class="cx">         return WTFMove(constraint);
</span><span class="cx">     }
</span><span class="lines">@@ -203,12 +203,12 @@
</span><span class="cx"> 
</span><span class="cx">     // Invalid constraint value.
</span><span class="cx">     LOG(Media, &quot;createDoubleConstraint() - ignoring double constraint '%s' since it has neither a dictionary nor scalar value.&quot;, name.utf8().data());
</span><del>-    return nullptr;
</del><ins>+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static RefPtr&lt;IntConstraint&gt; createIntConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</del><ins>+static Optional&lt;IntConstraint&gt; createIntConstraint(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaConstraintType type, ConstraintSetType constraintSetType)
</ins><span class="cx"> {
</span><del>-    auto constraint = IntConstraint::create(name, type);
</del><ins>+    auto constraint = IntConstraint(name, type);
</ins><span class="cx"> 
</span><span class="cx">     // Dictionary constraint value.
</span><span class="cx">     Dictionary dictionaryValue;
</span><span class="lines">@@ -215,23 +215,23 @@
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, dictionaryValue) &amp;&amp; !dictionaryValue.isUndefinedOrNull()) {
</span><span class="cx">         int minValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;min&quot;, minValue))
</span><del>-            constraint-&gt;setMin(minValue);
</del><ins>+            constraint.setMin(minValue);
</ins><span class="cx"> 
</span><span class="cx">         int maxValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;max&quot;, maxValue))
</span><del>-            constraint-&gt;setMax(maxValue);
</del><ins>+            constraint.setMax(maxValue);
</ins><span class="cx"> 
</span><span class="cx">         int exactValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;exact&quot;, exactValue))
</span><del>-            constraint-&gt;setExact(exactValue);
</del><ins>+            constraint.setExact(exactValue);
</ins><span class="cx"> 
</span><span class="cx">         int idealValue;
</span><span class="cx">         if (dictionaryValue.get(&quot;ideal&quot;, idealValue))
</span><del>-            constraint-&gt;setIdeal(idealValue);
</del><ins>+            constraint.setIdeal(idealValue);
</ins><span class="cx"> 
</span><del>-        if (constraint-&gt;isEmpty()) {
</del><ins>+        if (constraint.isEmpty()) {
</ins><span class="cx">             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());
</span><del>-            return nullptr;
</del><ins>+            return Nullopt;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return WTFMove(constraint);
</span><span class="lines">@@ -241,9 +241,9 @@
</span><span class="cx">     int value;
</span><span class="cx">     if (mediaTrackConstraintSet.get(name, value)) {
</span><span class="cx">         if (constraintSetType == ConstraintSetType::Mandatory)
</span><del>-            constraint-&gt;setIdeal(value);
</del><ins>+            constraint.setIdeal(value);
</ins><span class="cx">         else
</span><del>-            constraint-&gt;setExact(value);
</del><ins>+            constraint.setExact(value);
</ins><span class="cx">         
</span><span class="cx">         return WTFMove(constraint);
</span><span class="cx">     }
</span><span class="lines">@@ -250,45 +250,54 @@
</span><span class="cx"> 
</span><span class="cx">     // Invalid constraint value.
</span><span class="cx">     LOG(Media, &quot;createIntConstraint() - ignoring long constraint '%s' since it has neither a dictionary nor scalar value.&quot;, name.utf8().data());
</span><del>-    return nullptr;
</del><ins>+    return Nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void parseMediaTrackConstraintSetForKey(const Dictionary&amp; mediaTrackConstraintSet, const String&amp; name, MediaTrackConstraintSetMap&amp; map, ConstraintSetType constraintSetType)
</span><span class="cx"> {
</span><span class="cx">     MediaConstraintType constraintType = RealtimeMediaSourceSupportedConstraints::constraintFromName(name);
</span><del>-
-    RefPtr&lt;MediaConstraint&gt; mediaConstraint;
</del><span class="cx">     switch (constraintType) {
</span><span class="cx">     case MediaConstraintType::Width:
</span><ins>+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
</ins><span class="cx">     case MediaConstraintType::Height:
</span><ins>+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
</ins><span class="cx">     case MediaConstraintType::SampleRate:
</span><ins>+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
</ins><span class="cx">     case MediaConstraintType::SampleSize:
</span><del>-        mediaConstraint = createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
</del><ins>+        map.set(constraintType, createIntConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::AspectRatio:
</span><ins>+        map.set(constraintType, createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
</ins><span class="cx">     case MediaConstraintType::FrameRate:
</span><ins>+        map.set(constraintType, createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
</ins><span class="cx">     case MediaConstraintType::Volume:
</span><del>-        mediaConstraint = createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
</del><ins>+        map.set(constraintType, createDoubleConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::EchoCancellation:
</span><del>-        mediaConstraint = createBooleanConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
</del><ins>+        map.set(constraintType, createBooleanConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::FacingMode:
</span><ins>+        map.set(constraintType, createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
</ins><span class="cx">     case MediaConstraintType::DeviceId:
</span><ins>+        map.set(constraintType, createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
+        break;
</ins><span class="cx">     case MediaConstraintType::GroupId:
</span><del>-        mediaConstraint = createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType);
</del><ins>+        map.set(constraintType, createStringConstraint(mediaTrackConstraintSet, name, constraintType, constraintSetType));
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::Unknown:
</span><del>-        LOG(Media, &quot;parseMediaTrackConstraintSetForKey() - found unsupported constraint '%s'.&quot;, name.utf8().data());
-        mediaConstraint = UnknownConstraint::create(name, constraintType);
-        break;
</del><ins>+        LOG(Media, &quot;parseMediaTrackConstraintSetForKey() - ignoring unsupported constraint '%s'.&quot;, name.utf8().data());
+        return;
</ins><span class="cx">     }
</span><del>-    
-    map.add(name, WTFMove(mediaConstraint));
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void parseAdvancedConstraints(const Dictionary&amp; mediaTrackConstraints, Vector&lt;MediaTrackConstraintSetMap&gt;&amp; advancedConstraints)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamCaptureDeviceManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -72,16 +72,18 @@
</span><span class="cx"> 
</span><span class="cx"> bool CaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, const MediaConstraints&amp; constraints, const CaptureSessionInfo* session, String&amp; invalidConstraint)
</span><span class="cx"> {
</span><del>-    auto&amp; mandatoryConstraints = constraints.mandatoryConstraints();
-    for (auto&amp; nameConstraintPair : mandatoryConstraints) {
-        if (sessionSupportsConstraint(session, type, *nameConstraintPair.value))
-            continue;
</del><ins>+    invalidConstraint = emptyString();
+    constraints.mandatoryConstraints().filter([&amp;](const MediaConstraint&amp; constraint) {
+        if (!sessionSupportsConstraint(session, type, constraint)) {
+            invalidConstraint = constraint.name();
+            return true;
+        }
</ins><span class="cx"> 
</span><del>-        invalidConstraint = nameConstraintPair.key;
</del><span class="cx">         return false;
</span><del>-    }
</del><ins>+    });
</ins><span class="cx"> 
</span><del>-    return true;
</del><ins>+    return invalidConstraint.isEmpty();
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; CaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, MediaConstraints&amp; constraints)
</span><span class="lines">@@ -153,7 +155,7 @@
</span><span class="cx"> bool CaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type type, const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><span class="cx">     const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
</span><del>-    MediaConstraintType constraintType = constraint.type();
</del><ins>+    MediaConstraintType constraintType = constraint.constraintType();
</ins><span class="cx">     if (!supportedConstraints.supportsConstraint(constraintType))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="lines">@@ -176,7 +178,7 @@
</span><span class="cx"> 
</span><span class="cx">         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160793. Handle sequence of facingMode constraints.
</span><span class="cx">         Vector&lt;String&gt; exactFacingMode;
</span><del>-        if (!constraint.getExact(exactFacingMode))
</del><ins>+        if (!downcast&lt;const StringConstraint&gt;(constraint).getExact(exactFacingMode))
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         return bestDeviceForFacingMode(facingModeFromString(exactFacingMode[0]));
</span><span class="lines">@@ -192,15 +194,15 @@
</span><span class="cx">     bool isSupported = true;
</span><span class="cx"> 
</span><span class="cx">     int min = 0;
</span><del>-    if (constraint.getMin(min))
</del><ins>+    if (downcast&lt;const IntConstraint&gt;(constraint).getMin(min))
</ins><span class="cx">         isSupported &amp;= min &gt; 60;
</span><span class="cx"> 
</span><span class="cx">     int max = 60;
</span><del>-    if (constraint.getMax(max))
</del><ins>+    if (downcast&lt;const IntConstraint&gt;(constraint).getMax(max))
</ins><span class="cx">         isSupported &amp;= max &lt; min;
</span><span class="cx"> 
</span><span class="cx">     int exact;
</span><del>-    if (constraint.getExact(exact))
</del><ins>+    if (downcast&lt;const IntConstraint&gt;(constraint).getExact(exact))
</ins><span class="cx">         isSupported &amp;= (exact &lt; min || exact &gt; max);
</span><span class="cx"> 
</span><span class="cx">     return isSupported;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaConstraintscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/MediaConstraints.cpp        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -34,82 +34,10 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> #include &quot;RealtimeMediaSourceCenter.h&quot;
</span><span class="cx"> #include &quot;RealtimeMediaSourceSupportedConstraints.h&quot;
</span><ins>+#include &lt;wtf/StdLibExtras.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-Ref&lt;MediaConstraint&gt; MediaConstraint::create(const String&amp; name)
-{
-    MediaConstraintType constraintType = RealtimeMediaSourceSupportedConstraints::constraintFromName(name);
-
-    switch (constraintType) {
-    case MediaConstraintType::Width:
-    case MediaConstraintType::Height:
-    case MediaConstraintType::SampleRate:
-    case MediaConstraintType::SampleSize:
-        return IntConstraint::create(name, constraintType);
-    case MediaConstraintType::AspectRatio:
-    case MediaConstraintType::FrameRate:
-    case MediaConstraintType::Volume:
-        return DoubleConstraint::create(name, constraintType);
-    case MediaConstraintType::EchoCancellation:
-        return BooleanConstraint::create(name, constraintType);
-    case MediaConstraintType::FacingMode:
-    case MediaConstraintType::DeviceId:
-    case MediaConstraintType::GroupId:
-        return StringConstraint::create(name, constraintType);
-    case MediaConstraintType::Unknown:
-        return UnknownConstraint::create(name, constraintType);
-    }
-
-    ASSERT_NOT_REACHED();
-    return MediaConstraint::create(String());
-}
-
-Ref&lt;MediaConstraint&gt; MediaConstraint::copy() const
-{
-    return MediaConstraint::create(name());
-}
-
-Ref&lt;MediaConstraint&gt; IntConstraint::copy() const
-{
-    auto copy = IntConstraint::create(name(), type());
-    copy-&gt;m_min = m_min;
-    copy-&gt;m_max = m_max;
-    copy-&gt;m_exact = m_exact;
-    copy-&gt;m_ideal = m_ideal;
-
-    return copy.leakRef();
-}
-
-Ref&lt;MediaConstraint&gt; DoubleConstraint::copy() const
-{
-    auto copy = DoubleConstraint::create(name(), type());
-    copy-&gt;m_min = m_min;
-    copy-&gt;m_max = m_max;
-    copy-&gt;m_exact = m_exact;
-    copy-&gt;m_ideal = m_ideal;
-    
-    return copy.leakRef();
-}
-
-Ref&lt;MediaConstraint&gt; BooleanConstraint::copy() const
-{
-    auto copy = BooleanConstraint::create(name(), type());
-    copy-&gt;m_exact = m_exact;
-    copy-&gt;m_ideal = m_ideal;
-
-    return copy.leakRef();
-}
-
-Ref&lt;MediaConstraint&gt; StringConstraint::copy() const
-{
-    auto copy = StringConstraint::create(name(), type());
-    copy-&gt;m_exact = m_exact;
-    copy-&gt;m_ideal = m_ideal;
-
-    return copy.leakRef();
-}
-
</del><span class="cx"> bool BooleanConstraint::getExact(bool&amp; exact) const
</span><span class="cx"> {
</span><span class="cx">     if (!m_exact)
</span><span class="lines">@@ -169,15 +97,15 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const String&amp; StringConstraint::find(std::function&lt;bool(ConstraintType, const String&amp;)&gt; filter) const
</del><ins>+const String&amp; StringConstraint::find(std::function&lt;bool(const String&amp;)&gt; filter) const
</ins><span class="cx"> {
</span><span class="cx">     for (auto&amp; constraint : m_exact) {
</span><del>-        if (filter(ConstraintType::ExactConstraint, constraint))
</del><ins>+        if (filter(constraint))
</ins><span class="cx">             return constraint;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; constraint : m_ideal) {
</span><del>-        if (filter(ConstraintType::IdealConstraint, constraint))
</del><ins>+        if (filter(constraint))
</ins><span class="cx">             return constraint;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -222,11 +150,14 @@
</span><span class="cx"> 
</span><span class="cx"> void StringConstraint::merge(const MediaConstraint&amp; other)
</span><span class="cx"> {
</span><ins>+    ASSERT(other.isString());
+    const StringConstraint&amp; typedOther = downcast&lt;StringConstraint&gt;(other);
+
</ins><span class="cx">     if (other.isEmpty())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;String&gt; values;
</span><del>-    if (other.getExact(values)) {
</del><ins>+    if (typedOther.getExact(values)) {
</ins><span class="cx">         if (m_exact.isEmpty())
</span><span class="cx">             m_exact = values;
</span><span class="cx">         else {
</span><span class="lines">@@ -237,7 +168,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (other.getIdeal(values)) {
</del><ins>+    if (typedOther.getIdeal(values)) {
</ins><span class="cx">         if (m_ideal.isEmpty())
</span><span class="cx">             m_ideal = values;
</span><span class="cx">         else {
</span><span class="lines">@@ -251,28 +182,235 @@
</span><span class="cx"> 
</span><span class="cx"> void FlattenedConstraint::set(const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><del>-    for (auto existingConstraint : m_constraints) {
-        if (existingConstraint-&gt;type() == constraint.type()) {
-            existingConstraint = constraint.copy();
</del><ins>+    for (auto&amp; variant : m_variants) {
+        if (variant.constraintType() == constraint.constraintType())
</ins><span class="cx">             return;
</span><del>-        }
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_constraints.append(constraint.copy());
</del><ins>+    append(constraint);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void FlattenedConstraint::merge(const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><del>-    for (auto existingConstraint : m_constraints) {
-        if (existingConstraint-&gt;type() == constraint.type()) {
-            existingConstraint-&gt;merge(constraint);
</del><ins>+    for (auto&amp; variant : *this) {
+        if (variant.constraintType() != constraint.constraintType())
+            continue;
+
+        switch (variant.dataType()) {
+        case MediaConstraint::DataType::Integer:
+            ASSERT(constraint.isInt());
+            downcast&lt;const IntConstraint&gt;(variant).merge(downcast&lt;const IntConstraint&gt;(constraint));
</ins><span class="cx">             return;
</span><ins>+        case MediaConstraint::DataType::Double:
+            ASSERT(constraint.isDouble());
+            downcast&lt;const DoubleConstraint&gt;(variant).merge(downcast&lt;const DoubleConstraint&gt;(constraint));
+            return;
+        case MediaConstraint::DataType::Boolean:
+            ASSERT(constraint.isBoolean());
+            downcast&lt;const BooleanConstraint&gt;(variant).merge(downcast&lt;const BooleanConstraint&gt;(constraint));
+            return;
+        case MediaConstraint::DataType::String:
+            ASSERT(constraint.isString());
+            downcast&lt;const StringConstraint&gt;(variant).merge(downcast&lt;const StringConstraint&gt;(constraint));
+            return;
+        case MediaConstraint::DataType::None:
+            ASSERT_NOT_REACHED();
+            return;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_constraints.append(constraint.copy());
</del><ins>+    append(constraint);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void FlattenedConstraint::append(const MediaConstraint&amp; constraint)
+{
+#ifndef NDEBUG
+    ++m_generation;
+#endif
+
+    m_variants.append(ConstraintHolder::create(constraint));
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaTrackConstraintSetMap::forEach(std::function&lt;void(const MediaConstraint&amp;)&gt; callback) const
+{
+    if (m_width &amp;&amp; !m_width-&gt;isEmpty())
+        callback(*m_width);
+    if (m_height &amp;&amp; !m_height-&gt;isEmpty())
+        callback(*m_height);
+    if (m_sampleRate &amp;&amp; !m_sampleRate-&gt;isEmpty())
+        callback(*m_sampleRate);
+    if (m_sampleSize &amp;&amp; !m_sampleSize-&gt;isEmpty())
+        callback(*m_sampleSize);
+
+    if (m_aspectRatio &amp;&amp; !m_aspectRatio-&gt;isEmpty())
+        callback(*m_aspectRatio);
+    if (m_frameRate &amp;&amp; !m_frameRate-&gt;isEmpty())
+        callback(*m_frameRate);
+    if (m_volume &amp;&amp; !m_volume-&gt;isEmpty())
+        callback(*m_volume);
+
+    if (m_echoCancellation &amp;&amp; !m_echoCancellation-&gt;isEmpty())
+        callback(*m_echoCancellation);
+
+    if (m_facingMode &amp;&amp; !m_facingMode-&gt;isEmpty())
+        callback(*m_facingMode);
+    if (m_deviceId &amp;&amp; !m_deviceId-&gt;isEmpty())
+        callback(*m_deviceId);
+    if (m_groupId &amp;&amp; !m_groupId-&gt;isEmpty())
+        callback(*m_groupId);
+}
+
+void MediaTrackConstraintSetMap::filter(std::function&lt;bool(const MediaConstraint&amp;)&gt; callback) const
+{
+    if (m_width &amp;&amp; !m_width-&gt;isEmpty() &amp;&amp; callback(*m_width))
+        return;
+    if (m_height &amp;&amp; !m_height-&gt;isEmpty() &amp;&amp; callback(*m_height))
+        return;
+    if (m_sampleRate &amp;&amp; !m_sampleRate-&gt;isEmpty() &amp;&amp; callback(*m_sampleRate))
+        return;
+    if (m_sampleSize &amp;&amp; !m_sampleSize-&gt;isEmpty() &amp;&amp; callback(*m_sampleSize))
+        return;
+
+    if (m_aspectRatio &amp;&amp; !m_aspectRatio-&gt;isEmpty() &amp;&amp; callback(*m_aspectRatio))
+        return;
+    if (m_frameRate &amp;&amp; !m_frameRate-&gt;isEmpty() &amp;&amp; callback(*m_frameRate))
+        return;
+    if (m_volume &amp;&amp; !m_volume-&gt;isEmpty() &amp;&amp; callback(*m_volume))
+        return;
+
+    if (m_echoCancellation &amp;&amp; !m_echoCancellation-&gt;isEmpty() &amp;&amp; callback(*m_echoCancellation))
+        return;
+
+    if (m_facingMode &amp;&amp; !m_facingMode-&gt;isEmpty() &amp;&amp; callback(*m_facingMode))
+        return;
+    if (m_deviceId &amp;&amp; !m_deviceId-&gt;isEmpty() &amp;&amp; callback(*m_deviceId))
+        return;
+    if (m_groupId &amp;&amp; !m_groupId-&gt;isEmpty() &amp;&amp; callback(*m_groupId))
+        return;
+}
+
+bool MediaTrackConstraintSetMap::isEmpty() const
+{
+    return (!m_width || m_width-&gt;isEmpty())
+        &amp;&amp; (!m_height || m_height-&gt;isEmpty())
+        &amp;&amp; (!m_sampleRate || m_sampleRate-&gt;isEmpty())
+        &amp;&amp; (!m_sampleSize || m_sampleSize-&gt;isEmpty())
+        &amp;&amp; (!m_aspectRatio || m_aspectRatio-&gt;isEmpty())
+        &amp;&amp; (!m_frameRate || m_frameRate-&gt;isEmpty())
+        &amp;&amp; (!m_volume || m_volume-&gt;isEmpty())
+        &amp;&amp; (!m_echoCancellation || m_echoCancellation-&gt;isEmpty())
+        &amp;&amp; (!m_facingMode || m_facingMode-&gt;isEmpty())
+        &amp;&amp; (!m_deviceId || m_deviceId-&gt;isEmpty())
+        &amp;&amp; (!m_groupId || m_groupId-&gt;isEmpty());
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional&lt;IntConstraint&gt;&amp;&amp; constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::Width:
+        m_width = WTFMove(constraint);
+        break;
+    case MediaConstraintType::Height:
+        m_height = WTFMove(constraint);
+        break;
+    case MediaConstraintType::SampleRate:
+        m_sampleRate = WTFMove(constraint);
+        break;
+    case MediaConstraintType::SampleSize:
+        m_sampleSize = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::AspectRatio:
+    case MediaConstraintType::FrameRate:
+    case MediaConstraintType::Volume:
+    case MediaConstraintType::EchoCancellation:
+    case MediaConstraintType::FacingMode:
+    case MediaConstraintType::DeviceId:
+    case MediaConstraintType::GroupId:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional&lt;DoubleConstraint&gt;&amp;&amp; constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::AspectRatio:
+        m_aspectRatio = WTFMove(constraint);
+        break;
+    case MediaConstraintType::FrameRate:
+        m_frameRate = WTFMove(constraint);
+        break;
+    case MediaConstraintType::Volume:
+        m_volume = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::Width:
+    case MediaConstraintType::Height:
+    case MediaConstraintType::SampleRate:
+    case MediaConstraintType::SampleSize:
+    case MediaConstraintType::EchoCancellation:
+    case MediaConstraintType::FacingMode:
+    case MediaConstraintType::DeviceId:
+    case MediaConstraintType::GroupId:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional&lt;BooleanConstraint&gt;&amp;&amp; constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::EchoCancellation:
+        m_echoCancellation = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::Width:
+    case MediaConstraintType::Height:
+    case MediaConstraintType::SampleRate:
+    case MediaConstraintType::SampleSize:
+    case MediaConstraintType::AspectRatio:
+    case MediaConstraintType::FrameRate:
+    case MediaConstraintType::Volume:
+    case MediaConstraintType::FacingMode:
+    case MediaConstraintType::DeviceId:
+    case MediaConstraintType::GroupId:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+void MediaTrackConstraintSetMap::set(MediaConstraintType constraintType, Optional&lt;StringConstraint&gt;&amp;&amp; constraint)
+{
+    switch (constraintType) {
+    case MediaConstraintType::FacingMode:
+        m_facingMode = WTFMove(constraint);
+        break;
+    case MediaConstraintType::DeviceId:
+        m_deviceId = WTFMove(constraint);
+        break;
+    case MediaConstraintType::GroupId:
+        m_groupId = WTFMove(constraint);
+        break;
+
+    case MediaConstraintType::Width:
+    case MediaConstraintType::Height:
+    case MediaConstraintType::SampleRate:
+    case MediaConstraintType::SampleSize:
+    case MediaConstraintType::AspectRatio:
+    case MediaConstraintType::FrameRate:
+    case MediaConstraintType::Volume:
+    case MediaConstraintType::EchoCancellation:
+    case MediaConstraintType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+}
+
</ins><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamMediaConstraintsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/MediaConstraints.h (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/MediaConstraints.h        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/MediaConstraints.h        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -38,83 +38,56 @@
</span><span class="cx"> #include &lt;cstdlib&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><ins>+#include &lt;wtf/Variant.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/StringHash.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>-class MediaConstraint : public RefCounted&lt;MediaConstraint&gt; {
</del><ins>+class MediaConstraint {
</ins><span class="cx"> public:
</span><del>-    static Ref&lt;MediaConstraint&gt; create(const String&amp;);
</del><ins>+    enum class DataType { None, Integer, Double, Boolean, String };
</ins><span class="cx"> 
</span><del>-    enum class ConstraintType { ExactConstraint, IdealConstraint, MinConstraint, MaxConstraint };
-
</del><span class="cx">     virtual ~MediaConstraint() { };
</span><span class="cx"> 
</span><del>-    virtual Ref&lt;MediaConstraint&gt; copy() const;
-    virtual bool isEmpty() const = 0;
-    virtual bool isMandatory() const = 0;
</del><ins>+    virtual bool isEmpty() const { return true; }
+    virtual bool isMandatory() const { return false; }
+    virtual void merge(const MediaConstraint&amp;) { }
</ins><span class="cx"> 
</span><del>-    virtual bool getMin(int&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(int&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(int&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(int&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool validForRange(int, int) const { ASSERT_NOT_REACHED(); return false; }
-    virtual int find(std::function&lt;bool(ConstraintType, int)&gt;) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual double fitnessDistance(int, int) const { ASSERT_NOT_REACHED(); return 0; }
</del><ins>+    bool isInt() const { return m_dataType == DataType::Integer; }
+    bool isDouble() const { return m_dataType == DataType::Double; }
+    bool isBoolean() const { return m_dataType == DataType::Boolean; }
+    bool isString() const { return m_dataType == DataType::String; }
</ins><span class="cx"> 
</span><del>-    virtual bool getMin(double&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(double&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(double&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(double&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool validForRange(double, double) const { ASSERT_NOT_REACHED(); return false; }
-    virtual double find(std::function&lt;bool(ConstraintType, double)&gt;) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual double fitnessDistance(double, double) const { ASSERT_NOT_REACHED(); return 0; }
-
-    virtual bool getMin(bool&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(bool&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(bool&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(bool&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual double fitnessDistance(bool) const { ASSERT_NOT_REACHED(); return 0; }
-
-    virtual bool getMin(Vector&lt;String&gt;&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getMax(Vector&lt;String&gt;&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getExact(Vector&lt;String&gt;&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getIdeal(Vector&lt;String&gt;&amp;) const { ASSERT_NOT_REACHED(); return false; }
-    virtual const String&amp; find(std::function&lt;bool(ConstraintType, const String&amp;)&gt;) const { ASSERT_NOT_REACHED(); return emptyString(); }
-
-    virtual double fitnessDistance(const String&amp;) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual double fitnessDistance(const Vector&lt;String&gt;&amp;) const { ASSERT_NOT_REACHED(); return 0; }
-
-    virtual void merge(const MediaConstraint&amp;) { ASSERT_NOT_REACHED(); }
-
-    MediaConstraintType type() const { return m_type; }
</del><ins>+    DataType dataType() const { return m_dataType; }
+    MediaConstraintType constraintType() const { return m_constraintType; }
</ins><span class="cx">     const String&amp; name() const { return m_name; }
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><del>-    explicit MediaConstraint(const String&amp; name, MediaConstraintType type)
</del><ins>+    explicit MediaConstraint(const AtomicString&amp; name, MediaConstraintType constraintType, DataType dataType)
</ins><span class="cx">         : m_name(name)
</span><del>-        , m_type(type)
</del><ins>+        , m_constraintType(constraintType)
+        , m_dataType(dataType)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> private:
</span><del>-    String m_name;
-    MediaConstraintType m_type;
</del><ins>+    AtomicString m_name;
+    MediaConstraintType m_constraintType;
+    DataType m_dataType;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;class ValueType&gt;
</span><span class="cx"> class NumericConstraint : public MediaConstraint {
</span><span class="cx"> public:
</span><del>-    bool isEmpty() const override { return !m_min &amp;&amp; !m_max &amp;&amp; !m_exact &amp;&amp; !m_ideal; }
-    bool isMandatory() const override { return m_min || m_max || m_exact; }
-
</del><span class="cx">     void setMin(ValueType value) { m_min = value; }
</span><span class="cx">     void setMax(ValueType value) { m_max = value; }
</span><span class="cx">     void setExact(ValueType value) { m_exact = value; }
</span><span class="cx">     void setIdeal(ValueType value) { m_ideal = value; }
</span><span class="cx"> 
</span><del>-    bool getMin(ValueType&amp; min) const final {
</del><ins>+    bool getMin(ValueType&amp; min) const
+    {
</ins><span class="cx">         if (!m_min)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -122,7 +95,8 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool getMax(ValueType&amp; max) const final {
</del><ins>+    bool getMax(ValueType&amp; max) const
+    {
</ins><span class="cx">         if (!m_max)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -130,7 +104,8 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool getExact(ValueType&amp; exact) const final {
</del><ins>+    bool getExact(ValueType&amp; exact) const
+    {
</ins><span class="cx">         if (!m_exact)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -138,7 +113,8 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool getIdeal(ValueType&amp; ideal) const final {
</del><ins>+    bool getIdeal(ValueType&amp; ideal) const
+    {
</ins><span class="cx">         if (!m_ideal)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -154,7 +130,8 @@
</span><span class="cx">         return std::abs(a - b) &lt;= epsilon;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    double fitnessDistance(ValueType rangeMin, ValueType rangeMax) const final {
</del><ins>+    double fitnessDistance(ValueType rangeMin, ValueType rangeMax) const
+    {
</ins><span class="cx">         // https://w3c.github.io/mediacapture-main/#dfn-applyconstraints
</span><span class="cx">         // 1. If the constraint is not supported by the browser, the fitness distance is 0.
</span><span class="cx">         if (isEmpty())
</span><span class="lines">@@ -189,32 +166,8 @@
</span><span class="cx">         return static_cast&lt;double&gt;(std::abs(ideal - m_ideal.value())) / std::max(std::abs(ideal), std::abs(m_ideal.value()));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void merge(const MediaConstraint&amp; other) final {
-        if (other.isEmpty())
-            return;
-
-        ValueType value;
-        if (other.getExact(value))
-            m_exact = value;
-
-        if (other.getMin(value))
-            m_min = value;
-
-        if (other.getMax(value))
-            m_max = value;
-
-        // https://w3c.github.io/mediacapture-main/#constrainable-interface
-        // When processing advanced constraints:
-        //   ... the User Agent must attempt to apply, individually, any 'ideal' constraints or
-        //   a constraint given as a bare value for the property. Of these properties, it must
-        //   satisfy the largest number that it can, in any order.
-        if (other.getIdeal(value)) {
-            if (!m_ideal || value &gt; m_ideal.value())
-                m_ideal = value;
-        }
-    }
-
-    bool validForRange(ValueType rangeMin, ValueType rangeMax) const final {
</del><ins>+    bool validForRange(ValueType rangeMin, ValueType rangeMax) const
+    {
</ins><span class="cx">         if (isEmpty())
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -242,29 +195,58 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ValueType find(std::function&lt;bool(ConstraintType, ValueType)&gt; function) const final {
-        if (m_min &amp;&amp; function(ConstraintType::MinConstraint, m_min.value()))
</del><ins>+    ValueType find(std::function&lt;bool(ValueType)&gt; function) const
+    {
+        if (m_min &amp;&amp; function(m_min.value()))
</ins><span class="cx">             return m_min.value();
</span><span class="cx"> 
</span><del>-        if (m_max &amp;&amp; function(ConstraintType::MaxConstraint, m_max.value()))
</del><ins>+        if (m_max &amp;&amp; function(m_max.value()))
</ins><span class="cx">             return m_max.value();
</span><span class="cx"> 
</span><del>-        if (m_exact &amp;&amp; function(ConstraintType::ExactConstraint, m_exact.value()))
</del><ins>+        if (m_exact &amp;&amp; function(m_exact.value()))
</ins><span class="cx">             return m_exact.value();
</span><span class="cx"> 
</span><del>-        if (m_ideal &amp;&amp; function(ConstraintType::IdealConstraint, m_ideal.value()))
</del><ins>+        if (m_ideal &amp;&amp; function(m_ideal.value()))
</ins><span class="cx">             return m_ideal.value();
</span><span class="cx"> 
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><del>-    
</del><span class="cx"> 
</span><ins>+    bool isEmpty() const override { return !m_min &amp;&amp; !m_max &amp;&amp; !m_exact &amp;&amp; !m_ideal; }
+    bool isMandatory() const override { return m_min || m_max || m_exact; }
+
</ins><span class="cx"> protected:
</span><del>-    explicit NumericConstraint(const String&amp; name, MediaConstraintType type)
-        : MediaConstraint(name, type)
</del><ins>+    explicit NumericConstraint(const AtomicString&amp; name, MediaConstraintType type, DataType dataType)
+        : MediaConstraint(name, type, dataType)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void innerMerge(const NumericConstraint&amp; other)
+    {
+        if (other.isEmpty())
+            return;
+
+        ValueType value;
+        if (other.getExact(value))
+            m_exact = value;
+
+        if (other.getMin(value))
+            m_min = value;
+
+        if (other.getMax(value))
+            m_max = value;
+
+        // https://w3c.github.io/mediacapture-main/#constrainable-interface
+        // When processing advanced constraints:
+        //   ... the User Agent must attempt to apply, individually, any 'ideal' constraints or
+        //   a constraint given as a bare value for the property. Of these properties, it must
+        //   satisfy the largest number that it can, in any order.
+        if (other.getIdeal(value)) {
+            if (!m_ideal || value &gt; m_ideal.value())
+                m_ideal = value;
+        }
+    }
+
</ins><span class="cx">     Optional&lt;ValueType&gt; m_min;
</span><span class="cx">     Optional&lt;ValueType&gt; m_max;
</span><span class="cx">     Optional&lt;ValueType&gt; m_exact;
</span><span class="lines">@@ -273,46 +255,45 @@
</span><span class="cx"> 
</span><span class="cx"> class IntConstraint final : public NumericConstraint&lt;int&gt; {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;IntConstraint&gt; create(const String&amp; name, MediaConstraintType type) { return adoptRef(*new IntConstraint(name, type)); }
-
-    Ref&lt;MediaConstraint&gt; copy() const final;
-
-private:
-    explicit IntConstraint(const String&amp; name, MediaConstraintType type)
-        : NumericConstraint&lt;int&gt;(name, type)
</del><ins>+    explicit IntConstraint(const AtomicString&amp; name, MediaConstraintType type)
+        : NumericConstraint&lt;int&gt;(name, type, DataType::Integer)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><ins>+
+    void merge(const MediaConstraint&amp; other) final {
+        ASSERT(other.isInt());
+        NumericConstraint::innerMerge(downcast&lt;const IntConstraint&gt;(other));
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class DoubleConstraint final : public NumericConstraint&lt;double&gt; {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;DoubleConstraint&gt; create(const String&amp; name, MediaConstraintType type) { return adoptRef(*new DoubleConstraint(name, type)); }
-
-    Ref&lt;MediaConstraint&gt; copy() const final;
-
-private:
-    explicit DoubleConstraint(const String&amp; name, MediaConstraintType type)
-        : NumericConstraint&lt;double&gt;(name, type)
</del><ins>+    explicit DoubleConstraint(const AtomicString&amp; name, MediaConstraintType type)
+        : NumericConstraint&lt;double&gt;(name, type, DataType::Double)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><ins>+
+    void merge(const MediaConstraint&amp; other) final {
+        ASSERT(other.isDouble());
+        NumericConstraint::innerMerge(downcast&lt;DoubleConstraint&gt;(other));
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class BooleanConstraint final : public MediaConstraint {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;BooleanConstraint&gt; create(const String&amp; name, MediaConstraintType type) { return adoptRef(*new BooleanConstraint(name, type)); }
</del><ins>+    explicit BooleanConstraint(const AtomicString&amp; name, MediaConstraintType type)
+        : MediaConstraint(name, type, DataType::Boolean)
+    {
+    }
</ins><span class="cx"> 
</span><del>-    Ref&lt;MediaConstraint&gt; copy() const final;
-
</del><span class="cx">     void setExact(bool value) { m_exact = value; }
</span><span class="cx">     void setIdeal(bool value) { m_ideal = value; }
</span><span class="cx"> 
</span><del>-    bool getExact(bool&amp;) const final;
-    bool getIdeal(bool&amp;) const final;
</del><ins>+    bool getExact(bool&amp;) const;
+    bool getIdeal(bool&amp;) const;
</ins><span class="cx"> 
</span><del>-    bool isEmpty() const final { return !m_exact &amp;&amp; !m_ideal; };
-    bool isMandatory() const final { return bool(m_exact); }
-
-    double fitnessDistance(bool value) const final {
</del><ins>+    double fitnessDistance(bool value) const
+    {
</ins><span class="cx">         // https://w3c.github.io/mediacapture-main/#dfn-applyconstraints
</span><span class="cx">         // 1. If the constraint is not supported by the browser, the fitness distance is 0.
</span><span class="cx">         if (isEmpty())
</span><span class="lines">@@ -335,25 +316,26 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void merge(const MediaConstraint&amp; other) final {
</span><del>-        if (other.isEmpty())
</del><ins>+        ASSERT(other.isBoolean());
+        const BooleanConstraint&amp; typedOther = downcast&lt;BooleanConstraint&gt;(other);
+
+        if (typedOther.isEmpty())
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         bool value;
</span><del>-        if (other.getExact(value))
</del><ins>+        if (typedOther.getExact(value))
</ins><span class="cx">             m_exact = value;
</span><span class="cx"> 
</span><del>-        if (other.getIdeal(value)) {
</del><ins>+        if (typedOther.getIdeal(value)) {
</ins><span class="cx">             if (!m_ideal || (value &amp;&amp; !m_ideal.value()))
</span><span class="cx">                 m_ideal = value;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool isEmpty() const final { return !m_exact &amp;&amp; !m_ideal; };
+    bool isMandatory() const final { return bool(m_exact); }
+
</ins><span class="cx"> private:
</span><del>-    explicit BooleanConstraint(const String&amp; name, MediaConstraintType type)
-        : MediaConstraint(name, type)
-    {
-    }
-
</del><span class="cx">     Optional&lt;bool&gt; m_exact;
</span><span class="cx">     Optional&lt;bool&gt; m_ideal;
</span><span class="cx"> };
</span><span class="lines">@@ -360,33 +342,29 @@
</span><span class="cx"> 
</span><span class="cx"> class StringConstraint final : public MediaConstraint {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;StringConstraint&gt; create(const String&amp; name, MediaConstraintType type) { return adoptRef(*new StringConstraint(name, type)); }
</del><ins>+    explicit StringConstraint(const AtomicString&amp; name, MediaConstraintType type)
+        : MediaConstraint(name, type, DataType::String)
+    {
+    }
</ins><span class="cx"> 
</span><del>-    Ref&lt;MediaConstraint&gt; copy() const final;
-
</del><span class="cx">     void setExact(const String&amp;);
</span><span class="cx">     void appendExact(const String&amp;);
</span><span class="cx">     void setIdeal(const String&amp;);
</span><span class="cx">     void appendIdeal(const String&amp;);
</span><span class="cx"> 
</span><del>-    bool getExact(Vector&lt;String&gt;&amp;) const final;
-    bool getIdeal(Vector&lt;String&gt;&amp;) const final;
</del><ins>+    bool getExact(Vector&lt;String&gt;&amp;) const;
+    bool getIdeal(Vector&lt;String&gt;&amp;) const;
</ins><span class="cx"> 
</span><ins>+    double fitnessDistance(const String&amp;) const;
+    double fitnessDistance(const Vector&lt;String&gt;&amp;) const;
+
+    const String&amp; find(std::function&lt;bool(const String&amp;)&gt;) const;
+    void merge(const MediaConstraint&amp;) final;
+
</ins><span class="cx">     bool isEmpty() const final { return m_exact.isEmpty() &amp;&amp; m_ideal.isEmpty(); }
</span><span class="cx">     bool isMandatory() const final { return !m_exact.isEmpty(); }
</span><span class="cx"> 
</span><del>-    double fitnessDistance(const String&amp;) const final;
-    double fitnessDistance(const Vector&lt;String&gt;&amp;) const final;
-
-    const String&amp; find(std::function&lt;bool(ConstraintType, const String&amp;)&gt;) const final;
-    void merge(const MediaConstraint&amp;) final;
-
</del><span class="cx"> private:
</span><del>-    explicit StringConstraint(const String&amp; name, MediaConstraintType type)
-        : MediaConstraint(name, type)
-    {
-    }
-
</del><span class="cx">     Vector&lt;String&gt; m_exact;
</span><span class="cx">     Vector&lt;String&gt; m_ideal;
</span><span class="cx"> };
</span><span class="lines">@@ -393,34 +371,161 @@
</span><span class="cx"> 
</span><span class="cx"> class UnknownConstraint final : public MediaConstraint {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;UnknownConstraint&gt; create(const String&amp; name, MediaConstraintType type) { return adoptRef(*new UnknownConstraint(name, type)); }
</del><ins>+    explicit UnknownConstraint(const AtomicString&amp; name, MediaConstraintType type)
+        : MediaConstraint(name, type, DataType::None)
+    {
+    }
</ins><span class="cx"> 
</span><ins>+private:
</ins><span class="cx">     bool isEmpty() const final { return true; }
</span><span class="cx">     bool isMandatory() const final { return false; }
</span><ins>+    void merge(const MediaConstraint&amp;) final { }
+};
</ins><span class="cx"> 
</span><ins>+class MediaTrackConstraintSetMap {
+public:
+    void forEach(std::function&lt;void(const MediaConstraint&amp;)&gt;) const;
+    void filter(std::function&lt;bool(const MediaConstraint&amp;)&gt;) const;
+    bool isEmpty() const;
+
+    void set(MediaConstraintType, Optional&lt;IntConstraint&gt;&amp;&amp;);
+    void set(MediaConstraintType, Optional&lt;DoubleConstraint&gt;&amp;&amp;);
+    void set(MediaConstraintType, Optional&lt;BooleanConstraint&gt;&amp;&amp;);
+    void set(MediaConstraintType, Optional&lt;StringConstraint&gt;&amp;&amp;);
+
</ins><span class="cx"> private:
</span><del>-    explicit UnknownConstraint(const String&amp; name, MediaConstraintType type)
-        : MediaConstraint(name, type)
-    {
-    }
</del><ins>+    Optional&lt;IntConstraint&gt; m_width;
+    Optional&lt;IntConstraint&gt; m_height;
+    Optional&lt;IntConstraint&gt; m_sampleRate;
+    Optional&lt;IntConstraint&gt; m_sampleSize;
+
+    Optional&lt;DoubleConstraint&gt; m_aspectRatio;
+    Optional&lt;DoubleConstraint&gt; m_frameRate;
+    Optional&lt;DoubleConstraint&gt; m_volume;
+
+    Optional&lt;BooleanConstraint&gt; m_echoCancellation;
+
+    Optional&lt;StringConstraint&gt; m_facingMode;
+    Optional&lt;StringConstraint&gt; m_deviceId;
+    Optional&lt;StringConstraint&gt; m_groupId;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-using MediaTrackConstraintSetMap = HashMap&lt;String, RefPtr&lt;MediaConstraint&gt;&gt;;
-
</del><span class="cx"> class FlattenedConstraint {
</span><span class="cx"> public:
</span><del>-    typedef Vector&lt;RefPtr&lt;MediaConstraint&gt;&gt;::const_iterator const_iterator;
</del><span class="cx"> 
</span><span class="cx">     void set(const MediaConstraint&amp;);
</span><span class="cx">     void merge(const MediaConstraint&amp;);
</span><del>-    bool isEmpty() const { return m_constraints.isEmpty(); }
</del><ins>+    void append(const MediaConstraint&amp;);
+    bool isEmpty() const { return m_variants.isEmpty(); }
</ins><span class="cx"> 
</span><del>-    const_iterator begin() const { return m_constraints.begin(); }
-    const_iterator end() const { return m_constraints.end(); }
</del><ins>+    class iterator {
+    public:
+        iterator(const FlattenedConstraint* constraint, size_t index)
+            : m_constraint(constraint)
+            , m_index(index)
+#ifndef NDEBUG
+            , m_generation(constraint-&gt;m_generation)
+#endif
+        {
+        }
</ins><span class="cx"> 
</span><ins>+        MediaConstraint&amp; operator*() const
+        {
+            return m_constraint-&gt;m_variants.at(m_index).constraint();
+        }
+
+        iterator&amp; operator++()
+        {
+#ifndef NDEBUG
+            ASSERT(m_generation == m_constraint-&gt;m_generation);
+#endif
+            m_index++;
+            return *this;
+        }
+
+        bool operator==(const iterator&amp; other) const { return m_index == other.m_index; }
+        bool operator!=(const iterator&amp; other) const { return !(*this == other); }
+
+    private:
+        const FlattenedConstraint* m_constraint { nullptr };
+        size_t m_index { 0 };
+#ifndef NDEBUG
+        int m_generation { 0 };
+#endif
+    };
+
+    const iterator begin() const { return iterator(this, 0); }
+    const iterator end() const { return iterator(this, m_variants.size()); }
+
</ins><span class="cx"> private:
</span><ins>+    class ConstraintHolder {
+    public:
+        static ConstraintHolder&amp; create(const MediaConstraint&amp; value) { return *new ConstraintHolder(value); }
</ins><span class="cx"> 
</span><del>-    Vector&lt;RefPtr&lt;MediaConstraint&gt;&gt; m_constraints;
</del><ins>+        ~ConstraintHolder()
+        {
+            switch (dataType()) {
+            case MediaConstraint::DataType::Integer:
+                delete m_value.asInteger;
+                break;
+            case MediaConstraint::DataType::Double:
+                delete m_value.asDouble;
+                break;
+            case MediaConstraint::DataType::Boolean:
+                delete m_value.asBoolean;
+                break;
+            case MediaConstraint::DataType::String:
+                delete m_value.asString;
+                break;
+            case MediaConstraint::DataType::None:
+                ASSERT_NOT_REACHED();
+                break;
+            }
+
+#ifndef NDEBUG
+            m_value.asRaw = reinterpret_cast&lt;MediaConstraint*&gt;(0xbbadbeef);
+#endif
+        }
+
+        MediaConstraint&amp; constraint() const { return *m_value.asRaw; }
+        MediaConstraint::DataType dataType() const { return constraint().dataType(); }
+        MediaConstraintType constraintType() const { return constraint().constraintType(); }
+
+    private:
+        explicit ConstraintHolder(const MediaConstraint&amp; value)
+        {
+            switch (value.dataType()) {
+            case MediaConstraint::DataType::Integer:
+                m_value.asInteger = new IntConstraint(downcast&lt;const IntConstraint&gt;(value));
+                break;
+            case MediaConstraint::DataType::Double:
+                m_value.asDouble = new DoubleConstraint(downcast&lt;DoubleConstraint&gt;(value));
+                break;
+            case MediaConstraint::DataType::Boolean:
+                m_value.asBoolean = new BooleanConstraint(downcast&lt;BooleanConstraint&gt;(value));
+                break;
+            case MediaConstraint::DataType::String:
+                m_value.asString = new StringConstraint(downcast&lt;StringConstraint&gt;(value));
+                break;
+            case MediaConstraint::DataType::None:
+                ASSERT_NOT_REACHED();
+                break;
+            }
+        }
+        
+        union {
+            MediaConstraint* asRaw;
+            IntConstraint* asInteger;
+            DoubleConstraint* asDouble;
+            BooleanConstraint* asBoolean;
+            StringConstraint* asString;
+        } m_value;
+    };
+
+    Vector&lt;ConstraintHolder&gt; m_variants;
+#ifndef NDEBUG
+    int m_generation { 0 };
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class MediaConstraints : public RefCounted&lt;MediaConstraints&gt; {
</span><span class="lines">@@ -437,6 +542,16 @@
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><ins>+#define SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(ConstraintType, predicate) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ConstraintType) \
+static bool isType(const WebCore::MediaConstraint&amp; constraint) { return constraint.predicate; } \
+SPECIALIZE_TYPE_TRAITS_END()
+
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(IntConstraint, isInt())
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(DoubleConstraint, isDouble())
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(StringConstraint, isString())
+SPECIALIZE_TYPE_TRAITS_MEDIACONSTRAINT(BooleanConstraint, isBoolean())
+
</ins><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><span class="cx"> #endif // MediaConstraints_h
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -150,75 +150,84 @@
</span><span class="cx">     stop(callingObserver);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if 1
</ins><span class="cx"> double RealtimeMediaSource::fitnessDistance(const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><span class="cx">     RealtimeMediaSourceCapabilities&amp; capabilities = *this-&gt;capabilities();
</span><span class="cx"> 
</span><del>-    switch (constraint.type()) {
</del><ins>+    switch (constraint.constraintType()) {
</ins><span class="cx">     case MediaConstraintType::Width: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsWidth())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.width();
</span><del>-        return constraint.fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
</del><ins>+        return downcast&lt;IntConstraint&gt;(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::Height: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsHeight())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.height();
</span><del>-        return constraint.fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
</del><ins>+        return downcast&lt;IntConstraint&gt;(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::FrameRate: {
</span><ins>+        ASSERT(constraint.isDouble());
</ins><span class="cx">         if (!capabilities.supportsFrameRate())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.frameRate();
</span><del>-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</del><ins>+        return downcast&lt;DoubleConstraint&gt;(constraint).fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::AspectRatio: {
</span><ins>+        ASSERT(constraint.isDouble());
</ins><span class="cx">         if (!capabilities.supportsAspectRatio())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.aspectRatio();
</span><del>-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</del><ins>+        return downcast&lt;DoubleConstraint&gt;(constraint).fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::Volume: {
</span><ins>+        ASSERT(constraint.isDouble());
</ins><span class="cx">         if (!capabilities.supportsVolume())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.volume();
</span><del>-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</del><ins>+        return downcast&lt;DoubleConstraint&gt;(constraint).fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::SampleRate: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsSampleRate())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.sampleRate();
</span><del>-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</del><ins>+        return downcast&lt;IntConstraint&gt;(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::SampleSize: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsSampleSize())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.sampleSize();
</span><del>-        return constraint.fitnessDistance(range.rangeMin().asDouble, range.rangeMax().asDouble);
</del><ins>+        return downcast&lt;IntConstraint&gt;(constraint).fitnessDistance(range.rangeMin().asInt, range.rangeMax().asInt);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::FacingMode: {
</span><ins>+        ASSERT(constraint.isString());
</ins><span class="cx">         if (!capabilities.supportsFacingMode())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="lines">@@ -227,32 +236,35 @@
</span><span class="cx">         supportedModes.reserveInitialCapacity(modes.size());
</span><span class="cx">         for (auto&amp; mode : modes)
</span><span class="cx">             supportedModes.append(RealtimeMediaSourceSettings::facingMode(mode));
</span><del>-        return constraint.fitnessDistance(supportedModes);
</del><ins>+        return downcast&lt;StringConstraint&gt;(constraint).fitnessDistance(supportedModes);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::EchoCancellation: {
</span><ins>+        ASSERT(constraint.isBoolean());
</ins><span class="cx">         if (!capabilities.supportsEchoCancellation())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><span class="cx">         bool echoCancellationReadWrite = capabilities.echoCancellation() == RealtimeMediaSourceCapabilities::EchoCancellation::ReadWrite;
</span><del>-        return constraint.fitnessDistance(echoCancellationReadWrite);
</del><ins>+        return downcast&lt;BooleanConstraint&gt;(constraint).fitnessDistance(echoCancellationReadWrite);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::DeviceId: {
</span><ins>+        ASSERT(constraint.isString());
</ins><span class="cx">         if (!capabilities.supportsDeviceId())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><del>-        return constraint.fitnessDistance(m_id);
</del><ins>+        return downcast&lt;StringConstraint&gt;(constraint).fitnessDistance(m_id);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::GroupId: {
</span><ins>+        ASSERT(constraint.isString());
</ins><span class="cx">         if (!capabilities.supportsDeviceId())
</span><span class="cx">             return 0;
</span><span class="cx"> 
</span><del>-        return constraint.fitnessDistance(settings().groupId());
</del><ins>+        return downcast&lt;StringConstraint&gt;(constraint).fitnessDistance(settings().groupId());
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -263,9 +275,10 @@
</span><span class="cx"> 
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx"> template &lt;typename ValueType&gt;
</span><del>-static void applyNumericConstraint(const MediaConstraint&amp; constraint, ValueType current, ValueType capabilityMin, ValueType capabilityMax, RealtimeMediaSource* source, void (RealtimeMediaSource::*function)(ValueType))
</del><ins>+static void applyNumericConstraint(const NumericConstraint&lt;ValueType&gt;&amp; constraint, ValueType current, ValueType capabilityMin, ValueType capabilityMax, RealtimeMediaSource* source, void (RealtimeMediaSource::*applier)(ValueType))
</ins><span class="cx"> {
</span><span class="cx">     ValueType value;
</span><span class="cx">     ValueType min = capabilityMin;
</span><span class="lines">@@ -273,7 +286,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (constraint.getExact(value)) {
</span><span class="cx">         ASSERT(constraint.validForRange(capabilityMin, capabilityMax));
</span><del>-        (source-&gt;*function)(value);
</del><ins>+        (source-&gt;*applier)(value);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -302,91 +315,102 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (value != current)
</span><del>-        (source-&gt;*function)(value);
</del><ins>+        (source-&gt;*applier)(value);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RealtimeMediaSource::applyConstraint(const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><span class="cx">     RealtimeMediaSourceCapabilities&amp; capabilities = *this-&gt;capabilities();
</span><del>-    switch (constraint.type()) {
</del><ins>+    switch (constraint.constraintType()) {
</ins><span class="cx">     case MediaConstraintType::Width: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsWidth())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.width();
</span><del>-        applyNumericConstraint(constraint, size().width(), range.rangeMin().asInt, range.rangeMax().asInt, this, &amp;RealtimeMediaSource::setWidth);
</del><ins>+        applyNumericConstraint(downcast&lt;IntConstraint&gt;(constraint), size().width(), range.rangeMin().asInt, range.rangeMax().asInt, this, &amp;RealtimeMediaSource::setWidth);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::Height: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsHeight())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.height();
</span><del>-        applyNumericConstraint(constraint, size().height(), range.rangeMin().asInt, range.rangeMax().asInt, this, &amp;RealtimeMediaSource::setHeight);
</del><ins>+        applyNumericConstraint(downcast&lt;IntConstraint&gt;(constraint), size().height(), range.rangeMin().asInt, range.rangeMax().asInt, this, &amp;RealtimeMediaSource::setHeight);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::FrameRate: {
</span><ins>+        ASSERT(constraint.isDouble());
</ins><span class="cx">         if (!capabilities.supportsFrameRate())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.frameRate();
</span><del>-        applyNumericConstraint(constraint, frameRate(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setFrameRate);
</del><ins>+        applyNumericConstraint(downcast&lt;DoubleConstraint&gt;(constraint), frameRate(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setFrameRate);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::AspectRatio: {
</span><ins>+        ASSERT(constraint.isDouble());
</ins><span class="cx">         if (!capabilities.supportsAspectRatio())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.aspectRatio();
</span><del>-        applyNumericConstraint(constraint, aspectRatio(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setAspectRatio);
</del><ins>+        applyNumericConstraint(downcast&lt;DoubleConstraint&gt;(constraint), aspectRatio(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setAspectRatio);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::Volume: {
</span><ins>+        ASSERT(constraint.isDouble());
</ins><span class="cx">         if (!capabilities.supportsVolume())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.volume();
</span><del>-        applyNumericConstraint(constraint, volume(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setVolume);
</del><ins>+        applyNumericConstraint(downcast&lt;DoubleConstraint&gt;(constraint), volume(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setVolume);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::SampleRate: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsSampleRate())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.sampleRate();
</span><del>-        applyNumericConstraint(constraint, sampleRate(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setSampleRate);
</del><ins>+        applyNumericConstraint(downcast&lt;IntConstraint&gt;(constraint), sampleRate(), range.rangeMin().asInt, range.rangeMax().asInt, this, &amp;RealtimeMediaSource::setSampleRate);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::SampleSize: {
</span><ins>+        ASSERT(constraint.isInt());
</ins><span class="cx">         if (!capabilities.supportsSampleSize())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto range = capabilities.sampleSize();
</span><del>-        applyNumericConstraint(constraint, sampleSize(), range.rangeMin().asDouble, range.rangeMax().asDouble, this, &amp;RealtimeMediaSource::setSampleSize);
</del><ins>+        applyNumericConstraint(downcast&lt;IntConstraint&gt;(constraint), sampleSize(), range.rangeMin().asInt, range.rangeMax().asInt, this, &amp;RealtimeMediaSource::setSampleSize);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case MediaConstraintType::EchoCancellation:
</del><ins>+    case MediaConstraintType::EchoCancellation: {
+        ASSERT(constraint.isBoolean());
</ins><span class="cx">         if (!capabilities.supportsEchoCancellation())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         bool setting;
</span><del>-        if (constraint.getExact(setting) || constraint.getIdeal(setting))
</del><ins>+        const BooleanConstraint&amp; boolConstraint = downcast&lt;BooleanConstraint&gt;(constraint);
+        if (boolConstraint.getExact(setting) || boolConstraint.getIdeal(setting))
</ins><span class="cx">             setEchoCancellation(setting);
</span><span class="cx">         break;
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::FacingMode: {
</span><ins>+        ASSERT(constraint.isString());
</ins><span class="cx">         if (!capabilities.supportsFacingMode())
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         auto&amp; supportedModes = capabilities.facingMode();
</span><del>-        std::function&lt;bool(MediaConstraint::ConstraintType, const String&amp;)&gt; filter = [supportedModes](MediaConstraint::ConstraintType, const String&amp; modeString) {
</del><ins>+        auto filter = [supportedModes](const String&amp; modeString) {
</ins><span class="cx">             auto mode = RealtimeMediaSourceSettings::videoFacingModeEnum(modeString);
</span><span class="cx">             for (auto&amp; supportedMode : supportedModes) {
</span><span class="cx">                 if (mode == supportedMode)
</span><span class="lines">@@ -395,7 +419,7 @@
</span><span class="cx">             return false;
</span><span class="cx">         };
</span><span class="cx"> 
</span><del>-        auto modeString = constraint.find(filter);
</del><ins>+        auto modeString = downcast&lt;StringConstraint&gt;(constraint).find(filter);
</ins><span class="cx">         if (!modeString.isEmpty())
</span><span class="cx">             setFacingMode(RealtimeMediaSourceSettings::videoFacingModeEnum(modeString));
</span><span class="cx">         break;
</span><span class="lines">@@ -403,6 +427,7 @@
</span><span class="cx"> 
</span><span class="cx">     case MediaConstraintType::DeviceId:
</span><span class="cx">     case MediaConstraintType::GroupId:
</span><ins>+        ASSERT(constraint.isString());
</ins><span class="cx">         // There is nothing to do here, neither can be changed.
</span><span class="cx">         break;
</span><span class="cx"> 
</span><span class="lines">@@ -431,17 +456,21 @@
</span><span class="cx">     // 3. For every possible settings dictionary of copy compute its fitness distance, treating bare values of
</span><span class="cx">     //    properties as ideal values. Let candidates be the set of settings dictionaries for which the fitness
</span><span class="cx">     //    distance is finite.
</span><del>-    auto&amp; mandatoryConstraints = constraints.mandatoryConstraints();
-    for (auto&amp; nameConstraintPair : mandatoryConstraints) {
-        const auto&amp; constraint = nameConstraintPair.value;
-        if (fitnessDistance(*constraint) == std::numeric_limits&lt;double&gt;::infinity()) {
-            failedConstraint = constraint-&gt;name();
-            return false;
</del><ins>+
+    failedConstraint = emptyString();
+    constraints.mandatoryConstraints().filter([&amp;](const MediaConstraint&amp; constraint) {
+        if (fitnessDistance(constraint) == std::numeric_limits&lt;double&gt;::infinity()) {
+            failedConstraint = constraint.name();
+            return true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        candidates.set(*constraint);
-    }
</del><ins>+        candidates.set(constraint);
+        return false;
+    });
</ins><span class="cx"> 
</span><ins>+    if (!failedConstraint.isEmpty())
+        return false;
+
</ins><span class="cx">     // 4. If candidates is empty, return undefined as the result of the SelectSettings() algorithm.
</span><span class="cx">     if (candidates.isEmpty())
</span><span class="cx">         return true;
</span><span class="lines">@@ -453,15 +482,17 @@
</span><span class="cx">     //     values of properties as exact.
</span><span class="cx">     Vector&lt;std::pair&lt;double, MediaTrackConstraintSetMap&gt;&gt; supportedConstraints;
</span><span class="cx">     double minimumDistance = std::numeric_limits&lt;double&gt;::infinity();
</span><ins>+
</ins><span class="cx">     for (const auto&amp; advancedConstraint : constraints.advancedConstraints()) {
</span><span class="cx">         double constraintDistance = 0;
</span><span class="cx">         bool supported = false;
</span><del>-        for (auto&amp; nameConstraintPair : advancedConstraint) {
-            double distance = fitnessDistance(*nameConstraintPair.value);
</del><ins>+
+        advancedConstraint.forEach([&amp;](const MediaConstraint&amp; constraint) {
+            double distance = fitnessDistance(constraint);
</ins><span class="cx">             constraintDistance += distance;
</span><span class="cx">             if (distance != std::numeric_limits&lt;double&gt;::infinity())
</span><span class="cx">                 supported = true;
</span><del>-        }
</del><ins>+        });
</ins><span class="cx"> 
</span><span class="cx">         if (constraintDistance &lt; minimumDistance)
</span><span class="cx">             minimumDistance = constraintDistance;
</span><span class="lines">@@ -476,14 +507,15 @@
</span><span class="cx">     // 6. Select one settings dictionary from candidates, and return it as the result of the SelectSettings() algorithm.
</span><span class="cx">     //    The UA should use the one with the smallest fitness distance, as calculated in step 3.
</span><span class="cx">     if (minimumDistance != std::numeric_limits&lt;double&gt;::infinity()) {
</span><del>-        supportedConstraints.removeAllMatching( [&amp;] (std::pair&lt;double, MediaTrackConstraintSetMap&gt; pair) -&gt; bool {
</del><ins>+        supportedConstraints.removeAllMatching([&amp;](std::pair&lt;double, MediaTrackConstraintSetMap&gt; pair) -&gt; bool {
</ins><span class="cx">             return pair.first &gt; minimumDistance;
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         if (!supportedConstraints.isEmpty()) {
</span><span class="cx">             auto&amp; advancedConstraint = supportedConstraints[0].second;
</span><del>-            for (auto&amp; nameConstraintPair : advancedConstraint)
-                candidates.merge(*nameConstraintPair.value);
</del><ins>+            advancedConstraint.forEach([&amp;](const MediaConstraint&amp; constraint) {
+                candidates.merge(constraint);
+            });
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -490,13 +522,11 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> void RealtimeMediaSource::applyConstraints(const MediaConstraints&amp; constraints, SuccessHandler successHandler, FailureHandler failureHandler)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(constraints.isValid());
</span><span class="cx"> 
</span><span class="cx">     FlattenedConstraint candidates;
</span><del>-
</del><span class="cx">     String failedConstraint;
</span><span class="cx">     if (!selectSettings(constraints, candidates, failedConstraint)) {
</span><span class="cx">         failureHandler(failedConstraint, &quot;Constraint not supported&quot;);
</span><span class="lines">@@ -503,8 +533,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    for (auto constraint : candidates)
-        applyConstraint(*constraint);
</del><ins>+    for (auto&amp; variant : candidates)
+        applyConstraint(variant);
</ins><span class="cx"> 
</span><span class="cx">     successHandler();
</span><span class="cx"> }
</span><span class="lines">@@ -578,7 +608,7 @@
</span><span class="cx">     settingsDidChange();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RealtimeMediaSource::setSampleRate(double rate)
</del><ins>+void RealtimeMediaSource::setSampleRate(int rate)
</ins><span class="cx"> {
</span><span class="cx">     if (m_sampleRate == rate || !applySampleRate(rate))
</span><span class="cx">         return;
</span><span class="lines">@@ -587,7 +617,7 @@
</span><span class="cx">     settingsDidChange();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RealtimeMediaSource::setSampleSize(double size)
</del><ins>+void RealtimeMediaSource::setSampleSize(int size)
</ins><span class="cx"> {
</span><span class="cx">     if (m_sampleSize == size || !applySampleSize(size))
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -148,13 +148,13 @@
</span><span class="cx">     void setVolume(double);
</span><span class="cx">     virtual bool applyVolume(double) { return false; }
</span><span class="cx"> 
</span><del>-    double sampleRate() const { return m_sampleRate; }
-    void setSampleRate(double);
-    virtual bool applySampleRate(double) { return false; }
</del><ins>+    int sampleRate() const { return m_sampleRate; }
+    void setSampleRate(int);
+    virtual bool applySampleRate(int) { return false; }
</ins><span class="cx"> 
</span><del>-    double sampleSize() const { return m_sampleSize; }
-    void setSampleSize(double);
-    virtual bool applySampleSize(double) { return false; }
</del><ins>+    int sampleSize() const { return m_sampleSize; }
+    void setSampleSize(int);
+    virtual bool applySampleSize(int) { return false; }
</ins><span class="cx"> 
</span><span class="cx">     bool echoCancellation() const { return m_echoCancellation; }
</span><span class="cx">     void setEchoCancellation(bool);
</span><span class="lines">@@ -170,7 +170,6 @@
</span><span class="cx"> private:
</span><span class="cx">     WeakPtr&lt;RealtimeMediaSource&gt; createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
</span><span class="cx"> 
</span><del>-    bool supportsConstraints(const MediaTrackConstraintSetMap&amp;);
</del><span class="cx">     bool selectSettings(const MediaConstraints&amp;, FlattenedConstraint&amp;, String&amp;);
</span><span class="cx">     double fitnessDistance(const MediaConstraint&amp;);
</span><span class="cx">     void applyConstraint(const MediaConstraint&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -267,7 +267,7 @@
</span><span class="cx"> bool AVCaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo* session, RealtimeMediaSource::Type type, const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><span class="cx">     const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
</span><del>-    MediaConstraintType constraintType = constraint.type();
</del><ins>+    MediaConstraintType constraintType = constraint.constraintType();
</ins><span class="cx">     if (!supportedConstraints.supportsConstraint(constraintType))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="lines">@@ -279,7 +279,7 @@
</span><span class="cx">         if (constraintType == MediaConstraintType::Width) {
</span><span class="cx">             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160578. Support min, max constraints.
</span><span class="cx">             int exact;
</span><del>-            if (!constraint.getExact(exact))
</del><ins>+            if (!downcast&lt;const IntConstraint&gt;(constraint).getExact(exact))
</ins><span class="cx">                 return false;
</span><span class="cx"> 
</span><span class="cx">             return !session-&gt;bestSessionPresetForVideoDimensions(exact, 0).isEmpty();
</span><span class="lines">@@ -288,7 +288,7 @@
</span><span class="cx">         if (constraintType == MediaConstraintType::Height) {
</span><span class="cx">             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=160578. Support min, max constraints.
</span><span class="cx">             int exact;
</span><del>-            if (!constraint.getExact(exact))
</del><ins>+            if (!downcast&lt;const IntConstraint&gt;(constraint).getExact(exact))
</ins><span class="cx">                 return false;
</span><span class="cx"> 
</span><span class="cx">             return !session-&gt;bestSessionPresetForVideoDimensions(0, exact).isEmpty();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMediaConstraintsMockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MediaConstraintsMock.cpp        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -43,15 +43,15 @@
</span><span class="cx">     int floor = 0;
</span><span class="cx"> 
</span><span class="cx">     int min = floor;
</span><del>-    if (constraint.getMin(min) &amp;&amp; min &gt; ceiling)
</del><ins>+    if (downcast&lt;const IntConstraint&gt;(constraint).getMin(min) &amp;&amp; min &gt; ceiling)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     int max = ceiling;
</span><del>-    if (constraint.getMax(max) &amp;&amp; max &lt; min)
</del><ins>+    if (downcast&lt;const IntConstraint&gt;(constraint).getMax(max) &amp;&amp; max &lt; min)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     int exact;
</span><del>-    if (constraint.getExact(exact) &amp;&amp; (exact &lt; min || exact &gt; max))
</del><ins>+    if (downcast&lt;const IntConstraint&gt;(constraint).getExact(exact) &amp;&amp; (exact &lt; min || exact &gt; max))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="lines">@@ -63,15 +63,15 @@
</span><span class="cx">     double floor = 0;
</span><span class="cx"> 
</span><span class="cx">     double min = floor;
</span><del>-    if (constraint.getMin(min) &amp;&amp; min &gt; ceiling)
</del><ins>+    if (downcast&lt;const DoubleConstraint&gt;(constraint).getMin(min) &amp;&amp; min &gt; ceiling)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     double max = ceiling;
</span><del>-    if (constraint.getMax(max) &amp;&amp; max &lt; min)
</del><ins>+    if (downcast&lt;const DoubleConstraint&gt;(constraint).getMax(max) &amp;&amp; max &lt; min)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     double exact;
</span><del>-    if (constraint.getExact(exact) &amp;&amp; (exact &lt; min || exact &gt; max))
</del><ins>+    if (downcast&lt;const DoubleConstraint&gt;(constraint).getExact(exact) &amp;&amp; (exact &lt; min || exact &gt; max))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx"> static bool isBooleanMediaConstraintSatisfiable(const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><span class="cx">     bool exact;
</span><del>-    if (constraint.getExact(exact))
</del><ins>+    if (downcast&lt;const BooleanConstraint&gt;(constraint).getExact(exact))
</ins><span class="cx">         return exact;
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx"> static bool isStringMediaConstraintSatisfiable(const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;String&gt; exact;
</span><del>-    if (constraint.getExact(exact)) {
</del><ins>+    if (downcast&lt;const StringConstraint&gt;(constraint).getExact(exact)) {
</ins><span class="cx">         for (auto&amp; constraintValue : exact) {
</span><span class="cx">             if (constraintValue.find(&quot;invalid&quot;) != notFound)
</span><span class="cx">                 return false;
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx"> 
</span><span class="cx"> static bool isSatisfiable(RealtimeMediaSource::Type type, const MediaConstraint&amp; constraint)
</span><span class="cx"> {
</span><del>-    MediaConstraintType constraintType = constraint.type();
</del><ins>+    MediaConstraintType constraintType = constraint.constraintType();
</ins><span class="cx"> 
</span><span class="cx">     if (type == RealtimeMediaSource::Audio) {
</span><span class="cx">         if (constraintType == MediaConstraintType::SampleRate || constraintType == MediaConstraintType::SampleSize)
</span><span class="lines">@@ -124,15 +124,20 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const String&amp; MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Type type, const MediaConstraints&amp; constraints)
</del><ins>+const String MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Type type, const MediaConstraints&amp; constraints)
</ins><span class="cx"> {
</span><del>-    auto&amp; mandatoryConstraints = constraints.mandatoryConstraints();
-    for (auto&amp; nameConstraintPair : mandatoryConstraints) {
-        if (!isSatisfiable(type, *nameConstraintPair.value))
-            return nameConstraintPair.key;
-    }
</del><ins>+    String invalidConstraint = emptyString();
+    constraints.mandatoryConstraints().filter([&amp;](const MediaConstraint&amp; constraint) {
+        if (!isSatisfiable(type, constraint)) {
+            invalidConstraint = constraint.name();
+            return true;
+        }
</ins><span class="cx"> 
</span><del>-    return emptyString();
</del><ins>+        return false;
+    });
+
+    return invalidConstraint;
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMediaConstraintsMockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MediaConstraintsMock.h        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> class MediaConstraintsMock {
</span><span class="cx"> public:
</span><del>-    static const String&amp; verifyConstraints(RealtimeMediaSource::Type, const MediaConstraints&amp;);
</del><ins>+    static const String 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="trunkSourceWebCoreplatformmockMockRealtimeAudioSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeAudioSource.h        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -53,8 +53,8 @@
</span><span class="cx"> private:
</span><span class="cx"> 
</span><span class="cx">     bool applyVolume(double) override { return true; }
</span><del>-    bool applySampleRate(double) override { return true; }
-    bool applySampleSize(double) override { return true; }
</del><ins>+    bool applySampleRate(int) override { return true; }
+    bool applySampleSize(int) override { return true; }
</ins><span class="cx">     bool applyEchoCancellation(bool) override { return true; }
</span><span class="cx"> 
</span><span class="cx">     void updateSettings(RealtimeMediaSourceSettings&amp;) override;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (206444 => 206445)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2016-09-27 17:54:49 UTC (rev 206444)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2016-09-27 17:58:44 UTC (rev 206445)
</span><span class="lines">@@ -109,7 +109,7 @@
</span><span class="cx">     Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; videoSources;
</span><span class="cx"> 
</span><span class="cx">     if (audioConstraints.isValid()) {
</span><del>-        const String&amp; invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Audio, audioConstraints);
</del><ins>+        const String 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">@@ -120,7 +120,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (videoConstraints.isValid()) {
</span><del>-        const String&amp; invalidQuery = MediaConstraintsMock::verifyConstraints(RealtimeMediaSource::Video, videoConstraints);
</del><ins>+        const String 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>
</div>

</body>
</html>