Diff
Modified: trunk/Source/WebCore/ChangeLog (216171 => 216172)
--- trunk/Source/WebCore/ChangeLog 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/ChangeLog 2017-05-04 04:48:07 UTC (rev 216172)
@@ -1,3 +1,48 @@
+2017-05-03 Eric Carlson <eric.carl...@apple.com>
+
+ [MediaStream] Allow host application to enable/disable media capture
+ https://bugs.webkit.org/show_bug.cgi?id=171292
+ <rdar://problem/31821492>
+
+ Reviewed by Jer Noble.
+
+ No new layout tests, added an API test instead.
+
+ * Modules/mediastream/MediaStream.cpp:
+ (WebCore::MediaStream::endStream): New, stop all tracks.
+ * Modules/mediastream/MediaStream.h:
+
+ * Modules/mediastream/MediaStreamRegistry.cpp:
+ (WebCore::MediaStreamRegistry::unregisterStream): Minor cleanup.
+ (WebCore::MediaStreamRegistry::forEach): New, call the lambda with each stream.
+ (WebCore::MediaStreamRegistry::MediaStreamRegistry): Deleted, unused.
+ * Modules/mediastream/MediaStreamRegistry.h:
+
+ * Modules/mediastream/MediaStreamTrack.cpp:
+ (WebCore::MediaStreamTrack::stopTrack): Add parameter so caller can specify if an 'ended'
+ event should be sent or not.
+ (WebCore::MediaStreamTrack::trackMutedChanged): Don't post an event if the track has ended.
+ * Modules/mediastream/MediaStreamTrack.h:
+
+ * dom/Document.cpp:
+ (WebCore::Document::stopMediaCapture): Stop all streams in the document.
+ * dom/Document.h:
+
+ * page/Page.cpp:
+ (WebCore::Page::stopMediaCapture): Stop all streams.
+ * page/Page.h:
+
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode): Display a black frame
+ when the stream ends.
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::activeStatusChanged): Signal a characteristics
+ change to HTMLMediaElement refresh state.
+ * platform/mediastream/MediaStreamPrivate.h:
+
+ * platform/mediastream/mac/AVMediaCaptureSource.mm:
+ (WebCore::AVMediaCaptureSource::stopProducingData): Don't return early if the session isn't
+ running, we always need to clear m_session on iOS.
+
2017-05-03 John Wilander <wilan...@apple.com>
Resource Load Statistics: Remove all statistics for modifiedSince website data removals
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp (216171 => 216172)
--- trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -314,6 +314,12 @@
m_private->stopProducingData();
}
+void MediaStream::endStream()
+{
+ for (auto& track : m_trackSet.values())
+ track->stopTrack(MediaStreamTrack::StopMode::PostEvent);
+}
+
void MediaStream::pageMutedStateDidChange()
{
if (!m_isActive)
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStream.h (216171 => 216172)
--- trunk/Source/WebCore/Modules/mediastream/MediaStream.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStream.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -91,6 +91,8 @@
void startProducingData();
void stopProducingData();
+ void endStream();
+
// EventTarget
EventTargetInterface eventTargetInterface() const final { return MediaStreamEventTargetInterfaceType; }
ScriptExecutionContext* scriptExecutionContext() const final { return ContextDestructionObserver::scriptExecutionContext(); }
@@ -106,6 +108,8 @@
void addTrackFromPlatform(Ref<MediaStreamTrack>&&);
+ Document* document() const;
+
protected:
MediaStream(ScriptExecutionContext&, const MediaStreamTrackVector&);
MediaStream(ScriptExecutionContext&, Ref<MediaStreamPrivate>&&);
@@ -158,8 +162,6 @@
void setIsActive(bool);
void statusDidChange();
- Document* document() const;
-
MediaStreamTrackVector trackVectorForType(RealtimeMediaSource::Type) const;
Ref<MediaStreamPrivate> m_private;
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamRegistry.cpp (216171 => 216172)
--- trunk/Source/WebCore/Modules/mediastream/MediaStreamRegistry.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamRegistry.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -62,10 +62,6 @@
return m_mediaStreams.get(url);
}
-MediaStreamRegistry::MediaStreamRegistry()
-{
-}
-
MediaStream* MediaStreamRegistry::lookUp(const URL& url) const
{
return static_cast<MediaStream*>(lookup(url.string()));
@@ -84,21 +80,16 @@
void MediaStreamRegistry::unregisterStream(MediaStream& stream)
{
- Vector<MediaStream*>& allStreams = mediaStreams();
+ auto& allStreams = mediaStreams();
size_t pos = allStreams.find(&stream);
if (pos != notFound)
allStreams.remove(pos);
}
-MediaStream* MediaStreamRegistry::lookUp(const MediaStreamPrivate& privateStream) const
+void MediaStreamRegistry::forEach(std::function<void(MediaStream&)> callback) const
{
- Vector<MediaStream*>& allStreams = mediaStreams();
- for (auto& stream : allStreams) {
- if (&stream->privateStream() == &privateStream)
- return stream;
- }
-
- return nullptr;
+ for (auto& stream : mediaStreams())
+ callback(*stream);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamRegistry.h (216171 => 216172)
--- trunk/Source/WebCore/Modules/mediastream/MediaStreamRegistry.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamRegistry.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -54,10 +54,11 @@
void unregisterStream(MediaStream&);
MediaStream* lookUp(const URL&) const;
- MediaStream* lookUp(const MediaStreamPrivate&) const;
+ void forEach(std::function<void(MediaStream&)>) const;
+
private:
- MediaStreamRegistry();
+ MediaStreamRegistry() = default;
HashMap<String, RefPtr<MediaStream>> m_mediaStreams;
};
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp (216171 => 216172)
--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -113,7 +113,7 @@
return MediaStreamTrack::create(*scriptExecutionContext(), m_private->clone());
}
-void MediaStreamTrack::stopTrack()
+void MediaStreamTrack::stopTrack(StopMode mode)
{
// NOTE: this method is called when the "stop" method is called from JS, using the "ImplementedAs" IDL attribute.
// This is done because ActiveDOMObject requires a "stop" method.
@@ -121,8 +121,13 @@
if (ended())
return;
+ // An 'ended' event is not posted if m_ended is true when trackEnded is called, so set it now if we are
+ // not supposed to post the event.
+ if (mode == StopMode::Silently)
+ m_ended = true;
+
+ m_private->endTrack();
m_ended = true;
- m_private->endTrack();
}
MediaStreamTrack::TrackSettings MediaStreamTrack::getSettings() const
@@ -303,7 +308,7 @@
void MediaStreamTrack::trackMutedChanged(MediaStreamTrackPrivate&)
{
- if (scriptExecutionContext()->activeDOMObjectsAreSuspended() || scriptExecutionContext()->activeDOMObjectsAreStopped())
+ if (scriptExecutionContext()->activeDOMObjectsAreSuspended() || scriptExecutionContext()->activeDOMObjectsAreStopped() || m_ended)
return;
AtomicString eventType = muted() ? eventNames().muteEvent : eventNames().unmuteEvent;
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h (216171 => 216172)
--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -71,8 +71,10 @@
bool ended() const;
Ref<MediaStreamTrack> clone();
- void stopTrack();
+ enum class StopMode { Silently, PostEvent };
+ void stopTrack(StopMode = StopMode::Silently);
+
bool isCaptureTrack() const;
struct TrackSettings {
Modified: trunk/Source/WebCore/dom/Document.cpp (216171 => 216172)
--- trunk/Source/WebCore/dom/Document.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/dom/Document.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -271,6 +271,11 @@
#include "XSLTProcessor.h"
#endif
+#if ENABLE(MEDIA_STREAM)
+#include "MediaStream.h"
+#include "MediaStreamRegistry.h"
+#endif
+
using namespace WTF;
using namespace Unicode;
@@ -6972,4 +6977,14 @@
m_orientationNotifier.orientationChanged(orientation);
}
+#if ENABLE(MEDIA_STREAM)
+void Document::stopMediaCapture()
+{
+ MediaStreamRegistry::shared().forEach([this](MediaStream& stream) {
+ if (stream.document() == this)
+ stream.endStream();
+ });
+}
+#endif
+
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/Document.h (216171 => 216172)
--- trunk/Source/WebCore/dom/Document.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/dom/Document.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -1277,6 +1277,7 @@
bool hasHadActiveMediaStreamTrack() const { return m_hasHadActiveMediaStreamTrack; }
void setDeviceIDHashSalt(const String& salt) { m_idHashSalt = salt; }
String deviceIDHashSalt() const { return m_idHashSalt; }
+ void stopMediaCapture();
#endif
// FIXME: Find a better place for this functionality.
Modified: trunk/Source/WebCore/page/Page.cpp (216171 => 216172)
--- trunk/Source/WebCore/page/Page.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/page/Page.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -1532,6 +1532,18 @@
}
}
+void Page::stopMediaCapture()
+{
+#if ENABLE(MEDIA_STREAM)
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+
+ frame->document()->stopMediaCapture();
+ }
+#endif
+}
+
#if ENABLE(MEDIA_SESSION)
void Page::handleMediaEvent(MediaEventType eventType)
{
Modified: trunk/Source/WebCore/page/Page.h (216171 => 216172)
--- trunk/Source/WebCore/page/Page.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/page/Page.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -530,6 +530,7 @@
bool isAudioMuted() const { return m_mutedState & MediaProducer::AudioIsMuted; }
bool isMediaCaptureMuted() const { return m_mutedState & MediaProducer::CaptureDevicesAreMuted; };
WEBCORE_EXPORT void setMuted(MediaProducer::MutedStateFlags);
+ WEBCORE_EXPORT void stopMediaCapture();
#if ENABLE(MEDIA_SESSION)
WEBCORE_EXPORT void handleMediaEvent(MediaEventType);
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (216171 => 216172)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm 2017-05-04 04:48:07 UTC (rev 216172)
@@ -580,21 +580,21 @@
MediaPlayerPrivateMediaStreamAVFObjC::DisplayMode MediaPlayerPrivateMediaStreamAVFObjC::currentDisplayMode() const
{
- if (m_ended || m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)
+ if (m_intrinsicSize.isEmpty() || !metaDataAvailable() || !m_sampleBufferDisplayLayer)
return None;
if (auto* track = m_mediaStreamPrivate->activeVideoTrack()) {
- if (!track->enabled() || track->muted())
+ if (!track->enabled() || track->muted() || track->ended())
return PaintItBlack;
}
- if (playing()) {
+ if (playing() && !m_ended) {
if (!m_mediaStreamPrivate->isProducingData())
return PausedImage;
return LivePreview;
}
- if (m_playbackState == PlaybackState::None)
+ if (m_playbackState == PlaybackState::None || m_ended)
return PaintItBlack;
return PausedImage;
@@ -768,8 +768,10 @@
if (ended != m_ended) {
m_ended = ended;
- if (m_player)
+ if (m_player) {
m_player->timeChanged();
+ m_player->characteristicChanged();
+ }
}
});
}
Modified: trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h (216171 => 216172)
--- trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/platform/mediastream/MediaStreamPrivate.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -95,6 +95,8 @@
void stopProducingData();
bool isProducingData() const;
+ void endStream();
+
bool hasVideo() const;
bool hasAudio() const;
bool muted() const;
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm (216171 => 216172)
--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2017-05-04 04:48:07 UTC (rev 216172)
@@ -181,11 +181,14 @@
void AVMediaCaptureSource::stopProducingData()
{
- if (!m_session || ![m_session isRunning])
+ if (!m_session)
return;
[m_objcObserver removeNotificationObservers];
- [m_session stopRunning];
+
+ if ([m_session isRunning])
+ [m_session stopRunning];
+
#if PLATFORM(IOS)
m_session = nullptr;
#endif
Modified: trunk/Source/WebKit2/ChangeLog (216171 => 216172)
--- trunk/Source/WebKit2/ChangeLog 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/ChangeLog 2017-05-04 04:48:07 UTC (rev 216172)
@@ -1,3 +1,67 @@
+2017-05-03 Eric Carlson <eric.carl...@apple.com>
+
+ [MediaStream] Allow host application to enable/disable media capture
+ https://bugs.webkit.org/show_bug.cgi?id=171292
+ <rdar://problem/31821492>
+
+ Reviewed by Jer Noble.
+
+ * UIProcess/API/C/WKPage.cpp:
+ (WKPageSetMediaCaptureEnabled): New.
+ (WKPageGetMediaCaptureEnabled): New.
+ * UIProcess/API/C/WKPagePrivate.h:
+
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ (-[WKWebView _setMediaCaptureEnabled:]): New.
+ (-[WKWebView _mediaCaptureEnabled]): New.
+ * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+
+ * UIProcess/Cocoa/UIDelegate.mm:
+ (WebKit::UIDelegate::setDelegate): Initialize webViewRequestUserMediaAuthorizationForDevicesURLMainFrameURLDecisionHandler
+ and webViewCheckUserMediaPermissionForURLMainFrameURLFrameIdentifierDecisionHandler on macOS
+ and iOS.
+
+ * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+ (WebKit::UserMediaPermissionRequestManagerProxy::UserMediaPermissionRequestManagerProxy):
+ Initialize the rejection timer.
+ (WebKit::UserMediaPermissionRequestManagerProxy::~UserMediaPermissionRequestManagerProxy):
+ Call invalidatePendingRequests.
+ (WebKit::UserMediaPermissionRequestManagerProxy::invalidatePendingRequests): Invalidate all
+ pending requests.
+ (WebKit::UserMediaPermissionRequestManagerProxy::stopCapture): New.
+ (WebKit::UserMediaPermissionRequestManagerProxy::rejectionTimerFired): Reject a promise and
+ schedule the timer if there are any others pending.
+ (WebKit::UserMediaPermissionRequestManagerProxy::scheduleNextRejection):
+ (WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame): Don't
+ prompt the user if capture is disabled.
+ (WebKit::UserMediaPermissionRequestManagerProxy::invalidateRequests): Deleted.
+ (WebKit::UserMediaPermissionRequestManagerProxy::clearCachedState): Deleted.
+ * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+
+ * UIProcess/UserMediaProcessManager.cpp:
+ (WebKit::UserMediaProcessManager::willEnableMediaStreamInPage): Stop capture in the current
+ page on iOS.
+ (WebKit::UserMediaProcessManager::setCaptureEnabled):
+ * UIProcess/UserMediaProcessManager.h:
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::setMediaCaptureEnabled):
+
+ * UIProcess/WebPageProxy.h:
+ (WebKit::WebPageProxy::mediaCaptureEnabled):
+
+ * WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp:
+ (WebKit::UserMediaPermissionRequestManager::cancelPendingRequests): New, cancel all pending
+ requests.
+ (WebKit::UserMediaPermissionRequestManager::cancelUserMediaRequest): Deny the request.
+ (WebKit::UserMediaPermissionRequestManager::cancelMediaDevicesEnumeration):
+ * WebProcess/MediaStream/UserMediaPermissionRequestManager.h:
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::stopMediaCapture):
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/WebPage.messages.in:
+
2017-05-03 John Wilander <wilan...@apple.com>
Resource Load Statistics: Remove all statistics for modifiedSince website data removals
Modified: trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -2677,6 +2677,16 @@
toImpl(page)->setMuted(muted);
}
+void WKPageSetMediaCaptureEnabled(WKPageRef page, bool enabled)
+{
+ toImpl(page)->setMediaCaptureEnabled(enabled);
+}
+
+bool WKPageGetMediaCaptureEnabled(WKPageRef page)
+{
+ return toImpl(page)->mediaCaptureEnabled();
+}
+
void WKPageDidAllowPointerLock(WKPageRef page)
{
#if ENABLE(POINTER_LOCK)
Modified: trunk/Source/WebKit2/UIProcess/API/C/WKPagePrivate.h (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/API/C/WKPagePrivate.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/API/C/WKPagePrivate.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -127,6 +127,8 @@
WK_EXPORT void WKPageSetMuted(WKPageRef page, WKMediaMutedState muted);
WK_EXPORT void WKPageClearUserMediaState(WKPageRef page);
+WK_EXPORT void WKPageSetMediaCaptureEnabled(WKPageRef page, bool enabled);
+WK_EXPORT bool WKPageGetMediaCaptureEnabled(WKPageRef page);
WK_EXPORT void WKPageDidAllowPointerLock(WKPageRef page);
WK_EXPORT void WKPageDidDenyPointerLock(WKPageRef page);
Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm 2017-05-04 04:48:07 UTC (rev 216172)
@@ -4473,6 +4473,16 @@
_page->setMuted(WebCore::MediaProducer::CaptureDevicesAreMuted);
}
+- (void)_setMediaCaptureEnabled:(BOOL)enabled
+{
+ _page->setMediaCaptureEnabled(enabled);
+}
+
+- (BOOL)_mediaCaptureEnabled
+{
+ return _page->mediaCaptureEnabled();
+}
+
- (void)_setPageMuted:(_WKMediaMutedState)mutedState
{
WebCore::MediaProducer::MutedStateFlags coreState = WebCore::MediaProducer::NoneMuted;
Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -292,9 +292,11 @@
@property (nonatomic, setter=_setFullscreenDelegate:) id<_WKFullscreenDelegate> _fullscreenDelegate WK_API_AVAILABLE(macosx(WK_MAC_TBA));
@property (nonatomic, readonly) BOOL _isInFullscreen WK_API_AVAILABLE(macosx(WK_MAC_TBA));
-- (void)_muteMediaCapture;
+- (void)_muteMediaCapture WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
- (void)_setPageMuted:(_WKMediaMutedState)mutedState WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic, setter=_setMediaCaptureEnabled:) BOOL _mediaCaptureEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
@end
#if !TARGET_OS_IPHONE
Modified: trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/UIDelegate.mm 2017-05-04 04:48:07 UTC (rev 216172)
@@ -115,11 +115,11 @@
#endif
m_delegateMethods.webViewActionsForElementDefaultActions = [delegate respondsToSelector:@selector(_webView:actionsForElement:defaultActions:)];
m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint = [delegate respondsToSelector:@selector(_webView:didNotHandleTapAsClickAtPoint:)];
+ m_delegateMethods.presentingViewControllerForWebView = [delegate respondsToSelector:@selector(_presentingViewControllerForWebView:)];
+#endif
m_delegateMethods.webViewRequestUserMediaAuthorizationForDevicesURLMainFrameURLDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:)];
m_delegateMethods.webViewCheckUserMediaPermissionForURLMainFrameURLFrameIdentifierDecisionHandler = [delegate respondsToSelector:@selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:)];
m_delegateMethods.webViewMediaCaptureStateDidChange = [delegate respondsToSelector:@selector(_webView:mediaCaptureStateDidChange:)];
- m_delegateMethods.presentingViewControllerForWebView = [delegate respondsToSelector:@selector(_presentingViewControllerForWebView:)];
-#endif
m_delegateMethods.dataDetectionContextForWebView = [delegate respondsToSelector:@selector(_dataDetectionContextForWebView:)];
m_delegateMethods.webViewImageOrMediaDocumentSizeChanged = [delegate respondsToSelector:@selector(_webView:imageOrMediaDocumentSizeChanged:)];
Modified: trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -96,6 +96,7 @@
UserMediaPermissionRequestManagerProxy::UserMediaPermissionRequestManagerProxy(WebPageProxy& page)
: m_page(page)
+ , m_rejectionTimer(*this, &UserMediaPermissionRequestManagerProxy::rejectionTimerFired)
{
#if ENABLE(MEDIA_STREAM)
UserMediaProcessManager::singleton().addUserMediaPermissionRequestManagerProxy(*this);
@@ -107,10 +108,10 @@
#if ENABLE(MEDIA_STREAM)
UserMediaProcessManager::singleton().removeUserMediaPermissionRequestManagerProxy(*this);
#endif
- invalidateRequests();
+ invalidatePendingRequests();
}
-void UserMediaPermissionRequestManagerProxy::invalidateRequests()
+void UserMediaPermissionRequestManagerProxy::invalidatePendingRequests()
{
for (auto& request : m_pendingUserMediaRequests.values())
request->invalidate();
@@ -123,9 +124,15 @@
m_frameStates.clear();
}
+void UserMediaPermissionRequestManagerProxy::stopCapture()
+{
+ invalidatePendingRequests();
+ m_page.process().send(Messages::WebPage::StopMediaCapture(), m_page.pageID());
+}
+
void UserMediaPermissionRequestManagerProxy::clearCachedState()
{
- invalidateRequests();
+ invalidatePendingRequests();
}
Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID, uint64_t frameID, const String& userMediaDocumentOriginIdentifier, const String& topLevelDocumentOriginIdentifier, const Vector<String>& audioDeviceUIDs, const Vector<String>& videoDeviceUIDs)
@@ -223,6 +230,23 @@
#endif
}
+void UserMediaPermissionRequestManagerProxy::rejectionTimerFired()
+{
+ uint64_t userMediaID = m_pendingRejections[0];
+ m_pendingRejections.remove(0);
+
+ denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied, emptyString());
+ if (!m_pendingRejections.isEmpty())
+ scheduleNextRejection();
+}
+
+void UserMediaPermissionRequestManagerProxy::scheduleNextRejection()
+{
+ const double mimimumDelayBeforeReplying = .25;
+ if (!m_rejectionTimer.isActive())
+ m_rejectionTimer.startOneShot(Seconds(mimimumDelayBeforeReplying + randomNumber()));
+}
+
void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, String userMediaDocumentOriginIdentifier, String topLevelDocumentOriginIdentifier, const WebCore::MediaConstraintsData& audioConstraintsData, const WebCore::MediaConstraintsData& videoConstraintsData)
{
#if ENABLE(MEDIA_STREAM)
@@ -272,6 +296,12 @@
};
+ if (!UserMediaProcessManager::singleton().captureEnabled()) {
+ m_pendingRejections.append(userMediaID);
+ scheduleNextRejection();
+ return;
+ }
+
auto audioConstraints = MediaConstraintsImpl::create(MediaConstraintsData(audioConstraintsData));
auto videoConstraints = MediaConstraintsImpl::create(MediaConstraintsData(videoConstraintsData));
Modified: trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/UserMediaPermissionRequestManagerProxy.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -17,14 +17,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef UserMediaPermissionRequestManagerProxy_h
-#define UserMediaPermissionRequestManagerProxy_h
+#pragma once
#include "UserMediaPermissionCheckProxy.h"
#include "UserMediaPermissionRequestProxy.h"
#include <WebCore/SecurityOrigin.h>
+#include <WebCore/Timer.h>
#include <WebCore/UserMediaRequest.h>
#include <wtf/HashMap.h>
+#include <wtf/Seconds.h>
namespace WebCore {
class CaptureDevice;
@@ -57,7 +58,7 @@
WebPageProxy& page() const { return m_page; }
- void invalidateRequests();
+ void invalidatePendingRequests();
void requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, String userMediaDocumentOriginIdentifier, String topLevelDocumentOriginIdentifier, const WebCore::MediaConstraintsData& audioConstraintsData, const WebCore::MediaConstraintsData& videoConstraintsData);
@@ -69,6 +70,9 @@
void didCompleteUserMediaPermissionCheck(uint64_t, const String&, bool allow);
+ void stopCapture();
+ void scheduleNextRejection();
+ void rejectionTimerFired();
void clearCachedState();
void startedCaptureSession();
@@ -85,8 +89,10 @@
HashMap<uint64_t, std::unique_ptr<FrameAuthorizationState>> m_frameStates;
WebPageProxy& m_page;
+
+ WebCore::Timer m_rejectionTimer;
+ Vector<uint64_t> m_pendingRejections;
};
} // namespace WebKit
-#endif // UserMediaPermissionRequestManagerProxy_h
Modified: trunk/Source/WebKit2/UIProcess/UserMediaProcessManager.cpp (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/UserMediaProcessManager.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/UserMediaProcessManager.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -115,8 +115,12 @@
for (auto& state : stateMap()) {
for (auto& manager : state.value->managers()) {
- if (&manager->page() == &pageStartingCapture)
+ if (&manager->page() == &pageStartingCapture) {
+#if PLATFORM(IOS)
+ manager->page().stopMediaCapture();
+#endif
continue;
+ }
manager->page().setMuted(WebCore::MediaProducer::CaptureDevicesAreMuted);
}
@@ -230,6 +234,22 @@
#endif
}
+void UserMediaProcessManager::setCaptureEnabled(bool enabled)
+{
+ if (enabled == m_captureEnabled)
+ return;
+
+ m_captureEnabled = enabled;
+
+ if (enabled)
+ return;
+
+ for (auto& state : stateMap()) {
+ for (auto& manager : state.value->managers())
+ manager->stopCapture();
+ }
+}
+
} // namespace WebKit
#endif
Modified: trunk/Source/WebKit2/UIProcess/UserMediaProcessManager.h (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/UserMediaProcessManager.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/UserMediaProcessManager.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -39,6 +39,12 @@
void startedCaptureSession(UserMediaPermissionRequestManagerProxy&);
void endedCaptureSession(UserMediaPermissionRequestManagerProxy&);
+
+ void setCaptureEnabled(bool);
+ bool captureEnabled() const { return m_captureEnabled; }
+
+private:
+ bool m_captureEnabled { true };
};
} // namespace WebKit
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -4206,6 +4206,18 @@
activityStateDidChange(ActivityState::IsAudible | ActivityState::IsCapturingMedia);
}
+void WebPageProxy::setMediaCaptureEnabled(bool enabled)
+{
+ m_mediaCaptureEnabled = enabled;
+
+ if (!isValid())
+ return;
+
+#if ENABLE(MEDIA_STREAM)
+ UserMediaProcessManager::singleton().setCaptureEnabled(enabled);
+#endif
+}
+
#if ENABLE(MEDIA_SESSION)
void WebPageProxy::handleMediaEvent(MediaEventType eventType)
{
Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (216171 => 216172)
--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -979,6 +979,9 @@
void setMuted(WebCore::MediaProducer::MutedStateFlags);
void setMayStartMediaWhenInWindow(bool);
bool mayStartMediaWhenInWindow() const { return m_mayStartMediaWhenInWindow; }
+ void setMediaCaptureEnabled(bool);
+ bool mediaCaptureEnabled() const { return m_mediaCaptureEnabled; }
+
#if ENABLE(MEDIA_SESSION)
bool hasMediaSessionWithActiveMediaElements() const { return m_hasMediaSessionWithActiveMediaElements; }
@@ -1935,6 +1938,7 @@
float m_mediaVolume;
WebCore::MediaProducer::MutedStateFlags m_mutedState { WebCore::MediaProducer::NoneMuted };
bool m_mayStartMediaWhenInWindow;
+ bool m_mediaCaptureEnabled { true };
bool m_waitingForDidUpdateActivityState;
Modified: trunk/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp (216171 => 216172)
--- trunk/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -56,6 +56,15 @@
sandboxExtension.value->revoke();
}
+void UserMediaPermissionRequestManager::cancelPendingRequests()
+{
+ for (auto& request : m_idToUserMediaRequestMap.values())
+ cancelUserMediaRequest(*request);
+
+ for (auto& request : m_idToMediaDevicesEnumerationRequestMap.values())
+ cancelMediaDevicesEnumeration(*request);
+}
+
void UserMediaPermissionRequestManager::startUserMediaRequest(UserMediaRequest& request)
{
Document* document = request.document();
@@ -104,6 +113,8 @@
uint64_t requestID = m_userMediaRequestToIDMap.take(&request);
if (!requestID)
return;
+
+ request.deny(UserMediaRequest::OtherFailure, emptyString());
m_idToUserMediaRequestMap.remove(requestID);
removeMediaRequestFromMaps(request);
}
@@ -190,6 +201,7 @@
uint64_t requestID = m_mediaDevicesEnumerationRequestToIDMap.take(&request);
if (!requestID)
return;
+ request.setDeviceInfo(Vector<CaptureDevice>(), emptyString(), false);
m_idToMediaDevicesEnumerationRequestMap.remove(requestID);
}
Modified: trunk/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.h (216171 => 216172)
--- trunk/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/WebProcess/MediaStream/UserMediaPermissionRequestManager.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -55,6 +55,8 @@
void grantUserMediaDeviceSandboxExtensions(const MediaDeviceSandboxExtensions&);
void revokeUserMediaDeviceSandboxExtensions(const Vector<String>&);
+ void cancelPendingRequests();
+
private:
void sendUserMediaRequest(WebCore::UserMediaRequest&);
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (216171 => 216172)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2017-05-04 04:48:07 UTC (rev 216172)
@@ -4556,6 +4556,13 @@
m_page->setMuted(state);
}
+void WebPage::stopMediaCapture()
+{
+#if ENABLE(MEDIA_STREAM)
+ m_page->stopMediaCapture();
+#endif
+}
+
#if ENABLE(MEDIA_SESSION)
void WebPage::handleMediaEvent(uint32_t eventType)
{
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (216171 => 216172)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2017-05-04 04:48:07 UTC (rev 216172)
@@ -765,6 +765,7 @@
void setMediaVolume(float);
void setMuted(WebCore::MediaProducer::MutedStateFlags);
void setMayStartMediaWhenInWindow(bool);
+ void stopMediaCapture();
#if ENABLE(MEDIA_SESSION)
void handleMediaEvent(uint32_t /* WebCore::MediaEventType */);
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in (216171 => 216172)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in 2017-05-04 04:48:07 UTC (rev 216172)
@@ -338,6 +338,7 @@
SetMediaVolume(float volume)
SetMuted(WebCore::MediaProducer::MutedStateFlags muted)
SetMayStartMediaWhenInWindow(bool mayStartMedia)
+ StopMediaCapture()
#if ENABLE(MEDIA_SESSION)
HandleMediaEvent(uint32_t eventType)
Modified: trunk/Tools/ChangeLog (216171 => 216172)
--- trunk/Tools/ChangeLog 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Tools/ChangeLog 2017-05-04 04:48:07 UTC (rev 216172)
@@ -1,3 +1,21 @@
+2017-05-03 Eric Carlson <eric.carl...@apple.com>
+
+ [MediaStream] Allow host application to enable/disable media capture
+ https://bugs.webkit.org/show_bug.cgi?id=171292
+ <rdar://problem/31821492>
+
+ Reviewed by Jer Noble.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKit2Cocoa/UserMediaDisabled.mm: Added.
+ (-[UserMediaMessageHandler userContentController:didReceiveScriptMessage:]):
+ (-[UserMediaUIDelegate _webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:]):
+ (-[UserMediaUIDelegate _webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:]):
+ (MediaCaptureDisabledTest::SetUp):
+ (MediaCaptureDisabledTest::loadTestAndWaitForMessage):
+ (TEST_F):
+ * TestWebKitAPI/Tests/WebKit2Cocoa/disableGetUserMedia.html: Added.
+
2017-05-03 John Wilander <wilan...@apple.com>
Resource Load Statistics: Remove all statistics for modifiedSince website data removals
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (216171 => 216172)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-05-04 04:16:39 UTC (rev 216171)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-05-04 04:48:07 UTC (rev 216172)
@@ -25,6 +25,8 @@
07492B3B1DF8B14C00633DE1 /* EnumerateMediaDevices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07492B3A1DF8AE2D00633DE1 /* EnumerateMediaDevices.cpp */; };
07492B3C1DF8B86600633DE1 /* enumerateMediaDevices.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 07492B391DF8ADA400633DE1 /* enumerateMediaDevices.html */; };
074994421EA5034B000DA44E /* getUserMedia.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 4A410F4D19AF7BEF002EBAB5 /* getUserMedia.html */; };
+ 0799C3491EBA2D7B003B7532 /* UserMediaDisabled.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07EDEFAC1EB9400C00D43292 /* UserMediaDisabled.mm */; };
+ 0799C34B1EBA3301003B7532 /* disableGetUserMedia.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */; };
07C046CA1E4262A8007201E7 /* CARingBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C046C91E42573E007201E7 /* CARingBuffer.cpp */; };
0F139E771A423A5B00F590F5 /* WeakObjCPtr.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E751A423A5300F590F5 /* WeakObjCPtr.mm */; };
0F139E781A423A6B00F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
@@ -687,6 +689,7 @@
files = (
55226A2F1EBA44B900C36AD0 /* large-red-square-image.html in Copy Resources */,
5797FE331EB15AB100B2F4A0 /* navigation-client-default-crypto.html in Copy Resources */,
+ 0799C34B1EBA3301003B7532 /* disableGetUserMedia.html in Copy Resources */,
074994421EA5034B000DA44E /* getUserMedia.html in Copy Resources */,
C9BF06EF1E9C132500595E3E /* autoplay-muted-with-controls.html in Copy Resources */,
F4DEF6ED1E9B4DB60048EF61 /* image-in-link-and-input.html in Copy Resources */,
@@ -879,7 +882,9 @@
07492B391DF8ADA400633DE1 /* enumerateMediaDevices.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = enumerateMediaDevices.html; sourceTree = "<group>"; };
07492B3A1DF8AE2D00633DE1 /* EnumerateMediaDevices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EnumerateMediaDevices.cpp; sourceTree = "<group>"; };
0766DD1F1A5AD5200023E3BB /* PendingAPIRequestURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PendingAPIRequestURL.cpp; sourceTree = "<group>"; };
+ 0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = disableGetUserMedia.html; sourceTree = "<group>"; };
07C046C91E42573E007201E7 /* CARingBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CARingBuffer.cpp; sourceTree = "<group>"; };
+ 07EDEFAC1EB9400C00D43292 /* UserMediaDisabled.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserMediaDisabled.mm; sourceTree = "<group>"; };
0BCD833414857CE400EA2003 /* HashMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashMap.cpp; sourceTree = "<group>"; };
0BCD85691485C98B00EA2003 /* SetForScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SetForScope.cpp; sourceTree = "<group>"; };
0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformUtilitiesCocoa.mm; path = cocoa/PlatformUtilitiesCocoa.mm; sourceTree = "<group>"; };
@@ -1671,6 +1676,7 @@
children = (
A16F66B81C40E9E100BD4D24 /* Resources */,
7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */,
+ 07EDEFAC1EB9400C00D43292 /* UserMediaDisabled.mm */,
37E7DD631EA06FF2009B396D /* AdditionalReadAccessAllowedURLs.mm */,
37E7DD661EA071F3009B396D /* AdditionalReadAccessAllowedURLsPlugin.mm */,
37E7DD651EA0715B009B396D /* AdditionalReadAccessAllowedURLsProtocol.h */,
@@ -1896,6 +1902,7 @@
2EFF06C61D886A560004BB30 /* change-video-source-on-end.html */,
A16F66B91C40EA2000BD4D24 /* ContentFiltering.html */,
5C2936941D5BFD1900DEAB1E /* CookieMessage.html */,
+ 0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */,
837A35F01D9A1E6400663C57 /* DownloadRequestBlobURL.html */,
5714ECB81CA8B58800051AC8 /* DownloadRequestOriginalURL.html */,
5714ECBC1CA8C21800051AC8 /* DownloadRequestOriginalURL2.html */,
@@ -3079,6 +3086,7 @@
D34E08761E4E42E1005FF14A /* WKWebViewGetContents.mm in Sources */,
315231CA1EB3B3C700A22A16 /* GPUCommandQueue.mm in Sources */,
F4FA91811E61849B007B8C1D /* WKWebViewSelectionTests.mm in Sources */,
+ 0799C3491EBA2D7B003B7532 /* UserMediaDisabled.mm in Sources */,
93F56DA91E5F919D003EDE84 /* WKWebViewSnapshot.mm in Sources */,
9984FACC1CFFAF60008D198C /* WKWebViewTextInput.mm in Sources */,
764322D71B61CCC30024F801 /* WordBoundaryTypingAttributes.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserMediaDisabled.mm (0 => 216172)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserMediaDisabled.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserMediaDisabled.mm 2017-05-04 04:48:07 UTC (rev 216172)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestWKWebView.h"
+
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKUserContentControllerPrivate.h>
+#import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <wtf/RetainPtr.h>
+
+#if WK_API_ENABLED
+
+static bool refuseRequest = false;
+static bool wasPrompted = false;
+
+static bool receivedScriptMessage = false;
+static RetainPtr<WKScriptMessage> lastScriptMessage;
+
+@interface UserMediaMessageHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation UserMediaMessageHandler
+
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+ lastScriptMessage = message;
+ receivedScriptMessage = true;
+}
+@end
+
+@interface UserMediaUIDelegate : NSObject <WKUIDelegate>
+@end
+
+@implementation UserMediaUIDelegate
+
+- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(NSUInteger)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL))decisionHandler
+{
+ wasPrompted = true;
+
+ if (refuseRequest) {
+ decisionHandler(NO);
+ return;
+ }
+
+ BOOL needsMicrophoneAuthorized = devices & _WKCaptureDeviceMicrophone;
+ BOOL needsCameraAuthorized = devices & _WKCaptureDeviceCamera;
+ if (!needsMicrophoneAuthorized && !needsCameraAuthorized) {
+ decisionHandler(NO);
+ return;
+ }
+
+ decisionHandler(YES);
+}
+
+- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *, BOOL))decisionHandler
+{
+ if (refuseRequest) {
+ decisionHandler(nil, NO);
+ return;
+ }
+}
+@end
+
+class MediaCaptureDisabledTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ m_configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+ RetainPtr<UserMediaMessageHandler> handler = adoptNS([[UserMediaMessageHandler alloc] init]);
+ [[m_configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+
+ m_webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:m_configuration.get()]);
+
+ auto preferences = [m_webView configuration].preferences;
+ preferences._mediaDevicesEnabled = YES;
+ preferences._mockCaptureDevicesEnabled = YES;
+ preferences._mediaCaptureRequiresSecureConnection = NO;
+
+ m_uiDelegate = adoptNS([[UserMediaUIDelegate alloc] init]);
+ [m_webView setUIDelegate:m_uiDelegate.get()];
+ }
+
+ void loadTestAndWaitForMessage(const char* message)
+ {
+ wasPrompted = false;
+ receivedScriptMessage = false;
+ [m_webView loadTestPageNamed:@"disableGetUserMedia"];
+ TestWebKitAPI::Util::run(&receivedScriptMessage);
+ EXPECT_STREQ([(NSString *)[lastScriptMessage body] UTF8String], message);
+ }
+
+ RetainPtr<WKWebViewConfiguration> m_configuration;
+ RetainPtr<UserMediaUIDelegate> m_uiDelegate;
+ RetainPtr<TestWKWebView> m_webView;
+};
+
+TEST_F(MediaCaptureDisabledTest, EnableAndDisable)
+{
+ EXPECT_TRUE(m_webView.get()._mediaCaptureEnabled);
+ loadTestAndWaitForMessage("allowed");
+ EXPECT_TRUE(wasPrompted);
+
+ m_webView.get()._mediaCaptureEnabled = NO;
+ EXPECT_FALSE(m_webView.get()._mediaCaptureEnabled);
+ loadTestAndWaitForMessage("denied");
+ EXPECT_FALSE(wasPrompted);
+
+ m_webView.get()._mediaCaptureEnabled = YES;
+ EXPECT_TRUE(m_webView.get()._mediaCaptureEnabled);
+ loadTestAndWaitForMessage("allowed");
+ EXPECT_TRUE(wasPrompted);
+}
+#endif
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/disableGetUserMedia.html (0 => 216172)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/disableGetUserMedia.html (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/disableGetUserMedia.html 2017-05-04 04:48:07 UTC (rev 216172)
@@ -0,0 +1,16 @@
+<script>
+ function gotUserMedia(mediaStream)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('allowed');
+ }
+
+ function userMediaError(error)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('denied');
+ }
+
+ var constraints = { audio: false, video: true};
+ navigator.mediaDevices.getUserMedia(constraints)
+ .then(gotUserMedia).
+ catch(userMediaError);
+</script>