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 3 // found in the LICENSE file. 4 5 #include "net/base/network_change_notifier.h" 6 7 #include "base/metrics/histogram.h" 8 #include "base/synchronization/lock.h" 9 #include "base/threading/thread_checker.h" 10 #include "build/build_config.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 #include "net/url_request/url_request.h" 15 #include "url/gurl.h" 16 17 #if defined(OS_ANDROID) 18 #include "base/metrics/sparse_histogram.h" 19 #include "base/strings/string_number_conversions.h" 20 #include "net/android/network_library.h" 21 #endif 22 23 #if defined(OS_WIN) 24 #include "net/base/network_change_notifier_win.h" 25 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS) 26 #include "net/base/network_change_notifier_linux.h" 27 #elif defined(OS_MACOSX) 28 #include "net/base/network_change_notifier_mac.h" 29 #endif 30 31 namespace net { 32 33 namespace { 34 35 // The actual singleton notifier. The class contract forbids usage of the API 36 // in ways that would require us to place locks around access to this object. 37 // (The prohibition on global non-POD objects makes it tricky to do such a thing 38 // anyway.) 39 NetworkChangeNotifier* g_network_change_notifier = NULL; 40 41 // Class factory singleton. 42 NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL; 43 44 class MockNetworkChangeNotifier : public NetworkChangeNotifier { 45 public: 46 virtual ConnectionType GetCurrentConnectionType() const OVERRIDE { 47 return CONNECTION_UNKNOWN; 48 } 49 }; 50 51 } // namespace 52 53 // The main observer class that records UMAs for network events. 54 class HistogramWatcher 55 : public NetworkChangeNotifier::ConnectionTypeObserver, 56 public NetworkChangeNotifier::IPAddressObserver, 57 public NetworkChangeNotifier::DNSObserver, 58 public NetworkChangeNotifier::NetworkChangeObserver { 59 public: 60 HistogramWatcher() 61 : last_ip_address_change_(base::TimeTicks::Now()), 62 last_connection_change_(base::TimeTicks::Now()), 63 last_dns_change_(base::TimeTicks::Now()), 64 last_network_change_(base::TimeTicks::Now()), 65 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), 66 offline_packets_received_(0), 67 bytes_read_since_last_connection_change_(0), 68 peak_kbps_since_last_connection_change_(0) {} 69 70 // Registers our three Observer implementations. This is called from the 71 // network thread so that our Observer implementations are also called 72 // from the network thread. This avoids multi-threaded race conditions 73 // because the only other interface, |NotifyDataReceived| is also 74 // only called from the network thread. 75 void Init() { 76 DCHECK(thread_checker_.CalledOnValidThread()); 77 DCHECK(g_network_change_notifier); 78 NetworkChangeNotifier::AddConnectionTypeObserver(this); 79 NetworkChangeNotifier::AddIPAddressObserver(this); 80 NetworkChangeNotifier::AddDNSObserver(this); 81 NetworkChangeNotifier::AddNetworkChangeObserver(this); 82 } 83 84 virtual ~HistogramWatcher() { 85 DCHECK(thread_checker_.CalledOnValidThread()); 86 DCHECK(g_network_change_notifier); 87 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 88 NetworkChangeNotifier::RemoveIPAddressObserver(this); 89 NetworkChangeNotifier::RemoveDNSObserver(this); 90 NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 91 } 92 93 // NetworkChangeNotifier::IPAddressObserver implementation. 94 virtual void OnIPAddressChanged() OVERRIDE { 95 DCHECK(thread_checker_.CalledOnValidThread()); 96 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange", 97 SinceLast(&last_ip_address_change_)); 98 UMA_HISTOGRAM_MEDIUM_TIMES( 99 "NCN.ConnectionTypeChangeToIPAddressChange", 100 last_ip_address_change_ - last_connection_change_); 101 } 102 103 // NetworkChangeNotifier::ConnectionTypeObserver implementation. 104 virtual void OnConnectionTypeChanged( 105 NetworkChangeNotifier::ConnectionType type) OVERRIDE { 106 DCHECK(thread_checker_.CalledOnValidThread()); 107 base::TimeTicks now = base::TimeTicks::Now(); 108 int32 kilobytes_read = bytes_read_since_last_connection_change_ / 1000; 109 base::TimeDelta state_duration = SinceLast(&last_connection_change_); 110 if (bytes_read_since_last_connection_change_) { 111 switch (last_connection_type_) { 112 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 113 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnUnknown", 114 first_byte_after_connection_change_); 115 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnUnknown", 116 fastest_RTT_since_last_connection_change_); 117 break; 118 case NetworkChangeNotifier::CONNECTION_ETHERNET: 119 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnEthernet", 120 first_byte_after_connection_change_); 121 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnEthernet", 122 fastest_RTT_since_last_connection_change_); 123 break; 124 case NetworkChangeNotifier::CONNECTION_WIFI: 125 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnWifi", 126 first_byte_after_connection_change_); 127 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnWifi", 128 fastest_RTT_since_last_connection_change_); 129 break; 130 case NetworkChangeNotifier::CONNECTION_2G: 131 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn2G", 132 first_byte_after_connection_change_); 133 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn2G", 134 fastest_RTT_since_last_connection_change_); 135 break; 136 case NetworkChangeNotifier::CONNECTION_3G: 137 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn3G", 138 first_byte_after_connection_change_); 139 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn3G", 140 fastest_RTT_since_last_connection_change_); 141 break; 142 case NetworkChangeNotifier::CONNECTION_4G: 143 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn4G", 144 first_byte_after_connection_change_); 145 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn4G", 146 fastest_RTT_since_last_connection_change_); 147 break; 148 case NetworkChangeNotifier::CONNECTION_NONE: 149 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnNone", 150 first_byte_after_connection_change_); 151 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnNone", 152 fastest_RTT_since_last_connection_change_); 153 break; 154 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 155 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnBluetooth", 156 first_byte_after_connection_change_); 157 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnBluetooth", 158 fastest_RTT_since_last_connection_change_); 159 } 160 } 161 if (peak_kbps_since_last_connection_change_) { 162 switch (last_connection_type_) { 163 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 164 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnUnknown", 165 peak_kbps_since_last_connection_change_); 166 break; 167 case NetworkChangeNotifier::CONNECTION_ETHERNET: 168 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnEthernet", 169 peak_kbps_since_last_connection_change_); 170 break; 171 case NetworkChangeNotifier::CONNECTION_WIFI: 172 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnWifi", 173 peak_kbps_since_last_connection_change_); 174 break; 175 case NetworkChangeNotifier::CONNECTION_2G: 176 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn2G", 177 peak_kbps_since_last_connection_change_); 178 break; 179 case NetworkChangeNotifier::CONNECTION_3G: 180 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn3G", 181 peak_kbps_since_last_connection_change_); 182 break; 183 case NetworkChangeNotifier::CONNECTION_4G: 184 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn4G", 185 peak_kbps_since_last_connection_change_); 186 break; 187 case NetworkChangeNotifier::CONNECTION_NONE: 188 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnNone", 189 peak_kbps_since_last_connection_change_); 190 break; 191 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 192 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnBluetooth", 193 peak_kbps_since_last_connection_change_); 194 break; 195 } 196 } 197 switch (last_connection_type_) { 198 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 199 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnUnknown", state_duration); 200 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnUnknown", kilobytes_read); 201 break; 202 case NetworkChangeNotifier::CONNECTION_ETHERNET: 203 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnEthernet", state_duration); 204 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnEthernet", kilobytes_read); 205 break; 206 case NetworkChangeNotifier::CONNECTION_WIFI: 207 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnWifi", state_duration); 208 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnWifi", kilobytes_read); 209 break; 210 case NetworkChangeNotifier::CONNECTION_2G: 211 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn2G", state_duration); 212 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn2G", kilobytes_read); 213 break; 214 case NetworkChangeNotifier::CONNECTION_3G: 215 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn3G", state_duration); 216 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn3G", kilobytes_read); 217 break; 218 case NetworkChangeNotifier::CONNECTION_4G: 219 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn4G", state_duration); 220 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn4G", kilobytes_read); 221 break; 222 case NetworkChangeNotifier::CONNECTION_NONE: 223 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnNone", state_duration); 224 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnNone", kilobytes_read); 225 break; 226 case NetworkChangeNotifier::CONNECTION_BLUETOOTH: 227 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnBluetooth", state_duration); 228 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnBluetooth", kilobytes_read); 229 break; 230 } 231 232 if (type != NetworkChangeNotifier::CONNECTION_NONE) { 233 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", state_duration); 234 235 if (offline_packets_received_) { 236 if ((now - last_offline_packet_received_) < 237 base::TimeDelta::FromSeconds(5)) { 238 // We can compare this sum with the sum of NCN.OfflineDataRecv. 239 UMA_HISTOGRAM_COUNTS_10000( 240 "NCN.OfflineDataRecvAny5sBeforeOnline", 241 offline_packets_received_); 242 } 243 244 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline", 245 now - last_offline_packet_received_); 246 } 247 } else { 248 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", state_duration); 249 } 250 251 NetworkChangeNotifier::LogOperatorCodeHistogram(type); 252 253 UMA_HISTOGRAM_MEDIUM_TIMES( 254 "NCN.IPAddressChangeToConnectionTypeChange", 255 now - last_ip_address_change_); 256 257 offline_packets_received_ = 0; 258 bytes_read_since_last_connection_change_ = 0; 259 peak_kbps_since_last_connection_change_ = 0; 260 last_connection_type_ = type; 261 polling_interval_ = base::TimeDelta::FromSeconds(1); 262 } 263 264 // NetworkChangeNotifier::DNSObserver implementation. 265 virtual void OnDNSChanged() OVERRIDE { 266 DCHECK(thread_checker_.CalledOnValidThread()); 267 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange", 268 SinceLast(&last_dns_change_)); 269 } 270 271 // NetworkChangeNotifier::NetworkChangeObserver implementation. 272 virtual void OnNetworkChanged( 273 NetworkChangeNotifier::ConnectionType type) OVERRIDE { 274 DCHECK(thread_checker_.CalledOnValidThread()); 275 if (type != NetworkChangeNotifier::CONNECTION_NONE) { 276 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange", 277 SinceLast(&last_network_change_)); 278 } else { 279 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange", 280 SinceLast(&last_network_change_)); 281 } 282 } 283 284 // Record histogram data whenever we receive a packet. Should only be called 285 // from the network thread. 286 void NotifyDataReceived(const URLRequest& request, int bytes_read) { 287 DCHECK(thread_checker_.CalledOnValidThread()); 288 if (IsLocalhost(request.url().host()) || 289 !request.url().SchemeIsHTTPOrHTTPS()) { 290 return; 291 } 292 293 base::TimeTicks now = base::TimeTicks::Now(); 294 base::TimeDelta request_duration = now - request.creation_time(); 295 if (bytes_read_since_last_connection_change_ == 0) { 296 first_byte_after_connection_change_ = now - last_connection_change_; 297 fastest_RTT_since_last_connection_change_ = request_duration; 298 } 299 bytes_read_since_last_connection_change_ += bytes_read; 300 if (request_duration < fastest_RTT_since_last_connection_change_) 301 fastest_RTT_since_last_connection_change_ = request_duration; 302 // Ignore tiny transfers which will not produce accurate rates. 303 // Ignore zero duration transfers which might cause divide by zero. 304 if (bytes_read > 10000 && 305 request_duration > base::TimeDelta::FromMilliseconds(1) && 306 request.creation_time() > last_connection_change_) { 307 int32 kbps = bytes_read * 8 / request_duration.InMilliseconds(); 308 if (kbps > peak_kbps_since_last_connection_change_) 309 peak_kbps_since_last_connection_change_ = kbps; 310 } 311 312 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE) 313 return; 314 315 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv", 316 now - last_connection_change_); 317 offline_packets_received_++; 318 last_offline_packet_received_ = now; 319 320 if ((now - last_polled_connection_) > polling_interval_) { 321 polling_interval_ *= 2; 322 last_polled_connection_ = now; 323 last_polled_connection_type_ = 324 NetworkChangeNotifier::GetConnectionType(); 325 } 326 if (last_polled_connection_type_ == 327 NetworkChangeNotifier::CONNECTION_NONE) { 328 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.PollingOfflineDataRecv", 329 now - last_connection_change_); 330 } 331 } 332 333 private: 334 static base::TimeDelta SinceLast(base::TimeTicks *last_time) { 335 base::TimeTicks current_time = base::TimeTicks::Now(); 336 base::TimeDelta delta = current_time - *last_time; 337 *last_time = current_time; 338 return delta; 339 } 340 341 base::TimeTicks last_ip_address_change_; 342 base::TimeTicks last_connection_change_; 343 base::TimeTicks last_dns_change_; 344 base::TimeTicks last_network_change_; 345 base::TimeTicks last_offline_packet_received_; 346 base::TimeTicks last_polled_connection_; 347 // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our 348 // first transition to offline and on subsequent transitions. Once offline, 349 // |polling_interval_| doubles as offline data is received and we poll 350 // with |NetworkChangeNotifier::GetConnectionType| to verify the connection 351 // state. 352 base::TimeDelta polling_interval_; 353 // |last_connection_type_| is the last value passed to 354 // |OnConnectionTypeChanged|. 355 NetworkChangeNotifier::ConnectionType last_connection_type_; 356 // |last_polled_connection_type_| is last result from calling 357 // |NetworkChangeNotifier::GetConnectionType| in |NotifyDataReceived|. 358 NetworkChangeNotifier::ConnectionType last_polled_connection_type_; 359 // Count of how many times NotifyDataReceived() has been called while the 360 // NetworkChangeNotifier thought network connection was offline. 361 int32 offline_packets_received_; 362 // Number of bytes of network data received since last connectivity change. 363 int32 bytes_read_since_last_connection_change_; 364 // Fastest round-trip-time (RTT) since last connectivity change. RTT measured 365 // from URLRequest creation until first byte received. 366 base::TimeDelta fastest_RTT_since_last_connection_change_; 367 // Time between connectivity change and first network data byte received. 368 base::TimeDelta first_byte_after_connection_change_; 369 // Rough measurement of peak KB/s witnessed since last connectivity change. 370 // The accuracy is decreased by ignoring these factors: 371 // 1) Multiple URLRequests can occur concurrently. 372 // 2) NotifyDataReceived() may be called repeatedly for one URLRequest. 373 // 3) The transfer time includes at least one RTT while no bytes are read. 374 // Erring on the conservative side is hopefully offset by taking the maximum. 375 int32 peak_kbps_since_last_connection_change_; 376 377 base::ThreadChecker thread_checker_; 378 379 DISALLOW_COPY_AND_ASSIGN(HistogramWatcher); 380 }; 381 382 // NetworkState is thread safe. 383 class NetworkChangeNotifier::NetworkState { 384 public: 385 NetworkState() {} 386 ~NetworkState() {} 387 388 void GetDnsConfig(DnsConfig* config) const { 389 base::AutoLock lock(lock_); 390 *config = dns_config_; 391 } 392 393 void SetDnsConfig(const DnsConfig& dns_config) { 394 base::AutoLock lock(lock_); 395 dns_config_ = dns_config; 396 } 397 398 private: 399 mutable base::Lock lock_; 400 DnsConfig dns_config_; 401 }; 402 403 NetworkChangeNotifier::NetworkChangeCalculatorParams:: 404 NetworkChangeCalculatorParams() { 405 } 406 407 // Calculates NetworkChange signal from IPAddress and ConnectionType signals. 408 class NetworkChangeNotifier::NetworkChangeCalculator 409 : public ConnectionTypeObserver, 410 public IPAddressObserver { 411 public: 412 NetworkChangeCalculator(const NetworkChangeCalculatorParams& params) 413 : params_(params), 414 have_announced_(false), 415 last_announced_connection_type_(CONNECTION_NONE), 416 pending_connection_type_(CONNECTION_NONE) {} 417 418 void Init() { 419 DCHECK(thread_checker_.CalledOnValidThread()); 420 DCHECK(g_network_change_notifier); 421 AddConnectionTypeObserver(this); 422 AddIPAddressObserver(this); 423 } 424 425 virtual ~NetworkChangeCalculator() { 426 DCHECK(thread_checker_.CalledOnValidThread()); 427 DCHECK(g_network_change_notifier); 428 RemoveConnectionTypeObserver(this); 429 RemoveIPAddressObserver(this); 430 } 431 432 // NetworkChangeNotifier::IPAddressObserver implementation. 433 virtual void OnIPAddressChanged() OVERRIDE { 434 DCHECK(thread_checker_.CalledOnValidThread()); 435 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE 436 ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_; 437 // Cancels any previous timer. 438 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify); 439 } 440 441 // NetworkChangeNotifier::ConnectionTypeObserver implementation. 442 virtual void OnConnectionTypeChanged(ConnectionType type) OVERRIDE { 443 DCHECK(thread_checker_.CalledOnValidThread()); 444 pending_connection_type_ = type; 445 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE 446 ? params_.connection_type_offline_delay_ 447 : params_.connection_type_online_delay_; 448 // Cancels any previous timer. 449 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify); 450 } 451 452 private: 453 void Notify() { 454 DCHECK(thread_checker_.CalledOnValidThread()); 455 // Don't bother signaling about dead connections. 456 if (have_announced_ && 457 (last_announced_connection_type_ == CONNECTION_NONE) && 458 (pending_connection_type_ == CONNECTION_NONE)) { 459 return; 460 } 461 have_announced_ = true; 462 last_announced_connection_type_ = pending_connection_type_; 463 // Immediately before sending out an online signal, send out an offline 464 // signal to perform any destructive actions before constructive actions. 465 if (pending_connection_type_ != CONNECTION_NONE) 466 NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE); 467 NetworkChangeNotifier::NotifyObserversOfNetworkChange( 468 pending_connection_type_); 469 } 470 471 const NetworkChangeCalculatorParams params_; 472 473 // Indicates if NotifyObserversOfNetworkChange has been called yet. 474 bool have_announced_; 475 // Last value passed to NotifyObserversOfNetworkChange. 476 ConnectionType last_announced_connection_type_; 477 // Value to pass to NotifyObserversOfNetworkChange when Notify is called. 478 ConnectionType pending_connection_type_; 479 // Used to delay notifications so duplicates can be combined. 480 base::OneShotTimer<NetworkChangeCalculator> timer_; 481 482 base::ThreadChecker thread_checker_; 483 484 DISALLOW_COPY_AND_ASSIGN(NetworkChangeCalculator); 485 }; 486 487 NetworkChangeNotifier::~NetworkChangeNotifier() { 488 network_change_calculator_.reset(); 489 DCHECK_EQ(this, g_network_change_notifier); 490 g_network_change_notifier = NULL; 491 } 492 493 // static 494 void NetworkChangeNotifier::SetFactory( 495 NetworkChangeNotifierFactory* factory) { 496 CHECK(!g_network_change_notifier_factory); 497 g_network_change_notifier_factory = factory; 498 } 499 500 // static 501 NetworkChangeNotifier* NetworkChangeNotifier::Create() { 502 if (g_network_change_notifier_factory) 503 return g_network_change_notifier_factory->CreateInstance(); 504 505 #if defined(OS_WIN) 506 NetworkChangeNotifierWin* network_change_notifier = 507 new NetworkChangeNotifierWin(); 508 network_change_notifier->WatchForAddressChange(); 509 return network_change_notifier; 510 #elif defined(OS_CHROMEOS) || defined(OS_ANDROID) 511 // ChromeOS and Android builds MUST use their own class factory. 512 #if !defined(OS_CHROMEOS) 513 // TODO(oshima): ash_shell do not have access to chromeos'es 514 // notifier yet. Re-enable this when chromeos'es notifier moved to 515 // chromeos root directory. crbug.com/119298. 516 CHECK(false); 517 #endif 518 return NULL; 519 #elif defined(OS_LINUX) 520 return NetworkChangeNotifierLinux::Create(); 521 #elif defined(OS_MACOSX) 522 return new NetworkChangeNotifierMac(); 523 #else 524 NOTIMPLEMENTED(); 525 return NULL; 526 #endif 527 } 528 529 // static 530 NetworkChangeNotifier::ConnectionType 531 NetworkChangeNotifier::GetConnectionType() { 532 return g_network_change_notifier ? 533 g_network_change_notifier->GetCurrentConnectionType() : 534 CONNECTION_UNKNOWN; 535 } 536 537 // static 538 void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) { 539 if (!g_network_change_notifier) { 540 *config = DnsConfig(); 541 } else { 542 g_network_change_notifier->network_state_->GetDnsConfig(config); 543 } 544 } 545 546 // static 547 const char* NetworkChangeNotifier::ConnectionTypeToString( 548 ConnectionType type) { 549 static const char* kConnectionTypeNames[] = { 550 "CONNECTION_UNKNOWN", 551 "CONNECTION_ETHERNET", 552 "CONNECTION_WIFI", 553 "CONNECTION_2G", 554 "CONNECTION_3G", 555 "CONNECTION_4G", 556 "CONNECTION_NONE", 557 "CONNECTION_BLUETOOTH" 558 }; 559 COMPILE_ASSERT( 560 arraysize(kConnectionTypeNames) == 561 NetworkChangeNotifier::CONNECTION_LAST + 1, 562 ConnectionType_name_count_mismatch); 563 if (type < CONNECTION_UNKNOWN || type > CONNECTION_LAST) { 564 NOTREACHED(); 565 return "CONNECTION_INVALID"; 566 } 567 return kConnectionTypeNames[type]; 568 } 569 570 // static 571 void NetworkChangeNotifier::NotifyDataReceived(const URLRequest& request, 572 int bytes_read) { 573 if (!g_network_change_notifier || 574 !g_network_change_notifier->histogram_watcher_) { 575 return; 576 } 577 g_network_change_notifier->histogram_watcher_->NotifyDataReceived(request, 578 bytes_read); 579 } 580 581 // static 582 void NetworkChangeNotifier::InitHistogramWatcher() { 583 if (!g_network_change_notifier) 584 return; 585 g_network_change_notifier->histogram_watcher_.reset(new HistogramWatcher()); 586 g_network_change_notifier->histogram_watcher_->Init(); 587 } 588 589 // static 590 void NetworkChangeNotifier::ShutdownHistogramWatcher() { 591 if (!g_network_change_notifier) 592 return; 593 g_network_change_notifier->histogram_watcher_.reset(); 594 } 595 596 // static 597 void NetworkChangeNotifier::LogOperatorCodeHistogram(ConnectionType type) { 598 #if defined(OS_ANDROID) 599 // On a connection type change to 2/3/4G, log the network operator MCC/MNC. 600 // Log zero in other cases. 601 unsigned mcc_mnc = 0; 602 if (type == NetworkChangeNotifier::CONNECTION_2G || 603 type == NetworkChangeNotifier::CONNECTION_3G || 604 type == NetworkChangeNotifier::CONNECTION_4G) { 605 // Log zero if not perfectly converted. 606 if (!base::StringToUint( 607 net::android::GetTelephonyNetworkOperator(), &mcc_mnc)) { 608 mcc_mnc = 0; 609 } 610 } 611 UMA_HISTOGRAM_SPARSE_SLOWLY("NCN.NetworkOperatorMCCMNC", mcc_mnc); 612 #endif 613 } 614 615 #if defined(OS_LINUX) 616 // static 617 const internal::AddressTrackerLinux* 618 NetworkChangeNotifier::GetAddressTracker() { 619 return g_network_change_notifier ? 620 g_network_change_notifier->GetAddressTrackerInternal() : NULL; 621 } 622 #endif 623 624 // static 625 bool NetworkChangeNotifier::IsOffline() { 626 return GetConnectionType() == CONNECTION_NONE; 627 } 628 629 // static 630 bool NetworkChangeNotifier::IsConnectionCellular(ConnectionType type) { 631 bool is_cellular = false; 632 switch (type) { 633 case CONNECTION_2G: 634 case CONNECTION_3G: 635 case CONNECTION_4G: 636 is_cellular = true; 637 break; 638 case CONNECTION_UNKNOWN: 639 case CONNECTION_ETHERNET: 640 case CONNECTION_WIFI: 641 case CONNECTION_NONE: 642 case CONNECTION_BLUETOOTH: 643 is_cellular = false; 644 break; 645 } 646 return is_cellular; 647 } 648 649 // static 650 NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() { 651 return new MockNetworkChangeNotifier(); 652 } 653 654 void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) { 655 if (g_network_change_notifier) 656 g_network_change_notifier->ip_address_observer_list_->AddObserver(observer); 657 } 658 659 void NetworkChangeNotifier::AddConnectionTypeObserver( 660 ConnectionTypeObserver* observer) { 661 if (g_network_change_notifier) { 662 g_network_change_notifier->connection_type_observer_list_->AddObserver( 663 observer); 664 } 665 } 666 667 void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) { 668 if (g_network_change_notifier) { 669 g_network_change_notifier->resolver_state_observer_list_->AddObserver( 670 observer); 671 } 672 } 673 674 void NetworkChangeNotifier::AddNetworkChangeObserver( 675 NetworkChangeObserver* observer) { 676 if (g_network_change_notifier) { 677 g_network_change_notifier->network_change_observer_list_->AddObserver( 678 observer); 679 } 680 } 681 682 void NetworkChangeNotifier::RemoveIPAddressObserver( 683 IPAddressObserver* observer) { 684 if (g_network_change_notifier) { 685 g_network_change_notifier->ip_address_observer_list_->RemoveObserver( 686 observer); 687 } 688 } 689 690 void NetworkChangeNotifier::RemoveConnectionTypeObserver( 691 ConnectionTypeObserver* observer) { 692 if (g_network_change_notifier) { 693 g_network_change_notifier->connection_type_observer_list_->RemoveObserver( 694 observer); 695 } 696 } 697 698 void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) { 699 if (g_network_change_notifier) { 700 g_network_change_notifier->resolver_state_observer_list_->RemoveObserver( 701 observer); 702 } 703 } 704 705 void NetworkChangeNotifier::RemoveNetworkChangeObserver( 706 NetworkChangeObserver* observer) { 707 if (g_network_change_notifier) { 708 g_network_change_notifier->network_change_observer_list_->RemoveObserver( 709 observer); 710 } 711 } 712 713 // static 714 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() { 715 if (g_network_change_notifier) 716 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl(); 717 } 718 719 // static 720 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests( 721 ConnectionType type) { 722 if (g_network_change_notifier) 723 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(type); 724 } 725 726 // static 727 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( 728 ConnectionType type) { 729 if (g_network_change_notifier) 730 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type); 731 } 732 733 // static 734 void NetworkChangeNotifier::SetTestNotificationsOnly(bool test_only) { 735 if (g_network_change_notifier) 736 g_network_change_notifier->test_notifications_only_ = test_only; 737 } 738 739 NetworkChangeNotifier::NetworkChangeNotifier( 740 const NetworkChangeCalculatorParams& params 741 /*= NetworkChangeCalculatorParams()*/) 742 : ip_address_observer_list_( 743 new ObserverListThreadSafe<IPAddressObserver>( 744 ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)), 745 connection_type_observer_list_( 746 new ObserverListThreadSafe<ConnectionTypeObserver>( 747 ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)), 748 resolver_state_observer_list_( 749 new ObserverListThreadSafe<DNSObserver>( 750 ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)), 751 network_change_observer_list_( 752 new ObserverListThreadSafe<NetworkChangeObserver>( 753 ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)), 754 network_state_(new NetworkState()), 755 network_change_calculator_(new NetworkChangeCalculator(params)), 756 test_notifications_only_(false) { 757 DCHECK(!g_network_change_notifier); 758 g_network_change_notifier = this; 759 network_change_calculator_->Init(); 760 } 761 762 #if defined(OS_LINUX) 763 const internal::AddressTrackerLinux* 764 NetworkChangeNotifier::GetAddressTrackerInternal() const { 765 return NULL; 766 } 767 #endif 768 769 // static 770 void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() { 771 if (g_network_change_notifier && 772 !g_network_change_notifier->test_notifications_only_) { 773 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl(); 774 } 775 } 776 777 // static 778 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() { 779 if (g_network_change_notifier && 780 !g_network_change_notifier->test_notifications_only_) { 781 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl( 782 GetConnectionType()); 783 } 784 } 785 786 // static 787 void NetworkChangeNotifier::NotifyObserversOfNetworkChange( 788 ConnectionType type) { 789 if (g_network_change_notifier && 790 !g_network_change_notifier->test_notifications_only_) { 791 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type); 792 } 793 } 794 795 // static 796 void NetworkChangeNotifier::NotifyObserversOfDNSChange() { 797 if (g_network_change_notifier && 798 !g_network_change_notifier->test_notifications_only_) { 799 g_network_change_notifier->NotifyObserversOfDNSChangeImpl(); 800 } 801 } 802 803 // static 804 void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) { 805 if (!g_network_change_notifier) 806 return; 807 g_network_change_notifier->network_state_->SetDnsConfig(config); 808 NotifyObserversOfDNSChange(); 809 } 810 811 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() { 812 ip_address_observer_list_->Notify(&IPAddressObserver::OnIPAddressChanged); 813 } 814 815 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl( 816 ConnectionType type) { 817 connection_type_observer_list_->Notify( 818 &ConnectionTypeObserver::OnConnectionTypeChanged, type); 819 } 820 821 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl( 822 ConnectionType type) { 823 network_change_observer_list_->Notify( 824 &NetworkChangeObserver::OnNetworkChanged, type); 825 } 826 827 void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() { 828 resolver_state_observer_list_->Notify(&DNSObserver::OnDNSChanged); 829 } 830 831 NetworkChangeNotifier::DisableForTest::DisableForTest() 832 : network_change_notifier_(g_network_change_notifier) { 833 DCHECK(g_network_change_notifier); 834 g_network_change_notifier = NULL; 835 } 836 837 NetworkChangeNotifier::DisableForTest::~DisableForTest() { 838 DCHECK(!g_network_change_notifier); 839 g_network_change_notifier = network_change_notifier_; 840 } 841 842 } // namespace net 843