blob: c53099d4123c895400f18e538ad4fc02b7ca623c [file] [log] [blame]
// Copyright 2016 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/site_settings_helper.h"
#include "base/bind_helpers.h"
#include "base/guid.h"
#include "base/json/json_reader.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/usb/usb_chooser_context.h"
#include "chrome/browser/usb/usb_chooser_context_factory.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/content_settings/core/test/content_settings_mock_provider.h"
#include "components/content_settings/core/test/content_settings_test_utils.h"
#include "components/permissions/chooser_context_base.h"
#include "components/prefs/pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/extension_registry.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/cpp/test/fake_usb_device_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace site_settings {
namespace {
constexpr ContentSettingsType kContentType = ContentSettingsType::GEOLOCATION;
}
class SiteSettingsHelperTest : public testing::Test {
public:
void VerifySetting(const base::ListValue& exceptions,
int index,
const std::string& pattern,
const std::string& pattern_display_name,
const ContentSetting setting) {
const base::DictionaryValue* dict;
exceptions.GetDictionary(index, &dict);
std::string actual_pattern;
dict->GetString("origin", &actual_pattern);
EXPECT_EQ(pattern, actual_pattern);
std::string actual_display_name;
dict->GetString(kDisplayName, &actual_display_name);
EXPECT_EQ(pattern_display_name, actual_display_name);
std::string actual_setting;
dict->GetString(kSetting, &actual_setting);
EXPECT_EQ(content_settings::ContentSettingToString(setting),
actual_setting);
}
void AddSetting(HostContentSettingsMap* map,
const std::string& pattern,
ContentSetting setting) {
map->SetContentSettingCustomScope(
ContentSettingsPattern::FromString(pattern),
ContentSettingsPattern::Wildcard(), kContentType, std::string(),
setting);
}
private:
content::BrowserTaskEnvironment task_environment_;
};
TEST_F(SiteSettingsHelperTest, CheckExceptionOrder) {
TestingProfile profile;
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(&profile);
base::ListValue exceptions;
// Check that the initial state of the map is empty.
GetExceptionsFromHostContentSettingsMap(
map, kContentType, /*extension_registry=*/nullptr, /*web_ui=*/nullptr,
/*incognito=*/false, /*filter=*/nullptr, &exceptions);
EXPECT_EQ(0u, exceptions.GetSize());
map->SetDefaultContentSetting(kContentType, CONTENT_SETTING_ALLOW);
// Add a policy exception.
std::string star_google_com = "http://[*.]google.com";
auto policy_provider = std::make_unique<content_settings::MockProvider>();
policy_provider->SetWebsiteSetting(
ContentSettingsPattern::FromString(star_google_com),
ContentSettingsPattern::Wildcard(), kContentType, "",
std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
policy_provider->set_read_only(true);
content_settings::TestUtils::OverrideProvider(
map, std::move(policy_provider), HostContentSettingsMap::POLICY_PROVIDER);
// Add user preferences.
std::string http_star = "http://*";
std::string maps_google_com = "http://maps.google.com";
AddSetting(map, http_star, CONTENT_SETTING_BLOCK);
AddSetting(map, maps_google_com, CONTENT_SETTING_BLOCK);
AddSetting(map, star_google_com, CONTENT_SETTING_ALLOW);
// Add an extension exception.
std::string drive_google_com = "http://drive.google.com";
auto extension_provider = std::make_unique<content_settings::MockProvider>();
extension_provider->SetWebsiteSetting(
ContentSettingsPattern::FromString(drive_google_com),
ContentSettingsPattern::Wildcard(), kContentType, "",
std::make_unique<base::Value>(CONTENT_SETTING_ASK));
extension_provider->set_read_only(true);
content_settings::TestUtils::OverrideProvider(
map, std::move(extension_provider),
HostContentSettingsMap::CUSTOM_EXTENSION_PROVIDER);
exceptions.Clear();
GetExceptionsFromHostContentSettingsMap(
map, kContentType, /*extension_registry=*/nullptr, /*web_ui=*/nullptr,
/*incognito=*/false, /*filter=*/nullptr, &exceptions);
EXPECT_EQ(5u, exceptions.GetSize());
// The policy exception should be returned first, the extension exception
// second and pref exceptions afterwards.
// The default content setting should not be returned.
int i = 0;
// From policy provider:
VerifySetting(exceptions, i++, star_google_com, star_google_com,
CONTENT_SETTING_BLOCK);
// From extension provider:
VerifySetting(exceptions, i++, drive_google_com, drive_google_com,
CONTENT_SETTING_ASK);
// From user preferences:
VerifySetting(exceptions, i++, maps_google_com, maps_google_com,
CONTENT_SETTING_BLOCK);
VerifySetting(exceptions, i++, star_google_com, star_google_com,
CONTENT_SETTING_ALLOW);
VerifySetting(exceptions, i++, http_star, "http://*", CONTENT_SETTING_BLOCK);
}
// Tests the following content setting sources: Chrome default, user-set global
// default, user-set pattern, user-set origin setting, extension, and policy.
TEST_F(SiteSettingsHelperTest, ContentSettingSource) {
TestingProfile profile;
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(&profile);
GURL origin("https://www.example.com/");
auto* extension_registry = extensions::ExtensionRegistry::Get(&profile);
std::string source;
std::string display_name;
ContentSetting content_setting;
// Built in Chrome default.
content_setting =
GetContentSettingForOrigin(&profile, map, origin, kContentType, &source,
extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kDefault), source);
EXPECT_EQ(CONTENT_SETTING_ASK, content_setting);
// User-set global default.
map->SetDefaultContentSetting(kContentType, CONTENT_SETTING_ALLOW);
content_setting =
GetContentSettingForOrigin(&profile, map, origin, kContentType, &source,
extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kDefault), source);
EXPECT_EQ(CONTENT_SETTING_ALLOW, content_setting);
// User-set pattern.
AddSetting(map, "https://*", CONTENT_SETTING_BLOCK);
content_setting =
GetContentSettingForOrigin(&profile, map, origin, kContentType, &source,
extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kPreference), source);
EXPECT_EQ(CONTENT_SETTING_BLOCK, content_setting);
// User-set origin setting.
map->SetContentSettingDefaultScope(origin, origin, kContentType,
std::string(), CONTENT_SETTING_ALLOW);
content_setting =
GetContentSettingForOrigin(&profile, map, origin, kContentType, &source,
extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kPreference), source);
EXPECT_EQ(CONTENT_SETTING_ALLOW, content_setting);
// ChromeOS - DRM disabled.
#if defined(OS_CHROMEOS)
profile.GetPrefs()->SetBoolean(prefs::kEnableDRM, false);
// Note this is not testing |kContentType|, because this setting is only valid
// for protected content.
content_setting = GetContentSettingForOrigin(
&profile, map, origin, ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
&source, extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kDrmDisabled), source);
EXPECT_EQ(CONTENT_SETTING_BLOCK, content_setting);
#endif
// Extension.
auto extension_provider = std::make_unique<content_settings::MockProvider>();
extension_provider->SetWebsiteSetting(
ContentSettingsPattern::FromURL(origin),
ContentSettingsPattern::FromURL(origin), kContentType, "",
std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
extension_provider->set_read_only(true);
content_settings::TestUtils::OverrideProvider(
map, std::move(extension_provider),
HostContentSettingsMap::CUSTOM_EXTENSION_PROVIDER);
content_setting =
GetContentSettingForOrigin(&profile, map, origin, kContentType, &source,
extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kExtension), source);
EXPECT_EQ(CONTENT_SETTING_BLOCK, content_setting);
// Enterprise policy.
auto policy_provider = std::make_unique<content_settings::MockProvider>();
policy_provider->SetWebsiteSetting(
ContentSettingsPattern::FromURL(origin),
ContentSettingsPattern::FromURL(origin), kContentType, "",
std::make_unique<base::Value>(CONTENT_SETTING_ALLOW));
policy_provider->set_read_only(true);
content_settings::TestUtils::OverrideProvider(
map, std::move(policy_provider), HostContentSettingsMap::POLICY_PROVIDER);
content_setting =
GetContentSettingForOrigin(&profile, map, origin, kContentType, &source,
extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kPolicy), source);
EXPECT_EQ(CONTENT_SETTING_ALLOW, content_setting);
// Insecure origins.
content_setting = GetContentSettingForOrigin(
&profile, map, GURL("http://www.insecure_http_site.com/"), kContentType,
&source, extension_registry, &display_name);
EXPECT_EQ(SiteSettingSourceToString(SiteSettingSource::kInsecureOrigin),
source);
EXPECT_EQ(CONTENT_SETTING_BLOCK, content_setting);
}
namespace {
// Test GURLs
// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
// function.
GURL GoogleUrl() {
return GURL("https://google.com");
}
GURL ChromiumUrl() {
return GURL("https://chromium.org");
}
GURL AndroidUrl() {
return GURL("https://android.com");
}
void ExpectValidChooserExceptionObject(
const base::Value& actual_exception_object,
const std::string& chooser_type,
const base::string16& display_name,
const base::Value& chooser_object) {
const base::Value* chooser_type_value = actual_exception_object.FindKeyOfType(
kChooserType, base::Value::Type::STRING);
ASSERT_TRUE(chooser_type_value);
EXPECT_EQ(chooser_type_value->GetString(), chooser_type);
const base::Value* display_name_value = actual_exception_object.FindKeyOfType(
kDisplayName, base::Value::Type::STRING);
ASSERT_TRUE(display_name_value);
EXPECT_EQ(base::UTF8ToUTF16(display_name_value->GetString()), display_name);
const base::Value* object_value = actual_exception_object.FindKeyOfType(
kObject, base::Value::Type::DICTIONARY);
ASSERT_TRUE(object_value);
EXPECT_EQ(*object_value, chooser_object);
const base::Value* sites_value =
actual_exception_object.FindKeyOfType(kSites, base::Value::Type::LIST);
ASSERT_TRUE(sites_value);
}
void ExpectValidSiteExceptionObject(const base::Value& actual_site_object,
const GURL& origin,
const GURL& embedding_origin,
const std::string source,
bool incognito) {
ASSERT_TRUE(actual_site_object.is_dict());
const base::Value* display_name_value =
actual_site_object.FindKeyOfType(kDisplayName, base::Value::Type::STRING);
ASSERT_TRUE(display_name_value);
EXPECT_EQ(display_name_value->GetString(), origin.GetOrigin().spec());
const base::Value* origin_value =
actual_site_object.FindKeyOfType(kOrigin, base::Value::Type::STRING);
ASSERT_TRUE(origin_value);
EXPECT_EQ(origin_value->GetString(), origin.GetOrigin().spec());
const base::Value* embedding_origin_value = actual_site_object.FindKeyOfType(
kEmbeddingOrigin, base::Value::Type::STRING);
ASSERT_TRUE(embedding_origin_value);
EXPECT_EQ(embedding_origin_value->GetString(),
embedding_origin.GetOrigin().spec());
const base::Value* setting_value =
actual_site_object.FindKeyOfType(kSetting, base::Value::Type::STRING);
ASSERT_TRUE(setting_value);
EXPECT_EQ(setting_value->GetString(),
content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT));
const base::Value* source_value =
actual_site_object.FindKeyOfType(kSource, base::Value::Type::STRING);
ASSERT_TRUE(source_value);
EXPECT_EQ(source_value->GetString(), source);
const base::Value* incognito_value =
actual_site_object.FindKeyOfType(kIncognito, base::Value::Type::BOOLEAN);
ASSERT_TRUE(incognito_value);
EXPECT_EQ(incognito_value->GetBool(), incognito);
}
void ExpectValidSiteExceptionObject(const base::Value& actual_site_object,
const GURL& origin,
const std::string source,
bool incognito) {
ExpectValidSiteExceptionObject(actual_site_object, origin, GURL::EmptyGURL(),
source, incognito);
}
} // namespace
TEST_F(SiteSettingsHelperTest, CreateChooserExceptionObject) {
const std::string kUsbChooserGroupName =
ContentSettingsTypeToGroupName(ContentSettingsType::USB_CHOOSER_DATA);
const std::string& kPolicySource =
SiteSettingSourceToString(SiteSettingSource::kPolicy);
const std::string& kPreferenceSource =
SiteSettingSourceToString(SiteSettingSource::kPreference);
const base::string16& kObjectName = base::ASCIIToUTF16("Gadget");
ChooserExceptionDetails exception_details;
// Create a chooser object for testing.
auto chooser_object = std::make_unique<base::DictionaryValue>();
chooser_object->SetKey("name", base::Value(kObjectName));
// Add a user permission for a requesting origin of |kGoogleOrigin| and an
// embedding origin of |kChromiumOrigin|.
exception_details[std::make_pair(GoogleUrl().GetOrigin(), kPreferenceSource)]
.insert(std::make_pair(ChromiumUrl().GetOrigin(), /*incognito=*/false));
{
auto exception = CreateChooserExceptionObject(
/*display_name=*/kObjectName,
/*object=*/*chooser_object,
/*chooser_type=*/kUsbChooserGroupName,
/*chooser_exception_details=*/exception_details);
ExpectValidChooserExceptionObject(
exception, /*chooser_type=*/kUsbChooserGroupName,
/*display_name=*/kObjectName, *chooser_object);
const auto& sites_list = exception.FindKey(kSites)->GetList();
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[0],
/*origin=*/GoogleUrl(),
/*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
// Add a user permissions for a requesting and embedding origin pair of
// |kAndroidOrigin| granted in an off the record profile.
exception_details[std::make_pair(AndroidUrl().GetOrigin(), kPreferenceSource)]
.insert(std::make_pair(AndroidUrl().GetOrigin(), /*incognito=*/true));
{
auto exception = CreateChooserExceptionObject(
/*display_name=*/kObjectName,
/*object=*/*chooser_object,
/*chooser_type=*/kUsbChooserGroupName,
/*chooser_exception_details=*/exception_details);
ExpectValidChooserExceptionObject(exception,
/*chooser_type=*/kUsbChooserGroupName,
/*display_name=*/kObjectName,
*chooser_object);
// The map sorts the sites by requesting origin, so |kAndroidOrigin| should
// be first, followed by the origin pair (kGoogleOrigin, kChromiumOrigin).
const auto& sites_list = exception.FindKey(kSites)->GetList();
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[0],
/*origin=*/AndroidUrl(),
/*embedding_origin=*/AndroidUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/true);
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[1],
/*origin=*/GoogleUrl(),
/*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
// Add a policy permission for a requesting origin of |kGoogleOrigin| with a
// wildcard embedding origin.
exception_details[std::make_pair(GoogleUrl().GetOrigin(), kPolicySource)]
.insert(std::make_pair(GURL::EmptyGURL(), /*incognito=*/false));
{
auto exception = CreateChooserExceptionObject(
/*display_name=*/kObjectName,
/*object=*/*chooser_object,
/*chooser_type=*/kUsbChooserGroupName,
/*chooser_exception_details=*/exception_details);
ExpectValidChooserExceptionObject(exception,
/*chooser_type=*/kUsbChooserGroupName,
/*display_name=*/kObjectName,
*chooser_object);
// The map sorts the sites by requesting origin, but the
// CreateChooserExceptionObject method sorts the sites further by the
// source. Therefore, policy granted sites are listed before user granted
// sites.
const auto& sites_list = exception.FindKey(kSites)->GetList();
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[0],
/*origin=*/GoogleUrl(),
/*embedding_origin=*/GURL::EmptyGURL(),
/*source=*/kPolicySource,
/*incognito=*/false);
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[1],
/*origin=*/AndroidUrl(),
/*embedding_origin=*/AndroidUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/true);
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[2],
/*origin=*/GoogleUrl(),
/*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
}
namespace {
constexpr char kUsbPolicySetting[] = R"(
[
{
"devices": [{ "vendor_id": 6353, "product_id": 5678 }],
"urls": ["https://chromium.org"]
}, {
"devices": [{ "vendor_id": 6353 }],
"urls": ["https://google.com,https://android.com"]
}, {
"devices": [{ "vendor_id": 6354 }],
"urls": ["https://android.com,"]
}, {
"devices": [{}],
"urls": ["https://google.com,https://google.com"]
}
])";
class SiteSettingsHelperChooserExceptionTest : public testing::Test {
protected:
Profile* profile() { return &profile_; }
void SetUp() override { SetUpUsbChooserContext(); }
// Sets up the UsbChooserContext with two devices and permissions for these
// devices. It also adds three policy defined permissions. The two devices
// represent the two types of USB devices, persistent and ephemeral, that can
// be granted permission.
void SetUpUsbChooserContext() {
device::mojom::UsbDeviceInfoPtr persistent_device_info =
device_manager_.CreateAndAddDevice(6353, 5678, "Google", "Gizmo",
"123ABC");
device::mojom::UsbDeviceInfoPtr ephemeral_device_info =
device_manager_.CreateAndAddDevice(6354, 0, "Google", "Gadget", "");
auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile());
mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager;
device_manager_.AddReceiver(
device_manager.InitWithNewPipeAndPassReceiver());
chooser_context->SetDeviceManagerForTesting(std::move(device_manager));
chooser_context->GetDevices(
base::DoNothing::Once<std::vector<device::mojom::UsbDeviceInfoPtr>>());
base::RunLoop().RunUntilIdle();
const auto kAndroidOrigin = url::Origin::Create(AndroidUrl());
const auto kChromiumOrigin = url::Origin::Create(ChromiumUrl());
const auto kGoogleOrigin = url::Origin::Create(GoogleUrl());
// Add the user granted permissions for testing.
// These two persistent device permissions should be lumped together with
// the policy permissions, since they apply to the same device and URL.
chooser_context->GrantDevicePermission(kChromiumOrigin, kChromiumOrigin,
*persistent_device_info);
chooser_context->GrantDevicePermission(kChromiumOrigin, kGoogleOrigin,
*persistent_device_info);
chooser_context->GrantDevicePermission(kAndroidOrigin, kChromiumOrigin,
*persistent_device_info);
chooser_context->GrantDevicePermission(kAndroidOrigin, kAndroidOrigin,
*ephemeral_device_info);
// Add the policy granted permissions for testing.
auto policy_value = base::JSONReader::ReadDeprecated(kUsbPolicySetting);
DCHECK(policy_value);
profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls,
*policy_value);
}
device::FakeUsbDeviceManager device_manager_;
private:
content::BrowserTaskEnvironment task_environment_;
TestingProfile profile_;
};
void ExpectDisplayNameEq(const base::Value& actual_exception_object,
const std::string& display_name) {
const std::string* actual_display_name =
actual_exception_object.FindStringKey(kDisplayName);
ASSERT_TRUE(actual_display_name);
EXPECT_EQ(*actual_display_name, display_name);
}
} // namespace
TEST_F(SiteSettingsHelperChooserExceptionTest,
GetChooserExceptionListFromProfile) {
const std::string kUsbChooserGroupName =
ContentSettingsTypeToGroupName(ContentSettingsType::USB_CHOOSER_DATA);
const ChooserTypeNameEntry* chooser_type =
ChooserTypeFromGroupName(kUsbChooserGroupName);
const std::string& kPolicySource =
SiteSettingSourceToString(SiteSettingSource::kPolicy);
const std::string& kPreferenceSource =
SiteSettingSourceToString(SiteSettingSource::kPreference);
// The chooser exceptions are ordered by display name. Their corresponding
// sites are ordered by permission source precedence, then by the requesting
// origin and the embedding origin. User granted permissions that are also
// granted by policy are combined with the policy so that duplicate
// permissions are not displayed.
base::Value exceptions =
GetChooserExceptionListFromProfile(profile(), *chooser_type);
base::Value::ConstListView exceptions_list = exceptions.GetList();
ASSERT_EQ(exceptions_list.size(), 4u);
// This exception should describe the permissions for any device with the
// vendor ID corresponding to "Google Inc.". There are no user granted
// permissions that intersect with this permission, and this policy only
// grants one permission to the following site pair:
// * ("https://google.com", "https://android.com")
{
const auto& exception = exceptions_list[0];
ExpectDisplayNameEq(exception,
/*display_name=*/"Devices from Google Inc.");
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 1u);
ExpectValidSiteExceptionObject(sites_list[0],
/*origin=*/GoogleUrl(),
/*embedding_origin=*/AndroidUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
}
// This exception should describe the permissions for any device.
// There are no user granted permissions that intersect with this permission,
// and this policy only grants one permission to the following site pair:
// * ("https://google.com", "https://google.com")
{
const auto& exception = exceptions_list[1];
ExpectDisplayNameEq(exception,
/*display_name=*/"Devices from any vendor");
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 1u);
ExpectValidSiteExceptionObject(sites_list[0],
/*origin=*/GoogleUrl(),
/*embedding_origin=*/GoogleUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
}
// This exception should describe the permissions for any device with the
// vendor ID 6354. There is a user granted permission for a device with that
// vendor ID, so the site list for this exception will only have the policy
// granted permission, which is the following:
// * ("https://android.com", "")
{
const auto& exception = exceptions_list[2];
ExpectDisplayNameEq(exception,
/*display_name=*/"Devices from vendor 0x18D2");
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 1u);
ExpectValidSiteExceptionObject(sites_list[0],
/*origin=*/AndroidUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
}
// This exception should describe the permissions for the "Gizmo" device.
// The user granted permissions are the following:
// * ("https://chromium.org", "https://chromium.org")
// * ("https://chromium.org", "https://google.com")
// * ("https://android.com", "https://chromium.org")
// The policy granted permission is the following:
// * ("https://chromium.org", "")
// The embedding origin is a wildcard, so the policy granted permission covers
// any user granted permissions that contain a requesting origin of
// "https://chromium.org", so the site list for this exception will only have
// the following permissions:
// * ("https://chromium.org", "")
// * ("https://android.com", "https://chromium.org")
{
const auto& exception = exceptions_list[3];
ExpectDisplayNameEq(exception, /*display_name=*/"Gizmo");
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 2u);
ExpectValidSiteExceptionObject(sites_list[0],
/*origin=*/ChromiumUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
ExpectValidSiteExceptionObject(sites_list[1],
/*origin=*/AndroidUrl(),
/*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
}
namespace {
// All of the possible managed states for a boolean preference that can be
// both enforced and recommended.
enum class PrefSetting {
kEnforcedOff,
kEnforcedOn,
kRecommendedOff,
kRecommendedOn,
kNotSet,
};
// Possible preference sources supported by TestingPrefService.
// TODO(crbug.com/1063281): Extend TestingPrefService to support prefs set for
// supervised users.
enum class PrefSource {
kExtension,
kDevicePolicy,
kRecommended,
kNone,
};
// Represents a set of settings, preferences and the associated expected
// CookieControlsManagedState.
struct CookiesManagedStateTestCase {
ContentSetting default_content_setting;
content_settings::SettingSource default_content_setting_source;
PrefSetting block_third_party;
PrefSource block_third_party_source;
CookieControlsManagedState expected_result;
};
const std::vector<CookiesManagedStateTestCase> test_cases = {
{CONTENT_SETTING_DEFAULT,
content_settings::SETTING_SOURCE_NONE,
PrefSetting::kEnforcedOff,
PrefSource::kExtension,
{{false, PolicyIndicatorType::kNone},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone}}},
{CONTENT_SETTING_DEFAULT,
content_settings::SETTING_SOURCE_NONE,
PrefSetting::kEnforcedOn,
PrefSource::kDevicePolicy,
{{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone}}},
{CONTENT_SETTING_DEFAULT,
content_settings::SETTING_SOURCE_NONE,
PrefSetting::kRecommendedOff,
PrefSource::kRecommended,
{{false, PolicyIndicatorType::kRecommended},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone}}},
{CONTENT_SETTING_DEFAULT,
content_settings::SETTING_SOURCE_NONE,
PrefSetting::kRecommendedOn,
PrefSource::kRecommended,
{{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kRecommended},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone}}},
{CONTENT_SETTING_DEFAULT,
content_settings::SETTING_SOURCE_NONE,
PrefSetting::kNotSet,
PrefSource::kNone,
{{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone}}},
{CONTENT_SETTING_ALLOW,
content_settings::SETTING_SOURCE_POLICY,
PrefSetting::kEnforcedOff,
PrefSource::kExtension,
{{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy}}},
{CONTENT_SETTING_ALLOW,
content_settings::SETTING_SOURCE_EXTENSION,
PrefSetting::kEnforcedOn,
PrefSource::kDevicePolicy,
{{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension}}},
{CONTENT_SETTING_ALLOW,
content_settings::SETTING_SOURCE_SUPERVISED,
PrefSetting::kRecommendedOff,
PrefSource::kRecommended,
{{false, PolicyIndicatorType::kRecommended},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent}}},
{CONTENT_SETTING_ALLOW,
content_settings::SETTING_SOURCE_POLICY,
PrefSetting::kRecommendedOn,
PrefSource::kRecommended,
{{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kRecommended},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy}}},
{CONTENT_SETTING_ALLOW,
content_settings::SETTING_SOURCE_EXTENSION,
PrefSetting::kNotSet,
PrefSource::kNone,
{{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension}}},
{CONTENT_SETTING_BLOCK,
content_settings::SETTING_SOURCE_SUPERVISED,
PrefSetting::kEnforcedOff,
PrefSource::kDevicePolicy,
{{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent}}},
{CONTENT_SETTING_BLOCK,
content_settings::SETTING_SOURCE_POLICY,
PrefSetting::kEnforcedOn,
PrefSource::kExtension,
{{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy}}},
{CONTENT_SETTING_BLOCK,
content_settings::SETTING_SOURCE_EXTENSION,
PrefSetting::kRecommendedOff,
PrefSource::kRecommended,
{{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension}}},
{CONTENT_SETTING_BLOCK,
content_settings::SETTING_SOURCE_SUPERVISED,
PrefSetting::kRecommendedOn,
PrefSource::kRecommended,
{{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent}}},
{CONTENT_SETTING_BLOCK,
content_settings::SETTING_SOURCE_POLICY,
PrefSetting::kNotSet,
PrefSource::kNone,
{{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy}}},
{CONTENT_SETTING_SESSION_ONLY,
content_settings::SETTING_SOURCE_EXTENSION,
PrefSetting::kEnforcedOff,
PrefSource::kDevicePolicy,
{{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension}}},
{CONTENT_SETTING_SESSION_ONLY,
content_settings::SETTING_SOURCE_SUPERVISED,
PrefSetting::kEnforcedOn,
PrefSource::kExtension,
{{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent}}},
{CONTENT_SETTING_SESSION_ONLY,
content_settings::SETTING_SOURCE_POLICY,
PrefSetting::kRecommendedOff,
PrefSource::kRecommended,
{{false, PolicyIndicatorType::kRecommended},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{true, PolicyIndicatorType::kDevicePolicy},
{true, PolicyIndicatorType::kDevicePolicy}}},
{CONTENT_SETTING_SESSION_ONLY,
content_settings::SETTING_SOURCE_EXTENSION,
PrefSetting::kRecommendedOn,
PrefSource::kRecommended,
{{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kRecommended},
{true, PolicyIndicatorType::kExtension},
{true, PolicyIndicatorType::kExtension}}},
{CONTENT_SETTING_SESSION_ONLY,
content_settings::SETTING_SOURCE_SUPERVISED,
PrefSetting::kNotSet,
PrefSource::kNone,
{{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{false, PolicyIndicatorType::kNone},
{true, PolicyIndicatorType::kParent},
{true, PolicyIndicatorType::kParent}}}};
void SetupTestConditions(HostContentSettingsMap* map,
sync_preferences::TestingPrefServiceSyncable* prefs,
const CookiesManagedStateTestCase& test_case) {
if (test_case.default_content_setting != CONTENT_SETTING_DEFAULT) {
auto provider = std::make_unique<content_settings::MockProvider>();
provider->SetWebsiteSetting(
ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
ContentSettingsType::COOKIES, std::string(),
std::make_unique<base::Value>(test_case.default_content_setting));
HostContentSettingsMap::ProviderType provider_type;
switch (test_case.default_content_setting_source) {
case content_settings::SETTING_SOURCE_POLICY:
provider_type = HostContentSettingsMap::POLICY_PROVIDER;
break;
case content_settings::SETTING_SOURCE_EXTENSION:
provider_type = HostContentSettingsMap::CUSTOM_EXTENSION_PROVIDER;
break;
case content_settings::SETTING_SOURCE_SUPERVISED:
provider_type = HostContentSettingsMap::SUPERVISED_PROVIDER;
break;
case content_settings::SETTING_SOURCE_NONE:
default:
provider_type = HostContentSettingsMap::DEFAULT_PROVIDER;
}
content_settings::TestUtils::OverrideProvider(map, std::move(provider),
provider_type);
}
if (test_case.block_third_party != PrefSetting::kNotSet) {
bool third_party_value =
test_case.block_third_party == PrefSetting::kRecommendedOn ||
test_case.block_third_party == PrefSetting::kEnforcedOn;
if (test_case.block_third_party_source == PrefSource::kExtension) {
prefs->SetExtensionPref(prefs::kBlockThirdPartyCookies,
std::make_unique<base::Value>(third_party_value));
} else if (test_case.block_third_party_source ==
PrefSource::kDevicePolicy) {
prefs->SetManagedPref(prefs::kBlockThirdPartyCookies,
std::make_unique<base::Value>(third_party_value));
} else if (test_case.block_third_party_source == PrefSource::kRecommended) {
prefs->SetRecommendedPref(
prefs::kBlockThirdPartyCookies,
std::make_unique<base::Value>(third_party_value));
}
}
}
void AssertManagedCookieStateEqual(const CookieControlsManagedState& a,
const CookieControlsManagedState b) {
ASSERT_EQ(a.allow_all.disabled, b.allow_all.disabled);
ASSERT_EQ(a.allow_all.indicator, b.allow_all.indicator);
ASSERT_EQ(a.block_third_party_incognito.disabled,
b.block_third_party_incognito.disabled);
ASSERT_EQ(a.block_third_party_incognito.indicator,
b.block_third_party_incognito.indicator);
ASSERT_EQ(a.block_third_party.disabled, b.block_third_party.disabled);
ASSERT_EQ(a.block_third_party.indicator, b.block_third_party.indicator);
ASSERT_EQ(a.block_all.disabled, b.block_all.disabled);
ASSERT_EQ(a.block_all.indicator, b.block_all.indicator);
ASSERT_EQ(a.session_only.disabled, b.session_only.disabled);
ASSERT_EQ(a.session_only.indicator, b.session_only.indicator);
}
TEST_F(SiteSettingsHelperTest, CookiesManagedState) {
for (auto test_case : test_cases) {
TestingProfile profile;
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(&profile);
sync_preferences::TestingPrefServiceSyncable* prefs =
profile.GetTestingPrefService();
testing::Message scope_message;
scope_message << "Content Setting:" << test_case.default_content_setting
<< " Block Third Party:"
<< static_cast<int>(test_case.block_third_party);
SCOPED_TRACE(scope_message);
SetupTestConditions(map, prefs, test_case);
AssertManagedCookieStateEqual(
site_settings::GetCookieControlsManagedState(&profile),
test_case.expected_result);
}
}
} // namespace
} // namespace site_settings