Commit 78ff2568 authored by Ben Schwartz's avatar Ben Schwartz Committed by Commit Bot

Simplify DoH probe and separate it from the UI

This change reduces code duplication by reusing DnsProbeRunner for
probing DoH servers in the UI.  It also extracts the probe logic
from the UI code, in order to reuse it in the forthcoming Android
DoH settings UI.

Change-Id: If6f6f1a8d7b6bb8f1d5810880d56dafbfdcf26f1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2150031
Auto-Submit: Ben Schwartz <bemasc@chromium.org>
Reviewed-by: default avatarEric Orth <ericorth@chromium.org>
Reviewed-by: default avatarEsmael Elmoslimany <aee@chromium.org>
Commit-Queue: Eric Orth <ericorth@chromium.org>
Cr-Commit-Position: refs/heads/master@{#764137}
parent e276b4b2
...@@ -80,4 +80,14 @@ bool IsValidDohTemplateGroup(base::StringPiece group) { ...@@ -80,4 +80,14 @@ bool IsValidDohTemplateGroup(base::StringPiece group) {
}); });
} }
void ApplyDohTemplate(net::DnsConfigOverrides* overrides,
base::StringPiece server_template) {
std::string server_method;
// We only allow use of templates that have already passed a format
// validation check.
CHECK(net::dns_util::IsValidDohTemplate(server_template, &server_method));
overrides->dns_over_https_servers.emplace({net::DnsOverHttpsServerConfig(
std::string(server_template), server_method == "POST")});
}
} // namespace chrome_browser_net } // namespace chrome_browser_net
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <vector> #include <vector>
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "net/dns/dns_config_overrides.h"
class PrefRegistrySimple; class PrefRegistrySimple;
class PrefService; class PrefService;
...@@ -22,6 +23,10 @@ std::vector<base::StringPiece> SplitDohTemplateGroup(base::StringPiece group); ...@@ -22,6 +23,10 @@ std::vector<base::StringPiece> SplitDohTemplateGroup(base::StringPiece group);
// stored preferences. // stored preferences.
bool IsValidDohTemplateGroup(base::StringPiece group); bool IsValidDohTemplateGroup(base::StringPiece group);
// Modifies |overrides| to use the DoH server specified by |server_template|.
void ApplyDohTemplate(net::DnsConfigOverrides* overrides,
base::StringPiece server_template);
const char kDnsOverHttpsModeOff[] = "off"; const char kDnsOverHttpsModeOff[] = "off";
const char kDnsOverHttpsModeAutomatic[] = "automatic"; const char kDnsOverHttpsModeAutomatic[] = "automatic";
const char kDnsOverHttpsModeSecure[] = "secure"; const char kDnsOverHttpsModeSecure[] = "secure";
......
...@@ -165,4 +165,24 @@ TEST(DNSUtil, IsValidDohTemplateGroup) { ...@@ -165,4 +165,24 @@ TEST(DNSUtil, IsValidDohTemplateGroup) {
EXPECT_FALSE(IsValidDohTemplateGroup("invalid invalid2")); EXPECT_FALSE(IsValidDohTemplateGroup("invalid invalid2"));
} }
TEST(DNSUtil, ApplyDohTemplatePost) {
std::string post_template("https://valid");
net::DnsConfigOverrides overrides;
ApplyDohTemplate(&overrides, post_template);
EXPECT_THAT(overrides.dns_over_https_servers,
testing::Optional(ElementsAre(net::DnsOverHttpsServerConfig(
{post_template, true /* use_post */}))));
}
TEST(DNSUtil, ApplyDohTemplateGet) {
std::string get_template("https://valid/{?dns}");
net::DnsConfigOverrides overrides;
ApplyDohTemplate(&overrides, get_template);
EXPECT_THAT(overrides.dns_over_https_servers,
testing::Optional(ElementsAre(net::DnsOverHttpsServerConfig(
{get_template, false /* use_post */}))));
}
} // namespace chrome_browser_net } // namespace chrome_browser_net
...@@ -31,8 +31,6 @@ namespace settings { ...@@ -31,8 +31,6 @@ namespace settings {
namespace { namespace {
const char kProbeHostname[] = "google.com";
std::unique_ptr<base::DictionaryValue> CreateSecureDnsSettingDict() { std::unique_ptr<base::DictionaryValue> CreateSecureDnsSettingDict() {
// Fetch the current host resolver configuration. It is not sufficient to read // Fetch the current host resolver configuration. It is not sufficient to read
// the secure DNS prefs directly since the host resolver configuration takes // the secure DNS prefs directly since the host resolver configuration takes
...@@ -76,7 +74,10 @@ std::unique_ptr<base::DictionaryValue> CreateSecureDnsSettingDict() { ...@@ -76,7 +74,10 @@ std::unique_ptr<base::DictionaryValue> CreateSecureDnsSettingDict() {
} // namespace } // namespace
SecureDnsHandler::SecureDnsHandler() = default; SecureDnsHandler::SecureDnsHandler()
: network_context_getter_(
base::BindRepeating(&SecureDnsHandler::GetNetworkContext,
base::Unretained(this))) {}
SecureDnsHandler::~SecureDnsHandler() = default; SecureDnsHandler::~SecureDnsHandler() = default;
...@@ -179,7 +180,17 @@ base::Value SecureDnsHandler::GetSecureDnsResolverListForCountry( ...@@ -179,7 +180,17 @@ base::Value SecureDnsHandler::GetSecureDnsResolverListForCountry(
void SecureDnsHandler::SetNetworkContextForTesting( void SecureDnsHandler::SetNetworkContextForTesting(
network::mojom::NetworkContext* network_context) { network::mojom::NetworkContext* network_context) {
network_context_for_testing_ = network_context; network_context_getter_ = base::BindRepeating(
[](network::mojom::NetworkContext* network_context) {
return network_context;
},
network_context);
}
network::mojom::NetworkContext* SecureDnsHandler::GetNetworkContext() {
return content::BrowserContext::GetDefaultStoragePartition(
web_ui()->GetWebContents()->GetBrowserContext())
->GetNetworkContext();
} }
void SecureDnsHandler::HandleGetSecureDnsResolverList( void SecureDnsHandler::HandleGetSecureDnsResolverList(
...@@ -225,10 +236,10 @@ void SecureDnsHandler::HandleProbeCustomDnsTemplate( ...@@ -225,10 +236,10 @@ void SecureDnsHandler::HandleProbeCustomDnsTemplate(
AllowJavascript(); AllowJavascript();
if (!probe_callback_id_.empty()) { if (!probe_callback_id_.empty()) {
// Cancel the pending probe and report a non-error response to avoid // Cancel the pending probe by destroying the probe runner (which does not
// leaking the callback. // call the callback), and report a non-error response to avoid leaking the
receiver_.reset(); // callback.
host_resolver_.reset(); runner_.reset();
ResolveJavascriptCallback(base::Value(probe_callback_id_), ResolveJavascriptCallback(base::Value(probe_callback_id_),
base::Value(true)); base::Value(true));
} }
...@@ -242,33 +253,12 @@ void SecureDnsHandler::HandleProbeCustomDnsTemplate( ...@@ -242,33 +253,12 @@ void SecureDnsHandler::HandleProbeCustomDnsTemplate(
overrides.attempts = 1; overrides.attempts = 1;
overrides.randomize_ports = false; overrides.randomize_ports = false;
overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE; overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE;
std::string server_method; chrome_browser_net::ApplyDohTemplate(&overrides, server_template);
// We only send probe queries to templates that have already passed a format DCHECK(!runner_);
// validation check. runner_ = std::make_unique<chrome_browser_net::DnsProbeRunner>(
CHECK(net::dns_util::IsValidDohTemplate(server_template, &server_method)); overrides, network_context_getter_);
overrides.dns_over_https_servers.emplace({net::DnsOverHttpsServerConfig( runner_->RunProbe(base::BindOnce(&SecureDnsHandler::OnProbeComplete,
server_template, server_method == "POST")}); base::Unretained(this)));
auto* network_context =
network_context_for_testing_
? network_context_for_testing_
: content::BrowserContext::GetDefaultStoragePartition(
web_ui()->GetWebContents()->GetBrowserContext())
->GetNetworkContext();
network_context->CreateHostResolver(
overrides, host_resolver_.BindNewPipeAndPassReceiver());
network::mojom::ResolveHostParametersPtr parameters =
network::mojom::ResolveHostParameters::New();
parameters->dns_query_type = net::DnsQueryType::A;
parameters->source = net::HostResolverSource::DNS;
parameters->cache_usage =
network::mojom::ResolveHostParameters::CacheUsage::DISALLOWED;
host_resolver_->ResolveHost(net::HostPortPair(kProbeHostname, 80),
net::NetworkIsolationKey::CreateTransient(),
std::move(parameters),
receiver_.BindNewPipeAndPassRemote());
receiver_.set_disconnect_handler(base::BindOnce(
&SecureDnsHandler::OnMojoConnectionError, base::Unretained(this)));
} }
void SecureDnsHandler::HandleRecordUserDropdownInteraction( void SecureDnsHandler::HandleRecordUserDropdownInteraction(
...@@ -296,24 +286,16 @@ void SecureDnsHandler::HandleRecordUserDropdownInteraction( ...@@ -296,24 +286,16 @@ void SecureDnsHandler::HandleRecordUserDropdownInteraction(
} }
} }
// network::ResolveHostClientBase impl: void SecureDnsHandler::OnProbeComplete() {
void SecureDnsHandler::OnComplete( bool success =
int result, runner_->result() == chrome_browser_net::DnsProbeRunner::CORRECT;
const net::ResolveErrorInfo& resolve_error_info, runner_.reset();
const base::Optional<net::AddressList>& resolved_addresses) { UMA_HISTOGRAM_BOOLEAN("Net.DNS.UI.ProbeAttemptSuccess", success);
receiver_.reset();
host_resolver_.reset();
UMA_HISTOGRAM_BOOLEAN("Net.DNS.UI.ProbeAttemptSuccess", (result == 0));
ResolveJavascriptCallback(base::Value(probe_callback_id_), ResolveJavascriptCallback(base::Value(probe_callback_id_),
base::Value(result == 0)); base::Value(success));
probe_callback_id_.clear(); probe_callback_id_.clear();
} }
void SecureDnsHandler::OnMojoConnectionError() {
OnComplete(net::ERR_NAME_NOT_RESOLVED, net::ResolveErrorInfo(net::ERR_FAILED),
base::nullopt);
}
void SecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript() { void SecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript() {
FireWebUIListener("secure-dns-setting-changed", FireWebUIListener("secure-dns-setting-changed",
*CreateSecureDnsSettingDict()); *CreateSecureDnsSettingDict());
......
...@@ -11,20 +11,17 @@ ...@@ -11,20 +11,17 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/net/dns_probe_runner.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_change_registrar.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/dns/public/doh_provider_list.h" #include "net/dns/public/doh_provider_list.h"
#include "services/network/public/cpp/resolve_host_client_base.h" #include "services/network/public/cpp/resolve_host_client_base.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_context.mojom.h"
namespace settings { namespace settings {
// Handler for the Secure DNS setting. // Handler for the Secure DNS setting.
class SecureDnsHandler : public SettingsPageUIHandler, class SecureDnsHandler : public SettingsPageUIHandler {
network::ResolveHostClientBase {
public: public:
SecureDnsHandler(); SecureDnsHandler();
~SecureDnsHandler() override; ~SecureDnsHandler() override;
...@@ -66,18 +63,13 @@ class SecureDnsHandler : public SettingsPageUIHandler, ...@@ -66,18 +63,13 @@ class SecureDnsHandler : public SettingsPageUIHandler,
void SendSecureDnsSettingUpdatesToJavascript(); void SendSecureDnsSettingUpdatesToJavascript();
private: private:
// network::ResolveHostClientBase impl: network::mojom::NetworkContext* GetNetworkContext();
void OnComplete( void OnProbeComplete();
int result,
const net::ResolveErrorInfo& resolve_error_info,
const base::Optional<net::AddressList>& resolved_addresses) override;
void OnMojoConnectionError();
std::map<std::string, net::DohProviderIdForHistogram> resolver_histogram_map_; std::map<std::string, net::DohProviderIdForHistogram> resolver_histogram_map_;
network::mojom::NetworkContext* network_context_for_testing_ = nullptr; std::unique_ptr<chrome_browser_net::DnsProbeRunner> runner_;
mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this}; chrome_browser_net::DnsProbeRunner::NetworkContextGetter
mojo::Remote<network::mojom::HostResolver> host_resolver_; network_context_getter_;
// ID of the Javascript callback for the current pending probe, or "" if // ID of the Javascript callback for the current pending probe, or "" if
// there is no probe currently in progress. // there is no probe currently in progress.
std::string probe_callback_id_; std::string probe_callback_id_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment