| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/network_change_notifier.h" | 5 #include "net/base/network_change_notifier.h" |
| 6 #include "net/base/network_change_notifier_factory.h" | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/synchronization/lock.h" |
| 8 #include "build/build_config.h" | 9 #include "build/build_config.h" |
| 9 #include "googleurl/src/gurl.h" | 10 #include "googleurl/src/gurl.h" |
| 10 #include "net/base/net_util.h" | 11 #include "net/base/net_util.h" |
| 12 #include "net/base/network_change_notifier_factory.h" |
| 13 #include "net/dns/dns_config_service.h" |
| 14 |
| 11 #if defined(OS_WIN) | 15 #if defined(OS_WIN) |
| 12 #include "net/base/network_change_notifier_win.h" | 16 #include "net/base/network_change_notifier_win.h" |
| 13 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS) | 17 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 14 #include "net/base/network_change_notifier_linux.h" | 18 #include "net/base/network_change_notifier_linux.h" |
| 15 #elif defined(OS_MACOSX) | 19 #elif defined(OS_MACOSX) |
| 16 #include "net/base/network_change_notifier_mac.h" | 20 #include "net/base/network_change_notifier_mac.h" |
| 17 #endif | 21 #endif |
| 18 | 22 |
| 19 namespace net { | 23 namespace net { |
| 20 | 24 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 49 last_connection_change_(base::TimeTicks::Now()), | 53 last_connection_change_(base::TimeTicks::Now()), |
| 50 last_dns_change_(base::TimeTicks::Now()), | 54 last_dns_change_(base::TimeTicks::Now()), |
| 51 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), | 55 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), |
| 52 offline_packets_received_(0) {} | 56 offline_packets_received_(0) {} |
| 53 | 57 |
| 54 // Registers our three Observer implementations. This is called from the | 58 // Registers our three Observer implementations. This is called from the |
| 55 // network thread so that our Observer implementations are also called | 59 // network thread so that our Observer implementations are also called |
| 56 // from the network thread. This avoids multi-threaded race conditions | 60 // from the network thread. This avoids multi-threaded race conditions |
| 57 // because the only other interface, |NotifyDataReceived| is also | 61 // because the only other interface, |NotifyDataReceived| is also |
| 58 // only called from the network thread. | 62 // only called from the network thread. |
| 59 void InitHistogramWatcher() { | 63 void Init() { |
| 60 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 64 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 61 NetworkChangeNotifier::AddIPAddressObserver(this); | 65 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 62 NetworkChangeNotifier::AddDNSObserver(this); | 66 NetworkChangeNotifier::AddDNSObserver(this); |
| 63 } | 67 } |
| 64 | 68 |
| 65 virtual ~HistogramWatcher() {} | 69 virtual ~HistogramWatcher() {} |
| 66 | 70 |
| 67 // NetworkChangeNotifier::IPAddressObserver implementation. | 71 // NetworkChangeNotifier::IPAddressObserver implementation. |
| 68 virtual void OnIPAddressChanged() OVERRIDE { | 72 virtual void OnIPAddressChanged() OVERRIDE { |
| 69 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange", | 73 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange", |
| (...skipping 23 matching lines...) Expand all Loading... |
| 93 } else { | 97 } else { |
| 94 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", | 98 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", |
| 95 SinceLast(&last_connection_change_)); | 99 SinceLast(&last_connection_change_)); |
| 96 } | 100 } |
| 97 | 101 |
| 98 offline_packets_received_ = 0; | 102 offline_packets_received_ = 0; |
| 99 last_connection_type_ = type; | 103 last_connection_type_ = type; |
| 100 } | 104 } |
| 101 | 105 |
| 102 // NetworkChangeNotifier::DNSObserver implementation. | 106 // NetworkChangeNotifier::DNSObserver implementation. |
| 103 virtual void OnDNSChanged(unsigned detail) OVERRIDE { | 107 virtual void OnDNSChanged() OVERRIDE { |
| 104 if (detail == NetworkChangeNotifier::CHANGE_DNS_SETTINGS) { | 108 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange", |
| 105 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange", | 109 SinceLast(&last_dns_change_)); |
| 106 SinceLast(&last_dns_change_)); | |
| 107 } | |
| 108 } | 110 } |
| 109 | 111 |
| 110 // Record histogram data whenever we receive a packet but think we're | 112 // Record histogram data whenever we receive a packet but think we're |
| 111 // offline. Should only be called from the network thread. | 113 // offline. Should only be called from the network thread. |
| 112 void NotifyDataReceived(const GURL& source) { | 114 void NotifyDataReceived(const GURL& source) { |
| 113 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE || | 115 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE || |
| 114 IsLocalhost(source.host()) || | 116 IsLocalhost(source.host()) || |
| 115 !(source.SchemeIs("http") || source.SchemeIs("https"))) { | 117 !(source.SchemeIs("http") || source.SchemeIs("https"))) { |
| 116 return; | 118 return; |
| 117 } | 119 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 134 base::TimeTicks last_ip_address_change_; | 136 base::TimeTicks last_ip_address_change_; |
| 135 base::TimeTicks last_connection_change_; | 137 base::TimeTicks last_connection_change_; |
| 136 base::TimeTicks last_dns_change_; | 138 base::TimeTicks last_dns_change_; |
| 137 base::TimeTicks last_offline_packet_received_; | 139 base::TimeTicks last_offline_packet_received_; |
| 138 NetworkChangeNotifier::ConnectionType last_connection_type_; | 140 NetworkChangeNotifier::ConnectionType last_connection_type_; |
| 139 int32 offline_packets_received_; | 141 int32 offline_packets_received_; |
| 140 | 142 |
| 141 DISALLOW_COPY_AND_ASSIGN(HistogramWatcher); | 143 DISALLOW_COPY_AND_ASSIGN(HistogramWatcher); |
| 142 }; | 144 }; |
| 143 | 145 |
| 146 // NetworkState is thread safe. |
| 147 class NetworkChangeNotifier::NetworkState { |
| 148 public: |
| 149 NetworkState() {} |
| 150 ~NetworkState() {} |
| 151 |
| 152 void GetDnsConfig(DnsConfig* config) const { |
| 153 base::AutoLock lock(lock_); |
| 154 *config = dns_config_; |
| 155 } |
| 156 |
| 157 void SetDnsConfig(const DnsConfig& dns_config) { |
| 158 base::AutoLock lock(lock_); |
| 159 dns_config_ = dns_config; |
| 160 } |
| 161 |
| 162 private: |
| 163 mutable base::Lock lock_; |
| 164 DnsConfig dns_config_; |
| 165 }; |
| 166 |
| 144 NetworkChangeNotifier::~NetworkChangeNotifier() { | 167 NetworkChangeNotifier::~NetworkChangeNotifier() { |
| 145 DCHECK_EQ(this, g_network_change_notifier); | 168 DCHECK_EQ(this, g_network_change_notifier); |
| 146 g_network_change_notifier = NULL; | 169 g_network_change_notifier = NULL; |
| 147 } | 170 } |
| 148 | 171 |
| 149 // static | 172 // static |
| 150 void NetworkChangeNotifier::SetFactory( | 173 void NetworkChangeNotifier::SetFactory( |
| 151 NetworkChangeNotifierFactory* factory) { | 174 NetworkChangeNotifierFactory* factory) { |
| 152 CHECK(!g_network_change_notifier_factory); | 175 CHECK(!g_network_change_notifier_factory); |
| 153 g_network_change_notifier_factory = factory; | 176 g_network_change_notifier_factory = factory; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 184 | 207 |
| 185 // static | 208 // static |
| 186 NetworkChangeNotifier::ConnectionType | 209 NetworkChangeNotifier::ConnectionType |
| 187 NetworkChangeNotifier::GetConnectionType() { | 210 NetworkChangeNotifier::GetConnectionType() { |
| 188 return g_network_change_notifier ? | 211 return g_network_change_notifier ? |
| 189 g_network_change_notifier->GetCurrentConnectionType() : | 212 g_network_change_notifier->GetCurrentConnectionType() : |
| 190 CONNECTION_UNKNOWN; | 213 CONNECTION_UNKNOWN; |
| 191 } | 214 } |
| 192 | 215 |
| 193 // static | 216 // static |
| 217 void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) { |
| 218 if (!g_network_change_notifier) { |
| 219 *config = DnsConfig(); |
| 220 } else { |
| 221 g_network_change_notifier->network_state_->GetDnsConfig(config); |
| 222 } |
| 223 } |
| 224 |
| 225 // static |
| 194 void NetworkChangeNotifier::NotifyDataReceived(const GURL& source) { | 226 void NetworkChangeNotifier::NotifyDataReceived(const GURL& source) { |
| 195 if (!g_network_change_notifier) | 227 if (!g_network_change_notifier) |
| 196 return; | 228 return; |
| 197 g_network_change_notifier->histogram_watcher_->NotifyDataReceived(source); | 229 g_network_change_notifier->histogram_watcher_->NotifyDataReceived(source); |
| 198 } | 230 } |
| 199 | 231 |
| 200 // static | 232 // static |
| 201 void NetworkChangeNotifier::InitHistogramWatcher() { | 233 void NetworkChangeNotifier::InitHistogramWatcher() { |
| 202 if (!g_network_change_notifier) | 234 if (!g_network_change_notifier) |
| 203 return; | 235 return; |
| 204 g_network_change_notifier->histogram_watcher_->InitHistogramWatcher(); | 236 g_network_change_notifier->histogram_watcher_->Init(); |
| 205 } | 237 } |
| 206 | 238 |
| 207 #if defined(OS_LINUX) | 239 #if defined(OS_LINUX) |
| 208 // static | 240 // static |
| 209 const internal::AddressTrackerLinux* | 241 const internal::AddressTrackerLinux* |
| 210 NetworkChangeNotifier::GetAddressTracker() { | 242 NetworkChangeNotifier::GetAddressTracker() { |
| 211 return g_network_change_notifier ? | 243 return g_network_change_notifier ? |
| 212 g_network_change_notifier->GetAddressTrackerInternal() : NULL; | 244 g_network_change_notifier->GetAddressTrackerInternal() : NULL; |
| 213 } | 245 } |
| 214 #endif | 246 #endif |
| 215 | 247 |
| 216 // static | 248 // static |
| 217 bool NetworkChangeNotifier::IsWatchingDNS() { | |
| 218 if (!g_network_change_notifier) | |
| 219 return false; | |
| 220 base::AutoLock lock(g_network_change_notifier->watching_dns_lock_); | |
| 221 return g_network_change_notifier->watching_dns_; | |
| 222 } | |
| 223 | |
| 224 // static | |
| 225 NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() { | 249 NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() { |
| 226 return new MockNetworkChangeNotifier(); | 250 return new MockNetworkChangeNotifier(); |
| 227 } | 251 } |
| 228 | 252 |
| 229 void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) { | 253 void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) { |
| 230 if (g_network_change_notifier) | 254 if (g_network_change_notifier) |
| 231 g_network_change_notifier->ip_address_observer_list_->AddObserver(observer); | 255 g_network_change_notifier->ip_address_observer_list_->AddObserver(observer); |
| 232 } | 256 } |
| 233 | 257 |
| 234 void NetworkChangeNotifier::AddConnectionTypeObserver( | 258 void NetworkChangeNotifier::AddConnectionTypeObserver( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 NetworkChangeNotifier::NetworkChangeNotifier() | 296 NetworkChangeNotifier::NetworkChangeNotifier() |
| 273 : ip_address_observer_list_( | 297 : ip_address_observer_list_( |
| 274 new ObserverListThreadSafe<IPAddressObserver>( | 298 new ObserverListThreadSafe<IPAddressObserver>( |
| 275 ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)), | 299 ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)), |
| 276 connection_type_observer_list_( | 300 connection_type_observer_list_( |
| 277 new ObserverListThreadSafe<ConnectionTypeObserver>( | 301 new ObserverListThreadSafe<ConnectionTypeObserver>( |
| 278 ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)), | 302 ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)), |
| 279 resolver_state_observer_list_( | 303 resolver_state_observer_list_( |
| 280 new ObserverListThreadSafe<DNSObserver>( | 304 new ObserverListThreadSafe<DNSObserver>( |
| 281 ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)), | 305 ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)), |
| 282 watching_dns_(false) { | 306 network_state_(new NetworkState()), |
| 307 histogram_watcher_(new HistogramWatcher()) { |
| 283 DCHECK(!g_network_change_notifier); | 308 DCHECK(!g_network_change_notifier); |
| 284 g_network_change_notifier = this; | 309 g_network_change_notifier = this; |
| 285 histogram_watcher_.reset(new HistogramWatcher()); | |
| 286 } | 310 } |
| 287 | 311 |
| 288 #if defined(OS_LINUX) | 312 #if defined(OS_LINUX) |
| 289 const internal::AddressTrackerLinux* | 313 const internal::AddressTrackerLinux* |
| 290 NetworkChangeNotifier::GetAddressTrackerInternal() const { | 314 NetworkChangeNotifier::GetAddressTrackerInternal() const { |
| 291 return NULL; | 315 return NULL; |
| 292 } | 316 } |
| 293 #endif | 317 #endif |
| 294 | 318 |
| 295 // static | 319 // static |
| 296 void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() { | 320 void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() { |
| 297 if (g_network_change_notifier) { | 321 if (g_network_change_notifier) { |
| 298 g_network_change_notifier->ip_address_observer_list_->Notify( | 322 g_network_change_notifier->ip_address_observer_list_->Notify( |
| 299 &IPAddressObserver::OnIPAddressChanged); | 323 &IPAddressObserver::OnIPAddressChanged); |
| 300 } | 324 } |
| 301 } | 325 } |
| 302 | 326 |
| 303 // static | 327 // static |
| 304 void NetworkChangeNotifier::NotifyObserversOfDNSChange(unsigned detail) { | 328 void NetworkChangeNotifier::NotifyObserversOfDNSChange() { |
| 305 if (g_network_change_notifier) { | 329 if (g_network_change_notifier) { |
| 306 { | |
| 307 base::AutoLock lock(g_network_change_notifier->watching_dns_lock_); | |
| 308 if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_STARTED) { | |
| 309 g_network_change_notifier->watching_dns_ = true; | |
| 310 } else if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_FAILED) { | |
| 311 g_network_change_notifier->watching_dns_ = false; | |
| 312 } | |
| 313 // Include detail that watch is off to spare the call to IsWatchingDNS. | |
| 314 if (!g_network_change_notifier->watching_dns_) | |
| 315 detail |= NetworkChangeNotifier::CHANGE_DNS_WATCH_FAILED; | |
| 316 } | |
| 317 DCHECK(!(detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_FAILED) || | |
| 318 !(detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_STARTED)); | |
| 319 g_network_change_notifier->resolver_state_observer_list_->Notify( | 330 g_network_change_notifier->resolver_state_observer_list_->Notify( |
| 320 &DNSObserver::OnDNSChanged, detail); | 331 &DNSObserver::OnDNSChanged); |
| 321 } | 332 } |
| 322 } | 333 } |
| 323 | 334 |
| 335 // static |
| 336 void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) { |
| 337 if (!g_network_change_notifier) |
| 338 return; |
| 339 g_network_change_notifier->network_state_->SetDnsConfig(config); |
| 340 NotifyObserversOfDNSChange(); |
| 341 } |
| 342 |
| 324 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { | 343 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { |
| 325 if (g_network_change_notifier) { | 344 if (g_network_change_notifier) { |
| 326 g_network_change_notifier->connection_type_observer_list_->Notify( | 345 g_network_change_notifier->connection_type_observer_list_->Notify( |
| 327 &ConnectionTypeObserver::OnConnectionTypeChanged, | 346 &ConnectionTypeObserver::OnConnectionTypeChanged, |
| 328 GetConnectionType()); | 347 GetConnectionType()); |
| 329 } | 348 } |
| 330 } | 349 } |
| 331 | 350 |
| 332 NetworkChangeNotifier::DisableForTest::DisableForTest() | 351 NetworkChangeNotifier::DisableForTest::DisableForTest() |
| 333 : network_change_notifier_(g_network_change_notifier) { | 352 : network_change_notifier_(g_network_change_notifier) { |
| 334 DCHECK(g_network_change_notifier); | 353 DCHECK(g_network_change_notifier); |
| 335 g_network_change_notifier = NULL; | 354 g_network_change_notifier = NULL; |
| 336 } | 355 } |
| 337 | 356 |
| 338 NetworkChangeNotifier::DisableForTest::~DisableForTest() { | 357 NetworkChangeNotifier::DisableForTest::~DisableForTest() { |
| 339 DCHECK(!g_network_change_notifier); | 358 DCHECK(!g_network_change_notifier); |
| 340 g_network_change_notifier = network_change_notifier_; | 359 g_network_change_notifier = network_change_notifier_; |
| 341 } | 360 } |
| 342 | 361 |
| 343 } // namespace net | 362 } // namespace net |
| OLD | NEW |