Source/WebCore:
authormrajca@apple.com <mrajca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Sep 2018 17:20:26 +0000 (17:20 +0000)
committermrajca@apple.com <mrajca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Sep 2018 17:20:26 +0000 (17:20 +0000)
Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)
https://bugs.webkit.org/show_bug.cgi?id=189433
<rdar://problem/44186498> Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)

Reviewed by Eric Carlson.

When playing an audio element, the media Touch Bar displays an active PIP button even though only
videos are PIP-able. Pressing it does not do anything. The issue is canTogglePictureInPicture is set
to YES unconditionally on the WebPlaybackControlsManager. It is then only updated based on whether or
not external playback is enabled.

This patch extends that logic such that the picture-in-picture Touch Bar button will be disabled for
audio elements. Since PlaybackSessionModelMediaElement today does not know whether we're dealing
with an audio or video element, a new isPictureInPictureSupported flag has been added (as well as
the plumbing necessary to get the state over from the web process).

An API test has been added that checks the value of the canTogglePictureInPicture and ensures it
is NO when audio elements are playing. To expose it to tests, a _canTogglePictureInPictureForTesting
property has been added to the WKTesting category.

* platform/cocoa/PlaybackSessionModel.h:
(WebCore::PlaybackSessionModelClient::isPictureInPictureSupportedChanged):
* platform/cocoa/PlaybackSessionModelMediaElement.h:
* platform/cocoa/PlaybackSessionModelMediaElement.mm:
(WebCore::PlaybackSessionModelMediaElement::setMediaElement):
(WebCore::PlaybackSessionModelMediaElement::isPictureInPictureSupported const):
* platform/mac/PlaybackSessionInterfaceMac.h:
* platform/mac/PlaybackSessionInterfaceMac.mm:
(WebCore::PlaybackSessionInterfaceMac::isPictureInPictureSupportedChanged):
(WebCore::PlaybackSessionInterfaceMac::externalPlaybackChanged):
(WebCore::PlaybackSessionInterfaceMac::updatePlaybackControlsManagerCanTogglePictureInPicture):

Source/WebKit:
Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)
https://bugs.webkit.org/show_bug.cgi?id=189433
<rdar://problem/44186498> Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)

Reviewed by Eric Carlson.

When playing an audio element, the media Touch Bar displays an active PIP button even though only
videos are PIP-able. Pressing it does not do anything. The issue is canTogglePictureInPicture is set
to YES unconditionally on the WebPlaybackControlsManager. It is then only updated based on whether or
not external playback is enabled.

This patch extends that logic such that the picture-in-picture Touch Bar button will be disabled for
audio elements. Since PlaybackSessionModelMediaElement today does not know whether we're dealing
with an audio or video element, a new isPictureInPictureSupported flag has been added (as well as
the plumbing necessary to get the state over from the web process).

An API test has been added that checks the value of the canTogglePictureInPicture and ensures it
is NO when audio elements are playing. To expose it to tests, a _canTogglePictureInPictureForTesting
property has been added to the WKTesting category.

Source/WebKit:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _canTogglePictureInPictureForTesting]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/Cocoa/PlaybackSessionManagerProxy.h:
* UIProcess/Cocoa/PlaybackSessionManagerProxy.messages.in:
* UIProcess/Cocoa/PlaybackSessionManagerProxy.mm:
(WebKit::PlaybackSessionModelContext::pictureInPictureSupportedChanged):
(WebKit::PlaybackSessionManagerProxy::pictureInPictureSupportedChanged):
* UIProcess/Cocoa/WebViewImpl.h:
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::updateMediaTouchBar):
(WebKit::WebViewImpl::canTogglePictureInPictureForTesting):
* UIProcess/ios/fullscreen/WKFullScreenViewController.mm:
* WebProcess/cocoa/PlaybackSessionManager.h:
* WebProcess/cocoa/PlaybackSessionManager.mm:
(WebKit::PlaybackSessionInterfaceContext::isPictureInPictureSupportedChanged):
(WebKit::PlaybackSessionManager::isPictureInPictureSupportedChanged):

Tools:
https://bugs.webkit.org/show_bug.cgi?id=189433
<rdar://problem/44186498> Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)

