|  | // 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/stub_resolver_config_reader.h" | 
|  |  | 
|  | #include <memory> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/test/task_environment.h" | 
|  | #include "base/values.h" | 
|  | #include "chrome/browser/net/secure_dns_config.h" | 
|  | #include "chrome/common/pref_names.h" | 
|  | #include "chrome/test/base/scoped_testing_local_state.h" | 
|  | #include "components/prefs/pref_service.h" | 
|  | #include "components/prefs/testing_pref_service.h" | 
|  | #include "content/public/test/browser_task_environment.h" | 
|  | #include "net/dns/public/dns_over_https_server_config.h" | 
|  | #include "net/dns/public/secure_dns_mode.h" | 
|  | #include "testing/gmock/include/gmock/gmock.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | constexpr char kDohServerTemplate[] = | 
|  | "https://doh1.test https://doh2.test/query{?dns}"; | 
|  |  | 
|  | // Override the reader to mock out the ShouldDisableDohFor...() methods. | 
|  | class MockedStubResolverConfigReader : public StubResolverConfigReader { | 
|  | public: | 
|  | explicit MockedStubResolverConfigReader(PrefService* local_state) | 
|  | : StubResolverConfigReader(local_state, | 
|  | false /* set_up_pref_defaults */) {} | 
|  |  | 
|  | bool ShouldDisableDohForManaged() override { return disable_for_managed_; } | 
|  |  | 
|  | bool ShouldDisableDohForParentalControls() override { | 
|  | parental_controls_checked_ = true; | 
|  | return disable_for_parental_controls_; | 
|  | } | 
|  |  | 
|  | void set_disable_for_managed() { disable_for_managed_ = true; } | 
|  |  | 
|  | void set_disable_for_parental_controls() { | 
|  | disable_for_parental_controls_ = true; | 
|  | } | 
|  |  | 
|  | bool parental_controls_checked() { return parental_controls_checked_; } | 
|  |  | 
|  | private: | 
|  | bool disable_for_managed_ = false; | 
|  | bool disable_for_parental_controls_ = false; | 
|  |  | 
|  | bool parental_controls_checked_ = false; | 
|  | }; | 
|  |  | 
|  | class StubResolverConfigReaderTest : public testing::Test { | 
|  | public: | 
|  | StubResolverConfigReaderTest() { | 
|  | StubResolverConfigReader::RegisterPrefs(local_state_.registry()); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | content::BrowserTaskEnvironment task_environment_{ | 
|  | base::test::TaskEnvironment::TimeSource::MOCK_TIME}; | 
|  | TestingPrefServiceSimple local_state_; | 
|  | std::unique_ptr<MockedStubResolverConfigReader> config_reader_ = | 
|  | std::make_unique<MockedStubResolverConfigReader>(&local_state_); | 
|  | }; | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, GetSecureDnsConfiguration) { | 
|  | // |force_check_parental_controls_for_automatic_mode = true| is not the main | 
|  | // default case, but the specific behavior involved is tested separately. | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | true /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_FALSE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); | 
|  | EXPECT_TRUE(secure_dns_config.servers().empty()); | 
|  |  | 
|  | // Parental controls should not be checked when DoH otherwise disabled. | 
|  | EXPECT_FALSE(config_reader_->parental_controls_checked()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DohEnabled) { | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsMode, | 
|  | SecureDnsConfig::kModeAutomatic); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate); | 
|  |  | 
|  | // |force_check_parental_controls_for_automatic_mode = true| is not the main | 
|  | // default case, but the specific behavior involved is tested separately. | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | true /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); | 
|  | EXPECT_THAT(secure_dns_config.servers(), | 
|  | testing::ElementsAre( | 
|  | net::DnsOverHttpsServerConfig("https://doh1.test", | 
|  | true /* use_post */), | 
|  | net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}", | 
|  | false /* use_post */))); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->parental_controls_checked()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DohEnabled_Secure) { | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsMode, | 
|  | SecureDnsConfig::kModeSecure); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate); | 
|  |  | 
|  | // |force_check_parental_controls_for_automatic_mode| should have no effect on | 
|  | // SECURE mode, so set to false to ensure check is not deferred. | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | false /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kSecure, secure_dns_config.mode()); | 
|  | EXPECT_THAT(secure_dns_config.servers(), | 
|  | testing::ElementsAre( | 
|  | net::DnsOverHttpsServerConfig("https://doh1.test", | 
|  | true /* use_post */), | 
|  | net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}", | 
|  | false /* use_post */))); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->parental_controls_checked()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DisabledForManaged) { | 
|  | config_reader_->set_disable_for_managed(); | 
|  |  | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsMode, | 
|  | SecureDnsConfig::kModeAutomatic); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate); | 
|  |  | 
|  | // |force_check_parental_controls_for_automatic_mode = true| is not the main | 
|  | // default case, but the specific behavior involved is tested separately. | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | true /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); | 
|  | EXPECT_TRUE(secure_dns_config.servers().empty()); | 
|  |  | 
|  | // Parental controls should not be checked when DoH otherwise disabled. | 
|  | EXPECT_FALSE(config_reader_->parental_controls_checked()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DisabledForManaged_Secure) { | 
|  | config_reader_->set_disable_for_managed(); | 
|  |  | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsMode, | 
|  | SecureDnsConfig::kModeSecure); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate); | 
|  |  | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | false /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); | 
|  | EXPECT_TRUE(secure_dns_config.servers().empty()); | 
|  |  | 
|  | // Parental controls should not be checked when DoH otherwise disabled. | 
|  | EXPECT_FALSE(config_reader_->parental_controls_checked()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DisabledForParentalControls) { | 
|  | config_reader_->set_disable_for_parental_controls(); | 
|  |  | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsMode, | 
|  | SecureDnsConfig::kModeAutomatic); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate); | 
|  |  | 
|  | // |force_check_parental_controls_for_automatic_mode = true| is not the main | 
|  | // default case, but the specific behavior involved is tested separately. | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | true /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); | 
|  | EXPECT_TRUE(secure_dns_config.servers().empty()); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->parental_controls_checked()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DisabledForParentalControls_Secure) { | 
|  | config_reader_->set_disable_for_parental_controls(); | 
|  |  | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsMode, | 
|  | SecureDnsConfig::kModeSecure); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate); | 
|  |  | 
|  | // |force_check_parental_controls_for_automatic_mode| should have no effect on | 
|  | // SECURE mode, so set to false to ensure check is not deferred. | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | false /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); | 
|  | EXPECT_TRUE(secure_dns_config.servers().empty()); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->parental_controls_checked()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DeferredParentalControlsCheck) { | 
|  | config_reader_->set_disable_for_parental_controls(); | 
|  |  | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsMode, | 
|  | SecureDnsConfig::kModeAutomatic); | 
|  | local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate); | 
|  |  | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | false /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | // Parental controls check initially skipped. | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); | 
|  | EXPECT_THAT(secure_dns_config.servers(), | 
|  | testing::ElementsAre( | 
|  | net::DnsOverHttpsServerConfig("https://doh1.test", | 
|  | true /* use_post */), | 
|  | net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}", | 
|  | false /* use_post */))); | 
|  | EXPECT_FALSE(config_reader_->parental_controls_checked()); | 
|  |  | 
|  | task_environment_.AdvanceClock( | 
|  | StubResolverConfigReader::kParentalControlsCheckDelay); | 
|  | task_environment_.RunUntilIdle(); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->parental_controls_checked()); | 
|  |  | 
|  | secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | false /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); | 
|  | EXPECT_TRUE(secure_dns_config.servers().empty()); | 
|  | } | 
|  |  | 
|  | TEST_F(StubResolverConfigReaderTest, DeferredParentalControlsCheck_Managed) { | 
|  | config_reader_->set_disable_for_managed(); | 
|  | config_reader_->set_disable_for_parental_controls(); | 
|  |  | 
|  | local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true); | 
|  | local_state_.SetManagedPref( | 
|  | prefs::kDnsOverHttpsMode, | 
|  | std::make_unique<base::Value>(SecureDnsConfig::kModeAutomatic)); | 
|  | local_state_.SetManagedPref( | 
|  | prefs::kDnsOverHttpsTemplates, | 
|  | std::make_unique<base::Value>(kDohServerTemplate)); | 
|  |  | 
|  | SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | false /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | // Parental controls check initially skipped, and managed prefs take | 
|  | // precedence over disables. | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); | 
|  | EXPECT_THAT(secure_dns_config.servers(), | 
|  | testing::ElementsAre( | 
|  | net::DnsOverHttpsServerConfig("https://doh1.test", | 
|  | true /* use_post */), | 
|  | net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}", | 
|  | false /* use_post */))); | 
|  | EXPECT_FALSE(config_reader_->parental_controls_checked()); | 
|  |  | 
|  | task_environment_.AdvanceClock( | 
|  | StubResolverConfigReader::kParentalControlsCheckDelay); | 
|  | task_environment_.RunUntilIdle(); | 
|  |  | 
|  | EXPECT_TRUE(config_reader_->parental_controls_checked()); | 
|  |  | 
|  | secure_dns_config = config_reader_->GetSecureDnsConfiguration( | 
|  | false /* force_check_parental_controls_for_automatic_mode */); | 
|  |  | 
|  | // Expect DoH still enabled after parental controls check because managed | 
|  | // prefs have precedence. | 
|  | EXPECT_TRUE(config_reader_->GetInsecureStubResolverEnabled()); | 
|  | EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); | 
|  | EXPECT_THAT(secure_dns_config.servers(), | 
|  | testing::ElementsAre( | 
|  | net::DnsOverHttpsServerConfig("https://doh1.test", | 
|  | true /* use_post */), | 
|  | net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}", | 
|  | false /* use_post */))); | 
|  | } | 
|  |  | 
|  | }  // namespace |