summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/io_thread.cc3
-rw-r--r--net/base/network_change_notifier.cc121
-rw-r--r--net/base/network_change_notifier.h15
-rw-r--r--net/url_request/url_request.cc6
4 files changed, 145 insertions, 0 deletions
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 5ada21b..5e33747 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -395,6 +395,9 @@ void IOThread::Init() {
network_change_observer_.reset(
new LoggingNetworkChangeObserver(net_log_));
+ // Setup the HistogramWatcher to run on the IO thread.
+ net::NetworkChangeNotifier::InitHistogramWatcher();
+
globals_->extension_event_router_forwarder =
extension_event_router_forwarder_;
ChromeNetworkDelegate* network_delegate = new ChromeNetworkDelegate(
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index 8c5f446..fa0ad77 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -4,7 +4,10 @@
#include "net/base/network_change_notifier.h"
#include "net/base/network_change_notifier_factory.h"
+#include "base/metrics/histogram.h"
#include "build/build_config.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_util.h"
#if defined(OS_WIN)
#include "net/base/network_change_notifier_win.h"
#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
@@ -35,6 +38,109 @@ class MockNetworkChangeNotifier : public NetworkChangeNotifier {
} // namespace
+// The main observer class that records UMAs for network events.
+class HistogramWatcher
+ : public NetworkChangeNotifier::ConnectionTypeObserver,
+ public NetworkChangeNotifier::IPAddressObserver,
+ public NetworkChangeNotifier::DNSObserver {
+ public:
+ HistogramWatcher()
+ : last_ip_address_change_(base::TimeTicks::Now()),
+ last_connection_change_(base::TimeTicks::Now()),
+ last_dns_change_(base::TimeTicks::Now()),
+ last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
+ offline_packets_received_(0) {}
+
+ // Registers our three Observer implementations. This is called from the
+ // network thread so that our Observer implementations are also called
+ // from the network thread. This avoids multi-threaded race conditions
+ // because the only other interface, |NotifyDataReceived| is also
+ // only called from the network thread.
+ void InitHistogramWatcher() {
+ NetworkChangeNotifier::AddConnectionTypeObserver(this);
+ NetworkChangeNotifier::AddIPAddressObserver(this);
+ NetworkChangeNotifier::AddDNSObserver(this);
+ }
+
+ virtual ~HistogramWatcher() {}
+
+ // NetworkChangeNotifier::IPAddressObserver implementation.
+ virtual void OnIPAddressChanged() OVERRIDE {
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
+ SinceLast(&last_ip_address_change_));
+ }
+
+ // NetworkChangeNotifier::ConnectionTypeObserver implementation.
+ virtual void OnConnectionTypeChanged(
+ NetworkChangeNotifier::ConnectionType type) OVERRIDE {
+ if (type != NetworkChangeNotifier::CONNECTION_NONE) {
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange",
+ SinceLast(&last_connection_change_));
+
+ if (offline_packets_received_) {
+ if ((last_connection_change_ - last_offline_packet_received_) <
+ base::TimeDelta::FromSeconds(5)) {
+ // We can compare this sum with the sum of NCN.OfflineDataRecv.
+ UMA_HISTOGRAM_COUNTS_10000(
+ "NCN.OfflineDataRecvAny5sBeforeOnline",
+ offline_packets_received_);
+ }
+
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline",
+ last_connection_change_ -
+ last_offline_packet_received_);
+ }
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange",
+ SinceLast(&last_connection_change_));
+ }
+
+ offline_packets_received_ = 0;
+ last_connection_type_ = type;
+ }
+
+ // NetworkChangeNotifier::DNSObserver implementation.
+ virtual void OnDNSChanged(unsigned detail) OVERRIDE {
+ if (detail == NetworkChangeNotifier::CHANGE_DNS_SETTINGS) {
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange",
+ SinceLast(&last_dns_change_));
+ }
+ }
+
+ // Record histogram data whenever we receive a packet but think we're
+ // offline. Should only be called from the network thread.
+ void NotifyDataReceived(const GURL& source) {
+ if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE ||
+ IsLocalhost(source.host()) ||
+ !(source.SchemeIs("http") || source.SchemeIs("https"))) {
+ return;
+ }
+
+ base::TimeTicks current_time = base::TimeTicks::Now();
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv",
+ current_time - last_connection_change_);
+ offline_packets_received_++;
+ last_offline_packet_received_ = current_time;
+ }
+
+ private:
+ static base::TimeDelta SinceLast(base::TimeTicks *last_time) {
+ base::TimeTicks current_time = base::TimeTicks::Now();
+ base::TimeDelta delta = current_time - *last_time;
+ *last_time = current_time;
+ return delta;
+ }
+
+ base::TimeTicks last_ip_address_change_;
+ base::TimeTicks last_connection_change_;
+ base::TimeTicks last_dns_change_;
+ base::TimeTicks last_offline_packet_received_;
+ NetworkChangeNotifier::ConnectionType last_connection_type_;
+ int32 offline_packets_received_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistogramWatcher);
+};
+
NetworkChangeNotifier::~NetworkChangeNotifier() {
DCHECK_EQ(this, g_network_change_notifier);
g_network_change_notifier = NULL;
@@ -84,6 +190,20 @@ NetworkChangeNotifier::GetConnectionType() {
CONNECTION_UNKNOWN;
}
+// static
+void NetworkChangeNotifier::NotifyDataReceived(const GURL& source) {
+ if (!g_network_change_notifier)
+ return;
+ g_network_change_notifier->histogram_watcher_->NotifyDataReceived(source);
+}
+
+// static
+void NetworkChangeNotifier::InitHistogramWatcher() {
+ if (!g_network_change_notifier)
+ return;
+ g_network_change_notifier->histogram_watcher_->InitHistogramWatcher();
+}
+
#if defined(OS_LINUX)
// static
const internal::AddressTrackerLinux*
@@ -162,6 +282,7 @@ NetworkChangeNotifier::NetworkChangeNotifier()
watching_dns_(false) {
DCHECK(!g_network_change_notifier);
g_network_change_notifier = this;
+ histogram_watcher_.reset(new HistogramWatcher());
}
#if defined(OS_LINUX)
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index 03bcbf3..10c5064 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -10,8 +10,11 @@
#include "base/synchronization/lock.h"
#include "net/base/net_export.h"
+class GURL;
+
namespace net {
+class HistogramWatcher;
class NetworkChangeNotifierFactory;
namespace internal {
@@ -177,6 +180,15 @@ class NET_EXPORT NetworkChangeNotifier {
NotifyObserversOfIPAddressChange();
}
+ // Let the NetworkChangeNotifier know we received some data.
+ // This is used strictly for producing histogram data about the accuracy of
+ // the NetworkChangenotifier's online detection.
+ static void NotifyDataReceived(const GURL& source);
+
+ // Register the Observer callbacks for producing histogram data. This
+ // should be called from the network thread to avoid race conditions.
+ static void InitHistogramWatcher();
+
protected:
friend class internal::DnsConfigWatcher;
@@ -230,6 +242,9 @@ class NET_EXPORT NetworkChangeNotifier {
base::Lock watching_dns_lock_;
bool watching_dns_;
+ // A little-piggy-back observer that simply logs UMA histogram data.
+ scoped_ptr<HistogramWatcher> histogram_watcher_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier);
};
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 8ea6325..713e153 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -20,6 +20,7 @@
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
+#include "net/base/network_change_notifier.h"
#include "net/base/network_delegate.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/upload_data.h"
@@ -879,6 +880,11 @@ void URLRequest::NotifyReadCompleted(int bytes_read) {
if (bytes_read <= 0)
NotifyRequestCompleted();
+ // Notify NetworkChangeNotifier that we just received network data.
+ // This is to identify cases where the NetworkChangeNotifier thinks we
+ // are off-line but we are still receiving network data (crbug.com/124069).
+ NetworkChangeNotifier::NotifyDataReceived(url());
+
if (delegate_)
delegate_->OnReadCompleted(this, bytes_read);