Reviewed by Eric Carlson.

An API test has been added that checks the value of the canTogglePictureInPicture and ensures it
is NO when audio elements are playing.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/PictureInPictureDelegate.html:
* TestWebKitAPI/Tests/WebKitCocoa/PictureInPictureDelegate.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebKitCocoa/audio-with-controls.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235850 268f45cc-cd09-0410-ab3c-d52691b4dbfc

23 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/cocoa/PlaybackSessionModel.h
Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.h
Source/WebCore/platform/cocoa/PlaybackSessionModelMediaElement.mm
Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm
Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.h
Source/WebCore/platform/mac/PlaybackSessionInterfaceMac.mm
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.h
Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.messages.in
Source/WebKit/UIProcess/Cocoa/PlaybackSessionManagerProxy.mm
Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenViewController.mm
Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.h
Source/WebKit/WebProcess/cocoa/PlaybackSessionManager.mm
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/PictureInPictureDelegate.html
Tools/TestWebKitAPI/Tests/WebKitCocoa/PictureInPictureDelegate.mm
Tools/TestWebKitAPI/Tests/WebKitCocoa/audio-with-controls.html [new file with mode: 0644]

index dd210ef..5fff931 100644 (file)
@@ -1,3 +1,37 @@
+2018-09-07  Matt Rajca  <mrajca@apple.com>
+
+        Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)
+        https://bugs.webkit.org/show_bug.cgi?id=189433
+        <rdar://problem/44186498> Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)
+
+        Reviewed by Eric Carlson.
+
+        When playing an audio element, the media Touch Bar displays an active PIP button even though only
+        videos are PIP-able. Pressing it does not do anything. The issue is canTogglePictureInPicture is set
+        to YES unconditionally on the WebPlaybackControlsManager. It is then only updated based on whether or
+        not external playback is enabled.
+
+        This patch extends that logic such that the picture-in-picture Touch Bar button will be disabled for
+        audio elements. Since PlaybackSessionModelMediaElement today does not know whether we're dealing
+        with an audio or video element, a new isPictureInPictureSupported flag has been added (as well as
+        the plumbing necessary to get the state over from the web process).
+
+        An API test has been added that checks the value of the canTogglePictureInPicture and ensures it
+        is NO when audio elements are playing. To expose it to tests, a _canTogglePictureInPictureForTesting
+        property has been added to the WKTesting category.
+
+        * platform/cocoa/PlaybackSessionModel.h:
+        (WebCore::PlaybackSessionModelClient::isPictureInPictureSupportedChanged):
+        * platform/cocoa/PlaybackSessionModelMediaElement.h:
+        * platform/cocoa/PlaybackSessionModelMediaElement.mm:
+        (WebCore::PlaybackSessionModelMediaElement::setMediaElement):
+        (WebCore::PlaybackSessionModelMediaElement::isPictureInPictureSupported const):
+        * platform/mac/PlaybackSessionInterfaceMac.h:
+        * platform/mac/PlaybackSessionInterfaceMac.mm:
+        (WebCore::PlaybackSessionInterfaceMac::isPictureInPictureSupportedChanged):
+        (WebCore::PlaybackSessionInterfaceMac::externalPlaybackChanged):
+        (WebCore::PlaybackSessionInterfaceMac::updatePlaybackControlsManagerCanTogglePictureInPicture):
+
 2018-09-10  Alicia Boya GarcĂ­a  <aboya@igalia.com>
 
         [GStreamer] Fix overflow in buffered ranges
index eff018e..c43f732 100644 (file)
@@ -84,6 +84,7 @@ public:
     virtual bool wirelessVideoPlaybackDisabled() const = 0;
     virtual bool isMuted() const = 0;
     virtual double volume() const = 0;
+    virtual bool isPictureInPictureSupported() const = 0;
     virtual bool isPictureInPictureActive() const = 0;
 };
 
@@ -105,6 +106,7 @@ public:
     virtual void wirelessVideoPlaybackDisabledChanged(bool) { }
     virtual void mutedChanged(bool) { }
     virtual void volumeChanged(double) { }
+    virtual void isPictureInPictureSupportedChanged(bool) { }
     virtual void pictureInPictureActiveChanged(bool) { }
     virtual void ensureControlsManager() { }
 };
