- Revision
- 218140
- Author
- eric.carl...@apple.com
- Date
- 2017-06-12 14:56:55 -0700 (Mon, 12 Jun 2017)
Log Message
[MediaStream iOS] If a capturing tab is muted while it is in the background, it can not be unmuted
https://bugs.webkit.org/show_bug.cgi?id=173268
<rdar://problem/32259809>
Reviewed by Jer Noble.
No new tests, tested manually.
* Modules/mediastream/MediaStream.cpp:
(WebCore::MediaStream::startProducingData): Mute the private stream if page capture is muted.
(WebCore::MediaStream::mediaState): Set new interrupted state.
* dom/Document.cpp:
(WebCore::Document::notifyMediaCaptureOfVisibilityChanged): Don't track "muted for visibility"
state, let the source center deal with it.
* dom/Document.h:
* page/MediaProducer.h: Add bits for interrupted audio and video capture.
* platform/mediastream/RealtimeMediaSource.cpp:
(WebCore::RealtimeMediaSource::RealtimeMediaSource): Drive-by fix: delete m_suppressNotifications,
it isn't used.
(WebCore::RealtimeMediaSource::setInterrupted): New. Mute capture when an interruption begins,
and unmute when it ends in an unmuted page.
(WebCore::RealtimeMediaSource::setMuted): Do not unmute if interrupted.
(WebCore::RealtimeMediaSource::settingsDidChange): Don't check m_suppressNotifications, it is
never set.
* platform/mediastream/RealtimeMediaSource.h:
* platform/mediastream/RealtimeMediaSourceCenter.cpp:
(WebCore::RealtimeMediaSourceCenter::setVideoCapturePageState): Renamed from
setVideoCaptureMutedForPageVisibility.
(WebCore::RealtimeMediaSourceCenter::setVideoCaptureMutedForPageVisibility): Deleted.
* platform/mediastream/RealtimeMediaSourceCenter.h:
* platform/mediastream/mac/AVMediaCaptureSource.h:
* platform/mediastream/mac/AVMediaCaptureSource.mm:
(WebCore::AVMediaCaptureSource::stopProducingData): Clear m_interruption because the session
has been deleted, so we will never get an "end interruption" notification.
(WebCore::AVMediaCaptureSource::captureSessionIsRunningDidChange): Don't return early if
the muted state needs to be updated.
(WebCore::AVMediaCaptureSource::captureSessionEndInterruption): Return early if the session
has been cleared.
(WebCore::AVMediaCaptureSource::interrupted): New.
* platform/mediastream/mac/AVVideoCaptureSource.mm:
(WebCore::AVVideoCaptureSourceFactory::setVideoCapturePageState): Renamed from
setVideoCaptureMutedForPageVisibility.
(WebCore::AVVideoCaptureSourceFactory::setVideoCaptureMutedForPageVisibility): Deleted.
* platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSourceFactory::setVideoCapturePageState): Ditto.
(WebCore::MockRealtimeVideoSourceFactory::setVideoCaptureMutedForPageVisibility): Deleted.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (218139 => 218140)
--- trunk/Source/WebCore/ChangeLog 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/ChangeLog 2017-06-12 21:56:55 UTC (rev 218140)
@@ -1,3 +1,59 @@
+2017-06-12 Eric Carlson <eric.carl...@apple.com>
+
+ [MediaStream iOS] If a capturing tab is muted while it is in the background, it can not be unmuted
+ https://bugs.webkit.org/show_bug.cgi?id=173268
+ <rdar://problem/32259809>
+
+ Reviewed by Jer Noble.
+
+ No new tests, tested manually.
+
+ * Modules/mediastream/MediaStream.cpp:
+ (WebCore::MediaStream::startProducingData): Mute the private stream if page capture is muted.
+ (WebCore::MediaStream::mediaState): Set new interrupted state.
+
+ * dom/Document.cpp:
+ (WebCore::Document::notifyMediaCaptureOfVisibilityChanged): Don't track "muted for visibility"
+ state, let the source center deal with it.
+ * dom/Document.h:
+
+ * page/MediaProducer.h: Add bits for interrupted audio and video capture.
+
+ * platform/mediastream/RealtimeMediaSource.cpp:
+ (WebCore::RealtimeMediaSource::RealtimeMediaSource): Drive-by fix: delete m_suppressNotifications,
+ it isn't used.
+ (WebCore::RealtimeMediaSource::setInterrupted): New. Mute capture when an interruption begins,
+ and unmute when it ends in an unmuted page.
+ (WebCore::RealtimeMediaSource::setMuted): Do not unmute if interrupted.
+ (WebCore::RealtimeMediaSource::settingsDidChange): Don't check m_suppressNotifications, it is
+ never set.
+ * platform/mediastream/RealtimeMediaSource.h:
+
+ * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+ (WebCore::RealtimeMediaSourceCenter::setVideoCapturePageState): Renamed from
+ setVideoCaptureMutedForPageVisibility.
+ (WebCore::RealtimeMediaSourceCenter::setVideoCaptureMutedForPageVisibility): Deleted.
+ * platform/mediastream/RealtimeMediaSourceCenter.h:
+
+ * platform/mediastream/mac/AVMediaCaptureSource.h:
+ * platform/mediastream/mac/AVMediaCaptureSource.mm:
+ (WebCore::AVMediaCaptureSource::stopProducingData): Clear m_interruption because the session
+ has been deleted, so we will never get an "end interruption" notification.
+ (WebCore::AVMediaCaptureSource::captureSessionIsRunningDidChange): Don't return early if
+ the muted state needs to be updated.
+ (WebCore::AVMediaCaptureSource::captureSessionEndInterruption): Return early if the session
+ has been cleared.
+ (WebCore::AVMediaCaptureSource::interrupted): New.
+
+ * platform/mediastream/mac/AVVideoCaptureSource.mm:
+ (WebCore::AVVideoCaptureSourceFactory::setVideoCapturePageState): Renamed from
+ setVideoCaptureMutedForPageVisibility.
+ (WebCore::AVVideoCaptureSourceFactory::setVideoCaptureMutedForPageVisibility): Deleted.
+
+ * platform/mock/MockRealtimeVideoSource.cpp:
+ (WebCore::MockRealtimeVideoSourceFactory::setVideoCapturePageState): Ditto.
+ (WebCore::MockRealtimeVideoSourceFactory::setVideoCaptureMutedForPageVisibility): Deleted.
+
2017-06-12 Jiewen Tan <jiewen_...@apple.com>
[WebCrypto] Remove experimental feature flag of SubtleCrypto
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp (218139 => 218140)
--- trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp 2017-06-12 21:56:55 UTC (rev 218140)
@@ -297,8 +297,10 @@
m_isProducingData = true;
m_mediaSession->canProduceAudioChanged();
+ m_private->startProducingData();
- m_private->startProducingData();
+ if (document->page()->isMediaCaptureMuted())
+ m_private->setCaptureTracksMuted(true);
}
void MediaStream::stopProducingData()
@@ -336,23 +338,34 @@
{
MediaStateFlags state = IsNotPlaying;
- if (!m_isActive)
+ if (!m_isActive || !document() || !document()->page())
return state;
+ bool pageCaptureMuted = document()->page()->isMediaCaptureMuted();
for (const auto& track : m_trackSet.values()) {
if (!track->isCaptureTrack() || track->ended())
continue;
if (track->source().type() == RealtimeMediaSource::Type::Audio) {
- if (track->muted())
+ if (track->source().interrupted() && !pageCaptureMuted)
+ state |= HasInterruptedAudioCaptureDevice;
+ else if (track->muted())
state |= HasMutedAudioCaptureDevice;
- else if (m_isProducingData && m_private->isProducingData())
+ else if (m_isProducingData && m_private->isProducingData()) {
state |= HasActiveAudioCaptureDevice;
+ ASSERT(!track->source().interrupted());
+ ASSERT(!track->muted());
+ }
} else {
- if (track->muted())
+ if (track->source().interrupted() && !pageCaptureMuted)
+ state |= HasInterruptedVideoCaptureDevice;
+ else if (track->muted())
state |= HasMutedVideoCaptureDevice;
- else if (m_isProducingData && m_private->isProducingData())
+ else if (m_isProducingData && m_private->isProducingData()) {
state |= HasActiveVideoCaptureDevice;
+ ASSERT(!track->source().interrupted());
+ ASSERT(!track->muted());
+ }
}
}
Modified: trunk/Source/WebCore/dom/Document.cpp (218139 => 218140)
--- trunk/Source/WebCore/dom/Document.cpp 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/dom/Document.cpp 2017-06-12 21:56:55 UTC (rev 218140)
@@ -7082,16 +7082,10 @@
void Document::notifyMediaCaptureOfVisibilityChanged()
{
#if ENABLE(MEDIA_STREAM)
- if (!page() || page()->isMediaCaptureMuted()) {
- m_videoCaptureMutedForVisibilityChange = false;
+ if (!page())
return;
- }
- if (!hidden() && !m_videoCaptureMutedForVisibilityChange)
- return;
-
- m_videoCaptureMutedForVisibilityChange = hidden();
- RealtimeMediaSourceCenter::singleton().setVideoCaptureMutedForPageVisibility(m_videoCaptureMutedForVisibilityChange);
+ RealtimeMediaSourceCenter::singleton().setVideoCapturePageState(hidden(), page()->isMediaCaptureMuted());
#endif
}
Modified: trunk/Source/WebCore/dom/Document.h (218139 => 218140)
--- trunk/Source/WebCore/dom/Document.h 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/dom/Document.h 2017-06-12 21:56:55 UTC (rev 218140)
@@ -1778,7 +1778,6 @@
HashSet<HTMLMediaElement*> m_mediaStreamStateChangeElements;
String m_idHashSalt;
bool m_hasHadActiveMediaStreamTrack { false };
- bool m_videoCaptureMutedForVisibilityChange { false };
#endif
#ifndef NDEBUG
Modified: trunk/Source/WebCore/page/MediaProducer.h (218139 => 218140)
--- trunk/Source/WebCore/page/MediaProducer.h 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/page/MediaProducer.h 2017-06-12 21:56:55 UTC (rev 218140)
@@ -46,6 +46,8 @@
HasActiveVideoCaptureDevice = 1 << 12,
HasMutedAudioCaptureDevice = 1 << 13,
HasMutedVideoCaptureDevice = 1 << 14,
+ HasInterruptedAudioCaptureDevice = 1 << 15,
+ HasInterruptedVideoCaptureDevice = 1 << 15,
};
typedef unsigned MediaStateFlags;
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp (218139 => 218140)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.cpp 2017-06-12 21:56:55 UTC (rev 218140)
@@ -57,7 +57,6 @@
if (m_id.isEmpty())
m_id = createCanonicalUUIDString();
m_persistentID = m_id;
- m_suppressNotifications = false;
}
void RealtimeMediaSource::addObserver(RealtimeMediaSource::Observer& observer)
@@ -75,12 +74,28 @@
stop();
}
+void RealtimeMediaSource::setInterrupted(bool interrupted, bool pageMuted)
+{
+ if (interrupted == m_interrupted)
+ return;
+
+ m_interrupted = interrupted;
+ if (!interrupted && pageMuted)
+ return;
+
+ setMuted(interrupted);
+}
+
void RealtimeMediaSource::setMuted(bool muted)
{
if (muted)
stop();
- else
+ else {
+ if (interrupted())
+ return;
+
start();
+ }
notifyMutedChange(muted);
}
@@ -116,7 +131,7 @@
{
ASSERT(isMainThread());
- if (m_pendingSettingsDidChangeNotification || m_suppressNotifications)
+ if (m_pendingSettingsDidChangeNotification)
return;
m_pendingSettingsDidChangeNotification = true;
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (218139 => 218140)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2017-06-12 21:56:55 UTC (rev 218140)
@@ -120,7 +120,7 @@
public:
virtual ~VideoCaptureFactory() = default;
virtual CaptureSourceOrError createVideoCaptureSource(const String& videoDeviceID, const MediaConstraints*) = 0;
- virtual void setVideoCaptureMutedForPageVisibility(bool) { }
+ virtual void setVideoCapturePageState(bool, bool) { }
protected:
VideoCaptureFactory() = default;
@@ -143,6 +143,9 @@
bool muted() const { return m_muted; }
void setMuted(bool);
+
+ virtual bool interrupted() const { return m_interrupted; }
+ virtual void setInterrupted(bool, bool);
bool enabled() const { return m_enabled; }
void setEnabled(bool);
@@ -265,8 +268,8 @@
bool m_echoCancellation { false };
bool m_pendingSettingsDidChangeNotification { false };
- bool m_suppressNotifications { true };
bool m_isProducingData { false };
+ bool m_interrupted { false };
};
struct CaptureSourceOrError {
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp (218139 => 218140)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp 2017-06-12 21:56:55 UTC (rev 218140)
@@ -334,9 +334,9 @@
validHandler(WTFMove(audioSourceIds), WTFMove(videoSourceIds), WTFMove(deviceIdentifierHashSalt));
}
-void RealtimeMediaSourceCenter::setVideoCaptureMutedForPageVisibility(bool shouldMute)
+void RealtimeMediaSourceCenter::setVideoCapturePageState(bool interrupted, bool pageMuted)
{
- videoFactory().setVideoCaptureMutedForPageVisibility(shouldMute);
+ videoFactory().setVideoCapturePageState(interrupted, pageMuted);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h (218139 => 218140)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h 2017-06-12 21:56:55 UTC (rev 218140)
@@ -100,7 +100,7 @@
void removeDevicesChangedObserver(DevicesChangedObserverToken);
void captureDevicesChanged();
- void setVideoCaptureMutedForPageVisibility(bool);
+ void setVideoCapturePageState(bool, bool);
protected:
RealtimeMediaSourceCenter();
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h (218139 => 218140)
--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h 2017-06-12 21:56:55 UTC (rev 218140)
@@ -96,6 +96,8 @@
bool isCaptureSource() const final { return true; }
+ bool interrupted() const final;
+
void initializeSettings();
void initializeCapabilities();
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm (218139 => 218140)
--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2017-06-12 21:56:55 UTC (rev 218140)
@@ -188,6 +188,7 @@
if ([m_session isRunning])
[m_session stopRunning];
+ m_interruption = InterruptionReason::None;
#if PLATFORM(IOS)
m_session = nullptr;
#endif
@@ -264,7 +265,7 @@
void AVMediaCaptureSource::captureSessionIsRunningDidChange(bool state)
{
scheduleDeferredTask([this, state] {
- if (state == m_isRunning)
+ if ((state == m_isRunning) && (state == !muted()))
return;
m_isRunning = state;
@@ -293,7 +294,7 @@
InterruptionReason reason = m_interruption;
m_interruption = InterruptionReason::None;
- if (reason != InterruptionReason::VideoNotAllowedInSideBySide || m_isRunning)
+ if (reason != InterruptionReason::VideoNotAllowedInSideBySide || m_isRunning || !m_session)
return;
[m_session startRunning];
@@ -317,6 +318,14 @@
return nullptr;
}
+bool AVMediaCaptureSource::interrupted() const
+{
+ if (m_interruption != InterruptionReason::None)
+ return true;
+
+ return RealtimeMediaSource::interrupted();
+}
+
NSArray<NSString*>* sessionKVOProperties()
{
static NSArray* keys = [@[@"running"] retain];
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (218139 => 218140)
--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm 2017-06-12 21:56:55 UTC (rev 218140)
@@ -125,10 +125,10 @@
#if PLATFORM(IOS)
private:
- void setVideoCaptureMutedForPageVisibility(bool shouldMute)
+ void setVideoCapturePageState(bool interrupted, bool pageMuted)
{
if (activeSource())
- activeSource()->setMuted(shouldMute);
+ activeSource()->setInterrupted(interrupted, pageMuted);
}
#endif
};
Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (218139 => 218140)
--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp 2017-06-12 21:35:25 UTC (rev 218139)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp 2017-06-12 21:56:55 UTC (rev 218140)
@@ -63,10 +63,10 @@
}
#if PLATFORM(IOS)
private:
- void setVideoCaptureMutedForPageVisibility(bool shouldMute)
+ void setVideoCapturePageState(bool interrupted, bool pageMuted)
{
if (activeSource())
- activeSource()->setMuted(shouldMute);
+ activeSource()->setInterrupted(interrupted, pageMuted);
}
#endif
};