Restore the DNS over HTTPS work-around on Windows (#15989)

Re-introduces logic from https://github.com/brave/brave-core/pull/13434
This reverts commit b9f88f6d1b.

Fixes https://github.com/brave/brave-browser/issues/26787

Co-authored-by: Brian Clifton <brian@clifton.me>
This commit is contained in:
Cepera
2022-12-13 18:14:30 +03:00
committed by GitHub
co-authored by Brian Clifton
parent 6cd003869b
commit 604800b04e
27 changed files with 1338 additions and 11 deletions
+18 -1
View File
@@ -229,7 +229,12 @@ constexpr char kBraveSyncDescription[] =
constexpr char kBraveVPNName[] = "Enable experimental Brave VPN";
constexpr char kBraveVPNDescription[] = "Experimental native VPN support";
#if BUILDFLAG(IS_WIN)
constexpr char kBraveVPNDnsProtectionName[] = "Enable DoH for Brave VPN";
constexpr char kBraveVPNDnsProtectionDescription[] =
"Override DoH settings with Cloudflare dns if necessary to avoid leaking "
"requests due to Smart Multi-Home Named Resolution";
#endif
constexpr char kBraveSkusSdkName[] = "Enable experimental SKU SDK";
constexpr char kBraveSkusSdkDescription[] = "Experimental SKU SDK support";
@@ -422,8 +427,19 @@ constexpr char kBraveAndroidSafeBrowsingDescription[] =
flag_descriptions::kBraveVPNDescription, \
kOsMac | kOsWin, \
FEATURE_VALUE_TYPE(brave_vpn::features::kBraveVPN)},
#if BUILDFLAG(IS_WIN)
#define BRAVE_VPN_DNS_FEATURE_ENTRIES \
{kBraveVPNDnsFeatureInternalName, \
flag_descriptions::kBraveVPNDnsProtectionName, \
flag_descriptions::kBraveVPNDnsProtectionDescription, \
kOsWin, \
FEATURE_VALUE_TYPE(brave_vpn::features::kBraveVPNDnsProtection)},
#else
#define BRAVE_VPN_DNS_FEATURE_ENTRIES
#endif
#else
#define BRAVE_VPN_FEATURE_ENTRIES
#define BRAVE_VPN_DNS_FEATURE_ENTRIES
#endif
#define BRAVE_SKU_SDK_FEATURE_ENTRIES \
@@ -734,6 +750,7 @@ constexpr char kBraveAndroidSafeBrowsingDescription[] =
CRYPTO_WALLETS_FEATURE_ENTRIES \
BRAVE_REWARDS_GEMINI_FEATURE_ENTRIES \
BRAVE_VPN_FEATURE_ENTRIES \
BRAVE_VPN_DNS_FEATURE_ENTRIES \
BRAVE_SKU_SDK_FEATURE_ENTRIES \
SPEEDREADER_FEATURE_ENTRIES \
BRAVE_TRANSLATE_GO_FEATURE_ENTRIES \
+9 -1
View File
@@ -6,7 +6,15 @@
#ifndef BRAVE_BROWSER_BRAVE_FEATURES_INTERNAL_NAMES_H_
#define BRAVE_BROWSER_BRAVE_FEATURES_INTERNAL_NAMES_H_
constexpr char kBraveVPNFeatureInternalName[] = "brave-vpn";
#include "brave/components/brave_vpn/buildflags/buildflags.h"
#include "build/build_config.h"
constexpr char kPlaylistFeatureInternalName[] = "playlist";
#if BUILDFLAG(ENABLE_BRAVE_VPN)
constexpr char kBraveVPNFeatureInternalName[] = "brave-vpn";
#if BUILDFLAG(IS_WIN)
constexpr char kBraveVPNDnsFeatureInternalName[] = "brave-vpn-dns";
#endif
#endif
#endif // BRAVE_BROWSER_BRAVE_FEATURES_INTERNAL_NAMES_H_
+4
View File
@@ -5,6 +5,8 @@
#include "brave/browser/brave_local_state_prefs.h"
#include <string>
#include "base/values.h"
#include "brave/browser/brave_stats/brave_stats_updater.h"
#include "brave/browser/metrics/buildflags/buildflags.h"
@@ -128,6 +130,8 @@ void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
skus::RegisterLocalStatePrefs(registry);
#endif
registry->RegisterStringPref(::prefs::kBraveVpnDnsConfig, std::string());
ntp_background_images::NTPP3AHelperImpl::RegisterLocalStatePrefs(registry);
core_metrics::CoreMetricsService::RegisterPrefs(registry);
+22 -2
View File
@@ -11,6 +11,7 @@
#include "brave/components/brave_vpn/brave_vpn_os_connection_api.h"
#include "brave/components/brave_vpn/brave_vpn_service.h"
#include "brave/components/brave_vpn/brave_vpn_utils.h"
#include "brave/components/brave_vpn/features.h"
#include "brave/components/skus/common/features.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
@@ -21,6 +22,11 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#if BUILDFLAG(IS_WIN)
#include "brave/browser/brave_vpn/dns/brave_vpn_dns_observer_factory.h"
#include "brave/browser/brave_vpn/dns/brave_vpn_dns_observer_service.h"
#endif
namespace brave_vpn {
// static
@@ -50,6 +56,11 @@ BraveVpnServiceFactory::BraveVpnServiceFactory()
"BraveVpnService",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(skus::SkusServiceFactory::GetInstance());
#if BUILDFLAG(IS_WIN)
DependsOn(brave_vpn::BraveVpnDnsObserverFactory::GetInstance());
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
auto* connection_api = BraveVPNOSConnectionAPI::GetInstance();
connection_api->set_shared_url_loader_factory(
@@ -77,8 +88,17 @@ KeyedService* BraveVpnServiceFactory::BuildServiceInstanceFor(
},
context);
return new BraveVpnService(shared_url_loader_factory, local_state,
user_prefs::UserPrefs::Get(context), callback);
auto* vpn_service =
new BraveVpnService(shared_url_loader_factory, local_state,
user_prefs::UserPrefs::Get(context), callback);
#if BUILDFLAG(IS_WIN)
auto* dns_observer_service =
brave_vpn::BraveVpnDnsObserverFactory::GetInstance()
->GetServiceForContext(context);
if (dns_observer_service)
dns_observer_service->Observe(vpn_service);
#endif
return vpn_service;
}
void BraveVpnServiceFactory::RegisterProfilePrefs(
+22
View File
@@ -0,0 +1,22 @@
# Copyright (c) 2022 The Brave Authors. All rights reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at https://mozilla.org/MPL/2.0/.
import("//brave/components/brave_vpn/buildflags/buildflags.gni")
import("//testing/test.gni")
source_set("unit_tests") {
testonly = true
if (enable_brave_vpn && is_win) {
sources = [ "brave_vpn_dns_observer_service_unittest.cc" ]
deps = [
"//brave/components/brave_vpn",
"//chrome/common:constants",
"//chrome/test:test_support",
"//net",
"//testing/gtest",
"//third_party/abseil-cpp:absl",
]
}
}
@@ -0,0 +1,61 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "brave/browser/brave_vpn/dns/brave_vpn_dns_observer_factory.h"
#include <cstddef>
#include <memory>
#include <string>
#include "base/feature_list.h"
#include "brave/browser/brave_vpn/dns/brave_vpn_dns_observer_service.h"
#include "brave/components/brave_vpn/brave_vpn_utils.h"
#include "brave/components/brave_vpn/features.h"
#include "brave/components/brave_vpn/pref_names.h"
#include "chrome/browser/browser_process.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
namespace brave_vpn {
// static
BraveVpnDnsObserverFactory* BraveVpnDnsObserverFactory::GetInstance() {
return base::Singleton<BraveVpnDnsObserverFactory>::get();
}
BraveVpnDnsObserverFactory::~BraveVpnDnsObserverFactory() = default;
BraveVpnDnsObserverFactory::BraveVpnDnsObserverFactory()
: BrowserContextKeyedServiceFactory(
"BraveVpnDNSObserverService",
BrowserContextDependencyManager::GetInstance()) {}
KeyedService* BraveVpnDnsObserverFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
return new BraveVpnDnsObserverService(g_browser_process->local_state(),
user_prefs::UserPrefs::Get(context));
}
// static
BraveVpnDnsObserverService* BraveVpnDnsObserverFactory::GetServiceForContext(
content::BrowserContext* context) {
if (!base::FeatureList::IsEnabled(
brave_vpn::features::kBraveVPNDnsProtection)) {
return nullptr;
}
DCHECK(IsBraveVPNEnabled());
return static_cast<BraveVpnDnsObserverService*>(
GetInstance()->GetServiceForBrowserContext(context, true));
}
void BraveVpnDnsObserverFactory::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(prefs::kBraveVpnShowDNSPolicyWarningDialog,
true);
}
} // namespace brave_vpn
@@ -0,0 +1,49 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_BROWSER_BRAVE_VPN_DNS_BRAVE_VPN_DNS_OBSERVER_FACTORY_H_
#define BRAVE_BROWSER_BRAVE_VPN_DNS_BRAVE_VPN_DNS_OBSERVER_FACTORY_H_
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace content {
class BrowserContext;
} // namespace content
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
namespace brave_vpn {
class BraveVpnDnsObserverService;
class BraveVpnDnsObserverFactory : public BrowserContextKeyedServiceFactory {
public:
BraveVpnDnsObserverFactory(const BraveVpnDnsObserverFactory&) = delete;
BraveVpnDnsObserverFactory& operator=(const BraveVpnDnsObserverFactory&) =
delete;
static BraveVpnDnsObserverFactory* GetInstance();
static BraveVpnDnsObserverService* GetServiceForContext(
content::BrowserContext* context);
void RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) override;
private:
friend struct base::DefaultSingletonTraits<BraveVpnDnsObserverFactory>;
BraveVpnDnsObserverFactory();
~BraveVpnDnsObserverFactory() override;
// BrowserContextKeyedServiceFactory overrides:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
};
} // namespace brave_vpn
#endif // BRAVE_BROWSER_BRAVE_VPN_DNS_BRAVE_VPN_DNS_OBSERVER_FACTORY_H_
@@ -0,0 +1,131 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "brave/browser/brave_vpn/dns/brave_vpn_dns_observer_service.h"
#include <vector>
#include "base/strings/string_util.h"
#include "brave/browser/ui/views/brave_vpn/brave_vpn_dns_settings_notificiation_dialog_view.h"
#include "brave/components/brave_vpn/brave_vpn_utils.h"
#include "brave/components/brave_vpn/pref_names.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/chromium_strings.h"
#include "components/grit/brave_components_strings.h"
#include "components/prefs/pref_service.h"
#include "ui/base/l10n/l10n_util.h"
namespace brave_vpn {
namespace {
const char kCloudflareDnsProviderURL[] =
"https://chrome.cloudflare-dns.com/dns-query";
void SkipDNSDialog(PrefService* prefs, bool checked) {
if (!prefs)
return;
prefs->SetBoolean(prefs::kBraveVpnShowDNSPolicyWarningDialog, !checked);
}
gfx::NativeWindow GetAnchorBrowserWindow() {
auto* browser = chrome::FindLastActive();
return browser ? browser->window()->GetNativeWindow()
: gfx::kNullNativeWindow;
}
bool AreConfigsEqual(SecureDnsConfig& one, SecureDnsConfig& two) {
return one.mode() == two.mode() &&
one.management_mode() == two.management_mode() &&
one.doh_servers() == two.doh_servers();
}
} // namespace
BraveVpnDnsObserverService::BraveVpnDnsObserverService(
PrefService* local_state,
PrefService* profile_prefs)
: local_state_(local_state), profile_prefs_(profile_prefs) {
DCHECK(profile_prefs_);
DCHECK(local_state_);
local_state_->ClearPref(::prefs::kBraveVpnDnsConfig);
}
BraveVpnDnsObserverService::~BraveVpnDnsObserverService() = default;
void BraveVpnDnsObserverService::ShowPolicyWarningMessage() {
if (!profile_prefs_->GetBoolean(prefs::kBraveVpnShowDNSPolicyWarningDialog)) {
return;
}
if (policy_callback_) {
std::move(policy_callback_).Run();
return;
}
chrome::ShowWarningMessageBoxWithCheckbox(
GetAnchorBrowserWindow(), l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
l10n_util::GetStringUTF16(IDS_BRAVE_VPN_DNS_POLICY_ALERT),
l10n_util::GetStringUTF16(IDS_BRAVE_VPN_DNS_POLICY_CHECKBOX),
base::BindOnce(&SkipDNSDialog, profile_prefs_));
}
void BraveVpnDnsObserverService::ShowVpnDnsSettingsNotificationDialog() {
if (dialog_callback_) {
dialog_callback_.Run();
return;
}
BraveVpnDnsSettingsNotificiationDialogView::Show(chrome::FindLastActive());
}
void BraveVpnDnsObserverService::UnlockDNS() {
local_state_->ClearPref(::prefs::kBraveVpnDnsConfig);
// Read DNS config to initiate update of actual state.
SystemNetworkContextManager::GetStubResolverConfigReader()
->UpdateNetworkService(false);
}
void BraveVpnDnsObserverService::LockDNS() {
auto old_dns_config =
SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(false);
local_state_->SetString(::prefs::kBraveVpnDnsConfig,
kCloudflareDnsProviderURL);
// Trigger StubResolverConfigReader to see if it should override the settings
// with kBraveVpnDnsConfig
SystemNetworkContextManager::GetStubResolverConfigReader()
->UpdateNetworkService(false);
auto new_dns_config =
SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(false);
if (old_dns_config.mode() != net::SecureDnsMode::kSecure) {
if (AreConfigsEqual(old_dns_config, new_dns_config)) {
ShowPolicyWarningMessage();
} else {
ShowVpnDnsSettingsNotificationDialog();
}
}
}
void BraveVpnDnsObserverService::OnConnectionStateChanged(
brave_vpn::mojom::ConnectionState state) {
if (state == brave_vpn::mojom::ConnectionState::CONNECTED) {
LockDNS();
} else if (state == brave_vpn::mojom::ConnectionState::DISCONNECTED) {
UnlockDNS();
}
}
} // namespace brave_vpn
@@ -0,0 +1,68 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_BROWSER_BRAVE_VPN_DNS_BRAVE_VPN_DNS_OBSERVER_SERVICE_H_
#define BRAVE_BROWSER_BRAVE_VPN_DNS_BRAVE_VPN_DNS_OBSERVER_SERVICE_H_
#include <memory>
#include <string>
#include <utility>
#include "base/memory/weak_ptr.h"
#include "brave/components/brave_vpn/brave_vpn_service_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "net/dns/dns_config.h"
#include "net/dns/dns_config_service.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
namespace brave_vpn {
class BraveVpnDnsObserverService : public brave_vpn::BraveVPNServiceObserver,
public KeyedService {
public:
explicit BraveVpnDnsObserverService(PrefService* local_state,
PrefService* profile_prefs);
~BraveVpnDnsObserverService() override;
BraveVpnDnsObserverService(const BraveVpnDnsObserverService&) = delete;
BraveVpnDnsObserverService operator=(const BraveVpnDnsObserverService&) =
delete;
// brave_vpn::BraveVPNServiceObserver
void OnConnectionStateChanged(
brave_vpn::mojom::ConnectionState state) override;
void SetPolicyNotificationCallbackForTesting(base::OnceClosure callback) {
policy_callback_ = std::move(callback);
}
void SetVPNNotificationCallbackForTesting(base::RepeatingClosure callback) {
dialog_callback_ = std::move(callback);
}
private:
friend class BraveVpnDnsObserverServiceUnitTest;
void OnPrefChanged();
void LockDNS();
void UnlockDNS();
void ShowPolicyWarningMessage();
void ShowVpnDnsSettingsNotificationDialog();
void OnDnsModePrefChanged();
base::OnceClosure policy_callback_;
base::RepeatingClosure dialog_callback_;
bool skip_notification_dialog_for_testing_ = false;
raw_ptr<PrefService> local_state_;
raw_ptr<PrefService> profile_prefs_;
base::WeakPtrFactory<BraveVpnDnsObserverService> weak_ptr_factory_{this};
};
} // namespace brave_vpn
#endif // BRAVE_BROWSER_BRAVE_VPN_DNS_BRAVE_VPN_DNS_OBSERVER_SERVICE_H_
@@ -0,0 +1,392 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "brave/browser/brave_vpn/dns/brave_vpn_dns_observer_service.h"
#include <unordered_map>
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "brave/browser/brave_profile_prefs.h"
#include "brave/browser/brave_vpn/dns/brave_vpn_dns_observer_factory.h"
#include "brave/components/brave_vpn/brave_vpn_utils.h"
#include "brave/components/brave_vpn/features.h"
#include "brave/components/brave_vpn/pref_names.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/secure_dns_util.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "net/dns/public/secure_dns_mode.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace brave_vpn {
namespace {
const char kCustomServersURLs[] =
"https://server1.com\nhttps://server2.com/{?dns}";
const char kCloudflareDnsProviderURL[] =
"https://chrome.cloudflare-dns.com/dns-query";
} // namespace
class BraveVpnDnsObserverServiceUnitTest : public testing::Test {
public:
BraveVpnDnsObserverServiceUnitTest() {}
void SetUp() override {
RegisterLocalState(local_state_.registry());
BraveVpnDnsObserverFactory::GetInstance()->RegisterProfilePrefs(
profile_pref_service_.registry());
stub_resolver_config_reader_ =
std::make_unique<StubResolverConfigReader>(&local_state_);
SystemNetworkContextManager::set_stub_resolver_config_reader_for_testing(
stub_resolver_config_reader_.get());
CreateDnsObserverService();
}
void CreateDnsObserverService() {
dns_observer_service_.reset(
new BraveVpnDnsObserverService(local_state(), pref_service()));
dns_observer_service_->SetVPNNotificationCallbackForTesting(
base::DoNothing());
}
void ResetDnsObserverService() { dns_observer_service_.reset(); }
void TearDown() override {
// BraveVpnDnsObserverService destructor must be called before the task
// runner is destroyed.
ResetDnsObserverService();
}
void EnableParentalControl(bool value) {
StubResolverConfigReader* config_reader =
SystemNetworkContextManager::GetStubResolverConfigReader();
config_reader->OverrideParentalControlsForTesting(value);
}
PrefService* local_state() { return &local_state_; }
PrefService* pref_service() { return &profile_pref_service_; }
void FireBraveVPNStateChange(mojom::ConnectionState state) {
dns_observer_service_->OnConnectionStateChanged(state);
}
bool WasVpnNotificationShownForState(mojom::ConnectionState state) {
bool callback_called = false;
dns_observer_service_->SetVPNNotificationCallbackForTesting(
base::BindLambdaForTesting([&]() { callback_called = true; }));
FireBraveVPNStateChange(state);
return callback_called;
}
void CheckUserNotifiedAndDnsOverridenOnLaunch(
const std::string& user_dns_mode,
const std::string& user_servers,
const std::string& expected_servers,
bool expected_dialog_shown) {
ResetDnsObserverService();
// DNS mode was set to off by user.
SetDNSMode(user_dns_mode, user_servers);
// Set vpn config to indicate vpn was enabled when browser closed
local_state()->SetString(::prefs::kBraveVpnDnsConfig,
kCloudflareDnsProviderURL);
CreateDnsObserverService();
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
// After launch BraveVPNService will notify observers with actual state.
// and we expect the dns notification dialog will not be shown as vpn is
// enabled.
EXPECT_EQ(
WasVpnNotificationShownForState(mojom::ConnectionState::CONNECTED),
expected_dialog_shown);
// the dns config was overriden.
ExpectDNSMode(SecureDnsConfig::kModeSecure, expected_servers);
}
void SetDNSMode(const std::string& mode, const std::string& doh_providers) {
local_state()->SetString(::prefs::kDnsOverHttpsTemplates, doh_providers);
local_state()->SetString(::prefs::kDnsOverHttpsMode, mode);
SystemNetworkContextManager::GetStubResolverConfigReader()
->UpdateNetworkService(false);
}
bool WasPolicyNotificationShownForState(mojom::ConnectionState state) {
bool callback_called = false;
dns_observer_service_->SetPolicyNotificationCallbackForTesting(
base::BindLambdaForTesting([&]() { callback_called = true; }));
FireBraveVPNStateChange(state);
return callback_called;
}
void ExpectDNSMode(const std::string& mode,
const std::string& doh_providers) {
auto dns_config = SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(false);
auto* current_mode = SecureDnsConfig::ModeToString(dns_config.mode());
auto current_servers = dns_config.doh_servers().ToString();
EXPECT_EQ(current_mode, mode);
EXPECT_EQ(current_servers, doh_providers);
}
void SetManagedMode(const std::string& value) {
local_state_.SetManagedPref(::prefs::kDnsOverHttpsMode,
std::make_unique<base::Value>(value));
}
private:
std::unordered_map<std::string, std::string> policy_map_;
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<BraveVpnDnsObserverService> dns_observer_service_;
sync_preferences::TestingPrefServiceSyncable profile_pref_service_;
TestingPrefServiceSimple local_state_;
std::unique_ptr<StubResolverConfigReader> stub_resolver_config_reader_;
};
TEST_F(BraveVpnDnsObserverServiceUnitTest, OverrideDohConfigForOffMode) {
// Browser DoH mode off -> override browser config and enable vpn
local_state()->ClearPref(::prefs::kBraveVpnDnsConfig);
SetDNSMode(SecureDnsConfig::kModeOff, "");
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
EXPECT_FALSE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
TEST_F(BraveVpnDnsObserverServiceUnitTest, OverrideDohConfigForAutomaticMode) {
// Browser DoH mode automatic -> override browser config and enable vpn
SetDNSMode(SecureDnsConfig::kModeAutomatic, "");
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, "");
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
EXPECT_FALSE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, "");
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
TEST_F(BraveVpnDnsObserverServiceUnitTest, OverrideDohConfigForSecureMode) {
// Browser DoH mode secure -> override browser config and enable vpn
SetDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
EXPECT_FALSE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
OverrideDohConfigForAutomaticModeWithValidCustomServers) {
// Browser DoH mode automatic with custom servers
// -> we override browser config and enable vpn
SetDNSMode(SecureDnsConfig::kModeAutomatic, kCustomServersURLs);
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, kCustomServersURLs);
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
EXPECT_FALSE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, kCustomServersURLs);
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
OverrideDohConfigForAutomaticModeWithBrokenCustomServers) {
// Browser DoH mode automatic with broken custom servers
// -> override browser config and enable vpn
SetDNSMode(SecureDnsConfig::kModeAutomatic, std::string());
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, std::string());
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
EXPECT_FALSE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, std::string());
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
OverrideDohConfigForSecureModeWithCustomServers) {
// Browser DoH mode secure with custom servers
// -> override browser config and enable vpn
SetDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
EXPECT_FALSE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTING);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
DoNotOverrideDoHConfigWithPolicyOff) {
SetManagedMode(SecureDnsConfig::kModeOff);
SetDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_TRUE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_FALSE(WasPolicyNotificationShownForState(
mojom::ConnectionState::DISCONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::DISCONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
DoNotOverrideDoHConfigWithPolicyAutomatic) {
SetManagedMode(SecureDnsConfig::kModeAutomatic);
SetDNSMode(SecureDnsConfig::kModeAutomatic, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, "");
EXPECT_TRUE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, "");
EXPECT_FALSE(WasPolicyNotificationShownForState(
mojom::ConnectionState::DISCONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::DISCONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeAutomatic, "");
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
DoNotOverrideDoHConfigWithPolicySecure) {
SetManagedMode(SecureDnsConfig::kModeSecure);
SetDNSMode(SecureDnsConfig::kModeSecure, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeSecure, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeSecure, "");
EXPECT_FALSE(WasPolicyNotificationShownForState(
mojom::ConnectionState::DISCONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeSecure, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::DISCONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeSecure, "");
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
DoNotOverrideDoHConfigWithPolicySecureAndCustomServers) {
SetDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
SetManagedMode(SecureDnsConfig::kModeSecure);
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
EXPECT_FALSE(WasPolicyNotificationShownForState(
mojom::ConnectionState::DISCONNECTING));
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::DISCONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCustomServersURLs);
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
DoNotOverrideDoHConfigWithParentalControlEnabled) {
SetDNSMode(SecureDnsConfig::kModeSecure, "");
EnableParentalControl(true);
EXPECT_TRUE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::DISCONNECTED));
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EnableParentalControl(false);
ExpectDNSMode(SecureDnsConfig::kModeSecure, "");
}
TEST_F(BraveVpnDnsObserverServiceUnitTest, DoNotShowPolicyDialogIfUserSkipped) {
// Do not show dialog option enabled
SetManagedMode(SecureDnsConfig::kModeOff);
pref_service()->SetBoolean(prefs::kBraveVpnShowDNSPolicyWarningDialog, false);
SetDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_FALSE(
WasPolicyNotificationShownForState(mojom::ConnectionState::CONNECTED));
}
TEST_F(BraveVpnDnsObserverServiceUnitTest, DnsOverridenOnLaunchIfVPNEnabled) {
CheckUserNotifiedAndDnsOverridenOnLaunch(SecureDnsConfig::kModeOff,
std::string(),
kCloudflareDnsProviderURL, true);
CheckUserNotifiedAndDnsOverridenOnLaunch(SecureDnsConfig::kModeAutomatic,
std::string(),
kCloudflareDnsProviderURL, true);
CheckUserNotifiedAndDnsOverridenOnLaunch(SecureDnsConfig::kModeSecure, "", "",
false);
}
TEST_F(BraveVpnDnsObserverServiceUnitTest,
VPNConnectedOnBrowserShutDownAndDisconnectedOnStart) {
ResetDnsObserverService();
// DNS mode was set to off by user.
SetDNSMode(SecureDnsConfig::kModeOff, "");
// Set vpn config to indicate vpn was enabled when browser closed.
local_state()->SetString(::prefs::kBraveVpnDnsConfig,
kCloudflareDnsProviderURL);
CreateDnsObserverService();
// Before VPN service initialization we have vpn overriden.
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
// On launch vpn service notifies it is disconnected.
FireBraveVPNStateChange(mojom::ConnectionState::DISCONNECTED);
// Do not override anymore as vpn is disconnected.
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_TRUE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
TEST_F(BraveVpnDnsObserverServiceUnitTest, FeatureDisabledWhenVPNConnected) {
// DNS mode was set to off by user and the vpn dns observer feature
// is enabled by default.
SetDNSMode(SecureDnsConfig::kModeOff, "");
FireBraveVPNStateChange(mojom::ConnectionState::CONNECTED);
ExpectDNSMode(SecureDnsConfig::kModeSecure, kCloudflareDnsProviderURL);
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
brave_vpn::features::kBraveVPNDnsProtection);
// Do not override anymore because the feature is disabled.
ExpectDNSMode(SecureDnsConfig::kModeOff, "");
EXPECT_FALSE(local_state()->GetString(::prefs::kBraveVpnDnsConfig).empty());
}
} // namespace brave_vpn
+14
View File
@@ -15,6 +15,20 @@ if (enable_brave_vpn) {
"//brave/browser/brave_vpn/vpn_utils.cc",
"//brave/browser/brave_vpn/vpn_utils.h",
]
if (is_win) {
brave_browser_brave_vpn_sources += [
"//brave/browser/brave_vpn/dns/brave_vpn_dns_observer_factory.cc",
"//brave/browser/brave_vpn/dns/brave_vpn_dns_observer_factory.h",
"//brave/browser/brave_vpn/dns/brave_vpn_dns_observer_service.cc",
"//brave/browser/brave_vpn/dns/brave_vpn_dns_observer_service.h",
]
brave_browser_brave_vpn_deps += [
"//brave/app:brave_generated_resources_grit",
"//brave/browser:browser_process",
"//chrome/common:constants",
"//net",
]
}
brave_browser_brave_vpn_deps += [
"//base",
"//brave/components/brave_vpn",
+10 -1
View File
@@ -291,7 +291,16 @@ source_set("ui") {
"views/window_closing_confirm_dialog_view.cc",
"views/window_closing_confirm_dialog_view.h",
]
if (enable_brave_vpn) {
if (is_win) {
sources += [
"views/brave_vpn/brave_vpn_dns_settings_notificiation_dialog_view.cc",
"views/brave_vpn/brave_vpn_dns_settings_notificiation_dialog_view.h",
"webui/settings/brave_settings_secure_dns_handler.cc",
"webui/settings/brave_settings_secure_dns_handler.h",
]
}
}
if (use_aura) {
sources += [
"views/renderer_context_menu/brave_render_view_context_menu_views.cc",
@@ -0,0 +1,147 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "brave/browser/ui/views/brave_vpn/brave_vpn_dns_settings_notificiation_dialog_view.h"
#include <memory>
#include <utility>
#include "brave/components/brave_vpn/pref_names.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/grit/brave_components_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/link.h"
#include "ui/views/controls/styled_label.h"
#include "ui/views/layout/box_layout.h"
namespace brave_vpn {
namespace {
constexpr char kBraveVPNLearnMoreURL[] =
"https://support.brave.com/hc/en-us/articles/10864482160141";
constexpr int kChildSpacing = 16;
constexpr int kPadding = 24;
constexpr int kTopPadding = 32;
constexpr int kBottomPadding = 26;
constexpr int kDialogWidth = 400;
} // namespace
// static
void BraveVpnDnsSettingsNotificiationDialogView::Show(Browser* browser) {
auto* prefs = browser->profile()->GetPrefs();
if (!prefs->GetBoolean(prefs::kBraveVPNShowNotificationDialog))
return;
// The dialog eats mouse events which results in the close button
// getting stuck in the hover state. Reset the window controls to
// prevent this.
BrowserView::GetBrowserViewForBrowser(browser)
->GetWidget()
->non_client_view()
->ResetWindowControls();
constrained_window::CreateBrowserModalDialogViews(
new BraveVpnDnsSettingsNotificiationDialogView(browser),
browser->window()->GetNativeWindow())
->Show();
}
BraveVpnDnsSettingsNotificiationDialogView::
BraveVpnDnsSettingsNotificiationDialogView(Browser* browser)
: browser_(browser), prefs_(browser->profile()->GetPrefs()) {
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical,
gfx::Insets::TLBR(kTopPadding, kPadding, kBottomPadding, kPadding),
kChildSpacing));
SetButtons(ui::DIALOG_BUTTON_OK);
SetButtonLabel(ui::DIALOG_BUTTON_OK,
l10n_util::GetStringUTF16(
IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_OK_TEXT));
RegisterWindowClosingCallback(
base::BindOnce(&BraveVpnDnsSettingsNotificiationDialogView::OnClosing,
base::Unretained(this)));
SetAcceptCallback(
base::BindOnce(&BraveVpnDnsSettingsNotificiationDialogView::OnAccept,
base::Unretained(this)));
auto* header_label =
AddChildView(std::make_unique<views::Label>(l10n_util::GetStringUTF16(
IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_TITLE)));
header_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
const std::u16string contents_text = l10n_util::GetStringUTF16(
IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_TEXT);
std::u16string learn_more_link_text = l10n_util::GetStringUTF16(
IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_LEARN_MORE_TEXT);
std::u16string full_text = l10n_util::GetStringFUTF16(
IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_TEXT,
learn_more_link_text);
const int main_message_length =
full_text.size() - learn_more_link_text.size();
auto* contents_label = AddChildView(std::make_unique<views::StyledLabel>());
contents_label->SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT);
views::StyledLabel::RangeStyleInfo message_style;
contents_label->SetText(full_text);
contents_label->AddStyleRange(gfx::Range(0, main_message_length),
message_style);
contents_label->SizeToFit(kDialogWidth);
// Add "Learn more" link.
views::StyledLabel::RangeStyleInfo link_style =
views::StyledLabel::RangeStyleInfo::CreateForLink(base::BindRepeating(
&BraveVpnDnsSettingsNotificiationDialogView::OnLearnMoreLinkClicked,
base::Unretained(this)));
contents_label->AddStyleRange(
gfx::Range(main_message_length, full_text.size()), link_style);
contents_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
dont_ask_again_checkbox_ =
AddChildView(std::make_unique<views::Checkbox>(l10n_util::GetStringUTF16(
IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_CHECKBOX_TEXT)));
}
BraveVpnDnsSettingsNotificiationDialogView::
~BraveVpnDnsSettingsNotificiationDialogView() = default;
void BraveVpnDnsSettingsNotificiationDialogView::OnLearnMoreLinkClicked() {
chrome::AddSelectedTabWithURL(browser_, GURL(kBraveVPNLearnMoreURL),
ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
AcceptDialog();
}
ui::ModalType BraveVpnDnsSettingsNotificiationDialogView::GetModalType() const {
return ui::MODAL_TYPE_WINDOW;
}
bool BraveVpnDnsSettingsNotificiationDialogView::ShouldShowCloseButton() const {
return false;
}
bool BraveVpnDnsSettingsNotificiationDialogView::ShouldShowWindowTitle() const {
return false;
}
void BraveVpnDnsSettingsNotificiationDialogView::OnAccept() {
close_window_ = true;
}
void BraveVpnDnsSettingsNotificiationDialogView::OnClosing() {
prefs_->SetBoolean(prefs::kBraveVPNShowNotificationDialog,
!dont_ask_again_checkbox_->GetChecked());
}
BEGIN_METADATA(BraveVpnDnsSettingsNotificiationDialogView,
views::DialogDelegateView)
END_METADATA
} // namespace brave_vpn
@@ -0,0 +1,54 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_BROWSER_UI_VIEWS_BRAVE_VPN_BRAVE_VPN_DNS_SETTINGS_NOTIFICIATION_DIALOG_VIEW_H_
#define BRAVE_BROWSER_UI_VIEWS_BRAVE_VPN_BRAVE_VPN_DNS_SETTINGS_NOTIFICIATION_DIALOG_VIEW_H_
#include "ui/views/window/dialog_delegate.h"
class Browser;
class PrefService;
namespace views {
class Checkbox;
}
namespace brave_vpn {
class BraveVpnDnsSettingsNotificiationDialogView
: public views::DialogDelegateView {
public:
METADATA_HEADER(BraveVpnDnsSettingsNotificiationDialogView);
static void Show(Browser* browser);
BraveVpnDnsSettingsNotificiationDialogView(
const BraveVpnDnsSettingsNotificiationDialogView&) = delete;
BraveVpnDnsSettingsNotificiationDialogView& operator=(
const BraveVpnDnsSettingsNotificiationDialogView&) = delete;
private:
explicit BraveVpnDnsSettingsNotificiationDialogView(Browser* browser);
~BraveVpnDnsSettingsNotificiationDialogView() override;
void OnAccept();
void OnClosing();
void OnLearnMoreLinkClicked();
// views::DialogDelegate overrides:
ui::ModalType GetModalType() const override;
bool ShouldShowCloseButton() const override;
bool ShouldShowWindowTitle() const override;
bool close_window_ = true;
raw_ptr<Browser> browser_ = nullptr;
raw_ptr<PrefService> prefs_ = nullptr;
raw_ptr<views::Checkbox> dont_ask_again_checkbox_ = nullptr;
};
} // namespace brave_vpn
#endif // BRAVE_BROWSER_UI_VIEWS_BRAVE_VPN_BRAVE_VPN_DNS_SETTINGS_NOTIFICIATION_DIALOG_VIEW_H_
@@ -0,0 +1,37 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "brave/browser/ui/webui/settings/brave_settings_secure_dns_handler.h"
#include "base/feature_list.h"
#include "brave/components/brave_vpn/features.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
namespace settings {
BraveSecureDnsHandler::BraveSecureDnsHandler() = default;
BraveSecureDnsHandler::~BraveSecureDnsHandler() = default;
void BraveSecureDnsHandler::OnJavascriptAllowed() {
SecureDnsHandler::OnJavascriptAllowed();
pref_registrar_.Init(g_browser_process->local_state());
if (base::FeatureList::IsEnabled(
brave_vpn::features::kBraveVPNDnsProtection)) {
pref_registrar_.Add(
prefs::kBraveVpnDnsConfig,
base::BindRepeating(
&BraveSecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript,
base::Unretained(this)));
}
}
void BraveSecureDnsHandler::OnJavascriptDisallowed() {
SecureDnsHandler::OnJavascriptDisallowed();
pref_registrar_.RemoveAll();
}
} // namespace settings
@@ -0,0 +1,28 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_SETTINGS_SECURE_DNS_HANDLER_H_
#define BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_SETTINGS_SECURE_DNS_HANDLER_H_
#include "chrome/browser/ui/webui/settings/settings_secure_dns_handler.h"
#include "components/prefs/pref_change_registrar.h"
namespace settings {
class BraveSecureDnsHandler : public SecureDnsHandler {
public:
BraveSecureDnsHandler();
~BraveSecureDnsHandler() override;
void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override;
private:
PrefChangeRegistrar pref_registrar_;
};
} // namespace settings
#endif // BRAVE_BROWSER_UI_WEBUI_SETTINGS_BRAVE_SETTINGS_SECURE_DNS_HANDLER_H_
@@ -0,0 +1,140 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "base/feature_list.h"
#include "brave/components/brave_vpn/buildflags/buildflags.h"
#include "build/buildflag.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/network_service_instance.h"
#include "net/dns/public/dns_over_https_config.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#if BUILDFLAG(ENABLE_BRAVE_VPN)
#include "brave/components/brave_vpn/features.h"
#endif
#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_BRAVE_VPN)
namespace {
bool IsBraveVPNConnected(PrefService* local_state) {
if (!base::FeatureList::IsEnabled(
brave_vpn::features::kBraveVPNDnsProtection)) {
return false;
}
return !local_state->GetString(prefs::kBraveVpnDnsConfig).empty();
}
bool ShouldOverride(net::SecureDnsMode secure_dns_mode,
PrefService* local_state,
SecureDnsConfig::ManagementMode management_mode,
bool is_managed) {
if (!IsBraveVPNConnected(local_state))
return false;
if (secure_dns_mode == net::SecureDnsMode::kSecure)
return false;
if (management_mode != SecureDnsConfig::ManagementMode::kNoOverride ||
is_managed) {
// there is already a managed policy or parental control in place
return false;
}
return true;
}
bool MaybeOverrideDnsClientEnabled(
net::SecureDnsMode secure_dns_mode,
bool insecure_dns_client_enabled,
PrefService* local_state,
SecureDnsConfig::ManagementMode management_mode,
bool is_managed) {
if (ShouldOverride(secure_dns_mode, local_state, management_mode,
is_managed)) {
// disable the insecure client for doh
return false;
}
return insecure_dns_client_enabled;
}
net::SecureDnsMode MaybeOverrideDnsMode(
net::SecureDnsMode secure_dns_mode,
PrefService* local_state,
SecureDnsConfig::ManagementMode management_mode,
bool is_managed) {
if (ShouldOverride(secure_dns_mode, local_state, management_mode,
is_managed)) {
return net::SecureDnsMode::kSecure;
}
return secure_dns_mode;
}
net::DnsOverHttpsConfig MaybeOverrideDnsConfig(
net::SecureDnsMode secure_dns_mode,
net::DnsOverHttpsConfig doh_config,
PrefService* local_state,
SecureDnsConfig::ManagementMode management_mode,
bool is_managed) {
if (ShouldOverride(secure_dns_mode, local_state, management_mode,
is_managed)) {
return net::DnsOverHttpsConfig::FromStringLax(
local_state->GetString(prefs::kBraveVpnDnsConfig));
}
return doh_config;
}
SecureDnsConfig::ManagementMode MaybeOverrideForcedManagementMode(
net::SecureDnsMode secure_dns_mode,
PrefService* local_state,
SecureDnsConfig::ManagementMode management_mode,
bool is_managed) {
// Don't change management mode if the doh settings are
// managed by policy or by parental controls
if (is_managed ||
management_mode != SecureDnsConfig::ManagementMode::kNoOverride)
return management_mode;
// Otherwise always block changes to the doh config while the VPN
// is connected
if (IsBraveVPNConnected(local_state))
return SecureDnsConfig::ManagementMode::kDisabledManaged;
return management_mode;
}
} // namespace
#define SecureDnsConfig(SECURE_DNS_MODE, SECURE_DOH_CONFIG, \
FORCED_MANAGEMENT_MODE) \
SecureDnsConfig( \
MaybeOverrideDnsMode(SECURE_DNS_MODE, local_state_, \
FORCED_MANAGEMENT_MODE, is_managed), \
MaybeOverrideDnsConfig(SECURE_DNS_MODE, SECURE_DOH_CONFIG, local_state_, \
FORCED_MANAGEMENT_MODE, is_managed), \
MaybeOverrideForcedManagementMode(SECURE_DNS_MODE, local_state_, \
FORCED_MANAGEMENT_MODE, is_managed))
#define ConfigureStubHostResolver(INSECURE_DNS_CLIENT_ENABLED, \
SECURE_DNS_MODE, DNS_OVER_HTTPS_CONFIG, \
ADDITIONAL_DNS_TYPES_ENABLED) \
ConfigureStubHostResolver( \
MaybeOverrideDnsClientEnabled(SECURE_DNS_MODE, \
INSECURE_DNS_CLIENT_ENABLED, local_state_, \
forced_management_mode, is_managed), \
MaybeOverrideDnsMode(SECURE_DNS_MODE, local_state_, \
forced_management_mode, is_managed), \
MaybeOverrideDnsConfig(SECURE_DNS_MODE, DNS_OVER_HTTPS_CONFIG, \
local_state_, forced_management_mode, \
is_managed), \
ADDITIONAL_DNS_TYPES_ENABLED)
#endif // BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_BRAVE_VPN)
#include "src/chrome/browser/net/stub_resolver_config_reader.cc"
#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_BRAVE_VPN)
#undef ConfigureStubHostResolver
#undef SecureDnsConfig
#endif // BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_BRAVE_VPN)
@@ -6,8 +6,15 @@
#include "brave/browser/ui/webui/settings/brave_import_data_handler.h"
#include "brave/browser/ui/webui/settings/brave_search_engines_handler.h"
#include "brave/browser/ui/webui/settings/brave_site_settings_handler.h"
#include "brave/components/brave_vpn/buildflags/buildflags.h"
#include "chrome/browser/ui/webui/settings/settings_secure_dns_handler.h"
#include "chrome/browser/ui/webui/settings/site_settings_handler.h"
#if BUILDFLAG(IS_WIN) && BUILDFLAG(ENABLE_BRAVE_VPN)
#include "brave/browser/ui/webui/settings/brave_settings_secure_dns_handler.h"
#define SecureDnsHandler BraveSecureDnsHandler
#endif
#define SiteSettingsHandler BraveSiteSettingsHandler
#define ImportDataHandler BraveImportDataHandler
#define SearchEnginesHandler BraveSearchEnginesHandler
@@ -3,7 +3,40 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "brave/components/brave_vpn/buildflags/buildflags.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/grit/brave_components_strings.h"
#include "components/prefs/pref_service.h"
#include "net/dns/public/secure_dns_mode.h"
#if BUILDFLAG(ENABLE_BRAVE_VPN) && BUILDFLAG(IS_WIN)
#include "brave/components/brave_vpn/features.h"
namespace {
bool ShouldReplaceSecureDNSDisabledDescription() {
if (!base::FeatureList::IsEnabled(
brave_vpn::features::kBraveVPNDnsProtection))
return false;
auto dns_config = SystemNetworkContextManager::GetStubResolverConfigReader()
->GetSecureDnsConfiguration(false);
return !g_browser_process->local_state()
->GetString(prefs::kBraveVpnDnsConfig)
.empty() ||
dns_config.mode() == net::SecureDnsMode::kSecure;
}
} // namespace
#define AddSecureDnsStrings AddSecureDnsStrings_ChromiumImpl
#endif // BUILDFLAG(ENABLE_BRAVE_VPN) && BUILDFLAG(IS_WIN)
// Use custom strings for diagnostic (crashes, hangs) reporting settings.
#undef IDS_SETTINGS_ENABLE_LOGGING_PREF
@@ -13,3 +46,22 @@
IDS_BRAVE_DIAGNOSTIC_REPORTS_PREF_DESC
#include "src/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc"
#if BUILDFLAG(ENABLE_BRAVE_VPN) && BUILDFLAG(IS_WIN)
#undef AddSecureDnsStrings
namespace settings {
void AddSecureDnsStrings(content::WebUIDataSource* html_source) {
AddSecureDnsStrings_ChromiumImpl(html_source);
if (!ShouldReplaceSecureDNSDisabledDescription())
return;
static constexpr webui::LocalizedString kLocalizedStrings[] = {
{"secureDnsDisabledForManagedEnvironment",
IDS_SETTINGS_SECURE_DNS_DISABLED_BY_BRAVE_VPN}};
html_source->AddLocalizedStrings(kLocalizedStrings);
}
} // namespace settings
#endif // BUILDFLAG(ENABLE_BRAVE_VPN) && BUILDFLAG(IS_WIN)
+12
View File
@@ -0,0 +1,12 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#include "chrome/common/pref_names.h"
namespace prefs {
const char kBraveVpnDnsConfig[] = "brave.brave_vpn.dns_config";
} // namespace prefs
#include "src/chrome/common/pref_names.cc"
+21
View File
@@ -0,0 +1,21 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_CHROMIUM_SRC_CHROME_COMMON_PREF_NAMES_H_
#define BRAVE_CHROMIUM_SRC_CHROME_COMMON_PREF_NAMES_H_
#include "build/build_config.h"
namespace prefs {
// Used by BraveVpnDnsObserverService to set cloudflare server url when
// BraveVPN is connected, otherwise this pref is empty. Final decision
// about whether or not to override actual DNS state will be made in
// stub_resolver_config_reader.
extern const char kBraveVpnDnsConfig[];
} // namespace prefs
#include "src/chrome/common/pref_names.h"
#endif // BRAVE_CHROMIUM_SRC_CHROME_COMMON_PREF_NAMES_H_
+3 -3
View File
@@ -25,14 +25,11 @@
namespace brave_vpn {
namespace {
void RegisterVPNLocalStatePrefs(PrefRegistrySimple* registry) {
#if !BUILDFLAG(IS_ANDROID)
registry->RegisterListPref(prefs::kBraveVPNRegionList);
registry->RegisterStringPref(prefs::kBraveVPNDeviceRegion, "");
registry->RegisterStringPref(prefs::kBraveVPNSelectedRegion, "");
registry->RegisterBooleanPref(prefs::kBraveVPNShowDNSPolicyWarningDialog,
true);
#endif
registry->RegisterStringPref(prefs::kBraveVPNEnvironment,
skus::GetDefaultEnvironment());
@@ -101,6 +98,9 @@ std::string GetManageUrl(const std::string& env) {
void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterDictionaryPref(prefs::kBraveVPNRootPref);
registry->RegisterBooleanPref(prefs::kBraveVPNShowButton, true);
#if BUILDFLAG(IS_WIN)
registry->RegisterBooleanPref(prefs::kBraveVPNShowNotificationDialog, true);
#endif
#if BUILDFLAG(IS_ANDROID)
registry->RegisterStringPref(prefs::kBraveVPNPurchaseTokenAndroid, "");
registry->RegisterStringPref(prefs::kBraveVPNPackageAndroid, "");
+5
View File
@@ -25,6 +25,11 @@ BASE_FEATURE(kBraveVPNLinkSubscriptionAndroidUI,
"BraveVPNLinkSubscriptionAndroidUI",
base::FEATURE_DISABLED_BY_DEFAULT);
#if BUILDFLAG(IS_WIN)
BASE_FEATURE(kBraveVPNDnsProtection,
"BraveVPNDnsProtection",
base::FEATURE_ENABLED_BY_DEFAULT);
#endif
} // namespace features
} // namespace brave_vpn
+4 -1
View File
@@ -7,13 +7,16 @@
#define BRAVE_COMPONENTS_BRAVE_VPN_FEATURES_H_
#include "base/feature_list.h"
#include "build/build_config.h"
namespace brave_vpn {
namespace features {
BASE_DECLARE_FEATURE(kBraveVPN);
BASE_DECLARE_FEATURE(kBraveVPNLinkSubscriptionAndroidUI);
#if BUILDFLAG(IS_WIN)
BASE_DECLARE_FEATURE(kBraveVPNDnsProtection);
#endif
} // namespace features
} // namespace brave_vpn
+5 -2
View File
@@ -18,8 +18,12 @@ constexpr char kBraveVPNRegionList[] = "brave.brave_vpn.region_list";
constexpr char kBraveVPNDeviceRegion[] = "brave.brave_vpn.device_region_name";
constexpr char kBraveVPNSelectedRegion[] =
"brave.brave_vpn.selected_region_name";
constexpr char kBraveVPNShowDNSPolicyWarningDialog[] =
#if BUILDFLAG(IS_WIN)
constexpr char kBraveVpnShowDNSPolicyWarningDialog[] =
"brave.brave_vpn.show_dns_policy_warning_dialog";
constexpr char kBraveVPNShowNotificationDialog[] =
"brave.brave_vpn.show_notification_dialog";
#endif // BUILDFLAG(IS_WIN)
constexpr char kBraveVPNEnvironment[] = "brave.brave_vpn.env";
// Dict that has subscriber credential its expiration date.
constexpr char kBraveVPNSubscriberCredential[] =
@@ -36,7 +40,6 @@ constexpr char kBraveVPNLastUseTime[] = "brave.brave_vpn.last_use_time";
constexpr char kBraveVPNUsedSecondDay[] = "brave.brave_vpn.used_second_day";
constexpr char kBraveVPNDaysInMonthUsed[] =
"brave.brave_vpn.days_in_month_used";
} // namespace prefs
} // namespace brave_vpn
@@ -219,7 +219,29 @@
<message name="IDS_BRAVE_VPN_DNS_POLICY_ALERT" desc="A text shown to user when he enabled Brave VPN with disabled DoH by policies">
Secure DNS is disabled by your organization's policies. Using Brave VPN without Secure DNS may reveal the names of the sites you visit to your Internet service provider or organization.
</message>
<if expr="is_win">
<message name="IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_TITLE" desc="A title of text shown to user when he enabled Brave VPN without DoH and we override settings">
Brave VPN on Windows
</message>
</if>
<message name="IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_LEARN_MORE_TEXT" desc="A text shown to user when he enabled Brave VPN without DoH and we override settings to visit help center">
Learn more.
</message>
<message name="IDS_SETTINGS_SECURE_DNS_DISABLED_BY_BRAVE_VPN" desc="A text shown to user on settings page for DNS setting when it is blocked by BraveVPN">
The setting is locked by BraveVPN while it is connected
</message>
<message name="IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_TEXT" desc="A text shown to user when he enabled Brave VPN without DoH and we override settings">
Windows has a feature called Smart Multi-Homed Name Resolution, which can expose information about your location and the sites you visit. Now that youve enabled Brave VPN, weve changed the DNS settings in the browser to protect against this exposure. The settings will remain in effect and locked while VPN is connected. <ph name="LEARN_MORE">$1<ex>Learn more.</ex></ph>
</message>
<message name="IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_CHECKBOX_TEXT" desc="A text shown to user on dialog's checkbpox when he enabled Brave VPN and we override settings">
Do not warn me about this anymore.
</message>
<message name="IDS_BRAVE_VPN_DNS_SETTINGS_NOTIFICATION_DIALOG_OK_TEXT" desc="A text shown to user on dialog's ok button when he enabled Brave VPN and we override settings">
Ok
</message>
<message name="IDS_BRAVE_VPN_DNS_POLICY_CHECKBOX" desc="A text shown to user on dialog's checkbpox when he enabled Brave VPN with disabled DoH by policies">
Do not warn me about this anymore.
</message>
+1
View File
@@ -166,6 +166,7 @@ test("brave_unit_tests") {
"//brave/browser",
"//brave/browser:unit_tests",
"//brave/browser/brave_rewards/rewards_panel:unit_tests",
"//brave/browser/brave_vpn/dns:unit_tests",
"//brave/browser/brave_wallet",
"//brave/browser/brave_wallet:unit_tests",
"//brave/browser/content_settings:unit_tests",