index f7420b3..9eefd10 100644 (file)
@@ -95,6 +95,7 @@ public:
     bool wirelessVideoPlaybackDisabled() const final;
     bool isMuted() const final;
     double volume() const final;
+    bool isPictureInPictureSupported() const final;
     bool isPictureInPictureActive() const final;
 
 protected:
index a190d68..c017921 100644 (file)
@@ -101,6 +101,9 @@ void PlaybackSessionModelMediaElement::setMediaElement(HTMLMediaElement* mediaEl
     }
 
     updateForEventName(eventNameAll());
+
+    for (auto client : m_clients)
+        client->isPictureInPictureSupportedChanged(isPictureInPictureSupported());
 }
 
 void PlaybackSessionModelMediaElement::handleEvent(WebCore::ScriptExecutionContext&, WebCore::Event& event)
@@ -573,6 +576,11 @@ double PlaybackSessionModelMediaElement::volume() const
     return m_mediaElement ? m_mediaElement->volume() : 0;
 }
 
+bool PlaybackSessionModelMediaElement::isPictureInPictureSupported() const
+{
+    return m_mediaElement ? m_mediaElement->isVideo() : false;
+}
+
 bool PlaybackSessionModelMediaElement::isPictureInPictureActive() const
 {
     if (!m_mediaElement)
index 32a1e72..d43b87c 100644 (file)
@@ -202,6 +202,7 @@ private:
     FloatSize videoDimensions() const override;
     bool isMuted() const override;
     double volume() const override;
+    bool isPictureInPictureSupported() const override;
     bool isPictureInPictureActive() const override;
     void willEnterPictureInPicture() final;
     void didEnterPictureInPicture() final;
@@ -634,6 +635,12 @@ bool VideoFullscreenControllerContext::isPictureInPictureActive() const
     return m_playbackModel ? m_playbackModel->isPictureInPictureActive() : false;
 }
 
