Commit 7d2bbb8f authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Autoplay] Policy should follow kBlockAutoplayEnabled pref

The autoplay policy should follow the kBlockAutoplayEnabled pref
if the kAutoplaySoundSettings feature is enabled. If the pref is
true we will use document-user-activation otherwise we will
use no-user-gesture-required.

The only exception is if the user has overridden the autoplay
policy in which case we will use the autoplay policy command
line switch.

BUG=865548

Change-Id: I79ba3bbf5542ba17af9ab96baef80cd89d5b5326
Reviewed-on: https://chromium-review.googlesource.com/1157199
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarBernhard Bauer <bauerb@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#581382}
parent c9eed774
......@@ -2585,6 +2585,8 @@ jumbo_split_static_library("browser") {
"lifetime/browser_close_manager.h",
"lifetime/termination_notification.cc",
"lifetime/termination_notification.h",
"media/unified_autoplay_config.cc",
"media/unified_autoplay_config.h",
"media/webrtc/tab_desktop_media_list.cc",
"media/webrtc/tab_desktop_media_list.h",
"media_galleries/chromeos/mtp_device_delegate_impl_chromeos.cc",
......
......@@ -367,6 +367,7 @@
#if !defined(OS_ANDROID)
#include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/media/unified_autoplay_config.h"
#include "chrome/browser/payments/payment_request_factory.h"
#include "chrome/browser/search/instant_service.h"
#include "chrome/browser/search/instant_service_factory.h"
......@@ -3113,11 +3114,21 @@ void ChromeContentBrowserClient::OverrideWebkitPrefs(
}
#if !defined(OS_ANDROID)
// If autoplay is allowed by policy then update the autoplay policy in web
// preferences.
if (IsAutoplayAllowedByPolicy(contents, prefs)) {
// If autoplay is allowed by policy then force the no user gesture required
// autoplay policy.
web_prefs->autoplay_policy =
content::AutoplayPolicy::kNoUserGestureRequired;
} else if (base::FeatureList::IsEnabled(media::kAutoplaySoundSettings) &&
web_prefs->autoplay_policy ==
content::AutoplayPolicy::kDocumentUserActivationRequired) {
// If the autoplay sound settings feature is enabled and the autoplay policy
// is set to using the unified policy then set the default autoplay policy
// based on user preference.
web_prefs->autoplay_policy =
UnifiedAutoplayConfig::ShouldBlockAutoplay(profile)
? content::AutoplayPolicy::kDocumentUserActivationRequired
: content::AutoplayPolicy::kNoUserGestureRequired;
}
#endif // !defined(OS_ANDROID)
......
......@@ -8,9 +8,12 @@
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/prefs/pref_service.h"
#include "components/ukm/content/source_url_recorder.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/url_constants.h"
#include "services/metrics/public/cpp/ukm_builders.h"
......@@ -23,9 +26,20 @@ SoundContentSettingObserver::SoundContentSettingObserver(
: content::WebContentsObserver(contents),
logged_site_muted_ukm_(false),
observer_(this) {
host_content_settings_map_ = HostContentSettingsMapFactory::GetForProfile(
Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
Profile* profile =
Profile::FromBrowserContext(web_contents()->GetBrowserContext());
host_content_settings_map_ =
HostContentSettingsMapFactory::GetForProfile(profile);
observer_.Add(host_content_settings_map_);
#if !defined(OS_ANDROID)
// Listen to changes of the block autoplay pref.
pref_change_registrar_.Init(profile->GetPrefs());
pref_change_registrar_.Add(
prefs::kBlockAutoplayEnabled,
base::BindRepeating(&SoundContentSettingObserver::UpdateAutoplayPolicy,
base::Unretained(this)));
#endif
}
SoundContentSettingObserver::~SoundContentSettingObserver() = default;
......@@ -48,10 +62,19 @@ void SoundContentSettingObserver::OnContentSettingChanged(
const ContentSettingsPattern& secondary_pattern,
ContentSettingsType content_type,
const std::string& resource_identifier) {
if (content_type == CONTENT_SETTINGS_TYPE_SOUND) {
MuteOrUnmuteIfNecessary();
CheckSoundBlocked(web_contents()->IsCurrentlyAudible());
if (content_type != CONTENT_SETTINGS_TYPE_SOUND)
return;
#if !defined(OS_ANDROID)
if (primary_pattern == ContentSettingsPattern() &&
secondary_pattern == ContentSettingsPattern() &&
resource_identifier.empty()) {
UpdateAutoplayPolicy();
}
#endif
MuteOrUnmuteIfNecessary();
CheckSoundBlocked(web_contents()->IsCurrentlyAudible());
}
void SoundContentSettingObserver::MuteOrUnmuteIfNecessary() {
......@@ -137,3 +160,10 @@ SoundContentSettingObserver::GetSiteMutedReason() {
}
return MuteReason::kSiteException;
}
#if !defined(OS_ANDROID)
void SoundContentSettingObserver::UpdateAutoplayPolicy() {
// Force a WebkitPreferences update to update the autoplay policy.
web_contents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
}
#endif
......@@ -6,8 +6,10 @@
#define CHROME_BROWSER_CONTENT_SETTINGS_SOUND_CONTENT_SETTING_OBSERVER_H_
#include "base/scoped_observer.h"
#include "build/build_config.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/prefs/pref_change_registrar.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
......@@ -55,6 +57,14 @@ class SoundContentSettingObserver
// Determine the reason why audio was blocked on the page.
MuteReason GetSiteMutedReason();
#if !defined(OS_ANDROID)
// Update the autoplay policy on the attached |WebContents|.
void UpdateAutoplayPolicy();
// Manages registration of pref change observers.
PrefChangeRegistrar pref_change_registrar_;
#endif
// True if we have already logged a SiteMuted UKM event since last navigation.
bool logged_site_muted_ukm_;
......
......@@ -10,6 +10,10 @@ per-file cast_*=xjz@chromium.org
per-file media_engagement*=beccahughes@chromium.org
per-file media_engagement*=mlamouri@chromium.org
# For Unified Autoplay
per-file unified_autoplay*=beccahughes@chromium.org
per-file unified_autoplay*=mlamouri@chromium.org
# For IPC security review
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/unified_autoplay_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
// static
void UnifiedAutoplayConfig::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(prefs::kBlockAutoplayEnabled, true);
}
// static
bool UnifiedAutoplayConfig::ShouldBlockAutoplay(Profile* profile) {
HostContentSettingsMap* settings_map =
HostContentSettingsMapFactory::GetForProfile(profile);
if (settings_map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_SOUND,
nullptr) == CONTENT_SETTING_BLOCK) {
return true;
}
return profile->GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled);
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_UNIFIED_AUTOPLAY_CONFIG_H_
#define CHROME_BROWSER_MEDIA_UNIFIED_AUTOPLAY_CONFIG_H_
#include "base/macros.h"
class Profile;
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
class UnifiedAutoplayConfig {
public:
// Register profile prefs in the pref registry.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable*);
// Checks whether autoplay should be blocked by user preference. This will be
// true if the block autoplay pref is true and if the default sound content
// setting value is not block.
static bool ShouldBlockAutoplay(Profile*);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(UnifiedAutoplayConfig);
};
#endif // CHROME_BROWSER_MEDIA_UNIFIED_AUTOPLAY_CONFIG_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/unified_autoplay_config.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/content_settings/sound_content_setting_observer.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/prefs/pref_service.h"
#include "content/public/common/web_preferences.h"
#include "content/public/test/web_contents_tester.h"
#include "media/base/media_switches.h"
// Unit tests for the unified autoplay policy with the unified sound settings
// UI enabled.
class UnifiedAutoplaySoundSettingsTest
: public ChromeRenderViewHostTestHarness {
public:
~UnifiedAutoplaySoundSettingsTest() override = default;
void SetUp() override {
scoped_feature_list_.InitAndEnableFeature(media::kAutoplaySoundSettings);
ChromeRenderViewHostTestHarness::SetUp();
SoundContentSettingObserver::CreateForWebContents(web_contents());
}
void SetSoundContentSettingDefault(ContentSetting value) {
HostContentSettingsMap* content_settings =
HostContentSettingsMapFactory::GetForProfile(profile());
content_settings->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_SOUND,
value);
}
void SetAutoplayPrefValue(bool value) {
GetPrefs()->SetBoolean(prefs::kBlockAutoplayEnabled, value);
EXPECT_EQ(value, GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled));
}
bool ShouldBlockAutoplay() {
return UnifiedAutoplayConfig::ShouldBlockAutoplay(profile());
}
content::AutoplayPolicy GetAppliedAutoplayPolicy() {
return web_contents()
->GetRenderViewHost()
->GetWebkitPreferences()
.autoplay_policy;
}
void NavigateToTestPage() {
content::WebContentsTester::For(web_contents())
->NavigateAndCommit(GURL("https://first.example.com"));
}
private:
PrefService* GetPrefs() { return profile()->GetPrefs(); }
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(UnifiedAutoplaySoundSettingsTest, ContentSetting_Allow) {
SetSoundContentSettingDefault(CONTENT_SETTING_ALLOW);
SetAutoplayPrefValue(false);
EXPECT_FALSE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kNoUserGestureRequired,
GetAppliedAutoplayPolicy());
}
TEST_F(UnifiedAutoplaySoundSettingsTest, ContentSetting_Block) {
SetSoundContentSettingDefault(CONTENT_SETTING_BLOCK);
SetAutoplayPrefValue(false);
EXPECT_TRUE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kDocumentUserActivationRequired,
GetAppliedAutoplayPolicy());
// Set back to ALLOW to ensure that the policy is updated on the next
// navigation.
SetSoundContentSettingDefault(CONTENT_SETTING_ALLOW);
EXPECT_FALSE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kNoUserGestureRequired,
GetAppliedAutoplayPolicy());
}
TEST_F(UnifiedAutoplaySoundSettingsTest, Feature_DisabledNoop) {
// Explicitly disable the feature.
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures({}, {media::kAutoplaySoundSettings});
SetAutoplayPrefValue(false);
EXPECT_FALSE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kDocumentUserActivationRequired,
GetAppliedAutoplayPolicy());
}
TEST_F(UnifiedAutoplaySoundSettingsTest, Pref_DefaultEnabled) {
EXPECT_TRUE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kDocumentUserActivationRequired,
GetAppliedAutoplayPolicy());
}
TEST_F(UnifiedAutoplaySoundSettingsTest, Pref_Disabled) {
SetAutoplayPrefValue(false);
EXPECT_FALSE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kNoUserGestureRequired,
GetAppliedAutoplayPolicy());
// Now update the pref and make sure we apply it on the next navigation.
SetAutoplayPrefValue(true);
EXPECT_TRUE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kDocumentUserActivationRequired,
GetAppliedAutoplayPolicy());
}
// Unit tests for the unified autoplay policy with the unified sound settings
// UI enabled and a custom autoplay policy command line switch.
class UnifiedAutoplaySoundSettingsOverrideTest
: public UnifiedAutoplaySoundSettingsTest {
public:
~UnifiedAutoplaySoundSettingsOverrideTest() override = default;
void SetUp() override {
scoped_command_line_.GetProcessCommandLine()->AppendSwitchASCII(
switches::kAutoplayPolicy,
switches::autoplay::kUserGestureRequiredPolicy);
UnifiedAutoplaySoundSettingsTest::SetUp();
}
private:
base::test::ScopedCommandLine scoped_command_line_;
};
TEST_F(UnifiedAutoplaySoundSettingsOverrideTest, CommandLineOverride) {
EXPECT_TRUE(ShouldBlockAutoplay());
NavigateToTestPage();
EXPECT_EQ(content::AutoplayPolicy::kUserGestureRequired,
GetAppliedAutoplayPolicy());
}
......@@ -316,6 +316,7 @@
#endif
#if !defined(OS_ANDROID)
#include "chrome/browser/media/unified_autoplay_config.h"
#include "components/ntp_tiles/custom_links_manager_impl.h"
#endif
......@@ -740,6 +741,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
confirm_quit::RegisterLocalState(registry);
#endif
#if !defined(OS_ANDROID)
UnifiedAutoplayConfig::RegisterProfilePrefs(registry);
#endif
RegisterProfilePrefsForMigration(registry);
}
......
......@@ -2990,6 +2990,7 @@ test("unit_tests") {
"../browser/media/router/discovery/discovery_network_list_unittest.cc",
"../browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc",
"../browser/media/router/discovery/discovery_network_monitor_unittest.cc",
"../browser/media/unified_autoplay_config_unittest.cc",
"../browser/media/webrtc/tab_desktop_media_list_unittest.cc",
"../browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc",
"../browser/media/webrtc/webrtc_event_log_manager_unittest.cc",
......
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