15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/network_change_notifier.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
9e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/threading/thread_checker.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/network_change_notifier_factory.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_config_service.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_ANDROID)
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/metrics/sparse_histogram.h"
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/android/network_library.h"
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/network_change_notifier_win.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/network_change_notifier_linux.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/network_change_notifier_mac.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The actual singleton notifier.  The class contract forbids usage of the API
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in ways that would require us to place locks around access to this object.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (The prohibition on global non-POD objects makes it tricky to do such a thing
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// anyway.)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier* g_network_change_notifier = NULL;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Class factory singleton.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockNetworkChangeNotifier : public NetworkChangeNotifier {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CONNECTION_UNKNOWN;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The main observer class that records UMAs for network events.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HistogramWatcher
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public NetworkChangeNotifier::ConnectionTypeObserver,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public NetworkChangeNotifier::IPAddressObserver,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public NetworkChangeNotifier::DNSObserver,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public NetworkChangeNotifier::NetworkChangeObserver {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistogramWatcher()
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : last_ip_address_change_(base::TimeTicks::Now()),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_connection_change_(base::TimeTicks::Now()),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_dns_change_(base::TimeTicks::Now()),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_network_change_(base::TimeTicks::Now()),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        offline_packets_received_(0),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bytes_read_since_last_connection_change_(0),
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        peak_kbps_since_last_connection_change_(0) {}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Registers our three Observer implementations.  This is called from the
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // network thread so that our Observer implementations are also called
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the network thread.  This avoids multi-threaded race conditions
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because the only other interface, |NotifyDataReceived| is also
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only called from the network thread.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init() {
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(g_network_change_notifier);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkChangeNotifier::AddConnectionTypeObserver(this);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkChangeNotifier::AddIPAddressObserver(this);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkChangeNotifier::AddDNSObserver(this);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetworkChangeNotifier::AddNetworkChangeObserver(this);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual ~HistogramWatcher() {
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(g_network_change_notifier);
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    NetworkChangeNotifier::RemoveIPAddressObserver(this);
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    NetworkChangeNotifier::RemoveDNSObserver(this);
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NetworkChangeNotifier::IPAddressObserver implementation.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIPAddressChanged() OVERRIDE {
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               SinceLast(&last_ip_address_change_));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_MEDIUM_TIMES(
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "NCN.ConnectionTypeChangeToIPAddressChange",
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_ip_address_change_ - last_connection_change_);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NetworkChangeNotifier::ConnectionTypeObserver implementation.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnConnectionTypeChanged(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetworkChangeNotifier::ConnectionType type) OVERRIDE {
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks now = base::TimeTicks::Now();
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32 kilobytes_read = bytes_read_since_last_connection_change_ / 1000;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta state_duration = SinceLast(&last_connection_change_);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (bytes_read_since_last_connection_change_) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switch (last_connection_type_) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_UNKNOWN:
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnUnknown",
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              first_byte_after_connection_change_);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnUnknown",
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_ETHERNET:
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnEthernet",
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              first_byte_after_connection_change_);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnEthernet",
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_WIFI:
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnWifi",
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              first_byte_after_connection_change_);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnWifi",
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_2G:
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn2G",
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              first_byte_after_connection_change_);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn2G",
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_3G:
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn3G",
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              first_byte_after_connection_change_);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn3G",
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_4G:
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn4G",
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              first_byte_after_connection_change_);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn4G",
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_NONE:
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnNone",
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              first_byte_after_connection_change_);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnNone",
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnBluetooth",
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                              first_byte_after_connection_change_);
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnBluetooth",
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                              fastest_RTT_since_last_connection_change_);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (peak_kbps_since_last_connection_change_) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switch (last_connection_type_) {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_UNKNOWN:
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnUnknown",
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_ETHERNET:
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnEthernet",
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_WIFI:
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnWifi",
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_2G:
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn2G",
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_3G:
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn3G",
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_4G:
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn4G",
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_NONE:
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnNone",
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnBluetooth",
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                               peak_kbps_since_last_connection_change_);
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          break;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (last_connection_type_) {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_UNKNOWN:
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnUnknown", state_duration);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnUnknown", kilobytes_read);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_ETHERNET:
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnEthernet", state_duration);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnEthernet", kilobytes_read);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_WIFI:
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnWifi", state_duration);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnWifi", kilobytes_read);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_2G:
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn2G", state_duration);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn2G", kilobytes_read);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_3G:
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn3G", state_duration);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn3G", kilobytes_read);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_4G:
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn4G", state_duration);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn4G", kilobytes_read);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_NONE:
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnNone", state_duration);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnNone", kilobytes_read);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnBluetooth", state_duration);
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnBluetooth", kilobytes_read);
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        break;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type != NetworkChangeNotifier::CONNECTION_NONE) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", state_duration);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (offline_packets_received_) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if ((now - last_offline_packet_received_) <
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::TimeDelta::FromSeconds(5)) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // We can compare this sum with the sum of NCN.OfflineDataRecv.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          UMA_HISTOGRAM_COUNTS_10000(
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "NCN.OfflineDataRecvAny5sBeforeOnline",
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              offline_packets_received_);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline",
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   now - last_offline_packet_received_);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", state_duration);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NetworkChangeNotifier::LogOperatorCodeHistogram(type);
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UMA_HISTOGRAM_MEDIUM_TIMES(
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "NCN.IPAddressChangeToConnectionTypeChange",
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        now - last_ip_address_change_);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offline_packets_received_ = 0;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bytes_read_since_last_connection_change_ = 0;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    peak_kbps_since_last_connection_change_ = 0;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_connection_type_ = type;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    polling_interval_ = base::TimeDelta::FromSeconds(1);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NetworkChangeNotifier::DNSObserver implementation.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnDNSChanged() OVERRIDE {
266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange",
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               SinceLast(&last_dns_change_));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // NetworkChangeNotifier::NetworkChangeObserver implementation.
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnNetworkChanged(
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NetworkChangeNotifier::ConnectionType type) OVERRIDE {
274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (type != NetworkChangeNotifier::CONNECTION_NONE) {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange",
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 SinceLast(&last_network_change_));
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange",
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 SinceLast(&last_network_change_));
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Record histogram data whenever we receive a packet. Should only be called
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from the network thread.
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NotifyDataReceived(const URLRequest& request, int bytes_read) {
287e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (IsLocalhost(request.url().host()) ||
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        !request.url().SchemeIsHTTPOrHTTPS()) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks now = base::TimeTicks::Now();
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta request_duration = now - request.creation_time();
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (bytes_read_since_last_connection_change_ == 0) {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      first_byte_after_connection_change_ = now - last_connection_change_;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fastest_RTT_since_last_connection_change_ = request_duration;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bytes_read_since_last_connection_change_ += bytes_read;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (request_duration < fastest_RTT_since_last_connection_change_)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fastest_RTT_since_last_connection_change_ = request_duration;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ignore tiny transfers which will not produce accurate rates.
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ignore zero duration transfers which might cause divide by zero.
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (bytes_read > 10000 &&
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request_duration > base::TimeDelta::FromMilliseconds(1) &&
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request.creation_time() > last_connection_change_) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int32 kbps = bytes_read * 8 / request_duration.InMilliseconds();
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (kbps > peak_kbps_since_last_connection_change_)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        peak_kbps_since_last_connection_change_ = kbps;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv",
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               now - last_connection_change_);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offline_packets_received_++;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_offline_packet_received_ = now;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((now - last_polled_connection_) > polling_interval_) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      polling_interval_ *= 2;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_polled_connection_ = now;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_polled_connection_type_ =
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NetworkChangeNotifier::GetConnectionType();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_polled_connection_type_ ==
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetworkChangeNotifier::CONNECTION_NONE) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.PollingOfflineDataRecv",
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 now - last_connection_change_);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static base::TimeDelta SinceLast(base::TimeTicks *last_time) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeTicks current_time = base::TimeTicks::Now();
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delta = current_time - *last_time;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *last_time = current_time;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return delta;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks last_ip_address_change_;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks last_connection_change_;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks last_dns_change_;
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeTicks last_network_change_;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks last_offline_packet_received_;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks last_polled_connection_;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // first transition to offline and on subsequent transitions.  Once offline,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |polling_interval_| doubles as offline data is received and we poll
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with |NetworkChangeNotifier::GetConnectionType| to verify the connection
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // state.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta polling_interval_;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |last_connection_type_| is the last value passed to
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |OnConnectionTypeChanged|.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::ConnectionType last_connection_type_;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |last_polled_connection_type_| is last result from calling
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |NetworkChangeNotifier::GetConnectionType| in |NotifyDataReceived|.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::ConnectionType last_polled_connection_type_;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Count of how many times NotifyDataReceived() has been called while the
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // NetworkChangeNotifier thought network connection was offline.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 offline_packets_received_;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Number of bytes of network data received since last connectivity change.
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 bytes_read_since_last_connection_change_;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fastest round-trip-time (RTT) since last connectivity change. RTT measured
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from URLRequest creation until first byte received.
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta fastest_RTT_since_last_connection_change_;
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Time between connectivity change and first network data byte received.
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta first_byte_after_connection_change_;
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Rough measurement of peak KB/s witnessed since last connectivity change.
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The accuracy is decreased by ignoring these factors:
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 1) Multiple URLRequests can occur concurrently.
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 2) NotifyDataReceived() may be called repeatedly for one URLRequest.
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 3) The transfer time includes at least one RTT while no bytes are read.
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Erring on the conservative side is hopefully offset by taking the maximum.
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 peak_kbps_since_last_connection_change_;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
377e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::ThreadChecker thread_checker_;
378e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HistogramWatcher);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NetworkState is thread safe.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NetworkChangeNotifier::NetworkState {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkState() {}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~NetworkState() {}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetDnsConfig(DnsConfig* config) const {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *config = dns_config_;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetDnsConfig(const DnsConfig& dns_config) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dns_config_ = dns_config;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock lock_;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DnsConfig dns_config_;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetworkChangeNotifier::NetworkChangeCalculatorParams::
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetworkChangeCalculatorParams() {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Calculates NetworkChange signal from IPAddress and ConnectionType signals.
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NetworkChangeNotifier::NetworkChangeCalculator
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public ConnectionTypeObserver,
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public IPAddressObserver {
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : params_(params),
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        have_announced_(false),
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_announced_connection_type_(CONNECTION_NONE),
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_connection_type_(CONNECTION_NONE) {}
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Init() {
419e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
420e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(g_network_change_notifier);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddConnectionTypeObserver(this);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddIPAddressObserver(this);
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~NetworkChangeCalculator() {
426e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
427e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(g_network_change_notifier);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoveConnectionTypeObserver(this);
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoveIPAddressObserver(this);
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // NetworkChangeNotifier::IPAddressObserver implementation.
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnIPAddressChanged() OVERRIDE {
434e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_;
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Cancels any previous timer.
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // NetworkChangeNotifier::ConnectionTypeObserver implementation.
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnConnectionTypeChanged(ConnectionType type) OVERRIDE {
443e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_connection_type_ = type;
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ? params_.connection_type_offline_delay_
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        : params_.connection_type_online_delay_;
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Cancels any previous timer.
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Notify() {
454e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Don't bother signaling about dead connections.
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (have_announced_ &&
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (last_announced_connection_type_ == CONNECTION_NONE) &&
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (pending_connection_type_ == CONNECTION_NONE)) {
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    have_announced_ = true;
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_announced_connection_type_ = pending_connection_type_;
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Immediately before sending out an online signal, send out an offline
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // signal to perform any destructive actions before constructive actions.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (pending_connection_type_ != CONNECTION_NONE)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetworkChangeNotifier::NotifyObserversOfNetworkChange(
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_connection_type_);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const NetworkChangeCalculatorParams params_;
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Indicates if NotifyObserversOfNetworkChange has been called yet.
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool have_announced_;
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Last value passed to NotifyObserversOfNetworkChange.
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConnectionType last_announced_connection_type_;
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConnectionType pending_connection_type_;
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used to delay notifications so duplicates can be combined.
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::OneShotTimer<NetworkChangeCalculator> timer_;
481e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
482e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::ThreadChecker thread_checker_;
483e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
484e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DISALLOW_COPY_AND_ASSIGN(NetworkChangeCalculator);
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier::~NetworkChangeNotifier() {
488e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  network_change_calculator_.reset();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(this, g_network_change_notifier);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_network_change_notifier = NULL;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::SetFactory(
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkChangeNotifierFactory* factory) {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!g_network_change_notifier_factory);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_network_change_notifier_factory = factory;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier* NetworkChangeNotifier::Create() {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_network_change_notifier_factory)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return g_network_change_notifier_factory->CreateInstance();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifierWin* network_change_notifier =
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new NetworkChangeNotifierWin();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_change_notifier->WatchForAddressChange();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_change_notifier;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_CHROMEOS) || defined(OS_ANDROID)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChromeOS and Android builds MUST use their own class factory.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_CHROMEOS)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(oshima): ash_shell do not have access to chromeos'es
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifier yet. Re-enable this when chromeos'es notifier moved to
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chromeos root directory. crbug.com/119298.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(false);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NetworkChangeNotifierLinux::Create();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new NetworkChangeNotifierMac();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier::ConnectionType
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier::GetConnectionType() {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_network_change_notifier ?
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_network_change_notifier->GetCurrentConnectionType() :
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CONNECTION_UNKNOWN;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_network_change_notifier) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *config = DnsConfig();
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_network_change_notifier->network_state_->GetDnsConfig(config);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* NetworkChangeNotifier::ConnectionTypeToString(
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConnectionType type) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kConnectionTypeNames[] = {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "CONNECTION_UNKNOWN",
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "CONNECTION_ETHERNET",
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "CONNECTION_WIFI",
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "CONNECTION_2G",
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "CONNECTION_3G",
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "CONNECTION_4G",
55646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "CONNECTION_NONE",
55746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "CONNECTION_BLUETOOTH"
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      arraysize(kConnectionTypeNames) ==
56146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          NetworkChangeNotifier::CONNECTION_LAST + 1,
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ConnectionType_name_count_mismatch);
56346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (type < CONNECTION_UNKNOWN || type > CONNECTION_LAST) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "CONNECTION_INVALID";
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kConnectionTypeNames[type];
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkChangeNotifier::NotifyDataReceived(const URLRequest& request,
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               int bytes_read) {
573e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!g_network_change_notifier ||
574e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      !g_network_change_notifier->histogram_watcher_) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
576e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_network_change_notifier->histogram_watcher_->NotifyDataReceived(request,
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                                    bytes_read);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::InitHistogramWatcher() {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_network_change_notifier)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
585e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  g_network_change_notifier->histogram_watcher_.reset(new HistogramWatcher());
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_network_change_notifier->histogram_watcher_->Init();
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
589e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// static
590e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid NetworkChangeNotifier::ShutdownHistogramWatcher() {
591e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!g_network_change_notifier)
592e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
593e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  g_network_change_notifier->histogram_watcher_.reset();
594e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
595e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NetworkChangeNotifier::LogOperatorCodeHistogram(ConnectionType type) {
598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_ANDROID)
599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // On a connection type change to 2/3/4G, log the network operator MCC/MNC.
600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Log zero in other cases.
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  unsigned mcc_mnc = 0;
602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (type == NetworkChangeNotifier::CONNECTION_2G ||
603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      type == NetworkChangeNotifier::CONNECTION_3G ||
604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      type == NetworkChangeNotifier::CONNECTION_4G) {
605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Log zero if not perfectly converted.
606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!base::StringToUint(
607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        net::android::GetTelephonyNetworkOperator(), &mcc_mnc)) {
608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      mcc_mnc = 0;
609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_SPARSE_SLOWLY("NCN.NetworkOperatorMCCMNC", mcc_mnc);
612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const internal::AddressTrackerLinux*
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier::GetAddressTracker() {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_network_change_notifier ?
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_network_change_notifier->GetAddressTrackerInternal() : NULL;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkChangeNotifier::IsOffline() {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GetConnectionType() == CONNECTION_NONE;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NetworkChangeNotifier::IsConnectionCellular(ConnectionType type) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_cellular = false;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONNECTION_2G:
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONNECTION_3G:
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONNECTION_4G:
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_cellular =  true;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONNECTION_UNKNOWN:
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONNECTION_ETHERNET:
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONNECTION_WIFI:
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONNECTION_NONE:
64246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case CONNECTION_BLUETOOTH:
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_cellular = false;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_cellular;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new MockNetworkChangeNotifier();
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_network_change_notifier)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_network_change_notifier->ip_address_observer_list_->AddObserver(observer);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::AddConnectionTypeObserver(
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConnectionTypeObserver* observer) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_network_change_notifier) {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_network_change_notifier->connection_type_observer_list_->AddObserver(
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        observer);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_network_change_notifier) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_network_change_notifier->resolver_state_observer_list_->AddObserver(
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        observer);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkChangeNotifier::AddNetworkChangeObserver(
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetworkChangeObserver* observer) {
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_network_change_notifier) {
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_network_change_notifier->network_change_observer_list_->AddObserver(
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        observer);
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::RemoveIPAddressObserver(
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPAddressObserver* observer) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_network_change_notifier) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_network_change_notifier->ip_address_observer_list_->RemoveObserver(
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        observer);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::RemoveConnectionTypeObserver(
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConnectionTypeObserver* observer) {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_network_change_notifier) {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_network_change_notifier->connection_type_observer_list_->RemoveObserver(
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        observer);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_network_change_notifier) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_network_change_notifier->resolver_state_observer_list_->RemoveObserver(
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        observer);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkChangeNotifier::RemoveNetworkChangeObserver(
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetworkChangeObserver* observer) {
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_network_change_notifier) {
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_network_change_notifier->network_change_observer_list_->RemoveObserver(
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        observer);
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
713116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
714116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() {
715116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (g_network_change_notifier)
716116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
717116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
718116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
719116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
720116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
721116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ConnectionType type) {
722116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (g_network_change_notifier)
723116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(type);
724116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
725116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
726116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ConnectionType type) {
7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (g_network_change_notifier)
7301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
7311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
734116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::SetTestNotificationsOnly(bool test_only) {
735116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (g_network_change_notifier)
736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_network_change_notifier->test_notifications_only_ = test_only;
737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
738116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetworkChangeNotifier::NetworkChangeNotifier(
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const NetworkChangeCalculatorParams& params
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /*= NetworkChangeCalculatorParams()*/)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ip_address_observer_list_(
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new ObserverListThreadSafe<IPAddressObserver>(
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)),
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_type_observer_list_(
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new ObserverListThreadSafe<ConnectionTypeObserver>(
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)),
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_state_observer_list_(
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new ObserverListThreadSafe<DNSObserver>(
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)),
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      network_change_observer_list_(
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new ObserverListThreadSafe<NetworkChangeObserver>(
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)),
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_state_(new NetworkState()),
755116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      network_change_calculator_(new NetworkChangeCalculator(params)),
756116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      test_notifications_only_(false) {
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!g_network_change_notifier);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_network_change_notifier = this;
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  network_change_calculator_->Init();
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const internal::AddressTrackerLinux*
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier::GetAddressTrackerInternal() const {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() {
771116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (g_network_change_notifier &&
772116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      !g_network_change_notifier->test_notifications_only_) {
773116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
777116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
778116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (g_network_change_notifier &&
780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      !g_network_change_notifier->test_notifications_only_) {
781116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(
782116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        GetConnectionType());
783116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
786116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
787116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfNetworkChange(
788116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ConnectionType type) {
789116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (g_network_change_notifier &&
790116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      !g_network_change_notifier->test_notifications_only_) {
791116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::NotifyObserversOfDNSChange() {
797116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (g_network_change_notifier &&
798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      !g_network_change_notifier->test_notifications_only_) {
799116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    g_network_change_notifier->NotifyObserversOfDNSChangeImpl();
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_network_change_notifier)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_network_change_notifier->network_state_->SetDnsConfig(config);
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyObserversOfDNSChange();
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
811116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() {
812116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ip_address_observer_list_->Notify(&IPAddressObserver::OnIPAddressChanged);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl(
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ConnectionType type) {
817116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  connection_type_observer_list_->Notify(
818116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      &ConnectionTypeObserver::OnConnectionTypeChanged, type);
819116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
820116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
821116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl(
822116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ConnectionType type) {
823116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  network_change_observer_list_->Notify(
824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      &NetworkChangeObserver::OnNetworkChanged, type);
825116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
827116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() {
828116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  resolver_state_observer_list_->Notify(&DNSObserver::OnDNSChanged);
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier::DisableForTest::DisableForTest()
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : network_change_notifier_(g_network_change_notifier) {
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(g_network_change_notifier);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_network_change_notifier = NULL;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkChangeNotifier::DisableForTest::~DisableForTest() {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!g_network_change_notifier);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_network_change_notifier = network_change_notifier_;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
843