+bool VideoFullscreenControllerContext::isPictureInPictureSupported() const
+{
+    ASSERT(isUIThread());
+    return m_playbackModel ? m_playbackModel->isPictureInPictureSupported() : false;
+}
+
 void VideoFullscreenControllerContext::willEnterPictureInPicture()
 {
     ASSERT(isUIThread());
index 9aa955f..e7db397 100644 (file)
@@ -62,12 +62,15 @@ public:
     void audioMediaSelectionIndexChanged(uint64_t) final;
     void legibleMediaSelectionIndexChanged(uint64_t) final;
     void externalPlaybackChanged(bool /* enabled */, PlaybackSessionModel::ExternalPlaybackTargetType, const String& /* localizedDeviceName */) final;
+    void isPictureInPictureSupportedChanged(bool) final;
 
     void invalidate();
     void ensureControlsManager();
 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
     void setPlayBackControlsManager(WebPlaybackControlsManager *);
     WebPlaybackControlsManager *playBackControlsManager();
+
+    void updatePlaybackControlsManagerCanTogglePictureInPicture();
 #endif
     void beginScrubbing();
     void endScrubbing();
index 602eddb..b86266d 100644 (file)
@@ -184,12 +184,17 @@ void PlaybackSessionInterfaceMac::legibleMediaSelectionIndexChanged(uint64_t sel
 #endif
 }
 
-void PlaybackSessionInterfaceMac::externalPlaybackChanged(bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType, const String&)
+void PlaybackSessionInterfaceMac::isPictureInPictureSupportedChanged(bool)
 {
 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
-    [playBackControlsManager() setCanTogglePictureInPicture:!enabled];
-#else
-    UNUSED_PARAM(enabled);
+    updatePlaybackControlsManagerCanTogglePictureInPicture();
+#endif
+}
+
+void PlaybackSessionInterfaceMac::externalPlaybackChanged(bool, PlaybackSessionModel::ExternalPlaybackTargetType, const String&)
+{
+#if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
+    updatePlaybackControlsManagerCanTogglePictureInPicture();
 #endif
 }
 
@@ -237,6 +242,17 @@ void PlaybackSessionInterfaceMac::setPlayBackControlsManager(WebPlaybackControls
     [manager setLegibleMediaSelectionOptions:m_playbackSessionModel->legibleMediaSelectionOptions() withSelectedIndex:static_cast<NSUInteger>(m_playbackSessionModel->legibleMediaSelectedIndex())];
 }
 
+void PlaybackSessionInterfaceMac::updatePlaybackControlsManagerCanTogglePictureInPicture()
+{
+    PlaybackSessionModel* model = playbackSessionModel();
+    if (!model) {
+        [playBackControlsManager() setCanTogglePictureInPicture:NO];
+        return;
+    }
+
+    [playBackControlsManager() setCanTogglePictureInPicture:model->isPictureInPictureSupported() && !model->externalPlaybackEnabled()];
+}
+
 void PlaybackSessionInterfaceMac::updatePlaybackControlsManagerTiming(double currentTime, double anchorTime, double playbackRate, bool isPlaying)
 {
     WebPlaybackControlsManager *manager = playBackControlsManager();
index 5e1d804..5ba509d 100644 (file)
@@ -1,3 +1,44 @@
+2018-09-07  Matt Rajca  <mrajca@apple.com>
+
+        Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)
+        https://bugs.webkit.org/show_bug.cgi?id=189433
+        <rdar://problem/44186498> Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)
+
+        Reviewed by Eric Carlson.
+
+        When playing an audio element, the media Touch Bar displays an active PIP button even though only
+        videos are PIP-able. Pressing it does not do anything. The issue is canTogglePictureInPicture is set
+        to YES unconditionally on the WebPlaybackControlsManager. It is then only updated based on whether or
+        not external playback is enabled.
+
+        This patch extends that logic such that the picture-in-picture Touch Bar button will be disabled for
+        audio elements. Since PlaybackSessionModelMediaElement today does not know whether we're dealing
+        with an audio or video element, a new isPictureInPictureSupported flag has been added (as well as
+        the plumbing necessary to get the state over from the web process).
+
+        An API test has been added that checks the value of the canTogglePictureInPicture and ensures it
+        is NO when audio elements are playing. To expose it to tests, a _canTogglePictureInPictureForTesting
+        property has been added to the WKTesting category.
+
+        Source/WebKit:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _canTogglePictureInPictureForTesting]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/Cocoa/PlaybackSessionManagerProxy.h:
+        * UIProcess/Cocoa/PlaybackSessionManagerProxy.messages.in:
+        * UIProcess/Cocoa/PlaybackSessionManagerProxy.mm:
+        (WebKit::PlaybackSessionModelContext::pictureInPictureSupportedChanged):
+        (WebKit::PlaybackSessionManagerProxy::pictureInPictureSupportedChanged):
+        * UIProcess/Cocoa/WebViewImpl.h:
+        * UIProcess/Cocoa/WebViewImpl.mm:
+        (WebKit::WebViewImpl::updateMediaTouchBar):
+        (WebKit::WebViewImpl::canTogglePictureInPictureForTesting):
+        * UIProcess/ios/fullscreen/WKFullScreenViewController.mm:
+        * WebProcess/cocoa/PlaybackSessionManager.h:
+        * WebProcess/cocoa/PlaybackSessionManager.mm:
+        (WebKit::PlaybackSessionInterfaceContext::isPictureInPictureSupportedChanged):
+        (WebKit::PlaybackSessionManager::isPictureInPictureSupportedChanged):
+
 2018-09-10  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         [MSVC] X86Assembler.h(108): error C2666: 'WebCore::operator -': 7 overloads have similar conversions
index 66c28eb..e0c29c5 100644 (file)
@@ -6495,6 +6495,15 @@ static WebCore::UserInterfaceLayoutDirection toUserInterfaceLayoutDirection(UISe
     _page->setDefersLoadingForTesting(defersLoading);
 }
 
