Diff
Modified: trunk/Source/WebKit/ChangeLog (275536 => 275537)
--- trunk/Source/WebKit/ChangeLog 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/ChangeLog 2021-04-06 19:06:53 UTC (rev 275537)
@@ -1,3 +1,69 @@
+2021-04-06 Eric Carlson <eric.carl...@apple.com>
+
+ [macOS] Add MediaSessionCoordinator API test
+ https://bugs.webkit.org/show_bug.cgi?id=224140
+ <rdar://problem/76171173>
+
+ Reviewed by Jer Noble.
+
+ * Sources.txt: Include RemoteMediaSessionCoordinatorProxy.cpp and RemoteMediaSessionCoordinator.cpp
+ so they don't have to be included in the Xcode project.
+
+ * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h: Declare enums, struct, and protocols
+ necessary to implement and use an object derived from MediaSessionCoordinatorProxyPrivate.
+ * UIProcess/API/Cocoa/WKWebViewTesting.mm:
+ (-[WKWebView _createMediaSessionCoordinatorForTesting:completionHandler:]): New private
+ method to create a MediaSessionCoordinatorProxyPrivate.
+ (-[WKMediaSessionCoordinatorHelper initWithCoordinator:]):
+ (-[WKMediaSessionCoordinatorHelper seekSessionToTime:withCompletion:]):
+ (-[WKMediaSessionCoordinatorHelper playSessionWithCompletion:]):
+ (-[WKMediaSessionCoordinatorHelper pauseSessionWithCompletion:]):
+ (-[WKMediaSessionCoordinatorHelper setSessionTrack:withCompletion:]):
+
+ * UIProcess/Cocoa/WebViewImpl.h:
+ (WebKit::WebViewImpl::mediaSessionCoordinatorForTesting): MediaSessionCoordinatorProxyPrivate
+ getter.
+ * UIProcess/Cocoa/WebViewImpl.mm:
+ (WebKit::WebViewImpl::setMediaSessionCoordinatorForTesting): Setter for
+ MediaSessionCoordinatorProxyPrivate drived object.
+
+ * UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h: Add typedef for the completion
+ handler used by many coordinator proxy methods.
+
+ * UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp:
+ (WebKit::RemoteMediaSessionCoordinatorProxy::RemoteMediaSessionCoordinatorProxy):
+ Set the private coordinator client so calls to the session can be forwarded.
+ (WebKit::RemoteMediaSessionCoordinatorProxy::join): Use MediaSessionCommandCompletionHandler.
+ (WebKit::RemoteMediaSessionCoordinatorProxy::coordinateSeekTo): Ditto.
+ (WebKit::RemoteMediaSessionCoordinatorProxy::coordinatePlay): Ditto.
+ (WebKit::RemoteMediaSessionCoordinatorProxy::coordinatePause): Ditto.
+ (WebKit::RemoteMediaSessionCoordinatorProxy::coordinateSetTrack): Ditto.
+ (WebKit::RemoteMediaSessionCoordinatorProxy::coordinatorStateChanged): Ditto.
+ * UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h:
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::createMediaSessionCoordinator): Change completion handler
+ parameter to return a bool instead of a RemoteMediaSessionCoordinatorProxy as the
+ client interface provides all of the session access needed.
+ * UIProcess/WebPageProxy.h:
+
+ * WebKit.xcodeproj/project.pbxproj: Remove RemoteMediaSessionCoordinatorProxy.cpp
+ and RemoteMediaSessionCoordinator.cpp
+
+ * WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp:
+ (WebKit::RemoteMediaSessionCoordinator::join): Use ExceptionData's toException()
+ method instead of creating an Exception directly. Remove the destination ID parameter
+ to sendWithAsyncReply so messageSenderDestinationID() will be used.
+ (WebKit::RemoteMediaSessionCoordinator::leave): Ditto.
+ (WebKit::RemoteMediaSessionCoordinator::seekTo) Ditto.:
+ (WebKit::RemoteMediaSessionCoordinator::play): Ditto.
+ (WebKit::RemoteMediaSessionCoordinator::pause): Ditto.
+ (WebKit::RemoteMediaSessionCoordinator::setTrack): Ditto.
+ (WebKit::RemoteMediaSessionCoordinator::positionStateChanged): Ditto.
+ (WebKit::RemoteMediaSessionCoordinator::readyStateChanged): Ditto.
+ (WebKit::RemoteMediaSessionCoordinator::playbackStateChanged): Ditto.
+ (WebKit::RemoteMediaSessionCoordinator::coordinatorStateChanged): Ditto.
+
2021-04-06 Aditya Keerthi <akeer...@apple.com>
[iOS] Prevent background blur when presenting date/time pickers
Modified: trunk/Source/WebKit/Sources.txt (275536 => 275537)
--- trunk/Source/WebKit/Sources.txt 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/Sources.txt 2021-04-06 19:06:53 UTC (rev 275537)
@@ -469,6 +469,7 @@
UIProcess/Media/AudioSessionRoutingArbitratorProxy.cpp
UIProcess/Media/MediaUsageManager.cpp
+UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp
UIProcess/Notifications/NotificationPermissionRequestManagerProxy.cpp
UIProcess/Notifications/WebNotification.cpp
@@ -581,6 +582,8 @@
WebProcess/Inspector/WebPageInspectorTargetController.cpp
WebProcess/Inspector/WebPageInspectorTargetFrontendChannel.cpp
+WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp
+
WebProcess/MediaStream/MediaDeviceSandboxExtensions.cpp
WebProcess/MediaStream/UserMediaPermissionRequestManager.cpp
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h 2021-04-06 19:06:53 UTC (rev 275537)
@@ -26,6 +26,8 @@
#import "WKWebViewPrivateForTestingIOS.h"
#import "WKWebViewPrivateForTestingMac.h"
+NS_ASSUME_NONNULL_BEGIN
+
typedef enum {
WKWebViewAudioRoutingArbitrationStatusNone,
WKWebViewAudioRoutingArbitrationStatusPending,
@@ -37,6 +39,8 @@
BOOL hasLoadedNonAppBoundRequestTesting;
};
+@protocol _WKMediaSessionCoordinator;
+
@interface WKWebView (WKTesting)
- (void)_setPageScale:(CGFloat)scale withOrigin:(CGPoint)origin;
@@ -99,4 +103,56 @@
- (void)_appBoundNavigationData:(void(^)(struct WKAppBoundNavigationTestingData data))completionHandler;
- (void)_clearAppBoundNavigationData:(void(^)(void))completionHandler;
+- (void)_createMediaSessionCoordinatorForTesting:(id <_WKMediaSessionCoordinator>)privateCoordinator completionHandler:(void(^)(BOOL))completionHandler;
+
@end
+
+typedef NS_ENUM(NSInteger, _WKMediaSessionReadyState) {
+ WKMediaSessionReadyStateHaveNothing,
+ WKMediaSessionReadyStateHaveMetadata,
+ WKMediaSessionReadyStateHaveCurrentData,
+ WKMediaSessionReadyStateHaveFutureData,
+ WKMediaSessionReadyStateHaveEnoughData
+};
+
+typedef NS_ENUM(NSInteger, _WKMediaSessionPlaybackState) {
+ WKMediaSessionPlaybackStateNone,
+ WKMediaSessionPlaybackStatePaused,
+ WKMediaSessionPlaybackStatePlaying
+};
+
+typedef NS_ENUM(NSInteger, _WKMediaSessionCoordinatorState) {
+ WKMediaSessionCoordinatorStateWaiting,
+ WKMediaSessionCoordinatorStateJoined,
+ WKMediaSessionCoordinatorStateClosed
+};
+
+struct _WKMediaPositionState {
+ double duration;
+ double playbackRate;
+ double position;
+};
+
+@protocol _WKMediaSessionCoordinatorDelegate <NSObject>
+- (void)seekSessionToTime:(double)time withCompletion:(void(^)(BOOL))completionHandler;
+- (void)playSessionWithCompletion:(void(^)(BOOL))completionHandler;
+- (void)pauseSessionWithCompletion:(void(^)(BOOL))completionHandler;
+- (void)setSessionTrack:(NSString*)trackIdentifier withCompletion:(void(^)(BOOL))completionHandler;
+@end
+
+@protocol _WKMediaSessionCoordinator <NSObject>
+@property (nullable, weak) id <_WKMediaSessionCoordinatorDelegate> delegate;
+@property (nonatomic, readonly) NSString * _Nonnull identifier;
+- (void)joinWithCompletion:(void(^ _Nonnull)(BOOL))completionHandler;
+- (void)leave;
+- (void)seekTo:(double)time withCompletion:(void(^ _Nonnull)(BOOL))completionHandler;
+- (void)playWithCompletion:(void(^ _Nonnull)(BOOL))completionHandler;
+- (void)pauseWithCompletion:(void(^ _Nonnull)(BOOL))completionHandler;
+- (void)setTrack:(NSString *_Nonnull)trackIdentifier withCompletion:(void(^ _Nonnull)(BOOL))completionHandler;
+- (void)positionStateChanged:(struct _WKMediaPositionState * _Nullable)state;
+- (void)readyStateChanged:(_WKMediaSessionReadyState)state;
+- (void)playbackStateChanged:(_WKMediaSessionPlaybackState)state;
+- (void)coordinatorStateChanged:(_WKMediaSessionCoordinatorState)state;
+@end
+
+NS_ASSUME_NONNULL_END
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm 2021-04-06 19:06:53 UTC (rev 275537)
@@ -27,6 +27,7 @@
#import "WKWebViewPrivateForTesting.h"
#import "AudioSessionRoutingArbitratorProxy.h"
+#import "MediaSessionCoordinatorProxyPrivate.h"
#import "PlaybackSessionManagerProxy.h"
#import "UserMediaProcessManager.h"
#import "ViewGestureController.h"
@@ -39,7 +40,17 @@
#import "_WKInspectorInternal.h"
#import <WebCore/RuntimeApplicationChecks.h>
#import <WebCore/ValidationBubble.h>
+#import <wtf/RetainPtr.h>
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+@interface WKMediaSessionCoordinatorHelper : NSObject <_WKMediaSessionCoordinatorDelegate>
+- (id)initWithCoordinator:(WebCore::MediaSessionCoordinatorClient*)coordinator;
+- (void)seekSessionToTime:(double)time withCompletion:(void(^)(BOOL))completionHandler;
+- (void)playSessionWithCompletion:(void(^)(BOOL))completionHandler;
+- (void)pauseSessionWithCompletion:(void(^)(BOOL))completionHandler;
+- (void)setSessionTrack:(NSString*)trackIdentifier withCompletion:(void(^)(BOOL))completionHandler;
+@end
+#endif
@implementation WKWebView (WKTesting)
@@ -360,4 +371,240 @@
});
}
+- (void)_createMediaSessionCoordinatorForTesting:(id <_WKMediaSessionCoordinator>)privateCoordinator completionHandler:(void(^)(BOOL))completionHandler
+{
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+ class WKMediaSessionCoordinatorForTesting
+ : public WebKit::MediaSessionCoordinatorProxyPrivate
+ , public WebCore::MediaSessionCoordinatorClient {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
+
+ static Ref<WKMediaSessionCoordinatorForTesting> create(id <_WKMediaSessionCoordinator> privateCoordinator)
+ {
+ return adoptRef(*new WKMediaSessionCoordinatorForTesting(privateCoordinator));
+ }
+
+ using WebCore::MediaSessionCoordinatorClient::weakPtrFactory;
+ using WeakValueType = WebCore::MediaSessionCoordinatorClient::WeakValueType;
+
+ private:
+ explicit WKMediaSessionCoordinatorForTesting(id <_WKMediaSessionCoordinator> clientCoordinator)
+ : WebKit::MediaSessionCoordinatorProxyPrivate()
+ , m_clientCoordinator(clientCoordinator)
+ {
+ auto* delegateHelper = [[WKMediaSessionCoordinatorHelper alloc] initWithCoordinator:this];
+ [m_clientCoordinator setDelegate:delegateHelper];
+ m_coordinatorDelegate = adoptNS(delegateHelper);
+ }
+
+ void seekSessionToTime(double time, CompletionHandler<void(bool)>&& callback) final
+ {
+ if (auto coordinatorClient = client())
+ coordinatorClient->seekSessionToTime(time, WTFMove(callback));
+ else
+ callback(false);
+ }
+
+ void playSession(CompletionHandler<void(bool)>&& callback) final
+ {
+ if (auto coordinatorClient = client())
+ coordinatorClient->playSession(WTFMove(callback));
+ else
+ callback(false);
+ }
+
+ void pauseSession(CompletionHandler<void(bool)>&& callback) final
+ {
+ if (auto coordinatorClient = client())
+ coordinatorClient->pauseSession(WTFMove(callback));
+ else
+ callback(false);
+ }
+
+ void setSessionTrack(const String& trackIdentifier, CompletionHandler<void(bool)>&& callback) final
+ {
+ if (auto coordinatorClient = client())
+ coordinatorClient->setSessionTrack(trackIdentifier, WTFMove(callback));
+ else
+ callback(false);
+ }
+
+ Optional<WebCore::ExceptionData> result(bool success) const
+ {
+ if (!success)
+ return { WebCore::ExceptionData { WebCore::InvalidStateError } };
+
+ return { };
+ }
+
+ String identifier() const
+ {
+ return [m_clientCoordinator identifier];
+ }
+
+ void join(WebKit::MediaSessionCommandCompletionHandler&& callback) final
+ {
+ [m_clientCoordinator joinWithCompletion:makeBlockPtr([weakThis = makeWeakPtr(this), callback = WTFMove(callback)] (BOOL success) mutable {
+ if (!weakThis) {
+ callback(WebCore::ExceptionData { WebCore::InvalidStateError });
+ return;
+ }
+
+ callback(weakThis->result(success));
+ }).get()];
+ }
+
+ void leave() final
+ {
+ [m_clientCoordinator leave];
+ }
+
+ void seekTo(double time, WebKit::MediaSessionCommandCompletionHandler&& callback) final
+ {
+ [m_clientCoordinator seekTo:time withCompletion:makeBlockPtr([weakThis = makeWeakPtr(this), callback = WTFMove(callback)] (BOOL success) mutable {
+ if (!weakThis) {
+ callback(WebCore::ExceptionData { WebCore::InvalidStateError });
+ return;
+ }
+
+ callback(weakThis->result(success));
+ }).get()];
+ }
+
+ void play(WebKit::MediaSessionCommandCompletionHandler&& callback) final
+ {
+ [m_clientCoordinator playWithCompletion:makeBlockPtr([weakThis = makeWeakPtr(this), callback = WTFMove(callback)] (BOOL success) mutable {
+ if (!weakThis) {
+ callback(WebCore::ExceptionData { WebCore::InvalidStateError });
+ return;
+ }
+
+ callback(weakThis->result(success));
+ }).get()];
+ }
+
+ void pause(WebKit::MediaSessionCommandCompletionHandler&& callback) final
+ {
+ [m_clientCoordinator pauseWithCompletion:makeBlockPtr([weakThis = makeWeakPtr(this), callback = WTFMove(callback)] (BOOL success) mutable {
+ if (!weakThis) {
+ callback(WebCore::ExceptionData { WebCore::InvalidStateError });
+ return;
+ }
+
+ callback(weakThis->result(success));
+ }).get()];
+ }
+
+ void setTrack(const String& track, WebKit::MediaSessionCommandCompletionHandler&& callback) final
+ {
+ [m_clientCoordinator setTrack:track withCompletion:makeBlockPtr([weakThis = makeWeakPtr(this), callback = WTFMove(callback)] (BOOL success) mutable {
+ if (!weakThis) {
+ callback(WebCore::ExceptionData { WebCore::InvalidStateError });
+ return;
+ }
+
+ callback(weakThis->result(success));
+ }).get()];
+ }
+
+ void positionStateChanged(const Optional<WebCore::MediaPositionState>& state) final
+ {
+ if (!state) {
+ [m_clientCoordinator positionStateChanged:nil];
+ return;
+ }
+
+ _WKMediaPositionState position = {
+ .duration = state->duration,
+ .playbackRate = state->playbackRate,
+ .position = state->position
+ };
+ [m_clientCoordinator positionStateChanged:&position];
+ }
+
+ void readyStateChanged(WebCore::MediaSessionReadyState state) final
+ {
+ static_assert(static_cast<size_t>(WebCore::MediaSessionReadyState::HaveNothing) == static_cast<size_t>(WKMediaSessionReadyStateHaveNothing), "WKMediaSessionReadyStateHaveNothing does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionReadyState::HaveMetadata) == static_cast<size_t>(WKMediaSessionReadyStateHaveMetadata), "WKMediaSessionReadyStateHaveMetadata does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionReadyState::HaveCurrentData) == static_cast<size_t>(WKMediaSessionReadyStateHaveCurrentData), "WKMediaSessionReadyStateHaveCurrentData does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionReadyState::HaveFutureData) == static_cast<size_t>(WKMediaSessionReadyStateHaveFutureData), "WKMediaSessionReadyStateHaveFutureData does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionReadyState::HaveEnoughData) == static_cast<size_t>(WKMediaSessionReadyStateHaveEnoughData), "WKMediaSessionReadyStateHaveEnoughData does not match WebKit value");
+
+ [m_clientCoordinator readyStateChanged:static_cast<_WKMediaSessionReadyState>(state)];
+ }
+
+ void playbackStateChanged(WebCore::MediaSessionPlaybackState state) final
+ {
+ static_assert(static_cast<size_t>(WebCore::MediaSessionPlaybackState::None) == static_cast<size_t>(WKMediaSessionPlaybackStateNone), "WKMediaSessionPlaybackStateNone does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionPlaybackState::Paused) == static_cast<size_t>(WKMediaSessionPlaybackStatePaused), "WKMediaSessionPlaybackStatePaused does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionPlaybackState::Playing) == static_cast<size_t>(WKMediaSessionPlaybackStatePlaying), "WKMediaSessionPlaybackStatePlaying does not match WebKit value");
+
+ [m_clientCoordinator playbackStateChanged:static_cast<_WKMediaSessionPlaybackState>(state)];
+ }
+
+ void coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state) final
+ {
+ static_assert(static_cast<size_t>(WebCore::MediaSessionCoordinatorState::Waiting) == static_cast<size_t>(WKMediaSessionCoordinatorStateWaiting), "WKMediaSessionCoordinatorStateWaiting does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionCoordinatorState::Joined) == static_cast<size_t>(WKMediaSessionCoordinatorStateJoined), "WKMediaSessionCoordinatorStateJoined does not match WebKit value");
+ static_assert(static_cast<size_t>(WebCore::MediaSessionCoordinatorState::Closed) == static_cast<size_t>(WKMediaSessionCoordinatorStateClosed), "WKMediaSessionCoordinatorStateClosed does not match WebKit value");
+
+ [m_clientCoordinator coordinatorStateChanged:static_cast<_WKMediaSessionCoordinatorState>(state)];
+ }
+
+ private:
+ RetainPtr<id <_WKMediaSessionCoordinator>> m_clientCoordinator;
+ RetainPtr<WKMediaSessionCoordinatorHelper> m_coordinatorDelegate;
+ };
+
+ ASSERT(!_impl->mediaSessionCoordinatorForTesting());
+
+ _impl->setMediaSessionCoordinatorForTesting(WKMediaSessionCoordinatorForTesting::create(privateCoordinator).ptr());
+ _impl->page().createMediaSessionCoordinator(*_impl->mediaSessionCoordinatorForTesting(), [completionHandler = makeBlockPtr(completionHandler)] (bool success) {
+ completionHandler(success);
+ });
+#else
+
+ completionHandler(NO);
+
+#endif
+}
+
@end
+
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+@implementation WKMediaSessionCoordinatorHelper {
+ WeakPtr<WebCore::MediaSessionCoordinatorClient> m_coordinatorClient;
+}
+
+- (id)initWithCoordinator:(WebCore::MediaSessionCoordinatorClient*)coordinator
+{
+ self = [super init];
+ if (!self)
+ return nil;
+ m_coordinatorClient = makeWeakPtr(coordinator);
+ return self;
+}
+
+- (void)seekSessionToTime:(double)time withCompletion:(void(^)(BOOL))completionHandler
+{
+ m_coordinatorClient->seekSessionToTime(time, makeBlockPtr(completionHandler));
+}
+
+- (void)playSessionWithCompletion:(void(^)(BOOL))completionHandler
+{
+ m_coordinatorClient->playSession(makeBlockPtr(completionHandler));
+}
+
+- (void)pauseSessionWithCompletion:(void(^)(BOOL))completionHandler
+{
+ m_coordinatorClient->pauseSession(makeBlockPtr(completionHandler));
+}
+
+- (void)setSessionTrack:(NSString*)trackIdentifier withCompletion:(void(^)(BOOL))completionHandler
+{
+ m_coordinatorClient->setSessionTrack(trackIdentifier, makeBlockPtr(completionHandler));
+}
+
+@end
+#endif
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h 2021-04-06 19:06:53 UTC (rev 275537)
@@ -152,6 +152,7 @@
class PageClient;
class PageClientImpl;
class DrawingAreaProxy;
+class MediaSessionCoordinatorProxyPrivate;
class SafeBrowsingWarning;
class ViewGestureController;
class ViewSnapshot;
@@ -645,6 +646,11 @@
void handleContextMenuTranslation(const String& text, const WebCore::IntRect& boundsInView, const WebCore::IntPoint& menuLocation);
#endif
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+ MediaSessionCoordinatorProxyPrivate* mediaSessionCoordinatorForTesting() { return m_coordinatorForTesting.get(); }
+ void setMediaSessionCoordinatorForTesting(MediaSessionCoordinatorProxyPrivate*);
+#endif
+
private:
#if HAVE(TOUCH_BAR)
void setUpTextTouchBar(NSTouchBar *);
@@ -851,6 +857,10 @@
RetainPtr<WKDOMPasteMenuDelegate> m_domPasteMenuDelegate;
CompletionHandler<void(WebCore::DOMPasteAccessResponse)> m_domPasteRequestHandler;
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+ RefPtr<MediaSessionCoordinatorProxyPrivate> m_coordinatorForTesting;
+#endif
+
#if USE(APPLE_INTERNAL_SDK)
#import <WebKitAdditions/WebViewImplAdditionsAfter.h>
#endif
Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm 2021-04-06 19:06:53 UTC (rev 275537)
@@ -139,6 +139,10 @@
#import <WebCore/ImageExtractionResult.h>
#endif
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+#include <WebKit/MediaSessionCoordinatorProxyPrivate.h>
+#endif
+
#if HAVE(TRANSLATION_UI_SERVICES)
#import <TranslationUIServices/LTUITranslationViewController.h>
@@ -5582,6 +5586,13 @@
return false;
}
+#if ENABLE(MEDIA_SESSION_COORDINATOR)
+void WebViewImpl::setMediaSessionCoordinatorForTesting(MediaSessionCoordinatorProxyPrivate* coordinator)
+{
+ m_coordinatorForTesting = coordinator;
+}
+#endif
+
#if HAVE(TRANSLATION_UI_SERVICES) && ENABLE(CONTEXT_MENUS)
bool WebViewImpl::canHandleContextMenuTranslation() const
Modified: trunk/Source/WebKit/UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/Media/MediaSessionCoordinatorProxyPrivate.h 2021-04-06 19:06:53 UTC (rev 275537)
@@ -38,6 +38,8 @@
namespace WebKit {
+using MediaSessionCommandCompletionHandler = CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>;
+
class MediaSessionCoordinatorProxyPrivate
: public CanMakeWeakPtr<MediaSessionCoordinatorProxyPrivate>
, public RefCounted<MediaSessionCoordinatorProxyPrivate> {
@@ -46,12 +48,12 @@
virtual String identifier() const = 0;
- virtual void join(CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>&&) = 0;
+ virtual void join(MediaSessionCommandCompletionHandler&&) = 0;
virtual void leave() = 0;
- virtual void seekTo(double, CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>&&) = 0;
- virtual void play(CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>&&) = 0;
- virtual void pause(CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>&&) = 0;
- virtual void setTrack(const String&, CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>&&) = 0;
+ virtual void seekTo(double, MediaSessionCommandCompletionHandler&&) = 0;
+ virtual void play(MediaSessionCommandCompletionHandler&&) = 0;
+ virtual void pause(MediaSessionCommandCompletionHandler&&) = 0;
+ virtual void setTrack(const String&, MediaSessionCommandCompletionHandler&&) = 0;
virtual void positionStateChanged(const Optional<WebCore::MediaPositionState>&) = 0;
virtual void readyStateChanged(WebCore::MediaSessionReadyState) = 0;
Modified: trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp 2021-04-06 19:06:53 UTC (rev 275537)
@@ -59,6 +59,7 @@
, m_logIdentifier(LoggerHelper::uniqueLogIdentifier())
#endif
{
+ m_privateCoordinator->setClient(makeWeakPtr(this));
m_webPageProxy.process().addMessageReceiver(Messages::RemoteMediaSessionCoordinatorProxy::messageReceiverName(), m_webPageProxy.webPageID(), *this);
}
@@ -67,7 +68,7 @@
m_webPageProxy.process().removeMessageReceiver(Messages::RemoteMediaSessionCoordinatorProxy::messageReceiverName(), m_webPageProxy.webPageID());
}
-void RemoteMediaSessionCoordinatorProxy::join(CommandCompletionHandler&& completionHandler)
+void RemoteMediaSessionCoordinatorProxy::join(MediaSessionCommandCompletionHandler&& completionHandler)
{
auto identifier = LOGIDENTIFIER;
ALWAYS_LOG(identifier);
@@ -85,7 +86,7 @@
m_privateCoordinator->leave();
}
-void RemoteMediaSessionCoordinatorProxy::coordinateSeekTo(double time, CommandCompletionHandler&& completionHandler)
+void RemoteMediaSessionCoordinatorProxy::coordinateSeekTo(double time, MediaSessionCommandCompletionHandler&& completionHandler)
{
auto identifier = LOGIDENTIFIER;
ALWAYS_LOG(identifier, time);
@@ -96,7 +97,7 @@
});
}
-void RemoteMediaSessionCoordinatorProxy::coordinatePlay(CommandCompletionHandler&& completionHandler)
+void RemoteMediaSessionCoordinatorProxy::coordinatePlay(MediaSessionCommandCompletionHandler&& completionHandler)
{
auto identifier = LOGIDENTIFIER;
ALWAYS_LOG(identifier);
@@ -107,7 +108,7 @@
});
}
-void RemoteMediaSessionCoordinatorProxy::coordinatePause(CommandCompletionHandler&& completionHandler)
+void RemoteMediaSessionCoordinatorProxy::coordinatePause(MediaSessionCommandCompletionHandler&& completionHandler)
{
auto identifier = LOGIDENTIFIER;
ALWAYS_LOG(identifier);
@@ -118,7 +119,7 @@
});
}
-void RemoteMediaSessionCoordinatorProxy::coordinateSetTrack(const String& track, CommandCompletionHandler&& completionHandler)
+void RemoteMediaSessionCoordinatorProxy::coordinateSetTrack(const String& track, MediaSessionCommandCompletionHandler&& completionHandler)
{
auto identifier = LOGIDENTIFIER;
ALWAYS_LOG(identifier);
@@ -147,6 +148,12 @@
m_privateCoordinator->readyStateChanged(state);
}
+void RemoteMediaSessionCoordinatorProxy::coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state)
+{
+ ALWAYS_LOG(LOGIDENTIFIER);
+ m_privateCoordinator->coordinatorStateChanged(state);
+}
+
void RemoteMediaSessionCoordinatorProxy::seekSessionToTime(double time, CompletionHandler<void(bool)>&& callback)
{
m_webPageProxy.sendWithAsyncReply(Messages::RemoteMediaSessionCoordinator::SeekSessionToTime { time }, callback);
@@ -167,12 +174,6 @@
m_webPageProxy.sendWithAsyncReply(Messages::RemoteMediaSessionCoordinator::SetSessionTrack { trackId }, callback);
}
-void RemoteMediaSessionCoordinatorProxy::coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state)
-{
- ALWAYS_LOG(LOGIDENTIFIER);
- m_privateCoordinator->coordinatorStateChanged(state);
-}
-
#if !RELEASE_LOG_DISABLED
WTFLogChannel& RemoteMediaSessionCoordinatorProxy::logChannel() const
{
Modified: trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.h 2021-04-06 19:06:53 UTC (rev 275537)
@@ -41,7 +41,7 @@
class WebPageProxy;
class RemoteMediaSessionCoordinatorProxy
- : public IPC::MessageReceiver
+ : private IPC::MessageReceiver
, public RefCounted<RemoteMediaSessionCoordinatorProxy>
, public WebCore::MediaSessionCoordinatorClient {
WTF_MAKE_FAST_ALLOCATED;
@@ -60,19 +60,16 @@
private:
explicit RemoteMediaSessionCoordinatorProxy(WebPageProxy&, Ref<MediaSessionCoordinatorProxyPrivate>&&);
- using CoordinateCompletionHandler = CompletionHandler<void(const WebCore::ExceptionData&)>;
-
// IPC::MessageReceiver.
void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
// Receivers.
- using CommandCompletionHandler = CompletionHandler<void(Optional<WebCore::ExceptionData>&&)>;
- void join(CommandCompletionHandler&&);
+ void join(MediaSessionCommandCompletionHandler&&);
void leave();
- void coordinateSeekTo(double, CommandCompletionHandler&&);
- void coordinatePlay(CommandCompletionHandler&&);
- void coordinatePause(CommandCompletionHandler&&);
- void coordinateSetTrack(const String&, CommandCompletionHandler&&);
+ void coordinateSeekTo(double, MediaSessionCommandCompletionHandler&&);
+ void coordinatePlay(MediaSessionCommandCompletionHandler&&);
+ void coordinatePause(MediaSessionCommandCompletionHandler&&);
+ void coordinateSetTrack(const String&, MediaSessionCommandCompletionHandler&&);
void positionStateChanged(const Optional<WebCore::MediaPositionState>&);
void readyStateChanged(WebCore::MediaSessionReadyState);
void playbackStateChanged(WebCore::MediaSessionPlaybackState);
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2021-04-06 19:06:53 UTC (rev 275537)
@@ -10403,7 +10403,7 @@
#endif
#if ENABLE(MEDIA_SESSION_COORDINATOR)
-void WebPageProxy::createMediaSessionCoordinator(Ref<MediaSessionCoordinatorProxyPrivate>&& privateCoordinator, CompletionHandler<void(WeakPtr<RemoteMediaSessionCoordinatorProxy>)>&& completionHandler)
+void WebPageProxy::createMediaSessionCoordinator(Ref<MediaSessionCoordinatorProxyPrivate>&& privateCoordinator, CompletionHandler<void(bool)>&& completionHandler)
{
ASSERT(!m_mediaSessionCoordinatorProxy);
@@ -10410,12 +10410,12 @@
sendWithAsyncReply(Messages::WebPage::CreateMediaSessionCoordinator(privateCoordinator->identifier()), [weakThis = makeWeakPtr(*this), privateCoordinator = WTFMove(privateCoordinator), completionHandler = WTFMove(completionHandler)](bool success) mutable {
if (!weakThis || !success) {
- completionHandler({ });
+ completionHandler(false);
return;
}
weakThis->m_mediaSessionCoordinatorProxy = RemoteMediaSessionCoordinatorProxy::create(*weakThis, WTFMove(privateCoordinator));
- completionHandler(makeWeakPtr(weakThis->m_mediaSessionCoordinatorProxy.get()));
+ completionHandler(true);
});
}
#endif
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (275536 => 275537)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2021-04-06 19:06:53 UTC (rev 275537)
@@ -1892,7 +1892,7 @@
#endif
#if ENABLE(MEDIA_SESSION_COORDINATOR)
- void createMediaSessionCoordinator(Ref<MediaSessionCoordinatorProxyPrivate>&&, CompletionHandler<void(WeakPtr<RemoteMediaSessionCoordinatorProxy>)>&&);
+ void createMediaSessionCoordinator(Ref<MediaSessionCoordinatorProxyPrivate>&&, CompletionHandler<void(bool)>&&);
#endif
#if PLATFORM(COCOA)
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (275536 => 275537)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2021-04-06 19:06:53 UTC (rev 275537)
@@ -105,9 +105,9 @@
07297FA31C186ADB003F0735 /* WKUserMediaPermissionCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 07297FA11C186ADB003F0735 /* WKUserMediaPermissionCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
074879B92373A90900F5678E /* AppKitSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 074879B72373A90900F5678E /* AppKitSoftLink.h */; };
074E75FE1DF2211900D318EC /* UserMediaProcessManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 074E75FB1DF1FD1300D318EC /* UserMediaProcessManager.h */; };
+ 075A9CF326169BAB006DFA3A /* MediaSessionCoordinatorProxyPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 077BA570260E8F630072F19F /* MediaSessionCoordinatorProxyPrivate.h */; };
076E884E1A13CADF005E90FC /* APIContextMenuClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 076E884D1A13CADF005E90FC /* APIContextMenuClient.h */; };
0772811D21234FF600C8EF2E /* UserMediaPermissionRequestManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A410F4319AF7B27002EBAB5 /* UserMediaPermissionRequestManager.h */; };
- 077BA56E260E6D1C0072F19F /* RemoteMediaSessionCoordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0736B755260D03A000E06994 /* RemoteMediaSessionCoordinator.cpp */; };
07923148239CBCB8009598E2 /* RemoteMediaPlayerManagerProxyMessagesReplies.h in Headers */ = {isa = PBXBuildFile; fileRef = 07923142239CBCB5009598E2 /* RemoteMediaPlayerManagerProxyMessagesReplies.h */; };
0792314B239CBCB8009598E2 /* RemoteMediaPlayerManagerProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07923145239CBCB7009598E2 /* RemoteMediaPlayerManagerProxyMessageReceiver.cpp */; };
0792314C239CBCB8009598E2 /* RemoteMediaPlayerManagerProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 07923146239CBCB7009598E2 /* RemoteMediaPlayerManagerProxyMessages.h */; };
@@ -1864,7 +1864,6 @@
CD0C6831201FD10100A59409 /* WKFullScreenViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0C682F201FD10100A59409 /* WKFullScreenViewController.h */; };
CD19A26E1A13E834008D650E /* WebDiagnosticLoggingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CD19A26A1A13E821008D650E /* WebDiagnosticLoggingClient.h */; };
CD19D2EA2046406F0017074A /* FullscreenTouchSecheuristic.h in Headers */ = {isa = PBXBuildFile; fileRef = CD19D2E82046406F0017074A /* FullscreenTouchSecheuristic.h */; settings = {ATTRIBUTES = (Private, ); }; };
- CD1FE2D72613E18600ADC29B /* RemoteMediaSessionCoordinatorProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0736B75C260D4A4E00E06994 /* RemoteMediaSessionCoordinatorProxy.cpp */; };
CD3EEF462579C261006563BB /* RemoteMediaEngineConfigurationFactoryProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD3EEF442579C1D4006563BB /* RemoteMediaEngineConfigurationFactoryProxyMessageReceiver.cpp */; };
CD4570D3244113B500A3DCEB /* AudioSessionRoutingArbitratorProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD4570D02441014A00A3DCEB /* AudioSessionRoutingArbitratorProxyMessageReceiver.cpp */; };
CD4570D424411D0F00A3DCEB /* AudioSessionRoutingArbitrator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD4570CB2440FB2A00A3DCEB /* AudioSessionRoutingArbitrator.cpp */; };
@@ -9268,10 +9267,10 @@
5321594F1DBAE6D70054AA3C /* NetworkDataTaskCocoa.h */,
5CBC9B8B1C65257300A8FDCF /* NetworkDataTaskCocoa.mm */,
7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */,
+ 518324782615B00D003F239E /* NetworkSchemeURLProtocol.h */,
+ 518324792615B00D003F239E /* NetworkSchemeURLProtocol.mm */,
532159501DBAE6D70054AA3C /* NetworkSessionCocoa.h */,
5C20CB9B1BB0DCD200895BB1 /* NetworkSessionCocoa.mm */,
- 518324782615B00D003F239E /* NetworkSchemeURLProtocol.h */,
- 518324792615B00D003F239E /* NetworkSchemeURLProtocol.mm */,
41287D4C225C05C5009A3E26 /* WebSocketTaskCocoa.h */,
41287D4B225C05C4009A3E26 /* WebSocketTaskCocoa.mm */,
);
@@ -11676,7 +11675,6 @@
317FE7C51C487A6C00A0CA89 /* APIExperimentalFeature.h in Headers */,
00B9661618E24CBA00CE1F88 /* APIFindClient.h in Headers */,
2DD67A2E1BD819730053B251 /* APIFindMatchesClient.h in Headers */,
- 5183247D26168FF7003F239E /* NetworkURLSchemeTask.h in Headers */,
37E25D6E18FDE5D6005D3A00 /* APIFormClient.h in Headers */,
1AC1337218566C7C00F3EC05 /* APIFrameHandle.h in Headers */,
2DF9EEE61A781FB400B6CFBE /* APIFrameInfo.h in Headers */,
@@ -11929,6 +11927,7 @@
07E19EFD23D401F10094FFB4 /* MediaPlayerPrivateRemoteMessagesReplies.h in Headers */,
A1B4DCE125A7923C007D178C /* MediaSampleByteRange.h in Headers */,
A15799BD2584433200528236 /* MediaSampleCursor.h in Headers */,
+ 075A9CF326169BAB006DFA3A /* MediaSessionCoordinatorProxyPrivate.h in Headers */,
A15799B72584433200528236 /* MediaTrackReader.h in Headers */,
51933DEF1965EB31008AC3EA /* MenuUtilities.h in Headers */,
9B47908D25314D8300EC11AB /* MessageArgumentDescriptions.h in Headers */,
@@ -11997,6 +11996,8 @@
5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */,
532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */,
417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */,
+ 5183247C26168C62003F239E /* NetworkURLSchemeHandler.h in Headers */,
+ 5183247D26168FF7003F239E /* NetworkURLSchemeTask.h in Headers */,
570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */,
570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */,
31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */,
@@ -12827,7 +12828,6 @@
0FCB4E6818BBE3D9000FCFC9 /* WKTextInputWindowController.h in Headers */,
CE21215F240EE571006ED443 /* WKTextPlaceholder.h in Headers */,
CE45945C240F88550078019F /* WKTextSelectionRect.h in Headers */,
- 5183247C26168C62003F239E /* NetworkURLSchemeHandler.h in Headers */,
2EB6FC01203021960017E619 /* WKTimePickerViewController.h in Headers */,
71A676A622C62325007D6295 /* WKTouchActionGestureRecognizer.h in Headers */,
BC407608124FF0270068F20A /* WKType.h in Headers */,
@@ -14005,8 +14005,6 @@
0701789E23BE9CFC005F0FAA /* RemoteMediaPlayerMIMETypeCache.cpp in Sources */,
071BC58F23CE1EAA00680D7C /* RemoteMediaPlayerProxyMessageReceiver.cpp in Sources */,
1D4D737023A9E54700717A25 /* RemoteMediaResourceManagerMessageReceiver.cpp in Sources */,
- 077BA56E260E6D1C0072F19F /* RemoteMediaSessionCoordinator.cpp in Sources */,
- CD1FE2D72613E18600ADC29B /* RemoteMediaSessionCoordinatorProxy.cpp in Sources */,
1DD2A6632561246F00FF7B6F /* RemoteMediaSourceProxyMessageReceiver.cpp in Sources */,
1AC1338518590C4600F3EC05 /* RemoteObjectRegistryMessageReceiver.cpp in Sources */,
CD8252E225D4919100862FD8 /* RemoteRemoteCommandListenerMessageReceiver.cpp in Sources */,
Modified: trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp (275536 => 275537)
--- trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Source/WebKit/WebProcess/MediaSession/RemoteMediaSessionCoordinator.cpp 2021-04-06 19:06:53 UTC (rev 275537)
@@ -72,17 +72,17 @@
}
if (exception) {
- callback(Exception { exception->code, WTFMove(exception->message) });
+ callback(exception->toException());
return;
}
callback({ });
- }, 0);
+ });
}
void RemoteMediaSessionCoordinator::leave()
{
- m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::Leave { }, 0);
+ m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::Leave { });
}
void RemoteMediaSessionCoordinator::seekTo(double time, CompletionHandler<void(Optional<WebCore::Exception>&&)>&& callback)
@@ -95,12 +95,12 @@
}
if (exception) {
- callback(Exception { exception->code, WTFMove(exception->message) });
+ callback(exception->toException());
return;
}
callback({ });
- }, 0);
+ });
}
void RemoteMediaSessionCoordinator::play(CompletionHandler<void(Optional<WebCore::Exception>&&)>&& callback)
@@ -113,12 +113,12 @@
}
if (exception) {
- callback(Exception { exception->code, WTFMove(exception->message) });
+ callback(exception->toException());
return;
}
callback({ });
- }, 0);
+ });
}
void RemoteMediaSessionCoordinator::pause(CompletionHandler<void(Optional<WebCore::Exception>&&)>&& callback)
@@ -131,12 +131,12 @@
}
if (exception) {
- callback(Exception { exception->code, WTFMove(exception->message) });
+ callback(exception->toException());
return;
}
callback({ });
- }, 0);
+ });
}
void RemoteMediaSessionCoordinator::setTrack(const String& trackIdentifier, CompletionHandler<void(Optional<WebCore::Exception>&&)>&& callback)
@@ -149,36 +149,36 @@
}
if (exception) {
- callback(Exception { exception->code, WTFMove(exception->message) });
+ callback(exception->toException());
return;
}
callback({ });
- }, 0);
+ });
}
void RemoteMediaSessionCoordinator::positionStateChanged(const Optional<WebCore::MediaPositionState>& state)
{
ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER);
- m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::PositionStateChanged { state }, 0);
+ m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::PositionStateChanged { state });
}
void RemoteMediaSessionCoordinator::readyStateChanged(WebCore::MediaSessionReadyState state)
{
ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, state);
- m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::ReadyStateChanged { state }, 0);
+ m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::ReadyStateChanged { state });
}
void RemoteMediaSessionCoordinator::playbackStateChanged(WebCore::MediaSessionPlaybackState state)
{
ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, state);
- m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::PlaybackStateChanged { state }, 0);
+ m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::PlaybackStateChanged { state });
}
void RemoteMediaSessionCoordinator::coordinatorStateChanged(WebCore::MediaSessionCoordinatorState state)
{
ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, state);
- m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::CoordinatorStateChanged { state }, 0);
+ m_page.send(Messages::RemoteMediaSessionCoordinatorProxy::CoordinatorStateChanged { state });
}
void RemoteMediaSessionCoordinator::seekSessionToTime(double time, CompletionHandler<void(bool)>&& completionHandler)
Modified: trunk/Tools/ChangeLog (275536 => 275537)
--- trunk/Tools/ChangeLog 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Tools/ChangeLog 2021-04-06 19:06:53 UTC (rev 275537)
@@ -1,3 +1,56 @@
+2021-04-06 Eric Carlson <eric.carl...@apple.com>
+
+ [macOS] Add MediaSessionCoordinator API test
+ https://bugs.webkit.org/show_bug.cgi?id=224140
+ <rdar://problem/76171173>
+
+ Reviewed by Jer Noble.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/xcshareddata/xcschemes/TestWebKitAPI.xcscheme:
+ * TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm: Added.
+ (-[_WKMockMediaSessionCoordinator lastStateChange]):
+ (-[_WKMockMediaSessionCoordinator lastMethodCalled]):
+ (-[_WKMockMediaSessionCoordinator identifier]):
+ (-[_WKMockMediaSessionCoordinator joinWithCompletion:]):
+ (-[_WKMockMediaSessionCoordinator leave]):
+ (-[_WKMockMediaSessionCoordinator seekTo:withCompletion:]):
+ (-[_WKMockMediaSessionCoordinator playWithCompletion:]):
+ (-[_WKMockMediaSessionCoordinator pauseWithCompletion:]):
+ (-[_WKMockMediaSessionCoordinator setTrack:withCompletion:]):
+ (-[_WKMockMediaSessionCoordinator positionStateChanged:]):
+ (-[_WKMockMediaSessionCoordinator readyStateChanged:]):
+ (-[_WKMockMediaSessionCoordinator playbackStateChanged:]):
+ (-[_WKMockMediaSessionCoordinator coordinatorStateChanged:]):
+ (-[_WKMockMediaSessionCoordinator seekSessionToTime:]):
+ (-[_WKMockMediaSessionCoordinator playSession]):
+ (-[_WKMockMediaSessionCoordinator pauseSession]):
+ (-[_WKMockMediaSessionCoordinator setSessionTrack:]):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::createCoordinator):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::webView const):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::coordinator const):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::loadPageAndBecomeReady):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::runScriptWithUserGesture):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::play):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::pause):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::listenForEventMessages):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::eventListenerWasCalled):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::clearEventListenerState):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::executeUntil):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::waitForEventListenerToBeCalled):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::listenForMessagesPosted):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::clearMessagesPosted):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::listenForSessionHandlerMessages):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::sessionHandlerWasCalled):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::waitForSessionHandlerToBeCalled):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::listenForPromiseMessages):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::clearPromiseMessages):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::promiseWasResolved):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::promiseWasRejected):
+ (TestWebKitAPI::MediaSessionCoordinatorTest::waitForPromise):
+ (TestWebKitAPI::TEST_F):
+ * TestWebKitAPI/Tests/WebKitCocoa/media-remote.html:
+
2021-04-06 David Kilzer <ddkil...@apple.com>
set-webkit-configuration should print current settings
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (275536 => 275537)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-04-06 19:06:53 UTC (rev 275537)
@@ -54,6 +54,7 @@
074994421EA5034B000DA44F /* ondevicechange.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 4A410F4D19AF7BEF002EBAB6 /* ondevicechange.html */; };
074994421EA5034B000DA45E /* getUserMediaAudioVideoCapture.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 4A410F4D19AF7BEF002EBAC5 /* getUserMediaAudioVideoCapture.html */; };
074994521EA5034B000DA44E /* getUserMedia2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 41BAF4E225AC9DB800D82F32 /* getUserMedia2.html */; };
+ 075A9CF526177218006DFA3A /* MediaSessionCoordinatorTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 075A9CF426177217006DFA3A /* MediaSessionCoordinatorTest.mm */; };
076E507F1F4513D6006E9F5A /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 076E507E1F45031E006E9F5A /* Logging.cpp */; };
077A5AF3230638A600A7105C /* AccessibilityTestPlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0746645822FF630500E3451A /* AccessibilityTestPlugin.mm */; };
0794740D25CA0BDE00C597EB /* MediaSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0794740C25CA0BDE00C597EB /* MediaSession.mm */; };
@@ -1760,6 +1761,7 @@
0746645822FF630500E3451A /* AccessibilityTestPlugin.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AccessibilityTestPlugin.mm; sourceTree = "<group>"; };
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>"; };
+ 075A9CF426177217006DFA3A /* MediaSessionCoordinatorTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaSessionCoordinatorTest.mm; sourceTree = "<group>"; };
0766DD1F1A5AD5200023E3BB /* PendingAPIRequestURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PendingAPIRequestURL.cpp; sourceTree = "<group>"; };
076E507E1F45031E006E9F5A /* Logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Logging.cpp; sourceTree = "<group>"; };
0794740C25CA0BDE00C597EB /* MediaSession.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaSession.mm; sourceTree = "<group>"; };
@@ -4274,6 +4276,7 @@
33DC8910141953A300747EF7 /* LoadCanceledNoServerRedirectCallback.cpp */,
33DC89131419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp */,
8AA28C1916D2FA7B002FF4DB /* LoadPageOnCrash.cpp */,
+ 075A9CF426177217006DFA3A /* MediaSessionCoordinatorTest.mm */,
CDC9442C1EF1FC080059C3C4 /* MediaStreamTrackDetached.mm */,
7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */,
51CB4AD71B3A079C00C1B1C6 /* ModalAlertsSPI.cpp */,
@@ -5500,6 +5503,7 @@
07EF76D52540FC060053ED53 /* MediaMutedState.mm in Sources */,
CDA315981ED53651009F60D3 /* MediaPlaybackSleepAssertion.mm in Sources */,
0794740D25CA0BDE00C597EB /* MediaSession.mm in Sources */,
+ 075A9CF526177218006DFA3A /* MediaSessionCoordinatorTest.mm in Sources */,
CDC9442E1EF1FC080059C3C4 /* MediaStreamTrackDetached.mm in Sources */,
51BE9E662376089F00B4E117 /* MediaType.mm in Sources */,
7CCE7EC51A411A7E00447C4C /* MemoryCacheDisableWithinResourceLoadDelegate.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm (0 => 275537)
--- trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit/MediaSessionCoordinatorTest.mm 2021-04-06 19:06:53 UTC (rev 275537)
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2021 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 ENABLE(MEDIA_SESSION_COORDINATOR)
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKProcessPoolPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WKWebViewPrivateForTesting.h>
+#import <WebKit/_WKExperimentalFeature.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <wtf/BlockPtr.h>
+#import <wtf/HashSet.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/RunLoop.h>
+#import <wtf/WeakObjCPtr.h>
+#import <wtf/text/StringHash.h>
+
+@interface _WKMockMediaSessionCoordinator : NSObject <_WKMediaSessionCoordinator>
+@property (nonatomic, readonly) NSString *lastStateChange;
+@property (nonatomic, readonly) NSString *lastMethodCalled;
+@property (nonatomic) BOOL failsCommands;
+
+- (void)seekSessionToTime:(double)time;
+- (void)playSession;
+- (void)pauseSession;
+- (void)setSessionTrack:(NSString*)trackIdentifier;
+@end
+
+@implementation _WKMockMediaSessionCoordinator {
+ RetainPtr<NSString> _lastStateChange;
+ RetainPtr<NSString> _lastMethodCalled;
+ id <_WKMediaSessionCoordinatorDelegate> _delegate;
+}
+
+@synthesize delegate;
+
+- (NSString *)lastStateChange
+{
+ return std::exchange(_lastStateChange, @"").get();
+}
+
+- (NSString *)lastMethodCalled
+{
+ return std::exchange(_lastMethodCalled, @"").get();
+}
+
+- (NSString *)identifier
+{
+ return @"TestCoordinator";
+}
+
+- (void)joinWithCompletion:(void(^ _Nonnull)(BOOL))completionHandler
+{
+ _lastMethodCalled = @"join";
+ dispatch_async(dispatch_get_main_queue(), ^() {
+ completionHandler(!_failsCommands);
+ });
+}
+
+- (void)leave
+{
+ _lastMethodCalled = @"leave";
+}
+
+- (void)seekTo:(double)time withCompletion:(void(^ _Nonnull)(BOOL))completionHandler
+{
+ _lastMethodCalled = @"seekTo";
+ dispatch_async(dispatch_get_main_queue(), ^() {
+ completionHandler(!_failsCommands);
+ });
+}
+
+- (void)playWithCompletion:(void(^ _Nonnull)(BOOL))completionHandler
+{
+ _lastMethodCalled = @"play";
+ dispatch_async(dispatch_get_main_queue(), ^() {
+ completionHandler(!_failsCommands);
+ });
+}
+
+- (void)pauseWithCompletion:(void(^ _Nonnull)(BOOL))completionHandler
+{
+ _lastMethodCalled = @"pause";
+ dispatch_async(dispatch_get_main_queue(), ^() {
+ completionHandler(!_failsCommands);
+ });
+}
+
+- (void)setTrack:(NSString*)trackIdentifier withCompletion:(void(^ _Nonnull)(BOOL))completionHandler
+{
+ _lastMethodCalled = @"setTrack";
+ dispatch_async(dispatch_get_main_queue(), ^() {
+ completionHandler(!_failsCommands);
+ });
+}
+
+- (void)positionStateChanged:(nullable _WKMediaPositionState *)state
+{
+ _lastStateChange = @"positionStateChanged";
+}
+
+- (void)readyStateChanged:(_WKMediaSessionReadyState)state
+{
+ _lastStateChange = @"readyStateChanged";
+}
+
+- (void)playbackStateChanged:(_WKMediaSessionPlaybackState)state
+{
+ _lastStateChange = @"playbackStateChanged";
+}
+
+- (void)coordinatorStateChanged:(_WKMediaSessionCoordinatorState)state
+{
+ _lastStateChange = @"coordinatorStateChanged";
+}
+
+- (void)seekSessionToTime:(double)time
+{
+ [self.delegate seekSessionToTime:time withCompletion:^(BOOL result) {
+ _lastMethodCalled = @"seekSessionToTime";
+ }];
+}
+
+- (void)playSession
+{
+ [self.delegate playSessionWithCompletion:^(BOOL result) {
+ _lastMethodCalled = @"playSession";
+ }];
+}
+
+- (void)pauseSession
+{
+ [self.delegate pauseSessionWithCompletion:^(BOOL result) {
+ _lastMethodCalled = @"pauseSession";
+ }];
+}
+
+- (void)setSessionTrack:(NSString*)trackIdentifier
+{
+ [self.delegate setSessionTrack:trackIdentifier withCompletion:^(BOOL result) {
+ _lastMethodCalled = @"setSessionTrack";
+ }];
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+class MediaSessionCoordinatorTest : public testing::Test {
+public:
+ void SetUp() final
+ {
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto preferences = [configuration preferences];
+
+ for (_WKExperimentalFeature *feature in [WKPreferences _experimentalFeatures]) {
+ if ([feature.key isEqualToString:@"MediaSessionCoordinatorEnabled"])
+ [preferences _setEnabled:YES forFeature:feature];
+ if ([feature.key isEqualToString:@"MediaSessionEnabled"])
+ [preferences _setEnabled:YES forFeature:feature];
+ }
+
+ _webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
+ }
+
+ void TearDown() override
+ {
+ [_webView clearMessageHandlers:_messageHandlers.get()];
+ }
+
+ void createCoordinator()
+ {
+ _coordinator = [[_WKMockMediaSessionCoordinator alloc] init];
+
+ __block bool result = false;
+ __block bool done = false;
+ [webView() _createMediaSessionCoordinatorForTesting:(id <_WKMediaSessionCoordinator>)_coordinator.get() completionHandler:^(BOOL success) {
+ result = success;
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+
+ listenForEventMessages({ "coordinatorchange"_s });
+
+ EXPECT_TRUE(result);
+ if (!result)
+ NSLog(@"-[_createMediaSessionCoordinatorForTesting:completionHandler:] failed!");
+
+ waitForEventListenerToBeCalled("coordinatorchange"_s);
+ ASSERT_TRUE(eventListenerWasCalled("coordinatorchange"_s));
+ }
+
+ TestWKWebView* webView() const { return _webView.get(); }
+ _WKMockMediaSessionCoordinator* coordinator() const { return _coordinator.get(); }
+
+ void loadPageAndBecomeReady(const String& pageName)
+ {
+ [_webView synchronouslyLoadTestPageNamed:pageName];
+
+ bool canplaythrough = false;
+ [webView() performAfterReceivingMessage:@"canplaythrough event" action:[&] {
+ canplaythrough = true;
+ }];
+ runScriptWithUserGesture("load()");
+ Util::run(&canplaythrough);
+ }
+
+ void runScriptWithUserGesture(const String& script)
+ {
+ [_webView objectByEvaluatingJavaScriptWithUserGesture:script];
+ }
+
+ void play()
+ {
+ bool playing = false;
+ [_webView performAfterReceivingMessage:@"play event" action:[&] { playing = true; }];
+ runScriptWithUserGesture("audio.play()");
+ Util::run(&playing);
+ }
+
+ void pause()
+ {
+ bool paused = false;
+ [_webView performAfterReceivingMessage:@"pause event" action:[&] { paused = true; }];
+ runScriptWithUserGesture("audio.pause()");
+ Util::run(&paused);
+ }
+
+ void listenForEventMessages(std::initializer_list<const char*> events)
+ {
+ for (auto* event : events) {
+ auto eventMessage = makeString(event, " event");
+ [webView() performAfterReceivingMessage:eventMessage action:[this, eventMessage = WTFMove(eventMessage)] {
+ _eventListenersCalled.add(eventMessage);
+ }];
+ }
+ }
+
+ bool eventListenerWasCalled(const String& event)
+ {
+ return _eventListenersCalled.contains(makeString(event, " event"));
+ }
+
+ void clearEventListenerState()
+ {
+ _eventListenersCalled.clear();
+ }
+
+ void executeUntil(Function<bool()>&& callback, int retries = 50)
+ {
+ int tries = 0;
+ do {
+ if (callback())
+ return;
+ Util::sleep(0.1);
+ } while (++tries <= retries);
+
+ return;
+ }
+
+ void waitForEventListenerToBeCalled(const String& event)
+ {
+ executeUntil([&] {
+ return eventListenerWasCalled(event);
+ });
+ }
+
+ void listenForMessagesPosted(std::initializer_list<const char*> handlers, const char* suffix)
+ {
+ for (auto* handler : handlers) {
+ auto handlerMessage = makeString(handler, suffix);
+ [_messageHandlers addObject:handlerMessage];
+ [webView() performAfterReceivingMessage:handlerMessage action:[this, handlerMessage = WTFMove(handlerMessage)] {
+ _sessionMessagesPosted.add(handlerMessage);
+ }];
+ }
+ }
+
+ void clearMessagesPosted()
+ {
+ _sessionMessagesPosted.clear();
+ }
+
+ void listenForSessionHandlerMessages(std::initializer_list<const char*> handlers)
+ {
+ listenForMessagesPosted(handlers, " handler");
+ }
+
+ bool sessionHandlerWasCalled(const String& handler)
+ {
+ return _sessionMessagesPosted.contains(makeString(handler, " handler"));
+ }
+
+ void waitForSessionHandlerToBeCalled(const String& handler)
+ {
+ executeUntil([&] {
+ return sessionHandlerWasCalled(handler);
+ });
+ }
+
+ void listenForPromiseMessages(std::initializer_list<const char*> handlers)
+ {
+ listenForMessagesPosted(handlers, " resolved");
+ listenForMessagesPosted(handlers, " rejected");
+ }
+
+ void clearPromiseMessages(const String& promise)
+ {
+ _sessionMessagesPosted.remove(makeString(promise, " resolved"));
+ _sessionMessagesPosted.remove(makeString(promise, " rejected"));
+ }
+
+ bool promiseWasResolved(const String& promise)
+ {
+ return _sessionMessagesPosted.contains(makeString(promise, " resolved"));
+ }
+
+ bool promiseWasRejected(const String& promise)
+ {
+ return _sessionMessagesPosted.contains(makeString(promise, " rejected"));
+ }
+
+ void waitForPromise(const String& promise)
+ {
+ executeUntil([&] {
+ return promiseWasResolved(promise) || promiseWasRejected(promise);
+ }, 200);
+ }
+
+private:
+ RetainPtr<_WKMockMediaSessionCoordinator> _coordinator;
+ RetainPtr<WKWebViewConfiguration> _configuration;
+ RetainPtr<TestWKWebView> _webView;
+ HashSet<String> _sessionMessagesPosted;
+ HashSet<String> _eventListenersCalled;
+ RetainPtr<NSMutableArray> _messageHandlers;
+};
+
+TEST_F(MediaSessionCoordinatorTest, JoinAndLeave)
+{
+ loadPageAndBecomeReady("media-remote"_s);
+ listenForPromiseMessages({ "join"_s });
+
+ createCoordinator();
+
+ RetainPtr<NSString> state = [webView() stringByEvaluatingJavaScript:@"navigator.mediaSession.coordinator.state"];
+ EXPECT_STREQ("waiting", [state UTF8String]);
+
+ // 'join()' should fail if the remote coordinator refuses.
+ coordinator().failsCommands = YES;
+ [webView() objectByEvaluatingJavaScript:@"joinSession()"];
+ waitForPromise("join"_s);
+ ASSERT_TRUE(promiseWasRejected("join"_s));
+ clearPromiseMessages("join"_s);
+ EXPECT_STREQ("join", coordinator().lastMethodCalled.UTF8String);
+
+ // And it shoud succeed if it allows it.
+ coordinator().failsCommands = NO;
+ [webView() objectByEvaluatingJavaScript:@"joinSession()"];
+ waitForPromise("join"_s);
+ ASSERT_TRUE(promiseWasResolved("join"_s));
+ clearPromiseMessages("join"_s);
+ EXPECT_STREQ("join", coordinator().lastMethodCalled.UTF8String);
+
+ state = [webView() stringByEvaluatingJavaScript:@"navigator.mediaSession.coordinator.state"];
+ EXPECT_STREQ("joined", [state UTF8String]);
+
+ [webView() objectByEvaluatingJavaScript:@"navigator.mediaSession.coordinator.leave()"];
+ String lastMethodCalled;
+ executeUntil([&] {
+ lastMethodCalled = coordinator().lastMethodCalled;
+ return lastMethodCalled == "leave";
+ });
+ EXPECT_STREQ("leave", lastMethodCalled.utf8().data());
+
+ state = [webView() stringByEvaluatingJavaScript:@"navigator.mediaSession.coordinator.state"];
+ EXPECT_STREQ("closed", [state UTF8String]);
+
+ // It shouldn't be possible to re-join a close coordinator.
+ [webView() objectByEvaluatingJavaScript:@"joinSession()"];
+ waitForPromise("join"_s);
+ ASSERT_TRUE(promiseWasRejected("join"_s));
+ EXPECT_STREQ("", coordinator().lastMethodCalled.UTF8String);
+}
+
+TEST_F(MediaSessionCoordinatorTest, StateChanges)
+{
+ loadPageAndBecomeReady("media-remote"_s);
+
+ listenForPromiseMessages({ "join"_s });
+ createCoordinator();
+ [webView() objectByEvaluatingJavaScript:@"joinSession()"];
+ waitForPromise("join"_s);
+ ASSERT_TRUE(promiseWasResolved("join"_s));
+ clearPromiseMessages("join"_s);
+ EXPECT_STREQ("join", coordinator().lastMethodCalled.UTF8String);
+
+ [webView() objectByEvaluatingJavaScript:@"navigator.mediaSession.setPositionState({ duration: 1, playbackRate: 1, position: 0 })"];
+ String lastStateChange;
+ executeUntil([&] {
+ lastStateChange = coordinator().lastStateChange;
+ return lastStateChange == "positionStateChanged";
+ });
+ EXPECT_STREQ("positionStateChanged", lastStateChange.utf8().data());
+
+ for (NSString *state in @[ @"haveMetadata", @"haveCurrentData", @"haveFutureData", @"haveEnoughData", @"haveNothing" ]) {
+ [webView() objectByEvaluatingJavaScript:[NSString stringWithFormat:@"navigator.mediaSession.readyState = '%@'", state]];
+ executeUntil([&] {
+ lastStateChange = coordinator().lastStateChange;
+ return lastStateChange == "readyStateChanged";
+ });
+ EXPECT_STREQ("readyStateChanged", lastStateChange.utf8().data());
+
+ RetainPtr<NSString> currentState = [webView() stringByEvaluatingJavaScript:@"navigator.mediaSession.readyState"];
+ EXPECT_STREQ(state.UTF8String, currentState.get().UTF8String);
+ }
+
+ for (NSString *state in @[ @"paused", @"playing", @"none" ]) {
+ [webView() objectByEvaluatingJavaScript:[NSString stringWithFormat:@"navigator.mediaSession.playbackState = '%@'", state]];
+ executeUntil([&] {
+ lastStateChange = coordinator().lastStateChange;
+ return lastStateChange == "playbackStateChanged";
+ });
+ EXPECT_STREQ("playbackStateChanged", lastStateChange.utf8().data());
+
+ RetainPtr<NSString> currentState = [webView() stringByEvaluatingJavaScript:@"navigator.mediaSession.playbackState"];
+ EXPECT_STREQ(state.UTF8String, currentState.get().UTF8String);
+ }
+
+ [webView() objectByEvaluatingJavaScript:@"navigator.mediaSession.coordinator.leave()"];
+ String lastMethodCalled;
+ executeUntil([&] {
+ lastStateChange = coordinator().lastStateChange;
+ return lastStateChange == "coordinatorStateChanged";
+ });
+ EXPECT_STREQ("coordinatorStateChanged", lastStateChange.utf8().data());
+}
+
+TEST_F(MediaSessionCoordinatorTest, CoordinatorMethodCallbacks)
+{
+ loadPageAndBecomeReady("media-remote"_s);
+
+ listenForPromiseMessages({ "join"_s });
+ createCoordinator();
+ [webView() objectByEvaluatingJavaScript:@"joinSession()"];
+ waitForPromise("join"_s);
+ ASSERT_TRUE(promiseWasResolved("join"_s));
+ clearPromiseMessages("join"_s);
+ EXPECT_STREQ("join", coordinator().lastMethodCalled.UTF8String);
+
+ listenForPromiseMessages({ "play"_s, "pause"_s, "seekTo"_s, "setTrack"_s });
+ auto methodsAndArgs = @[
+ @[ @"play", @"" ],
+ @[ @"pause", @"" ],
+ @[ @"seekTo", @"10" ],
+ @[ @"setTrack", @"'\\'test-track-1\\''" ],
+ ];
+ for (NSArray *methodInfo in methodsAndArgs) {
+ NSString *method = methodInfo[0];
+ NSString *args = methodInfo[1];
+ auto str = [NSString stringWithFormat:@"callMethod('%@', %@)", method, args];
+ [webView() objectByEvaluatingJavaScript:str];
+ waitForPromise(method);
+ ASSERT_TRUE(promiseWasResolved(method));
+ clearPromiseMessages(method);
+ EXPECT_STREQ(method.UTF8String, coordinator().lastMethodCalled.UTF8String);
+ }
+}
+
+TEST_F(MediaSessionCoordinatorTest, CallSessionMethods)
+{
+ loadPageAndBecomeReady("media-remote"_s);
+ listenForSessionHandlerMessages({ "play"_s, "pause"_s, "seekto"_s, "nexttrack"_s });
+
+ listenForPromiseMessages({ "join"_s });
+ createCoordinator();
+ [webView() objectByEvaluatingJavaScript:@"joinSession()"];
+ waitForPromise("join"_s);
+ ASSERT_TRUE(promiseWasResolved("join"_s));
+ clearPromiseMessages("join"_s);
+ EXPECT_STREQ("join", coordinator().lastMethodCalled.UTF8String);
+
+ String lastMethodCalled;
+
+ [coordinator() seekSessionToTime:20];
+ executeUntil([&] {
+ lastMethodCalled = coordinator().lastMethodCalled;
+ return lastMethodCalled == "seekSessionToTime";
+ });
+ EXPECT_STREQ("seekSessionToTime", lastMethodCalled.utf8().data());
+
+ [coordinator() playSession];
+ executeUntil([&] {
+ lastMethodCalled = coordinator().lastMethodCalled;
+ return lastMethodCalled == "playSession";
+ });
+ EXPECT_STREQ("playSession", lastMethodCalled.utf8().data());
+
+ [coordinator() pauseSession];
+ executeUntil([&] {
+ lastMethodCalled = coordinator().lastMethodCalled;
+ return lastMethodCalled == "pauseSession";
+ });
+ EXPECT_STREQ("pauseSession", lastMethodCalled.utf8().data());
+
+ [coordinator() setSessionTrack:@"Track 0"];
+ executeUntil([&] {
+ lastMethodCalled = coordinator().lastMethodCalled;
+ return lastMethodCalled == "setSessionTrack";
+ });
+ EXPECT_STREQ("setSessionTrack", lastMethodCalled.utf8().data());
+}
+
+} // namespace TestWebKitAPI
+
+#endif // ENABLE(MEDIA_SESSION_COORDINATOR)
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/media-remote.html (275536 => 275537)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/media-remote.html 2021-04-06 18:15:34 UTC (rev 275536)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/media-remote.html 2021-04-06 19:06:53 UTC (rev 275537)
@@ -40,11 +40,23 @@
navigator.mediaSession.metadata = new MediaMetadata(data);
postMessage('set metadata')
}
+
+ function joinSession()
+ {
+ let promise = navigator.mediaSession.coordinator.join();
+ postPromise("join", promise);
+ }
+ function callMethod(method, args)
+ {
+ let code = `navigator.mediaSession.coordinator.${method}(${args})`;
+ let promise = eval(code);
+ postPromise(method, promise);
+ }
+
function setPlaylistMetadata(index)
{
setMetadata(playlist.metadata[index]);
-
}
function clearActionHandlers()
@@ -56,17 +68,11 @@
{
const actions = {
'play' : () => { postMessage('play handler'); },
-
'pause' : () => { postMessage('pause handler') },
-
'seekto' : (details) => { postMessage('seekto handler') },
-
'seekforward' : (details) => { postMessage('seekforward handler') },
-
- 'seekbackward' : (details) => { postMessage('seekbackward handler') },
-
- 'previoustrack' : () => { postMessage('previoustrack handler') },
-
+ 'seekbackward' : (details) => { postMessage('seekbackward handler') },
+ 'previoustrack' : () => { postMessage('previoustrack handler') },
'nexttrack' : () => { postMessage('nexttrack handler') },
};
@@ -95,6 +101,15 @@
postMessage(`${evt.type} event`);
}
+ async function postPromise(type, promise)
+ {
+ log(`waiting for ${type} promise`);
+ await promise
+ .then( () => { postMessage(`${type} resolved`); } )
+ .catch( () => { postMessage(`${type} rejected`); } );
+ log(`${type} promise settled`);
+ }
+
function load()
{
let src = ""
@@ -112,7 +127,8 @@
eventLog.insertBefore(note, eventLog.firstChild);
}
-
+ const session = navigator.mediaSession;
+
window.addEventListener("load", evt => {
audio = document.getElementsByTagName('audio')[0];
audio.addEventListener('canplaythrough', postEvent);
@@ -119,6 +135,7 @@
audio.addEventListener('play', postEvent);
audio.addEventListener('pause', postEvent);
audio.addEventListener('seeked', postEvent);
+ navigator.mediaSession.addEventListener('coordinatorchange', postEvent);
}, false);
</script>