<!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>[235086] trunk</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>[MediaStream] Move capture device monitoring to WebKit
https://bugs.webkit.org/show_bug.cgi?id=188521
<rdar://problem/43251787>

Reviewed by Youenn Fablet.

Source/WebCore:

No new tests, updated fast/mediastream/device-change-event-2.html for the changes.

* Modules/mediastream/MediaDevices.cpp:
(WebCore::MediaDevices::MediaDevices): Device change listener is added in addEventListener.
(WebCore::MediaDevices::stop): Device change listener is on the user media controller.
(WebCore::MediaDevices::addEventListener): Add the device change listener only once the first
event handler is added.
* Modules/mediastream/MediaDevices.h:

* Modules/mediastream/UserMediaClient.h:
* Modules/mediastream/UserMediaController.h:
(WebCore::UserMediaController::addDeviceChangeObserver): Pass through to the client.
(WebCore::UserMediaController::removeDeviceChangeObserver): Ditto.

* platform/mediastream/CaptureDeviceManager.cpp:
(CaptureDeviceManager::deviceChanged): Notify RealtimeMediaSourceCenter.
(nextObserverToken): Deleted.
(CaptureDeviceManager::addCaptureDeviceChangedObserver): Deleted.
(CaptureDeviceManager::removeCaptureDeviceChangedObserver): Deleted.
* platform/mediastream/CaptureDeviceManager.h:

* platform/mediastream/RealtimeMediaSourceCenter.cpp:
(WebCore::RealtimeMediaSourceCenter::setDevicesChangedObserver):
(WebCore::RealtimeMediaSourceCenter::captureDevicesChanged):
(WebCore::observerMap): Deleted.
(WebCore::RealtimeMediaSourceCenter::addDevicesChangedObserver): Deleted.
(WebCore::RealtimeMediaSourceCenter::removeDevicesChangedObserver): Deleted.
* platform/mediastream/RealtimeMediaSourceCenter.h:

* platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
(WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices): Call base class.

* platform/mediastream/mac/AVCaptureDeviceManager.mm:
(WebCore::AVCaptureDeviceManager::deviceConnected): Ditto.
(WebCore::AVCaptureDeviceManager::deviceDisconnected): Ditto.

* platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp:
(WebCore::deviceHasInputStreams): Drive-by fix, check the number of buffers to see if the
device has input streams.
(WebCore::CoreAudioCaptureDeviceManager::coreAudioCaptureDevices): Use new bool parameter
added to refreshAudioCaptureDevices so we won't trigger a device change event on the first scan.
(WebCore::CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices): Add param.
(WebCore::CoreAudioCaptureDeviceManager::devicesChanged): Use new param.
* platform/mediastream/mac/CoreAudioCaptureDeviceManager.h:

* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockRealtimeMediaSourceCenter::setDevices): Don't need to call captureDevicesChanged,
it is done in the UI process.
(WebCore::MockRealtimeMediaSourceCenter::addDevice): Ditto.
(WebCore::MockRealtimeMediaSourceCenter::removeDevice): Ditto.

* testing/InternalSettings.cpp:
(WebCore::InternalSettings::setPageIsFocusedAndActive): New, used by updated test.
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit:

* UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::UserMediaPermissionRequestManagerProxy::captureDevicesChanged): Notify as appropriate.
(WebKit::UserMediaPermissionRequestManagerProxy::viewIsBecomingVisible): Change name from
viewIsBecomingVisible. Call captureDevicesChanged if a change happened when not visible.
(WebKit::UserMediaPermissionRequestManagerProxy::watchdogTimerFired): Clear m_pendingDeviceChangeEvent.
(WebKit::UserMediaPermissionRequestManagerProxy::processPregrantedRequests): Deleted.
* UIProcess/UserMediaPermissionRequestManagerProxy.h:

* UIProcess/UserMediaProcessManager.cpp:
(WebKit::UserMediaProcessManager::UserMediaProcessManager): Initialize timer.
(WebKit::UserMediaProcessManager::captureDevicesChanged): New, notify each manager.
(WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices): Cache the device list and
register device change listener the first time it is called.
* UIProcess/UserMediaProcessManager.h:

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::viewIsBecomingVisible):
(WebKit::WebPageProxy::beginMonitoringCaptureDevices):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:

* WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
(WebKit::UserMediaPermissionRequestManager::addDeviceChangeObserver): Add listener, tell page
to start monitoring device changes.
(WebKit::UserMediaPermissionRequestManager::removeDeviceChangeObserver): Remove listener.
(WebKit::UserMediaPermissionRequestManager::captureDevicesChanged): Call listeners.
* WebProcess/MediaStream/UserMediaPermissionRequestManager.h:

* WebProcess/WebCoreSupport/WebUserMediaClient.cpp:
(WebKit::WebUserMediaClient::addDeviceChangeObserver):
(WebKit::WebUserMediaClient::removeDeviceChangeObserver):
* WebProcess/WebCoreSupport/WebUserMediaClient.h:

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::captureDevicesChanged):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::addMockMediaDevice):
(WebKit::WebProcess::clearMockMediaDevices):
(WebKit::WebProcess::removeMockMediaDevice):
(WebKit::WebProcess::resetMockMediaDevices):
(WebKit::WebProcess::captureDevicesChanged):
* WebProcess/WebProcess.h:

LayoutTests:

* fast/mediastream/device-change-event-2-expected.txt: Updated.
* fast/mediastream/device-change-event-2.html: Updated.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamdevicechangeevent2expectedtxt">trunk/LayoutTests/fast/mediastream/device-change-event-2-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastmediastreamdevicechangeevent2html">trunk/LayoutTests/fast/mediastream/device-change-event-2.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaDevicescpp">trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamMediaDevicesh">trunk/Source/WebCore/Modules/mediastream/MediaDevices.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamUserMediaClienth">trunk/Source/WebCore/Modules/mediastream/UserMediaClient.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamUserMediaControllerh">trunk/Source/WebCore/Modules/mediastream/UserMediaController.h</a></li>
<li><a href="#trunkSourceWebCorepagePageh">trunk/Source/WebCore/page/Page.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamCaptureDeviceManagercpp">trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamCaptureDeviceManagerh">trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceCentercpp">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceCenterh">trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamiosAVAudioSessionCaptureDeviceManagermm">trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacAVCaptureDeviceManagermm">trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacCoreAudioCaptureDeviceManagercpp">trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreammacCoreAudioCaptureDeviceManagerh">trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeMediaSourcecpp">trunk/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp">trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitScriptswebkitmessagespy">trunk/Source/WebKit/Scripts/webkit/messages.py</a></li>
<li><a href="#trunkSourceWebKitUIProcessUserMediaPermissionRequestManagerProxycpp">trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessUserMediaPermissionRequestManagerProxyh">trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessUserMediaProcessManagercpp">trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessUserMediaProcessManagerh">trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxycpp">trunk/Source/WebKit/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxyh">trunk/Source/WebKit/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxymessagesin">trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebKitxcodeprojprojectpbxproj">trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKitWebProcessMediaStreamUserMediaPermissionRequestManagercpp">trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessMediaStreamUserMediaPermissionRequestManagerh">trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebCoreSupportWebUserMediaClientcpp">trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebCoreSupportWebUserMediaClienth">trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagecpp">trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPageh">trunk/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagemessagesin">trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/LayoutTests/ChangeLog 2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2018-08-20  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] Move capture device monitoring to WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=188521
+        <rdar://problem/43251787>
+
+        Reviewed by Youenn Fablet.
+
+        * fast/mediastream/device-change-event-2-expected.txt: Updated.
+        * fast/mediastream/device-change-event-2.html: Updated.
+
</ins><span class="cx"> 2018-08-20  Rob Buis  <rbuis@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         Throw an exception if window.open() gets passed a URL that cannot be parsed
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamdevicechangeevent2expectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/device-change-event-2-expected.txt (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/device-change-event-2-expected.txt    2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/LayoutTests/fast/mediastream/device-change-event-2-expected.txt       2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,3 +1,6 @@
</span><span class="cx"> 
</span><span class="cx"> PASS 'devicechange' event fired when device list changes 
</span><ins>+PASS 'devicechange' events fired quickly are coalesced 
+PASS 'devicechange' event is not fired when the document doesn't has focus or permission to capture 
+PASS 'devicechange' event is fired when the document doesn't has focus but has permission to capture 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastmediastreamdevicechangeevent2html"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/mediastream/device-change-event-2.html (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/mediastream/device-change-event-2.html    2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/LayoutTests/fast/mediastream/device-change-event-2.html       2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -6,8 +6,9 @@
</span><span class="cx">     <script src="../../resources/testharness.js"></script>
</span><span class="cx">     <script src="../../resources/testharnessreport.js"></script>
</span><span class="cx">     <script>
</span><del>-    let deviceIds = [];
-    promise_test(async (test) => {
</del><ins>+    let stream = null;
+    
+    let setup = async (test) => {
</ins><span class="cx">         if (!window.testRunner)
</span><span class="cx">             return Promise.reject("test requires internal API");
</span><span class="cx"> 
</span><span class="lines">@@ -14,9 +15,17 @@
</span><span class="cx">         test.add_cleanup(() => { testRunner.resetMockMediaDevices(); });
</span><span class="cx"> 
</span><span class="cx">         testRunner.setUserMediaPermission(true);
</span><ins>+        
+        stream = null;
+    }
</ins><span class="cx"> 
</span><del>-        await navigator.mediaDevices.getUserMedia({ audio:true, video:true });
</del><ins>+    promise_test(async (test) => {
+    
+        await setup(test);
</ins><span class="cx"> 
</span><ins>+        await navigator.mediaDevices.getUserMedia({ audio:true, video:true })
+            .then(s => stream = s)
+
</ins><span class="cx">         let devices = await navigator.mediaDevices.enumerateDevices();
</span><span class="cx"> 
</span><span class="cx">         assert_true(!!devices.length, "check there are some devices");
</span><span class="lines">@@ -29,7 +38,7 @@
</span><span class="cx">         await new Promise((resolve, reject) => {
</span><span class="cx">             navigator.mediaDevices.ondevicechange = resolve;
</span><span class="cx">             setTimeout(() => {
</span><del>-                console.log("event 1 taking a long time");
</del><ins>+                console.log("event 1 took too long");
</ins><span class="cx">                 resolve();
</span><span class="cx">             }, 5000);
</span><span class="cx">             testRunner.addMockCameraDevice("id1", "my camera");
</span><span class="lines">@@ -41,7 +50,7 @@
</span><span class="cx">         await new Promise((resolve, reject) => {
</span><span class="cx">             navigator.mediaDevices.ondevicechange = resolve;
</span><span class="cx">             setTimeout(() => {
</span><del>-                console.log("event 2 taking a long time");
</del><ins>+                console.log("event 2 took too long");
</ins><span class="cx">                 resolve();
</span><span class="cx">             }, 5000);
</span><span class="cx">             testRunner.addMockMicrophoneDevice("id2", "my mic");
</span><span class="lines">@@ -51,6 +60,102 @@
</span><span class="cx">         assert_equals(devices[0].label, "my mic");
</span><span class="cx"> 
</span><span class="cx">     }, "'devicechange' event fired when device list changes");
</span><ins>+
+    promise_test(async (test) => {
+
+        await setup(test);
+
+        let eventCount = 0;
+        await new Promise((resolve, reject) => {
+            navigator.mediaDevices.ondevicechange = (evt) => {
+                ++eventCount;
+                setTimeout(() => {
+                    resolve();
+                }, 500);
+            }
+
+            setTimeout(() => {
+                console.log("navigator.mediaDevices.ondevicechange took too long");
+                resolve();
+            }, 4000);
+
+            testRunner.addMockMicrophoneDevice("id4", "microphone 3");
+            testRunner.addMockMicrophoneDevice("id5", "microphone 4");
+        });
+        assert_equals(eventCount, 1, "one event fired");
+
+    }, "'devicechange' events fired quickly are coalesced");
+
+
+    promise_test(async (test) => {
+
+        await setup(test);
+
+        await new Promise((resolve, reject) => {
+            let timeout = setTimeout(() => {
+                console.log("window.onblur took too long");
+                resolve();
+            }, 5000);
+
+            window.onblur = () => {
+                clearTimeout(timeout);
+                resolve();
+            }
+        
+            internals.setPageIsFocusedAndActive(false);
+        });
+
+        await new Promise((resolve, reject) => {
+            assert_false(document.hasFocus(), "document.hasFocus()");
+
+            navigator.mediaDevices.ondevicechange = () => {
+                assert_true(document.hasFocus(), "devicechange should only fire when the document is focused and active");
+                resolve();
+            };
+
+            setTimeout(() => {
+                internals.setPageIsFocusedAndActive(true);
+            }, 200);
+
+            testRunner.addMockMicrophoneDevice("id3", "microphone 2");
+        });
+
+    }, "'devicechange' event is not fired when the document doesn't has focus or permission to capture");
+
+    promise_test(async (test) => {
+
+        await setup(test);
+
+        await navigator.mediaDevices.getUserMedia({ audio:true, video:true })
+            .then(s => stream = s);
+
+        await new Promise((resolve, reject) => {
+            let timeout = setTimeout(() => {
+                console.log("window.onblur took too long");
+                resolve();
+            }, 5000);
+
+            window.onblur = () => {
+                clearTimeout(timeout);
+                resolve();
+            }
+        
+            internals.setPageIsFocusedAndActive(false);
+        });
+
+        await new Promise((resolve, reject) => {
+            assert_false(document.hasFocus(), "document.hasFocus()");
+
+            navigator.mediaDevices.ondevicechange = () => {
+                assert_false(document.hasFocus(), "devicechange should fire when the document is not focused but can capture");
+                resolve();
+            };
+
+            testRunner.addMockMicrophoneDevice("id3", "microphone 2");
+        });
+
+    }, "'devicechange' event is fired when the document doesn't has focus but has permission to capture");
+
</ins><span class="cx">     </script>
</span><span class="cx"> </head>
</span><span class="cx"> <body>
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/ChangeLog      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,3 +1,67 @@
</span><ins>+2018-08-20  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] Move capture device monitoring to WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=188521
+        <rdar://problem/43251787>
+
+        Reviewed by Youenn Fablet.
+
+        No new tests, updated fast/mediastream/device-change-event-2.html for the changes.
+
+        * Modules/mediastream/MediaDevices.cpp:
+        (WebCore::MediaDevices::MediaDevices): Device change listener is added in addEventListener.
+        (WebCore::MediaDevices::stop): Device change listener is on the user media controller.
+        (WebCore::MediaDevices::addEventListener): Add the device change listener only once the first
+        event handler is added.
+        * Modules/mediastream/MediaDevices.h:
+
+        * Modules/mediastream/UserMediaClient.h:
+        * Modules/mediastream/UserMediaController.h:
+        (WebCore::UserMediaController::addDeviceChangeObserver): Pass through to the client.
+        (WebCore::UserMediaController::removeDeviceChangeObserver): Ditto.
+
+        * platform/mediastream/CaptureDeviceManager.cpp:
+        (CaptureDeviceManager::deviceChanged): Notify RealtimeMediaSourceCenter.
+        (nextObserverToken): Deleted.
+        (CaptureDeviceManager::addCaptureDeviceChangedObserver): Deleted.
+        (CaptureDeviceManager::removeCaptureDeviceChangedObserver): Deleted.
+        * platform/mediastream/CaptureDeviceManager.h:
+
+        * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+        (WebCore::RealtimeMediaSourceCenter::setDevicesChangedObserver):
+        (WebCore::RealtimeMediaSourceCenter::captureDevicesChanged):
+        (WebCore::observerMap): Deleted.
+        (WebCore::RealtimeMediaSourceCenter::addDevicesChangedObserver): Deleted.
+        (WebCore::RealtimeMediaSourceCenter::removeDevicesChangedObserver): Deleted.
+        * platform/mediastream/RealtimeMediaSourceCenter.h:
+
+        * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
+        (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices): Call base class.
+
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::AVCaptureDeviceManager::deviceConnected): Ditto.
+        (WebCore::AVCaptureDeviceManager::deviceDisconnected): Ditto.
+
+        * platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp:
+        (WebCore::deviceHasInputStreams): Drive-by fix, check the number of buffers to see if the
+        device has input streams.
+        (WebCore::CoreAudioCaptureDeviceManager::coreAudioCaptureDevices): Use new bool parameter
+        added to refreshAudioCaptureDevices so we won't trigger a device change event on the first scan.
+        (WebCore::CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices): Add param.
+        (WebCore::CoreAudioCaptureDeviceManager::devicesChanged): Use new param.
+        * platform/mediastream/mac/CoreAudioCaptureDeviceManager.h:
+
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockRealtimeMediaSourceCenter::setDevices): Don't need to call captureDevicesChanged,
+        it is done in the UI process.
+        (WebCore::MockRealtimeMediaSourceCenter::addDevice): Ditto.
+        (WebCore::MockRealtimeMediaSourceCenter::removeDevice): Ditto.
+
+        * testing/InternalSettings.cpp:
+        (WebCore::InternalSettings::setPageIsFocusedAndActive): New, used by updated test.
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
</ins><span class="cx"> 2018-08-20  Rob Buis  <rbuis@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         Throw an exception if window.open() gets passed a URL that cannot be parsed
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaDevicescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp        2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp   2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2015 Ericsson AB. All rights reserved.
</span><del>- * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2018 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">@@ -41,6 +41,7 @@
</span><span class="cx"> #include "MediaTrackSupportedConstraints.h"
</span><span class="cx"> #include "RealtimeMediaSourceSettings.h"
</span><span class="cx"> #include "RuntimeEnabledFeatures.h"
</span><ins>+#include "UserMediaController.h"
</ins><span class="cx"> #include "UserMediaRequest.h"
</span><span class="cx"> #include <wtf/RandomNumber.h>
</span><span class="cx"> 
</span><span class="lines">@@ -51,17 +52,6 @@
</span><span class="cx">     , m_scheduledEventTimer(*this, &MediaDevices::scheduledEventTimerFired)
</span><span class="cx">     , m_eventNames(eventNames())
</span><span class="cx"> {
</span><del>-    m_deviceChangedToken = RealtimeMediaSourceCenter::singleton().addDevicesChangedObserver([weakThis = makeWeakPtr(*this), this]() {
-
-        if (!weakThis)
-            return;
-
-        // FIXME: We should only dispatch an event if the user has been granted access to the type of
-        // device that was added or removed.
-        if (!m_scheduledEventTimer.isActive())
-            m_scheduledEventTimer.startOneShot(Seconds(randomNumber() / 2));
-    });
-
</del><span class="cx">     suspendIfNeeded();
</span><span class="cx"> 
</span><span class="cx">     static_assert(static_cast<size_t>(MediaDevices::DisplayCaptureSurfaceType::Monitor) == static_cast<size_t>(RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor), "MediaDevices::DisplayCaptureSurfaceType::Monitor is not equal to RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor as expected");
</span><span class="lines">@@ -74,8 +64,12 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaDevices::stop()
</span><span class="cx"> {
</span><del>-    if (m_deviceChangedToken)
-        RealtimeMediaSourceCenter::singleton().removeDevicesChangedObserver(m_deviceChangedToken);
</del><ins>+    if (m_deviceChangeToken) {
+        auto* document = this->document();
+        auto* controller = document ? UserMediaController::from(document->page()) : nullptr;
+        if (document && controller)
+            controller->removeDeviceChangeObserver(m_deviceChangeToken);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Ref<MediaDevices> MediaDevices::create(Document& document)
</span><span class="lines">@@ -181,6 +175,27 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool MediaDevices::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
+{
+    if (!m_listeningForDeviceChanges && eventType == eventNames().devicechangeEvent) {
+        auto* document = this->document();
+        auto* controller = document ? UserMediaController::from(document->page()) : nullptr;
+        if (document && controller) {
+            m_listeningForDeviceChanges = true;
+
+            m_deviceChangeToken = controller->addDeviceChangeObserver([weakThis = makeWeakPtr(*this), this]() {
+
+                if (!weakThis || m_scheduledEventTimer.isActive())
+                    return;
+
+                m_scheduledEventTimer.startOneShot(Seconds(randomNumber() / 2));
+            });
+        }
+    }
+
+    return EventTargetWithInlineData::addEventListener(eventType, WTFMove(listener), options);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamMediaDevicesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/MediaDevices.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/MediaDevices.h  2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/Modules/mediastream/MediaDevices.h     2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2015 Ericsson AB. All rights reserved.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 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">@@ -41,11 +41,11 @@
</span><span class="cx"> #include "MediaTrackConstraints.h"
</span><span class="cx"> #include "RealtimeMediaSourceCenter.h"
</span><span class="cx"> #include "Timer.h"
</span><ins>+#include "UserMediaClient.h"
</ins><span class="cx"> #include <wtf/WeakPtr.h>
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class Document;
</del><span class="cx"> class MediaDeviceInfo;
</span><span class="cx"> class MediaStream;
</span><span class="cx"> 
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx">     explicit MediaDevices(Document&);
</span><span class="cx"> 
</span><span class="cx">     void scheduledEventTimerFired();
</span><ins>+    bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
</ins><span class="cx"> 
</span><span class="cx">     friend class JSMediaDevicesOwner;
</span><span class="cx"> 
</span><span class="lines">@@ -101,8 +102,9 @@
</span><span class="cx">     void derefEventTarget() final { deref(); }
</span><span class="cx"> 
</span><span class="cx">     Timer m_scheduledEventTimer;
</span><del>-    RealtimeMediaSourceCenter::DevicesChangedObserverToken m_deviceChangedToken;
</del><ins>+    UserMediaClient::DeviceChangeObserverToken m_deviceChangeToken;
</ins><span class="cx">     const EventNames& m_eventNames; // Need to cache this so we can use it from GC threads.
</span><ins>+    bool m_listeningForDeviceChanges { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamUserMediaClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaClient.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/UserMediaClient.h       2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaClient.h  2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2011 Ericsson AB. All rights reserved.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,6 +33,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><ins>+#include <wtf/ObjectIdentifier.h>
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class MediaDevicesEnumerationRequest;
</span><span class="lines">@@ -49,6 +51,11 @@
</span><span class="cx">     virtual void enumerateMediaDevices(MediaDevicesEnumerationRequest&) = 0;
</span><span class="cx">     virtual void cancelMediaDevicesEnumerationRequest(MediaDevicesEnumerationRequest&) = 0;
</span><span class="cx"> 
</span><ins>+    enum DeviceChangeObserverTokenType { };
+    using DeviceChangeObserverToken = ObjectIdentifier<DeviceChangeObserverTokenType>;
+    virtual DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&) = 0;
+    virtual void removeDeviceChangeObserver(DeviceChangeObserverToken) = 0;
+
</ins><span class="cx"> protected:
</span><span class="cx">     virtual ~UserMediaClient() = default;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamUserMediaControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaController.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/UserMediaController.h   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaController.h      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 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">@@ -48,6 +48,9 @@
</span><span class="cx">     void enumerateMediaDevices(MediaDevicesEnumerationRequest&);
</span><span class="cx">     void cancelMediaDevicesEnumerationRequest(MediaDevicesEnumerationRequest&);
</span><span class="cx"> 
</span><ins>+    UserMediaClient::DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&);
+    void removeDeviceChangeObserver(UserMediaClient::DeviceChangeObserverToken);
+
</ins><span class="cx">     WEBCORE_EXPORT static const char* supplementName();
</span><span class="cx">     static UserMediaController* from(Page* page) { return static_cast<UserMediaController*>(Supplement<Page>::from(page, supplementName())); }
</span><span class="cx"> 
</span><span class="lines">@@ -75,6 +78,16 @@
</span><span class="cx">     m_client->cancelMediaDevicesEnumerationRequest(request);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline UserMediaClient::DeviceChangeObserverToken UserMediaController::addDeviceChangeObserver(WTF::Function<void()>&& observer)
+{
+    return m_client->addDeviceChangeObserver(WTFMove(observer));
+}
+
+inline void UserMediaController::removeDeviceChangeObserver(UserMediaClient::DeviceChangeObserverToken token)
+{
+    m_client->removeDeviceChangeObserver(token);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCorepagePageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.h 2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/page/Page.h    2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -434,8 +434,8 @@
</span><span class="cx">     void setIsRestoringCachedPage(bool value) { m_isRestoringCachedPage = value; }
</span><span class="cx">     bool isRestoringCachedPage() const { return m_isRestoringCachedPage; }
</span><span class="cx"> 
</span><del>-    void addActivityStateChangeObserver(ActivityStateChangeObserver&);
-    void removeActivityStateChangeObserver(ActivityStateChangeObserver&);
</del><ins>+    WEBCORE_EXPORT void addActivityStateChangeObserver(ActivityStateChangeObserver&);
+    WEBCORE_EXPORT void removeActivityStateChangeObserver(ActivityStateChangeObserver&);
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT void suspendScriptedAnimations();
</span><span class="cx">     WEBCORE_EXPORT void resumeScriptedAnimations();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamCaptureDeviceManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp       2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp  2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2018 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">@@ -50,24 +50,14 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static CaptureDeviceManager::ObserverToken nextObserverToken()
</del><ins>+void CaptureDeviceManager::deviceChanged()
</ins><span class="cx"> {
</span><del>-    static CaptureDeviceManager::ObserverToken nextToken = 0;
-    return ++nextToken;
-}
</del><ins>+    callOnMainThread([weakThis = makeWeakPtr(*this)] {
+        if (!weakThis)
+            return;
</ins><span class="cx"> 
</span><del>-CaptureDeviceManager::ObserverToken CaptureDeviceManager::addCaptureDeviceChangedObserver(CaptureDeviceChangedCallback&& observer)
-{
-    auto token = nextObserverToken();
-    m_observers.set(token, WTFMove(observer));
-    return token;
</del><ins>+        RealtimeMediaSourceCenter::singleton().captureDevicesChanged();
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CaptureDeviceManager::removeCaptureDeviceChangedObserver(ObserverToken token)
-{
-    ASSERT(m_observers.contains(token));
-    m_observers.remove(token);
-}
-
-
</del><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamCaptureDeviceManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h 2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h    2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2018 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">@@ -29,16 +29,12 @@
</span><span class="cx"> 
</span><span class="cx"> #include "CaptureDevice.h"
</span><span class="cx"> #include "RealtimeMediaSource.h"
</span><ins>+#include <wtf/WeakPtr.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class CaptureDeviceManager {
</del><ins>+class CaptureDeviceManager : public CanMakeWeakPtr<CaptureDeviceManager> {
</ins><span class="cx"> public:
</span><del>-    using CaptureDeviceChangedCallback = WTF::Function<void()>;
-    using ObserverToken = uint32_t;
-    virtual ObserverToken addCaptureDeviceChangedObserver(CaptureDeviceChangedCallback&&);
-    virtual void removeCaptureDeviceChangedObserver(ObserverToken);
-
</del><span class="cx">     virtual const Vector<CaptureDevice>& captureDevices() = 0;
</span><span class="cx">     virtual std::optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&) { return std::nullopt; }
</span><span class="cx"> 
</span><span class="lines">@@ -45,7 +41,7 @@
</span><span class="cx"> protected:
</span><span class="cx">     virtual ~CaptureDeviceManager();
</span><span class="cx">     CaptureDevice captureDeviceFromPersistentID(const String& captureDeviceID);
</span><del>-    HashMap<ObserverToken, CaptureDeviceChangedCallback> m_observers;
</del><ins>+    void deviceChanged();
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp        2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp   2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -246,10 +246,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         distance = std::min(distance, constraintDistance);
</span><del>-        if (widthConstraint->isMandatory()) {
-            auto range = capabilities.width();
-            width = widthConstraint->valueForCapabilityRange(size().width(), range.rangeMin().asInt, range.rangeMax().asInt);
-        }
</del><ins>+        auto range = capabilities.width();
+        width = widthConstraint->valueForCapabilityRange(size().width(), range.rangeMin().asInt, range.rangeMax().asInt);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     std::optional<int> height;
</span><span class="lines">@@ -261,10 +259,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         distance = std::min(distance, constraintDistance);
</span><del>-        if (heightConstraint->isMandatory()) {
-            auto range = capabilities.height();
-            height = heightConstraint->valueForCapabilityRange(size().height(), range.rangeMin().asInt, range.rangeMax().asInt);
-        }
</del><ins>+        auto range = capabilities.height();
+        height = heightConstraint->valueForCapabilityRange(size().height(), range.rangeMin().asInt, range.rangeMax().asInt);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     std::optional<double> frameRate;
</span><span class="lines">@@ -276,10 +272,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         distance = std::min(distance, constraintDistance);
</span><del>-        if (frameRateConstraint->isMandatory()) {
-            auto range = capabilities.frameRate();
-            frameRate = frameRateConstraint->valueForCapabilityRange(this->frameRate(), range.rangeMin().asDouble, range.rangeMax().asDouble);
-        }
</del><ins>+        auto range = capabilities.frameRate();
+        frameRate = frameRateConstraint->valueForCapabilityRange(this->frameRate(), range.rangeMin().asDouble, range.rangeMax().asDouble);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Each of the non-null values is supported individually, see if they all can be applied at the same time.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceCentercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp  2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp     2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2011 Ericsson AB. All rights reserved.
</span><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2018 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">@@ -53,12 +53,6 @@
</span><span class="cx">     return override;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static HashMap<unsigned, std::function<void()>>& observerMap()
-{
-    static NeverDestroyed<HashMap<unsigned, std::function<void()>>> map;
-    return map;
-}
-
</del><span class="cx"> RealtimeMediaSourceCenter& RealtimeMediaSourceCenter::singleton()
</span><span class="cx"> {
</span><span class="cx">     RealtimeMediaSourceCenter* override = mediaStreamCenterOverride();
</span><span class="lines">@@ -199,25 +193,18 @@
</span><span class="cx">     return Exception { NotFoundError };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RealtimeMediaSourceCenter::DevicesChangedObserverToken RealtimeMediaSourceCenter::addDevicesChangedObserver(std::function<void()>&& observer)
</del><ins>+void RealtimeMediaSourceCenter::setDevicesChangedObserver(std::function<void()>&& observer)
</ins><span class="cx"> {
</span><del>-    static DevicesChangedObserverToken nextToken = 0;
-    observerMap().set(++nextToken, WTFMove(observer));
-    return nextToken;
</del><ins>+    ASSERT(isMainThread());
+    ASSERT(!m_deviceChangedObserver);
+    m_deviceChangedObserver = WTFMove(observer);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RealtimeMediaSourceCenter::removeDevicesChangedObserver(DevicesChangedObserverToken token)
-{
-    bool wasRemoved = observerMap().remove(token);
-    ASSERT_UNUSED(wasRemoved, wasRemoved);
-}
-
</del><span class="cx"> void RealtimeMediaSourceCenter::captureDevicesChanged()
</span><span class="cx"> {
</span><del>-    // Copy the hash map because the observer callback may call back in and modify the map.
-    auto callbacks = observerMap();
-    for (auto& it : callbacks)
-        it.value();
</del><ins>+    ASSERT(isMainThread());
+    if (m_deviceChangedObserver)
+        m_deviceChangedObserver();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RealtimeMediaSourceCenter::validateRequestConstraints(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamRealtimeMediaSourceCenterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h    2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h       2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2011 Ericsson AB. All rights reserved.
</span><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><del>- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2018 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">@@ -85,22 +85,22 @@
</span><span class="cx">     WEBCORE_EXPORT CaptureDevice captureDeviceWithUniqueID(const String& id, const String& hashSalt);
</span><span class="cx">     WEBCORE_EXPORT ExceptionOr<void> setDeviceEnabled(const String&, bool);
</span><span class="cx"> 
</span><del>-    using DevicesChangedObserverToken = unsigned;
-    DevicesChangedObserverToken addDevicesChangedObserver(std::function<void()>&&);
-    void removeDevicesChangedObserver(DevicesChangedObserverToken);
</del><ins>+    WEBCORE_EXPORT void setDevicesChangedObserver(std::function<void()>&&);
</ins><span class="cx"> 
</span><span class="cx">     void setVideoCapturePageState(bool, bool);
</span><span class="cx"> 
</span><ins>+    void captureDevicesChanged();
+
</ins><span class="cx"> protected:
</span><span class="cx">     RealtimeMediaSourceCenter();
</span><span class="cx"> 
</span><del>-    void captureDevicesChanged();
-
</del><span class="cx">     static RealtimeMediaSourceCenter& platformCenter();
</span><span class="cx">     RealtimeMediaSourceSupportedConstraints m_supportedConstraints;
</span><span class="cx"> 
</span><span class="cx">     CaptureDeviceManager* m_audioCaptureDeviceManager { nullptr };
</span><span class="cx">     CaptureDeviceManager* m_videoCaptureDeviceManager { nullptr };
</span><ins>+
+    WTF::Function<void()> m_deviceChangedObserver;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamiosAVAudioSessionCaptureDeviceManagermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm      2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm 2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2017-2018 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">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM) && PLATFORM(IOS)
</span><span class="cx"> 
</span><span class="cx"> #include "AVAudioSessionCaptureDevice.h"
</span><ins>+#include "RealtimeMediaSourceCenter.h"
</ins><span class="cx"> #include <AVFoundation/AVAudioSession.h>
</span><span class="cx"> #include <wtf/SoftLinking.h>
</span><span class="cx"> #include <wtf/Vector.h>
</span><span class="lines">@@ -141,8 +142,7 @@
</span><span class="cx">     m_audioSessionCaptureDevices = WTFMove(newAudioDevices);
</span><span class="cx">     m_devices = WTFMove(newDevices);
</span><span class="cx"> 
</span><del>-    for (auto& observer : m_observers.values())
-        observer();
</del><ins>+    deviceChanged();
</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 (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm  2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm     2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2018 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">@@ -179,9 +179,7 @@
</span><span class="cx"> void AVCaptureDeviceManager::deviceConnected()
</span><span class="cx"> {
</span><span class="cx">     refreshCaptureDevices();
</span><del>-
-    for (auto& observer : m_observers.values())
-        observer();
</del><ins>+    deviceChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void AVCaptureDeviceManager::deviceDisconnected(AVCaptureDeviceTypedef* device)
</span><span class="lines">@@ -200,8 +198,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    for (auto& observer : m_observers.values())
-        observer();
</del><ins>+    deviceChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacCoreAudioCaptureDeviceManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp  2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.cpp     2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2017-2018 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">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "CoreAudioCaptureDevice.h"
</span><span class="cx"> #include "Logging.h"
</span><ins>+#include "RealtimeMediaSourceCenter.h"
</ins><span class="cx"> #include <AudioUnit/AudioUnit.h>
</span><span class="cx"> #include <CoreMedia/CMSync.h>
</span><span class="cx"> #include <wtf/Assertions.h>
</span><span class="lines">@@ -64,10 +65,17 @@
</span><span class="cx"> static bool deviceHasInputStreams(AudioObjectID deviceID)
</span><span class="cx"> {
</span><span class="cx">     UInt32 dataSize = 0;
</span><del>-    AudioObjectPropertyAddress address = { kAudioDevicePropertyStreams, kAudioDevicePropertyScopeInput, kAudioObjectPropertyElementMaster };
</del><ins>+    AudioObjectPropertyAddress address = { kAudioDevicePropertyStreamConfiguration, kAudioDevicePropertyScopeInput, kAudioObjectPropertyElementMaster };
</ins><span class="cx">     auto err = AudioObjectGetPropertyDataSize(deviceID, &address, 0, nullptr, &dataSize);
</span><span class="cx"> 
</span><del>-    return !err && dataSize;
</del><ins>+    if (err || !dataSize)
+        return false;
+
+    auto bufferList = std::unique_ptr<AudioBufferList>((AudioBufferList*) ::operator new (dataSize));
+    memset(bufferList.get(), 0, dataSize);
+    err = AudioObjectGetPropertyData(deviceID, &address, 0, nullptr, &dataSize, bufferList.get());
+
+    return !err && bufferList->mNumberBuffers;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static bool isValidCaptureDevice(const CoreAudioCaptureDevice& device)
</span><span class="lines">@@ -81,7 +89,7 @@
</span><span class="cx">     static bool initialized;
</span><span class="cx">     if (!initialized) {
</span><span class="cx">         initialized = true;
</span><del>-        refreshAudioCaptureDevices();
</del><ins>+        refreshAudioCaptureDevices(DoNotNotify);
</ins><span class="cx"> 
</span><span class="cx">         AudioObjectPropertyAddress address = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
</span><span class="cx">         auto err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &address, devicesChanged, this);
</span><span class="lines">@@ -102,7 +110,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-void CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices()
</del><ins>+void CoreAudioCaptureDeviceManager::refreshAudioCaptureDevices(NotifyIfDevicesHaveChanged notify)
</ins><span class="cx"> {
</span><span class="cx">     AudioObjectPropertyAddress address = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
</span><span class="cx">     UInt32 dataSize = 0;
</span><span class="lines">@@ -156,13 +164,13 @@
</span><span class="cx">         m_devices.append(captureDevice);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    for (auto& observer : m_observers.values())
-        observer();
</del><ins>+    if (notify == Notify)
+        deviceChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> OSStatus CoreAudioCaptureDeviceManager::devicesChanged(AudioObjectID, UInt32, const AudioObjectPropertyAddress*, void* userData)
</span><span class="cx"> {
</span><del>-    static_cast<CoreAudioCaptureDeviceManager*>(userData)->refreshAudioCaptureDevices();
</del><ins>+    static_cast<CoreAudioCaptureDeviceManager*>(userData)->refreshAudioCaptureDevices(Notify);
</ins><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreammacCoreAudioCaptureDeviceManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h    2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mediastream/mac/CoreAudioCaptureDeviceManager.h       2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2017-2018 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">@@ -55,7 +55,8 @@
</span><span class="cx">     static OSStatus devicesChanged(AudioObjectID, UInt32, const AudioObjectPropertyAddress*, void*);
</span><span class="cx">     Vector<CoreAudioCaptureDevice>& coreAudioCaptureDevices();
</span><span class="cx"> 
</span><del>-    void refreshAudioCaptureDevices();
</del><ins>+    enum NotifyIfDevicesHaveChanged { Notify, DoNotNotify };
+    void refreshAudioCaptureDevices(NotifyIfDevicesHaveChanged);
</ins><span class="cx"> 
</span><span class="cx">     Vector<CaptureDevice> m_devices;
</span><span class="cx">     Vector<CoreAudioCaptureDevice> m_coreAudioCaptureDevices;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSource.cpp      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -97,6 +97,7 @@
</span><span class="cx"> void MockRealtimeMediaSource::resetDevices()
</span><span class="cx"> {
</span><span class="cx">     setDevices(defaultDevices());
</span><ins>+    RealtimeMediaSourceCenter::singleton().captureDevicesChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockRealtimeMediaSource::setDevices(Vector<MockMediaDevice>&& newMockDevices)
</span><span class="lines">@@ -115,6 +116,7 @@
</span><span class="cx">         map.add(device.persistentId, device);
</span><span class="cx">         createCaptureDevice(device);
</span><span class="cx">     }
</span><ins>+    RealtimeMediaSourceCenter::singleton().captureDevicesChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockRealtimeMediaSource::addDevice(const MockMediaDevice& device)
</span><span class="lines">@@ -122,6 +124,7 @@
</span><span class="cx">     devices().append(device);
</span><span class="cx">     deviceMap().set(device.persistentId, device);
</span><span class="cx">     createCaptureDevice(device);
</span><ins>+    RealtimeMediaSourceCenter::singleton().captureDevicesChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockRealtimeMediaSource::removeDevice(const String& persistentId)
</span><span class="lines">@@ -140,6 +143,7 @@
</span><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     map.remove(iterator);
</span><ins>+    RealtimeMediaSourceCenter::singleton().captureDevicesChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> std::optional<CaptureDevice> MockRealtimeMediaSource::captureDeviceWithPersistentID(CaptureDevice::DeviceType type, const String& id)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp     2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2013 Google Inc. All rights reserved.
</span><del>- * Copyright (C) 2013 Apple Inc.  All rights reserved.
</del><ins>+ * Copyright (C) 2013-2018 Apple Inc.  All rights reserved.
</ins><span class="cx">  * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -55,19 +55,16 @@
</span><span class="cx"> void MockRealtimeMediaSourceCenter::setDevices(Vector<MockMediaDevice>&& newMockDevices)
</span><span class="cx"> {
</span><span class="cx">     MockRealtimeMediaSource::setDevices(WTFMove(newMockDevices));
</span><del>-    singleton().captureDevicesChanged();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockRealtimeMediaSourceCenter::addDevice(const MockMediaDevice& device)
</span><span class="cx"> {
</span><span class="cx">     MockRealtimeMediaSource::addDevice(device);
</span><del>-    singleton().captureDevicesChanged();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MockRealtimeMediaSourceCenter::removeDevice(const String& persistentId)
</span><span class="cx"> {
</span><span class="cx">     MockRealtimeMediaSource::removeDevice(persistentId);
</span><del>-    singleton().captureDevicesChanged();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp       2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/testing/Internals.cpp  2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "AXObjectCache.h"
</span><span class="cx"> #include "ActiveDOMCallbackMicrotask.h"
</span><ins>+#include "ActivityState.h"
</ins><span class="cx"> #include "AnimationTimeline.h"
</span><span class="cx"> #include "ApplicationCacheStorage.h"
</span><span class="cx"> #include "AudioSession.h"
</span><span class="lines">@@ -4345,6 +4346,22 @@
</span><span class="cx">     page.setActivityState(state);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Internals::setPageIsFocusedAndActive(bool isFocusedAndActive)
+{
+    auto* document = contextDocument();
+    if (!document || !document->page())
+        return;
+    auto& page = *document->page();
+    auto state = page.activityState();
+
+    if (!isFocusedAndActive)
+        state -= { ActivityState::IsFocused, ActivityState::WindowIsActive };
+    else
+        state |= { ActivityState::IsFocused, ActivityState::WindowIsActive };
+
+    page.setActivityState(state);
+}
+
</ins><span class="cx"> #if ENABLE(WEB_RTC)
</span><span class="cx"> void Internals::setH264HardwareEncoderAllowed(bool allowed)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h 2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/testing/Internals.h    2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -645,7 +645,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void setPageVisibility(bool isVisible);
</span><ins>+    void setPageIsFocusedAndActive(bool);
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> #if ENABLE(WEB_RTC)
</span><span class="cx">     void setH264HardwareEncoderAllowed(bool allowed);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl       2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebCore/testing/Internals.idl  2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -604,6 +604,7 @@
</span><span class="cx">     [Conditional=WEBGL] void failNextGPUStatusCheck(WebGLRenderingContext context);
</span><span class="cx"> 
</span><span class="cx">     void setPageVisibility(boolean isVisible);
</span><ins>+    void setPageIsFocusedAndActive(boolean isFocused);
</ins><span class="cx"> 
</span><span class="cx">     [Conditional=WEB_RTC] void setH264HardwareEncoderAllowed(boolean allowed);
</span><span class="cx">     [Conditional=WEB_RTC] void applyRotationForOutgoingVideoSources(RTCPeerConnection connection);
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/ChangeLog       2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,3 +1,57 @@
</span><ins>+2018-08-20  Eric Carlson  <eric.carlson@apple.com>
+
+        [MediaStream] Move capture device monitoring to WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=188521
+        <rdar://problem/43251787>
+
+        Reviewed by Youenn Fablet.
+
+        * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+        (WebKit::UserMediaPermissionRequestManagerProxy::captureDevicesChanged): Notify as appropriate.
+        (WebKit::UserMediaPermissionRequestManagerProxy::viewIsBecomingVisible): Change name from
+        viewIsBecomingVisible. Call captureDevicesChanged if a change happened when not visible.
+        (WebKit::UserMediaPermissionRequestManagerProxy::watchdogTimerFired): Clear m_pendingDeviceChangeEvent.
+        (WebKit::UserMediaPermissionRequestManagerProxy::processPregrantedRequests): Deleted.
+        * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+
+        * UIProcess/UserMediaProcessManager.cpp:
+        (WebKit::UserMediaProcessManager::UserMediaProcessManager): Initialize timer.
+        (WebKit::UserMediaProcessManager::captureDevicesChanged): New, notify each manager.
+        (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices): Cache the device list and 
+        register device change listener the first time it is called.
+        * UIProcess/UserMediaProcessManager.h:
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::viewIsBecomingVisible):
+        (WebKit::WebPageProxy::beginMonitoringCaptureDevices):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+
+        * WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
+        (WebKit::UserMediaPermissionRequestManager::addDeviceChangeObserver): Add listener, tell page
+        to start monitoring device changes.
+        (WebKit::UserMediaPermissionRequestManager::removeDeviceChangeObserver): Remove listener.
+        (WebKit::UserMediaPermissionRequestManager::captureDevicesChanged): Call listeners.
+        * WebProcess/MediaStream/UserMediaPermissionRequestManager.h:
+
+        * WebProcess/WebCoreSupport/WebUserMediaClient.cpp:
+        (WebKit::WebUserMediaClient::addDeviceChangeObserver):
+        (WebKit::WebUserMediaClient::removeDeviceChangeObserver):
+        * WebProcess/WebCoreSupport/WebUserMediaClient.h:
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::captureDevicesChanged):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::addMockMediaDevice):
+        (WebKit::WebProcess::clearMockMediaDevices):
+        (WebKit::WebProcess::removeMockMediaDevice):
+        (WebKit::WebProcess::resetMockMediaDevices):
+        (WebKit::WebProcess::captureDevicesChanged):
+        * WebProcess/WebProcess.h:
+
</ins><span class="cx"> 2018-08-20  Carlos Garcia Campos  <cgarcia@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         Unreviewed. Fix GTK/WPE cookie API tests after r234396.
</span></span></pre></div>
<a id="trunkSourceWebKitScriptswebkitmessagespy"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Scripts/webkit/messages.py   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -419,6 +419,7 @@
</span><span class="cx">         'WebCore::SelectionRect': ['"EditorState.h"'],
</span><span class="cx">         'WebKit::ActivityStateChangeID': ['"DrawingAreaInfo.h"'],
</span><span class="cx">         'WebKit::BackForwardListItemState': ['"SessionState.h"'],
</span><ins>+        'WebKit::DeviceAccessState': ['"UserMediaPermissionRequestManager.h"'],
</ins><span class="cx">         'WebKit::LayerHostingMode': ['"LayerTreeContext.h"'],
</span><span class="cx">         'WebKit::PageState': ['"SessionState.h"'],
</span><span class="cx">         'WebKit::WebGestureEvent': ['"WebEvent.h"'],
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessUserMediaPermissionRequestManagerProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp 2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp    2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2014 Igalia S.L.
</span><del>- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -22,6 +22,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "APISecurityOrigin.h"
</span><span class="cx"> #include "APIUIClient.h"
</span><ins>+#include "UserMediaPermissionRequestManager.h"
</ins><span class="cx"> #include "UserMediaProcessManager.h"
</span><span class="cx"> #include "WebAutomationSession.h"
</span><span class="cx"> #include "WebPageMessages.h"
</span><span class="lines">@@ -77,6 +78,15 @@
</span><span class="cx">     m_page.stopMediaCapture();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UserMediaPermissionRequestManagerProxy::captureDevicesChanged()
+{
+#if ENABLE(MEDIA_STREAM)
+    // FIXME: a page with persistent access should always get device change notifications.
+    auto accessState = m_grantedRequests.isEmpty() ? DeviceAccessState::NoAccess : DeviceAccessState::SessionAccess;
+    m_page.process().send(Messages::WebPage::CaptureDevicesChanged(accessState), m_page.pageID());
+#endif
+}
+
</ins><span class="cx"> void UserMediaPermissionRequestManagerProxy::clearCachedState()
</span><span class="cx"> {
</span><span class="cx">     invalidatePendingRequests();
</span><span class="lines">@@ -434,7 +444,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void UserMediaPermissionRequestManagerProxy::processPregrantedRequests()
</del><ins>+void UserMediaPermissionRequestManagerProxy::viewIsBecomingVisible()
</ins><span class="cx"> {
</span><span class="cx">     for (auto& request : m_pregrantedRequests)
</span><span class="cx">         request->allow();
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessUserMediaPermissionRequestManagerProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2014 Igalia S.L.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx">     void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&&  userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, const WebCore::MediaStreamRequest&);
</span><span class="cx"> 
</span><span class="cx">     void resetAccess(uint64_t mainFrameID);
</span><del>-    void processPregrantedRequests();
</del><ins>+    void viewIsBecomingVisible();
</ins><span class="cx"> 
</span><span class="cx">     void userMediaAccessWasGranted(uint64_t, WebCore::CaptureDevice&& audioDevice, WebCore::CaptureDevice&& videoDevice);
</span><span class="cx">     void userMediaAccessWasDenied(uint64_t, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason);
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx">     void scheduleNextRejection();
</span><span class="cx">     void rejectionTimerFired();
</span><span class="cx">     void clearCachedState();
</span><ins>+    void captureDevicesChanged();
</ins><span class="cx"> 
</span><span class="cx">     void captureStateChanged(WebCore::MediaProducer::MediaStateFlags oldState, WebCore::MediaProducer::MediaStateFlags newState);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessUserMediaProcessManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp        2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/UIProcess/UserMediaProcessManager.cpp   2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> #include "WebPageMessages.h"
</span><span class="cx"> #include "WebPageProxy.h"
</span><span class="cx"> #include "WebProcessProxy.h"
</span><ins>+#include <WebCore/RealtimeMediaSourceCenter.h>
</ins><span class="cx"> #include <wtf/HashMap.h>
</span><span class="cx"> #include <wtf/NeverDestroyed.h>
</span><span class="cx"> 
</span><span class="lines">@@ -35,6 +36,8 @@
</span><span class="cx"> static const ASCIILiteral videoExtensionPath { "com.apple.webkit.camera"_s };
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+static const Seconds deviceChangeDebounceTimerInterval { 200_ms };
+
</ins><span class="cx"> class ProcessState {
</span><span class="cx"> public:
</span><span class="cx">     ProcessState() { }
</span><span class="lines">@@ -101,6 +104,11 @@
</span><span class="cx">     return manager;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+UserMediaProcessManager::UserMediaProcessManager()
+    : m_debounceTimer(RunLoop::main(), this, &UserMediaProcessManager::captureDevicesChanged)
+{
+}
+
</ins><span class="cx"> void UserMediaProcessManager::addUserMediaPermissionRequestManagerProxy(UserMediaPermissionRequestManagerProxy& proxy)
</span><span class="cx"> {
</span><span class="cx">     processState(proxy.page().process()).addRequestManager(proxy);
</span><span class="lines">@@ -254,6 +262,58 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UserMediaProcessManager::captureDevicesChanged()
+{
+    auto& map = stateMap();
+    for (auto& state : map) {
+        auto* process = state.key;
+        for (auto& manager : state.value->managers()) {
+            if (map.find(process) == map.end())
+                break;
+            manager->captureDevicesChanged();
+        }
+    }
+}
+
+void UserMediaProcessManager::beginMonitoringCaptureDevices()
+{
+    static std::once_flag onceFlag;
+
+    std::call_once(onceFlag, [this] {
+        m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
+
+        WebCore::RealtimeMediaSourceCenter::singleton().setDevicesChangedObserver([this]() {
+            auto oldDevices = WTFMove(m_captureDevices);
+            m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
+
+            if (m_captureDevices.size() == oldDevices.size()) {
+                bool haveChanges = false;
+                for (auto &newDevice : m_captureDevices) {
+                    if (newDevice.type() != WebCore::CaptureDevice::DeviceType::Camera && newDevice.type() != WebCore::CaptureDevice::DeviceType::Microphone)
+                        continue;
+
+                    auto index = oldDevices.findMatching([&newDevice] (auto& oldDevice) {
+                        return newDevice.persistentId() == oldDevice.persistentId() && newDevice.enabled() != oldDevice.enabled();
+                    });
+
+                    if (index == notFound) {
+                        haveChanges = true;
+                        break;
+                    }
+                }
+
+                if (!haveChanges)
+                    return;
+            }
+
+            // When a device with camera and microphone is attached or detached, the CaptureDevice notification for
+            // the different devices won't arrive at the same time so delay a bit so we can coalesce the callbacks.
+            if (!m_debounceTimer.isActive())
+                m_debounceTimer.startOneShot(deviceChangeDebounceTimerInterval);
+        });
+    });
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessUserMediaProcessManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h  2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/UIProcess/UserMediaProcessManager.h     2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -21,6 +21,8 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><span class="cx"> #include "UserMediaPermissionRequestManagerProxy.h"
</span><ins>+#include <WebCore/CaptureDevice.h>
+#include <wtf/RunLoop.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="lines">@@ -31,6 +33,8 @@
</span><span class="cx"> 
</span><span class="cx">     static UserMediaProcessManager& singleton();
</span><span class="cx"> 
</span><ins>+    UserMediaProcessManager();
+
</ins><span class="cx">     void addUserMediaPermissionRequestManagerProxy(UserMediaPermissionRequestManagerProxy&);
</span><span class="cx">     void removeUserMediaPermissionRequestManagerProxy(UserMediaPermissionRequestManagerProxy&);
</span><span class="cx"> 
</span><span class="lines">@@ -45,7 +49,13 @@
</span><span class="cx"> 
</span><span class="cx">     void denyNextUserMediaRequest() { m_denyNextRequest = true; }
</span><span class="cx"> 
</span><ins>+    void beginMonitoringCaptureDevices();
+
</ins><span class="cx"> private:
</span><ins>+    void captureDevicesChanged();
+
+    Vector<WebCore::CaptureDevice> m_captureDevices;
+    RunLoop::Timer<UserMediaProcessManager> m_debounceTimer;
</ins><span class="cx">     bool m_captureEnabled { true };
</span><span class="cx">     bool m_denyNextRequest { false };
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -3842,7 +3842,7 @@
</span><span class="cx"> void WebPageProxy::viewIsBecomingVisible()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><del>-    userMediaPermissionRequestManager().processPregrantedRequests();
</del><ins>+    userMediaPermissionRequestManager().viewIsBecomingVisible();
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -6459,6 +6459,13 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::beginMonitoringCaptureDevices()
+{
+#if ENABLE(MEDIA_STREAM)
+    UserMediaProcessManager::singleton().beginMonitoringCaptureDevices();
+#endif
+}
+
</ins><span class="cx"> void WebPageProxy::clearUserMediaState()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.h     2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h        2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1487,6 +1487,7 @@
</span><span class="cx"> #endif
</span><span class="cx">     void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginIdentifier, const WebCore::SecurityOriginData& topLevelDocumentOriginIdentifier, const WebCore::MediaStreamRequest&);
</span><span class="cx">     void enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData& userMediaDocumentOriginData, const WebCore::SecurityOriginData& topLevelDocumentOriginData);
</span><ins>+    void beginMonitoringCaptureDevices();
</ins><span class="cx"> 
</span><span class="cx">     void runModal();
</span><span class="cx">     void notifyScrollerThumbIsVisibleInRect(const WebCore::IntRect&);
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -287,6 +287,7 @@
</span><span class="cx">     # MediaSteam messages
</span><span class="cx">     RequestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, struct WebCore::SecurityOriginData userMediaDocumentOriginIdentifier, struct WebCore::SecurityOriginData topLevelDocumentOriginIdentifier, struct WebCore::MediaStreamRequest request)
</span><span class="cx">     EnumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, struct WebCore::SecurityOriginData userMediaDocumentOriginIdentifier, struct WebCore::SecurityOriginData topLevelDocumentOriginIdentifier)
</span><ins>+    BeginMonitoringCaptureDevices()
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     # Notification messages
</span></span></pre></div>
<a id="trunkSourceWebKitWebKitxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj     2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj        2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx">          074E75FE1DF2211900D318EC /* UserMediaProcessManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 074E75FB1DF1FD1300D318EC /* UserMediaProcessManager.h */; };
</span><span class="cx">          074E76021DF707BE00D318EC /* MediaDeviceSandboxExtensions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 074E76001DF7075D00D318EC /* MediaDeviceSandboxExtensions.cpp */; };
</span><span class="cx">          076E884E1A13CADF005E90FC /* APIContextMenuClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 076E884D1A13CADF005E90FC /* APIContextMenuClient.h */; };
</span><ins>+               0772811D21234FF600C8EF2E /* UserMediaPermissionRequestManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A410F4319AF7B27002EBAB5 /* UserMediaPermissionRequestManager.h */; };
</ins><span class="cx">           07A5EBBB1C7BA43E00B9CA69 /* WKFrameHandleRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A5EBB91C7BA43E00B9CA69 /* WKFrameHandleRef.cpp */; };
</span><span class="cx">          07A5EBBC1C7BA43E00B9CA69 /* WKFrameHandleRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 07A5EBBA1C7BA43E00B9CA69 /* WKFrameHandleRef.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          0E97D74D200E900400BF6643 /* SafeBrowsingSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E97D74C200E8FF300BF6643 /* SafeBrowsingSPI.h */; };
</span><span class="lines">@@ -9716,6 +9717,7 @@
</span><span class="cx">                          CD491B131E73482100009066 /* UserMediaCaptureManagerProxy.h in Headers */,
</span><span class="cx">                          CD491B181E73525500009066 /* UserMediaCaptureManagerProxyMessages.h in Headers */,
</span><span class="cx">                          07297F9F1C17BBEA003F0735 /* UserMediaPermissionCheckProxy.h in Headers */,
</span><ins>+                               0772811D21234FF600C8EF2E /* UserMediaPermissionRequestManager.h in Headers */,
</ins><span class="cx">                           4A3CC18B19B0640F00D14AEF /* UserMediaPermissionRequestManagerProxy.h in Headers */,
</span><span class="cx">                          4A3CC18D19B0641900D14AEF /* UserMediaPermissionRequestProxy.h in Headers */,
</span><span class="cx">                          074E75FE1DF2211900D318EC /* UserMediaProcessManager.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessMediaStreamUserMediaPermissionRequestManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp 2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp    2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2014 Igalia S.L.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -40,6 +40,8 @@
</span><span class="cx"> 
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><ins>+static constexpr OptionSet<WebCore::ActivityState::Flag> focusedActiveWindow = { WebCore::ActivityState::IsFocused, WebCore::ActivityState::WindowIsActive };
+
</ins><span class="cx"> static uint64_t generateRequestID()
</span><span class="cx"> {
</span><span class="cx">     static uint64_t uniqueRequestID = 1;
</span><span class="lines">@@ -53,6 +55,8 @@
</span><span class="cx"> 
</span><span class="cx"> UserMediaPermissionRequestManager::~UserMediaPermissionRequestManager()
</span><span class="cx"> {
</span><ins>+    if (m_monitoringActivityStateChange)
+        m_page.corePage()->removeActivityStateChangeObserver(*this);
</ins><span class="cx">     for (auto& sandboxExtension : m_userMediaDeviceSandboxExtensions)
</span><span class="cx">         sandboxExtension.value->revoke();
</span><span class="cx"> }
</span><span class="lines">@@ -222,6 +226,77 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+UserMediaClient::DeviceChangeObserverToken UserMediaPermissionRequestManager::addDeviceChangeObserver(WTF::Function<void()>&& observer)
+{
+    auto identifier = generateObjectIdentifier<WebCore::UserMediaClient::DeviceChangeObserverTokenType>();
+    m_deviceChangeObserverMap.add(identifier, WTFMove(observer));
+
+    if (!m_monitoringDeviceChange) {
+        m_monitoringDeviceChange = true;
+        m_page.send(Messages::WebPageProxy::BeginMonitoringCaptureDevices());
+    }
+    return identifier;
+}
+
+void UserMediaPermissionRequestManager::removeDeviceChangeObserver(UserMediaClient::DeviceChangeObserverToken token)
+{
+    bool wasRemoved = m_deviceChangeObserverMap.remove(token);
+    ASSERT_UNUSED(wasRemoved, wasRemoved);
+}
+
+void UserMediaPermissionRequestManager::captureDevicesChanged(DeviceAccessState accessState)
+{
+    // When new media input and/or output devices are made available, or any available input and/or
+    // output device becomes unavailable, the User Agent MUST run the following steps in browsing
+    // contexts where at least one of the following criteria are met, but in no other contexts:
+
+    // * The permission state of the "device-info" permission is "granted",
+    // * any of the input devices are attached to an active MediaStream in the browsing context, or
+    // * the active document is fully active and has focus.
+
+    bool isActive = (m_page.corePage()->activityState() & focusedActiveWindow) == focusedActiveWindow;
+    if (!isActive && accessState == DeviceAccessState::NoAccess) {
+        if (!isActive) {
+            if (!m_monitoringActivityStateChange) {
+                m_monitoringActivityStateChange = true;
+                m_page.corePage()->addActivityStateChangeObserver(*this);
+            }
+            m_pendingDeviceChangeEvent = true;
+            m_accessStateWhenDevicesChanged = accessState;
+        }
+        return;
+    }
+
+    auto identifiers = m_deviceChangeObserverMap.keys();
+    for (auto& identifier : identifiers) {
+        auto iterator = m_deviceChangeObserverMap.find(identifier);
+        if (iterator != m_deviceChangeObserverMap.end())
+            (iterator->value)();
+    }
+}
+
+void UserMediaPermissionRequestManager::activityStateDidChange(OptionSet<WebCore::ActivityState::Flag> oldActivityState, OptionSet<WebCore::ActivityState::Flag> newActivityState)
+{
+    if ((newActivityState & focusedActiveWindow) != focusedActiveWindow)
+        return;
+
+    RunLoop::main().dispatch([this, weakThis = makeWeakPtr(*this)]() mutable {
+        if (!weakThis || !m_monitoringActivityStateChange)
+            return;
+
+        m_monitoringActivityStateChange = false;
+        m_page.corePage()->removeActivityStateChangeObserver(*this);
+    });
+
+    if (!m_pendingDeviceChangeEvent)
+        return;
+
+    m_pendingDeviceChangeEvent = false;
+    auto accessState = m_accessStateWhenDevicesChanged;
+    m_accessStateWhenDevicesChanged = DeviceAccessState::NoAccess;
+    captureDevicesChanged(accessState);
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessMediaStreamUserMediaPermissionRequestManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h   2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebProcess/MediaStream/UserMediaPermissionRequestManager.h      2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2014 Igalia S.L.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "MediaDeviceSandboxExtensions.h"
</span><span class="cx"> #include "SandboxExtension.h"
</span><ins>+#include <WebCore/ActivityStateChangeObserver.h>
</ins><span class="cx"> #include <WebCore/MediaCanStartListener.h>
</span><span class="cx"> #include <WebCore/MediaConstraints.h>
</span><span class="cx"> #include <WebCore/MediaDevicesEnumerationRequest.h>
</span><span class="lines">@@ -37,8 +38,9 @@
</span><span class="cx"> 
</span><span class="cx"> class WebPage;
</span><span class="cx"> 
</span><del>-class UserMediaPermissionRequestManager
-    : private WebCore::MediaCanStartListener {
</del><ins>+enum class DeviceAccessState { NoAccess, SessionAccess, PersistentAccess };
+
+class UserMediaPermissionRequestManager : public CanMakeWeakPtr<UserMediaPermissionRequestManager>, private WebCore::MediaCanStartListener, private WebCore::ActivityStateChangeObserver {
</ins><span class="cx"> public:
</span><span class="cx">     explicit UserMediaPermissionRequestManager(WebPage&);
</span><span class="cx">     ~UserMediaPermissionRequestManager();
</span><span class="lines">@@ -55,12 +57,20 @@
</span><span class="cx">     void grantUserMediaDeviceSandboxExtensions(MediaDeviceSandboxExtensions&&);
</span><span class="cx">     void revokeUserMediaDeviceSandboxExtensions(const Vector<String>&);
</span><span class="cx"> 
</span><ins>+    WebCore::UserMediaClient::DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&);
+    void removeDeviceChangeObserver(WebCore::UserMediaClient::DeviceChangeObserverToken);
+
+    void captureDevicesChanged(DeviceAccessState);
+
</ins><span class="cx"> private:
</span><span class="cx">     void sendUserMediaRequest(WebCore::UserMediaRequest&);
</span><span class="cx"> 
</span><span class="cx">     // WebCore::MediaCanStartListener
</span><del>-    void mediaCanStart(WebCore::Document&) override;
</del><ins>+    void mediaCanStart(WebCore::Document&) final;
</ins><span class="cx"> 
</span><ins>+    // WebCore::ActivityStateChangeObserver
+    void activityStateDidChange(OptionSet<WebCore::ActivityState::Flag> oldActivityState, OptionSet<WebCore::ActivityState::Flag> newActivityState) final;
+
</ins><span class="cx">     void removeMediaRequestFromMaps(WebCore::UserMediaRequest&);
</span><span class="cx"> 
</span><span class="cx">     WebPage& m_page;
</span><span class="lines">@@ -73,10 +83,29 @@
</span><span class="cx">     HashMap<RefPtr<WebCore::MediaDevicesEnumerationRequest>, uint64_t> m_mediaDevicesEnumerationRequestToIDMap;
</span><span class="cx"> 
</span><span class="cx">     HashMap<String, RefPtr<SandboxExtension>> m_userMediaDeviceSandboxExtensions;
</span><ins>+
+    HashMap<WebCore::UserMediaClient::DeviceChangeObserverToken, WTF::Function<void()>> m_deviceChangeObserverMap;
+    DeviceAccessState m_accessStateWhenDevicesChanged { DeviceAccessState::NoAccess };
+    bool m_monitoringDeviceChange { false };
+    bool m_pendingDeviceChangeEvent { false };
+    bool m_monitoringActivityStateChange { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><ins>+namespace WTF {
+
+template<> struct EnumTraits<WebKit::DeviceAccessState> {
+    using values = EnumValues<
+        WebKit::DeviceAccessState,
+        WebKit::DeviceAccessState::NoAccess,
+        WebKit::DeviceAccessState::SessionAccess,
+        WebKit::DeviceAccessState::PersistentAccess
+    >;
+};
+
+} // namespace WTF
+
</ins><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span><span class="cx"> 
</span><span class="cx"> #endif // UserMediaPermissionRequestManager_h
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebCoreSupportWebUserMediaClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp     2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.cpp        2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2014 Igalia S.L.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -62,6 +62,16 @@
</span><span class="cx">     m_page.userMediaPermissionRequestManager().cancelMediaDevicesEnumeration(request);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+WebUserMediaClient::DeviceChangeObserverToken WebUserMediaClient::addDeviceChangeObserver(WTF::Function<void()>&& observer)
+{
+    return m_page.userMediaPermissionRequestManager().addDeviceChangeObserver(WTFMove(observer));
+}
+
+void WebUserMediaClient::removeDeviceChangeObserver(DeviceChangeObserverToken token)
+{
+    m_page.userMediaPermissionRequestManager().removeDeviceChangeObserver(token);
+}
+
</ins><span class="cx"> } // namespace WebKit;
</span><span class="cx"> 
</span><span class="cx"> #endif // MEDIA_STREAM
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebCoreSupportWebUserMediaClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h       2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebUserMediaClient.h  2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2014 Igalia S.L.
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -42,6 +42,9 @@
</span><span class="cx">     void enumerateMediaDevices(WebCore::MediaDevicesEnumerationRequest&) final;
</span><span class="cx">     void cancelMediaDevicesEnumerationRequest(WebCore::MediaDevicesEnumerationRequest&) final;
</span><span class="cx"> 
</span><ins>+    DeviceChangeObserverToken addDeviceChangeObserver(WTF::Function<void()>&&) final;
+    void removeDeviceChangeObserver(DeviceChangeObserverToken) final;
+
</ins><span class="cx">     void initializeFactories();
</span><span class="cx"> 
</span><span class="cx">     WebPage& m_page;
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp       2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp  2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -3739,6 +3739,12 @@
</span><span class="cx"> {
</span><span class="cx">     m_userMediaPermissionRequestManager->didCompleteMediaDeviceEnumeration(userMediaID, devices, WTFMove(deviceIdentifierHashSalt), originHasPersistentAccess);
</span><span class="cx"> }
</span><ins>+
+void WebPage::captureDevicesChanged(DeviceAccessState accessState)
+{
+    m_userMediaPermissionRequestManager->captureDevicesChanged(accessState);
+}
+
</ins><span class="cx"> #if ENABLE(SANDBOX_EXTENSIONS)
</span><span class="cx"> void WebPage::grantUserMediaDeviceSandboxExtensions(MediaDeviceSandboxExtensions&& extensions)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h    2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -228,6 +228,7 @@
</span><span class="cx"> class WebCredentialsMessenger;
</span><span class="cx"> class RemoteLayerTreeTransaction;
</span><span class="cx"> 
</span><ins>+enum class DeviceAccessState;
</ins><span class="cx"> enum FindOptions : uint16_t;
</span><span class="cx"> enum class DragControllerAction;
</span><span class="cx"> 
</span><span class="lines">@@ -565,6 +566,7 @@
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><span class="cx">     UserMediaPermissionRequestManager& userMediaPermissionRequestManager() { return *m_userMediaPermissionRequestManager; }
</span><span class="cx">     void prepareToSendUserMediaPermissionRequest();
</span><ins>+    void captureDevicesChanged(DeviceAccessState);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void elementDidFocus(WebCore::Node*);
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (235085 => 235086)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in       2018-08-20 17:41:23 UTC (rev 235085)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in  2018-08-20 18:10:22 UTC (rev 235086)
</span><span class="lines">@@ -318,6 +318,7 @@
</span><span class="cx">     UserMediaAccessWasGranted(uint64_t userMediaID, WebCore::CaptureDevice audioDevice, WebCore::CaptureDevice videoDevice, String mediaDeviceIdentifierHashSalt)
</span><span class="cx">     UserMediaAccessWasDenied(uint64_t userMediaID, uint64_t reason, String invalidConstraint)
</span><span class="cx">     DidCompleteMediaDeviceEnumeration(uint64_t userMediaID, Vector<WebCore::CaptureDevice> devices, String mediaDeviceIdentifierHashSalt, bool hasPersistentAccess)
</span><ins>+    CaptureDevicesChanged(enum WebKit::DeviceAccessState accessState)
</ins><span class="cx"> #if ENABLE(SANDBOX_EXTENSIONS)
</span><span class="cx">     GrantUserMediaDeviceSandboxExtensions(WebKit::MediaDeviceSandboxExtensions sandboxExtensions)
</span><span class="cx">     RevokeUserMediaDeviceSandboxExtensions(Vector<String> sandboxExtensionIDs)
</span></span></pre>
</div>
</div>

</body>
</html>