+- (BOOL)_canTogglePictureInPictureForTesting
+{
+#if HAVE(TOUCH_BAR)
+    return _impl->canTogglePictureInPictureForTesting();
+#else
+    return NO;
+#endif
+}
+
 - (_WKInspector *)_inspector
 {
     if (auto* inspector = _page->inspector())
index 6d1cb1d..f5e9997 100644 (file)
@@ -472,6 +472,8 @@ typedef NS_OPTIONS(NSUInteger, _WKRectEdge) {
 - (BOOL)_completeBackSwipeForTesting;
 - (void)_setDefersLoadingForTesting:(BOOL)defersLoading;
 
+- (BOOL)_canTogglePictureInPictureForTesting;
+
 @property (nonatomic, readonly) _WKInspector *_inspector WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 @property (nonatomic, readonly) _WKFrameHandle *_mainFrame WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
index 68a88b5..a2773e6 100644 (file)
@@ -85,6 +85,7 @@ public:
     void wirelessVideoPlaybackDisabledChanged(bool);
     void mutedChanged(bool);
     void volumeChanged(double);
+    void pictureInPictureSupportedChanged(bool);
     void pictureInPictureActiveChanged(bool);
 
 private:
@@ -136,6 +137,7 @@ private:
     bool wirelessVideoPlaybackDisabled() const final { return m_wirelessVideoPlaybackDisabled; }
     bool isMuted() const final { return m_muted; }
     double volume() const final { return m_volume; }
+    bool isPictureInPictureSupported() const final { return m_pictureInPictureSupported; }
     bool isPictureInPictureActive() const final { return m_pictureInPictureActive; }
 
     PlaybackSessionManagerProxy* m_manager;
@@ -163,6 +165,7 @@ private:
     bool m_wirelessVideoPlaybackDisabled { false };
     bool m_muted { false };
     double m_volume { 0 };
+    bool m_pictureInPictureSupported { false };
     bool m_pictureInPictureActive { false };
 };
 
@@ -213,6 +216,7 @@ private:
     void handleControlledElementIDResponse(uint64_t, String) const;
     void mutedChanged(uint64_t contextId, bool muted);
     void volumeChanged(uint64_t contextId, double volume);
+    void pictureInPictureSupportedChanged(uint64_t contextId, bool pictureInPictureSupported);
     void pictureInPictureActiveChanged(uint64_t contextId, bool pictureInPictureActive);
 
     // Messages to PlaybackSessionManager
index b151c9c..b31b582 100644 (file)
@@ -38,6 +38,7 @@ messages -> PlaybackSessionManagerProxy {
     RateChanged(uint64_t contextId, bool isPlaying, double rate)
     MutedChanged(uint64_t contextId, bool muted);
     VolumeChanged(uint64_t contextId, double volume);
+    PictureInPictureSupportedChanged(uint64_t contextID, bool pictureInPictureSupported)
     PictureInPictureActiveChanged(uint64_t contextId, bool pictureInPictureActive)
     SetUpPlaybackControlsManagerWithID(uint64_t contextId)
     ClearPlaybackControlsManager()
index 6304be7..dc36171 100644 (file)
@@ -276,6 +276,13 @@ void PlaybackSessionModelContext::volumeChanged(double volume)
         client->volumeChanged(volume);
 }
 
+void PlaybackSessionModelContext::pictureInPictureSupportedChanged(bool supported)
+{
+    m_pictureInPictureSupported = supported;
+    for (auto* client : m_clients)
+        client->isPictureInPictureSupportedChanged(supported);
+}
+
 void PlaybackSessionModelContext::pictureInPictureActiveChanged(bool active)
 {
     m_pictureInPictureActive = active;
@@ -478,6 +485,11 @@ void PlaybackSessionManagerProxy::rateChanged(uint64_t contextId, bool isPlaying
     ensureModel(contextId).rateChanged(isPlaying, rate);
 }
 
+void PlaybackSessionManagerProxy::pictureInPictureSupportedChanged(uint64_t contextId, bool supported)
+{
+    ensureModel(contextId).pictureInPictureSupportedChanged(supported);
+}
+
 void PlaybackSessionManagerProxy::pictureInPictureActiveChanged(uint64_t contextId, bool active)
 {
     ensureModel(contextId).pictureInPictureActiveChanged(active);
index 796c928..d964d50 100644 (file)
@@ -559,6 +559,8 @@ public:
 
     void updateTouchBarAndRefreshTextBarIdentifiers();
     void setIsCustomizingTouchBar(bool isCustomizingTouchBar) { m_isCustomizingTouchBar = isCustomizingTouchBar; };
+
+    bool canTogglePictureInPictureForTesting();
 #endif // HAVE(TOUCH_BAR)
 
     bool beginBackSwipeForTesting();
index 552d650..1af4add 100644 (file)
@@ -1235,11 +1235,13 @@ void WebViewImpl::updateMediaTouchBar()
     if (!m_playbackControlsManager) {
         m_playbackControlsManager = adoptNS([[WebPlaybackControlsManager alloc] init]);
         [m_playbackControlsManager setAllowsPictureInPicturePlayback:m_page->preferences().allowsPictureInPictureMediaPlayback()];
-        [m_playbackControlsManager setCanTogglePictureInPicture:YES];
+        [m_playbackControlsManager setCanTogglePictureInPicture:NO];
     }
 
-    if (PlatformPlaybackSessionInterface* interface = m_page->playbackSessionManager()->controlsManagerInterface())
+    if (PlatformPlaybackSessionInterface* interface = m_page->playbackSessionManager()->controlsManagerInterface()) {
         [m_playbackControlsManager setPlaybackSessionInterfaceMac:interface];
+        interface->updatePlaybackControlsManagerCanTogglePictureInPicture();
+    }
 
     [m_mediaTouchBarProvider setPlaybackControlsController:m_playbackControlsManager.get()];
     [m_mediaPlaybackControlsView setPlaybackControlsController:m_playbackControlsManager.get()];
@@ -1275,6 +1277,19 @@ void WebViewImpl::updateMediaTouchBar()
 #endif
 }
 
+#if HAVE(TOUCH_BAR)
+
+bool WebViewImpl::canTogglePictureInPictureForTesting()
+{
+#if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
+    return [m_playbackControlsManager canTogglePictureInPicture];
+#else
+    return NO;
+#endif
+}
+
+#endif // HAVE(TOUCH_BAR)
+
 void WebViewImpl::forceRequestCandidatesForTesting()
 {
     m_canCreateTouchBars = true;
index d88d63d..0fc3885 100644 (file)
@@ -65,6 +65,10 @@ public:
         m_parent.playing = isPlaying;
     }
 
+    void pictureInPictureSupportedChanged(bool) override
+    {
+    }
+
     void pictureInPictureActiveChanged(bool active) override
     {
         m_parent.pictureInPictureActive = active;
index 1a85762..f0de62b 100644 (file)
@@ -89,6 +89,7 @@ private:
     void wirelessVideoPlaybackDisabledChanged(bool) final;
     void mutedChanged(bool) final;
     void volumeChanged(double) final;
+    void isPictureInPictureSupportedChanged(bool) final;
 
     PlaybackSessionInterfaceContext(PlaybackSessionManager&, uint64_t contextId);
 
@@ -143,6 +144,7 @@ protected:
     void wirelessVideoPlaybackDisabledChanged(uint64_t contextId, bool);
     void mutedChanged(uint64_t contextId, bool);
     void volumeChanged(uint64_t contextId, double);
+    void isPictureInPictureSupportedChanged(uint64_t contextId, bool);
 
     // Messages from PlaybackSessionManagerProxy
     void play(uint64_t contextId);
index 088494b..d0aec25 100644 (file)
@@ -154,6 +154,12 @@ void PlaybackSessionInterfaceContext::mutedChanged(bool muted)
         m_manager->mutedChanged(m_contextId, muted);
 }
 
+void PlaybackSessionInterfaceContext::isPictureInPictureSupportedChanged(bool supported)
+{
+    if (m_manager)
+        m_manager->isPictureInPictureSupportedChanged(m_contextId, supported);
+}
+
 void PlaybackSessionInterfaceContext::volumeChanged(double volume)
 {
     if (m_manager)
@@ -402,6 +408,11 @@ void PlaybackSessionManager::volumeChanged(uint64_t contextId, double volume)
     m_page->send(Messages::PlaybackSessionManagerProxy::VolumeChanged(contextId, volume));
 }
 
+void PlaybackSessionManager::isPictureInPictureSupportedChanged(uint64_t contextId, bool supported)
+{
+    m_page->send(Messages::PlaybackSessionManagerProxy::PictureInPictureSupportedChanged(contextId, supported));
+}
+
 #pragma mark Messages from PlaybackSessionManagerProxy:
 
 void PlaybackSessionManager::play(uint64_t contextId)
index 80e5b8e..321cefe 100644 (file)
@@ -1,3 +1,19 @@
+2018-09-07  Matt Rajca  <mrajca@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=189433
+        <rdar://problem/44186498> Touch Bar displays an active PIP button for audio elements (and it doesn't do anything)
+
+        Reviewed by Eric Carlson.
+
+        An API test has been added that checks the value of the canTogglePictureInPicture and ensures it
+        is NO when audio elements are playing.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/PictureInPictureDelegate.html:
+        * TestWebKitAPI/Tests/WebKitCocoa/PictureInPictureDelegate.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/audio-with-controls.html: Added.
+
 2018-09-09  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r235832.
index 4cb5ecc..8b4d677 100644 (file)
                C540F784152E5A9A00A40C8C /* verboseMarkup.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C540F783152E5A7800A40C8C /* verboseMarkup.html */; };
                C54237F116B8957D00E638FC /* PasteboardNotifications_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C54237ED16B8955800E638FC /* PasteboardNotifications_Bundle.cpp */; };
                C5E1AFFE16B221F1006CC1F2 /* execCopy.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C5E1AFFD16B22179006CC1F2 /* execCopy.html */; };
