Title: [280840] trunk
Revision
280840
Author
[email protected]
Date
2021-08-10 07:31:51 -0700 (Tue, 10 Aug 2021)

Log Message

[macOS] REGRESSION(r278850): modifying `playbackRate` via JS on a TouchBar mac only sometimes works and also causes the `defaultPlaybackRate` to change
https://bugs.webkit.org/show_bug.cgi?id=228939
<rdar://problem/80427578>

Reviewed by Eric Carlson.

Source/WebCore:

Test: VideoControlsManager.VideoControlsManagerDoesNotChangeValuesExposedToJavaScript

* platform/mac/PlaybackSessionInterfaceMac.mm:
(WebCore::PlaybackSessionInterfaceMac::rateChanged):
Make sure to change the `defaultPlaybackRate` before the `rate` as otherwise the former will
override changes made to the latter (see r278850 (and r277203) for details as to why).

* platform/mac/WebPlaybackControlsManager.h:
* platform/mac/WebPlaybackControlsManager.mm:
(-[WebPlaybackControlsManager setDefaultPlaybackRate:]):
(-[WebPlaybackControlsManager setDefaultPlaybackRate:fromJavaScript:]): Added.
(-[WebPlaybackControlsManager setRate:]):
(-[WebPlaybackControlsManager setRate:fromJavaScript:]): Added.
Add a way to distinguish whether the change to the `rate`/`defaultPlaybackRate` came from JS
or some native call (e.g. AVKit). If the former, don't propagate the change to the playback
model (which eventually is the `HTMLMediaElement` in the WebProcess) as that's where the
value came from in the first place. Note that we still want to propagate the `rate` to the
`defaultPlaybackRate` (and vice versa when `isPlaying`) in the UIProcess for the reasons
described in r278850 (and r277203), but we don't want to expose it to JS.

* platform/ios/PlaybackSessionInterfaceAVKit.mm:
(WebCore::PlaybackSessionInterfaceAVKit::rateChanged):
* platform/ios/WebAVPlayerController.h:
* platform/ios/WebAVPlayerController.mm:
(-[WebAVPlayerController setDefaultPlaybackRate:]):
(-[WebAVPlayerController setDefaultPlaybackRate:fromJavaScript:]): Added.
(-[WebAVPlayerController setRate:]):
(-[WebAVPlayerController setRate:fromJavaScript:]): Added.
Drive-by: r278850 was based r277203 (which added the above), so fix that code now too.

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/VideoControlsManager.mm:
(TestWebKitAPI::TEST.VideoControlsManager.VideoControlsManagerDoesNotChangeValuesExposedToJavaScript): Added.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (280839 => 280840)


--- trunk/Source/WebCore/ChangeLog	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Source/WebCore/ChangeLog	2021-08-10 14:31:51 UTC (rev 280840)
@@ -1,3 +1,41 @@
+2021-08-10  Devin Rousso  <[email protected]>
+
+        [macOS] REGRESSION(r278850): modifying `playbackRate` via JS on a TouchBar mac only sometimes works and also causes the `defaultPlaybackRate` to change
+        https://bugs.webkit.org/show_bug.cgi?id=228939
+        <rdar://problem/80427578>
+
+        Reviewed by Eric Carlson.
+
+        Test: VideoControlsManager.VideoControlsManagerDoesNotChangeValuesExposedToJavaScript
+
+        * platform/mac/PlaybackSessionInterfaceMac.mm:
+        (WebCore::PlaybackSessionInterfaceMac::rateChanged):
+        Make sure to change the `defaultPlaybackRate` before the `rate` as otherwise the former will
+        override changes made to the latter (see r278850 (and r277203) for details as to why).
+
+        * platform/mac/WebPlaybackControlsManager.h:
+        * platform/mac/WebPlaybackControlsManager.mm:
+        (-[WebPlaybackControlsManager setDefaultPlaybackRate:]):
+        (-[WebPlaybackControlsManager setDefaultPlaybackRate:fromJavaScript:]): Added.
+        (-[WebPlaybackControlsManager setRate:]):
+        (-[WebPlaybackControlsManager setRate:fromJavaScript:]): Added.
+        Add a way to distinguish whether the change to the `rate`/`defaultPlaybackRate` came from JS
+        or some native call (e.g. AVKit). If the former, don't propagate the change to the playback
+        model (which eventually is the `HTMLMediaElement` in the WebProcess) as that's where the
+        value came from in the first place. Note that we still want to propagate the `rate` to the
+        `defaultPlaybackRate` (and vice versa when `isPlaying`) in the UIProcess for the reasons
+        described in r278850 (and r277203), but we don't want to expose it to JS.
+
+        * platform/ios/PlaybackSessionInterfaceAVKit.mm:
+        (WebCore::PlaybackSessionInterfaceAVKit::rateChanged):
+        * platform/ios/WebAVPlayerController.h:
+        * platform/ios/WebAVPlayerController.mm:
+        (-[WebAVPlayerController setDefaultPlaybackRate:]):
+        (-[WebAVPlayerController setDefaultPlaybackRate:fromJavaScript:]): Added.
+        (-[WebAVPlayerController setRate:]):
+        (-[WebAVPlayerController setRate:fromJavaScript:]): Added.
+        Drive-by: r278850 was based r277203 (which added the above), so fix that code now too.
+
 2021-08-09  Yusuke Suzuki  <[email protected]>
 
         Partially revert r280256 behavior change since it broke Facetime

Modified: trunk/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm (280839 => 280840)


--- trunk/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Source/WebCore/platform/ios/PlaybackSessionInterfaceAVKit.mm	2021-08-10 14:31:51 UTC (rev 280840)
@@ -130,9 +130,9 @@
 
 void PlaybackSessionInterfaceAVKit::rateChanged(OptionSet<PlaybackSessionModel::PlaybackState> playbackState, double playbackRate, double defaultPlaybackRate)
 {
-    [m_playerController setDefaultPlaybackRate:defaultPlaybackRate];
+    [m_playerController setDefaultPlaybackRate:defaultPlaybackRate fromJavaScript:YES];
     if (!playbackState.contains(PlaybackSessionModel::PlaybackState::Stalled))
-        [m_playerController setRate:playbackState.contains(PlaybackSessionModel::PlaybackState::Playing) ? playbackRate : 0.];
+        [m_playerController setRate:playbackState.contains(PlaybackSessionModel::PlaybackState::Playing) ? playbackRate : 0. fromJavaScript:YES];
 }
 
 void PlaybackSessionInterfaceAVKit::seekableRangesChanged(const TimeRanges& timeRanges, double lastModifiedTime, double liveUpdateInterval)

Modified: trunk/Source/WebCore/platform/ios/WebAVPlayerController.h (280839 => 280840)


--- trunk/Source/WebCore/platform/ios/WebAVPlayerController.h	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Source/WebCore/platform/ios/WebAVPlayerController.h	2021-08-10 14:31:51 UTC (rev 280840)
@@ -103,6 +103,9 @@
 
 @property (NS_NONATOMIC_IOSONLY, retain, readwrite) AVValueTiming *minTiming;
 @property (NS_NONATOMIC_IOSONLY, retain, readwrite) AVValueTiming *maxTiming;
+
+- (void)setDefaultPlaybackRate:(double)defaultPlaybackRate fromJavaScript:(BOOL)fromJavaScript;
+- (void)setRate:(double)rate fromJavaScript:(BOOL)fromJavaScript;
 @end
 
 #endif

Modified: trunk/Source/WebCore/platform/ios/WebAVPlayerController.mm (280839 => 280840)


--- trunk/Source/WebCore/platform/ios/WebAVPlayerController.mm	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Source/WebCore/platform/ios/WebAVPlayerController.mm	2021-08-10 14:31:51 UTC (rev 280840)
@@ -165,16 +165,21 @@
 
 - (void)setDefaultPlaybackRate:(double)defaultPlaybackRate
 {
+    [self setDefaultPlaybackRate:defaultPlaybackRate fromJavaScript:NO];
+}
+
+- (void)setDefaultPlaybackRate:(double)defaultPlaybackRate fromJavaScript:(BOOL)fromJavaScript
+{
     if (defaultPlaybackRate == _defaultPlaybackRate)
         return;
 
     _defaultPlaybackRate = defaultPlaybackRate;
 
-    if (self.delegate && self.delegate->defaultPlaybackRate() != _defaultPlaybackRate)
+    if (!fromJavaScript && self.delegate && self.delegate->defaultPlaybackRate() != _defaultPlaybackRate)
         self.delegate->setDefaultPlaybackRate(_defaultPlaybackRate);
 
     if ([self isPlaying])
-        [self setRate:_defaultPlaybackRate];
+        [self setRate:_defaultPlaybackRate fromJavaScript:fromJavaScript];
 }
 
 - (double)rate
