Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5070)

Unified Diff: chrome/browser/net/dns_probe_runner.cc

Issue 13270005: Display DNS probe results. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: ...actually add the unittests Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/net/dns_probe_runner.cc
diff --git a/chrome/browser/net/dns_probe_runner.cc b/chrome/browser/net/dns_probe_runner.cc
new file mode 100644
index 0000000000000000000000000000000000000000..74d91fb7091469433955772c5a7b5d50abee8548
--- /dev/null
+++ b/chrome/browser/net/dns_probe_runner.cc
@@ -0,0 +1,258 @@
+// Copyright (c) 2013 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/dns_probe_runner.h"
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/base/net_util.h"
+#include "net/base/network_change_notifier.h"
+#include "net/dns/dns_client.h"
+#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_protocol.h"
+#include "net/dns/dns_response.h"
+#include "net/dns/dns_transaction.h"
+
+using base::TimeDelta;
+using net::AddressList;
+using net::BoundNetLog;
+using net::DnsClient;
+using net::DnsConfig;
+using net::DnsResponse;
+using net::DnsTransaction;
+using net::IPAddressNumber;
+using net::IPEndPoint;
+using net::NetLog;
+using net::NetworkChangeNotifier;
+using net::ParseIPLiteralToNumber;
+
+namespace {
+
+// The public DNS servers used by the DnsProbeService to verify internet
+// connectivity.
+const char kPublicDnsPrimary[] = "8.8.8.8";
+const char kPublicDnsSecondary[] = "8.8.4.4";
+
+IPEndPoint MakeDnsEndPoint(const std::string& dns_ip_literal) {
+ IPAddressNumber dns_ip_number;
+ bool rv = ParseIPLiteralToNumber(dns_ip_literal, &dns_ip_number);
+ DCHECK(rv);
+ return IPEndPoint(dns_ip_number, net::dns_protocol::kDefaultPort);
+}
+
+// Returns true if the given net_error indicates that we received a response
+// from the DNS server containing an error, or false if the given net_error
+// indicates that we never received a response.
+bool DidReceiveDnsResponse(int net_error) {
+ switch (net_error) {
+ case net::ERR_NAME_NOT_RESOLVED: // NXDOMAIN maps to this.
+ case net::ERR_DNS_MALFORMED_RESPONSE:
+ case net::ERR_DNS_SERVER_REQUIRES_TCP:
+ case net::ERR_DNS_SERVER_FAILED:
+ case net::ERR_DNS_SORT_ERROR: // Can only happen if the server responds.
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace
+
+DnsProbeRunner::ProbeInfo::ProbeInfo(
+ DnsProbeRunner::Type type,
+ const DnsProbeRunner::ProbeCallback& callback)
+ : type(type),
+ callback(callback) {}
+
+DnsProbeRunner::ProbeInfo::~ProbeInfo() {}
+
+DnsProbeRunner::DnsProbeRunner()
+ : weak_factory_(this),
+ bound_net_log_(BoundNetLog::Make(NULL, NetLog::SOURCE_DNS_PROBER)),
+ mock_mode_(DnsProbeRunner::NO_MOCK) {
+ NetworkChangeNotifier::AddDNSObserver(this);
+ InitializeSystemClient();
+ InitializePublicClient();
+}
+
+DnsProbeRunner::~DnsProbeRunner() {
+ NetworkChangeNotifier::RemoveDNSObserver(this);
+ for (TransactionMap::iterator it = pending_transactions_.begin();
+ it != pending_transactions_.end(); ++it) {
+ delete it->first;
+ }
+}
+
+void DnsProbeRunner::OnDNSChanged() {
+ InitializeSystemClient();
szym 2013/06/07 19:31:28 Note that this does not affect any pending transac
Deprecated (see juliatuttle) 2013/06/11 01:07:34 That's okay; error pages can be obsolete for other
+}
+
+void DnsProbeRunner::RunProbe(Type type,
+ const ProbeCallback& callback) {
+ if (mock_mode_ == MOCK_RESULTS) {
+ callback.Run(type, GetMockResult(type));
+ return;
+ }
+
+ DnsTransaction* transaction =
+ GetClient(type)->GetTransactionFactory()->CreateTransaction(
+ "google.com",
+ net::dns_protocol::kTypeA,
+ base::Bind(&DnsProbeRunner::OnTransactionComplete,
+ weak_factory_.GetWeakPtr(),
+ true /* async */),
+ bound_net_log_).release();
+
+ pending_transactions_.insert(std::pair<DnsTransaction*,ProbeInfo>(
+ transaction,
+ ProbeInfo(type, callback)));
szym 2013/06/07 19:31:28 Instead bind ProbeInfo as an argument to OnTransac
Deprecated (see juliatuttle) 2013/06/11 01:07:34 Obsolete.
+
+ int rv = transaction->Start();
+ if (rv != net::ERR_IO_PENDING) {
+ OnTransactionComplete(false /* not async */,
+ transaction,
+ rv,
+ NULL);
+ }
+}
+
+void DnsProbeRunner::SetClientsForTesting(
+ scoped_ptr<DnsClient> mock_system_client,
+ scoped_ptr<DnsClient> mock_public_client) {
+ DCHECK_EQ(NO_MOCK, mock_mode_);
+ DCHECK(mock_system_client.get());
+ DCHECK(mock_public_client.get());
+
+ mock_mode_ = MOCK_CLIENTS;
+ mock_system_client_ = mock_system_client.Pass();
+ mock_public_client_ = mock_public_client.Pass();
+}
+
+void DnsProbeRunner::SetResultsForTesting(
+ Result system_result,
+ Result public_result) {
+ mock_mode_ = MOCK_RESULTS;
+ mock_system_result_ = system_result;
+ mock_public_result_ = public_result;
+ mock_system_client_.reset();
+ mock_public_client_.reset();
+}
+
+void DnsProbeRunner::InitializeSystemClient() {
+ DnsConfig config;
+ NetworkChangeNotifier::GetDnsConfig(&config);
+ config.search.clear();
+ config.attempts = 1;
+ config.randomize_ports = false;
+
+ scoped_ptr<DnsClient> client = DnsClient::CreateClient(NULL);
+ client->SetConfig(config);
+
+ system_client_ = client.Pass();
+}
+
+void DnsProbeRunner::InitializePublicClient() {
+ DnsConfig config;
+ config.nameservers.push_back(MakeDnsEndPoint(kPublicDnsPrimary));
+ config.nameservers.push_back(MakeDnsEndPoint(kPublicDnsSecondary));
+ config.search.clear();
+ config.attempts = 1;
+ config.randomize_ports = false;
+
+ scoped_ptr<DnsClient> client = DnsClient::CreateClient(NULL);
+ client->SetConfig(config);
+
+ public_client_ = client.Pass();
+}
+
+DnsProbeRunner::Result DnsProbeRunner::GetMockResult(Type type) {
+ DCHECK_EQ(MOCK_RESULTS, mock_mode_);
+
+ switch (type) {
+ case SYSTEM:
+ return mock_system_result_;
+ case PUBLIC:
+ return mock_public_result_;
+ }
+
+ NOTREACHED();
+ return UNKNOWN;
+}
+
+DnsClient* DnsProbeRunner::GetClient(Type type) {
+ DCHECK_NE(MOCK_RESULTS, mock_mode_);
+
+ switch (mock_mode_) {
+ case NO_MOCK:
+ switch (type) {
+ case SYSTEM:
+ return system_client_.get();
+ case PUBLIC:
+ return public_client_.get();
+ }
+ case MOCK_CLIENTS:
+ switch (type) {
+ case SYSTEM:
+ return mock_system_client_.get();
+ case PUBLIC:
+ return mock_public_client_.get();
+ }
+ case MOCK_RESULTS:
+ NOTREACHED();
+ return NULL;
+ }
+
+ NOTREACHED();
+ return NULL;
+}
+
+void DnsProbeRunner::OnTransactionComplete(
+ bool async,
+ DnsTransaction* transaction,
+ int net_error,
+ const DnsResponse* response) {
+ TransactionMap::iterator it = pending_transactions_.find(transaction);
+ // I'd use DCHECK_NE, but it doesn't know how to print iterators.
+ DCHECK(it != pending_transactions_.end());
+
+ const ProbeInfo& info = it->second;
+ const Result result = EvaluateResponse(async, net_error, response);
+ info.callback.Run(info.type, result);
+
+ pending_transactions_.erase(it);
+}
+
+DnsProbeRunner::Result DnsProbeRunner::EvaluateResponse(
+ bool async,
+ int net_error,
+ const DnsResponse* response) {
+ if (!async) {
szym 2013/06/07 19:31:28 I'm not sure you need this. The net_error returned
Deprecated (see juliatuttle) 2013/06/11 01:07:34 I don't *need* it, but I want to be explicit about
+ return UNREACHABLE;
+ }
+
+ if (net_error != net::OK) {
+ if (DidReceiveDnsResponse(net_error)) {
+ return FAILING;
+ } else {
+ return UNREACHABLE;
+ }
+ }
+
+ AddressList addr_list;
+ TimeDelta ttl;
+ DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl);
+
+ if (result != DnsResponse::DNS_PARSE_OK) {
+ return FAILING;
+ }
+
+ if (addr_list.empty()) {
+ return INCORRECT;
+ }
+
+ return CORRECT;
+}

Powered by Google App Engine
This is Rietveld 408576698