// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/network_change_notifier.h"

#include <limits>

#include "base/metrics/histogram.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "net/base/net_util.h"
#include "net/base/network_change_notifier_factory.h"
#include "net/dns/dns_config_service.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"

#if defined(OS_ANDROID)
#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_number_conversions.h"
#include "net/android/network_library.h"
#endif

#if defined(OS_WIN)
#include "net/base/network_change_notifier_win.h"
#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
#include "net/base/network_change_notifier_linux.h"
#elif defined(OS_MACOSX)
#include "net/base/network_change_notifier_mac.h"
#endif

namespace net {

namespace {

// The actual singleton notifier.  The class contract forbids usage of the API
// in ways that would require us to place locks around access to this object.
// (The prohibition on global non-POD objects makes it tricky to do such a thing
// anyway.)
NetworkChangeNotifier* g_network_change_notifier = NULL;

// Class factory singleton.
NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL;

class MockNetworkChangeNotifier : public NetworkChangeNotifier {
 public:
  virtual ConnectionType GetCurrentConnectionType() const override {
    return CONNECTION_UNKNOWN;
  }
};

}  // namespace

// The main observer class that records UMAs for network events.
class HistogramWatcher
    : public NetworkChangeNotifier::ConnectionTypeObserver,
      public NetworkChangeNotifier::IPAddressObserver,
      public NetworkChangeNotifier::DNSObserver,
      public NetworkChangeNotifier::NetworkChangeObserver {
 public:
  HistogramWatcher()
      : last_ip_address_change_(base::TimeTicks::Now()),
        last_connection_change_(base::TimeTicks::Now()),
        last_dns_change_(base::TimeTicks::Now()),
        last_network_change_(base::TimeTicks::Now()),
        last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
        offline_packets_received_(0),
        bytes_read_since_last_connection_change_(0),
        peak_kbps_since_last_connection_change_(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 Init() {
    DCHECK(thread_checker_.CalledOnValidThread());
    DCHECK(g_network_change_notifier);
    NetworkChangeNotifier::AddConnectionTypeObserver(this);
    NetworkChangeNotifier::AddIPAddressObserver(this);
    NetworkChangeNotifier::AddDNSObserver(this);
    NetworkChangeNotifier::AddNetworkChangeObserver(this);
  }

  virtual ~HistogramWatcher() {
    DCHECK(thread_checker_.CalledOnValidThread());
    DCHECK(g_network_change_notifier);
    NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
    NetworkChangeNotifier::RemoveIPAddressObserver(this);
    NetworkChangeNotifier::RemoveDNSObserver(this);
    NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
  }

  // NetworkChangeNotifier::IPAddressObserver implementation.
  virtual void OnIPAddressChanged() override {
    DCHECK(thread_checker_.CalledOnValidThread());
    UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
                               SinceLast(&last_ip_address_change_));
    UMA_HISTOGRAM_MEDIUM_TIMES(
        "NCN.ConnectionTypeChangeToIPAddressChange",
        last_ip_address_change_ - last_connection_change_);
  }

  // NetworkChangeNotifier::ConnectionTypeObserver implementation.
  virtual void OnConnectionTypeChanged(
      NetworkChangeNotifier::ConnectionType type) override {
    DCHECK(thread_checker_.CalledOnValidThread());
    base::TimeTicks now = base::TimeTicks::Now();
    int32 kilobytes_read = bytes_read_since_last_connection_change_ / 1000;
    base::TimeDelta state_duration = SinceLast(&last_connection_change_);
    if (bytes_read_since_last_connection_change_) {
      switch (last_connection_type_) {
        case NetworkChangeNotifier::CONNECTION_UNKNOWN:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnUnknown",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnUnknown",
                              fastest_RTT_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_ETHERNET:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnEthernet",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnEthernet",
                              fastest_RTT_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_WIFI:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnWifi",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnWifi",
                              fastest_RTT_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_2G:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn2G",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn2G",
                              fastest_RTT_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_3G:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn3G",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn3G",
                              fastest_RTT_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_4G:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn4G",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn4G",
                              fastest_RTT_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_NONE:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnNone",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnNone",
                              fastest_RTT_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
          UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnBluetooth",
                              first_byte_after_connection_change_);
          UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnBluetooth",
                              fastest_RTT_since_last_connection_change_);
      }
    }
    if (peak_kbps_since_last_connection_change_) {
      switch (last_connection_type_) {
        case NetworkChangeNotifier::CONNECTION_UNKNOWN:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnUnknown",
                               peak_kbps_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_ETHERNET:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnEthernet",
                               peak_kbps_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_WIFI:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnWifi",
                               peak_kbps_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_2G:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn2G",
                               peak_kbps_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_3G:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn3G",
                               peak_kbps_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_4G:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn4G",
                               peak_kbps_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_NONE:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnNone",
                               peak_kbps_since_last_connection_change_);
          break;
        case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
          UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnBluetooth",
                               peak_kbps_since_last_connection_change_);
          break;
      }
    }
    switch (last_connection_type_) {
      case NetworkChangeNotifier::CONNECTION_UNKNOWN:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnUnknown", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnUnknown", kilobytes_read);
        break;
      case NetworkChangeNotifier::CONNECTION_ETHERNET:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnEthernet", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnEthernet", kilobytes_read);
        break;
      case NetworkChangeNotifier::CONNECTION_WIFI:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnWifi", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnWifi", kilobytes_read);
        break;
      case NetworkChangeNotifier::CONNECTION_2G:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn2G", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn2G", kilobytes_read);
        break;
      case NetworkChangeNotifier::CONNECTION_3G:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn3G", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn3G", kilobytes_read);
        break;
      case NetworkChangeNotifier::CONNECTION_4G:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn4G", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn4G", kilobytes_read);
        break;
      case NetworkChangeNotifier::CONNECTION_NONE:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnNone", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnNone", kilobytes_read);
        break;
      case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
        UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnBluetooth", state_duration);
        UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnBluetooth", kilobytes_read);
        break;
    }

    if (type != NetworkChangeNotifier::CONNECTION_NONE) {
      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", state_duration);

      if (offline_packets_received_) {
        if ((now - 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",
                                   now - last_offline_packet_received_);
      }
    } else {
      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", state_duration);
    }

    NetworkChangeNotifier::LogOperatorCodeHistogram(type);

    UMA_HISTOGRAM_MEDIUM_TIMES(
        "NCN.IPAddressChangeToConnectionTypeChange",
        now - last_ip_address_change_);

    offline_packets_received_ = 0;
    bytes_read_since_last_connection_change_ = 0;
    peak_kbps_since_last_connection_change_ = 0;
    last_connection_type_ = type;
    polling_interval_ = base::TimeDelta::FromSeconds(1);
  }

  // NetworkChangeNotifier::DNSObserver implementation.
  virtual void OnDNSChanged() override {
    DCHECK(thread_checker_.CalledOnValidThread());
    UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange",
                               SinceLast(&last_dns_change_));
  }

  // NetworkChangeNotifier::NetworkChangeObserver implementation.
  virtual void OnNetworkChanged(
      NetworkChangeNotifier::ConnectionType type) override {
    DCHECK(thread_checker_.CalledOnValidThread());
    if (type != NetworkChangeNotifier::CONNECTION_NONE) {
      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange",
                                 SinceLast(&last_network_change_));
    } else {
      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange",
                                 SinceLast(&last_network_change_));
    }
  }

  // Record histogram data whenever we receive a packet. Should only be called
  // from the network thread.
  void NotifyDataReceived(const URLRequest& request, int bytes_read) {
    DCHECK(thread_checker_.CalledOnValidThread());
    if (IsLocalhost(request.url().host()) ||
        !request.url().SchemeIsHTTPOrHTTPS()) {
      return;
    }

    base::TimeTicks now = base::TimeTicks::Now();
    base::TimeDelta request_duration = now - request.creation_time();
    if (bytes_read_since_last_connection_change_ == 0) {
      first_byte_after_connection_change_ = now - last_connection_change_;
      fastest_RTT_since_last_connection_change_ = request_duration;
    }
    bytes_read_since_last_connection_change_ += bytes_read;
    if (request_duration < fastest_RTT_since_last_connection_change_)
      fastest_RTT_since_last_connection_change_ = request_duration;
    // Ignore tiny transfers which will not produce accurate rates.
    // Ignore zero duration transfers which might cause divide by zero.
    if (bytes_read > 10000 &&
        request_duration > base::TimeDelta::FromMilliseconds(1) &&
        request.creation_time() > last_connection_change_) {
      int32 kbps = bytes_read * 8 / request_duration.InMilliseconds();
      if (kbps > peak_kbps_since_last_connection_change_)
        peak_kbps_since_last_connection_change_ = kbps;
    }

    if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE)
      return;

    UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv",
                               now - last_connection_change_);
    offline_packets_received_++;
    last_offline_packet_received_ = now;

    if ((now - last_polled_connection_) > polling_interval_) {
      polling_interval_ *= 2;
      last_polled_connection_ = now;
      last_polled_connection_type_ =
          NetworkChangeNotifier::GetConnectionType();
    }
    if (last_polled_connection_type_ ==
        NetworkChangeNotifier::CONNECTION_NONE) {
      UMA_HISTOGRAM_MEDIUM_TIMES("NCN.PollingOfflineDataRecv",
                                 now - last_connection_change_);
    }
  }

 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_network_change_;
  base::TimeTicks last_offline_packet_received_;
  base::TimeTicks last_polled_connection_;
  // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our
  // first transition to offline and on subsequent transitions.  Once offline,
  // |polling_interval_| doubles as offline data is received and we poll
  // with |NetworkChangeNotifier::GetConnectionType| to verify the connection
  // state.
  base::TimeDelta polling_interval_;
  // |last_connection_type_| is the last value passed to
  // |OnConnectionTypeChanged|.
  NetworkChangeNotifier::ConnectionType last_connection_type_;
  // |last_polled_connection_type_| is last result from calling
  // |NetworkChangeNotifier::GetConnectionType| in |NotifyDataReceived|.
  NetworkChangeNotifier::ConnectionType last_polled_connection_type_;
  // Count of how many times NotifyDataReceived() has been called while the
  // NetworkChangeNotifier thought network connection was offline.
  int32 offline_packets_received_;
  // Number of bytes of network data received since last connectivity change.
  int32 bytes_read_since_last_connection_change_;
  // Fastest round-trip-time (RTT) since last connectivity change. RTT measured
  // from URLRequest creation until first byte received.
  base::TimeDelta fastest_RTT_since_last_connection_change_;
  // Time between connectivity change and first network data byte received.
  base::TimeDelta first_byte_after_connection_change_;
  // Rough measurement of peak KB/s witnessed since last connectivity change.
  // The accuracy is decreased by ignoring these factors:
  // 1) Multiple URLRequests can occur concurrently.
  // 2) NotifyDataReceived() may be called repeatedly for one URLRequest.
  // 3) The transfer time includes at least one RTT while no bytes are read.
  // Erring on the conservative side is hopefully offset by taking the maximum.
  int32 peak_kbps_since_last_connection_change_;

  base::ThreadChecker thread_checker_;

  DISALLOW_COPY_AND_ASSIGN(HistogramWatcher);
};

