blob: 202da404a31ee50c0aed071dfcc62f93e3cf57a8 [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/settings_secure_dns_handler.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_probe_test_util.h"
#include "chrome/browser/net/dns_util.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/country_codes/country_codes.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/test_web_ui.h"
#include "net/dns/public/resolve_error_info.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_WIN)
#include "base/win/win_util.h"
#endif
using net::DohProviderEntry;
using testing::_;
using testing::Return;
namespace settings {
namespace {
constexpr char kGetSecureDnsResolverList[] = "getSecureDnsResolverList";
constexpr char kValidateCustomDnsEntry[] = "validateCustomDnsEntry";
constexpr char kProbeCustomDnsTemplate[] = "probeCustomDnsTemplate";
constexpr char kRecordUserDropdownInteraction[] =
"recordUserDropdownInteraction";
constexpr char kWebUiFunctionName[] = "webUiCallbackName";
const std::vector<DohProviderEntry>& GetDohProviderListForTesting() {
static const base::NoDestructor<std::vector<DohProviderEntry>> test_providers{
{
DohProviderEntry(
"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 */),
DohProviderEntry(
"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 */),
DohProviderEntry(
"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 */),
DohProviderEntry(
"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 */),
DohProviderEntry(
"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 *test_providers;
}
bool FindDropdownItem(const base::Value& resolvers,
const std::string& name,
const std::string& value,
const std::string& policy) {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey("name", base::Value(name));
dict.SetKey("value", base::Value(value));
dict.SetKey("policy", base::Value(policy));
return std::find(resolvers.GetList().begin(), resolvers.GetList().end(),
dict) != resolvers.GetList().end();
}
} // namespace
class TestSecureDnsHandler : public SecureDnsHandler {
public:
// Pull WebUIMessageHandler::set_web_ui() into public so tests can call it.
using SecureDnsHandler::set_web_ui;
};
class SecureDnsHandlerTest : public InProcessBrowserTest {
protected:
#if defined(OS_WIN)
SecureDnsHandlerTest()
// Mark as not enterprise managed to prevent the secure DNS mode from
// being downgraded to off.
: scoped_domain_(false) {}
#else
SecureDnsHandlerTest() = default;
#endif
~SecureDnsHandlerTest() override = default;
// InProcessBrowserTest:
void SetUpInProcessBrowserTestFixture() override {
// Initialize user policy.
ON_CALL(provider_, IsInitializationComplete(_)).WillByDefault(Return(true));
policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
}
void SetUpOnMainThread() override {
handler_ = std::make_unique<TestSecureDnsHandler>();
handler_->set_web_ui(&web_ui_);
handler_->RegisterMessages();
handler_->AllowJavascriptForTesting();
base::RunLoop().RunUntilIdle();
}
void TearDownOnMainThread() override { handler_.reset(); }
// Updates out-params from the last message sent to WebUI about a secure DNS
// change. Returns false if the message was invalid or not found.
bool GetLastSettingsChangedMessage(
std::string* secure_dns_mode,
std::vector<std::string>* secure_dns_templates,
int* management_mode) {
for (auto it = web_ui_.call_data().rbegin();
it != web_ui_.call_data().rend(); ++it) {
const content::TestWebUI::CallData* data = it->get();
if (data->function_name() != "cr.webUIListenerCallback" ||
!data->arg1()->is_string() ||
data->arg1()->GetString() != "secure-dns-setting-changed") {
continue;
}
const base::DictionaryValue* dict = nullptr;
if (!data->arg2()->GetAsDictionary(&dict))
return false;
// Get the secure DNS mode.
if (!dict->FindStringPath("mode"))
return false;
*secure_dns_mode = *dict->FindStringPath("mode");
// Get the secure DNS templates.
if (!dict->FindListPath("templates"))
return false;
secure_dns_templates->clear();
for (const auto& template_str :
dict->FindListPath("templates")->GetList()) {
if (!template_str.is_string())
return false;
secure_dns_templates->push_back(template_str.GetString());
}
// Get the forced management description.
if (!dict->FindIntPath("managementMode"))
return false;
*management_mode = *dict->FindIntPath("managementMode");
return true;
}
return false;
}
// Sets a policy update which will cause power pref managed change.
void SetPolicyForPolicyKey(policy::PolicyMap* policy_map,
const std::string& policy_key,
std::unique_ptr<base::Value> value) {
policy_map->Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
std::move(value), nullptr);
provider_.UpdateChromePolicy(*policy_map);
base::RunLoop().RunUntilIdle();
}
std::unique_ptr<TestSecureDnsHandler> handler_;
content::TestWebUI web_ui_;
policy::MockConfigurationPolicyProvider provider_;
private:
#if defined(OS_WIN)
base::win::ScopedDomainStateForTesting scoped_domain_;
#endif
DISALLOW_COPY_AND_ASSIGN(SecureDnsHandlerTest);
};
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsModes) {
PrefService* local_state = g_browser_process->local_state();
std::string secure_dns_mode;
std::vector<std::string> secure_dns_templates;
int management_mode;
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeOff);
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeAutomatic);
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeAutomatic, secure_dns_mode);
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeSecure);
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeSecure, secure_dns_mode);
local_state->SetString(prefs::kDnsOverHttpsMode, "unknown");
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsPolicy) {
policy::PolicyMap policy_map;
SetPolicyForPolicyKey(&policy_map, policy::key::kDnsOverHttpsMode,
std::make_unique<base::Value>(
chrome_browser_net::kDnsOverHttpsModeAutomatic));
PrefService* local_state = g_browser_process->local_state();
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeSecure);
std::string secure_dns_mode;
std::vector<std::string> secure_dns_templates;
int management_mode;
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeAutomatic, secure_dns_mode);
EXPECT_EQ(static_cast<int>(
chrome_browser_net::SecureDnsUiManagementMode::kNoOverride),
management_mode);
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsPolicyChange) {
policy::PolicyMap policy_map;
SetPolicyForPolicyKey(&policy_map, policy::key::kDnsOverHttpsMode,
std::make_unique<base::Value>(
chrome_browser_net::kDnsOverHttpsModeAutomatic));
std::string secure_dns_mode;
std::vector<std::string> secure_dns_templates;
int management_mode;
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeAutomatic, secure_dns_mode);
EXPECT_EQ(static_cast<int>(
chrome_browser_net::SecureDnsUiManagementMode::kNoOverride),
management_mode);
SetPolicyForPolicyKey(
&policy_map, policy::key::kDnsOverHttpsMode,
std::make_unique<base::Value>(chrome_browser_net::kDnsOverHttpsModeOff));
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
EXPECT_EQ(static_cast<int>(
chrome_browser_net::SecureDnsUiManagementMode::kNoOverride),
management_mode);
}
// On platforms where enterprise policies do not have default values, test
// that DoH is disabled when non-DoH policies are set.
#if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, OtherPoliciesSet) {
policy::PolicyMap policy_map;
SetPolicyForPolicyKey(&policy_map, policy::key::kIncognitoModeAvailability,
std::make_unique<base::Value>(1));
PrefService* local_state = g_browser_process->local_state();
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeSecure);
std::string secure_dns_mode;
std::vector<std::string> secure_dns_templates;
int management_mode;
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
EXPECT_EQ(
static_cast<int>(
chrome_browser_net::SecureDnsUiManagementMode::kDisabledManaged),
management_mode);
}
#endif
// This test makes no assumptions about the country or underlying resolver list.
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownList) {
base::ListValue args;
args.AppendString(kWebUiFunctionName);
web_ui_.HandleReceivedMessage(kGetSecureDnsResolverList, &args);
const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString());
ASSERT_TRUE(call_data.arg2()->GetBool());
// Check results.
base::Value::ConstListView resolver_list = call_data.arg3()->GetList();
ASSERT_GE(resolver_list.size(), 1U);
EXPECT_EQ("custom", resolver_list[0].FindKey("value")->GetString());
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListForCountry) {
// The 'EE' list should start with the custom entry, followed by the two
// global providers and the 'EE' provider in some random order.
base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry(
country_codes::CountryCharsToCountryID('E', 'E'),
GetDohProviderListForTesting());
EXPECT_EQ(4u, resolver_list.GetList().size());
EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
"https://global1.provider/dns-query{?dns}",
"https://global1.provider/privacy_policy/"));
EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2",
"https://global2.provider/dns-query{?dns}",
"https://global2.provider/privacy_policy/"));
EXPECT_TRUE(FindDropdownItem(resolver_list, "EE/FR Provider",
"https://ee.fr.provider/dns-query{?dns}",
"https://ee.fr.provider/privacy_policy/"));
// The 'FR' list should start with the custom entry, followed by the two
// global providers and the two 'FR' providers in some random order.
resolver_list = handler_->GetSecureDnsResolverListForCountry(
country_codes::CountryCharsToCountryID('F', 'R'),
GetDohProviderListForTesting());
EXPECT_EQ(5u, resolver_list.GetList().size());
EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
"https://global1.provider/dns-query{?dns}",
"https://global1.provider/privacy_policy/"));
EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2",
"https://global2.provider/dns-query{?dns}",
"https://global2.provider/privacy_policy/"));
EXPECT_TRUE(FindDropdownItem(resolver_list, "EE/FR Provider",
"https://ee.fr.provider/dns-query{?dns}",
"https://ee.fr.provider/privacy_policy/"));
EXPECT_TRUE(FindDropdownItem(resolver_list, "FR Provider",
"https://fr.provider/dns-query{?dns}",
"https://fr.provider/privacy_policy/"));
// The 'CA' list should start with the custom entry, followed by the two
// global providers.
resolver_list = handler_->GetSecureDnsResolverListForCountry(
country_codes::CountryCharsToCountryID('C', 'A'),
GetDohProviderListForTesting());
EXPECT_EQ(3u, resolver_list.GetList().size());
EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
"https://global1.provider/dns-query{?dns}",
"https://global1.provider/privacy_policy/"));
EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2",
"https://global2.provider/dns-query{?dns}",
"https://global2.provider/privacy_policy/"));
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListChange) {
// Populate the map for recording dropdown change metrics.
base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry(
country_codes::CountryCharsToCountryID('E', 'E'),
GetDohProviderListForTesting());
EXPECT_EQ(4u, resolver_list.GetList().size());
base::HistogramTester histograms;
base::ListValue args;
args.AppendString("custom" /* old_provider */);
args.AppendString(
"https://global1.provider/dns-query{?dns}" /* new_provider */);
web_ui_.HandleReceivedMessage(kRecordUserDropdownInteraction, &args);
const std::string uma_base("Net.DNS.UI.DropdownSelectionEvent");
histograms.ExpectTotalCount(uma_base + ".Ignored", 2u);
histograms.ExpectTotalCount(uma_base + ".Selected", 1u);
histograms.ExpectTotalCount(uma_base + ".Unselected", 1u);
}
class SecureDnsHandlerTestWithDisabledProviders : public SecureDnsHandlerTest {
protected:
SecureDnsHandlerTestWithDisabledProviders() {
scoped_features_.InitAndEnableFeatureWithParameters(
features::kDnsOverHttps,
{{"DisabledProviders",
"Provider_Global2, , Provider_EE_FR,Unexpected"}});
}
private:
base::test::ScopedFeatureList scoped_features_;
DISALLOW_COPY_AND_ASSIGN(SecureDnsHandlerTestWithDisabledProviders);
};
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders,
DropdownListDisabledProviders) {
// The 'FR' list should start with the custom entry, followed by the two
// global providers and the two 'FR' providers in some random order.
base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry(
country_codes::CountryCharsToCountryID('F', 'R'),
GetDohProviderListForTesting());
EXPECT_EQ(3u, resolver_list.GetList().size());
EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
"https://global1.provider/dns-query{?dns}",
"https://global1.provider/privacy_policy/"));
EXPECT_TRUE(FindDropdownItem(resolver_list, "FR Provider",
"https://fr.provider/dns-query{?dns}",
"https://fr.provider/privacy_policy/"));
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders,
SecureDnsTemplates) {
std::string good_post_template = "https://foo.test/";
std::string good_get_template = "https://bar.test/dns-query{?dns}";
std::string bad_template = "dns-query{?dns}";
std::string secure_dns_mode;
std::vector<std::string> secure_dns_templates;
int management_mode;
PrefService* local_state = g_browser_process->local_state();
local_state->SetString(prefs::kDnsOverHttpsTemplates, good_post_template);
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(1u, secure_dns_templates.size());
EXPECT_EQ(good_post_template, secure_dns_templates[0]);
local_state->SetString(prefs::kDnsOverHttpsTemplates,
good_post_template + " " + good_get_template);
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(2u, secure_dns_templates.size());
EXPECT_EQ(good_post_template, secure_dns_templates[0]);
EXPECT_EQ(good_get_template, secure_dns_templates[1]);
local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_template);
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(0u, secure_dns_templates.size());
local_state->SetString(prefs::kDnsOverHttpsTemplates,
bad_template + " " + good_post_template);
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(1u, secure_dns_templates.size());
EXPECT_EQ(good_post_template, secure_dns_templates[0]);
// Should still return a provider that was disabled.
local_state->SetString(prefs::kDnsOverHttpsTemplates,
"https://global2.provider/dns-query{?dns}");
EXPECT_TRUE(GetLastSettingsChangedMessage(
&secure_dns_mode, &secure_dns_templates, &management_mode));
EXPECT_EQ(1u, secure_dns_templates.size());
EXPECT_EQ("https://global2.provider/dns-query{?dns}",
secure_dns_templates[0]);
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateValid) {
base::ListValue args;
args.AppendString(kWebUiFunctionName);
args.AppendString("https://example.template/dns-query");
base::HistogramTester histograms;
web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args);
const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data.arg2()->GetBool());
// The template should be valid.
ASSERT_EQ("https://example.template/dns-query",
call_data.arg3()->GetString());
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 0);
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 1);
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateInvalid) {
base::ListValue args;
args.AppendString(kWebUiFunctionName);
args.AppendString("invalid_template");
base::HistogramTester histograms;
web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args);
const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data.arg2()->GetBool());
// The template should be invalid.
ASSERT_EQ(std::string(), call_data.arg3()->GetString());
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 1);
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 0);
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, MultipleTemplates) {
base::HistogramTester histograms;
base::ListValue args_valid;
args_valid.AppendString(kWebUiFunctionName);
args_valid.AppendString(
"invalid_template https://example.template/dns-query");
web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args_valid);
const content::TestWebUI::CallData& call_data_valid =
*web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data_valid.arg2()->GetBool());
// The second template should be valid.
ASSERT_EQ("https://example.template/dns-query",
call_data_valid.arg3()->GetString());
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 0);
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 1);
base::ListValue args_invalid;
args_invalid.AppendString(kWebUiFunctionName);
args_invalid.AppendString("invalid_template another_invalid_template");
web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args_invalid);
const content::TestWebUI::CallData& call_data_invalid =
*web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data_invalid.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data_invalid.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data_invalid.arg2()->GetBool());
// The entry should be invalid.
ASSERT_EQ(std::string(), call_data_invalid.arg3()->GetString());
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 1);
histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 1);
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeSuccess) {
auto network_context_ =
std::make_unique<chrome_browser_net::FakeHostResolverNetworkContext>(
std::vector<chrome_browser_net::FakeHostResolver::SingleResult>(
{chrome_browser_net::FakeHostResolver::SingleResult(
net::OK, net::ResolveErrorInfo(net::OK),
chrome_browser_net::FakeHostResolver::
kOneAddressResponse)}) /* current_config_result_list */,
std::vector<chrome_browser_net::FakeHostResolver::
SingleResult>() /* google_config_result_list */);
handler_->SetNetworkContextForTesting(network_context_.get());
base::HistogramTester histograms;
base::ListValue args_valid;
args_valid.AppendString(kWebUiFunctionName);
args_valid.AppendString("https://example.template/dns-query");
web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid);
base::RunLoop().RunUntilIdle();
const content::TestWebUI::CallData& call_data_valid =
*web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data_valid.arg2()->GetBool());
// The probe query should have succeeded.
ASSERT_TRUE(call_data_valid.arg3()->GetBool());
histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", false, 0);
histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", true, 1);
}
IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeFailure) {
auto network_context_ =
std::make_unique<chrome_browser_net::FakeHostResolverNetworkContext>(
std::vector<chrome_browser_net::FakeHostResolver::SingleResult>(
{chrome_browser_net::FakeHostResolver::SingleResult(
net::ERR_NAME_NOT_RESOLVED,
net::ResolveErrorInfo(net::ERR_DNS_MALFORMED_RESPONSE),
chrome_browser_net::FakeHostResolver::
kNoResponse)}) /* current_config_result_list */,
std::vector<chrome_browser_net::FakeHostResolver::
SingleResult>() /* google_config_result_list */);
handler_->SetNetworkContextForTesting(network_context_.get());
base::HistogramTester histograms;
base::ListValue args_valid;
args_valid.AppendString(kWebUiFunctionName);
args_valid.AppendString("https://example.template/dns-query");
web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid);
base::RunLoop().RunUntilIdle();
const content::TestWebUI::CallData& call_data_valid =
*web_ui_.call_data().back();
EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
// The request should be successful.
ASSERT_TRUE(call_data_valid.arg2()->GetBool());
// The probe query should have failed.
ASSERT_FALSE(call_data_valid.arg3()->GetBool());
histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", false, 1);
histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", true, 0);
}
} // namespace settings