blob: 6d73bb89dbdd8eda62cbc1d42a20a941c0020959 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/content_settings/core/browser/content_settings_pref_provider.h"
#include <memory>
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/test/simple_test_clock.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/content_settings_mock_observer.h"
#include "components/content_settings/core/browser/content_settings_observable_provider.h"
#include "components/content_settings/core/browser/content_settings_pref.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
#include "components/content_settings/core/browser/website_settings_info.h"
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_constraints.h"
#include "components/content_settings/core/common/content_settings_metadata.h"
#include "components/content_settings/core/common/content_settings_partition_key.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/test/content_settings_test_utils.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/default_pref_store.h"
#include "components/prefs/overlay_user_pref_store.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_store.h"
#include "components/sync_preferences/pref_service_mock_factory.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "ppapi/buildflags/buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using ::testing::_;
namespace content_settings {
class DeadlockCheckerThread : public base::PlatformThread::Delegate {
public:
explicit DeadlockCheckerThread(const ContentSettingsPref* pref)
: pref_(pref) {}
DeadlockCheckerThread(const DeadlockCheckerThread&) = delete;
DeadlockCheckerThread& operator=(const DeadlockCheckerThread&) = delete;
void ThreadMain() override { EXPECT_TRUE(pref_->TryLockForTesting()); }
private:
raw_ptr<const ContentSettingsPref> pref_;
};
// A helper for observing an preference changes and testing whether
// |PrefProvider| holds a lock when the preferences change.
class DeadlockCheckerObserver {
public:
// |DeadlockCheckerObserver| doesn't take the ownership of |prefs| or
// |provider|.
DeadlockCheckerObserver(PrefService* prefs, PrefProvider* provider)
: provider_(provider), notification_received_(false) {
pref_change_registrar_.Init(prefs);
WebsiteSettingsRegistry* registry = WebsiteSettingsRegistry::GetInstance();
for (const auto& pair : provider_->content_settings_prefs_) {
const ContentSettingsPref* pref = pair.second.get();
pref_change_registrar_.Add(
registry->Get(pair.first)->pref_name(),
base::BindRepeating(
&DeadlockCheckerObserver::OnContentSettingsPatternPairsChanged,
base::Unretained(this), base::Unretained(pref)));
}
}
DeadlockCheckerObserver(const DeadlockCheckerObserver&) = delete;
DeadlockCheckerObserver& operator=(const DeadlockCheckerObserver&) = delete;
virtual ~DeadlockCheckerObserver() = default;
bool notification_received() const { return notification_received_; }
private:
void OnContentSettingsPatternPairsChanged(const ContentSettingsPref* pref) {
// Check whether |provider_| holds its lock. For this, we need a
// separate thread.
DeadlockCheckerThread thread(pref);
base::PlatformThreadHandle handle;
ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle));
base::PlatformThread::Join(handle);
notification_received_ = true;
}
raw_ptr<PrefProvider> provider_;
PrefChangeRegistrar pref_change_registrar_;
bool notification_received_;
};
class PrefProviderTest : public testing::Test {
public:
PrefProviderTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
// Ensure all content settings are initialized.
ContentSettingsRegistry::GetInstance();
}
void FastForwardTime(base::TimeDelta delta) {
task_environment_.FastForwardBy(delta);
}
private:
content::BrowserTaskEnvironment task_environment_;
};
TEST_F(PrefProviderTest, Observer) {
TestingProfile profile;
PrefProvider pref_content_settings_provider(profile.GetPrefs(),
/*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
ContentSettingsPattern pattern =
ContentSettingsPattern::FromString("[*.]example.com");
MockObserver mock_observer;
EXPECT_CALL(mock_observer, OnContentSettingChanged(
pattern, ContentSettingsPattern::Wildcard(),
ContentSettingsType::COOKIES));
pref_content_settings_provider.AddObserver(&mock_observer);
pref_content_settings_provider.SetWebsiteSetting(
pattern, ContentSettingsPattern::Wildcard(), ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_ALLOW), {},
content_settings::PartitionKey::GetDefaultForTesting());
pref_content_settings_provider.ShutdownOnUIThread();
}
// Tests that obsolete content settings are cleared.
TEST_F(PrefProviderTest, DiscardObsoletePreferences) {
#if !BUILDFLAG(IS_ANDROID)
const char kObsoleteInstalledWebAppMetadataExceptionsPref[] =
"profile.content_settings.exceptions.installed_web_app_metadata";
#endif
static const char kGeolocationPrefPath[] =
"profile.content_settings.exceptions.geolocation";
static const char kGetDisplayMediaSetSelectAllScreensAllowedForUrlsPref[] =
"profile.content_settings.exceptions.get_display_media_set_select_all_"
"screens";
static const char kPattern[] = "[*.]example.com";
TestingProfile profile;
PrefService* prefs = profile.GetPrefs();
// Set some pref data. Each content setting type has the following value:
// {"[*.]example.com": {"setting": 1}}
base::Value::Dict plugins_data_pref;
constexpr char kFlagKey[] = "flashPreviouslyChanged";
plugins_data_pref.Set(kFlagKey, base::Value::Dict());
base::Value::Dict data_for_pattern;
data_for_pattern.Set("setting", static_cast<int>(CONTENT_SETTING_ALLOW));
base::Value::Dict pref_data;
base::Value::List pref_list;
pref_data.Set(kPattern, std::move(data_for_pattern));
#if !BUILDFLAG(IS_ANDROID)
prefs->SetDict(kObsoleteInstalledWebAppMetadataExceptionsPref,
pref_data.Clone());
#endif
prefs->SetDict(kGeolocationPrefPath, std::move(pref_data));
prefs->SetList(kGetDisplayMediaSetSelectAllScreensAllowedForUrlsPref,
std::move(pref_list));
// Instantiate a new PrefProvider here, because we want to test the
// constructor's behavior after setting the above.
PrefProvider provider(prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
provider.ShutdownOnUIThread();
#if !BUILDFLAG(IS_ANDROID)
EXPECT_FALSE(
prefs->HasPrefPath(kObsoleteInstalledWebAppMetadataExceptionsPref));
#endif
EXPECT_FALSE(prefs->HasPrefPath(
kGetDisplayMediaSetSelectAllScreensAllowedForUrlsPref));
EXPECT_TRUE(prefs->HasPrefPath(kGeolocationPrefPath));
GURL primary_url("http://example.com/");
EXPECT_EQ(
CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::GEOLOCATION, false));
}
// Test for regression in which the PrefProvider modified the user pref store
// of the OTR unintentionally: http://crbug.com/74466.
TEST_F(PrefProviderTest, Incognito) {
PersistentPrefStore* user_prefs = new TestingPrefStore();
OverlayUserPrefStore* otr_user_prefs = new OverlayUserPrefStore(user_prefs);
sync_preferences::PrefServiceMockFactory factory;
factory.set_user_prefs(base::WrapRefCounted(user_prefs));
scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
new user_prefs::PrefRegistrySyncable);
sync_preferences::PrefServiceSyncable* regular_prefs =
factory.CreateSyncable(registry.get()).release();
RegisterUserProfilePrefs(registry.get());
sync_preferences::PrefServiceMockFactory otr_factory;
otr_factory.set_user_prefs(base::WrapRefCounted(otr_user_prefs));
scoped_refptr<user_prefs::PrefRegistrySyncable> otr_registry(
new user_prefs::PrefRegistrySyncable);
sync_preferences::PrefServiceSyncable* otr_prefs =
otr_factory.CreateSyncable(otr_registry.get()).release();
RegisterUserProfilePrefs(otr_registry.get());
TestingProfile::Builder profile_builder;
profile_builder.SetPrefService(base::WrapUnique(regular_prefs));
std::unique_ptr<TestingProfile> profile = profile_builder.Build();
TestingProfile::Builder otr_profile_builder;
otr_profile_builder.SetPrefService(base::WrapUnique(otr_prefs));
otr_profile_builder.BuildIncognito(profile.get());
PrefProvider pref_content_settings_provider(
regular_prefs, /*off_the_record=*/false, /*store_last_modified=*/true,
/*restore_session=*/false);
PrefProvider pref_content_settings_provider_incognito(
otr_prefs, true /*off_the_record=*/, /*store_last_modified=*/true,
/*restore_session=*/false);
ContentSettingsPattern pattern =
ContentSettingsPattern::FromString("[*.]example.com");
pref_content_settings_provider.SetWebsiteSetting(
pattern, pattern, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_ALLOW), {},
content_settings::PartitionKey::GetDefaultForTesting());
GURL host("http://example.com/");
// The value should of course be visible in the regular PrefProvider.
EXPECT_EQ(
CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&pref_content_settings_provider, host, host,
ContentSettingsType::COOKIES, false));
// And also in the OTR version.
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(
&pref_content_settings_provider_incognito, host, host,
ContentSettingsType::COOKIES, false));
const WebsiteSettingsInfo* info =
WebsiteSettingsRegistry::GetInstance()->Get(ContentSettingsType::COOKIES);
// But the value should not be overridden in the OTR user prefs accidentally.
EXPECT_FALSE(otr_user_prefs->IsSetInOverlay(info->pref_name()));
pref_content_settings_provider.ShutdownOnUIThread();
pref_content_settings_provider_incognito.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, GetContentSettingsValue) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
EXPECT_EQ(CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::COOKIES, false));
EXPECT_EQ(base::Value(), TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url,
ContentSettingsType::COOKIES, false));
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_BLOCK), {},
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::COOKIES, false));
base::Value value = TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url, ContentSettingsType::COOKIES, false);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
IntToContentSetting(value.GetIfInt().value_or(-1)));
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::COOKIES,
base::Value(), {},
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(base::Value(), TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url,
ContentSettingsType::COOKIES, false));
provider.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, Patterns) {
TestingProfile testing_profile;
PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(),
/*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL host1("http://example.com/");
GURL host2("http://www.example.com/");
GURL host3("http://example.org/");
GURL host4("file:///tmp/test.html");
ContentSettingsPattern pattern1 =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingsPattern pattern2 =
ContentSettingsPattern::FromString("example.org");
ContentSettingsPattern pattern3 =
ContentSettingsPattern::FromString("file:///tmp/test.html");
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&pref_content_settings_provider, host1,
host1, ContentSettingsType::COOKIES, false));
pref_content_settings_provider.SetWebsiteSetting(
pattern1, pattern1, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_BLOCK), {},
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&pref_content_settings_provider, host1,
host1, ContentSettingsType::COOKIES, false));
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&pref_content_settings_provider, host2,
host2, ContentSettingsType::COOKIES, false));
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&pref_content_settings_provider, host3,
host3, ContentSettingsType::COOKIES, false));
pref_content_settings_provider.SetWebsiteSetting(
pattern2, pattern2, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_BLOCK), {},
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&pref_content_settings_provider, host3,
host3, ContentSettingsType::COOKIES, false));
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&pref_content_settings_provider, host4,
host4, ContentSettingsType::COOKIES, false));
pref_content_settings_provider.SetWebsiteSetting(
pattern3, pattern3, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_BLOCK), {},
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&pref_content_settings_provider, host4,
host4, ContentSettingsType::COOKIES, false));
pref_content_settings_provider.ShutdownOnUIThread();
}
// http://crosbug.com/17760
TEST_F(PrefProviderTest, Deadlock) {
sync_preferences::TestingPrefServiceSyncable prefs;
PrefProvider::RegisterProfilePrefs(prefs.registry());
// Chain of events: a preference changes, |PrefProvider| notices it, and reads
// and writes the preference. When the preference is written, a notification
// is sent, and this used to happen when |PrefProvider| was still holding its
// lock.
const WebsiteSettingsInfo* info =
WebsiteSettingsRegistry::GetInstance()->Get(ContentSettingsType::COOKIES);
PrefProvider provider(&prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
DeadlockCheckerObserver observer(&prefs, &provider);
{
ScopedDictPrefUpdate update(&prefs, info->pref_name());
base::Value::Dict& mutable_settings = update.Get();
mutable_settings.Set("www.example.com,*",
base::Value(base::Value::Type::DICT));
}
EXPECT_TRUE(observer.notification_received());
provider.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, IncognitoInheritsValueMap) {
sync_preferences::TestingPrefServiceSyncable prefs;
PrefProvider::RegisterProfilePrefs(prefs.registry());
ContentSettingsPattern pattern_1 =
ContentSettingsPattern::FromString("google.com");
ContentSettingsPattern pattern_2 =
ContentSettingsPattern::FromString("www.google.com");
ContentSettingsPattern pattern_3 =
ContentSettingsPattern::FromString("example.com");
ContentSettingsPattern pattern_4 =
ContentSettingsPattern::FromString("foo.com");
ContentSettingsPattern pattern_5 =
ContentSettingsPattern::FromString("bar.com");
ContentSettingsPattern wildcard = ContentSettingsPattern::FromString("*");
// Create a normal provider and set a setting.
PrefProvider normal_provider(&prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
{
ContentSettingConstraints constraints;
constraints.set_session_model(mojom::SessionModel::USER_SESSION);
normal_provider.SetWebsiteSetting(
pattern_1, wildcard, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_ALLOW), {},
content_settings::PartitionKey::GetDefaultForTesting());
normal_provider.SetWebsiteSetting(
pattern_3, pattern_3, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
}
{
// Durable and not expired
ContentSettingConstraints constraints;
constraints.set_lifetime(base::Days(1));
constraints.set_session_model(mojom::SessionModel::DURABLE);
normal_provider.SetWebsiteSetting(
pattern_4, pattern_4, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
}
{
// Durable but expired
ContentSettingConstraints constraints(base::Time::Now() - base::Days(2));
constraints.set_lifetime(base::Days(1));
constraints.set_session_model(mojom::SessionModel::DURABLE);
normal_provider.SetWebsiteSetting(
pattern_5, pattern_5, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
}
// Non-OTR provider, Non-OTR iterator has one setting (pattern 1) using
// default params and one scoped to a UserSession lifetime model.
{
std::unique_ptr<RuleIterator> it(normal_provider.GetRuleIterator(
ContentSettingsType::COOKIES, false,
content_settings::PartitionKey::GetDefaultForTesting()));
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_5, it->Next()->primary_pattern);
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_3, it->Next()->primary_pattern);
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_4, it->Next()->primary_pattern);
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_1, it->Next()->primary_pattern);
EXPECT_FALSE(it->HasNext());
}
// Non-OTR provider, OTR iterator has no settings.
{
std::unique_ptr<RuleIterator> it(normal_provider.GetRuleIterator(
ContentSettingsType::COOKIES, true,
content_settings::PartitionKey::GetDefaultForTesting()));
EXPECT_FALSE(it);
}
// Create an incognito provider and set a setting.
PrefProvider incognito_provider(&prefs, true /* incognito */,
/*store_last_modified=*/true,
/*restore_session=*/false);
incognito_provider.SetWebsiteSetting(
pattern_2, wildcard, ContentSettingsType::COOKIES,
base::Value(CONTENT_SETTING_ALLOW), {},
content_settings::PartitionKey::GetDefaultForTesting());
// OTR provider, non-OTR iterator has two settings (pattern 1/3).
{
std::unique_ptr<RuleIterator> it(incognito_provider.GetRuleIterator(
ContentSettingsType::COOKIES, false,
content_settings::PartitionKey::GetDefaultForTesting()));
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_3, it->Next()->primary_pattern);
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_4, it->Next()->primary_pattern);
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_1, it->Next()->primary_pattern);
EXPECT_FALSE(it->HasNext());
}
// OTR provider, OTR iterator has one setting (pattern 2).
{
std::unique_ptr<RuleIterator> it(incognito_provider.GetRuleIterator(
ContentSettingsType::COOKIES, true,
content_settings::PartitionKey::GetDefaultForTesting()));
EXPECT_TRUE(it->HasNext());
EXPECT_EQ(pattern_2, it->Next()->primary_pattern);
EXPECT_FALSE(it->HasNext());
}
incognito_provider.ShutdownOnUIThread();
normal_provider.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, ClearAllContentSettingsRules) {
sync_preferences::TestingPrefServiceSyncable prefs;
PrefProvider::RegisterProfilePrefs(prefs.registry());
ContentSettingsPattern pattern =
ContentSettingsPattern::FromString("google.com");
ContentSettingsPattern wildcard = ContentSettingsPattern::FromString("*");
base::Value value(CONTENT_SETTING_ALLOW);
PrefProvider provider(&prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
// Non-empty pattern, syncable, empty resource identifier.
provider.SetWebsiteSetting(
pattern, wildcard, ContentSettingsType::JAVASCRIPT,
value.Clone(), {},
content_settings::PartitionKey::GetDefaultForTesting());
// Non-empty pattern, non-syncable, empty resource identifier.
provider.SetWebsiteSetting(
pattern, wildcard, ContentSettingsType::GEOLOCATION, value.Clone(), {},
content_settings::PartitionKey::GetDefaultForTesting());
// Non-empty pattern, syncable, empty resource identifier.
provider.SetWebsiteSetting(
pattern, wildcard, ContentSettingsType::COOKIES,
value.Clone(), {},
content_settings::PartitionKey::GetDefaultForTesting());
// Non-empty pattern, non-syncable, empty resource identifier.
provider.SetWebsiteSetting(
pattern, wildcard, ContentSettingsType::NOTIFICATIONS, value.Clone(), {},
content_settings::PartitionKey::GetDefaultForTesting());
// Test that the preferences for images, geolocation and plugins get cleared.
WebsiteSettingsRegistry* registry = WebsiteSettingsRegistry::GetInstance();
const char* cleared_prefs[] = {
registry->Get(ContentSettingsType::JAVASCRIPT)->pref_name().c_str(),
registry->Get(ContentSettingsType::GEOLOCATION)->pref_name().c_str(),
};
// Expect the prefs are not empty before we trigger clearing them.
for (const char* pref : cleared_prefs) {
const base::Value::Dict& dictionary = prefs.GetDict(pref);
ASSERT_FALSE(dictionary.empty());
}
provider.ClearAllContentSettingsRules(
ContentSettingsType::JAVASCRIPT,
content_settings::PartitionKey::GetDefaultForTesting());
provider.ClearAllContentSettingsRules(
ContentSettingsType::GEOLOCATION,
content_settings::PartitionKey::GetDefaultForTesting());
// Ensure they become empty afterwards.
for (const char* pref : cleared_prefs) {
const base::Value::Dict& dictionary = prefs.GetDict(pref);
EXPECT_TRUE(dictionary.empty());
}
// Test that the preferences for cookies and notifications are not empty.
const char* nonempty_prefs[] = {
registry->Get(ContentSettingsType::COOKIES)->pref_name().c_str(),
registry->Get(ContentSettingsType::NOTIFICATIONS)->pref_name().c_str(),
};
for (const char* pref : nonempty_prefs) {
const base::Value::Dict& dictionary = prefs.GetDict(pref);
EXPECT_EQ(1u, dictionary.size());
}
provider.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, LastModified) {
sync_preferences::TestingPrefServiceSyncable prefs;
PrefProvider::RegisterProfilePrefs(prefs.registry());
GURL url1("https://google.com");
GURL url2("https://www.google.com");
ContentSettingsPattern pattern_1 =
ContentSettingsPattern::FromString("google.com");
ContentSettingsPattern pattern_2 =
ContentSettingsPattern::FromString("www.google.com");
// Create a provider and set a few settings.
PrefProvider provider(&prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
base::SimpleTestClock test_clock;
test_clock.SetNow(base::Time::Now());
provider.SetClockForTesting(&test_clock);
base::Time t1 = test_clock.Now();
provider.SetWebsiteSetting(
pattern_1, ContentSettingsPattern::Wildcard(),
ContentSettingsType::COOKIES, base::Value(CONTENT_SETTING_ALLOW), {},
content_settings::PartitionKey::GetDefaultForTesting());
provider.SetWebsiteSetting(
pattern_2, ContentSettingsPattern::Wildcard(),
ContentSettingsType::COOKIES, base::Value(CONTENT_SETTING_ALLOW), {},
content_settings::PartitionKey::GetDefaultForTesting());
// Make sure that the timestamps for pattern_1 and patter_2 are before |t2|.
test_clock.Advance(base::Seconds(1));
base::Time t2 = test_clock.Now();
base::Time last_modified = TestUtils::GetLastModified(
&provider, url1, url1, ContentSettingsType::COOKIES);
EXPECT_EQ(t1, last_modified);
last_modified = TestUtils::GetLastModified(&provider, url2, url2,
ContentSettingsType::COOKIES);
EXPECT_EQ(t1, last_modified);
// A change for pattern_1, which will update the last_modified timestamp.
;
provider.SetWebsiteSetting(
pattern_1, ContentSettingsPattern::Wildcard(),
ContentSettingsType::COOKIES, base::Value(CONTENT_SETTING_BLOCK), {},
content_settings::PartitionKey::GetDefaultForTesting());
last_modified = TestUtils::GetLastModified(&provider, url1, url1,
ContentSettingsType::COOKIES);
EXPECT_EQ(t2, last_modified);
// The timestamp of pattern_2 shouldn't change.
last_modified = TestUtils::GetLastModified(&provider, url2, url2,
ContentSettingsType::COOKIES);
EXPECT_EQ(t1, last_modified);
provider.ShutdownOnUIThread();
// Ensure the timestamps survive roundtrip through a provider reload properly.
PrefProvider provider2(&prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
last_modified = TestUtils::GetLastModified(&provider, url1, url1,
ContentSettingsType::COOKIES);
EXPECT_EQ(t2, last_modified);
// The timestamp of pattern_2 shouldn't change.
last_modified = TestUtils::GetLastModified(&provider, url2, url2,
ContentSettingsType::COOKIES);
EXPECT_EQ(t1, last_modified);
provider2.ShutdownOnUIThread();
}
// If a setting is constrained to a session scope it should only persist in
// memory.
TEST_F(PrefProviderTest, SessionScopeSettingsDontPersist) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
ContentSettingConstraints constraints;
constraints.set_session_model(mojom::SessionModel::USER_SESSION);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
base::Value value = TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
false);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
IntToContentSetting(value.GetIfInt().value_or(-1)));
// Now if we create a new provider, it should not be able to read our setting
// back.
provider.ShutdownOnUIThread();
PrefProvider provider2(testing_profile.GetPrefs(),
/*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider2.ShutdownOnUIThread();
}
// If a setting is constrained to a session scope and a provider is made with
// the `restore_Session` flag, the setting should not be cleared.
TEST_F(PrefProviderTest, SessionScopeSettingsRestoreSession) {
sync_preferences::TestingPrefServiceSyncable prefs;
PrefProvider::RegisterProfilePrefs(prefs.registry());
// Create a normal provider and set a setting.
PrefProvider provider(&prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
ContentSettingConstraints constraints;
constraints.set_session_model(mojom::SessionModel::USER_SESSION);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
base::Value value(TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
false));
EXPECT_EQ(CONTENT_SETTING_BLOCK,
IntToContentSetting(value.GetIfInt().value_or(-1)));
// Now if we create a new provider, it should be able to read our setting
// back.
provider.ShutdownOnUIThread();
PrefProvider provider2(&prefs, /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/true);
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider2.ShutdownOnUIThread();
}
// If a setting is constrained to a non-restorable session scope and a provider
// is made with the `restore_Session` flag, the setting should be cleared.
TEST_F(PrefProviderTest, SessionScopeSettingsRestoreSessionNonRestorable) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
ContentSettingConstraints constraints;
constraints.set_session_model(
mojom::SessionModel::NON_RESTORABLE_USER_SESSION);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
base::Value value(TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
false));
EXPECT_EQ(CONTENT_SETTING_BLOCK,
IntToContentSetting(value.GetIfInt().value_or(-1)));
// Now if we create a new provider, it should not be able to read our setting
// back even with `restore_session` is true.
provider.ShutdownOnUIThread();
PrefProvider provider2(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/true);
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider2.ShutdownOnUIThread();
}
// Validate our settings will properly store our expiry time if specified.
TEST_F(PrefProviderTest, GetContentSettingsExpiry) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_lifetime(base::Seconds(123));
constraints.set_session_model(mojom::SessionModel::DURABLE);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
base::Value value = TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
false);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
IntToContentSetting(value.GetIfInt().value_or(-1)));
// Now if we skip ahead our time our setting should be expired and no longer
// valid.
FastForwardTime(base::Seconds(200));
EXPECT_EQ(base::Value(), TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider.ShutdownOnUIThread();
}
// Any specified expiry time should persist in our prefs and outlive a restart.
TEST_F(PrefProviderTest, GetContentSettingsExpiryPersists) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_lifetime(base::Seconds(123));
constraints.set_session_model(mojom::SessionModel::DURABLE);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
base::Value value = TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
false);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
IntToContentSetting(value.GetIfInt().value_or(-1)));
// Shutdown our provider and we should still have a setting present.
provider.ShutdownOnUIThread();
PrefProvider provider2(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
// Now if we skip ahead our time our setting should be expired and no longer
// valid.
FastForwardTime(base::Seconds(200));
EXPECT_EQ(base::Value(), TestUtils::GetContentSettingValue(
&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider2.ShutdownOnUIThread();
}
// Any specified expiry time should persist in our prefs and outlive a restart.
TEST_F(PrefProviderTest, GetContentSettingsExpiryAfterRestore) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_lifetime(base::Seconds(123));
constraints.set_session_model(mojom::SessionModel::DURABLE);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
base::Value value = TestUtils::GetContentSettingValue(
&provider, primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
false);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
IntToContentSetting(value.GetIfInt().value_or(-1)));
provider.ShutdownOnUIThread();
PrefProvider provider2(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/true);
// Now if we skip ahead our time our setting should be expired and no longer
// valid.
FastForwardTime(base::Seconds(200));
EXPECT_EQ(base::Value(), TestUtils::GetContentSettingValue(
&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider2.ShutdownOnUIThread();
}
// If we update a setting and change the scope from Session to Durable it
// should persist in the same way as an original Durable scoped setting.
TEST_F(PrefProviderTest, ScopeSessionToDurablePersists) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_session_model(mojom::SessionModel::USER_SESSION);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
// Update to Durable and expect that the setting is still there.
constraints.set_session_model(mojom::SessionModel::DURABLE);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
// Shutdown our provider and we should still have a setting present.
provider.ShutdownOnUIThread();
PrefProvider provider2(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider2.ShutdownOnUIThread();
}
// If we update a setting and change the scope from Durable to Session it
// should drop in the same way as an original Session scoped setting would.
TEST_F(PrefProviderTest, ScopeDurableToSessionDrops) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_session_model(mojom::SessionModel::DURABLE);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
// Update to Durable and expect that the setting is still there.
constraints.set_session_model(mojom::SessionModel::USER_SESSION);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_BLOCK), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
// Shutdown our provider and we should still have a setting present.
provider.ShutdownOnUIThread();
PrefProvider provider2(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
TestUtils::GetContentSetting(&provider2, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS, false));
provider2.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, LastVisitedTimeIsTracked) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
base::SimpleTestClock clock;
clock.SetNow(base::Time::Now());
provider.SetClockForTesting(&clock);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_track_last_visit_for_autoexpiration(false);
// Set one setting with track_last_visit_for_autoexpiration enabled and one
// disabled.
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::MEDIASTREAM_CAMERA,
base::Value(CONTENT_SETTING_ALLOW), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
constraints.set_track_last_visit_for_autoexpiration(true);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::GEOLOCATION,
base::Value(CONTENT_SETTING_ALLOW), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
RuleMetaData metadata;
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(
&provider, primary_url, primary_url,
ContentSettingsType::MEDIASTREAM_CAMERA, false, &metadata));
EXPECT_EQ(metadata.last_visited(), base::Time());
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::GEOLOCATION,
false, &metadata));
EXPECT_NE(metadata.last_visited(), base::Time());
EXPECT_GE(metadata.last_visited(), clock.Now() - base::Days(7));
EXPECT_LE(metadata.last_visited(), clock.Now());
provider.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, RenewContentSetting) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
base::SimpleTestClock clock;
clock.SetNow(base::Time::Now());
provider.SetClockForTesting(&clock);
GURL primary_url("https://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("https://[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_lifetime(base::Days(2));
ASSERT_TRUE(provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::STORAGE_ACCESS,
base::Value(CONTENT_SETTING_ALLOW), constraints,
content_settings::PartitionKey::GetDefaultForTesting()));
RuleMetaData metadata;
EXPECT_EQ(CONTENT_SETTING_ALLOW, TestUtils::GetContentSetting(
&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS,
/*include_incognito=*/false, &metadata));
EXPECT_EQ(metadata.lifetime(), base::Days(2));
EXPECT_EQ(metadata.expiration(), clock.Now() + base::Days(2));
clock.Advance(base::Days(1));
EXPECT_EQ(CONTENT_SETTING_ALLOW, TestUtils::GetContentSetting(
&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS,
/*include_incognito=*/false, &metadata));
EXPECT_EQ(metadata.lifetime(), base::Days(2));
EXPECT_EQ(metadata.expiration(), clock.Now() + base::Days(1));
// Wrong ContentSetting, doesn't match.
EXPECT_FALSE(provider.RenewContentSetting(
primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
CONTENT_SETTING_BLOCK, PartitionKey::GetDefaultForTesting()));
EXPECT_TRUE(provider.RenewContentSetting(
primary_url, primary_url, ContentSettingsType::STORAGE_ACCESS,
CONTENT_SETTING_ALLOW, PartitionKey::GetDefaultForTesting()));
EXPECT_EQ(CONTENT_SETTING_ALLOW, TestUtils::GetContentSetting(
&provider, primary_url, primary_url,
ContentSettingsType::STORAGE_ACCESS,
/*include_incognito=*/false, &metadata));
EXPECT_EQ(metadata.lifetime(), base::Days(2));
EXPECT_EQ(metadata.expiration(), clock.Now() + base::Days(2));
provider.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, LastVisitedTimeStoredOnDisk) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_track_last_visit_for_autoexpiration(true);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::GEOLOCATION,
base::Value(CONTENT_SETTING_ALLOW), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
RuleMetaData metadata;
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::GEOLOCATION,
false, &metadata));
EXPECT_NE(metadata.last_visited(), base::Time());
// Shutdown our provider and we should still have a setting present.
provider.ShutdownOnUIThread();
PrefProvider provider2(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
RuleMetaData metadata_from_disk;
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::GEOLOCATION,
false, &metadata_from_disk));
EXPECT_EQ(metadata.last_visited(), metadata_from_disk.last_visited());
provider2.ShutdownOnUIThread();
}
TEST_F(PrefProviderTest, LastVisitedTimeUpdating) {
TestingProfile testing_profile;
PrefProvider provider(testing_profile.GetPrefs(), /*off_the_record=*/false,
/*store_last_modified=*/true,
/*restore_session=*/false);
base::SimpleTestClock clock;
clock.SetNow(base::Time::Now());
provider.SetClockForTesting(&clock);
GURL primary_url("http://example.com/");
ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromString("[*.]example.com");
ContentSettingConstraints constraints;
constraints.set_track_last_visit_for_autoexpiration(true);
provider.SetWebsiteSetting(
primary_pattern, primary_pattern, ContentSettingsType::GEOLOCATION,
base::Value(CONTENT_SETTING_ALLOW), constraints,
content_settings::PartitionKey::GetDefaultForTesting());
RuleMetaData metadata;
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::GEOLOCATION,
false, &metadata));
EXPECT_GE(metadata.last_visited(), clock.Now() - base::Days(7));
EXPECT_LE(metadata.last_visited(), clock.Now());
clock.Advance(base::Days(20));
provider.UpdateLastVisitTime(primary_pattern, primary_pattern,
ContentSettingsType::GEOLOCATION,
PartitionKey::GetDefaultForTesting());
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::GEOLOCATION,
false, &metadata));
EXPECT_GE(metadata.last_visited(), clock.Now() - base::Days(7));
EXPECT_LE(metadata.last_visited(), clock.Now());
// Test resetting the last_visited time.
provider.ResetLastVisitTime(primary_pattern, primary_pattern,
ContentSettingsType::GEOLOCATION,
PartitionKey::GetDefaultForTesting());
EXPECT_EQ(CONTENT_SETTING_ALLOW,
TestUtils::GetContentSetting(&provider, primary_url, primary_url,
ContentSettingsType::GEOLOCATION,
false, &metadata));
EXPECT_EQ(metadata.last_visited(), base::Time());
provider.ShutdownOnUIThread();
}
} // namespace content_settings