+               C944160021430E8900B1EDDA /* audio-with-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C94415FF21430B6700B1EDDA /* audio-with-controls.html */; };
                C95984F41E36BC6B002C0D45 /* autoplay-check.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C95984F21E36BC55002C0D45 /* autoplay-check.html */; };
                C95984F51E36BC6B002C0D45 /* autoplay-no-audio-check.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C95984F31E36BC55002C0D45 /* autoplay-no-audio-check.html */; };
                C95984F71E36BCEF002C0D45 /* test-without-audio-track.mp4 in Copy Resources */ = {isa = PBXBuildFile; fileRef = C95984F61E36BCD7002C0D45 /* test-without-audio-track.mp4 */; };
                        dstPath = TestWebKitAPI.resources;
                        dstSubfolderSpec = 7;
                        files = (
+                               C944160021430E8900B1EDDA /* audio-with-controls.html in Copy Resources */,
                                1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
                                379028B914FAC24C007E6B43 /* acceptsFirstMouse.html in Copy Resources */,
                                1C2B81871C8925A000A5529F /* Ahem.ttf in Copy Resources */,
                C54237ED16B8955800E638FC /* PasteboardNotifications_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PasteboardNotifications_Bundle.cpp; sourceTree = "<group>"; };
                C54237EE16B8955800E638FC /* PasteboardNotifications.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteboardNotifications.mm; sourceTree = "<group>"; };
                C5E1AFFD16B22179006CC1F2 /* execCopy.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = execCopy.html; sourceTree = "<group>"; };
+               C94415FF21430B6700B1EDDA /* audio-with-controls.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "audio-with-controls.html"; sourceTree = "<group>"; };
                C95501BE19AD2FAF0049BE3E /* Preferences.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Preferences.mm; sourceTree = "<group>"; };
                C95984F21E36BC55002C0D45 /* autoplay-check.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "autoplay-check.html"; sourceTree = "<group>"; };
                C95984F31E36BC55002C0D45 /* autoplay-no-audio-check.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "autoplay-no-audio-check.html"; sourceTree = "<group>"; };
                A16F66B81C40E9E100BD4D24 /* Resources */ = {
                        isa = PBXGroup;
                        children = (
+                               C94415FF21430B6700B1EDDA /* audio-with-controls.html */,
                                C25CCA0C1E5140E50026CB8A /* AllAhem.svg */,
                                F4A9202E1FEE34C800F59590 /* apple-data-url.html */,
                                F47D30EB1ED28619000482E1 /* apple.gif */,
index f95b7f1..82cdc81 100644 (file)
@@ -8,6 +8,9 @@
             });
             
             function load() {
+                var target = document.getElementById('video');
+                target.play();
+
                 if (window.webkit !== undefined && window.webkit.messageHandlers.pictureInPictureChangeHandler !== undefined) {
                     window.webkit.messageHandlers.pictureInPictureChangeHandler.postMessage('load');
                 }
index c224490..acac484 100644 (file)
@@ -30,6 +30,7 @@
 #import "PlatformUtilities.h"
 #import "PlatformWebView.h"
 #import "Test.h"
+#import "TestWKWebView.h"
 #import <JavaScriptCore/JSRetainPtr.h>
 #import <JavaScriptCore/JavaScriptCore.h>
 #import <WebKit/WKPagePrivateMac.h>
@@ -119,13 +120,17 @@ TEST(PictureInPicture, WKUIDelegate)
     RetainPtr<PictureInPictureUIDelegate> handler = adoptNS([[PictureInPictureUIDelegate alloc] init]);
     [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"pictureInPictureChangeHandler"];
     [webView setUIDelegate:handler.get()];
-    
+
+#if HAVE(TOUCH_BAR)
+    [webView _forceRequestCandidates];
+#endif
+
     RetainPtr<NSWindow> window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:NO]);
     [[window contentView] addSubview:webView.get()];
     [window makeKeyAndOrderFront:nil];
 
     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"PictureInPictureDelegate" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