// NetworkState is thread safe.
class NetworkChangeNotifier::NetworkState {
 public:
  NetworkState() {}
  ~NetworkState() {}

  void GetDnsConfig(DnsConfig* config) const {
    base::AutoLock lock(lock_);
    *config = dns_config_;
  }

  void SetDnsConfig(const DnsConfig& dns_config) {
    base::AutoLock lock(lock_);
    dns_config_ = dns_config;
  }

 private:
  mutable base::Lock lock_;
  DnsConfig dns_config_;
};

NetworkChangeNotifier::NetworkChangeCalculatorParams::
    NetworkChangeCalculatorParams() {
}

// Calculates NetworkChange signal from IPAddress and ConnectionType signals.
class NetworkChangeNotifier::NetworkChangeCalculator
    : public ConnectionTypeObserver,
      public IPAddressObserver {
 public:
  NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
      : params_(params),
        have_announced_(false),
        last_announced_connection_type_(CONNECTION_NONE),
        pending_connection_type_(CONNECTION_NONE) {}

  void Init() {
    DCHECK(thread_checker_.CalledOnValidThread());
    DCHECK(g_network_change_notifier);
    AddConnectionTypeObserver(this);
    AddIPAddressObserver(this);
  }

  virtual ~NetworkChangeCalculator() {
    DCHECK(thread_checker_.CalledOnValidThread());
    DCHECK(g_network_change_notifier);
    RemoveConnectionTypeObserver(this);
    RemoveIPAddressObserver(this);
  }

  // NetworkChangeNotifier::IPAddressObserver implementation.
  virtual void OnIPAddressChanged() override {
    DCHECK(thread_checker_.CalledOnValidThread());
    base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
        ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_;
    // Cancels any previous timer.
    timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
  }

  // NetworkChangeNotifier::ConnectionTypeObserver implementation.
  virtual void OnConnectionTypeChanged(ConnectionType type) override {
    DCHECK(thread_checker_.CalledOnValidThread());
    pending_connection_type_ = type;
    base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
        ? params_.connection_type_offline_delay_
        : params_.connection_type_online_delay_;
    // Cancels any previous timer.
    timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
  }

 private:
  void Notify() {
    DCHECK(thread_checker_.CalledOnValidThread());
    // Don't bother signaling about dead connections.
    if (have_announced_ &&
        (last_announced_connection_type_ == CONNECTION_NONE) &&
        (pending_connection_type_ == CONNECTION_NONE)) {
      return;
    }
    have_announced_ = true;
    last_announced_connection_type_ = pending_connection_type_;
    // Immediately before sending out an online signal, send out an offline
    // signal to perform any destructive actions before constructive actions.
    if (pending_connection_type_ != CONNECTION_NONE)
      NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE);
    NetworkChangeNotifier::NotifyObserversOfNetworkChange(
        pending_connection_type_);
  }

  const NetworkChangeCalculatorParams params_;

  // Indicates if NotifyObserversOfNetworkChange has been called yet.
  bool have_announced_;
  // Last value passed to NotifyObserversOfNetworkChange.
  ConnectionType last_announced_connection_type_;
  // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
  ConnectionType pending_connection_type_;
  // Used to delay notifications so duplicates can be combined.
  base::OneShotTimer<NetworkChangeCalculator> timer_;

  base::ThreadChecker thread_checker_;

  DISALLOW_COPY_AND_ASSIGN(NetworkChangeCalculator);
};

