Pass down website autoplay policies to media elements
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jan 2017 21:03:42 +0000 (21:03 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jan 2017 21:03:42 +0000 (21:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=167355

Patch by Matt Rajca <mrajca@apple.com> on 2017-01-24
Reviewed by Alex Christensen.

Source/WebCore:

Autoplay policies can be specified at the global web view preferences level or on a per-page
basis during navigation. This patch ensures that policies specified on a per-page basis hold
precedence over global policies. If no policies are specified during navigation, global
policies are used. A WebsiteAutoplayPolicy::Default option has been added to let clients
explicitly specify web view defaults should be used.

* dom/Document.cpp:
(WebCore::Document::audioPlaybackRequiresUserGesture):
(WebCore::Document::videoPlaybackRequiresUserGesture):
* dom/Document.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(WebCore::HTMLMediaElement::playInternal):
* loader/DocumentLoader.h:
(WebCore::DocumentLoader::audioPlaybackRequiresUserGesture):
(WebCore::DocumentLoader::setAudioPlaybackRequiresUserGesture):
(WebCore::DocumentLoader::videoPlaybackRequiresUserGesture):
(WebCore::DocumentLoader::setVideoPlaybackRequiresUserGesture):

Source/WebKit2:

Autoplay policies can be specified at the global web view preferences level or on a per-page
basis during navigation. This patch ensures that policies specified on a per-page basis hold
precedence over global policies. If no policies are specified during navigation, global
policies are used. A WebsiteAutoplayPolicy::Default option has been added to let clients
explicitly specify web view defaults should be used.

* Shared/WebsitePolicies.h:
* UIProcess/API/C/WKWebsitePolicies.cpp:
(WKWebsitePoliciesGetAutoplayPolicy):
(WKWebsitePoliciesSetAutoplayPolicy):
* UIProcess/API/C/WKWebsitePolicies.h:
* UIProcess/API/Cocoa/_WKWebsitePolicies.h:
* UIProcess/API/Cocoa/_WKWebsitePolicies.mm:
(-[_WKWebsitePolicies setAutoplayPolicy:]):
(-[_WKWebsitePolicies autoplayPolicy]):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2/autoplay-check.html: Renamed from Tools/TestWebKitAPI/Tests/WebKit2/autoplayCheck.html to match our naming conventions.
* TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html: Added.
* TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4: Added.
* TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm:
(-[AutoplayPoliciesDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):
(TEST):

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

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/loader/DocumentLoader.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebsitePolicies.h
Source/WebKit2/UIProcess/API/APIWebsitePolicies.h
Source/WebKit2/UIProcess/API/C/WKWebsitePolicies.cpp
Source/WebKit2/UIProcess/API/C/WKWebsitePolicies.h
Source/WebKit2/UIProcess/API/Cocoa/_WKWebsitePolicies.h
Source/WebKit2/UIProcess/API/Cocoa/_WKWebsitePolicies.mm
Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4 [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm

index 3c297d4..2bc231c 100644 (file)
@@ -1,3 +1,29 @@
+2017-01-24  Matt Rajca  <mrajca@apple.com>
+
+        Pass down website autoplay policies to media elements
+        https://bugs.webkit.org/show_bug.cgi?id=167355
+
+        Reviewed by Alex Christensen.
+
+        Autoplay policies can be specified at the global web view preferences level or on a per-page
+        basis during navigation. This patch ensures that policies specified on a per-page basis hold
+        precedence over global policies. If no policies are specified during navigation, global
+        policies are used. A WebsiteAutoplayPolicy::Default option has been added to let clients
+        explicitly specify web view defaults should be used.
+
+        * dom/Document.cpp:
+        (WebCore::Document::audioPlaybackRequiresUserGesture):
+        (WebCore::Document::videoPlaybackRequiresUserGesture):
+        * dom/Document.h:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement):
+        (WebCore::HTMLMediaElement::playInternal):
+        * loader/DocumentLoader.h:
+        (WebCore::DocumentLoader::audioPlaybackRequiresUserGesture):
+        (WebCore::DocumentLoader::setAudioPlaybackRequiresUserGesture):
+        (WebCore::DocumentLoader::videoPlaybackRequiresUserGesture):
+        (WebCore::DocumentLoader::setVideoPlaybackRequiresUserGesture):
+
 2017-01-24  Joseph Pecoraro  <pecoraro@apple.com>
 
         Remove always true selectionIncludesAltImageText setting
index 83290dc..7725bda 100644 (file)
@@ -4646,6 +4646,32 @@ void Document::unregisterForMediaVolumeCallbacks(Element* e)
     m_mediaVolumeCallbackElements.remove(e);
 }
 
+bool Document::audioPlaybackRequiresUserGesture() const
+{
+    if (DocumentLoader* loader = this->loader()) {
+        // If an audio playback policy was set during navigation, use it. If not, use the global settings.
+        AutoplayPolicy policy = loader->autoplayPolicy();
+        if (policy != AutoplayPolicy::Default)
+            return policy == AutoplayPolicy::AllowWithoutSound || policy == AutoplayPolicy::Deny;
+    }
+
+    Settings* settings = this->settings();
+    return settings && settings->audioPlaybackRequiresUserGesture();
+}
+
+bool Document::videoPlaybackRequiresUserGesture() const
+{
+    if (DocumentLoader* loader = this->loader()) {
+        // If a video playback policy was set during navigation, use it. If not, use the global settings.
+        AutoplayPolicy policy = loader->autoplayPolicy();
+        if (policy != AutoplayPolicy::Default)
+            return policy == AutoplayPolicy::Deny;
+    }
+
+    Settings* settings = this->settings();
+    return settings && settings->videoPlaybackRequiresUserGesture();
+}
+
 void Document::storageBlockingStateDidChange()
 {
     if (Settings* settings = this->settings())
index 00d1560..28c0154 100644 (file)
@@ -984,6 +984,9 @@ public:
     void unregisterForMediaVolumeCallbacks(Element*);
     void mediaVolumeDidChange();
 
+    bool audioPlaybackRequiresUserGesture() const;
+    bool videoPlaybackRequiresUserGesture() const;
+
 #if ENABLE(MEDIA_SESSION)
     MediaSession& defaultMediaSession();
 #endif
index f9af78e..6074cc3 100644 (file)
@@ -462,17 +462,20 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
         m_mediaSession->addBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted);
 
     if (document.ownerElement() || !document.isMediaDocument()) {
-        if (settings && settings->videoPlaybackRequiresUserGesture()) {
+        bool shouldAudioPlaybackRequireUserGesture = document.audioPlaybackRequiresUserGesture();
+        bool shouldVideoPlaybackRequireUserGesture = document.videoPlaybackRequiresUserGesture();
+
+        if (shouldVideoPlaybackRequireUserGesture) {
             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoRateChange);
-            if (settings->requiresUserGestureToLoadVideo())
+            if (settings && settings->requiresUserGestureToLoadVideo())
                 m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForLoad);
         }
 
-        if (settings && settings->audioPlaybackRequiresUserGesture())
+        if (shouldAudioPlaybackRequireUserGesture)
             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForAudioRateChange);
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
-        if (settings && (settings->videoPlaybackRequiresUserGesture() || settings->audioPlaybackRequiresUserGesture()))
+        if (shouldVideoPlaybackRequireUserGesture || shouldAudioPlaybackRequireUserGesture)
             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker);
 #endif
 
