Chromium Code Reviews| Index: net/base/network_change_notifier.cc |
| diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc |
| index e8dd1208e4127713433df6c0dfbb9836d6d46a57..43c9247fb01962eb1cff36381d3f885f445b4c56 100644 |
| --- a/net/base/network_change_notifier.cc |
| +++ b/net/base/network_change_notifier.cc |
| @@ -35,6 +35,7 @@ NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL; |
| class MockNetworkChangeNotifier : public NetworkChangeNotifier { |
| public: |
| + MockNetworkChangeNotifier() : NetworkChangeNotifier(0, 0, 0, 0) {} |
| virtual ConnectionType GetCurrentConnectionType() const OVERRIDE { |
| return CONNECTION_UNKNOWN; |
| } |
| @@ -46,12 +47,14 @@ class MockNetworkChangeNotifier : public NetworkChangeNotifier { |
| class HistogramWatcher |
| : public NetworkChangeNotifier::ConnectionTypeObserver, |
| public NetworkChangeNotifier::IPAddressObserver, |
| - public NetworkChangeNotifier::DNSObserver { |
| + 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) {} |
| @@ -64,6 +67,7 @@ class HistogramWatcher |
| NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| NetworkChangeNotifier::AddIPAddressObserver(this); |
| NetworkChangeNotifier::AddDNSObserver(this); |
| + NetworkChangeNotifier::AddNetworkChangeObserver(this); |
| } |
| virtual ~HistogramWatcher() {} |
| @@ -72,6 +76,9 @@ class HistogramWatcher |
| virtual void OnIPAddressChanged() OVERRIDE { |
| 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. |
| @@ -98,6 +105,9 @@ class HistogramWatcher |
| UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", |
| SinceLast(&last_connection_change_)); |
| } |
| + UMA_HISTOGRAM_MEDIUM_TIMES( |
| + "NCN.IPAddressChangeToConnectionTypeChange", |
| + last_connection_change_ - last_ip_address_change_); |
| offline_packets_received_ = 0; |
| last_connection_type_ = type; |
| @@ -110,6 +120,18 @@ class HistogramWatcher |
| SinceLast(&last_dns_change_)); |
| } |
| + // NetworkChangeNotifier::NetworkChangeObserver implementation. |
| + virtual void OnNetworkChanged( |
| + NetworkChangeNotifier::ConnectionType type) OVERRIDE { |
| + 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 but think we're |
| // offline. Should only be called from the network thread. |
| void NotifyDataReceived(const GURL& source) { |
| @@ -153,6 +175,7 @@ class HistogramWatcher |
| 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 |
| @@ -193,6 +216,89 @@ class NetworkChangeNotifier::NetworkState { |
| DnsConfig dns_config_; |
| }; |
| +// Calculates NetworkChange signal from IPAddress and ConnectionType signals. |
| +class NetworkChangeNotifier::NetworkChangeCalculator |
| + : public ConnectionTypeObserver, |
| + public IPAddressObserver { |
| + public: |
| + // Delay arguments control how many milliseconds to delay notifications |
| + // so as to combine duplicates. |ip_address_offline_delay_ms| controls |
| + // delay after OnIPAddressChanged when transitioning from an offline state. |
| + // |ip_address_online_delay_ms| controls delay after OnIPAddressChanged when |
| + // transitioning from an online state. |connection_type_offline_delay_ms| |
| + // controls delay after OnConnectionTypeChanged when transitioning from an |
| + // offline state. |connection_type_online_delay_ms| controls delay after |
| + // OnConnectionTypeChanged when transitioning from an online state. |
|
szym
2012/11/25 07:37:37
This comment needs to explain that the notificatio
|
| + NetworkChangeCalculator(uint32 ip_address_offline_delay_ms, |
| + uint32 ip_address_online_delay_ms, |
| + uint32 connection_type_offline_delay_ms, |
| + uint32 connection_type_online_delay_ms) |
| + : ip_address_offline_delay_(base::TimeDelta::FromMilliseconds( |
| + ip_address_offline_delay_ms)), |
| + ip_address_online_delay_(base::TimeDelta::FromMilliseconds( |
| + ip_address_online_delay_ms)), |
| + connection_type_offline_delay_(base::TimeDelta::FromMilliseconds( |
| + connection_type_offline_delay_ms)), |
| + connection_type_online_delay_(base::TimeDelta::FromMilliseconds( |
| + connection_type_online_delay_ms)), |
| + have_announced_(false), |
| + last_announced_connection_type_(CONNECTION_NONE), |
| + pending_connection_type_(CONNECTION_NONE) {} |
| + void Init() { |
| + AddConnectionTypeObserver(this); |
| + AddIPAddressObserver(this); |
| + } |
| + virtual ~NetworkChangeCalculator() { |
| + RemoveConnectionTypeObserver(this); |
| + RemoveIPAddressObserver(this); |
| + } |
| + |
| + // NetworkChangeNotifier::IPAddressObserver implementation. |
|
szym
2012/11/25 07:37:37
nit: no need for "implementation"
pauljensen
2012/11/27 21:47:42
I see a lot of people using "implementation": URLR
|
| + virtual void OnIPAddressChanged() OVERRIDE { |
| + base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE |
| + ? ip_address_offline_delay_ : ip_address_online_delay_; |
| + timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify); |
|
szym
2012/11/25 07:37:37
Perhaps a note (a reminder really) that this cance
|
| + } |
| + |
| + // NetworkChangeNotifier::ConnectionTypeObserver implementation. |
| + virtual void OnConnectionTypeChanged(ConnectionType type) OVERRIDE { |
| + pending_connection_type_ = type; |
| + base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE |
| + ? connection_type_offline_delay_ : connection_type_online_delay_; |
| + timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify); |
| + } |
| + |
| + private: |
| + void Notify() { |
| + // Don't bother signaling about dead connections. |
| + if (have_announced_ && last_announced_connection_type_ == CONNECTION_NONE && |
|
szym
2012/11/25 07:37:37
suggest parens for readability
|
| + pending_connection_type_ == CONNECTION_NONE) |
|
szym
2012/11/25 07:37:37
Could the same logic be accomplished by initializi
pauljensen
2012/11/27 21:47:42
The timeouts are essential for all announcements;
|
| + return; |
|
szym
2012/11/25 07:37:37
use braces when if condition is multiline
|
| + 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 base::TimeDelta ip_address_offline_delay_; |
| + const base::TimeDelta ip_address_online_delay_; |
| + const base::TimeDelta connection_type_offline_delay_; |
| + const base::TimeDelta connection_type_online_delay_; |
| + |
| + // 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_; |
| +}; |
| + |
| NetworkChangeNotifier::~NetworkChangeNotifier() { |
| DCHECK_EQ(this, g_network_change_notifier); |
| g_network_change_notifier = NULL; |
| @@ -346,6 +452,14 @@ void NetworkChangeNotifier::AddDNSObserver(DNSObserver* 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) { |
| @@ -369,7 +483,19 @@ void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) { |
| } |
| } |
| -NetworkChangeNotifier::NetworkChangeNotifier() |
| +void NetworkChangeNotifier::RemoveNetworkChangeObserver( |
| + NetworkChangeObserver* observer) { |
| + if (g_network_change_notifier) { |
| + g_network_change_notifier->network_change_observer_list_->RemoveObserver( |
| + observer); |
| + } |
| +} |
| + |
| +NetworkChangeNotifier::NetworkChangeNotifier( |
| + uint32 ip_address_offline_delay_ms, |
| + uint32 ip_address_online_delay_ms, |
| + uint32 connection_type_offline_delay_ms, |
| + uint32 connection_type_online_delay_ms) |
| : ip_address_observer_list_( |
| new ObserverListThreadSafe<IPAddressObserver>( |
| ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)), |
| @@ -379,10 +505,19 @@ NetworkChangeNotifier::NetworkChangeNotifier() |
| 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()), |
| - histogram_watcher_(new HistogramWatcher()) { |
| + histogram_watcher_(new HistogramWatcher()), |
| + network_change_calculator_(new NetworkChangeCalculator( |
| + ip_address_offline_delay_ms, |
| + ip_address_online_delay_ms, |
| + connection_type_offline_delay_ms, |
| + connection_type_online_delay_ms)) { |
| DCHECK(!g_network_change_notifier); |
| g_network_change_notifier = this; |
| + network_change_calculator_->Init(); |
| } |
| #if defined(OS_LINUX) |
| @@ -424,6 +559,15 @@ void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { |
| } |
| } |
| +void NetworkChangeNotifier::NotifyObserversOfNetworkChange( |
| + ConnectionType type) { |
| + if (g_network_change_notifier) { |
| + g_network_change_notifier->network_change_observer_list_->Notify( |
| + &NetworkChangeObserver::OnNetworkChanged, |
| + type); |
| + } |
| +} |
| + |
| NetworkChangeNotifier::DisableForTest::DisableForTest() |
| : network_change_notifier_(g_network_change_notifier) { |
| DCHECK(g_network_change_notifier); |