NetworkChangeNotifier::~NetworkChangeNotifier() {
  network_change_calculator_.reset();
  DCHECK_EQ(this, g_network_change_notifier);
  g_network_change_notifier = NULL;
}

// static
void NetworkChangeNotifier::SetFactory(
    NetworkChangeNotifierFactory* factory) {
  CHECK(!g_network_change_notifier_factory);
  g_network_change_notifier_factory = factory;
}

// static
NetworkChangeNotifier* NetworkChangeNotifier::Create() {
  if (g_network_change_notifier_factory)
    return g_network_change_notifier_factory->CreateInstance();

#if defined(OS_WIN)
  NetworkChangeNotifierWin* network_change_notifier =
      new NetworkChangeNotifierWin();
  network_change_notifier->WatchForAddressChange();
  return network_change_notifier;
#elif defined(OS_CHROMEOS) || defined(OS_ANDROID)
  // ChromeOS and Android builds MUST use their own class factory.
#if !defined(OS_CHROMEOS)
  // TODO(oshima): ash_shell do not have access to chromeos'es
  // notifier yet. Re-enable this when chromeos'es notifier moved to
  // chromeos root directory. crbug.com/119298.
  CHECK(false);
#endif
  return NULL;
#elif defined(OS_LINUX)
  return NetworkChangeNotifierLinux::Create();
#elif defined(OS_MACOSX)
  return new NetworkChangeNotifierMac();
#else
  NOTIMPLEMENTED();
  return NULL;
#endif
}