@@ -184,6 +189,11 @@
 
 - (void)setRate:(double)rate
 {
+    [self setRate:rate fromJavaScript:NO];
+}
+
+- (void)setRate:(double)rate fromJavaScript:(BOOL)fromJavaScript
+{
     if (rate == _rate)
         return;
 
@@ -201,9 +211,9 @@
     // ending scanning, with the `playbackRate` being used in all other cases, including when
     // resuming after pausing. As such, WebKit should return the `playbackRate` instead of the
     // `defaultPlaybackRate` in these cases when communicating with AVKit.
-    [self setDefaultPlaybackRate:_rate];
+    [self setDefaultPlaybackRate:_rate fromJavaScript:fromJavaScript];
 
-    if (self.delegate && self.delegate->playbackRate() != _rate)
+    if (!fromJavaScript && self.delegate && self.delegate->playbackRate() != _rate)
         self.delegate->setPlaybackRate(_rate);
 }
 

Modified: trunk/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm (280839 => 280840)


--- trunk/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm	2021-08-10 14:31:51 UTC (rev 280840)
@@ -97,8 +97,8 @@
 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
     auto isPlaying = playbackState.contains(PlaybackSessionModel::PlaybackState::Playing);
     WebPlaybackControlsManager* controlsManager = playBackControlsManager();
-    [controlsManager setRate:isPlaying ? playbackRate : 0.];
-    [controlsManager setDefaultPlaybackRate:defaultPlaybackRate];
+    [controlsManager setDefaultPlaybackRate:defaultPlaybackRate fromJavaScript:YES];
+    [controlsManager setRate:isPlaying ? playbackRate : 0. fromJavaScript:YES];
     [controlsManager setPlaying:isPlaying];
     updatePlaybackControlsManagerTiming(m_playbackSessionModel ? m_playbackSessionModel->currentTime() : 0, [[NSProcessInfo processInfo] systemUptime], playbackRate, isPlaying);
 #else

Modified: trunk/Source/WebCore/platform/mac/WebPlaybackControlsManager.h (280839 => 280840)


--- trunk/Source/WebCore/platform/mac/WebPlaybackControlsManager.h	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Source/WebCore/platform/mac/WebPlaybackControlsManager.h	2021-08-10 14:31:51 UTC (rev 280840)
@@ -84,6 +84,9 @@
 - (void)setLegibleMediaSelectionOptions:(const Vector<WebCore::MediaSelectionOption>&)options withSelectedIndex:(NSUInteger)selectedIndex;
 - (void)setAudioMediaSelectionIndex:(NSUInteger)selectedIndex;
 - (void)setLegibleMediaSelectionIndex:(NSUInteger)selectedIndex;
+
+- (void)setDefaultPlaybackRate:(double)defaultPlaybackRate fromJavaScript:(BOOL)fromJavaScript;
+- (void)setRate:(double)rate fromJavaScript:(BOOL)fromJavaScript;
 @end
 
 #endif // ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)

Modified: trunk/Source/WebCore/platform/mac/WebPlaybackControlsManager.mm (280839 => 280840)


