<!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>[192838] 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/192838">192838</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2015-11-30 15:48:42 -0800 (Mon, 30 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Split platform-independent logic in AVCaptureDeviceManager out into a new class
https://bugs.webkit.org/show_bug.cgi?id=151388
&lt;rdar://problem/23593980&gt;

Reviewed by Eric Carlson.

To prepare for creating a MockCaptureDeviceManager to be able to test
MediaDevices.getUserMedia, we create a platform-independent capture device manager
which all platforms should extend and add platform-specific logic to.

The methods CaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints and
CaptureDeviceManager::captureDeviceList should be overridden by each platform
CaptureDeviceManager to respectively create a RealtimeMediaSource and return a list of
capture devices. createMediaSourceForCaptureDeviceWithConstraints attempts to create
a media source for a given device with some constraints; if the contraints cannot be
satisfied, this returns null.

The refactored capture device manager also introduces the notion of a platform-
independent capture session which may be extended by platform device managers for
determining whether a given constraint name, value and media type is valid.

A platform-independent CaptureDeviceInfo now represents either the video or audio
component of a capture device, but not both at once. This means a capture device that
supports both video and audio will emit two separate capture devices.

No new tests, since there should be no behavior change.

* Modules/mediastream/CaptureDeviceInfo.h: Added.
(WebCore::CaptureSessionInfo::~CaptureSessionInfo):
(WebCore::CaptureSessionInfo::supportsVideoSize):
(WebCore::CaptureSessionInfo::bestSessionPresetForVideoDimensions):
* Modules/mediastream/CaptureDeviceManager.cpp: Added.
(CaptureDeviceManager::~CaptureDeviceManager):
(CaptureDeviceManager::getSourcesInfo):
(CaptureDeviceManager::captureDeviceFromDeviceID):
(CaptureDeviceManager::verifyConstraintsForMediaType):
(CaptureDeviceManager::bestSourcesForTypeAndConstraints):
(CaptureDeviceManager::sourceWithUID):
(CaptureDeviceManager::bestDeviceForFacingMode):
(facingModeFromString):
(CaptureDeviceManager::sessionSupportsConstraint):
(CaptureDeviceManager::isSupportedFrameRate):
* Modules/mediastream/CaptureDeviceManager.h: Added.
(WebCore::CaptureDeviceManager::refreshCaptureDeviceList):
(WebCore::CaptureDeviceManager::defaultCaptureSession):
* WebCore.xcodeproj/project.pbxproj:
* platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp: Added.
(WebCore::RealtimeMediaSourceSupportedConstraints::nameForConstraint):
(WebCore::RealtimeMediaSourceSupportedConstraints::constraintFromName):
(WebCore::RealtimeMediaSourceSupportedConstraints::supportsConstraint):
* platform/mediastream/RealtimeMediaSourceSupportedConstraints.h:
* platform/mediastream/mac/AVCaptureDeviceManager.h:
* platform/mediastream/mac/AVCaptureDeviceManager.mm:
(WebCore::AVCaptureSessionInfo::AVCaptureSessionInfo):
(WebCore::AVCaptureSessionInfo::supportsVideoSize):
(WebCore::AVCaptureSessionInfo::bestSessionPresetForVideoDimensions):
(WebCore::AVCaptureDeviceManager::captureDeviceList):
(WebCore::shouldConsiderDeviceInDeviceList):
(WebCore::AVCaptureDeviceManager::refreshCaptureDeviceList):
(WebCore::AVCaptureDeviceManager::AVCaptureDeviceManager):
(WebCore::AVCaptureDeviceManager::bestSourcesForTypeAndConstraints):
(WebCore::AVCaptureDeviceManager::sourceWithUID):
(WebCore::AVCaptureDeviceManager::getSourcesInfo):
(WebCore::AVCaptureDeviceManager::verifyConstraintsForMediaType):
(WebCore::AVCaptureDeviceManager::defaultCaptureSession):
(WebCore::AVCaptureDeviceManager::sessionSupportsConstraint):
(WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints):
(WebCore::AVCaptureDeviceManager::deviceDisconnected):
(WebCore::AVCaptureDeviceManager::isSupportedFrameRate):
(WebCore::CaptureDevice:::m_enabled): Deleted.
(WebCore::captureDeviceList): Deleted.
(WebCore::captureDeviceFromDeviceID): Deleted.
(WebCore::refreshCaptureDeviceList): Deleted.
(WebCore::AVCaptureDeviceManager::bestSessionPresetForVideoSize): Deleted.
(WebCore::AVCaptureDeviceManager::deviceSupportsFacingMode): Deleted.
(WebCore::AVCaptureDeviceManager::bestDeviceForFacingMode): Deleted.
(WebCore::AVCaptureDeviceManager::isValidConstraint): Deleted.
(WebCore::AVCaptureDeviceManager::validConstraintNames): Deleted.
(WebCore::AVCaptureDeviceManager::validFacingModes): Deleted.
* platform/mediastream/mac/AVVideoCaptureSource.mm:
(WebCore::AVVideoCaptureSource::applyConstraints):
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
(WebCore::RealtimeMediaSourceCenterMac::createMediaStream):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceSupportedConstraintsh">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagerh">trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm">trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourcemm">trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacRealtimeMediaSourceCenterMaccpp">trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreModulesmediastreamCaptureDeviceInfoh">trunk/Source/WebCore/Modules/mediastream/CaptureDeviceInfo.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamCaptureDeviceManagercpp">trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamCaptureDeviceManagerh">trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceSupportedConstraintscpp">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192837 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/ChangeLog        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -1,3 +1,90 @@
</span><ins>+2015-11-30  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Split platform-independent logic in AVCaptureDeviceManager out into a new class
+        https://bugs.webkit.org/show_bug.cgi?id=151388
+        &lt;rdar://problem/23593980&gt;
+
+        Reviewed by Eric Carlson.
+
+        To prepare for creating a MockCaptureDeviceManager to be able to test
+        MediaDevices.getUserMedia, we create a platform-independent capture device manager
+        which all platforms should extend and add platform-specific logic to.
+
+        The methods CaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints and
+        CaptureDeviceManager::captureDeviceList should be overridden by each platform
+        CaptureDeviceManager to respectively create a RealtimeMediaSource and return a list of
+        capture devices. createMediaSourceForCaptureDeviceWithConstraints attempts to create
+        a media source for a given device with some constraints; if the contraints cannot be
+        satisfied, this returns null.
+
+        The refactored capture device manager also introduces the notion of a platform-
+        independent capture session which may be extended by platform device managers for
+        determining whether a given constraint name, value and media type is valid.
+
+        A platform-independent CaptureDeviceInfo now represents either the video or audio
+        component of a capture device, but not both at once. This means a capture device that
+        supports both video and audio will emit two separate capture devices.
+
+        No new tests, since there should be no behavior change.
+
+        * Modules/mediastream/CaptureDeviceInfo.h: Added.
+        (WebCore::CaptureSessionInfo::~CaptureSessionInfo):
+        (WebCore::CaptureSessionInfo::supportsVideoSize):
+        (WebCore::CaptureSessionInfo::bestSessionPresetForVideoDimensions):
+        * Modules/mediastream/CaptureDeviceManager.cpp: Added.
+        (CaptureDeviceManager::~CaptureDeviceManager):
+        (CaptureDeviceManager::getSourcesInfo):
+        (CaptureDeviceManager::captureDeviceFromDeviceID):
+        (CaptureDeviceManager::verifyConstraintsForMediaType):
+        (CaptureDeviceManager::bestSourcesForTypeAndConstraints):
+        (CaptureDeviceManager::sourceWithUID):
+        (CaptureDeviceManager::bestDeviceForFacingMode):
+        (facingModeFromString):
+        (CaptureDeviceManager::sessionSupportsConstraint):
+        (CaptureDeviceManager::isSupportedFrameRate):
+        * Modules/mediastream/CaptureDeviceManager.h: Added.
+        (WebCore::CaptureDeviceManager::refreshCaptureDeviceList):
+        (WebCore::CaptureDeviceManager::defaultCaptureSession):
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp: Added.
+        (WebCore::RealtimeMediaSourceSupportedConstraints::nameForConstraint):
+        (WebCore::RealtimeMediaSourceSupportedConstraints::constraintFromName):
+        (WebCore::RealtimeMediaSourceSupportedConstraints::supportsConstraint):
+        * platform/mediastream/RealtimeMediaSourceSupportedConstraints.h:
+        * platform/mediastream/mac/AVCaptureDeviceManager.h:
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::AVCaptureSessionInfo::AVCaptureSessionInfo):
+        (WebCore::AVCaptureSessionInfo::supportsVideoSize):
+        (WebCore::AVCaptureSessionInfo::bestSessionPresetForVideoDimensions):
+        (WebCore::AVCaptureDeviceManager::captureDeviceList):
+        (WebCore::shouldConsiderDeviceInDeviceList):
+        (WebCore::AVCaptureDeviceManager::refreshCaptureDeviceList):
+        (WebCore::AVCaptureDeviceManager::AVCaptureDeviceManager):
+        (WebCore::AVCaptureDeviceManager::bestSourcesForTypeAndConstraints):
+        (WebCore::AVCaptureDeviceManager::sourceWithUID):
+        (WebCore::AVCaptureDeviceManager::getSourcesInfo):
+        (WebCore::AVCaptureDeviceManager::verifyConstraintsForMediaType):
+        (WebCore::AVCaptureDeviceManager::defaultCaptureSession):
+        (WebCore::AVCaptureDeviceManager::sessionSupportsConstraint):
+        (WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints):
+        (WebCore::AVCaptureDeviceManager::deviceDisconnected):
+        (WebCore::AVCaptureDeviceManager::isSupportedFrameRate):
+        (WebCore::CaptureDevice:::m_enabled): Deleted.
+        (WebCore::captureDeviceList): Deleted.
+        (WebCore::captureDeviceFromDeviceID): Deleted.
+        (WebCore::refreshCaptureDeviceList): Deleted.
+        (WebCore::AVCaptureDeviceManager::bestSessionPresetForVideoSize): Deleted.
+        (WebCore::AVCaptureDeviceManager::deviceSupportsFacingMode): Deleted.
+        (WebCore::AVCaptureDeviceManager::bestDeviceForFacingMode): Deleted.
+        (WebCore::AVCaptureDeviceManager::isValidConstraint): Deleted.
+        (WebCore::AVCaptureDeviceManager::validConstraintNames): Deleted.
+        (WebCore::AVCaptureDeviceManager::validFacingModes): Deleted.
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        (WebCore::AVVideoCaptureSource::applyConstraints):
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
+        (WebCore::RealtimeMediaSourceCenterMac::createMediaStream):
+
</ins><span class="cx"> 2015-11-30  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Modern IDB: Set the correct source on the IDBRequest for cursor updates
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamCaptureDeviceInfoh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceInfo.h (0 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceInfo.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceInfo.h        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -0,0 +1,59 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CaptureDeviceInfo_h
+#define CaptureDeviceInfo_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include &lt;RealtimeMediaSource.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+struct CaptureDeviceInfo {
+    String m_persistentDeviceID;
+    String m_localizedName;
+    String m_groupID;
+
+    String m_sourceId;
+
+    bool m_enabled { false };
+    RealtimeMediaSource::Type m_sourceType { RealtimeMediaSource::None };
+    RealtimeMediaSourceStates::VideoFacingMode m_position { RealtimeMediaSourceStates::Unknown };
+};
+
+class CaptureSessionInfo {
+public:
+    virtual ~CaptureSessionInfo() { }
+    virtual bool supportsVideoSize(const String&amp; /* videoSize */) const { return false; }
+    virtual String bestSessionPresetForVideoDimensions(int /* width */, int /* height */) const { return emptyString(); }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif /* CaptureDeviceInfo_h */
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamCaptureDeviceManagercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp (0 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -0,0 +1,193 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import &quot;config.h&quot;
+#import &quot;CaptureDeviceManager.h&quot;
+
+#if ENABLE(MEDIA_STREAM)
+
+#import &quot;Logging.h&quot;
+#import &quot;MediaConstraints.h&quot;
+#import &quot;RealtimeMediaSource.h&quot;
+#import &quot;RealtimeMediaSourceCenter.h&quot;
+#import &quot;RealtimeMediaSourceStates.h&quot;
+#import &quot;UUID.h&quot;
+#import &lt;wtf/MainThread.h&gt;
+#import &lt;wtf/NeverDestroyed.h&gt;
+
+using namespace WebCore;
+
+CaptureDeviceManager::~CaptureDeviceManager()
+{
+}
+
+Vector&lt;RefPtr&lt;TrackSourceInfo&gt;&gt; CaptureDeviceManager::getSourcesInfo(const String&amp; requestOrigin)
+{
+    UNUSED_PARAM(requestOrigin);
+    Vector&lt;RefPtr&lt;TrackSourceInfo&gt;&gt; sourcesInfo;
+    for (auto captureDevice : captureDeviceList()) {
+        if (!captureDevice.m_enabled || captureDevice.m_sourceType == RealtimeMediaSource::None)
+            continue;
+
+        TrackSourceInfo::SourceKind trackSourceType = captureDevice.m_sourceType == RealtimeMediaSource::Video ? TrackSourceInfo::Video : TrackSourceInfo::Audio;
+        sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_sourceId, trackSourceType, captureDevice.m_localizedName, captureDevice.m_groupID));
+    }
+    LOG(Media, &quot;CaptureDeviceManager::getSourcesInfo(%p), found %zu active devices&quot;, this, sourcesInfo.size());
+    return sourcesInfo;
+}
+
+bool CaptureDeviceManager::captureDeviceFromDeviceID(const String&amp; captureDeviceID, CaptureDeviceInfo&amp; foundDevice)
+{
+    for (auto&amp; device : captureDeviceList()) {
+        if (device.m_persistentDeviceID == captureDeviceID) {
+            foundDevice = device;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool CaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, MediaConstraints* constraints, const CaptureSessionInfo* session, String&amp; invalidConstraint)
+{
+    if (!constraints)
+        return true;
+
+    Vector&lt;MediaConstraint&gt; mandatoryConstraints;
+    constraints-&gt;getMandatoryConstraints(mandatoryConstraints);
+    for (auto&amp; constraint : mandatoryConstraints) {
+        if (sessionSupportsConstraint(session, type, constraint.m_name, constraint.m_value))
+            continue;
+
+        invalidConstraint = constraint.m_name;
+        return false;
+    }
+
+    return true;
+}
+
+Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; CaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, PassRefPtr&lt;MediaConstraints&gt; constraints)
+{
+    Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; bestSourcesList;
+
+    struct {
+        bool operator()(RefPtr&lt;RealtimeMediaSource&gt; a, RefPtr&lt;RealtimeMediaSource&gt; b)
+        {
+            return a-&gt;fitnessScore() &lt; b-&gt;fitnessScore();
+        }
+    } sortBasedOnFitnessScore;
+
+    for (auto&amp; captureDevice : captureDeviceList()) {
+        if (!captureDevice.m_enabled || captureDevice.m_sourceId.isEmpty() || captureDevice.m_sourceType == RealtimeMediaSource::None)
+            continue;
+
+        if (RefPtr&lt;RealtimeMediaSource&gt; captureSource = sourceWithUID(captureDevice.m_persistentDeviceID, type, constraints.get()))
+            bestSourcesList.append(captureSource.leakRef());
+    }
+    std::sort(bestSourcesList.begin(), bestSourcesList.end(), sortBasedOnFitnessScore);
+    return bestSourcesList;
+}
+
+RefPtr&lt;RealtimeMediaSource&gt; CaptureDeviceManager::sourceWithUID(const String&amp; deviceUID, RealtimeMediaSource::Type type, MediaConstraints* constraints)
+{
+    for (auto&amp; captureDevice : captureDeviceList()) {
+        if (captureDevice.m_persistentDeviceID != deviceUID || captureDevice.m_sourceType != type)
+            continue;
+
+        if (!captureDevice.m_enabled || type == RealtimeMediaSource::None || captureDevice.m_sourceId.isEmpty())
+            continue;
+
+        if (RealtimeMediaSource* mediaSource = createMediaSourceForCaptureDeviceWithConstraints(captureDevice, constraints))
+            return mediaSource;
+    }
+    return nullptr;
+}
+
+CaptureDeviceInfo* CaptureDeviceManager::bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode facingMode)
+{
+    if (facingMode == RealtimeMediaSourceStates::Unknown)
+        return nullptr;
+
+    for (auto&amp; device : captureDeviceList()) {
+        if (device.m_sourceType == RealtimeMediaSource::Video &amp;&amp; device.m_position == facingMode)
+            return &amp;device;
+    }
+    return nullptr;
+}
+
+static inline RealtimeMediaSourceStates::VideoFacingMode facingModeFromString(const String&amp; facingModeString)
+{
+    static NeverDestroyed&lt;AtomicString&gt; userFacingModeString(&quot;user&quot;, AtomicString::ConstructFromLiteral);
+    static NeverDestroyed&lt;AtomicString&gt; environmentFacingModeString(&quot;environment&quot;, AtomicString::ConstructFromLiteral);
+    static NeverDestroyed&lt;AtomicString&gt; leftFacingModeString(&quot;left&quot;, AtomicString::ConstructFromLiteral);
+    static NeverDestroyed&lt;AtomicString&gt; rightFacingModeString(&quot;right&quot;, AtomicString::ConstructFromLiteral);
+    if (facingModeString == userFacingModeString)
+        return RealtimeMediaSourceStates::User;
+    if (facingModeString == environmentFacingModeString)
+        return RealtimeMediaSourceStates::Environment;
+    if (facingModeString == leftFacingModeString)
+        return RealtimeMediaSourceStates::Left;
+    if (facingModeString == rightFacingModeString)
+        return RealtimeMediaSourceStates::Right;
+    return RealtimeMediaSourceStates::Unknown;
+}
+
+bool CaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type type, const String&amp; name, const String&amp; value)
+{
+    const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    MediaConstraintType constraint = supportedConstraints.constraintFromName(name);
+    if (!supportedConstraints.supportsConstraint(constraint))
+        return false;
+
+    switch (constraint) {
+    case MediaConstraintType::Width:
+        return type == RealtimeMediaSource::Video;
+
+    case MediaConstraintType::Height:
+        return type == RealtimeMediaSource::Video;
+
+    case MediaConstraintType::FrameRate: {
+        if (type == RealtimeMediaSource::Audio)
+            return false;
+
+        return isSupportedFrameRate(value.toFloat());
+    }
+    case MediaConstraintType::FacingMode: {
+        if (type == RealtimeMediaSource::Audio)
+            return false;
+
+        return bestDeviceForFacingMode(facingModeFromString(value));
+    }
+    default:
+        return false;
+    }
+}
+
+bool CaptureDeviceManager::isSupportedFrameRate(float frameRate) const
+{
+    return 0 &lt; frameRate &amp;&amp; frameRate &lt;= 60;
+}
+
+#endif // ENABLE(MEDIA_STREAM)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamCaptureDeviceManagerh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h (0 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CaptureDeviceManager_h
+#define CaptureDeviceManager_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include &quot;CaptureDeviceInfo.h&quot;
+#include &quot;MediaStreamTrackSourcesRequestClient.h&quot;
+#include &quot;RealtimeMediaSource.h&quot;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+class CaptureDeviceManager {
+public:
+    virtual Vector&lt;CaptureDeviceInfo&gt;&amp; captureDeviceList() = 0;
+    virtual void refreshCaptureDeviceList() { }
+    virtual TrackSourceInfoVector getSourcesInfo(const String&amp;);
+    virtual Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, PassRefPtr&lt;MediaConstraints&gt;);
+    virtual RefPtr&lt;RealtimeMediaSource&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*);
+
+    virtual bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, MediaConstraints*, const CaptureSessionInfo*, String&amp;);
+
+protected:
+    virtual ~CaptureDeviceManager();
+    virtual RealtimeMediaSource* createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&amp;, MediaConstraints*) = 0;
+
+    virtual CaptureSessionInfo defaultCaptureSession() const { return CaptureSessionInfo(); }
+    virtual bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const String&amp; name, const String&amp; value);
+    virtual bool isSupportedFrameRate(float frameRate) const;
+
+    bool captureDeviceFromDeviceID(const String&amp; captureDeviceID, CaptureDeviceInfo&amp; source);
+    CaptureDeviceInfo* bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif /* CaptureDeviceManager_h */
</ins></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (192837 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -1210,6 +1210,9 @@
</span><span class="cx">                 2E3BC108117D479800B9409A /* DOMFileError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC106117D479800B9409A /* DOMFileError.h */; };
</span><span class="cx">                 2E3BC109117D479800B9409A /* DOMFileError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E3BC107117D479800B9409A /* DOMFileError.mm */; };
</span><span class="cx">                 2E3BC10B117D47C800B9409A /* DOMFileErrorInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC10A117D47C800B9409A /* DOMFileErrorInternal.h */; };
</span><ins>+                2E3C8C621BFBA97500309566 /* CaptureDeviceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3C8C611BFBA8DC00309566 /* CaptureDeviceManager.h */; };
+                2E3C8C641BFBB75D00309566 /* CaptureDeviceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E3C8C631BFBB75D00309566 /* CaptureDeviceManager.cpp */; };
+                2E3C8C681BFBF8E100309566 /* CaptureDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3C8C661BFBF8E100309566 /* CaptureDeviceInfo.h */; };
</ins><span class="cx">                 2E4346450F546A8200B0F1BA /* Worker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E4346330F546A8200B0F1BA /* Worker.cpp */; };
</span><span class="cx">                 2E4346460F546A8200B0F1BA /* Worker.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346340F546A8200B0F1BA /* Worker.h */; };
</span><span class="cx">                 2E4346480F546A8200B0F1BA /* WorkerGlobalScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E4346360F546A8200B0F1BA /* WorkerGlobalScope.cpp */; };
</span><span class="lines">@@ -1237,6 +1240,7 @@
</span><span class="cx">                 2EB4BCD2121F03E300EC4885 /* BlobResourceHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2EB4BCD0121F03E300EC4885 /* BlobResourceHandle.cpp */; };
</span><span class="cx">                 2EB4BCD3121F03E300EC4885 /* BlobResourceHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */; };
</span><span class="cx">                 2EBBC3D81B65988300F5253D /* WheelEventDeltaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EBBC3D71B65988300F5253D /* WheelEventDeltaFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                2EC41DE41C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2EC41DE21C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp */; };
</ins><span class="cx">                 2ECF7ADC10162B3800427DE7 /* JSErrorEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ECF7ADA10162B3800427DE7 /* JSErrorEvent.cpp */; };
</span><span class="cx">                 2ECF7ADD10162B3800427DE7 /* JSErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECF7ADB10162B3800427DE7 /* JSErrorEvent.h */; };
</span><span class="cx">                 2ECF7AE110162B5800427DE7 /* ErrorEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */; };
</span><span class="lines">@@ -8587,6 +8591,9 @@
</span><span class="cx">                 2E3BC106117D479800B9409A /* DOMFileError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFileError.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2E3BC107117D479800B9409A /* DOMFileError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMFileError.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2E3BC10A117D47C800B9409A /* DOMFileErrorInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFileErrorInternal.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                2E3C8C611BFBA8DC00309566 /* CaptureDeviceManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CaptureDeviceManager.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2E3C8C631BFBB75D00309566 /* CaptureDeviceManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CaptureDeviceManager.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2E3C8C661BFBF8E100309566 /* CaptureDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CaptureDeviceInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2E4346330F546A8200B0F1BA /* Worker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Worker.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2E4346340F546A8200B0F1BA /* Worker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Worker.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2E4346350F546A8200B0F1BA /* Worker.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Worker.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -8617,6 +8624,7 @@
</span><span class="cx">                 2EB4BCD0121F03E300EC4885 /* BlobResourceHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlobResourceHandle.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobResourceHandle.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2EBBC3D71B65988300F5253D /* WheelEventDeltaFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WheelEventDeltaFilter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                2EC41DE21C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RealtimeMediaSourceSupportedConstraints.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2ECF7ADA10162B3800427DE7 /* JSErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSErrorEvent.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2ECF7ADB10162B3800427DE7 /* JSErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSErrorEvent.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorEvent.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15138,6 +15146,9 @@
</span><span class="cx">                                 070584FE17F9F05E005F2BCB /* CapabilityRange.cpp */,
</span><span class="cx">                                 07C59B7417F7D09D000FBCBB /* CapabilityRange.h */,
</span><span class="cx">                                 07C59B7517F7D09D000FBCBB /* CapabilityRange.idl */,
</span><ins>+                                2E3C8C611BFBA8DC00309566 /* CaptureDeviceManager.h */,
+                                2E3C8C631BFBB75D00309566 /* CaptureDeviceManager.cpp */,
+                                2E3C8C661BFBF8E100309566 /* CaptureDeviceInfo.h */,
</ins><span class="cx">                                 073794ED19EE364200E5A045 /* DOMURLMediaStream.cpp */,
</span><span class="cx">                                 15FCC9FD1B4DF85600E72326 /* DOMURLMediaStream.h */,
</span><span class="cx">                                 073794EE19EE364200E5A045 /* DOMURLMediaStream.idl */,
</span><span class="lines">@@ -15276,6 +15287,7 @@
</span><span class="cx">                                 07FFDE66181AED420072D409 /* MediaStreamTrackPrivate.cpp */,
</span><span class="cx">                                 07FFDE67181AED420072D409 /* MediaStreamTrackPrivate.h */,
</span><span class="cx">                                 07C1C0E41BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h */,
</span><ins>+                                2EC41DE21C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp */,
</ins><span class="cx">                                 076306E217E22A43005A7C4E /* MediaStreamTrackSourcesRequestClient.h */,
</span><span class="cx">                                 4A4F656B1AA997F100E38CDD /* RealtimeMediaSource.cpp */,
</span><span class="cx">                                 4A4F656C1AA997F100E38CDD /* RealtimeMediaSource.h */,
</span><span class="lines">@@ -26619,6 +26631,7 @@
</span><span class="cx">                                 BCEFE1EB0DCA5F6400739219 /* JSXSLTProcessor.h in Headers */,
</span><span class="cx">                                 85031B440A44EFC700F992E0 /* KeyboardEvent.h in Headers */,
</span><span class="cx">                                 1AE00D59182DAC8D00087DD7 /* KeyedCoding.h in Headers */,
</span><ins>+                                2E3C8C621BFBA97500309566 /* CaptureDeviceManager.h in Headers */,
</ins><span class="cx">                                 517A63C51B74318F00E7DCDC /* KeyedDecoderCF.h in Headers */,
</span><span class="cx">                                 517A63C61B74319200E7DCDC /* KeyedEncoderCF.h in Headers */,
</span><span class="cx">                                 A513B3D7114B1666001C429B /* KeyEventCocoa.h in Headers */,
</span><span class="lines">@@ -26704,6 +26717,7 @@
</span><span class="cx">                                 FABE72F91059C1EB00D999DD /* MathMLMathElement.h in Headers */,
</span><span class="cx">                                 44A28AAF12DFB8BF00AE923B /* MathMLNames.h in Headers */,
</span><span class="cx">                                 FA654A6C1108ABED002615E0 /* MathMLTextElement.h in Headers */,
</span><ins>+                                2E3C8C681BFBF8E100309566 /* CaptureDeviceInfo.h in Headers */,
</ins><span class="cx">                                 49D5DC2C0F423A73008F20FD /* Matrix3DTransformOperation.h in Headers */,
</span><span class="cx">                                 49E911C70EF86D47009D0CAF /* MatrixTransformOperation.h in Headers */,
</span><span class="cx">                                 5CBC8DAD1AAA302200E1C803 /* MediaAccessibilitySoftLink.h in Headers */,
</span><span class="lines">@@ -28652,6 +28666,7 @@
</span><span class="cx">                                 E164A2ED191AE6350010737D /* BlobDataFileReferenceMac.mm in Sources */,
</span><span class="cx">                                 E14A94D716DFDF950068DE82 /* BlobRegistry.cpp in Sources */,
</span><span class="cx">                                 2EDEF1F6121B0EFC00726DB2 /* BlobRegistryImpl.cpp in Sources */,
</span><ins>+                                2EC41DE41C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp in Sources */,
</ins><span class="cx">                                 2EB4BCD2121F03E300EC4885 /* BlobResourceHandle.cpp in Sources */,
</span><span class="cx">                                 976D6C7E122B8A3D001FD1F7 /* BlobURL.cpp in Sources */,
</span><span class="cx">                                 93F19AE108245E59001E9ABC /* BlockExceptions.mm in Sources */,
</span><span class="lines">@@ -30373,6 +30388,7 @@
</span><span class="cx">                                 E4B65A5A132FAAF90070E7BE /* LegacyTileGrid.mm in Sources */,
</span><span class="cx">                                 E424A3A01330DF1E00CF6DC9 /* LegacyTileGridTile.mm in Sources */,
</span><span class="cx">                                 E4B65A5E132FADB60070E7BE /* LegacyTileLayer.mm in Sources */,
</span><ins>+                                2E3C8C641BFBB75D00309566 /* CaptureDeviceManager.cpp in Sources */,
</ins><span class="cx">                                 E4E39AFD1330EFC6003AB274 /* LegacyTileLayerPool.mm in Sources */,
</span><span class="cx">                                 51645B6A1B9FA6C800F789CE /* LegacyTransaction.cpp in Sources */,
</span><span class="cx">                                 51645B6C1B9FA6C800F789CE /* LegacyVersionChangeEvent.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceSupportedConstraintscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp (0 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp                                (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -0,0 +1,133 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;RealtimeMediaSourceSupportedConstraints.h&quot;
+
+#if ENABLE(MEDIA_STREAM)
+
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/NeverDestroyed.h&gt;
+#include &lt;wtf/text/AtomicString.h&gt;
+#include &lt;wtf/text/AtomicStringHash.h&gt;
+
+namespace WebCore {
+
+const AtomicString&amp; RealtimeMediaSourceSupportedConstraints::nameForConstraint(MediaConstraintType constraint) const
+{
+    static NeverDestroyed&lt;AtomicString&gt; unknownConstraintName(emptyString());
+    static NeverDestroyed&lt;AtomicString&gt; widthConstraintName(&quot;width&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; heightConstraintName(&quot;height&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; aspectRatioConstraintName(&quot;aspectRatio&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; frameRateConstraintName(&quot;frameRate&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; facingModeConstraintName(&quot;facingMode&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; volumeConstraintName(&quot;volume&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; sampleRateConstraintName(&quot;sampleRate&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; sampleSizeConstraintName(&quot;sampleSize&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; echoCancellationConstraintName(&quot;echoCancellation&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; deviceIdConstraintName(&quot;deviceId&quot;);
+    static NeverDestroyed&lt;AtomicString&gt; groupIdConstraintName(&quot;groupId&quot;);
+    switch (constraint) {
+    case MediaConstraintType::Unknown:
+        return unknownConstraintName;
+    case MediaConstraintType::Width:
+        return widthConstraintName;
+    case MediaConstraintType::Height:
+        return heightConstraintName;
+    case MediaConstraintType::AspectRatio:
+        return aspectRatioConstraintName;
+    case MediaConstraintType::FrameRate:
+        return frameRateConstraintName;
+    case MediaConstraintType::FacingMode:
+        return facingModeConstraintName;
+    case MediaConstraintType::Volume:
+        return volumeConstraintName;
+    case MediaConstraintType::SampleRate:
+        return sampleRateConstraintName;
+    case MediaConstraintType::SampleSize:
+        return sampleSizeConstraintName;
+    case MediaConstraintType::EchoCancellation:
+        return echoCancellationConstraintName;
+    case MediaConstraintType::DeviceId:
+        return deviceIdConstraintName;
+    case MediaConstraintType::GroupId:
+        return groupIdConstraintName;
+    }
+}
+
+MediaConstraintType RealtimeMediaSourceSupportedConstraints::constraintFromName(const String&amp; constraintName) const
+{
+    static NeverDestroyed&lt;HashMap&lt;AtomicString, MediaConstraintType&gt;&gt; nameToConstraintMap;
+    HashMap&lt;AtomicString, MediaConstraintType&gt;&amp; nameToConstraintMapValue = nameToConstraintMap.get();
+    if (!nameToConstraintMapValue.size()) {
+        nameToConstraintMapValue.add(&quot;width&quot;, MediaConstraintType::Width);
+        nameToConstraintMapValue.add(&quot;height&quot;, MediaConstraintType::Height);
+        nameToConstraintMapValue.add(&quot;aspectRatio&quot;, MediaConstraintType::AspectRatio);
+        nameToConstraintMapValue.add(&quot;frameRate&quot;, MediaConstraintType::FrameRate);
+        nameToConstraintMapValue.add(&quot;facingMode&quot;, MediaConstraintType::FacingMode);
+        nameToConstraintMapValue.add(&quot;volume&quot;, MediaConstraintType::Volume);
+        nameToConstraintMapValue.add(&quot;sampleRate&quot;, MediaConstraintType::SampleRate);
+        nameToConstraintMapValue.add(&quot;sampleSize&quot;, MediaConstraintType::SampleSize);
+        nameToConstraintMapValue.add(&quot;echoCancellation&quot;, MediaConstraintType::EchoCancellation);
+        nameToConstraintMapValue.add(&quot;deviceId&quot;, MediaConstraintType::DeviceId);
+        nameToConstraintMapValue.add(&quot;groupId&quot;, MediaConstraintType::GroupId);
+    }
+    auto iter = nameToConstraintMapValue.find(constraintName);
+    return iter == nameToConstraintMapValue.end() ? MediaConstraintType::Unknown : iter-&gt;value;
+}
+
+bool RealtimeMediaSourceSupportedConstraints::supportsConstraint(MediaConstraintType constraint) const
+{
+    switch (constraint) {
+    case MediaConstraintType::Unknown:
+        return false;
+    case MediaConstraintType::Width:
+        return supportsWidth();
+    case MediaConstraintType::Height:
+        return supportsHeight();
+    case MediaConstraintType::AspectRatio:
+        return supportsAspectRatio();
+    case MediaConstraintType::FrameRate:
+        return supportsFrameRate();
+    case MediaConstraintType::FacingMode:
+        return supportsFacingMode();
+    case MediaConstraintType::Volume:
+        return supportsVolume();
+    case MediaConstraintType::SampleRate:
+        return supportsSampleRate();
+    case MediaConstraintType::SampleSize:
+        return supportsSampleSize();
+    case MediaConstraintType::EchoCancellation:
+        return supportsEchoCancellation();
+    case MediaConstraintType::DeviceId:
+        return supportsDeviceId();
+    case MediaConstraintType::GroupId:
+        return supportsGroupId();
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceSupportedConstraintsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h (192837 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h        2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -33,8 +33,25 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/text/WTFString.h&gt;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+enum class MediaConstraintType {
+    Unknown,
+    Width,
+    Height,
+    AspectRatio,
+    FrameRate,
+    FacingMode,
+    Volume,
+    SampleRate,
+    SampleSize,
+    EchoCancellation,
+    DeviceId,
+    GroupId
+};
+
</ins><span class="cx"> class RealtimeMediaSourceSupportedConstraints {
</span><span class="cx"> public:
</span><span class="cx">     RealtimeMediaSourceSupportedConstraints()
</span><span class="lines">@@ -74,6 +91,10 @@
</span><span class="cx">     bool supportsGroupId() const { return m_supportsGroupId; }
</span><span class="cx">     void setSupportsGroupId(bool value) { m_supportsGroupId = value; }
</span><span class="cx"> 
</span><ins>+    const AtomicString&amp; nameForConstraint(MediaConstraintType) const;
+    MediaConstraintType constraintFromName(const String&amp; constraintName) const;
+    bool supportsConstraint(MediaConstraintType) const;
+
</ins><span class="cx"> private:
</span><span class="cx">     bool m_supportsWidth { false };
</span><span class="cx">     bool m_supportsHeight { false };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h (192837 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h        2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><ins>+#include &quot;CaptureDeviceManager.h&quot;
</ins><span class="cx"> #include &quot;MediaStreamTrackSourcesRequestClient.h&quot;
</span><span class="cx"> #include &quot;RealtimeMediaSource.h&quot;
</span><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><span class="lines">@@ -40,38 +41,46 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class CaptureDevice;
</del><ins>+class AVCaptureSessionInfo : public CaptureSessionInfo {
+public:
+    AVCaptureSessionInfo(AVCaptureSession*);
+    virtual bool supportsVideoSize(const String&amp;) const override;
+    virtual String bestSessionPresetForVideoDimensions(int width, int height) const override;
</ins><span class="cx"> 
</span><del>-class AVCaptureDeviceManager {
</del><ins>+private:
+    AVCaptureSession *m_platformSession;
+};
+
+class AVCaptureDeviceManager final : public CaptureDeviceManager {
</ins><span class="cx"> public:
</span><ins>+    virtual Vector&lt;CaptureDeviceInfo&gt;&amp; captureDeviceList() override;
+
</ins><span class="cx">     static AVCaptureDeviceManager&amp; singleton();
</span><del>-    static bool isAvailable();
</del><span class="cx"> 
</span><del>-    TrackSourceInfoVector getSourcesInfo(const String&amp;);
-    bool verifyConstraintsForMediaType(AVCaptureSession *, RealtimeMediaSource::Type, MediaConstraints*, String&amp;);
-    Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, PassRefPtr&lt;MediaConstraints&gt;);
-    RefPtr&lt;RealtimeMediaSource&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*);
</del><ins>+    virtual RefPtr&lt;RealtimeMediaSource&gt; sourceWithUID(const String&amp;, RealtimeMediaSource::Type, MediaConstraints*) override;
+    virtual Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, PassRefPtr&lt;MediaConstraints&gt;) override;
</ins><span class="cx"> 
</span><del>-    enum ValidConstraints { Width = 0, Height, FrameRate, FacingMode, Gain };
-    static const Vector&lt;AtomicString&gt;&amp; validConstraintNames();
-    static const Vector&lt;AtomicString&gt;&amp; validFacingModes();
</del><ins>+    virtual TrackSourceInfoVector getSourcesInfo(const String&amp;) override;
+    virtual bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, MediaConstraints*, const CaptureSessionInfo*, String&amp;) override;
</ins><span class="cx"> 
</span><del>-    static bool deviceSupportsFacingMode(AVCaptureDevice*, RealtimeMediaSourceStates::VideoFacingMode);
-    static bool isValidConstraint(RealtimeMediaSource::Type, const String&amp;);
-    static String bestSessionPresetForVideoSize(AVCaptureSession*, int width, int height);
-
-    void registerForDeviceNotifications();
</del><span class="cx">     void deviceConnected();
</span><span class="cx">     void deviceDisconnected(AVCaptureDevice*);
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><ins>+    static bool isAvailable();
+
</ins><span class="cx">     AVCaptureDeviceManager();
</span><del>-    ~AVCaptureDeviceManager();
</del><ins>+    virtual ~AVCaptureDeviceManager() override;
+    virtual bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const String&amp; name, const String&amp; value) override;
+    virtual RealtimeMediaSource* createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&amp;, MediaConstraints*) override;
+    virtual CaptureSessionInfo defaultCaptureSession() const override;
+    virtual void refreshCaptureDeviceList() override;
+    virtual bool isSupportedFrameRate(float frameRate) const override;
</ins><span class="cx"> 
</span><del>-    CaptureDevice* bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode);
-    bool sessionSupportsConstraint(AVCaptureSession*, RealtimeMediaSource::Type, const String&amp; name, const String&amp; value);
</del><ins>+    void registerForDeviceNotifications();
</ins><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;WebCoreAVCaptureDeviceManagerObserver&gt; m_objcObserver;
</span><ins>+    Vector&lt;CaptureDeviceInfo&gt; m_devices;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm (192837 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -35,7 +35,9 @@
</span><span class="cx"> #import &quot;Logging.h&quot;
</span><span class="cx"> #import &quot;MediaConstraints.h&quot;
</span><span class="cx"> #import &quot;RealtimeMediaSource.h&quot;
</span><ins>+#import &quot;RealtimeMediaSourceCenter.h&quot;
</ins><span class="cx"> #import &quot;RealtimeMediaSourceStates.h&quot;
</span><ins>+#import &quot;RealtimeMediaSourceSupportedConstraints.h&quot;
</ins><span class="cx"> #import &quot;SoftLinking.h&quot;
</span><span class="cx"> #import &quot;UUID.h&quot;
</span><span class="cx"> #import &lt;AVFoundation/AVFoundation.h&gt;
</span><span class="lines">@@ -89,86 +91,113 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static void refreshCaptureDeviceList();
</del><ins>+AVCaptureSessionInfo::AVCaptureSessionInfo(AVCaptureSessionType *platformSession)
+    : m_platformSession(platformSession)
+{
+}
</ins><span class="cx"> 
</span><del>-class CaptureDevice {
-public:
-    CaptureDevice()
-        :m_enabled(false)
-    {
</del><ins>+bool AVCaptureSessionInfo::supportsVideoSize(const String&amp; videoSize) const
+{
+    return [m_platformSession canSetSessionPreset:videoSize];
+}
+
+String AVCaptureSessionInfo::bestSessionPresetForVideoDimensions(int width, int height) const
+{
+    ASSERT(width &gt;= 0);
+    ASSERT(height &gt;= 0);
+
+    if (width &gt; 1280 || height &gt; 720) {
+        // FIXME: this restriction could be adjusted with the videoMaxScaleAndCropFactor property.
+        return emptyString();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    String m_captureDeviceID;
-    String m_localizedName;
-    String m_groupID;
</del><ins>+    if (width &gt; 640 || height &gt; 480) {
+        if (supportsVideoSize(AVCaptureSessionPreset1280x720))
+            return AVCaptureSessionPreset1280x720;
</ins><span class="cx"> 
</span><del>-    String m_audioSourceId;
-    String m_videoSourceId;
</del><ins>+        return emptyString();
+    }
</ins><span class="cx"> 
</span><del>-    bool m_enabled;
-};
</del><ins>+    if (width &gt; 352 || height &gt; 288) {
+        if (supportsVideoSize(AVCaptureSessionPreset640x480))
+            return AVCaptureSessionPreset640x480;
</ins><span class="cx"> 
</span><del>-static Vector&lt;CaptureDevice&gt;&amp; captureDeviceList()
</del><ins>+        return emptyString();
+    }
+
+    if (supportsVideoSize(AVCaptureSessionPreset352x288))
+        return AVCaptureSessionPreset352x288;
+
+    if (supportsVideoSize(AVCaptureSessionPresetLow))
+        return AVCaptureSessionPresetLow;
+
+    return emptyString();
+}
+
+
+Vector&lt;CaptureDeviceInfo&gt;&amp; AVCaptureDeviceManager::captureDeviceList()
</ins><span class="cx"> {
</span><del>-    DEPRECATED_DEFINE_STATIC_LOCAL(Vector&lt;CaptureDevice&gt;, captureDeviceList, ());
</del><span class="cx">     static bool firstTime = true;
</span><del>-
-    if (firstTime &amp;&amp; !captureDeviceList.size()) {
</del><ins>+    if (firstTime &amp;&amp; !m_devices.size()) {
</ins><span class="cx">         firstTime = false;
</span><span class="cx">         refreshCaptureDeviceList();
</span><del>-        AVCaptureDeviceManager::singleton().registerForDeviceNotifications();
</del><ins>+        registerForDeviceNotifications();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return captureDeviceList;
</del><ins>+    return m_devices;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool captureDeviceFromDeviceID(const String&amp; captureDeviceID, CaptureDevice&amp; source)
</del><ins>+inline static bool shouldConsiderDeviceInDeviceList(AVCaptureDeviceType *device)
</ins><span class="cx"> {
</span><del>-    Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
-    
-    size_t count = devices.size();
-    for (size_t i = 0; i &lt; count; ++i) {
-        if (devices[i].m_captureDeviceID == captureDeviceID) {
-            source = devices[i];
-            return true;
-        }
-    }
-    
-    return false;
</del><ins>+    if (![device isConnected])
+        return false;
+
+#if !PLATFORM(IOS)
+    if ([device isSuspended] || [device isInUseByAnotherApplication])
+        return false;
+#endif
+
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void refreshCaptureDeviceList()
</del><ins>+void AVCaptureDeviceManager::refreshCaptureDeviceList()
</ins><span class="cx"> {
</span><del>-    Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
-    
-    for (AVCaptureDeviceType *device in [getAVCaptureDeviceClass() devices]) {
-        CaptureDevice source;
-
-        if (![device isConnected])
</del><ins>+    for (AVCaptureDeviceType *platformDevice in [getAVCaptureDeviceClass() devices]) {
+        if (!shouldConsiderDeviceInDeviceList(platformDevice))
</ins><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-#if !PLATFORM(IOS)
-        if ([device isSuspended] || [device isInUseByAnotherApplication])
-            continue;
-#endif
-
-        if (!captureDeviceFromDeviceID(device.uniqueID, source)) {
</del><ins>+        CaptureDeviceInfo captureDevice;
+        if (!captureDeviceFromDeviceID(platformDevice.uniqueID, captureDevice)) {
</ins><span class="cx">             // An AVCaptureDevice has a unique ID, but we can't use it for the source ID because:
</span><span class="cx">             // 1. if it provides both audio and video we will need to create two sources for it
</span><span class="cx">             // 2. the unique ID persists on one system across device connections, disconnections,
</span><span class="cx">             //    application restarts, and reboots, so it could be used to figerprint a user.
</span><del>-            source.m_captureDeviceID = device.uniqueID;
-            source.m_enabled = true;
-            if ([device hasMediaType:AVMediaTypeAudio] || [device hasMediaType:AVMediaTypeMuxed])
-                source.m_audioSourceId = createCanonicalUUIDString();
</del><ins>+            captureDevice.m_persistentDeviceID = platformDevice.uniqueID;
+            captureDevice.m_enabled = true;
+            captureDevice.m_groupID = createCanonicalUUIDString();
+            captureDevice.m_localizedName = platformDevice.localizedName;
+            if ([platformDevice position] == AVCaptureDevicePositionFront)
+                captureDevice.m_position = RealtimeMediaSourceStates::User;
+            if ([platformDevice position] == AVCaptureDevicePositionBack)
+                captureDevice.m_position = RealtimeMediaSourceStates::Environment;
</ins><span class="cx"> 
</span><del>-            if ([device hasMediaType:AVMediaTypeVideo] || [device hasMediaType:AVMediaTypeMuxed])
-                source.m_videoSourceId = createCanonicalUUIDString();
</del><ins>+            bool hasAudio = [platformDevice hasMediaType:AVMediaTypeAudio] || [platformDevice hasMediaType:AVMediaTypeMuxed];
+            bool hasVideo = [platformDevice hasMediaType:AVMediaTypeVideo] || [platformDevice hasMediaType:AVMediaTypeMuxed];
+            if (!hasAudio &amp;&amp; !hasVideo)
+                continue;
</ins><span class="cx"> 
</span><del>-            source.m_groupID = createCanonicalUUIDString();
-            source.m_localizedName = device.localizedName;
-
-            devices.append(source);
</del><ins>+            // FIXME: For a given device, the source ID should persist when visiting the same request origin,
+            // but differ across different request origins.
+            captureDevice.m_sourceId = createCanonicalUUIDString();
+            captureDevice.m_sourceType = hasVideo ? RealtimeMediaSource::Video : RealtimeMediaSource::Audio;
+            if (hasVideo &amp;&amp; hasAudio) {
+                // Add the audio component as a separate device.
+                CaptureDeviceInfo audioCaptureDevice = captureDevice;
+                audioCaptureDevice.m_sourceId = createCanonicalUUIDString();
+                audioCaptureDevice.m_sourceType = RealtimeMediaSource::Audio;
+                m_devices.append(audioCaptureDevice);
+            }
+            m_devices.append(captureDevice);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -185,7 +214,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> AVCaptureDeviceManager::AVCaptureDeviceManager()
</span><del>-    : m_objcObserver(adoptNS([[WebCoreAVCaptureDeviceManagerObserver alloc] initWithCallback:this]))
</del><ins>+    : m_objcObserver(adoptNS([[WebCoreAVCaptureDeviceManagerObserver alloc] initWithCallback: this]))
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -195,269 +224,91 @@
</span><span class="cx">     [m_objcObserver disconnect];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String AVCaptureDeviceManager::bestSessionPresetForVideoSize(AVCaptureSessionType *captureSession, int width, int height)
</del><ins>+Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; AVCaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, PassRefPtr&lt;MediaConstraints&gt; constraints)
</ins><span class="cx"> {
</span><del>-    ASSERT(width &gt;= 0);
-    ASSERT(height &gt;= 0);
-    
-    if (width &gt; 1280 || height &gt; 720)
-        // FIXME: this restriction could be adjusted with the videoMaxScaleAndCropFactor property.
-        return emptyString();
-    
-    if (width &gt; 640 || height &gt; 480) {
-        if (![captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720])
-            emptyString();
-        return AVCaptureSessionPreset1280x720;
-    }
-    
-    if (width &gt; 352 || height &gt; 288) {
-        if (![captureSession canSetSessionPreset:AVCaptureSessionPreset640x480])
-            emptyString();
-        return AVCaptureSessionPreset640x480;
-    }
-    
-    if ([captureSession canSetSessionPreset:AVCaptureSessionPreset352x288])
-        return AVCaptureSessionPreset352x288;
-    
-    if ([captureSession canSetSessionPreset:AVCaptureSessionPresetLow])
-        return AVCaptureSessionPresetLow;
-    
-    return emptyString();
-}
</del><ins>+    if (!isAvailable())
+        return Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt;();
</ins><span class="cx"> 
</span><del>-bool AVCaptureDeviceManager::deviceSupportsFacingMode(AVCaptureDeviceType *device, RealtimeMediaSourceStates::VideoFacingMode facingMode)
-{
-    if (![device hasMediaType:AVMediaTypeVideo])
-        return false;
-    
-    switch (facingMode) {
-    case RealtimeMediaSourceStates::User:
-        if ([device position] == AVCaptureDevicePositionFront)
-            return true;
-        break;
-    case RealtimeMediaSourceStates::Environment:
-        if ([device position] == AVCaptureDevicePositionBack)
-            return true;
-        break;
-    case RealtimeMediaSourceStates::Left:
-    case RealtimeMediaSourceStates::Right:
-    case RealtimeMediaSourceStates::Unknown:
-        return false;
-    }
-    
-    return false;
</del><ins>+    return CaptureDeviceManager::bestSourcesForTypeAndConstraints(type, constraints);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-CaptureDevice* AVCaptureDeviceManager::bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode facingMode)
</del><ins>+RefPtr&lt;RealtimeMediaSource&gt; AVCaptureDeviceManager::sourceWithUID(const String&amp; deviceUID, RealtimeMediaSource::Type type, MediaConstraints* constraints)
</ins><span class="cx"> {
</span><del>-    Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
-    
-    size_t count = devices.size();
-    for (size_t i = 0; i &lt; count; ++i) {
-        AVCaptureDeviceType *device = [getAVCaptureDeviceClass() deviceWithUniqueID:devices[i].m_captureDeviceID];
-        ASSERT(device);
-        
-        if (device &amp;&amp; deviceSupportsFacingMode(device, facingMode))
-            return &amp;devices[i];
-    }
-    
-    return 0;
</del><ins>+    if (!isAvailable())
+        return nullptr;
+
+    return CaptureDeviceManager::sourceWithUID(deviceUID, type, constraints);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVCaptureDeviceManager::sessionSupportsConstraint(AVCaptureSessionType *session, RealtimeMediaSource::Type type, const String&amp; name, const String&amp; value)
</del><ins>+TrackSourceInfoVector AVCaptureDeviceManager::getSourcesInfo(const String&amp; requestOrigin)
</ins><span class="cx"> {
</span><del>-    size_t constraint = validConstraintNames().find(name);
-    if (constraint == notFound)
-        return true;
-    
-    switch (constraint) {
-    case Width:
-        if (type == RealtimeMediaSource::Audio)
-            return false;
</del><ins>+    if (!isAvailable())
+        return TrackSourceInfoVector();
</ins><span class="cx"> 
</span><del>-        return !bestSessionPresetForVideoSize(session, value.toInt(), 0).isEmpty();
-    case Height:
-        if (type == RealtimeMediaSource::Audio)
-            return false;
-
-        return !bestSessionPresetForVideoSize(session, 0, value.toInt()).isEmpty();
-    case FrameRate: {
-        if (type == RealtimeMediaSource::Audio)
-            return false;
-        
-        // It would make sense to use [AVCaptureConnection videoMinFrameDuration] and
-        // [AVCaptureConnection videoMaxFrameDuration], but they only work with a &quot;live&quot; AVCaptureConnection.
-        float rate = value.toFloat();
-        return rate &gt; 0 &amp;&amp; rate &lt;= 60;
-    }
-    case Gain: {
-        if (type != RealtimeMediaSource::Audio)
-            return false;
-        
-        float level = value.toFloat();
-        return level &gt; 0 &amp;&amp; level &lt;= 1;
-    }
-    case FacingMode: {
-        if (type == RealtimeMediaSource::Audio)
-            return false;
-
-        size_t facingMode =  validFacingModes().find(value);
-        if (facingMode != notFound)
-            return false;
-        return bestDeviceForFacingMode(static_cast&lt;RealtimeMediaSourceStates::VideoFacingMode&gt;(facingMode));
-    }
-    }
-    
-    return false;
</del><ins>+    return CaptureDeviceManager::getSourcesInfo(requestOrigin);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVCaptureDeviceManager::isValidConstraint(RealtimeMediaSource::Type type, const String&amp; name)
</del><ins>+bool AVCaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, MediaConstraints* constraints, const CaptureSessionInfo* session, String&amp; invalidConstraint)
</ins><span class="cx"> {
</span><del>-    size_t constraint = validConstraintNames().find(name);
-    if (constraint == notFound)
</del><ins>+    if (!isAvailable())
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (constraint == Gain)
-        return type == RealtimeMediaSource::Audio;
-
-    return true;
</del><ins>+    return CaptureDeviceManager::verifyConstraintsForMediaType(type, constraints, session, invalidConstraint);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-Vector&lt;RefPtr&lt;TrackSourceInfo&gt;&gt; AVCaptureDeviceManager::getSourcesInfo(const String&amp; requestOrigin)
</del><ins>+CaptureSessionInfo AVCaptureDeviceManager::defaultCaptureSession() const
</ins><span class="cx"> {
</span><del>-    UNUSED_PARAM(requestOrigin);
-    Vector&lt;RefPtr&lt;TrackSourceInfo&gt;&gt; sourcesInfo;
-
-    if (!isAvailable())
-        return sourcesInfo;
-
-    Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
-    for (auto captureDevice : devices) {
-
-        if (!captureDevice.m_enabled)
-            continue;
-
-        if (!captureDevice.m_videoSourceId.isEmpty())
-            sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_videoSourceId, TrackSourceInfo::Video, captureDevice.m_localizedName, captureDevice.m_groupID));
-        if (!captureDevice.m_audioSourceId.isEmpty())
-            sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_audioSourceId, TrackSourceInfo::Audio, captureDevice.m_localizedName, captureDevice.m_groupID));
-    }
-
-    LOG(Media, &quot;AVCaptureDeviceManager::getSourcesInfo(%p), found %d active devices&quot;, this, sourcesInfo.size());
-
-    return sourcesInfo;
</del><ins>+    // FIXME: I don't know if it's safe to use a static var here, since the state of a newly
+    // initialized AVCaptureSession may be different. If not, this should be static and use a
+    // static NeverDestroyed&lt;CaptureSessionInfo&gt;.
+    return AVCaptureSessionInfo([allocAVCaptureSessionInstance() init]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool AVCaptureDeviceManager::verifyConstraintsForMediaType(AVCaptureSessionType *session, RealtimeMediaSource::Type type, MediaConstraints* constraints, String&amp; invalidConstraint)
</del><ins>+bool AVCaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo* session, RealtimeMediaSource::Type type, const String&amp; name, const String&amp; value)
</ins><span class="cx"> {
</span><del>-    if (!isAvailable())
</del><ins>+    const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    MediaConstraintType constraint = supportedConstraints.constraintFromName(name);
+    if (!supportedConstraints.supportsConstraint(constraint))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (!constraints)
-        return true;
</del><ins>+    CaptureSessionInfo defaultSession = defaultCaptureSession();
+    if (!session)
+        session = &amp;defaultSession;
</ins><span class="cx"> 
</span><del>-    Vector&lt;MediaConstraint&gt; mandatoryConstraints;
-    constraints-&gt;getMandatoryConstraints(mandatoryConstraints);
-    if (mandatoryConstraints.size()) {
</del><ins>+    if (type == RealtimeMediaSource::Video) {
+        if (constraint == MediaConstraintType::Width)
+            return session-&gt;bestSessionPresetForVideoDimensions(value.toInt(), 0) != emptyString();
</ins><span class="cx"> 
</span><del>-        RetainPtr&lt;AVCaptureSessionType&gt; captureSession = session ? session : adoptNS([allocAVCaptureSessionInstance() init]);
-        for (size_t i = 0; i &lt; mandatoryConstraints.size(); ++i) {
-            const MediaConstraint&amp; constraint = mandatoryConstraints[i];
-            if (!sessionSupportsConstraint(captureSession.get(), type, constraint.m_name, constraint.m_value)) {
-                invalidConstraint = constraint.m_name;
-                return false;
-            }
-        }
</del><ins>+        if (constraint == MediaConstraintType::Height)
+            return session-&gt;bestSessionPresetForVideoDimensions(0, value.toInt()) != emptyString();
</ins><span class="cx">     }
</span><del>-
-    return true;
</del><ins>+    return CaptureDeviceManager::sessionSupportsConstraint(session, type, name, value);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; AVCaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, PassRefPtr&lt;MediaConstraints&gt; constraints)
</del><ins>+RealtimeMediaSource* AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&amp; captureDevice, MediaConstraints* constraints)
</ins><span class="cx"> {
</span><del>-    Vector&lt;RefPtr&lt;RealtimeMediaSource&gt;&gt; bestSourcesList;
-    
-    if (!isAvailable())
-        return bestSourcesList;
-    
-    struct {
-        bool operator()(RefPtr&lt;RealtimeMediaSource&gt; a, RefPtr&lt;RealtimeMediaSource&gt; b)
-        {
-            return a-&gt;fitnessScore() &lt; b-&gt;fitnessScore();
-        }
-    } sortBasedOffFitnessScore;
</del><ins>+    AVCaptureDeviceType *device = [getAVCaptureDeviceClass() deviceWithUniqueID:captureDevice.m_persistentDeviceID];
+    if (!device)
+        return nullptr;
</ins><span class="cx"> 
</span><del>-    Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
</del><ins>+    RefPtr&lt;AVMediaCaptureSource&gt; captureSource;
+    if (captureDevice.m_sourceType == RealtimeMediaSource::Audio)
+        captureSource = AVAudioCaptureSource::create(device, captureDevice.m_sourceId, constraints);
+    else
+        captureSource = AVVideoCaptureSource::create(device, captureDevice.m_sourceId, constraints);
</ins><span class="cx"> 
</span><del>-    for (auto&amp; captureDevice : devices) {
-        if (!captureDevice.m_enabled)
-            continue;
</del><ins>+    if (constraints) {
+        CaptureSessionInfo captureSession = defaultCaptureSession();
+        if (captureDevice.m_sourceType != RealtimeMediaSource::None)
+            captureSession = AVCaptureSessionInfo(captureSource-&gt;session());
</ins><span class="cx"> 
</span><del>-        if (type == RealtimeMediaSource::Audio &amp;&amp; !captureDevice.m_audioSourceId.isEmpty()) {
-            RefPtr&lt;RealtimeMediaSource&gt; captureSource = AVCaptureDeviceManager::sourceWithUID(captureDevice.m_captureDeviceID, RealtimeMediaSource::Audio, constraints.get());
-            if (!captureSource)
-                continue;
-
-            bestSourcesList.append(captureSource.leakRef());
-        }
-
-        if (type == RealtimeMediaSource::Video &amp;&amp; !captureDevice.m_videoSourceId.isEmpty()) {
-            RefPtr&lt;RealtimeMediaSource&gt; captureSource = AVCaptureDeviceManager::sourceWithUID(captureDevice.m_captureDeviceID, RealtimeMediaSource::Video, constraints.get());
-            if (!captureSource)
-                continue;
-
-            bestSourcesList.append(captureSource.leakRef());
-        }
</del><ins>+        String ignoredInvalidConstraints;
+        if (!verifyConstraintsForMediaType(captureDevice.m_sourceType, constraints, &amp;captureSession, ignoredInvalidConstraints))
+            return nullptr;
</ins><span class="cx">     }
</span><del>-    std::sort(bestSourcesList.begin(), bestSourcesList.end(), sortBasedOffFitnessScore);
-    return bestSourcesList;
</del><ins>+    return captureSource.leakRef();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;RealtimeMediaSource&gt; AVCaptureDeviceManager::sourceWithUID(const String&amp; deviceUID, RealtimeMediaSource::Type type, MediaConstraints* constraints)
-{
-    if (!isAvailable())
-        return 0;
-
-    Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
-    for (auto&amp; captureDevice : devices) {
-        if (captureDevice.m_captureDeviceID != deviceUID || !captureDevice.m_enabled)
-            continue;
-
-        if (type == RealtimeMediaSource::Audio &amp;&amp; captureDevice.m_audioSourceId.isEmpty())
-            continue;
-        if (type == RealtimeMediaSource::Video &amp;&amp; captureDevice.m_videoSourceId.isEmpty())
-            continue;
-
-        AVCaptureDeviceType *device = [getAVCaptureDeviceClass() deviceWithUniqueID:captureDevice.m_captureDeviceID];
-        ASSERT(device);
-
-        RefPtr&lt;AVMediaCaptureSource&gt; captureSource;
-        if (type == RealtimeMediaSource::Audio)
-            captureSource = AVAudioCaptureSource::create(device, captureDevice.m_audioSourceId, constraints);
-        else
-            captureSource = AVVideoCaptureSource::create(device, captureDevice.m_videoSourceId, constraints);
-
-        if (constraints) {
-            String invalidConstraints;
-            AVCaptureSessionType *session = nil;
-
-            if (type == RealtimeMediaSource::Video)
-                session = captureSource-&gt;session();
-            else if (type == RealtimeMediaSource::Audio)
-                session = captureSource-&gt;session();
-            AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(session, type, constraints, invalidConstraints);
-
-            if (!invalidConstraints.isEmpty())
-                continue;
-        }
-        
-        return captureSource.leakRef();
-    }
-    
-    return nullptr;
-
-}
-
</del><span class="cx"> void AVCaptureDeviceManager::registerForDeviceNotifications()
</span><span class="cx"> {
</span><span class="cx">     [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(deviceConnected:) name:AVCaptureDeviceWasConnectedNotification object:nil];
</span><span class="lines">@@ -471,7 +322,7 @@
</span><span class="cx"> 
</span><span class="cx"> void AVCaptureDeviceManager::deviceDisconnected(AVCaptureDeviceType* device)
</span><span class="cx"> {
</span><del>-    Vector&lt;CaptureDevice&gt;&amp; devices = captureDeviceList();
</del><ins>+    Vector&lt;CaptureDeviceInfo&gt;&amp; devices = captureDeviceList();
</ins><span class="cx"> 
</span><span class="cx">     size_t count = devices.size();
</span><span class="cx">     if (!count)
</span><span class="lines">@@ -479,47 +330,20 @@
</span><span class="cx"> 
</span><span class="cx">     String deviceID = device.uniqueID;
</span><span class="cx">     for (size_t i = 0; i &lt; count; ++i) {
</span><del>-        if (devices[i].m_captureDeviceID == deviceID) {
</del><ins>+        if (devices[i].m_persistentDeviceID == deviceID) {
</ins><span class="cx">             LOG(Media, &quot;AVCaptureDeviceManager::deviceDisconnected(%p), device %d disabled&quot;, this, i);
</span><span class="cx">             devices[i].m_enabled = false;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const Vector&lt;AtomicString&gt;&amp; AVCaptureDeviceManager::validConstraintNames()
</del><ins>+bool AVCaptureDeviceManager::isSupportedFrameRate(float frameRate) const
</ins><span class="cx"> {
</span><del>-    DEPRECATED_DEFINE_STATIC_LOCAL(Vector&lt;AtomicString&gt;, constraints, ());
-    static NeverDestroyed&lt;AtomicString&gt; heightConstraint(&quot;height&quot;, AtomicString::ConstructFromLiteral);
-    static NeverDestroyed&lt;AtomicString&gt; widthConstraint(&quot;width&quot;, AtomicString::ConstructFromLiteral);
-    static NeverDestroyed&lt;AtomicString&gt; frameRateConstraint(&quot;frameRate&quot;, AtomicString::ConstructFromLiteral);
-    static NeverDestroyed&lt;AtomicString&gt; facingModeConstraint(&quot;facingMode&quot;, AtomicString::ConstructFromLiteral);
-    static NeverDestroyed&lt;AtomicString&gt; gainConstraint(&quot;gain&quot;, AtomicString::ConstructFromLiteral);
-    
-    if (!constraints.size()) {
-        constraints.insert(Width, widthConstraint);
-        constraints.insert(Height, heightConstraint);
-        constraints.insert(FrameRate, frameRateConstraint);
-        constraints.insert(FacingMode, facingModeConstraint);
-        constraints.insert(Gain, gainConstraint);
-    }
-    
-    return constraints;
</del><ins>+    // FIXME: We should use [AVCaptureConnection videoMinFrameDuration] and [AVCaptureConnection videoMaxFrameDuration],
+    // but they only work with a &quot;live&quot; AVCaptureConnection. For now, just use the default platform-independent behavior.
+    return CaptureDeviceManager::isSupportedFrameRate(frameRate);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-const Vector&lt;AtomicString&gt;&amp; AVCaptureDeviceManager::validFacingModes()
-{
-    DEPRECATED_DEFINE_STATIC_LOCAL(Vector&lt;AtomicString&gt;, modes, ());
-    
-    if (!modes.size()) {
-        modes.insert(RealtimeMediaSourceStates::User, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::User));
-        modes.insert(RealtimeMediaSourceStates::Environment, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::Environment));
-        modes.insert(RealtimeMediaSourceStates::Left, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::Left));
-        modes.insert(RealtimeMediaSourceStates::Right, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::Right));
-    }
-    
-    return modes;
-}
-
</del><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> @implementation WebCoreAVCaptureDeviceManagerObserver
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacAVVideoCaptureSourcemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (192837 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #import &quot;MediaConstraints.h&quot;
</span><span class="cx"> #import &quot;NotImplemented.h&quot;
</span><span class="cx"> #import &quot;PlatformLayer.h&quot;
</span><ins>+#import &quot;RealtimeMediaSourceCenter.h&quot;
</ins><span class="cx"> #import &quot;RealtimeMediaSourceStates.h&quot;
</span><span class="cx"> #import &lt;AVFoundation/AVFoundation.h&gt;
</span><span class="cx"> #import &lt;objc/runtime.h&gt;
</span><span class="lines">@@ -179,36 +180,39 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(constraints);
</span><span class="cx"> 
</span><del>-    const Vector&lt;AtomicString&gt;&amp; constraintNames = AVCaptureDeviceManager::validConstraintNames();
-    String widthConstraint;
-    String heightConstraint;
</del><ins>+    const RealtimeMediaSourceSupportedConstraints&amp; supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    String widthConstraintValue;
+    String heightConstraintValue;
+    String widthConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::Width);
+    String heightConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::Height);
</ins><span class="cx"> 
</span><del>-    constraints-&gt;getMandatoryConstraintValue(constraintNames[AVCaptureDeviceManager::Width], widthConstraint);
-    constraints-&gt;getMandatoryConstraintValue(constraintNames[AVCaptureDeviceManager::Height], heightConstraint);
</del><ins>+    constraints-&gt;getMandatoryConstraintValue(widthConstraintName, widthConstraintValue);
+    constraints-&gt;getMandatoryConstraintValue(heightConstraintName, heightConstraintValue);
</ins><span class="cx"> 
</span><del>-    int width = widthConstraint.toInt();
-    int height = heightConstraint.toInt();
</del><ins>+    int width = widthConstraintValue.toInt();
+    int height = heightConstraintValue.toInt();
</ins><span class="cx">     if (!width &amp;&amp; !height) {
</span><del>-        constraints-&gt;getOptionalConstraintValue(constraintNames[AVCaptureDeviceManager::Width], widthConstraint);
-        constraints-&gt;getOptionalConstraintValue(constraintNames[AVCaptureDeviceManager::Height], heightConstraint);
-        width = widthConstraint.toInt();
-        height = heightConstraint.toInt();
</del><ins>+        constraints-&gt;getOptionalConstraintValue(widthConstraintName, widthConstraintValue);
+        constraints-&gt;getOptionalConstraintValue(heightConstraintName, heightConstraintValue);
+        width = widthConstraintValue.toInt();
+        height = heightConstraintValue.toInt();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (width || height) {
</span><del>-        NSString *preset = AVCaptureDeviceManager::bestSessionPresetForVideoSize(session(), width, height);
</del><ins>+        NSString *preset = AVCaptureSessionInfo(session()).bestSessionPresetForVideoDimensions(width, height);
</ins><span class="cx">         if (!preset || ![session() canSetSessionPreset:preset])
</span><span class="cx">             return false;
</span><span class="cx">         
</span><span class="cx">         [session() setSessionPreset:preset];
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    String frameRateConstraint;
-    constraints-&gt;getMandatoryConstraintValue(constraintNames[AVCaptureDeviceManager::FrameRate], frameRateConstraint);
-    float frameRate = frameRateConstraint.toFloat();
</del><ins>+    String frameRateConstraintValue;
+    String frameRateConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::FrameRate);
+    constraints-&gt;getMandatoryConstraintValue(frameRateConstraintName, frameRateConstraintValue);
+    float frameRate = frameRateConstraintValue.toFloat();
</ins><span class="cx">     if (!frameRate) {
</span><del>-        constraints-&gt;getOptionalConstraintValue(constraintNames[AVCaptureDeviceManager::FrameRate], frameRateConstraint);
-        frameRate = frameRateConstraint.toFloat();
</del><ins>+        constraints-&gt;getOptionalConstraintValue(frameRateConstraintName, frameRateConstraintValue);
+        frameRate = frameRateConstraintValue.toFloat();
</ins><span class="cx">     }
</span><span class="cx">     if (frameRate &amp;&amp; !setFrameRateConstraint(frameRate, 0))
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacRealtimeMediaSourceCenterMaccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp (192837 => 192838)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp        2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp        2015-11-30 23:48:42 UTC (rev 192838)
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (audioConstraints) {
</span><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Audio, audioConstraints.get(), invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints.get(), nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;constraintsInvalid(invalidConstraint);
</span><span class="cx">             return;
</span><span class="lines">@@ -87,7 +87,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (videoConstraints) {
</span><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Video, videoConstraints.get(), invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints.get(), nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;constraintsInvalid(invalidConstraint);
</span><span class="cx">             return;
</span><span class="lines">@@ -109,7 +109,7 @@
</span><span class="cx">     
</span><span class="cx">     if (audioConstraints) {
</span><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Audio, audioConstraints.get(), invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints.get(), nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;failedToCreateStreamWithConstraintsError(invalidConstraint);
</span><span class="cx">             return;
</span><span class="lines">@@ -124,7 +124,7 @@
</span><span class="cx">     
</span><span class="cx">     if (videoConstraints) {
</span><span class="cx">         String invalidConstraint;
</span><del>-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Video, videoConstraints.get(), invalidConstraint);
</del><ins>+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints.get(), nullptr, invalidConstraint);
</ins><span class="cx">         if (!invalidConstraint.isEmpty()) {
</span><span class="cx">             client-&gt;failedToCreateStreamWithConstraintsError(invalidConstraint);
</span><span class="cx">             return;
</span></span></pre>
</div>
</div>

</body>
</html>