// static
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifier::GetConnectionType() {
  return g_network_change_notifier ?
      g_network_change_notifier->GetCurrentConnectionType() :
      CONNECTION_UNKNOWN;
}

// static
double NetworkChangeNotifier::GetMaxBandwidth() {
  return g_network_change_notifier ?
      g_network_change_notifier->GetCurrentMaxBandwidth() :
      std::numeric_limits<double>::infinity();
}

// static
void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) {
  if (!g_network_change_notifier) {
    *config = DnsConfig();
  } else {
    g_network_change_notifier->network_state_->GetDnsConfig(config);
  }
}

// static
const char* NetworkChangeNotifier::ConnectionTypeToString(
    ConnectionType type) {
  static const char* kConnectionTypeNames[] = {
    "CONNECTION_UNKNOWN",
    "CONNECTION_ETHERNET",
    "CONNECTION_WIFI",
    "CONNECTION_2G",
    "CONNECTION_3G",
    "CONNECTION_4G",
    "CONNECTION_NONE",
    "CONNECTION_BLUETOOTH"
  };
  COMPILE_ASSERT(
      arraysize(kConnectionTypeNames) ==
          NetworkChangeNotifier::CONNECTION_LAST + 1,
      ConnectionType_name_count_mismatch);
  if (type < CONNECTION_UNKNOWN || type > CONNECTION_LAST) {
    NOTREACHED();
    return "CONNECTION_INVALID";
  }
  return kConnectionTypeNames[type];
}

