Changeset 267081 in webkit
- Timestamp:
- Sep 15, 2020 1:56:47 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r267077 r267081 1 2020-09-15 Youenn Fablet <youenn@apple.com> 2 3 End of media capture should not be reported before 3 seconds of the start of capture 4 https://bugs.webkit.org/show_bug.cgi?id=216415 5 6 Reviewed by Eric Carlson. 7 8 Add a timer that allows taking a function and a delay as parameter. 9 Covered by added API test. 10 11 * platform/Timer.h: 12 (WebCore::DeferrableTaskTimer::fired): 13 (WebCore::DeferrableTaskTimer::doTask): 14 (WebCore::DeferrableTaskTimer::cancel): 15 1 16 2020-09-14 Fujii Hironori <Hironori.Fujii@sony.com> 2 17 -
trunk/Source/WebCore/platform/Timer.h
r244288 r267081 196 196 }; 197 197 198 } 198 class DeferrableTaskTimer final : private TimerBase { 199 WTF_MAKE_FAST_ALLOCATED; 200 public: 201 DeferrableTaskTimer() = default; 202 203 void doTask(Function<void()>&&, Seconds); 204 void cancel(); 205 bool isActive() const { return TimerBase::isActive(); } 206 207 private: 208 void fired() final; 209 210 Function<void()> m_function; 211 }; 212 213 inline void DeferrableTaskTimer::fired() 214 { 215 std::exchange(m_function, { })(); 216 } 217 218 inline void DeferrableTaskTimer::doTask(Function<void()>&& function, Seconds delay) 219 { 220 ASSERT(!isActive()); 221 ASSERT(!m_function); 222 m_function = WTFMove(function); 223 startOneShot(delay); 224 } 225 226 inline void DeferrableTaskTimer::cancel() 227 { 228 std::exchange(m_function, { }); 229 stop(); 230 } 231 232 } -
trunk/Source/WebKit/ChangeLog
r267079 r267081 1 2020-09-15 Youenn Fablet <youenn@apple.com> 2 3 End of media capture should not be reported before 3 seconds of the start of capture 4 https://bugs.webkit.org/show_bug.cgi?id=216415 5 <rdar://problem/68512358> 6 7 Reviewed by Eric Carlson. 8 9 Add support for delaying of end of capture notification to the application. 10 This allows to ensure that a capture indicator stays for long enough for the user to notice it. 11 A capture indicator should be visible to the user for at least three seconds. 12 13 A timer is scheduled when starting a capture and there is no ongoing capture. 14 As long as the timer is active, the capture state cannot be transitioned to no capture. 15 Other transitions are allowed. 16 Once the timer kicks in, any capture state update is done synchronously. 17 Ensure to update the capture state when the timer kicks in. 18 19 Note that even navigations will not allow transitioning the capture state sooner. 20 This is done to ensure a page does not try to capture one frame before navigating to another page. 21 In practice, very few pages should navigate quickly after starting capture. 22 23 * UIProcess/API/C/WKPage.cpp: 24 (WKPageGetMediaState): 25 (WKPageSetMediaCaptureReportingDelayForTesting): 26 * UIProcess/API/C/WKPagePrivate.h: 27 * UIProcess/API/Cocoa/WKWebView.mm: 28 (-[WKWebView _mediaCaptureState]): 29 * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h: 30 * UIProcess/API/Cocoa/WKWebViewTesting.mm: 31 (-[WKWebView _mediaCaptureReportingDelayForTesting]): 32 (-[WKWebView _setMediaCaptureReportingDelayForTesting:]): 33 * UIProcess/WebPageProxy.cpp: 34 (WebKit::WebPageProxy::updatePlayingMediaDidChange): 35 (WebKit::WebPageProxy::updateReportedMediaCaptureState): 36 * UIProcess/WebPageProxy.h: 37 (WebKit::WebPageProxy::reportedMediaCaptureState const): 38 (WebKit::WebPageProxy::mediaCaptureReportingDelay const): 39 (WebKit::WebPageProxy::setMediaCaptureReportingDelay): 40 1 41 2020-09-15 Youenn Fablet <youenn@apple.com> 2 42 -
trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp
r265916 r267081 2863 2863 WKMediaState WKPageGetMediaState(WKPageRef page) 2864 2864 { 2865 WebCore::MediaProducer::MediaStateFlags coreState = toImpl(page)-> mediaStateFlags();2865 WebCore::MediaProducer::MediaStateFlags coreState = toImpl(page)->reportedMediaCaptureState(); 2866 2866 WKMediaState state = kWKMediaIsNotPlaying; 2867 2867 … … 2998 2998 #endif 2999 2999 } 3000 3001 void WKPageSetMediaCaptureReportingDelayForTesting(WKPageRef page, double delay) 3002 { 3003 toImpl(page)->setMediaCaptureReportingDelay(Seconds(delay)); 3004 } -
trunk/Source/WebKit/UIProcess/API/C/WKPagePrivate.h
r265916 r267081 199 199 WK_EXPORT void WKPageClearLoadedSubresourceDomains(WKPageRef page); 200 200 201 WK_EXPORT void WKPageSetMediaCaptureReportingDelayForTesting(WKPageRef page, double delay); 202 201 203 #ifdef __cplusplus 202 204 } -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
r266993 r267081 2952 2952 - (_WKMediaCaptureState)_mediaCaptureState 2953 2953 { 2954 return WebKit::toWKMediaCaptureState(_page-> mediaStateFlags());2954 return WebKit::toWKMediaCaptureState(_page->reportedMediaCaptureState()); 2955 2955 } 2956 2956 -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h
r266847 r267081 49 49 50 50 - (void)_denyNextUserMediaRequest; 51 @property (nonatomic, setter=_setMediaCaptureReportingDelayForTesting:) double _mediaCaptureReportingDelayForTesting WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 51 52 52 53 - (BOOL)_beginBackSwipeForTesting; -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm
r266847 r267081 227 227 } 228 228 229 - (double)_mediaCaptureReportingDelayForTesting 230 { 231 return _page->mediaCaptureReportingDelay().value(); 232 } 233 234 - (void)_setMediaCaptureReportingDelayForTesting:(double)captureReportingDelay 235 { 236 _page->setMediaCaptureReportingDelay(Seconds(captureReportingDelay)); 237 } 238 229 239 - (void)_doAfterProcessingAllPendingMouseEvents:(dispatch_block_t)action 230 240 { -
trunk/Source/WebKit/UIProcess/WebPageProxy.cpp
r266890 r267081 9038 9038 #if ENABLE(MEDIA_STREAM) 9039 9039 if (oldMediaCaptureState != newMediaCaptureState) { 9040 m_uiClient->mediaCaptureStateDidChange(m_mediaState); 9040 updateReportedMediaCaptureState(); 9041 9041 9042 ASSERT(m_userMediaPermissionRequestManager); 9042 9043 if (m_userMediaPermissionRequestManager) … … 9055 9056 9056 9057 m_process->updateAudibleMediaAssertions(); 9058 } 9059 9060 void WebPageProxy::updateReportedMediaCaptureState() 9061 { 9062 if (m_reportedMediaCaptureState == m_mediaState) 9063 return; 9064 9065 bool haveReportedCapture = m_reportedMediaCaptureState & MediaProducer::MediaCaptureMask; 9066 bool willReportCapture = m_mediaState & MediaProducer::MediaCaptureMask; 9067 9068 if (haveReportedCapture && !willReportCapture && m_delayStopCapturingReportingTimer.isActive()) 9069 return; 9070 9071 if (!haveReportedCapture && willReportCapture) { 9072 m_delayStopCapturingReporting = true; 9073 m_delayStopCapturingReportingTimer.doTask([this] { 9074 m_delayStopCapturingReporting = false; 9075 updateReportedMediaCaptureState(); 9076 }, m_mediaCaptureReportingDelay); 9077 } 9078 9079 m_reportedMediaCaptureState = m_mediaState; 9080 m_uiClient->mediaCaptureStateDidChange(m_mediaState); 9057 9081 } 9058 9082 -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r266890 r267081 1450 1450 bool isPlayingAudio() const { return !!(m_mediaState & WebCore::MediaProducer::IsPlayingAudio); } 1451 1451 void isPlayingMediaDidChange(WebCore::MediaProducer::MediaStateFlags, uint64_t); 1452 void updateReportedMediaCaptureState(); 1453 1452 1454 void updatePlayingMediaDidChange(WebCore::MediaProducer::MediaStateFlags); 1453 1455 bool isCapturingAudio() const { return m_mediaState & WebCore::MediaProducer::AudioCaptureMask; } … … 1456 1458 bool hasActiveVideoStream() const { return m_mediaState & WebCore::MediaProducer::HasActiveVideoCaptureDevice; } 1457 1459 WebCore::MediaProducer::MediaStateFlags mediaStateFlags() const { return m_mediaState; } 1460 WebCore::MediaProducer::MediaStateFlags reportedMediaCaptureState() const { return m_reportedMediaCaptureState; } 1458 1461 WebCore::MediaProducer::MutedStateFlags mutedStateFlags() const { return m_mutedState; } 1459 1462 … … 1821 1824 void pdfOpenWithPreview(PDFPluginIdentifier); 1822 1825 #endif 1826 1827 Seconds mediaCaptureReportingDelay() const { return m_mediaCaptureReportingDelay; } 1828 void setMediaCaptureReportingDelay(Seconds captureReportingDelay) { m_mediaCaptureReportingDelay = captureReportingDelay; } 1823 1829 1824 1830 private: … … 2757 2763 WebCore::MediaProducer::MediaStateFlags m_mediaState { WebCore::MediaProducer::IsNotPlaying }; 2758 2764 2765 // To make sure capture indicators are visible long enough, m_reportedMediaCaptureState is the same as m_mediaState except that we might delay a bit transition from capturing to not-capturing. 2766 WebCore::MediaProducer::MediaStateFlags m_reportedMediaCaptureState { WebCore::MediaProducer::IsNotPlaying }; 2767 WebCore::DeferrableTaskTimer m_delayStopCapturingReportingTimer; 2768 bool m_delayStopCapturingReporting { false }; 2769 static constexpr Seconds DefaultMediaCaptureReportingDelay { 3_s }; 2770 Seconds m_mediaCaptureReportingDelay { DefaultMediaCaptureReportingDelay }; 2771 2759 2772 bool m_hasHadSelectionChangesFromUserInteraction { false }; 2760 2773 -
trunk/Tools/ChangeLog
r267069 r267081 1 2020-09-15 Youenn Fablet <youenn@apple.com> 2 3 End of media capture should not be reported before 3 seconds of the start of capture 4 https://bugs.webkit.org/show_bug.cgi?id=216415 5 6 Reviewed by Eric Carlson. 7 8 * TestWebKitAPI/Tests/WebKit/GetUserMedia.mm: 9 (TestWebKitAPI::TEST): 10 * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm: 11 (-[GetUserMediaUIDelegate _webView:mediaCaptureStateDidChange:]): 12 Add a notCapturing boolean and wait for the notification before going back to the capturing page. 13 Decrease delay to 1 second to make the test run faster. 14 * WebKitTestRunner/TestController.cpp: 15 (WTR::TestController::resetStateToConsistentValues): 16 Make sure to set media capture state delay to zero. 17 1 18 2020-09-14 Sam Weinig <weinig@apple.com> 2 19 -
trunk/Tools/TestWebKitAPI/Tests/WebKit/GetUserMedia.mm
r256377 r267081 37 37 #import <WebKit/WKWebView.h> 38 38 #import <WebKit/WKWebViewConfiguration.h> 39 #import <WebKit/WKWebViewPrivateForTesting.h> 39 40 #import <WebKit/_WKProcessPoolConfiguration.h> 40 41 #import <wtf/text/StringBuilder.h> … … 125 126 webView.UIDelegate = delegate.get(); 126 127 128 webView._mediaCaptureReportingDelayForTesting = 0; 129 127 130 [webView loadTestPageNamed:@"getUserMedia"]; 128 131 EXPECT_TRUE(waitUntilCaptureState(webView, _WKMediaCaptureStateActiveCamera)); … … 202 205 } 203 206 207 TEST(WebKit2, CaptureIndicatorDelay) 208 { 209 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 210 auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]); 211 auto preferences = [configuration preferences]; 212 preferences._mediaCaptureRequiresSecureConnection = NO; 213 preferences._mediaDevicesEnabled = YES; 214 preferences._mockCaptureDevicesEnabled = YES; 215 216 auto messageHandler = adoptNS([[GUMMessageHandler alloc] init]); 217 [[configuration.get() userContentController] addScriptMessageHandler:messageHandler.get() name:@"gum"]; 218 219 auto webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]; 220 webView._mediaCaptureReportingDelayForTesting = 2; 221 222 auto delegate = adoptNS([[GetUserMediaCaptureUIDelegate alloc] init]); 223 webView.UIDelegate = delegate.get(); 224 225 wasPrompted = false; 226 227 [webView loadTestPageNamed:@"getUserMedia"]; 228 EXPECT_TRUE(waitUntilCaptureState(webView, _WKMediaCaptureStateActiveCamera)); 229 230 TestWebKitAPI::Util::run(&wasPrompted); 231 wasPrompted = false; 232 233 [webView stringByEvaluatingJavaScript:@"stop()"]; 234 235 // We wait 1 second, we should still see camera be reported. 236 sleep(1_s); 237 EXPECT_EQ([webView _mediaCaptureState], _WKMediaCaptureStateActiveCamera); 238 239 // One additional second should allow us to go back to no capture being reported. 240 EXPECT_TRUE(waitUntilCaptureState(webView, _WKMediaCaptureStateNone)); 241 242 } 243 204 244 TEST(WebKit2, GetCapabilities) 205 245 { -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm
r266951 r267081 6397 6397 6398 6398 static bool isCapturing = false; 6399 static bool isNotCapturing = false; 6399 6400 @interface GetUserMediaUIDelegate : NSObject<WKUIDelegate> 6400 6401 - (void)_webView:(WKWebView *)webView requestUserMediaAuthorizationForDevices:(_WKCaptureDevices)devices url:(NSURL *)url mainFrameURL:(NSURL *)mainFrameURL decisionHandler:(void (^)(BOOL authorized))decisionHandler; … … 6417 6418 { 6418 6419 isCapturing = state == _WKMediaCaptureStateActiveCamera; 6420 isNotCapturing = !state; 6419 6421 } 6420 6422 @end … … 6449 6451 6450 6452 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]); 6453 webView.get()._mediaCaptureReportingDelayForTesting = 1; 6451 6454 6452 6455 auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]); … … 6473 6476 6474 6477 auto pid2 = [webView _webProcessIdentifier]; 6478 TestWebKitAPI::Util::run(&isNotCapturing); 6475 6479 6476 6480 EXPECT_FALSE(isCapturing); … … 6479 6483 isCapturing = false; 6480 6484 [webView goBack]; 6485 6481 6486 TestWebKitAPI::Util::run(&isCapturing); 6482 6487 isCapturing = false; 6488 isNotCapturing = true; 6483 6489 } 6484 6490 -
trunk/Tools/WebKitTestRunner/TestController.cpp
r266951 r267081 1075 1075 WKPageSetMockCameraOrientation(m_mainWebView->page(), 0); 1076 1076 resetMockMediaDevices(); 1077 WKPageSetMediaCaptureReportingDelayForTesting(m_mainWebView->page(), 0); 1077 1078 1078 1079 // FIXME: This function should also ensure that there is only one page open.
Note: See TracChangeset
for help on using the changeset viewer.