blob: 8d765b17cbedb820474241340d12c784bf2e9eb0 [file] [log] [blame]
// Copyright 2020 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/ui/webui/settings/recent_site_settings_helper.h"
#include "base/test/simple_test_clock.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/permissions/permission_decision_auto_blocker.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace site_settings {
namespace {
ContentSetting kBlocked = ContentSetting::CONTENT_SETTING_BLOCK;
ContentSetting kAllowed = ContentSetting::CONTENT_SETTING_ALLOW;
ContentSetting kDefault = ContentSetting::CONTENT_SETTING_DEFAULT;
SiteSettingSource kEmbargo = site_settings::SiteSettingSource::kEmbargo;
SiteSettingSource kPreference = site_settings::SiteSettingSource::kPreference;
ContentSettingsType kNotifications = ContentSettingsType::NOTIFICATIONS;
ContentSettingsType kPlugins = ContentSettingsType::PLUGINS;
ContentSettingsType kPopups = ContentSettingsType::POPUPS;
ContentSettingsType kLocation = ContentSettingsType::GEOLOCATION;
} // namespace
class RecentSiteSettingsHelperTest : public testing::Test {
protected:
TestingProfile* profile() { return &profile_; }
TestingProfile* incognito_profile() { return incognito_profile_; }
base::SimpleTestClock* clock() { return &clock_; }
void CreateIncognitoProfile() {
incognito_profile_ = TestingProfile::Builder().BuildIncognito(profile());
}
private:
content::BrowserTaskEnvironment task_environment_;
base::SimpleTestClock clock_;
TestingProfile profile_;
TestingProfile* incognito_profile_;
};
TEST_F(RecentSiteSettingsHelperTest, IncognitoPermissionTimestamps) {
// Confirm our expectation that content settings prefs copied to the incognito
// profile have a timestamp of base::Time().
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(profile());
const GURL url("http://example.com");
const ContentSettingsPattern primary_pattern =
ContentSettingsPattern::FromURLNoWildcard(url);
const ContentSettingsPattern wildcard_pattern =
ContentSettingsPattern::Wildcard();
map->SetContentSettingDefaultScope(url, url, kNotifications, std::string(),
kBlocked);
CreateIncognitoProfile();
HostContentSettingsMap* incognito_map =
HostContentSettingsMapFactory::GetForProfile(incognito_profile());
EXPECT_NE(base::Time(),
map->GetSettingLastModifiedDate(primary_pattern, wildcard_pattern,
kNotifications));
EXPECT_EQ(base::Time(),
incognito_map->GetSettingLastModifiedDate(
primary_pattern, wildcard_pattern, kNotifications));
}
TEST_F(RecentSiteSettingsHelperTest, CheckRecentSitePermissions) {
const GURL url1("https://example.com");
const GURL url2("http://example.com");
std::vector<ContentSettingsType> content_types = {kNotifications, kPlugins,
kPopups, kLocation};
clock()->SetNow(base::Time::Now());
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(profile());
map->SetClockForTesting(clock());
auto* auto_blocker =
PermissionDecisionAutoBlockerFactory::GetForProfile(profile());
auto_blocker->SetClockForTesting(clock());
// Check that with default permissions nothing is returned.
auto recent_permissions =
GetRecentSitePermissions(profile(), content_types, 10);
EXPECT_EQ(0UL, recent_permissions.size());
// Add two permissions for different urls via different mechanisms and
// confirm they're returned correctly. Ensure that simply creating an
// ingocnito profile does not change recent permissions.
for (int i = 0; i < 3; ++i) {
auto_blocker->RecordDismissAndEmbargo(url1, kNotifications, false);
}
clock()->Advance(base::TimeDelta::FromHours(2));
map->SetContentSettingDefaultScope(url2, url2, kPlugins, std::string(),
kAllowed);
CreateIncognitoProfile();
recent_permissions = GetRecentSitePermissions(profile(), content_types, 10);
{
EXPECT_EQ(2UL, recent_permissions.size());
EXPECT_EQ(1UL, recent_permissions[0].settings.size());
EXPECT_EQ(1UL, recent_permissions[1].settings.size());
EXPECT_EQ(url1.spec(), recent_permissions[1].origin);
EXPECT_EQ(url2.spec(), recent_permissions[0].origin);
auto url1_permissions = recent_permissions[1].settings;
auto url2_permissions = recent_permissions[0].settings;
EXPECT_EQ(kNotifications, url1_permissions[0].content_type);
EXPECT_EQ(kBlocked, url1_permissions[0].content_setting);
EXPECT_EQ(kEmbargo, url1_permissions[0].setting_source);
EXPECT_EQ(kPlugins, url2_permissions[0].content_type);
EXPECT_EQ(kAllowed, url2_permissions[0].content_setting);
EXPECT_EQ(kPreference, url2_permissions[0].setting_source);
}
// Ensure incognito generated permissions are separated correctly.
clock()->Advance(base::TimeDelta::FromHours(1));
HostContentSettingsMap* incognito_map =
HostContentSettingsMapFactory::GetForProfile(incognito_profile());
incognito_map->SetClockForTesting(clock());
incognito_map->SetContentSettingDefaultScope(url1, url1, kPlugins,
std::string(), kAllowed);
clock()->Advance(base::TimeDelta::FromHours(1));
permissions::PermissionDecisionAutoBlocker* incognito_auto_blocker =
PermissionDecisionAutoBlockerFactory::GetForProfile(incognito_profile());
incognito_auto_blocker->SetClockForTesting(clock());
for (int i = 0; i < 3; ++i) {
incognito_auto_blocker->RecordDismissAndEmbargo(url1, kNotifications,
false);
}
recent_permissions = GetRecentSitePermissions(profile(), content_types, 10);
{
EXPECT_EQ(3UL, recent_permissions.size());
EXPECT_EQ(2UL, recent_permissions[0].settings.size());
EXPECT_EQ(1UL, recent_permissions[1].settings.size());
EXPECT_EQ(1UL, recent_permissions[2].settings.size());
EXPECT_EQ(url1.spec(), recent_permissions[2].origin);
EXPECT_EQ(url2.spec(), recent_permissions[1].origin);
EXPECT_EQ(url1.spec(), recent_permissions[0].origin);
EXPECT_TRUE(recent_permissions[0].incognito);
EXPECT_FALSE(recent_permissions[1].incognito);
EXPECT_FALSE(recent_permissions[2].incognito);
auto incognito_url1_permissions = recent_permissions[0].settings;
EXPECT_EQ(kNotifications, incognito_url1_permissions[0].content_type);
EXPECT_EQ(kBlocked, incognito_url1_permissions[0].content_setting);
EXPECT_EQ(kEmbargo, incognito_url1_permissions[0].setting_source);
EXPECT_EQ(kPlugins, incognito_url1_permissions[1].content_type);
EXPECT_EQ(kAllowed, incognito_url1_permissions[1].content_setting);
EXPECT_EQ(kPreference, incognito_url1_permissions[1].setting_source);
}
// Test additional permissions are correctly compacted down to the provided
// maximum number of sources and that order of origins is based on the
// most recent permission for that source.
const GURL url3("https://example.com:8443");
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url1, url1, kPlugins, std::string(),
kBlocked);
clock()->Advance(base::TimeDelta::FromHours(1));
for (int i = 0; i < 4; ++i) {
auto_blocker->RecordIgnoreAndEmbargo(url3, kNotifications, false);
}
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url2, url2, kPopups, std::string(),
kAllowed);
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url3, url3, kPopups, std::string(),
kBlocked);
recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
{
EXPECT_EQ(3UL, recent_permissions.size());
EXPECT_EQ(2UL, recent_permissions[0].settings.size());
EXPECT_EQ(1UL, recent_permissions[1].settings.size());
EXPECT_EQ(1UL, recent_permissions[2].settings.size());
EXPECT_EQ(url3.spec(), recent_permissions[0].origin);
EXPECT_EQ(url2.spec(), recent_permissions[1].origin);
EXPECT_EQ(url1.spec(), recent_permissions[2].origin);
// The oldest record will those for the inconito URL1, they should have
// been removed.
EXPECT_FALSE(recent_permissions[2].incognito);
auto url1_permissions = recent_permissions[2].settings;
auto url2_permissions = recent_permissions[1].settings;
auto url3_permissions = recent_permissions[0].settings;
EXPECT_EQ(kPlugins, url1_permissions[0].content_type);
EXPECT_EQ(kBlocked, url1_permissions[0].content_setting);
EXPECT_EQ(kPreference, url1_permissions[0].setting_source);
EXPECT_EQ(kPopups, url2_permissions[0].content_type);
EXPECT_EQ(kAllowed, url2_permissions[0].content_setting);
EXPECT_EQ(kPreference, url2_permissions[0].setting_source);
EXPECT_EQ(kNotifications, url3_permissions[0].content_type);
EXPECT_EQ(kBlocked, url3_permissions[0].content_setting);
EXPECT_EQ(kEmbargo, url3_permissions[0].setting_source);
EXPECT_EQ(kPopups, url3_permissions[1].content_type);
EXPECT_EQ(kBlocked, url3_permissions[1].content_setting);
EXPECT_EQ(kPreference, url3_permissions[1].setting_source);
}
// Assign a new permission to a previously recorded site whose other
// permissions are too old and ensure only the recent permission is returned.
clock()->Advance(base::TimeDelta::FromHours(1));
incognito_map->SetContentSettingDefaultScope(url1, url1, kPopups,
std::string(), kBlocked);
recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
{
EXPECT_EQ(3UL, recent_permissions.size());
EXPECT_EQ(1UL, recent_permissions[0].settings.size());
EXPECT_EQ(url1.spec(), recent_permissions[0].origin);
EXPECT_TRUE(recent_permissions[0].incognito);
EXPECT_EQ(kPopups, recent_permissions[0].settings[0].content_type);
EXPECT_EQ(kBlocked, recent_permissions[0].settings[0].content_setting);
EXPECT_EQ(kPreference, recent_permissions[0].settings[0].setting_source);
}
// Reset a changed permission to default and confirm it does not appear as a
// recent permission change.
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url3, url3, kPopups, std::string(),
kDefault);
recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
{
EXPECT_EQ(3UL, recent_permissions.size());
EXPECT_EQ(1UL, recent_permissions[0].settings.size());
EXPECT_NE(url3.spec(), recent_permissions[0].origin);
}
// Expire all existing embargoes, then re-embargo a site with a single
// dismissal and confirm this is recorded as a new permission change. Also
// confirm that sources with no permission changes associated are not
// considered. I.e. url3 now has an expired embargo and a default setting. It
// should not be considered and should allow the plugins setting for url1 to
// be included as a recent change.
clock()->Advance(base::TimeDelta::FromDays(7));
auto_blocker->RecordDismissAndEmbargo(url1, kNotifications, false);
recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
{
EXPECT_EQ(3UL, recent_permissions.size());
EXPECT_EQ(2UL, recent_permissions[0].settings.size());
EXPECT_EQ(2UL, recent_permissions[1].settings.size());
EXPECT_EQ(2UL, recent_permissions[2].settings.size());
EXPECT_EQ(url1.spec(), recent_permissions[0].origin);
EXPECT_FALSE(recent_permissions[0].incognito);
auto url1_permissions = recent_permissions[0].settings;
EXPECT_EQ(kNotifications, url1_permissions[0].content_type);
EXPECT_EQ(kBlocked, url1_permissions[0].content_setting);
EXPECT_EQ(kEmbargo, url1_permissions[0].setting_source);
EXPECT_EQ(kPlugins, url1_permissions[1].content_type);
EXPECT_EQ(kBlocked, url1_permissions[1].content_setting);
EXPECT_EQ(kPreference, url1_permissions[1].setting_source);
}
// Confirm that powerful permissions are listed first, and that other
// permissions remain sorted by time.
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url1, url1, kPopups, std::string(),
kBlocked);
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url1, url1, kLocation, std::string(),
kAllowed);
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url1, url1, kPlugins, std::string(),
kAllowed);
recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
{
EXPECT_EQ(3UL, recent_permissions.size());
auto url1_permissions = recent_permissions[0].settings;
EXPECT_EQ(4UL, url1_permissions.size());
EXPECT_EQ(kLocation, url1_permissions[0].content_type);
EXPECT_EQ(kNotifications, url1_permissions[1].content_type);
EXPECT_EQ(kPlugins, url1_permissions[2].content_type);
EXPECT_EQ(kPopups, url1_permissions[3].content_type);
}
// Check that adding a conflicting permission to the regular profile after
// the incognito profile has been created returns correctly for each profile.
const GURL url4("http://example.com:8443");
clock()->Advance(base::TimeDelta::FromHours(1));
incognito_map->SetContentSettingDefaultScope(url4, url4, kLocation,
std::string(), kAllowed);
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url4, url4, kLocation, std::string(),
kBlocked);
recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
{
EXPECT_EQ(3UL, recent_permissions.size());
EXPECT_EQ(url4.spec(), recent_permissions[0].origin);
EXPECT_EQ(url4.spec(), recent_permissions[1].origin);
EXPECT_EQ(1UL, recent_permissions[0].settings.size());
EXPECT_EQ(1UL, recent_permissions[1].settings.size());
EXPECT_FALSE(recent_permissions[0].incognito);
EXPECT_TRUE(recent_permissions[1].incognito);
EXPECT_EQ(kLocation, recent_permissions[0].settings[0].content_type);
EXPECT_EQ(kLocation, recent_permissions[1].settings[0].content_type);
EXPECT_EQ(kBlocked, recent_permissions[0].settings[0].content_setting);
EXPECT_EQ(kAllowed, recent_permissions[1].settings[0].content_setting);
}
// Check that resetting the permission to default in the regular profile
// does not affect the permission in the incognito profile.
clock()->Advance(base::TimeDelta::FromHours(1));
map->SetContentSettingDefaultScope(url4, url4, kLocation, std::string(),
kDefault);
recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
{
EXPECT_EQ(3UL, recent_permissions.size());
EXPECT_EQ(url4.spec(), recent_permissions[0].origin);
EXPECT_EQ(1UL, recent_permissions[0].settings.size());
EXPECT_TRUE(recent_permissions[0].incognito);
EXPECT_EQ(kLocation, recent_permissions[0].settings[0].content_type);
EXPECT_EQ(kAllowed, recent_permissions[0].settings[0].content_setting);
}
}
} // namespace site_settings