// static
void NetworkChangeNotifier::NotifyDataReceived(const URLRequest& request,
                                               int bytes_read) {
  if (!g_network_change_notifier ||
      !g_network_change_notifier->histogram_watcher_) {
    return;
  }
  g_network_change_notifier->histogram_watcher_->NotifyDataReceived(request,
                                                                    bytes_read);
}

// static
void NetworkChangeNotifier::InitHistogramWatcher() {
  if (!g_network_change_notifier)
    return;
  g_network_change_notifier->histogram_watcher_.reset(new HistogramWatcher());
  g_network_change_notifier->histogram_watcher_->Init();
}

// static
void NetworkChangeNotifier::ShutdownHistogramWatcher() {
  if (!g_network_change_notifier)
    return;
  g_network_change_notifier->histogram_watcher_.reset();
}

// static
void NetworkChangeNotifier::LogOperatorCodeHistogram(ConnectionType type) {
#if defined(OS_ANDROID)
  // On a connection type change to 2/3/4G, log the network operator MCC/MNC.
  // Log zero in other cases.
  unsigned mcc_mnc = 0;
  if (type == NetworkChangeNotifier::CONNECTION_2G ||
      type == NetworkChangeNotifier::CONNECTION_3G ||
      type == NetworkChangeNotifier::CONNECTION_4G) {
    // Log zero if not perfectly converted.
    if (!base::StringToUint(
        net::android::GetTelephonyNetworkOperator(), &mcc_mnc)) {
      mcc_mnc = 0;
    }
  }
  UMA_HISTOGRAM_SPARSE_SLOWLY("NCN.NetworkOperatorMCCMNC", mcc_mnc);
#endif
}

#if defined(OS_LINUX)
// static
const internal::AddressTrackerLinux*
NetworkChangeNotifier::GetAddressTracker() {
  return g_network_change_notifier ?
        g_network_change_notifier->GetAddressTrackerInternal() : NULL;
}
#endif

// static
bool NetworkChangeNotifier::IsOffline() {
   return GetConnectionType() == CONNECTION_NONE;
}

// static
bool NetworkChangeNotifier::IsConnectionCellular(ConnectionType type) {
  bool is_cellular = false;
  switch (type) {
    case CONNECTION_2G:
    case CONNECTION_3G:
    case CONNECTION_4G:
      is_cellular =  true;
      break;
    case CONNECTION_UNKNOWN:
    case CONNECTION_ETHERNET:
    case CONNECTION_WIFI:
    case CONNECTION_NONE:
    case CONNECTION_BLUETOOTH:
      is_cellular = false;
      break;
  }
  return is_cellular;
}

// static
NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() {
  return new MockNetworkChangeNotifier();
}

void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) {
  if (g_network_change_notifier)
    g_network_change_notifier->ip_address_observer_list_->AddObserver(observer);
}

void NetworkChangeNotifier::AddConnectionTypeObserver(
    ConnectionTypeObserver* observer) {
  if (g_network_change_notifier) {
    g_network_change_notifier->connection_type_observer_list_->AddObserver(
        observer);
  }
}

void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) {
  if (g_network_change_notifier) {
    g_network_change_notifier->resolver_state_observer_list_->AddObserver(
        observer);
  }
}

void NetworkChangeNotifier::AddNetworkChangeObserver(
    NetworkChangeObserver* observer) {
  if (g_network_change_notifier) {
    g_network_change_notifier->network_change_observer_list_->AddObserver(
        observer);
  }
}

void NetworkChangeNotifier::RemoveIPAddressObserver(
    IPAddressObserver* observer) {
  if (g_network_change_notifier) {
    g_network_change_notifier->ip_address_observer_list_->RemoveObserver(
        observer);
  }
}

void NetworkChangeNotifier::RemoveConnectionTypeObserver(
    ConnectionTypeObserver* observer) {
  if (g_network_change_notifier) {
    g_network_change_notifier->connection_type_observer_list_->RemoveObserver(
        observer);
  }
}

