blob: b68a7206096a740b7581417609ed1dc4b9e6ce24 [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/net/secure_dns_util.h"
#include <memory>
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/common/chrome_features.h"
#include "components/country_codes/country_codes.h"
#include "components/embedder_support/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "net/dns/dns_config_overrides.h"
#include "net/dns/public/doh_provider_entry.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::ElementsAre;
namespace chrome_browser_net {
namespace {
const char kAlternateErrorPagesBackup[] = "alternate_error_pages.backup";
} // namespace
namespace secure_dns {
class SecureDnsUtilTest : public testing::Test {
public:
void SetUp() override { DisableRedesign(); }
void EnableRedesign() {
scoped_feature_list_.Reset();
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kPrivacySettingsRedesign, base::FieldTrialParams());
}
void DisableRedesign() {
scoped_feature_list_.Reset();
scoped_feature_list_.InitAndDisableFeature(
features::kPrivacySettingsRedesign);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(SecureDnsUtilTest, MigrateProbesPref) {
TestingPrefServiceSimple prefs;
prefs.registry()->RegisterBooleanPref(
embedder_support::kAlternateErrorPagesEnabled, true);
prefs.registry()->RegisterBooleanPref(kAlternateErrorPagesBackup, true);
const PrefService::Preference* current_pref =
prefs.FindPreference(embedder_support::kAlternateErrorPagesEnabled);
const PrefService::Preference* backup_pref =
prefs.FindPreference(kAlternateErrorPagesBackup);
// No migration happens if the privacy settings redesign is not enabled.
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_FALSE(backup_pref->HasUserSetting());
// The hardcoded default value of TRUE gets correctly migrated.
EnableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_FALSE(current_pref->HasUserSetting());
EXPECT_TRUE(backup_pref->HasUserSetting());
EXPECT_TRUE(prefs.GetBoolean(kAlternateErrorPagesBackup));
// And correctly restored.
DisableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_TRUE(current_pref->HasUserSetting());
EXPECT_TRUE(prefs.GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
EXPECT_FALSE(backup_pref->HasUserSetting());
// An explicit user value of TRUE will be correctly migrated.
EnableRedesign();
prefs.SetBoolean(embedder_support::kAlternateErrorPagesEnabled, true);
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_FALSE(current_pref->HasUserSetting());
EXPECT_TRUE(backup_pref->HasUserSetting());
EXPECT_TRUE(prefs.GetBoolean(kAlternateErrorPagesBackup));
// And correctly restored.
DisableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_TRUE(current_pref->HasUserSetting());
EXPECT_TRUE(prefs.GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
EXPECT_FALSE(backup_pref->HasUserSetting());
// An explicit user value of FALSE will also be correctly migrated.
EnableRedesign();
prefs.SetBoolean(embedder_support::kAlternateErrorPagesEnabled, false);
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_FALSE(current_pref->HasUserSetting());
EXPECT_TRUE(backup_pref->HasUserSetting());
EXPECT_FALSE(prefs.GetBoolean(kAlternateErrorPagesBackup));
// And correctly restored.
DisableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_TRUE(current_pref->HasUserSetting());
EXPECT_FALSE(prefs.GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
EXPECT_FALSE(backup_pref->HasUserSetting());
// A policy-sourced value of TRUE takes precedence over the user-sourced value
// of FALSE when the preference is evaluated. However, it will still be the
// user-sourced value of FALSE that will be migrated.
prefs.SetManagedPref(embedder_support::kAlternateErrorPagesEnabled,
std::make_unique<base::Value>(true));
EnableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_FALSE(current_pref->HasUserSetting());
EXPECT_TRUE(backup_pref->HasUserSetting());
EXPECT_FALSE(prefs.GetBoolean(kAlternateErrorPagesBackup));
// And correctly restored.
DisableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_TRUE(current_pref->HasUserSetting());
{
const base::Value* user_pref =
prefs.GetUserPref(embedder_support::kAlternateErrorPagesEnabled);
ASSERT_TRUE(user_pref->is_bool());
EXPECT_FALSE(user_pref->GetBool());
}
EXPECT_FALSE(backup_pref->HasUserSetting());
// After clearing the user-sourced value, the hardcoded value of TRUE should
// be the value which is migrated, even if it is overridden by
// a policy-sourced value of FALSE.
prefs.ClearPref(embedder_support::kAlternateErrorPagesEnabled);
prefs.SetManagedPref(embedder_support::kAlternateErrorPagesEnabled,
std::make_unique<base::Value>(false));
EnableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_FALSE(current_pref->HasUserSetting());
EXPECT_TRUE(backup_pref->HasUserSetting());
EXPECT_TRUE(prefs.GetBoolean(kAlternateErrorPagesBackup));
// And correctly restored.
DisableRedesign();
MigrateProbesSettingToOrFromBackup(&prefs);
EXPECT_TRUE(current_pref->HasUserSetting());
{
const base::Value* user_pref =
prefs.GetUserPref(embedder_support::kAlternateErrorPagesEnabled);
ASSERT_TRUE(user_pref->is_bool());
EXPECT_TRUE(user_pref->GetBool());
}
EXPECT_FALSE(backup_pref->HasUserSetting());
}
TEST(SecureDnsUtil, SplitGroup) {
EXPECT_THAT(SplitGroup("a"), ElementsAre("a"));
EXPECT_THAT(SplitGroup("a b"), ElementsAre("a", "b"));
EXPECT_THAT(SplitGroup("a \tb\nc"), ElementsAre("a", "b\nc"));
EXPECT_THAT(SplitGroup(" \ta b\n"), ElementsAre("a", "b"));
}
TEST(SecureDnsUtil, IsValidGroup) {
EXPECT_TRUE(IsValidGroup(""));
EXPECT_TRUE(IsValidGroup("https://valid"));
EXPECT_TRUE(IsValidGroup("https://valid https://valid2"));
EXPECT_FALSE(IsValidGroup("https://valid invalid"));
EXPECT_FALSE(IsValidGroup("invalid https://valid"));
EXPECT_FALSE(IsValidGroup("invalid"));
EXPECT_FALSE(IsValidGroup("invalid invalid2"));
}
TEST(SecureDnsUtil, ApplyDohTemplatePost) {
std::string post_template("https://valid");
net::DnsConfigOverrides overrides;
ApplyTemplate(&overrides, post_template);
EXPECT_THAT(overrides.dns_over_https_servers,
testing::Optional(ElementsAre(net::DnsOverHttpsServerConfig(
{post_template, true /* use_post */}))));
}
TEST(SecureDnsUtil, ApplyDohTemplateGet) {
std::string get_template("https://valid/{?dns}");
net::DnsConfigOverrides overrides;
ApplyTemplate(&overrides, get_template);
EXPECT_THAT(overrides.dns_over_https_servers,
testing::Optional(ElementsAre(net::DnsOverHttpsServerConfig(
{get_template, false /* use_post */}))));
}
net::DohProviderEntry::List GetProvidersForTesting() {
static const auto global1 = net::DohProviderEntry::ConstructForTesting(
"Provider_Global1", net::DohProviderIdForHistogram(-1), {} /*ip_strs */,
{} /* dot_hostnames */, "https://global1.provider/dns-query{?dns}",
"Global Provider 1" /* ui_name */,
"https://global1.provider/privacy_policy/" /* privacy_policy */,
true /* display_globally */, {} /* display_countries */);
static const auto no_display = net::DohProviderEntry::ConstructForTesting(
"Provider_NoDisplay", net::DohProviderIdForHistogram(-2), {} /*ip_strs */,
{} /* dot_hostnames */, "https://nodisplay.provider/dns-query{?dns}",
"No Display Provider" /* ui_name */,
"https://nodisplay.provider/privacy_policy/" /* privacy_policy */,
false /* display_globally */, {} /* display_countries */);
static const auto ee_fr = net::DohProviderEntry::ConstructForTesting(
"Provider_EE_FR", net::DohProviderIdForHistogram(-3), {} /*ip_strs */,
{} /* dot_hostnames */, "https://ee.fr.provider/dns-query{?dns}",
"EE/FR Provider" /* ui_name */,
"https://ee.fr.provider/privacy_policy/" /* privacy_policy */,
false /* display_globally */, {"EE", "FR"} /* display_countries */);
static const auto fr = net::DohProviderEntry::ConstructForTesting(
"Provider_FR", net::DohProviderIdForHistogram(-4), {} /*ip_strs */,
{} /* dot_hostnames */, "https://fr.provider/dns-query{?dns}",
"FR Provider" /* ui_name */,
"https://fr.provider/privacy_policy/" /* privacy_policy */,
false /* display_globally */, {"FR"} /* display_countries */);
static const auto global2 = net::DohProviderEntry::ConstructForTesting(
"Provider_Global2", net::DohProviderIdForHistogram(-5), {} /*ip_strs */,
{} /* dot_hostnames */, "https://global2.provider/dns-query{?dns}",
"Global Provider 2" /* ui_name */,
"https://global2.provider/privacy_policy/" /* privacy_policy */,
true /* display_globally */, {} /* display_countries */);
return {&global1, &no_display, &ee_fr, &fr, &global2};
}
TEST(SecureDnsUtil, LocalProviders) {
const auto providers = GetProvidersForTesting();
const auto fr_providers = ProvidersForCountry(
providers, country_codes::CountryStringToCountryID("FR"));
EXPECT_THAT(fr_providers, ElementsAre(providers[0], providers[2],
providers[3], providers[4]));
const auto ee_providers = ProvidersForCountry(
providers, country_codes::CountryStringToCountryID("EE"));
EXPECT_THAT(ee_providers,
ElementsAre(providers[0], providers[2], providers[4]));
const auto us_providers = ProvidersForCountry(
providers, country_codes::CountryStringToCountryID("US"));
EXPECT_THAT(us_providers, ElementsAre(providers[0], providers[4]));
const auto unknown_providers =
ProvidersForCountry(providers, country_codes::kCountryIDUnknown);
EXPECT_THAT(unknown_providers, ElementsAre(providers[0], providers[4]));
}
TEST(SecureDnsUtil, DisabledProviders) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeatureWithParameters(
features::kDnsOverHttps,
{{"DisabledProviders", "Provider_Global2, , Provider_EE_FR,Unexpected"}});
EXPECT_THAT(GetDisabledProviders(),
ElementsAre("Provider_Global2", "Provider_EE_FR", "Unexpected"));
}
TEST(SecureDnsUtil, RemoveDisabled) {
const auto providers = GetProvidersForTesting();
const auto filtered_providers = RemoveDisabledProviders(
providers, {"Provider_Global2", "", "Provider_EE_FR", "Unexpected"});
EXPECT_THAT(filtered_providers,
ElementsAre(providers[0], providers[1], providers[3]));
}
TEST(SecureDnsUtil, UpdateDropdownHistograms) {
base::HistogramTester histograms;
const auto providers = GetProvidersForTesting();
UpdateDropdownHistograms(providers, providers[4]->dns_over_https_template,
providers[0]->dns_over_https_template);
const std::string kUmaBase = "Net.DNS.UI.DropdownSelectionEvent";
histograms.ExpectTotalCount(kUmaBase + ".Ignored", 4u);
histograms.ExpectTotalCount(kUmaBase + ".Selected", 1u);
histograms.ExpectTotalCount(kUmaBase + ".Unselected", 1u);
}
TEST(SecureDnsUtil, UpdateDropdownHistogramsCustom) {
base::HistogramTester histograms;
const auto providers = GetProvidersForTesting();
UpdateDropdownHistograms(providers, std::string(),
providers[2]->dns_over_https_template);
const std::string kUmaBase = "Net.DNS.UI.DropdownSelectionEvent";
histograms.ExpectTotalCount(kUmaBase + ".Ignored", 4u);
histograms.ExpectTotalCount(kUmaBase + ".Selected", 1u);
histograms.ExpectTotalCount(kUmaBase + ".Unselected", 1u);
}
} // namespace secure_dns
} // namespace chrome_browser_net