index c01b997..2d537b3 100644 (file)
@@ -78,6 +78,13 @@ class SubstituteResource;
 
 using ResourceLoaderMap = HashMap<unsigned long, RefPtr<ResourceLoader>>;
 
+enum class AutoplayPolicy {
+    Default, // Uses policies specified in document settings.
+    Allow,
+    AllowWithoutSound,
+    Deny,
+};
+
 class DocumentLoader : public RefCounted<DocumentLoader>, private CachedRawResourceClient {
     WTF_MAKE_FAST_ALLOCATED;
     friend class ContentFilter;
@@ -232,6 +239,9 @@ public:
     bool userContentExtensionsEnabled() const { return m_userContentExtensionsEnabled; }
     void setUserContentExtensionsEnabled(bool enabled) { m_userContentExtensionsEnabled = enabled; }
 
+    AutoplayPolicy autoplayPolicy() const { return m_autoplayPolicy; }
+    void setAutoplayPolicy(AutoplayPolicy policy) { m_autoplayPolicy = policy; }
+
     void addSubresourceLoader(ResourceLoader*);
     void removeSubresourceLoader(ResourceLoader*);
     void addPlugInStreamLoader(ResourceLoader&);
@@ -461,6 +471,7 @@ private:
     HashMap<String, Vector<std::pair<String, uint32_t>>> m_pendingContentExtensionDisplayNoneSelectors;
 #endif
     bool m_userContentExtensionsEnabled { true };
+    AutoplayPolicy m_autoplayPolicy { AutoplayPolicy::Default };
 
 #ifndef NDEBUG
     bool m_hasEverBeenAttached { false };
index 04f7cb2..01ebd28 100644 (file)
@@ -1,3 +1,28 @@
+2017-01-24  Matt Rajca  <mrajca@apple.com>
+
+        Pass down website autoplay policies to media elements
+        https://bugs.webkit.org/show_bug.cgi?id=167355
+
+        Reviewed by Alex Christensen.
+
+        Autoplay policies can be specified at the global web view preferences level or on a per-page
+        basis during navigation. This patch ensures that policies specified on a per-page basis hold
+        precedence over global policies. If no policies are specified during navigation, global
+        policies are used. A WebsiteAutoplayPolicy::Default option has been added to let clients
+        explicitly specify web view defaults should be used.
+
+        * Shared/WebsitePolicies.h:
+        * UIProcess/API/C/WKWebsitePolicies.cpp:
+        (WKWebsitePoliciesGetAutoplayPolicy):
+        (WKWebsitePoliciesSetAutoplayPolicy):
+        * UIProcess/API/C/WKWebsitePolicies.h:
+        * UIProcess/API/Cocoa/_WKWebsitePolicies.h:
+        * UIProcess/API/Cocoa/_WKWebsitePolicies.mm:
+        (-[_WKWebsitePolicies setAutoplayPolicy:]):
+        (-[_WKWebsitePolicies autoplayPolicy]):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
+
 2017-01-24  Nan Wang  <n_wang@apple.com>
 
         AX: Speak Selection does not work in an iframe
index f3b9a10..f79c3fb 100644 (file)
 namespace WebKit {
 
 enum class WebsiteAutoplayPolicy {
-    UseHeuristics,
-    AlwaysAllow,
-    AlwaysDeny
+    Default,
+    Allow,
+    AllowWithoutSound,
+    Deny
 };
 
 struct WebsitePolicies {
 
     bool contentBlockersEnabled { true };
-    bool autoplayEnabled { true };
+    WebsiteAutoplayPolicy autoplayPolicy { WebsiteAutoplayPolicy::Default };
     
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static bool decode(Decoder&, WebsitePolicies&);
@@ -45,14 +46,14 @@ struct WebsitePolicies {
 template<class Encoder> void WebsitePolicies::encode(Encoder& encoder) const
 {
     encoder << contentBlockersEnabled;
-    encoder << autoplayEnabled;
+    encoder.encodeEnum(autoplayPolicy);
 }
 
 template<class Decoder> bool WebsitePolicies::decode(Decoder& decoder, WebsitePolicies& result)
 {
     if (!decoder.decode(result.contentBlockersEnabled))
         return false;
-    if (!decoder.decode(result.autoplayEnabled))
+    if (!decoder.decodeEnum(result.autoplayPolicy))
         return false;
     return true;
 }
index af747ba..ca74f81 100644 (file)
@@ -39,8 +39,8 @@ public:
     bool contentBlockersEnabled() const { return m_websitePolicies.contentBlockersEnabled; }
     void setContentBlockersEnabled(bool enabled) { m_websitePolicies.contentBlockersEnabled = enabled; }
 
-    bool autoplayEnabled() const { return m_websitePolicies.autoplayEnabled; }
-    void setAutoplayEnabled(bool enabled) { m_websitePolicies.autoplayEnabled = enabled; }
+    WebKit::WebsiteAutoplayPolicy autoplayPolicy() const { return m_websitePolicies.autoplayPolicy; }
+    void setAutoplayPolicy(WebKit::WebsiteAutoplayPolicy policy) { m_websitePolicies.autoplayPolicy = policy; }
 
     const WebKit::WebsitePolicies& websitePolicies() { return m_websitePolicies; }
     
index 6e527cc..b9709a6 100644 (file)
@@ -52,12 +52,37 @@ bool WKWebsitePoliciesGetContentBlockersEnabled(WKWebsitePoliciesRef websitePoli
     return toImpl(websitePolicies)->contentBlockersEnabled();
 }
 
-bool WKWebsitePoliciesGetAutoplayEnabled(WKWebsitePoliciesRef websitePolicies)
+WKWebsiteAutoplayPolicy WKWebsitePoliciesGetAutoplayPolicy(WKWebsitePoliciesRef websitePolicies)
 {
-    return toImpl(websitePolicies)->autoplayEnabled();
+    switch (toImpl(websitePolicies)->autoplayPolicy()) {
+    case WebKit::WebsiteAutoplayPolicy::Default:
+        return kWKWebsiteAutoplayPolicyDefault;
+    case WebsiteAutoplayPolicy::Allow:
+        return kWKWebsiteAutoplayPolicyAllow;
+    case WebsiteAutoplayPolicy::AllowWithoutSound:
+        return kWKWebsiteAutoplayPolicyAllowWithoutSound;
+    case WebsiteAutoplayPolicy::Deny:
+        return kWKWebsiteAutoplayPolicyDeny;
+    }
+    ASSERT_NOT_REACHED();
+    return kWKWebsiteAutoplayPolicyDefault;
 }
 
-void WKWebsitePoliciesSetAutoplayEnabled(WKWebsitePoliciesRef websitePolicies, bool enabled)
+void WKWebsitePoliciesSetAutoplayPolicy(WKWebsitePoliciesRef websitePolicies, WKWebsiteAutoplayPolicy policy)
 {
-    toImpl(websitePolicies)->setAutoplayEnabled(enabled);
+    switch (policy) {
+    case kWKWebsiteAutoplayPolicyDefault:
+        toImpl(websitePolicies)->setAutoplayPolicy(WebsiteAutoplayPolicy::Default);
+        return;
+    case kWKWebsiteAutoplayPolicyAllow:
+        toImpl(websitePolicies)->setAutoplayPolicy(WebsiteAutoplayPolicy::Allow);
+        return;
+    case kWKWebsiteAutoplayPolicyAllowWithoutSound:
+        toImpl(websitePolicies)->setAutoplayPolicy(WebsiteAutoplayPolicy::AllowWithoutSound);
+        return;
+    case kWKWebsiteAutoplayPolicyDeny:
+        toImpl(websitePolicies)->setAutoplayPolicy(WebsiteAutoplayPolicy::Deny);
+        return;
+    }
+    ASSERT_NOT_REACHED();
 }
index 6551fdc..0c8e34f 100644 (file)
@@ -34,9 +34,10 @@ extern "C" {
 WK_EXPORT WKTypeID WKWebsitePoliciesGetTypeID();
 
 enum WKWebsiteAutoplayPolicy {
-    kWKWebsiteAutoplayPolicyUseHeuristics,
-    kWKWebsiteAutoplayPolicyAlwaysAllow,
-    kWKWebsiteAutoplayPolicyAlwaysDeny
+    kWKWebsiteAutoplayPolicyDefault,
+    kWKWebsiteAutoplayPolicyAllow,
+    kWKWebsiteAutoplayPolicyAllowWithoutSound,
+    kWKWebsiteAutoplayPolicyDeny
 };
 
 WK_EXPORT WKWebsitePoliciesRef WKWebsitePoliciesCreate();
@@ -44,8 +45,8 @@ WK_EXPORT WKWebsitePoliciesRef WKWebsitePoliciesCreate();
 WK_EXPORT bool WKWebsitePoliciesGetContentBlockersEnabled(WKWebsitePoliciesRef);
 WK_EXPORT void WKWebsitePoliciesSetContentBlockersEnabled(WKWebsitePoliciesRef, bool);
 
-WK_EXPORT bool WKWebsitePoliciesGetAutoplayEnabled(WKWebsitePoliciesRef);
-WK_EXPORT void WKWebsitePoliciesSetAutoplayEnabled(WKWebsitePoliciesRef, bool);
+WK_EXPORT WKWebsiteAutoplayPolicy WKWebsitePoliciesGetAutoplayPolicy(WKWebsitePoliciesRef);
+WK_EXPORT void WKWebsitePoliciesSetAutoplayPolicy(WKWebsitePoliciesRef, WKWebsiteAutoplayPolicy);
 
 #ifdef __cplusplus
 }
index ba2587f..e10cfc8 100644 (file)
 #if WK_API_ENABLED
 
 typedef NS_ENUM(NSInteger, _WKWebsiteAutoplayPolicy) {
-    _WKWebsiteAutoplayPolicyUseHeuristics,
-    _WKWebsiteAutoplayPolicyAlwaysAllow,
-    _WKWebsiteAutoplayPolicyAlwaysDeny
+    _WKWebsiteAutoplayPolicyDefault,
+    _WKWebsiteAutoplayPolicyAllow,
+    _WKWebsiteAutoplayPolicyAllowWithoutSound,
+    _WKWebsiteAutoplayPolicyDeny
 } WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
 @interface _WKWebsitePolicies : NSObject
 
 @property (nonatomic) BOOL contentBlockersEnabled;
-@property (nonatomic) BOOL autoplayEnabled;
+@property (nonatomic) _WKWebsiteAutoplayPolicy autoplayPolicy;
 
 @end
 
index 1ee9ad3..a621e45 100644 (file)
     return _websitePolicies->contentBlockersEnabled();
 }
 
-- (void)setAutoplayEnabled:(BOOL)enabled
+- (void)setAutoplayPolicy:(_WKWebsiteAutoplayPolicy)policy
 {
-    _websitePolicies->setAutoplayEnabled(enabled);
+    switch (policy) {
+    case _WKWebsiteAutoplayPolicyDefault:
+        _websitePolicies->setAutoplayPolicy(WebKit::WebsiteAutoplayPolicy::Default);
+        break;
+    case _WKWebsiteAutoplayPolicyAllow:
+        _websitePolicies->setAutoplayPolicy(WebKit::WebsiteAutoplayPolicy::Allow);
+        break;
+    case _WKWebsiteAutoplayPolicyAllowWithoutSound:
+        _websitePolicies->setAutoplayPolicy(WebKit::WebsiteAutoplayPolicy::AllowWithoutSound);
+        break;
+    case _WKWebsiteAutoplayPolicyDeny:
+        _websitePolicies->setAutoplayPolicy(WebKit::WebsiteAutoplayPolicy::Deny);
+        break;
+    }
 }
 
-- (BOOL)autoplayEnabled
+- (_WKWebsiteAutoplayPolicy)autoplayPolicy
 {
-    return _websitePolicies->autoplayEnabled();
+    switch (_websitePolicies->autoplayPolicy()) {
+    case WebKit::WebsiteAutoplayPolicy::Default:
+        return _WKWebsiteAutoplayPolicyDefault;
+    case WebKit::WebsiteAutoplayPolicy::Allow:
+        return _WKWebsiteAutoplayPolicyAllow;
+    case WebKit::WebsiteAutoplayPolicy::AllowWithoutSound:
+        return _WKWebsiteAutoplayPolicyAllowWithoutSound;
+    case WebKit::WebsiteAutoplayPolicy::Deny:
+        return _WKWebsiteAutoplayPolicyDeny;
+    }
 }
 
 - (NSString *)description
index 43398fc..fc0ac2e 100644 (file)
@@ -817,6 +817,21 @@ void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const Navigat
     if (documentLoader->userContentExtensionsEnabled())
         documentLoader->setUserContentExtensionsEnabled(websitePolicies.contentBlockersEnabled);
 
+    switch (websitePolicies.autoplayPolicy) {
+    case WebsiteAutoplayPolicy::Default:
+        documentLoader->setAutoplayPolicy(AutoplayPolicy::Default);
+        break;
+    case WebsiteAutoplayPolicy::Allow:
+        documentLoader->setAutoplayPolicy(AutoplayPolicy::Allow);
+        break;
+    case WebsiteAutoplayPolicy::AllowWithoutSound:
+        documentLoader->setAutoplayPolicy(AutoplayPolicy::AllowWithoutSound);
+        break;
+    case WebsiteAutoplayPolicy::Deny:
+        documentLoader->setAutoplayPolicy(AutoplayPolicy::Deny);
+        break;
+    }
+
     // We call this synchronously because WebCore cannot gracefully handle a frame load without a synchronous navigation policy reply.
     if (receivedPolicyAction)
         m_frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), newNavigationID, downloadID);
index 714b4f8..df7a8a0 100644 (file)
@@ -1,3 +1,18 @@
+2017-01-24  Matt Rajca  <mrajca@apple.com>
+
+        Pass down website autoplay policies to media elements
+        https://bugs.webkit.org/show_bug.cgi?id=167355
+
+        Reviewed by Alex Christensen.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2/autoplay-check.html: Renamed from Tools/TestWebKitAPI/Tests/WebKit2/autoplayCheck.html to match our naming conventions.
+        * TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html: Added.
+        * TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4: Added.
+        * TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm:
+        (-[AutoplayPoliciesDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):
+        (TEST):
+
 2017-01-24  Nan Wang  <n_wang@apple.com>
 
         AX: Speak Selection does not work in an iframe
index ddc13f1..f8f9c69 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 */; };
+               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 */; };
                CD59F53419E9110D00CF1835 /* file-with-mse.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CD59F53219E910AA00CF1835 /* file-with-mse.html */; };
                CD59F53519E9110D00CF1835 /* test-mse.mp4 in Copy Resources */ = {isa = PBXBuildFile; fileRef = CD59F53319E910BC00CF1835 /* test-mse.mp4 */; };
                CD78E11D1DB7EA660014A2DE /* FullscreenDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD78E11A1DB7EA360014A2DE /* FullscreenDelegate.mm */; };
                        dstPath = TestWebKitAPI.resources;
                        dstSubfolderSpec = 7;
                        files = (
+                               C95984F71E36BCEF002C0D45 /* test-without-audio-track.mp4 in Copy Resources */,
+                               C95984F41E36BC6B002C0D45 /* autoplay-check.html in Copy Resources */,
+                               C95984F51E36BC6B002C0D45 /* autoplay-no-audio-check.html in Copy Resources */,
                                7AEAD4811E20122700416EFE /* CrossPartitionFileSchemeAccess.html in Copy Resources */,
                                CDB4115A1E0B00DB00EAD352 /* video-with-muted-audio.html in Copy Resources */,
                                9BD4239C1E04C01C00200395 /* chinese-character-with-image.html in Copy Resources */,
                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>"; };
                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>"; };
+               C95984F61E36BCD7002C0D45 /* test-without-audio-track.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "test-without-audio-track.mp4"; sourceTree = "<group>"; };
                CD225C071C45A69200140761 /* ParsedContentRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParsedContentRange.cpp; sourceTree = "<group>"; };
                CD5393C71757BA9700C07123 /* MD5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD5.cpp; sourceTree = "<group>"; };
                CD5393C91757BAC400C07123 /* SHA1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SHA1.cpp; sourceTree = "<group>"; };
                BC90977B125571AE00083756 /* Resources */ = {
                        isa = PBXGroup;
                        children = (
-                               9BD4239B1E04BFD000200395 /* chinese-character-with-image.html */,
-                               07492B391DF8ADA400633DE1 /* enumerateMediaDevices.html */,
                                C045F9461385C2F800C0F3CD /* 18-characters.html */,
                                1C2B81851C89252300A5529F /* Ahem.ttf */,
                                93D3D19B17B1A7B000C7C415 /* all-content-in-one-iframe.html */,
                                F6B7BE9617469B7E008A3445 /* associate-form-controls.html */,
                                76E182DE15475A8300F1FADD /* auto-submitting-form.html */,
+                               C95984F21E36BC55002C0D45 /* autoplay-check.html */,
+                               C95984F31E36BC55002C0D45 /* autoplay-no-audio-check.html */,
                                7C486BA01AA1254B003F6F9B /* bundle-file.html */,
+                               9BD4239B1E04BFD000200395 /* chinese-character-with-image.html */,
                                1A50AA1F1A2A4EA500F4C345 /* close-from-within-create-page.html */,
                                9B270FED1DDC25FD002D53F3 /* closed-shadow-tree-test.html */,
                                5C9E56861DF9148E00C9EE33 /* contentBlockerCheck.html */,
                                290F4274172A1FDE00939FF0 /* custom-protocol-sync-xhr.html */,
+                               07492B391DF8ADA400633DE1 /* enumerateMediaDevices.html */,
                                C5E1AFFD16B22179006CC1F2 /* execCopy.html */,
                                BC2D004A12A9FEB300E732A3 /* file-with-anchor.html */,
                                CD59F53219E910AA00CF1835 /* file-with-mse.html */,
                                51E780371919AFF8001829A2 /* simple3.html */,
                                C02B7882126615410026BF0F /* spacebar-scrolling.html */,
                                CD59F53319E910BC00CF1835 /* test-mse.mp4 */,
+                               C95984F61E36BCD7002C0D45 /* test-without-audio-track.mp4 */,
                                524BBCA019E30C63002F1AF1 /* test.mp4 */,
                                7AE9E5081AE5AE8B00CF874B /* test.pdf */,
                                1C2B81841C8924A200A5529F /* webfont.html */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html
new file mode 100644 (file)
index 0000000..1acaf9c
--- /dev/null
@@ -0,0 +1,22 @@
+<html>
+    <head>
+        <script>
+            function pageLoaded() {
+                setTimeout(function() {
+                    try {
+                        window.webkit.messageHandlers.testHandler.postMessage("did-not-play");
+                    } catch(e) { }
+                }, 100);
+            }
+
+            function beganPlaying() {
+                try {
+                    window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+                } catch(e) { }
+            }
+        </script>
+    </head>
+    <body onload="pageLoaded()">
+        <video id="video" autoplay onplaying=beganPlaying() src="test.mp4" />
+    </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html
new file mode 100644 (file)
index 0000000..93b73e5
--- /dev/null
@@ -0,0 +1,22 @@
+<html>
+    <head>
+        <script>
+            function pageLoaded() {
+                setTimeout(function() {
+                    try {
+                        window.webkit.messageHandlers.testHandler.postMessage("did-not-play");
+                    } catch(e) { }
+                }, 100);
+            }
+
+            function beganPlaying() {
+                try {
+                    window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+                } catch(e) { }
+            }
+        </script>
+    </head>
+    <body onload="pageLoaded()">
+        <video id="video" autoplay onplaying=beganPlaying() src="test-without-audio-track.mp4" />
+    </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4 b/Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4
new file mode 100644 (file)
index 0000000..8ad09c0
Binary files /dev/null and b/Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4 differ
index 2519f8c..680a7ef 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 
 #import "PlatformUtilities.h"
+#import "TestWKWebView.h"
 #import <WebKit/WKUserContentControllerPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/_WKUserContentExtensionStorePrivate.h>
@@ -38,10 +39,10 @@ static bool doneCompiling;
 static bool receivedAlert;
 static size_t alertCount;
 
-@interface WebsitePoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
+@interface ContentBlockingWebsitePoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
 @end
 
-@implementation WebsitePoliciesDelegate
+@implementation ContentBlockingWebsitePoliciesDelegate
 
 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
 {
@@ -123,7 +124,7 @@ TEST(WebKit2, WebsitePoliciesContentBlockersEnabled)
 
     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
 
-    auto delegate = adoptNS([[WebsitePoliciesDelegate alloc] init]);
+    auto delegate = adoptNS([[ContentBlockingWebsitePoliciesDelegate alloc] init]);
     [webView setNavigationDelegate:delegate.get()];
     [webView setUIDelegate:delegate.get()];
 
@@ -148,4 +149,59 @@ TEST(WebKit2, WebsitePoliciesContentBlockersEnabled)
     [[_WKUserContentExtensionStore defaultStore] _removeAllContentExtensions];
 }
 
+@interface AutoplayPoliciesDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
+@property (nonatomic) _WKWebsiteAutoplayPolicy autoplayPolicy;
+@end
+
+@implementation AutoplayPoliciesDelegate
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
+{
+    // _webView:decidePolicyForNavigationAction:decisionHandler: should be called instead if it is implemented.
+    EXPECT_TRUE(false);
+    decisionHandler(WKNavigationActionPolicyAllow);
+}
+
+- (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
+{
+    _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
+    websitePolicies.autoplayPolicy = _autoplayPolicy;
+    decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
+}
+
+@end
+
+TEST(WebKit2, WebsitePoliciesAutoplayEnabled)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    auto delegate = adoptNS([[AutoplayPoliciesDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *requestWithAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+    NSURLRequest *requestWithoutAudio = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"autoplay-no-audio-check" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+    
+    [delegate setAutoplayPolicy:_WKWebsiteAutoplayPolicyAllowWithoutSound];
+    [webView loadRequest:requestWithAudio];
+    [webView waitForMessage:@"did-not-play"];
+
+    [webView loadRequest:requestWithoutAudio];
+    [webView waitForMessage:@"autoplayed"];
+
+    [delegate setAutoplayPolicy:_WKWebsiteAutoplayPolicyDeny];
+    [webView loadRequest:requestWithAudio];
+    [webView waitForMessage:@"did-not-play"];
+
+    [webView loadRequest:requestWithoutAudio];
+    [webView waitForMessage:@"did-not-play"];
+
+    [delegate setAutoplayPolicy:_WKWebsiteAutoplayPolicyAllow];
+    [webView loadRequest:requestWithAudio];
+    [webView waitForMessage:@"autoplayed"];
+
+    [webView loadRequest:requestWithoutAudio];
+    [webView waitForMessage:@"autoplayed"];
+}
+
 #endif