void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) {
  if (g_network_change_notifier) {
    g_network_change_notifier->resolver_state_observer_list_->RemoveObserver(
        observer);
  }
}

void NetworkChangeNotifier::RemoveNetworkChangeObserver(
    NetworkChangeObserver* observer) {
  if (g_network_change_notifier) {
    g_network_change_notifier->network_change_observer_list_->RemoveObserver(
        observer);
  }
}

// static
void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() {
  if (g_network_change_notifier)
    g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
}

// static
void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
    ConnectionType type) {
  if (g_network_change_notifier)
    g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(type);
}

// static
void NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
    ConnectionType type) {
  if (g_network_change_notifier)
    g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
}

// static
void NetworkChangeNotifier::SetTestNotificationsOnly(bool test_only) {
  if (g_network_change_notifier)
    g_network_change_notifier->test_notifications_only_ = test_only;
}

NetworkChangeNotifier::NetworkChangeNotifier(
    const NetworkChangeCalculatorParams& params
        /*= NetworkChangeCalculatorParams()*/)
    : ip_address_observer_list_(
        new ObserverListThreadSafe<IPAddressObserver>(
            ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)),
      connection_type_observer_list_(
        new ObserverListThreadSafe<ConnectionTypeObserver>(
            ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)),
      resolver_state_observer_list_(
        new ObserverListThreadSafe<DNSObserver>(
            ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)),
      network_change_observer_list_(
        new ObserverListThreadSafe<NetworkChangeObserver>(
            ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)),
      network_state_(new NetworkState()),
      network_change_calculator_(new NetworkChangeCalculator(params)),
      test_notifications_only_(false) {
  DCHECK(!g_network_change_notifier);
  g_network_change_notifier = this;
  network_change_calculator_->Init();
}

#if defined(OS_LINUX)
const internal::AddressTrackerLinux*
NetworkChangeNotifier::GetAddressTrackerInternal() const {
  return NULL;
}
#endif

double NetworkChangeNotifier::GetCurrentMaxBandwidth() const {
  // This default implementation conforms to the NetInfo V3 specification but
  // should be overridden to provide specific bandwidth data based on the
  // platform.
  if (GetCurrentConnectionType() == CONNECTION_NONE)
    return 0.0;
  return std::numeric_limits<double>::infinity();
}

// static
void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() {
  if (g_network_change_notifier &&
      !g_network_change_notifier->test_notifications_only_) {
    g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
  }
}

// static
void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
  if (g_network_change_notifier &&
      !g_network_change_notifier->test_notifications_only_) {
    g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(
        GetConnectionType());
  }
}

// static
void NetworkChangeNotifier::NotifyObserversOfNetworkChange(
    ConnectionType type) {
  if (g_network_change_notifier &&
      !g_network_change_notifier->test_notifications_only_) {
    g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
  }
}

// static
void NetworkChangeNotifier::NotifyObserversOfDNSChange() {
  if (g_network_change_notifier &&
      !g_network_change_notifier->test_notifications_only_) {
    g_network_change_notifier->NotifyObserversOfDNSChangeImpl();
  }
}

// static
void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) {
  if (!g_network_change_notifier)
    return;
  g_network_change_notifier->network_state_->SetDnsConfig(config);
  NotifyObserversOfDNSChange();
}

void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() {
  ip_address_observer_list_->Notify(&IPAddressObserver::OnIPAddressChanged);
}

void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl(
    ConnectionType type) {
  connection_type_observer_list_->Notify(
      &ConnectionTypeObserver::OnConnectionTypeChanged, type);
}

void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl(
    ConnectionType type) {
  network_change_observer_list_->Notify(
      &NetworkChangeObserver::OnNetworkChanged, type);
}

void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() {
  resolver_state_observer_list_->Notify(&DNSObserver::OnDNSChanged);
}

NetworkChangeNotifier::DisableForTest::DisableForTest()
    : network_change_notifier_(g_network_change_notifier) {
  DCHECK(g_network_change_notifier);
  g_network_change_notifier = NULL;
}

NetworkChangeNotifier::DisableForTest::~DisableForTest() {
  DCHECK(!g_network_change_notifier);
  g_network_change_notifier = network_change_notifier_;
}

}  // namespace net
