Commit fc9e1d68 authored by Mounir Lamouri's avatar Mounir Lamouri Committed by Commit Bot

Autoplay: only check for high media engagement on main frame.

The bit is sent to all subframes instead of only the main frame. This is
a quick fix until a better one is found that will not break OOPIF.

This CL also de-recursify `HasBeenActivated()`

Bug: 810822
Change-Id: Ib8f494749221da5ec27f5a9b92d531de6d06a5d9
Reviewed-on: https://chromium-review.googlesource.com/934451Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Commit-Queue: Mounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539243}
parent 941fec3d
...@@ -69,7 +69,7 @@ class MediaEngagementAutoplayBrowserTest : public InProcessBrowserTest { ...@@ -69,7 +69,7 @@ class MediaEngagementAutoplayBrowserTest : public InProcessBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override { void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII( command_line->AppendSwitchASCII(
switches::kAutoplayPolicy, switches::kAutoplayPolicy,
switches::autoplay::kUserGestureRequiredPolicy); switches::autoplay::kDocumentUserActivationRequiredPolicy);
} }
void SetUp() override { void SetUp() override {
...@@ -89,19 +89,27 @@ class MediaEngagementAutoplayBrowserTest : public InProcessBrowserTest { ...@@ -89,19 +89,27 @@ class MediaEngagementAutoplayBrowserTest : public InProcessBrowserTest {
}; };
void LoadTestPage(const std::string& page) { void LoadTestPage(const std::string& page) {
ui_test_utils::NavigateToURL(browser(), http_server_.GetURL("/" + page)); NavigateParams params(browser()->profile(), http_server_.GetURL("/" + page),
ui::PageTransition::PAGE_TRANSITION_LINK);
params.user_gesture = false;
params.is_renderer_initiated = false;
ui_test_utils::NavigateToURL(&params);
} }
void LoadTestPageSecondaryOrigin(const std::string& page) { void LoadTestPageSecondaryOrigin(const std::string& page) {
ui_test_utils::NavigateToURL(browser(), NavigateParams params(browser()->profile(),
http_server_origin2_.GetURL("/" + page)); http_server_origin2_.GetURL("/" + page),
ui::PageTransition::PAGE_TRANSITION_LINK);
params.user_gesture = false;
params.is_renderer_initiated = false;
ui_test_utils::NavigateToURL(&params);
} }
void LoadSubFrame(const std::string& page) { void LoadSubFrame(const std::string& page) {
EXPECT_TRUE(content::ExecuteScript( EXPECT_TRUE(content::ExecuteScriptWithoutUserGesture(
GetWebContents(), "window.open(\"" + GetWebContents(), "document.getElementsByName('subframe')[0].src = \"" +
http_server_origin2_.GetURL("/" + page).spec() + http_server_origin2_.GetURL("/" + page).spec() +
"\", \"subframe\")")); "\""));
} }
void SetScores(GURL url, int visits, int media_playbacks) { void SetScores(GURL url, int visits, int media_playbacks) {
...@@ -206,21 +214,37 @@ IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest, ...@@ -206,21 +214,37 @@ IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest,
} }
IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest, IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest,
BypassAutoplayFrameHighEngagement) { DoNotBypassAutoplayFrameHighEngagement_NoDelegation) {
SetScores(PrimaryOrigin(), 20, 20); SetScores(PrimaryOrigin(), 20, 20);
LoadTestPage("engagement_autoplay_iframe_test.html"); LoadTestPage("engagement_autoplay_iframe_test.html");
LoadSubFrame("engagement_autoplay_iframe_test_frame.html"); LoadSubFrame("engagement_autoplay_iframe_test_frame.html");
ExpectAutoplayAllowed(); ExpectAutoplayDenied();
} }
IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest, IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest,
DoNotBypassAutoplayFrameLowEngagement) { DoNotBypassAutoplayFrameLowEngagement_NoDelegation) {
SetScores(SecondaryOrigin(), 20, 20); SetScores(SecondaryOrigin(), 20, 20);
LoadTestPage("engagement_autoplay_iframe_test.html"); LoadTestPage("engagement_autoplay_iframe_test.html");
LoadSubFrame("engagement_autoplay_iframe_test_frame.html"); LoadSubFrame("engagement_autoplay_iframe_test_frame.html");
ExpectAutoplayDenied(); ExpectAutoplayDenied();
} }
IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest,
BypassAutoplayFrameHighEngagement_Delegation) {
SetScores(PrimaryOrigin(), 20, 20);
LoadTestPage("engagement_autoplay_iframe_delegation.html");
LoadSubFrame("engagement_autoplay_iframe_test_frame.html");
ExpectAutoplayAllowed();
}
IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest,
DoNotBypassAutoplayFrameLowEngagement_Delegation) {
SetScores(SecondaryOrigin(), 20, 20);
LoadTestPage("engagement_autoplay_iframe_delegation.html");
LoadSubFrame("engagement_autoplay_iframe_test_frame.html");
ExpectAutoplayDenied();
}
IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest, IN_PROC_BROWSER_TEST_F(MediaEngagementAutoplayBrowserTest,
DoNotBypassAutoplayFrameNoEngagement) { DoNotBypassAutoplayFrameNoEngagement) {
LoadTestPage("engagement_autoplay_iframe_test.html"); LoadTestPage("engagement_autoplay_iframe_test.html");
......
<!DOCTYPE html>
<meta charset="utf-8">
<title>Media Engagement Test</title>
<iframe allow="autoplay" name="subframe" frameborder="0" style="width:500px;height:500px"></iframe>
<script>
window.addEventListener("message", function(e) {
window.document.title = e.data;
}, false);
</script>
...@@ -72,29 +72,6 @@ bool ComputeLockPendingUserGestureRequired(const Document& document) { ...@@ -72,29 +72,6 @@ bool ComputeLockPendingUserGestureRequired(const Document& document) {
return true; return true;
} }
// Return true if any frame between |frame| and the root has been activated in
// either the current or previous navigation. If the
// FeaturePolicyAutoplayFeature flag is disabled then it will stop at the
// current frame.
bool HasBeenActivated(const Frame& frame) {
// Check if the current frame has received a user activation.
if (frame.HasBeenActivated() ||
frame.HasReceivedUserGestureBeforeNavigation()) {
return true;
}
// Check feature policy before traversing the tree.
if (!RuntimeEnabledFeatures::FeaturePolicyAutoplayFeatureEnabled() ||
!frame.IsFeatureEnabled(mojom::FeaturePolicyFeature::kAutoplay)) {
return false;
}
// If there is a parent check if the parent has received a
// user gesture.
const Frame* parent = frame.Tree().Parent();
return parent && HasBeenActivated(*parent);
}
} // anonymous namespace } // anonymous namespace
// static // static
...@@ -106,11 +83,6 @@ AutoplayPolicy::Type AutoplayPolicy::GetAutoplayPolicyForDocument( ...@@ -106,11 +83,6 @@ AutoplayPolicy::Type AutoplayPolicy::GetAutoplayPolicyForDocument(
if (IsDocumentWhitelisted(document)) if (IsDocumentWhitelisted(document))
return Type::kNoUserGestureRequired; return Type::kNoUserGestureRequired;
if (RuntimeEnabledFeatures::MediaEngagementBypassAutoplayPoliciesEnabled() &&
document.HasHighMediaEngagement()) {
return Type::kNoUserGestureRequired;
}
return document.GetSettings()->GetAutoplayPolicy(); return document.GetSettings()->GetAutoplayPolicy();
} }
...@@ -119,7 +91,29 @@ bool AutoplayPolicy::IsDocumentAllowedToPlay(const Document& document) { ...@@ -119,7 +91,29 @@ bool AutoplayPolicy::IsDocumentAllowedToPlay(const Document& document) {
if (!document.GetFrame()) if (!document.GetFrame())
return false; return false;
return HasBeenActivated(*document.GetFrame()); for (Frame* frame = document.GetFrame(); frame;
frame = frame->Tree().Parent()) {
if (frame->HasBeenActivated() ||
frame->HasReceivedUserGestureBeforeNavigation()) {
return true;
}
// TODO(mlamouri): checking HasHighMediaEngagement from the document as all
// documents are in this state if the main frame has a high media
// engagement. This allows OOPIF to work but a follow-up fix is in progress.
if (RuntimeEnabledFeatures::
MediaEngagementBypassAutoplayPoliciesEnabled() &&
frame->IsMainFrame() && document.HasHighMediaEngagement()) {
return true;
}
if (!RuntimeEnabledFeatures::FeaturePolicyAutoplayFeatureEnabled() ||
!frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kAutoplay)) {
return false;
}
}
return false;
} }
AutoplayPolicy::AutoplayPolicy(HTMLMediaElement* element) AutoplayPolicy::AutoplayPolicy(HTMLMediaElement* element)
......
...@@ -34,6 +34,13 @@ class AutoplayPolicy final : public GarbageCollected<AutoplayPolicy> { ...@@ -34,6 +34,13 @@ class AutoplayPolicy final : public GarbageCollected<AutoplayPolicy> {
}; };
CORE_EXPORT static Type GetAutoplayPolicyForDocument(const Document&); CORE_EXPORT static Type GetAutoplayPolicyForDocument(const Document&);
// Return true if the given |document| is allowed to play.
// This method may check parent frames if allow=autoplay (Feature Policy) was
// used, in which case, the frame will be allowed to play if its parents are,
// and so on.
// Otherwise, frames are allowed to play if they have been activated or, for
// the main frame, if it has a high MEI.
CORE_EXPORT static bool IsDocumentAllowedToPlay(const Document&); CORE_EXPORT static bool IsDocumentAllowedToPlay(const Document&);
explicit AutoplayPolicy(HTMLMediaElement*); explicit AutoplayPolicy(HTMLMediaElement*);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment