Diff
Modified: trunk/Source/WebKit/ChangeLog (223987 => 223988)
--- trunk/Source/WebKit/ChangeLog 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/ChangeLog 2017-10-25 22:15:05 UTC (rev 223988)
@@ -1,3 +1,41 @@
+2017-10-25 Eric Carlson <[email protected]>
+
+ [MediaStream] Clear cached gUM prompt state
+ https://bugs.webkit.org/show_bug.cgi?id=178754
+ <rdar://problem/32742356>
+
+ Reviewed by Youenn Fablet.
+
+ * Shared/WebPreferences.yaml: Define new settings.
+
+ * Shared/WebPreferencesDefinitionsBase.h: New default values.
+
+ * UIProcess/API/C/WKPreferences.cpp:
+ (WKPreferencesSetInactiveMediaCaptureSteamRepromptIntervalInMinutes): New.
+ (WKPreferencesGetInactiveMediaCaptureSteamRepromptIntervalInMinutes): Ditto.
+ * UIProcess/API/C/WKPreferencesRefPrivate.h:
+
+ * UIProcess/API/Cocoa/WKPreferences.mm:
+ (-[WKPreferences _inactiveMediaCaptureSteamRepromptIntervalInMinutes]): Ditto.
+ (-[WKPreferences _setInactiveMediaCaptureSteamRepromptIntervalInMinutes:]): Ditto.
+ * UIProcess/API/Cocoa/WKPreferencesPrivate.h:
+
+ * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+ (WebKit::UserMediaPermissionRequestManagerProxy::UserMediaPermissionRequestManagerProxy): Initialize
+ the timer.
+ (WebKit::UserMediaPermissionRequestManagerProxy::createRequest): Remove unneeded namespace.
+ (WebKit::toWebCore): Remove unneeded breaks.
+ (WebKit::UserMediaPermissionRequestManagerProxy::searchForGrantedRequest const): Remove unneeded namespace.
+ (WebKit::UserMediaPermissionRequestManagerProxy::wasRequestDenied): Ditto.
+ (WebKit::UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame): Ditto.
+ (WebKit::UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo): Ditto.
+ (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame): Ditto.
+ (WebKit::UserMediaPermissionRequestManagerProxy::syncWithWebCorePrefs const): Ditto.
+ (WebKit::UserMediaPermissionRequestManagerProxy::captureStateChanged): Set the watchdog timer
+ to the correct interval based on capture state.
+ (WebKit::UserMediaPermissionRequestManagerProxy::watchdogTimerFired): Clear cached state.
+ * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+
2017-10-25 Simon Fraser <[email protected]>
When navigating back to a page, compositing layers may not use accelerated drawing
Modified: trunk/Source/WebKit/Shared/WebPreferences.yaml (223987 => 223988)
--- trunk/Source/WebKit/Shared/WebPreferences.yaml 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/Shared/WebPreferences.yaml 2017-10-25 22:15:05 UTC (rev 223988)
@@ -822,7 +822,14 @@
defaultValue: '""'
webkitOnly: true
+InactiveMediaCaptureSteamRepromptIntervalInMinutes:
+ type: double
+ defaultValue: DEFAULT_INTERACTIVE_MNEDIA_CAPTURE_STREAM_REPROMPT_INTERVAL_IN_MINUTES
+LongRunningMediaCaptureStreamRepromptIntervalInHours:
+ type: double
+ defaultValue: 24
+
# Debug Preferences
Modified: trunk/Source/WebKit/Shared/WebPreferencesDefinitionsBase.h (223987 => 223988)
--- trunk/Source/WebKit/Shared/WebPreferencesDefinitionsBase.h 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/Shared/WebPreferencesDefinitionsBase.h 2017-10-25 22:15:05 UTC (rev 223988)
@@ -75,6 +75,7 @@
#define DEFAULT_TEMPORARY_TILE_COHORT_RETENTION_ENABLED false
#define DEFAULT_REQUIRES_USER_GESTURE_FOR_AUDIO_PLAYBACK true
#define DEFAULT_LEGACY_ENCRYPTED_MEDIA_API_ENABLED false
+#define DEFAULT_INTERACTIVE_MNEDIA_CAPTURE_STREAM_REPROMPT_INTERVAL_IN_MINUTES 1
#else
#define DEFAULT_ALLOWS_PICTURE_IN_PICTURE_MEDIA_PLAYBACK false
#define DEFAULT_BACKSPACE_KEY_NAVIGATION_ENABLED true
@@ -93,6 +94,7 @@
#define DEFAULT_TEMPORARY_TILE_COHORT_RETENTION_ENABLED true
#define DEFAULT_REQUIRES_USER_GESTURE_FOR_AUDIO_PLAYBACK false
#define DEFAULT_LEGACY_ENCRYPTED_MEDIA_API_ENABLED true
+#define DEFAULT_INTERACTIVE_MNEDIA_CAPTURE_STREAM_REPROMPT_INTERVAL_IN_MINUTES 10
#endif
#if PLATFORM(COCOA)
Modified: trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp (223987 => 223988)
--- trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp 2017-10-25 22:15:05 UTC (rev 223988)
@@ -1650,6 +1650,16 @@
return toImpl(preferencesRef)->mediaCaptureRequiresSecureConnection();
}
+void WKPreferencesSetInactiveMediaCaptureSteamRepromptIntervalInMinutes(WKPreferencesRef preferencesRef, double interval)
+{
+ toImpl(preferencesRef)->setInactiveMediaCaptureSteamRepromptIntervalInMinutes(interval);
+}
+
+double WKPreferencesGetInactiveMediaCaptureSteamRepromptIntervalInMinutes(WKPreferencesRef preferencesRef)
+{
+ return toImpl(preferencesRef)->inactiveMediaCaptureSteamRepromptIntervalInMinutes();
+}
+
void WKPreferencesSetFetchAPIEnabled(WKPreferencesRef preferencesRef, bool flag)
{
toImpl(preferencesRef)->setFetchAPIEnabled(flag);
Modified: trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h (223987 => 223988)
--- trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h 2017-10-25 22:15:05 UTC (rev 223988)
@@ -441,6 +441,10 @@
WK_EXPORT void WKPreferencesSetMediaCaptureRequiresSecureConnection(WKPreferencesRef, bool);
WK_EXPORT bool WKPreferencesGetMediaCaptureRequiresSecureConnection(WKPreferencesRef);
+// Defaults to 1 minute on iOS, 10 minutes elsewhere
+WK_EXPORT void WKPreferencesSetInactiveMediaCaptureSteamRepromptIntervalInMinutes(WKPreferencesRef, double);
+WK_EXPORT double WKPreferencesGetInactiveMediaCaptureSteamRepromptIntervalInMinutes(WKPreferencesRef);
+
// Defaults to false
WK_EXPORT void WKPreferencesSetFetchAPIEnabled(WKPreferencesRef, bool flag);
WK_EXPORT bool WKPreferencesGetFetchAPIEnabled(WKPreferencesRef);
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm (223987 => 223988)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm 2017-10-25 22:15:05 UTC (rev 223988)
@@ -612,6 +612,16 @@
_preferences->setMediaCaptureRequiresSecureConnection(requiresSecureConnection);
}
+- (double)_inactiveMediaCaptureSteamRepromptIntervalInMinutes
+{
+ return _preferences->inactiveMediaCaptureSteamRepromptIntervalInMinutes();
+}
+
+- (void)_setInactiveMediaCaptureSteamRepromptIntervalInMinutes:(double)interval
+{
+ _preferences->setInactiveMediaCaptureSteamRepromptIntervalInMinutes(interval);
+}
+
- (BOOL)_enumeratingAllNetworkInterfacesEnabled
{
return _preferences->enumeratingAllNetworkInterfacesEnabled();
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h (223987 => 223988)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h 2017-10-25 22:15:05 UTC (rev 223988)
@@ -110,6 +110,7 @@
@property (nonatomic, setter=_setEnumeratingAllNetworkInterfacesEnabled:) BOOL _enumeratingAllNetworkInterfacesEnabled WK_API_AVAILABLE(macosx(10.13), ios(11.0));
@property (nonatomic, setter=_setICECandidateFilteringEnabled:) BOOL _iceCandidateFilteringEnabled WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@property (nonatomic, setter=_setWebRTCLegacyAPIEnabled:) BOOL _webRTCLegacyAPIEnabled WK_API_AVAILABLE(macosx(10.13), ios(11.0));
+@property (nonatomic, setter=_setInactiveMediaCaptureSteamRepromptIntervalInMinutes:) double _inactiveMediaCaptureSteamRepromptIntervalInMinutes WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@property (nonatomic, setter=_setJavaScriptCanAccessClipboard:) BOOL _javaScriptCanAccessClipboard WK_API_AVAILABLE(macosx(10.13), ios(11.0));
@property (nonatomic, setter=_setDOMPasteAllowed:) BOOL _domPasteAllowed WK_API_AVAILABLE(macosx(10.13), ios(11.0));
Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (223987 => 223988)
--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp 2017-10-25 22:15:05 UTC (rev 223988)
@@ -34,17 +34,16 @@
#include <WebCore/SecurityOriginData.h>
#include <WebCore/UserMediaRequest.h>
-#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
-#include <WebCore/RealtimeMediaSourceCenterMac.h>
-#endif
-
using namespace WebCore;
namespace WebKit {
+static const MediaProducer::MediaStateFlags activeCaptureMask = MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice;
+
UserMediaPermissionRequestManagerProxy::UserMediaPermissionRequestManagerProxy(WebPageProxy& page)
: m_page(page)
, m_rejectionTimer(RunLoop::main(), this, &UserMediaPermissionRequestManagerProxy::rejectionTimerFired)
+ , m_watchdogTimer(RunLoop::main(), this, &UserMediaPermissionRequestManagerProxy::watchdogTimerFired)
{
#if ENABLE(MEDIA_STREAM)
UserMediaProcessManager::singleton().addUserMediaPermissionRequestManagerProxy(*this);
@@ -81,7 +80,7 @@
invalidatePendingRequests();
}
-Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIDHashSalt)
+Ref<UserMediaPermissionRequestProxy> UserMediaPermissionRequestManagerProxy::createRequest(uint64_t userMediaID, uint64_t mainFrameID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin, Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIDHashSalt)
{
auto request = UserMediaPermissionRequestProxy::create(*this, userMediaID, mainFrameID, frameID, WTFMove(userMediaDocumentOrigin), WTFMove(topLevelDocumentOrigin), WTFMove(audioDeviceUIDs), WTFMove(videoDeviceUIDs), WTFMove(deviceIDHashSalt));
m_pendingUserMediaRequests.add(userMediaID, request.ptr());
@@ -94,25 +93,18 @@
switch (reason) {
case UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoConstraints:
return static_cast<uint64_t>(UserMediaRequest::MediaAccessDenialReason::NoConstraints);
- break;
case UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled:
return static_cast<uint64_t>(UserMediaRequest::MediaAccessDenialReason::UserMediaDisabled);
- break;
case UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::NoCaptureDevices:
return static_cast<uint64_t>(UserMediaRequest::MediaAccessDenialReason::NoCaptureDevices);
- break;
case UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::InvalidConstraint:
return static_cast<uint64_t>(UserMediaRequest::MediaAccessDenialReason::InvalidConstraint);
- break;
case UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::HardwareError:
return static_cast<uint64_t>(UserMediaRequest::MediaAccessDenialReason::HardwareError);
- break;
case UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied:
return static_cast<uint64_t>(UserMediaRequest::MediaAccessDenialReason::PermissionDenied);
- break;
case UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::OtherFailure:
return static_cast<uint64_t>(UserMediaRequest::MediaAccessDenialReason::OtherFailure);
- break;
}
ASSERT_NOT_REACHED();
@@ -178,7 +170,7 @@
m_deniedRequests.clear();
}
-const UserMediaPermissionRequestProxy* UserMediaPermissionRequestManagerProxy::searchForGrantedRequest(uint64_t frameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo) const
+const UserMediaPermissionRequestProxy* UserMediaPermissionRequestManagerProxy::searchForGrantedRequest(uint64_t frameID, const SecurityOrigin& userMediaDocumentOrigin, const SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo) const
{
if (m_page.isMediaStreamCaptureMuted())
return nullptr;
@@ -207,7 +199,7 @@
return nullptr;
}
-bool UserMediaPermissionRequestManagerProxy::wasRequestDenied(uint64_t mainFrameID, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo)
+bool UserMediaPermissionRequestManagerProxy::wasRequestDenied(uint64_t mainFrameID, const SecurityOrigin& userMediaDocumentOrigin, const SecurityOrigin& topLevelDocumentOrigin, bool needsAudio, bool needsVideo)
{
for (const auto& deniedRequest : m_deniedRequests) {
if (!deniedRequest.userMediaDocumentOrigin->isSameSchemeHostPort(userMediaDocumentOrigin))
@@ -253,7 +245,7 @@
request.allow(request.audioDeviceUIDs().isEmpty() ? String() : request.audioDeviceUIDs()[0], request.videoDeviceUIDs().isEmpty() ? String() : request.videoDeviceUIDs()[0]);
}
-void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, const WebCore::MediaConstraints& audioConstraints, const WebCore::MediaConstraints& videoConstraints)
+void UserMediaPermissionRequestManagerProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin, const MediaConstraints& audioConstraints, const MediaConstraints& videoConstraints)
{
#if ENABLE(MEDIA_STREAM)
if (!UserMediaProcessManager::singleton().captureEnabled()) {
@@ -262,7 +254,7 @@
return;
}
- WebCore::RealtimeMediaSourceCenter::InvalidConstraintsHandler invalidHandler = [this, userMediaID](const String& invalidConstraint) {
+ RealtimeMediaSourceCenter::InvalidConstraintsHandler invalidHandler = [this, userMediaID](const String& invalidConstraint) {
if (!m_page.isValid())
return;
@@ -269,7 +261,7 @@
denyRequest(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::InvalidConstraint, invalidConstraint);
};
- WebCore::RealtimeMediaSourceCenter::ValidConstraintsHandler validHandler = [this, userMediaID, frameID, userMediaDocumentOrigin = userMediaDocumentOrigin.copyRef(), topLevelDocumentOrigin = topLevelDocumentOrigin.copyRef()](Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIdentifierHashSalt) mutable {
+ RealtimeMediaSourceCenter::ValidConstraintsHandler validHandler = [this, userMediaID, frameID, userMediaDocumentOrigin = userMediaDocumentOrigin.copyRef(), topLevelDocumentOrigin = topLevelDocumentOrigin.copyRef()](Vector<String>&& audioDeviceUIDs, Vector<String>&& videoDeviceUIDs, String&& deviceIdentifierHashSalt) mutable {
if (!m_page.isValid() || !m_page.mainFrame())
return;
@@ -318,7 +310,7 @@
userMediaAccessWasDenied(userMediaID, UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::UserMediaDisabled);
};
- auto haveDeviceSaltHandler = [this, validHandler = WTFMove(validHandler), invalidHandler = WTFMove(invalidHandler), audioConstraints = WebCore::MediaConstraints(audioConstraints), videoConstraints = WebCore::MediaConstraints(videoConstraints)](uint64_t userMediaID, String&& deviceIdentifierHashSalt, bool originHasPersistentAccess) mutable {
+ auto haveDeviceSaltHandler = [this, validHandler = WTFMove(validHandler), invalidHandler = WTFMove(invalidHandler), audioConstraints = MediaConstraints(audioConstraints), videoConstraints = MediaConstraints(videoConstraints)](uint64_t userMediaID, String&& deviceIdentifierHashSalt, bool originHasPersistentAccess) mutable {
auto request = m_pendingDeviceRequests.take(userMediaID);
if (!request)
@@ -347,7 +339,7 @@
}
#if ENABLE(MEDIA_STREAM)
-void UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&& handler, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin)
+void UserMediaPermissionRequestManagerProxy::getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&& handler, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin)
{
auto userMediaOrigin = API::SecurityOrigin::create(userMediaDocumentOrigin.get());
auto topLevelOrigin = API::SecurityOrigin::create(topLevelDocumentOrigin.get());
@@ -360,7 +352,7 @@
}
#endif
-void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin)
+void UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t frameID, Ref<SecurityOrigin>&& userMediaDocumentOrigin, Ref<SecurityOrigin>&& topLevelDocumentOrigin)
{
#if ENABLE(MEDIA_STREAM)
auto completionHandler = [this](uint64_t userMediaID, String&& deviceIdentifierHashSalt, bool originHasPersistentAccess) {
@@ -391,25 +383,42 @@
// Enable/disable the mock capture devices for the UI process as per the WebCore preferences. Note that
// this is a noop if the preference hasn't changed since the last time this was called.
bool mockDevicesEnabled = m_page.preferences().mockCaptureDevicesEnabled();
- WebCore::MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled(mockDevicesEnabled);
+ MockRealtimeMediaSourceCenter::setMockRealtimeMediaSourceCenterEnabled(mockDevicesEnabled);
#endif
}
-void UserMediaPermissionRequestManagerProxy::captureStateChanged(WebCore::MediaProducer::MediaStateFlags oldState, WebCore::MediaProducer::MediaStateFlags newState)
+void UserMediaPermissionRequestManagerProxy::captureStateChanged(MediaProducer::MediaStateFlags oldState, MediaProducer::MediaStateFlags newState)
{
if (!m_page.isValid())
return;
#if ENABLE(MEDIA_STREAM)
- bool wasCapturingAudio = oldState & WebCore::MediaProducer::AudioCaptureMask;
- bool wasCapturingVideo = oldState & WebCore::MediaProducer::VideoCaptureMask;
- bool isCapturingAudio = newState & WebCore::MediaProducer::AudioCaptureMask;
- bool isCapturingVideo = newState & WebCore::MediaProducer::VideoCaptureMask;
+ bool wasCapturingAudio = oldState & MediaProducer::AudioCaptureMask;
+ bool wasCapturingVideo = oldState & MediaProducer::VideoCaptureMask;
+ bool isCapturingAudio = newState & MediaProducer::AudioCaptureMask;
+ bool isCapturingVideo = newState & MediaProducer::VideoCaptureMask;
if ((wasCapturingAudio && !isCapturingAudio) || (wasCapturingVideo && !isCapturingVideo))
UserMediaProcessManager::singleton().endedCaptureSession(*this);
if ((!wasCapturingAudio && isCapturingAudio) || (!wasCapturingVideo && isCapturingVideo))
UserMediaProcessManager::singleton().startedCaptureSession(*this);
+
+ if (m_captureState == (newState & activeCaptureMask))
+ return;
+
+ m_captureState = newState & activeCaptureMask;
+
+ Seconds interval;
+ if (m_captureState & activeCaptureMask)
+ interval = Seconds::fromHours(m_page.preferences().longRunningMediaCaptureStreamRepromptIntervalInHours());
+ else
+ interval = Seconds::fromMinutes(m_page.preferences().inactiveMediaCaptureSteamRepromptIntervalInMinutes());
+
+ if (interval == m_currentWatchdogInterval)
+ return;
+
+ m_currentWatchdogInterval = interval;
+ m_watchdogTimer.startOneShot(m_currentWatchdogInterval);
#endif
}
@@ -420,4 +429,11 @@
m_pregrantedRequests.clear();
}
+void UserMediaPermissionRequestManagerProxy::watchdogTimerFired()
+{
+ m_grantedRequests.clear();
+ m_pregrantedRequests.clear();
+ m_currentWatchdogInterval = 0_s;
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h (223987 => 223988)
--- trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h 2017-10-25 22:15:05 UTC (rev 223988)
@@ -75,6 +75,7 @@
void getUserMediaPermissionInfo(uint64_t userMediaID, uint64_t frameID, UserMediaPermissionCheckProxy::CompletionHandler&&, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin);
void syncWithWebCorePrefs() const;
+ void watchdogTimerFired();
HashMap<uint64_t, RefPtr<UserMediaPermissionRequestProxy>> m_pendingUserMediaRequests;
HashMap<uint64_t, Ref<UserMediaPermissionCheckProxy>> m_pendingDeviceRequests;
@@ -95,6 +96,10 @@
bool isVideoDenied;
};
Vector<DeniedRequest> m_deniedRequests;
+
+ WebCore::MediaProducer::MediaStateFlags m_captureState { WebCore::MediaProducer::IsNotPlaying };
+ RunLoop::Timer<UserMediaPermissionRequestManagerProxy> m_watchdogTimer;
+ Seconds m_currentWatchdogInterval;
};
} // namespace WebKit
Modified: trunk/Tools/ChangeLog (223987 => 223988)
--- trunk/Tools/ChangeLog 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Tools/ChangeLog 2017-10-25 22:15:05 UTC (rev 223988)
@@ -1,3 +1,20 @@
+2017-10-25 Eric Carlson <[email protected]>
+
+ [MediaStream] Clear cached gUM prompt state
+ https://bugs.webkit.org/show_bug.cgi?id=178754
+ <rdar://problem/32742356>
+
+ Reviewed by Youenn Fablet.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Add new test
+
+ * TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm: Added.
+ (-[GetUserMediaRepromptUIDelegate _webView:requestUserMediaAuthorizationForDevices:url:mainFrameURL:decisionHandler:]):
+ (-[GetUserMediaRepromptUIDelegate _webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:]):
+ (TestWebKitAPI::TEST):
+
+ * TestWebKitAPI/Tests/WebKit/getUserMedia.html:
+
2017-10-25 Ross Kirsling <[email protected]>
Add committer status for Ross Kirsling
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (223987 => 223988)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-10-25 22:15:05 UTC (rev 223988)
@@ -30,6 +30,7 @@
0799C34B1EBA3301003B7532 /* disableGetUserMedia.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 0799C34A1EBA32F4003B7532 /* disableGetUserMedia.html */; };
07C046CA1E4262A8007201E7 /* CARingBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07C046C91E42573E007201E7 /* CARingBuffer.cpp */; };
07CE1CF31F06A7E000BF89F5 /* GetUserMediaNavigation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07CE1CF21F06A7E000BF89F5 /* GetUserMediaNavigation.mm */; };
+ 07E499911F9E56DF002F1EF3 /* GetUserMediaReprompt.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07E499901F9E56A1002F1EF3 /* GetUserMediaReprompt.mm */; };
0F139E771A423A5B00F590F5 /* WeakObjCPtr.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E751A423A5300F590F5 /* WeakObjCPtr.mm */; };
0F139E781A423A6B00F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
0F139E791A42457000F590F5 /* PlatformUtilitiesCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F139E721A423A2B00F590F5 /* PlatformUtilitiesCocoa.mm */; };
@@ -1054,6 +1055,7 @@
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>"; };
07CE1CF21F06A7E000BF89F5 /* GetUserMediaNavigation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GetUserMediaNavigation.mm; sourceTree = "<group>"; };
+ 07E499901F9E56A1002F1EF3 /* GetUserMediaReprompt.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GetUserMediaReprompt.mm; 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>"; };
@@ -2435,6 +2437,7 @@
BC9096411255616000083756 /* WebKit */ = {
isa = PBXGroup;
children = (
+ 07E499901F9E56A1002F1EF3 /* GetUserMediaReprompt.mm */,
0F139E741A423A4600F590F5 /* cocoa */,
C0C5D3BB14598B6F00A802A6 /* mac */,
BC90977B125571AE00083756 /* Resources */,
@@ -3271,6 +3274,7 @@
46397B951DC2C850009A78AE /* DOMNode.mm in Sources */,
7CCE7EBC1A411A7E00447C4C /* DOMNodeFromJSObject.mm in Sources */,
7CCE7EBD1A411A7E00447C4C /* DOMRangeOfString.mm in Sources */,
+ 07E499911F9E56DF002F1EF3 /* GetUserMediaReprompt.mm in Sources */,
7CCE7EEC1A411AE600447C4C /* DOMWindowExtensionBasic.cpp in Sources */,
7CCE7EED1A411AE600447C4C /* DOMWindowExtensionNoCache.cpp in Sources */,
7CCE7F231A411AF600447C4C /* Download.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm (0 => 223988)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMediaReprompt.mm 2017-10-25 22:15:05 UTC (rev 223988)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 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"
+
+#if WK_API_ENABLED
+
+#if ENABLE(MEDIA_STREAM)
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKUIDelegatePrivate.h>
+#import <WebKit/WKWebView.h>
+#import <WebKit/WKWebViewConfiguration.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+
+static bool wasPrompted = false;
+
+@interface GetUserMediaRepromptUIDelegate : NSObject<WKUIDelegate>
+- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler;
+- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *salt, BOOL authorized))decisionHandler;
+@end
+
+@implementation GetUserMediaRepromptUIDelegate
+- (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler
+{
+ wasPrompted = true;
+ decisionHandler(YES);
+}
+
+- (void)_webView:(WKWebView *)webView checkUserMediaPermissionForURL:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL frameIdentifier:(NSUInteger)frameIdentifier decisionHandler:(void (^)(NSString *salt, BOOL authorized))decisionHandler
+{
+ decisionHandler(@"0x987654321", YES);
+}
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, GetUserMediaReprompt)
+{
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+ auto preferences = [configuration preferences];
+ preferences._mediaCaptureRequiresSecureConnection = NO;
+ preferences._mediaDevicesEnabled = YES;
+ preferences._mockCaptureDevicesEnabled = YES;
+ auto webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()];
+ auto delegate = adoptNS([[GetUserMediaRepromptUIDelegate alloc] init]);
+ webView.UIDelegate = delegate.get();
+
+ wasPrompted = false;
+ [webView loadTestPageNamed:@"getUserMedia"];
+ TestWebKitAPI::Util::run(&wasPrompted);
+
+ auto result = [webView stringByEvaluatingJavaScript:@"haveStream()"];
+ EXPECT_TRUE([result boolValue]);
+
+ [webView stringByEvaluatingJavaScript:@"stop()"];
+ result = [webView stringByEvaluatingJavaScript:@"haveStream()"];
+ EXPECT_FALSE([result boolValue]);
+
+ wasPrompted = false;
+ [webView stringByEvaluatingJavaScript:@"promptForCapture()"];
+ result = [webView stringByEvaluatingJavaScript:@"haveStream()"];
+ EXPECT_TRUE([result boolValue]);
+ EXPECT_FALSE(wasPrompted);
+
+ preferences._inactiveMediaCaptureSteamRepromptIntervalInMinutes = .5 / 60;
+ [webView stringByEvaluatingJavaScript:@"stop()"];
+ result = [webView stringByEvaluatingJavaScript:@"haveStream()"];
+ EXPECT_FALSE([result boolValue]);
+
+ // Sleep long enough for the reprompt timer to fire and clear cached state.
+ Util::sleep(1);
+
+ wasPrompted = false;
+ [webView stringByEvaluatingJavaScript:@"promptForCapture()"];
+ TestWebKitAPI::Util::run(&wasPrompted);
+ result = [webView stringByEvaluatingJavaScript:@"haveStream()"];
+ EXPECT_TRUE([result boolValue]);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // WK_API_ENABLED
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit/getUserMedia.html (223987 => 223988)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit/getUserMedia.html 2017-10-25 22:06:51 UTC (rev 223987)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/getUserMedia.html 2017-10-25 22:15:05 UTC (rev 223988)
@@ -1,16 +1,48 @@
-<script>
- function gotUserMedia(mediaStream)
- {
- console.log("Got user media");
- }
+<!DOCTYPE html>
+<html>
+ <head>
+ <script>
- function userMediaError(error)
- {
- console.log(error);
- }
+ let stream = null;
- var constraints = { audio: false, video: true};
- navigator.mediaDevices.getUserMedia(constraints)
- .then(gotUserMedia).
- catch(userMediaError);
-</script>
+ function promptForCapture()
+ {
+ navigator.mediaDevices.getUserMedia({ audio: false, video: true })
+ .then((s) => {
+ stream = s;
+ video.srcObject = stream;
+ console.log("Got user media");
+ })
+ .catch((error) => console.log(`Failed with error: ${error}`));
+ }
+
+ function stop(kind)
+ {
+ let activeTracks = [];
+ stream.getTracks().forEach(track => {
+ if (!kind || track.kind == kind)
+ track.stop();
+ else
+ activeTracks.push(track);
+ });
+
+ if (!activeTracks.length) {
+ stream = null;
+ video.srcObject = null;
+ }
+ }
+
+ function haveStream()
+ {
+ return stream !== null;
+ }
+ </script>
+ <head>
+
+ <body _onload_="promptForCapture()">
+ <video id="video" controls></video>
+ <p>
+ <button _onclick_="stop()">Stop</button>
+ </p>
+ </body>
+</html>