-    
+
     receivedLoadedMessage = false;
     
     [webView loadRequest:request];
@@ -138,16 +143,46 @@ TEST(PictureInPicture, WKUIDelegate)
     [webView mouseDown:event];
     TestWebKitAPI::Util::run(&hasVideoInPictureInPictureCalled);
     ASSERT_TRUE(hasVideoInPictureInPictureValue);
-    
-    sleep(1_s); // Wait for PIPAgent to launch, or it won't call -pipDidClose: callback.
-    
+
+    // Wait for PIPAgent to launch, or it won't call -pipDidClose: callback.
+    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
+
+#if HAVE(TOUCH_BAR)
+    ASSERT_TRUE([webView _canTogglePictureInPictureForTesting]);
+#endif
+
     hasVideoInPictureInPictureCalled = false;
     [webView mouseDown:event];
     TestWebKitAPI::Util::run(&hasVideoInPictureInPictureCalled);
     ASSERT_FALSE(hasVideoInPictureInPictureValue);
 }
-    
-    
+
+#if HAVE(TOUCH_BAR)
+
+TEST(PictureInPicture, AudioCannotTogglePictureInPicture)
+{
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 54) configuration:configuration.get()]);
+    [configuration preferences]._fullScreenEnabled = YES;
+    [configuration preferences]._allowsPictureInPictureMediaPlayback = YES;
+    RetainPtr<PictureInPictureUIDelegate> handler = adoptNS([[PictureInPictureUIDelegate alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"pictureInPictureChangeHandler"];
+    [webView setUIDelegate:handler.get()];
+    [webView _forceRequestCandidates];
+
+    RetainPtr<NSWindow> window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:NO]);
+    [[window contentView] addSubview:webView.get()];
+    [window makeKeyAndOrderFront:nil];
+
+    [webView synchronouslyLoadTestPageNamed:@"audio-with-controls"];
+    [webView evaluateJavaScript:@"play()" completionHandler:nil];
+
+    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
+    ASSERT_FALSE([webView _canTogglePictureInPictureForTesting]);
+}
+
+#endif // HAVE(TOUCH_BAR)
+
 TEST(PictureInPicture, WKPageUIClient)
 {
     WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/audio-with-controls.html b/Tools/TestWebKitAPI/Tests/WebKitCocoa/audio-with-controls.html
new file mode 100644 (file)
index 0000000..2d727b7
--- /dev/null
@@ -0,0 +1,24 @@
+<html>
+    <head>
+        <script>
+            function pageLoaded() {
+                try {
+                    window.webkit.messageHandlers.pictureInPictureChangeHandler.postMessage('load');
+                } catch(e) { }
+            }
+
+            function play() {
+                document.getElementById("audio").play();
+            }
+
+            function didStartPlaying() {
+                try {
+                    window.webkit.messageHandlers.pictureInPictureChangeHandler.postMessage('playing');
+                } catch(e) { }
+            }
+        </script>
+    </head>
+    <body onload="pageLoaded()">
+        <audio controls id="audio" src="silence-long.m4a" onplaying="didStartPlaying()" />
+    </body>
+</html>