<!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>[284275] branches/safari-612-branch</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/284275">284275</a></dd>
<dt>Author</dt> <dd>repstein@apple.com</dd>
<dt>Date</dt> <dd>2021-10-15 15:16:20 -0700 (Fri, 15 Oct 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Cherry-pick <a href="http://trac.webkit.org/projects/webkit/changeset/283033">r283033</a>. rdar://problem/83953190

    [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
    https://bugs.webkit.org/show_bug.cgi?id=230538
    <rdar://problem/83355705>

    Reviewed by Eric Carlson.

    Source/WebCore:

    Add support for interrupting mock cameras.
    Update internals to handle the case of out of main thread videoSampleAvailable calls.

    Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
    This ensures we can restart capture in case a track is muted without the page being muted itself.

    When a source is muted and is in producing data state, it is interrupted.
    When setMuted(false) is called, we need to uninterrupt.
    To do so, we do a stop/start cycle

    Test: fast/mediastream/media-stream-video-track-interrupted.html

    * page/Page.cpp:
    (WebCore::Page::setMuted):
    * platform/mediastream/RealtimeMediaSource.cpp:
    (WebCore::RealtimeMediaSource::setMuted):
    * platform/mock/MockRealtimeMediaSourceCenter.cpp:
    (WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
    * platform/mock/MockRealtimeMediaSourceCenter.h:
    * platform/mock/MockRealtimeVideoSource.cpp:
    (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
    (WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
    (WebCore::MockRealtimeVideoSource::setIsInterrupted):
    * platform/mock/MockRealtimeVideoSource.h:
    * testing/Internals.cpp:
    (WebCore::Internals::videoSampleAvailable):
    * testing/Internals.h:

    Source/WebKit:

    Add support for mock capture interruption.
    When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
    In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
    It is important to not stop the source so that it can continue receiving interruption notifications.

    * GPUProcess/GPUProcess.cpp:
    (WebKit::GPUProcess::setMockCameraIsInterrupted):
    * GPUProcess/GPUProcess.h:
    * GPUProcess/GPUProcess.messages.in:
    * UIProcess/API/C/WKPage.cpp:
    (WKPageIsMockRealtimeMediaSourceCenterEnabled):
    (WKPageSetMockCameraIsInterrupted):
    * UIProcess/API/C/WKPagePrivate.h:
    * UIProcess/GPU/GPUProcessProxy.cpp:
    (WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
    * UIProcess/GPU/GPUProcessProxy.h:
    * WebProcess/cocoa/RemoteRealtimeAudioSource.h:
    * WebProcess/cocoa/RemoteRealtimeVideoSource.h:
    * WebProcess/cocoa/UserMediaCaptureManager.cpp:
    (WebKit::UserMediaCaptureManager::sourceMutedChanged):

    Tools:

    Add mock API to mock camera interruption.

    * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
    * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
    (WTR::TestRunner::setMockCameraIsInterrupted):
    * WebKitTestRunner/InjectedBundle/TestRunner.h:
    * WebKitTestRunner/TestController.cpp:
    (WTR::TestController::setMockCameraIsInterrupted):
    * WebKitTestRunner/TestController.h:
    * WebKitTestRunner/TestInvocation.cpp:
    (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

    LayoutTests:

    * fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
    * fast/mediastream/media-stream-video-track-interrupted.html: Added.

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@283033 268f45cc-cd09-0410-ab3c-d52691b4dbfc</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari612branchLayoutTestsChangeLog">branches/safari-612-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari612branchSourceWebCoreChangeLog">branches/safari-612-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari612branchSourceWebCorepagePagecpp">branches/safari-612-branch/Source/WebCore/page/Page.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp">branches/safari-612-branch/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp">branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebCoreplatformmockMockRealtimeMediaSourceCenterh">branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h</a></li>
<li><a href="#branchessafari612branchSourceWebCoreplatformmockMockRealtimeVideoSourcecpp">branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebCoreplatformmockMockRealtimeVideoSourceh">branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.h</a></li>
<li><a href="#branchessafari612branchSourceWebCoretestingInternalscpp">branches/safari-612-branch/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebCoretestingInternalsh">branches/safari-612-branch/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#branchessafari612branchSourceWebKitChangeLog">branches/safari-612-branch/Source/WebKit/ChangeLog</a></li>
<li><a href="#branchessafari612branchSourceWebKitGPUProcessGPUProcesscpp">branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebKitGPUProcessGPUProcessh">branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.h</a></li>
<li><a href="#branchessafari612branchSourceWebKitGPUProcessGPUProcessmessagesin">branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.messages.in</a></li>
<li><a href="#branchessafari612branchSourceWebKitUIProcessAPICWKPagecpp">branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPage.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebKitUIProcessAPICWKPagePrivateh">branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPagePrivate.h</a></li>
<li><a href="#branchessafari612branchSourceWebKitUIProcessGPUGPUProcessProxycpp">branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebKitUIProcessGPUGPUProcessProxyh">branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h</a></li>
<li><a href="#branchessafari612branchSourceWebKitWebProcesscocoaRemoteRealtimeAudioSourceh">branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeAudioSource.h</a></li>
<li><a href="#branchessafari612branchSourceWebKitWebProcesscocoaRemoteRealtimeVideoSourceh">branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeVideoSource.h</a></li>
<li><a href="#branchessafari612branchSourceWebKitWebProcesscocoaUserMediaCaptureManagercpp">branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp</a></li>
<li><a href="#branchessafari612branchToolsChangeLog">branches/safari-612-branch/Tools/ChangeLog</a></li>
<li><a href="#branchessafari612branchToolsWebKitTestRunnerInjectedBundleBindingsTestRunneridl">branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl</a></li>
<li><a href="#branchessafari612branchToolsWebKitTestRunnerInjectedBundleTestRunnercpp">branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp</a></li>
<li><a href="#branchessafari612branchToolsWebKitTestRunnerInjectedBundleTestRunnerh">branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h</a></li>
<li><a href="#branchessafari612branchToolsWebKitTestRunnerTestControllercpp">branches/safari-612-branch/Tools/WebKitTestRunner/TestController.cpp</a></li>
<li><a href="#branchessafari612branchToolsWebKitTestRunnerTestControllerh">branches/safari-612-branch/Tools/WebKitTestRunner/TestController.h</a></li>
<li><a href="#branchessafari612branchToolsWebKitTestRunnerTestInvocationcpp">branches/safari-612-branch/Tools/WebKitTestRunner/TestInvocation.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari612branchLayoutTestsfastmediastreammediastreamvideotrackinterruptedexpectedtxt">branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted-expected.txt</a></li>
<li><a href="#branchessafari612branchLayoutTestsfastmediastreammediastreamvideotrackinterruptedhtml">branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari612branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/LayoutTests/ChangeLog (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/LayoutTests/ChangeLog 2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/LayoutTests/ChangeLog    2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -1,3 +1,99 @@
</span><ins>+2021-10-15  Russell Epstein  <repstein@apple.com>
+
+        Cherry-pick r283033. rdar://problem/83953190
+
+    [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+    https://bugs.webkit.org/show_bug.cgi?id=230538
+    <rdar://problem/83355705>
+    
+    Reviewed by Eric Carlson.
+    
+    Source/WebCore:
+    
+    Add support for interrupting mock cameras.
+    Update internals to handle the case of out of main thread videoSampleAvailable calls.
+    
+    Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
+    This ensures we can restart capture in case a track is muted without the page being muted itself.
+    
+    When a source is muted and is in producing data state, it is interrupted.
+    When setMuted(false) is called, we need to uninterrupt.
+    To do so, we do a stop/start cycle
+    
+    Test: fast/mediastream/media-stream-video-track-interrupted.html
+    
+    * page/Page.cpp:
+    (WebCore::Page::setMuted):
+    * platform/mediastream/RealtimeMediaSource.cpp:
+    (WebCore::RealtimeMediaSource::setMuted):
+    * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+    (WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
+    * platform/mock/MockRealtimeMediaSourceCenter.h:
+    * platform/mock/MockRealtimeVideoSource.cpp:
+    (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::setIsInterrupted):
+    * platform/mock/MockRealtimeVideoSource.h:
+    * testing/Internals.cpp:
+    (WebCore::Internals::videoSampleAvailable):
+    * testing/Internals.h:
+    
+    Source/WebKit:
+    
+    Add support for mock capture interruption.
+    When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
+    In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
+    It is important to not stop the source so that it can continue receiving interruption notifications.
+    
+    * GPUProcess/GPUProcess.cpp:
+    (WebKit::GPUProcess::setMockCameraIsInterrupted):
+    * GPUProcess/GPUProcess.h:
+    * GPUProcess/GPUProcess.messages.in:
+    * UIProcess/API/C/WKPage.cpp:
+    (WKPageIsMockRealtimeMediaSourceCenterEnabled):
+    (WKPageSetMockCameraIsInterrupted):
+    * UIProcess/API/C/WKPagePrivate.h:
+    * UIProcess/GPU/GPUProcessProxy.cpp:
+    (WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
+    * UIProcess/GPU/GPUProcessProxy.h:
+    * WebProcess/cocoa/RemoteRealtimeAudioSource.h:
+    * WebProcess/cocoa/RemoteRealtimeVideoSource.h:
+    * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+    (WebKit::UserMediaCaptureManager::sourceMutedChanged):
+    
+    Tools:
+    
+    Add mock API to mock camera interruption.
+    
+    * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+    * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+    (WTR::TestRunner::setMockCameraIsInterrupted):
+    * WebKitTestRunner/InjectedBundle/TestRunner.h:
+    * WebKitTestRunner/TestController.cpp:
+    (WTR::TestController::setMockCameraIsInterrupted):
+    * WebKitTestRunner/TestController.h:
+    * WebKitTestRunner/TestInvocation.cpp:
+    (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+    
+    LayoutTests:
+    
+    * fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
+    * fast/mediastream/media-stream-video-track-interrupted.html: Added.
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@283033 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-09-24  Youenn Fablet  <youenn@apple.com>
+
+            [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+            https://bugs.webkit.org/show_bug.cgi?id=230538
+            <rdar://problem/83355705>
+
+            Reviewed by Eric Carlson.
+
+            * fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
+            * fast/mediastream/media-stream-video-track-interrupted.html: Added.
+
</ins><span class="cx"> 2021-10-12  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Apply patch. rdar://problem/84113071
</span></span></pre></div>
<a id="branchessafari612branchLayoutTestsfastmediastreammediastreamvideotrackinterruptedexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted-expected.txt (0 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted-expected.txt                                (rev 0)
+++ branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted-expected.txt   2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+
+PASS Interrupt/resume video track
+PASS Interrupt video track then uninterrupt it using page unmuting
+
</ins></span></pre></div>
<a id="branchessafari612branchLayoutTestsfastmediastreammediastreamvideotrackinterruptedhtml"></a>
<div class="addfile"><h4>Added: branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted.html (0 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted.html                                (rev 0)
+++ branches/safari-612-branch/LayoutTests/fast/mediastream/media-stream-video-track-interrupted.html   2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>Capture source interruption.</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+ </head>
+<body>
+    <script>
+    promise_test(async (test) => {
+        const stream = await navigator.mediaDevices.getUserMedia({video: true});
+        const track = stream.getVideoTracks()[0];
+        if (!window.testRunner)
+            return;
+
+        let promise = new Promise((resolve, reject) => { track.onmute = resolve; setTimeout(() => reject("no mute"), 5000) });
+        testRunner.setMockCameraIsInterrupted(true);
+        await promise;
+
+        assert_true(track.muted, "track is muted");
+
+        promise = new Promise((resolve, reject) => { track.onunmute = resolve; setTimeout(() => reject("no unmute"), 5000) });
+        testRunner.setMockCameraIsInterrupted(false);
+        await promise;
+
+        assert_false(track.muted, "track is not muted");
+
+        track.stop();
+    }, "Interrupt/resume video track");
+
+    promise_test(async (test) => {
+        const stream = await navigator.mediaDevices.getUserMedia({video: true});
+        const track = stream.getVideoTracks()[0];
+        if (!window.testRunner || !window.internals)
+            return;
+        internals.observeMediaStreamTrack(track);
+
+        // video frames should flow.
+        let current = internals.trackVideoSampleCount;
+        let counter = 0;
+        while (internals.trackVideoSampleCount === current && ++counter < 50)
+            await new Promise(resolve => setTimeout(resolve, 50));
+        assert_less_than(counter, 50, "first live check");
+
+        // getting an interruption, track should be muted.
+        let promise = new Promise((resolve, reject) => { track.onmute = resolve; setTimeout(() => reject("no mute"), 5000) });
+        testRunner.setMockCameraIsInterrupted(true);
+        await promise;
+
+        assert_true(track.muted, "track is muted");
+
+        // video frames should not flow.
+        counter = 0;
+        while (internals.trackVideoSampleCount !== current && ++counter < 50) {
+            current = internals.trackVideoSampleCount;
+            await new Promise(resolve => setTimeout(resolve, 200));
+        }
+        assert_less_than(counter, 50, "first muted check");
+
+        // Unmuting page should restart capture.
+        promise = new Promise((resolve, reject) => { track.onunmute = resolve; setTimeout(() => reject("no unmute"), 5000) });
+        internals.setPageMuted('');
+        await promise;
+
+        assert_false(track.muted, "track is not muted");
+
+        current = internals.trackVideoSampleCount;
+        counter = 0;
+        while (internals.trackVideoSampleCount === current && ++counter < 50)
+            await new Promise(resolve => setTimeout(resolve, 50));
+        assert_less_than(counter, 50, "second live check");
+
+        track.stop();
+    }, "Interrupt video track then uninterrupt it using page unmuting");
+    </script>
+</body>
+</html>
</ins></span></pre></div>
<a id="branchessafari612branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/ChangeLog (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/ChangeLog      2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/ChangeLog 2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -1,3 +1,124 @@
</span><ins>+2021-10-15  Russell Epstein  <repstein@apple.com>
+
+        Cherry-pick r283033. rdar://problem/83953190
+
+    [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+    https://bugs.webkit.org/show_bug.cgi?id=230538
+    <rdar://problem/83355705>
+    
+    Reviewed by Eric Carlson.
+    
+    Source/WebCore:
+    
+    Add support for interrupting mock cameras.
+    Update internals to handle the case of out of main thread videoSampleAvailable calls.
+    
+    Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
+    This ensures we can restart capture in case a track is muted without the page being muted itself.
+    
+    When a source is muted and is in producing data state, it is interrupted.
+    When setMuted(false) is called, we need to uninterrupt.
+    To do so, we do a stop/start cycle
+    
+    Test: fast/mediastream/media-stream-video-track-interrupted.html
+    
+    * page/Page.cpp:
+    (WebCore::Page::setMuted):
+    * platform/mediastream/RealtimeMediaSource.cpp:
+    (WebCore::RealtimeMediaSource::setMuted):
+    * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+    (WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
+    * platform/mock/MockRealtimeMediaSourceCenter.h:
+    * platform/mock/MockRealtimeVideoSource.cpp:
+    (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::setIsInterrupted):
+    * platform/mock/MockRealtimeVideoSource.h:
+    * testing/Internals.cpp:
+    (WebCore::Internals::videoSampleAvailable):
+    * testing/Internals.h:
+    
+    Source/WebKit:
+    
+    Add support for mock capture interruption.
+    When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
+    In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
+    It is important to not stop the source so that it can continue receiving interruption notifications.
+    
+    * GPUProcess/GPUProcess.cpp:
+    (WebKit::GPUProcess::setMockCameraIsInterrupted):
+    * GPUProcess/GPUProcess.h:
+    * GPUProcess/GPUProcess.messages.in:
+    * UIProcess/API/C/WKPage.cpp:
+    (WKPageIsMockRealtimeMediaSourceCenterEnabled):
+    (WKPageSetMockCameraIsInterrupted):
+    * UIProcess/API/C/WKPagePrivate.h:
+    * UIProcess/GPU/GPUProcessProxy.cpp:
+    (WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
+    * UIProcess/GPU/GPUProcessProxy.h:
+    * WebProcess/cocoa/RemoteRealtimeAudioSource.h:
+    * WebProcess/cocoa/RemoteRealtimeVideoSource.h:
+    * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+    (WebKit::UserMediaCaptureManager::sourceMutedChanged):
+    
+    Tools:
+    
+    Add mock API to mock camera interruption.
+    
+    * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+    * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+    (WTR::TestRunner::setMockCameraIsInterrupted):
+    * WebKitTestRunner/InjectedBundle/TestRunner.h:
+    * WebKitTestRunner/TestController.cpp:
+    (WTR::TestController::setMockCameraIsInterrupted):
+    * WebKitTestRunner/TestController.h:
+    * WebKitTestRunner/TestInvocation.cpp:
+    (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+    
+    LayoutTests:
+    
+    * fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
+    * fast/mediastream/media-stream-video-track-interrupted.html: Added.
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@283033 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-09-24  Youenn Fablet  <youenn@apple.com>
+
+            [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+            https://bugs.webkit.org/show_bug.cgi?id=230538
+            <rdar://problem/83355705>
+
+            Reviewed by Eric Carlson.
+
+            Add support for interrupting mock cameras.
+            Update internals to handle the case of out of main thread videoSampleAvailable calls.
+
+            Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
+            This ensures we can restart capture in case a track is muted without the page being muted itself.
+
+            When a source is muted and is in producing data state, it is interrupted.
+            When setMuted(false) is called, we need to uninterrupt.
+            To do so, we do a stop/start cycle
+
+            Test: fast/mediastream/media-stream-video-track-interrupted.html
+
+            * page/Page.cpp:
+            (WebCore::Page::setMuted):
+            * platform/mediastream/RealtimeMediaSource.cpp:
+            (WebCore::RealtimeMediaSource::setMuted):
+            * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+            (WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
+            * platform/mock/MockRealtimeMediaSourceCenter.h:
+            * platform/mock/MockRealtimeVideoSource.cpp:
+            (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
+            (WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
+            (WebCore::MockRealtimeVideoSource::setIsInterrupted):
+            * platform/mock/MockRealtimeVideoSource.h:
+            * testing/Internals.cpp:
+            (WebCore::Internals::videoSampleAvailable):
+            * testing/Internals.h:
+
</ins><span class="cx"> 2021-10-12  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Apply patch. rdar://problem/83953336
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCorepagePagecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/page/Page.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/page/Page.cpp  2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/page/Page.cpp     2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -2203,9 +2203,6 @@
</span><span class="cx"> 
</span><span class="cx"> void Page::setMuted(MediaProducer::MutedStateFlags muted)
</span><span class="cx"> {
</span><del>-    if (m_mutedState == muted)
-        return;
-
</del><span class="cx">     m_mutedState = muted;
</span><span class="cx"> 
</span><span class="cx">     forEachDocument([] (Document& document) {
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoreplatformmediastreamRealtimeMediaSourcecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp   2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp      2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -107,8 +107,11 @@
</span><span class="cx">     // Changed m_muted before calling start/stop so muted() will reflect the correct state.
</span><span class="cx">     bool changed = m_muted != muted;
</span><span class="cx"> 
</span><del>-    if (changed)
-        ALWAYS_LOG_IF(m_logger, LOGIDENTIFIER, muted);
</del><ins>+    ALWAYS_LOG_IF(m_logger && changed, LOGIDENTIFIER, muted);
+    if (changed && !muted && m_isProducingData) {
+        // Let's uninterrupt by doing a stop/start cycle.
+        stop();
+    }
</ins><span class="cx"> 
</span><span class="cx">     m_muted = muted;
</span><span class="cx">     if (muted)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoreplatformmockMockRealtimeMediaSourceCentercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp        2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp   2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -295,6 +295,11 @@
</span><span class="cx">     RealtimeMediaSourceCenter::singleton().captureDevicesChanged();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    MockRealtimeVideoSource::setIsInterrupted(isInterrupted);
+}
+
</ins><span class="cx"> void MockRealtimeMediaSourceCenter::setDevices(Vector<MockMediaDevice>&& newMockDevices)
</span><span class="cx"> {
</span><span class="cx">     microphoneDevices().clear();
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoreplatformmockMockRealtimeMediaSourceCenterh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h  2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h     2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx">     WEBCORE_EXPORT static void addDevice(const MockMediaDevice&);
</span><span class="cx">     WEBCORE_EXPORT static void removeDevice(const String& persistentId);
</span><span class="cx">     WEBCORE_EXPORT static void resetDevices();
</span><ins>+    WEBCORE_EXPORT static void setMockCameraIsInterrupted(bool);
</ins><span class="cx"> 
</span><span class="cx">     void setMockAudioCaptureEnabled(bool isEnabled) { m_isMockAudioCaptureEnabled = isEnabled; }
</span><span class="cx">     void setMockVideoCaptureEnabled(bool isEnabled) { m_isMockVideoCaptureEnabled = isEnabled; }
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoreplatformmockMockRealtimeVideoSourcecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp      2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp 2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -67,10 +67,19 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+static HashSet<MockRealtimeVideoSource*>& allMockRealtimeVideoSource()
+{
+    static NeverDestroyed<HashSet<MockRealtimeVideoSource*>> videoSources;
+    return videoSources;
+}
+
</ins><span class="cx"> MockRealtimeVideoSource::MockRealtimeVideoSource(String&& deviceID, String&& name, String&& hashSalt)
</span><span class="cx">     : RealtimeVideoCaptureSource(WTFMove(name), WTFMove(deviceID), WTFMove(hashSalt))
</span><span class="cx">     , m_emitFrameTimer(RunLoop::current(), this, &MockRealtimeVideoSource::generateFrame)
</span><span class="cx"> {
</span><ins>+    ASSERT(isMainThread());
+    allMockRealtimeVideoSource().add(this);
+
</ins><span class="cx">     auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(persistentID());
</span><span class="cx">     ASSERT(device);
</span><span class="cx">     m_device = *device;
</span><span class="lines">@@ -93,6 +102,12 @@
</span><span class="cx">     m_fillColor = properties.fillColor;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MockRealtimeVideoSource::~MockRealtimeVideoSource()
+{
+    ASSERT(isMainThread());
+    allMockRealtimeVideoSource().remove(this);
+}
+
</ins><span class="cx"> bool MockRealtimeVideoSource::supportsSizeAndFrameRate(std::optional<int> width, std::optional<int> height, std::optional<double> rate)
</span><span class="cx"> {
</span><span class="cx">     // FIXME: consider splitting mock display into another class so we don't don't have to do this silly dance
</span><span class="lines">@@ -514,6 +529,19 @@
</span><span class="cx">     orientationChanged(notifier.orientation());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockRealtimeVideoSource::setIsInterrupted(bool isInterrupted)
+{
+    for (auto* source : allMockRealtimeVideoSource()) {
+        if (!source->isProducingData())
+            continue;
+        if (isInterrupted)
+            source->m_emitFrameTimer.stop();
+        else
+            source->startCaptureTimer();
+        source->notifyMutedChange(isInterrupted);
+    }
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(MEDIA_STREAM)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoreplatformmockMockRealtimeVideoSourceh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.h        2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/platform/mock/MockRealtimeVideoSource.h   2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -49,7 +49,10 @@
</span><span class="cx"> class MockRealtimeVideoSource : public RealtimeVideoCaptureSource, private OrientationNotifier::Observer {
</span><span class="cx"> public:
</span><span class="cx">     static CaptureSourceOrError create(String&& deviceID, String&& name, String&& hashSalt, const MediaConstraints*);
</span><ins>+    ~MockRealtimeVideoSource();
</ins><span class="cx"> 
</span><ins>+    static void setIsInterrupted(bool);
+
</ins><span class="cx">     ImageBuffer* imageBuffer() const;
</span><span class="cx"> 
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/testing/Internals.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/testing/Internals.cpp  2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/testing/Internals.cpp     2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -5434,24 +5434,28 @@
</span><span class="cx"> 
</span><span class="cx"> void Internals::videoSampleAvailable(MediaSample& sample)
</span><span class="cx"> {
</span><del>-    m_trackVideoSampleCount++;
-    if (!m_nextTrackFramePromise)
-        return;
</del><ins>+    callOnMainThread([this, weakThis = makeWeakPtr(this), sample = Ref { sample }] {
+        if (!weakThis)
+            return;
+        m_trackVideoSampleCount++;
+        if (!m_nextTrackFramePromise)
+            return;
</ins><span class="cx"> 
</span><del>-    auto& videoSettings = m_trackSource->settings();
-    if (!videoSettings.width() || !videoSettings.height())
-        return;
-    
-    auto rgba = sample.getRGBAImageData();
-    if (!rgba)
-        return;
-    
-    auto imageData = ImageData::create(rgba.releaseNonNull(), videoSettings.width(), videoSettings.height(), { { PredefinedColorSpace::SRGB } });
-    if (!imageData.hasException())
-        m_nextTrackFramePromise->resolve(imageData.releaseReturnValue());
-    else
-        m_nextTrackFramePromise->reject(imageData.exception().code());
-    m_nextTrackFramePromise = nullptr;
</del><ins>+        auto& videoSettings = m_trackSource->settings();
+        if (!videoSettings.width() || !videoSettings.height())
+            return;
+
+        auto rgba = sample->getRGBAImageData();
+        if (!rgba)
+            return;
+
+        auto imageData = ImageData::create(rgba.releaseNonNull(), videoSettings.width(), videoSettings.height(), { { PredefinedColorSpace::SRGB } });
+        if (!imageData.hasException())
+            m_nextTrackFramePromise->resolve(imageData.releaseReturnValue());
+        else
+            m_nextTrackFramePromise->reject(imageData.exception().code());
+        m_nextTrackFramePromise = nullptr;
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Internals::delayMediaStreamTrackSamples(MediaStreamTrack& track, float delay)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/testing/Internals.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/testing/Internals.h    2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebCore/testing/Internals.h       2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -148,7 +148,7 @@
</span><span class="cx"> 
</span><span class="cx"> class Internals final : public RefCounted<Internals>, private ContextDestructionObserver
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><del>-    , private RealtimeMediaSource::Observer
</del><ins>+    , public RealtimeMediaSource::Observer
</ins><span class="cx">     , private RealtimeMediaSource::AudioSampleObserver
</span><span class="cx">     , private RealtimeMediaSource::VideoSampleObserver
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/ChangeLog (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/ChangeLog       2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/ChangeLog  2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -1,3 +1,117 @@
</span><ins>+2021-10-15  Russell Epstein  <repstein@apple.com>
+
+        Cherry-pick r283033. rdar://problem/83953190
+
+    [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+    https://bugs.webkit.org/show_bug.cgi?id=230538
+    <rdar://problem/83355705>
+    
+    Reviewed by Eric Carlson.
+    
+    Source/WebCore:
+    
+    Add support for interrupting mock cameras.
+    Update internals to handle the case of out of main thread videoSampleAvailable calls.
+    
+    Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
+    This ensures we can restart capture in case a track is muted without the page being muted itself.
+    
+    When a source is muted and is in producing data state, it is interrupted.
+    When setMuted(false) is called, we need to uninterrupt.
+    To do so, we do a stop/start cycle
+    
+    Test: fast/mediastream/media-stream-video-track-interrupted.html
+    
+    * page/Page.cpp:
+    (WebCore::Page::setMuted):
+    * platform/mediastream/RealtimeMediaSource.cpp:
+    (WebCore::RealtimeMediaSource::setMuted):
+    * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+    (WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
+    * platform/mock/MockRealtimeMediaSourceCenter.h:
+    * platform/mock/MockRealtimeVideoSource.cpp:
+    (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::setIsInterrupted):
+    * platform/mock/MockRealtimeVideoSource.h:
+    * testing/Internals.cpp:
+    (WebCore::Internals::videoSampleAvailable):
+    * testing/Internals.h:
+    
+    Source/WebKit:
+    
+    Add support for mock capture interruption.
+    When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
+    In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
+    It is important to not stop the source so that it can continue receiving interruption notifications.
+    
+    * GPUProcess/GPUProcess.cpp:
+    (WebKit::GPUProcess::setMockCameraIsInterrupted):
+    * GPUProcess/GPUProcess.h:
+    * GPUProcess/GPUProcess.messages.in:
+    * UIProcess/API/C/WKPage.cpp:
+    (WKPageIsMockRealtimeMediaSourceCenterEnabled):
+    (WKPageSetMockCameraIsInterrupted):
+    * UIProcess/API/C/WKPagePrivate.h:
+    * UIProcess/GPU/GPUProcessProxy.cpp:
+    (WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
+    * UIProcess/GPU/GPUProcessProxy.h:
+    * WebProcess/cocoa/RemoteRealtimeAudioSource.h:
+    * WebProcess/cocoa/RemoteRealtimeVideoSource.h:
+    * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+    (WebKit::UserMediaCaptureManager::sourceMutedChanged):
+    
+    Tools:
+    
+    Add mock API to mock camera interruption.
+    
+    * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+    * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+    (WTR::TestRunner::setMockCameraIsInterrupted):
+    * WebKitTestRunner/InjectedBundle/TestRunner.h:
+    * WebKitTestRunner/TestController.cpp:
+    (WTR::TestController::setMockCameraIsInterrupted):
+    * WebKitTestRunner/TestController.h:
+    * WebKitTestRunner/TestInvocation.cpp:
+    (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+    
+    LayoutTests:
+    
+    * fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
+    * fast/mediastream/media-stream-video-track-interrupted.html: Added.
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@283033 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-09-24  Youenn Fablet  <youenn@apple.com>
+
+            [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+            https://bugs.webkit.org/show_bug.cgi?id=230538
+            <rdar://problem/83355705>
+
+            Reviewed by Eric Carlson.
+
+            Add support for mock capture interruption.
+            When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
+            In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
+            It is important to not stop the source so that it can continue receiving interruption notifications.
+
+            * GPUProcess/GPUProcess.cpp:
+            (WebKit::GPUProcess::setMockCameraIsInterrupted):
+            * GPUProcess/GPUProcess.h:
+            * GPUProcess/GPUProcess.messages.in:
+            * UIProcess/API/C/WKPage.cpp:
+            (WKPageIsMockRealtimeMediaSourceCenterEnabled):
+            (WKPageSetMockCameraIsInterrupted):
+            * UIProcess/API/C/WKPagePrivate.h:
+            * UIProcess/GPU/GPUProcessProxy.cpp:
+            (WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
+            * UIProcess/GPU/GPUProcessProxy.h:
+            * WebProcess/cocoa/RemoteRealtimeAudioSource.h:
+            * WebProcess/cocoa/RemoteRealtimeVideoSource.h:
+            * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+            (WebKit::UserMediaCaptureManager::sourceMutedChanged):
+
</ins><span class="cx"> 2021-10-11  Russell Epstein  <repstein@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Cherry-pick r283846. rdar://problem/84117092
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitGPUProcessGPUProcesscpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.cpp       2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.cpp  2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -348,6 +348,12 @@
</span><span class="cx"> {
</span><span class="cx">     MockRealtimeMediaSourceCenter::resetDevices();
</span><span class="cx"> }
</span><ins>+
+void GPUProcess::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted(isInterrupted);
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitGPUProcessGPUProcessh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.h 2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.h    2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -132,6 +132,7 @@
</span><span class="cx">     void clearMockMediaDevices();
</span><span class="cx">     void removeMockMediaDevice(const String& persistentId);
</span><span class="cx">     void resetMockMediaDevices();
</span><ins>+    void setMockCameraIsInterrupted(bool);
</ins><span class="cx">     bool setCaptureAttributionString(const String&);
</span><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(MAC)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitGPUProcessGPUProcessmessagesin"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.messages.in (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.messages.in       2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/GPUProcess/GPUProcess.messages.in  2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx">     ClearMockMediaDevices();
</span><span class="cx">     RemoveMockMediaDevice(String persistentId);
</span><span class="cx">     ResetMockMediaDevices();
</span><ins>+    SetMockCameraIsInterrupted(bool isInterrupted);
</ins><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     DisplayConfigurationChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitUIProcessAPICWKPagecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPage.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPage.cpp      2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPage.cpp 2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -3154,7 +3154,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-WK_EXPORT bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef)
</del><ins>+bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef)
</ins><span class="cx"> {
</span><span class="cx"> #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
</span><span class="cx">     return MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled();
</span><span class="lines">@@ -3163,6 +3163,15 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WKPageSetMockCameraIsInterrupted(WKPageRef pageRef, bool isInterrupted)
+{
+    CRASH_IF_SUSPENDED;
+#if ENABLE(MEDIA_STREAM) && ENABLE(GPU_PROCESS)
+    auto& gpuProcess = toImpl(pageRef)->process().processPool().ensureGPUProcess();
+    gpuProcess.setMockCameraIsInterrupted(isInterrupted);
+#endif
+}
+
</ins><span class="cx"> void WKPageLoadedSubresourceDomains(WKPageRef pageRef, WKPageLoadedSubresourceDomainsFunction callback, void* callbackContext)
</span><span class="cx"> {
</span><span class="cx">     CRASH_IF_SUSPENDED;
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitUIProcessAPICWKPagePrivateh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPagePrivate.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPagePrivate.h 2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKPagePrivate.h    2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -197,6 +197,7 @@
</span><span class="cx"> 
</span><span class="cx"> WK_EXPORT void WKPageSetMockCameraOrientation(WKPageRef page, uint64_t orientation);
</span><span class="cx"> WK_EXPORT bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef page);
</span><ins>+WK_EXPORT void WKPageSetMockCameraIsInterrupted(WKPageRef page, bool isInterrupted);
</ins><span class="cx"> 
</span><span class="cx"> typedef void (*WKPageLoadedSubresourceDomainsFunction)(WKArrayRef domains, void* functionContext);
</span><span class="cx"> WK_EXPORT void WKPageLoadedSubresourceDomains(WKPageRef page, WKPageLoadedSubresourceDomainsFunction callback, void* callbackContext);
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitUIProcessGPUGPUProcessProxycpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp       2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp  2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -310,6 +310,11 @@
</span><span class="cx"> {
</span><span class="cx">     send(Messages::GPUProcess::ResetMockMediaDevices { }, 0);
</span><span class="cx"> }
</span><ins>+
+void GPUProcessProxy::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    send(Messages::GPUProcess::SetMockCameraIsInterrupted { isInterrupted }, 0);
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> void GPUProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitUIProcessGPUGPUProcessProxyh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h 2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h    2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">     void clearMockMediaDevices();
</span><span class="cx">     void removeMockMediaDevice(const String&);
</span><span class="cx">     void resetMockMediaDevices();
</span><ins>+    void setMockCameraIsInterrupted(bool);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void removeSession(PAL::SessionID);
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitWebProcesscocoaRemoteRealtimeAudioSourceh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeAudioSource.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeAudioSource.h    2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeAudioSource.h       2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -69,6 +69,7 @@
</span><span class="cx">     void captureFailed() final;
</span><span class="cx"> 
</span><span class="cx">     void remoteAudioSamplesAvailable(const MediaTime&, const WebCore::PlatformAudioData&, const WebCore::AudioStreamDescription&, size_t);
</span><ins>+    void sourceMutedChanged(bool value) { notifyMutedChange(value); }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     RemoteRealtimeAudioSource(WebCore::RealtimeMediaSourceIdentifier, const WebCore::CaptureDevice&, const WebCore::MediaConstraints*, String&& name, String&& hashSalt, UserMediaCaptureManager&, bool shouldCaptureInGPUProcess);
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitWebProcesscocoaRemoteRealtimeVideoSourceh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeVideoSource.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeVideoSource.h    2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/RemoteRealtimeVideoSource.h       2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -67,6 +67,7 @@
</span><span class="cx">     void captureFailed() final;
</span><span class="cx"> 
</span><span class="cx">     void videoSampleAvailable(WebCore::MediaSample&, WebCore::IntSize);
</span><ins>+    void sourceMutedChanged(bool value) { notifyMutedChange(value); }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     RemoteRealtimeVideoSource(WebCore::RealtimeMediaSourceIdentifier, const WebCore::CaptureDevice&, const WebCore::MediaConstraints*, String&& name, String&& hashSalt, UserMediaCaptureManager&, bool shouldCaptureInGPUProcess);
</span></span></pre></div>
<a id="branchessafari612branchSourceWebKitWebProcesscocoaUserMediaCaptureManagercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp    2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp       2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -137,9 +137,9 @@
</span><span class="cx"> void UserMediaCaptureManager::sourceMutedChanged(RealtimeMediaSourceIdentifier id, bool muted)
</span><span class="cx"> {
</span><span class="cx">     if (auto source = m_audioSources.get(id))
</span><del>-        source->setMuted(muted);
</del><ins>+        source->sourceMutedChanged(muted);
</ins><span class="cx">     else if (auto source = m_videoSources.get(id))
</span><del>-        source->setMuted(muted);
</del><ins>+        source->sourceMutedChanged(muted);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void UserMediaCaptureManager::sourceSettingsChanged(RealtimeMediaSourceIdentifier id, RealtimeMediaSourceSettings&& settings)
</span></span></pre></div>
<a id="branchessafari612branchToolsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Tools/ChangeLog (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Tools/ChangeLog       2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Tools/ChangeLog  2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -1,3 +1,108 @@
</span><ins>+2021-10-15  Russell Epstein  <repstein@apple.com>
+
+        Cherry-pick r283033. rdar://problem/83953190
+
+    [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+    https://bugs.webkit.org/show_bug.cgi?id=230538
+    <rdar://problem/83355705>
+    
+    Reviewed by Eric Carlson.
+    
+    Source/WebCore:
+    
+    Add support for interrupting mock cameras.
+    Update internals to handle the case of out of main thread videoSampleAvailable calls.
+    
+    Update Page::setMuted to trigger setMuted logic even if Page muted state did not change.
+    This ensures we can restart capture in case a track is muted without the page being muted itself.
+    
+    When a source is muted and is in producing data state, it is interrupted.
+    When setMuted(false) is called, we need to uninterrupt.
+    To do so, we do a stop/start cycle
+    
+    Test: fast/mediastream/media-stream-video-track-interrupted.html
+    
+    * page/Page.cpp:
+    (WebCore::Page::setMuted):
+    * platform/mediastream/RealtimeMediaSource.cpp:
+    (WebCore::RealtimeMediaSource::setMuted):
+    * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+    (WebCore::MockRealtimeMediaSourceCenter::setMockCameraIsInterrupted):
+    * platform/mock/MockRealtimeMediaSourceCenter.h:
+    * platform/mock/MockRealtimeVideoSource.cpp:
+    (WebCore::MockRealtimeVideoSource::MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::~MockRealtimeVideoSource):
+    (WebCore::MockRealtimeVideoSource::setIsInterrupted):
+    * platform/mock/MockRealtimeVideoSource.h:
+    * testing/Internals.cpp:
+    (WebCore::Internals::videoSampleAvailable):
+    * testing/Internals.h:
+    
+    Source/WebKit:
+    
+    Add support for mock capture interruption.
+    When receiving a notification that GPUProcess source is muted, we consider it is interrupted.
+    In that case, we notify the source is muted instead of calling setMuted (which would set the source as muted AND stop producing data).
+    It is important to not stop the source so that it can continue receiving interruption notifications.
+    
+    * GPUProcess/GPUProcess.cpp:
+    (WebKit::GPUProcess::setMockCameraIsInterrupted):
+    * GPUProcess/GPUProcess.h:
+    * GPUProcess/GPUProcess.messages.in:
+    * UIProcess/API/C/WKPage.cpp:
+    (WKPageIsMockRealtimeMediaSourceCenterEnabled):
+    (WKPageSetMockCameraIsInterrupted):
+    * UIProcess/API/C/WKPagePrivate.h:
+    * UIProcess/GPU/GPUProcessProxy.cpp:
+    (WebKit::GPUProcessProxy::setMockCameraIsInterrupted):
+    * UIProcess/GPU/GPUProcessProxy.h:
+    * WebProcess/cocoa/RemoteRealtimeAudioSource.h:
+    * WebProcess/cocoa/RemoteRealtimeVideoSource.h:
+    * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+    (WebKit::UserMediaCaptureManager::sourceMutedChanged):
+    
+    Tools:
+    
+    Add mock API to mock camera interruption.
+    
+    * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+    * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+    (WTR::TestRunner::setMockCameraIsInterrupted):
+    * WebKitTestRunner/InjectedBundle/TestRunner.h:
+    * WebKitTestRunner/TestController.cpp:
+    (WTR::TestController::setMockCameraIsInterrupted):
+    * WebKitTestRunner/TestController.h:
+    * WebKitTestRunner/TestInvocation.cpp:
+    (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+    
+    LayoutTests:
+    
+    * fast/mediastream/media-stream-video-track-interrupted-expected.txt: Added.
+    * fast/mediastream/media-stream-video-track-interrupted.html: Added.
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@283033 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-09-24  Youenn Fablet  <youenn@apple.com>
+
+            [IOS 15] Video track does not get unmuted in case of tab was inactive less than ~500 ms
+            https://bugs.webkit.org/show_bug.cgi?id=230538
+            <rdar://problem/83355705>
+
+            Reviewed by Eric Carlson.
+
+            Add mock API to mock camera interruption.
+
+            * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+            * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+            (WTR::TestRunner::setMockCameraIsInterrupted):
+            * WebKitTestRunner/InjectedBundle/TestRunner.h:
+            * WebKitTestRunner/TestController.cpp:
+            (WTR::TestController::setMockCameraIsInterrupted):
+            * WebKitTestRunner/TestController.h:
+            * WebKitTestRunner/TestInvocation.cpp:
+            (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
</ins><span class="cx"> 2021-10-12  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Apply patch. rdar://problem/84130892
</span></span></pre></div>
<a id="branchessafari612branchToolsWebKitTestRunnerInjectedBundleBindingsTestRunneridl"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl    2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -388,6 +388,7 @@
</span><span class="cx">     undefined resetMockMediaDevices();
</span><span class="cx">     undefined setMockCameraOrientation(unsigned long orientation);
</span><span class="cx">     boolean isMockRealtimeMediaSourceCenterEnabled();
</span><ins>+    undefined setMockCameraIsInterrupted(boolean isInterrupted);
</ins><span class="cx"> 
</span><span class="cx">     boolean hasAppBoundSession();
</span><span class="cx">     undefined clearAppBoundSession();
</span></span></pre></div>
<a id="branchessafari612branchToolsWebKitTestRunnerInjectedBundleTestRunnercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp  2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp     2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -1824,6 +1824,11 @@
</span><span class="cx">     return postSynchronousMessageReturningBoolean("IsMockRealtimeMediaSourceCenterEnabled");
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void TestRunner::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    postSynchronousMessage("SetMockCameraIsInterrupted", isInterrupted);
+}
+
</ins><span class="cx"> #if ENABLE(GAMEPAD)
</span><span class="cx"> 
</span><span class="cx"> void TestRunner::connectMockGamepad(unsigned index)
</span></span></pre></div>
<a id="branchessafari612branchToolsWebKitTestRunnerInjectedBundleTestRunnerh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h    2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h       2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -502,6 +502,7 @@
</span><span class="cx">     void resetMockMediaDevices();
</span><span class="cx">     void setMockCameraOrientation(unsigned);
</span><span class="cx">     bool isMockRealtimeMediaSourceCenterEnabled();
</span><ins>+    void setMockCameraIsInterrupted(bool);
</ins><span class="cx"> 
</span><span class="cx">     bool hasAppBoundSession();
</span><span class="cx">     void clearAppBoundSession();
</span></span></pre></div>
<a id="branchessafari612branchToolsWebKitTestRunnerTestControllercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Tools/WebKitTestRunner/TestController.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Tools/WebKitTestRunner/TestController.cpp     2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Tools/WebKitTestRunner/TestController.cpp        2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -3493,6 +3493,11 @@
</span><span class="cx">     return WKPageIsMockRealtimeMediaSourceCenterEnabled(m_mainWebView->page());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void TestController::setMockCameraIsInterrupted(bool isInterrupted)
+{
+    WKPageSetMockCameraIsInterrupted(m_mainWebView->page(), isInterrupted);
+}
+
</ins><span class="cx"> struct InAppBrowserPrivacyCallbackContext {
</span><span class="cx">     explicit InAppBrowserPrivacyCallbackContext(TestController& controller)
</span><span class="cx">         : testController(controller)
</span></span></pre></div>
<a id="branchessafari612branchToolsWebKitTestRunnerTestControllerh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Tools/WebKitTestRunner/TestController.h (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Tools/WebKitTestRunner/TestController.h       2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Tools/WebKitTestRunner/TestController.h  2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -307,6 +307,7 @@
</span><span class="cx">     void resetMockMediaDevices();
</span><span class="cx">     void setMockCameraOrientation(uint64_t);
</span><span class="cx">     bool isMockRealtimeMediaSourceCenterEnabled() const;
</span><ins>+    void setMockCameraIsInterrupted(bool);
</ins><span class="cx">     bool hasAppBoundSession();
</span><span class="cx"> 
</span><span class="cx">     void injectUserScript(WKStringRef);
</span></span></pre></div>
<a id="branchessafari612branchToolsWebKitTestRunnerTestInvocationcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Tools/WebKitTestRunner/TestInvocation.cpp (284274 => 284275)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Tools/WebKitTestRunner/TestInvocation.cpp     2021-10-15 21:45:12 UTC (rev 284274)
+++ branches/safari-612-branch/Tools/WebKitTestRunner/TestInvocation.cpp        2021-10-15 22:16:20 UTC (rev 284275)
</span><span class="lines">@@ -962,6 +962,11 @@
</span><span class="cx">     if (WKStringIsEqualToUTF8CString(messageName, "IsMockRealtimeMediaSourceCenterEnabled"))
</span><span class="cx">         return adoptWK(WKBooleanCreate(TestController::singleton().isMockRealtimeMediaSourceCenterEnabled()));
</span><span class="cx">     
</span><ins>+    if (WKStringIsEqualToUTF8CString(messageName, "SetMockCameraIsInterrupted")) {
+        TestController::singleton().setMockCameraIsInterrupted(booleanValue(messageBody));
+        return nullptr;
+    }
+
</ins><span class="cx">     if (WKStringIsEqualToUTF8CString(messageName, "HasAppBoundSession"))
</span><span class="cx">         return adoptWK(WKBooleanCreate(TestController::singleton().hasAppBoundSession()));
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>