--- trunk/Source/WebCore/platform/mac/WebPlaybackControlsManager.mm	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Source/WebCore/platform/mac/WebPlaybackControlsManager.mm	2021-08-10 14:31:51 UTC (rev 280840)
@@ -336,18 +336,23 @@
 
 - (void)setDefaultPlaybackRate:(double)defaultPlaybackRate
 {
+    [self setDefaultPlaybackRate:defaultPlaybackRate fromJavaScript:NO];
+}
+
+- (void)setDefaultPlaybackRate:(double)defaultPlaybackRate fromJavaScript:(BOOL)fromJavaScript
+{
     if (defaultPlaybackRate == _defaultPlaybackRate)
         return;
 
     _defaultPlaybackRate = defaultPlaybackRate;
 
-    if (_playbackSessionInterfaceMac) {
+    if (!fromJavaScript && _playbackSessionInterfaceMac) {
         if (auto* model = _playbackSessionInterfaceMac->playbackSessionModel(); model && model->defaultPlaybackRate() != _defaultPlaybackRate)
             model->setDefaultPlaybackRate(_defaultPlaybackRate);
     }
 
     if ([self isPlaying])
-        [self setRate:_defaultPlaybackRate];
+        [self setRate:_defaultPlaybackRate fromJavaScript:fromJavaScript];
 }
 
 - (float)rate
@@ -357,6 +362,11 @@
 
 - (void)setRate:(float)rate
 {
+    [self setRate:rate fromJavaScript:NO];
+}
+
+- (void)setRate:(double)rate fromJavaScript:(BOOL)fromJavaScript
+{
     if (rate == _rate)
         return;
 
@@ -374,9 +384,9 @@
     // ending scanning, with the `playbackRate` being used in all other cases, including when
     // resuming after pausing. As such, WebKit should return the `playbackRate` instead of the
     // `defaultPlaybackRate` in these cases when communicating with AVKit.
-    [self setDefaultPlaybackRate:_rate];
+    [self setDefaultPlaybackRate:_rate fromJavaScript:fromJavaScript];
 
-    if (_playbackSessionInterfaceMac) {
+    if (!fromJavaScript && _playbackSessionInterfaceMac) {
         if (auto* model = _playbackSessionInterfaceMac->playbackSessionModel(); model && model->playbackRate() != _rate)
             model->setPlaybackRate(_rate);
     }

Modified: trunk/Tools/ChangeLog (280839 => 280840)


--- trunk/Tools/ChangeLog	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Tools/ChangeLog	2021-08-10 14:31:51 UTC (rev 280840)
@@ -1,3 +1,14 @@
+2021-08-10  Devin Rousso  <[email protected]>
+
+        [macOS] REGRESSION(r278850): modifying `playbackRate` via JS on a TouchBar mac only sometimes works and also causes the `defaultPlaybackRate` to change
+        https://bugs.webkit.org/show_bug.cgi?id=228939
+        <rdar://problem/80427578>
+
+        Reviewed by Eric Carlson.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/VideoControlsManager.mm:
+        (TestWebKitAPI::TEST.VideoControlsManager.VideoControlsManagerDoesNotChangeValuesExposedToJavaScript): Added.
+
 2021-08-08  Wenson Hsieh  <[email protected]>
 
         caret-color does not work on first click in ios

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/VideoControlsManager.mm (280839 => 280840)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/VideoControlsManager.mm	2021-08-10 09:35:09 UTC (rev 280839)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/VideoControlsManager.mm	2021-08-10 14:31:51 UTC (rev 280840)
@@ -28,6 +28,7 @@
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
 #import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/WKWebViewPrivateForTesting.h>
 #import <wtf/RetainPtr.h>
 
@@ -464,6 +465,25 @@
     [webView expectControlsManager:NO afterReceivingMessage:@"playing"];
 }
 
+TEST(VideoControlsManager, VideoControlsManagerDoesNotChangeValuesExposedToJavaScript)
+{
+    RetainPtr<VideoControlsManagerTestWebView> webView = setUpWebViewForTestingVideoControlsManager(NSMakeRect(0, 0, 500, 500));
+
+    // A large video with audio should have a controls manager even if it is played via script like this video.
+    // So the expectation is YES.
+    [webView loadTestPageNamed:@"large-video-with-audio"];
+    [webView waitForMediaControlsToShow];
+    [webView _updateMediaPlaybackControlsManager];
+
+    EXPECT_EQ(1.0, [[webView objectByEvaluatingJavaScript:@"document.getElementsByTagName('video')[0].playbackRate"] doubleValue]);
+    EXPECT_EQ(1.0, [[webView objectByEvaluatingJavaScript:@"document.getElementsByTagName('video')[0].defaultPlaybackRate"] doubleValue]);
+
+    [webView objectByEvaluatingJavaScript:@"document.getElementsByTagName('video')[0].playbackRate = 2.0;"];
+
+    EXPECT_EQ(2.0, [[webView objectByEvaluatingJavaScript:@"document.getElementsByTagName('video')[0].playbackRate"] doubleValue]);
+    EXPECT_EQ(1.0, [[webView objectByEvaluatingJavaScript:@"document.getElementsByTagName('video')[0].defaultPlaybackRate"] doubleValue]);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // PLATFORM(MAC)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to