Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / net / base / network_change_notifier.cc
blob03502f6dbfd6a21daef19127e08348013198660d
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.
5 #include "net/base/network_change_notifier.h"
7 #include <limits>
9 #include "base/metrics/histogram_macros.h"
10 #include "base/strings/string_util.h"
11 #include "base/synchronization/lock.h"
12 #include "base/threading/thread_checker.h"
13 #include "build/build_config.h"
14 #include "net/base/net_util.h"
15 #include "net/base/network_change_notifier_factory.h"
16 #include "net/base/network_interfaces.h"
17 #include "net/dns/dns_config_service.h"
18 #include "net/url_request/url_request.h"
19 #include "url/gurl.h"
21 #if defined(OS_ANDROID)
22 #include "base/metrics/sparse_histogram.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "net/android/network_library.h"
25 #endif
27 #if defined(OS_WIN)
28 #include "net/base/network_change_notifier_win.h"
29 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
30 #include "net/base/network_change_notifier_linux.h"
31 #elif defined(OS_MACOSX)
32 #include "net/base/network_change_notifier_mac.h"
33 #endif
35 namespace net {
37 namespace {
39 // The actual singleton notifier. The class contract forbids usage of the API
40 // in ways that would require us to place locks around access to this object.
41 // (The prohibition on global non-POD objects makes it tricky to do such a thing
42 // anyway.)
43 NetworkChangeNotifier* g_network_change_notifier = NULL;
45 // Class factory singleton.
46 NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL;
48 class MockNetworkChangeNotifier : public NetworkChangeNotifier {
49 public:
50 ConnectionType GetCurrentConnectionType() const override {
51 return CONNECTION_UNKNOWN;
55 } // namespace
57 // static
58 bool NetworkChangeNotifier::test_notifications_only_ = false;
60 // The main observer class that records UMAs for network events.
61 class HistogramWatcher
62 : public NetworkChangeNotifier::ConnectionTypeObserver,
63 public NetworkChangeNotifier::IPAddressObserver,
64 public NetworkChangeNotifier::DNSObserver,
65 public NetworkChangeNotifier::NetworkChangeObserver {
66 public:
67 HistogramWatcher()
68 : last_ip_address_change_(base::TimeTicks::Now()),
69 last_connection_change_(base::TimeTicks::Now()),
70 last_dns_change_(base::TimeTicks::Now()),
71 last_network_change_(base::TimeTicks::Now()),
72 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
73 offline_packets_received_(0),
74 bytes_read_since_last_connection_change_(0),
75 peak_kbps_since_last_connection_change_(0) {}
77 // Registers our three Observer implementations. This is called from the
78 // network thread so that our Observer implementations are also called
79 // from the network thread. This avoids multi-threaded race conditions
80 // because the only other interface, |NotifyDataReceived| is also
81 // only called from the network thread.
82 void Init() {
83 DCHECK(thread_checker_.CalledOnValidThread());
84 DCHECK(g_network_change_notifier);
85 NetworkChangeNotifier::AddConnectionTypeObserver(this);
86 NetworkChangeNotifier::AddIPAddressObserver(this);
87 NetworkChangeNotifier::AddDNSObserver(this);
88 NetworkChangeNotifier::AddNetworkChangeObserver(this);
91 ~HistogramWatcher() override {
92 DCHECK(thread_checker_.CalledOnValidThread());
93 DCHECK(g_network_change_notifier);
94 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
95 NetworkChangeNotifier::RemoveIPAddressObserver(this);
96 NetworkChangeNotifier::RemoveDNSObserver(this);
97 NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
100 // NetworkChangeNotifier::IPAddressObserver implementation.
101 void OnIPAddressChanged() override {
102 DCHECK(thread_checker_.CalledOnValidThread());
103 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
104 SinceLast(&last_ip_address_change_));
105 UMA_HISTOGRAM_MEDIUM_TIMES(
106 "NCN.ConnectionTypeChangeToIPAddressChange",
107 last_ip_address_change_ - last_connection_change_);
110 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
111 void OnConnectionTypeChanged(
112 NetworkChangeNotifier::ConnectionType type) override {
113 DCHECK(thread_checker_.CalledOnValidThread());
114 base::TimeTicks now = base::TimeTicks::Now();
115 int32_t kilobytes_read = bytes_read_since_last_connection_change_ / 1000;
116 base::TimeDelta state_duration = SinceLast(&last_connection_change_);
117 if (bytes_read_since_last_connection_change_) {
118 switch (last_connection_type_) {
119 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
120 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnUnknown",
121 first_byte_after_connection_change_);
122 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnUnknown",
123 fastest_RTT_since_last_connection_change_);
124 break;
125 case NetworkChangeNotifier::CONNECTION_ETHERNET:
126 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnEthernet",
127 first_byte_after_connection_change_);
128 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnEthernet",
129 fastest_RTT_since_last_connection_change_);
130 break;
131 case NetworkChangeNotifier::CONNECTION_WIFI:
132 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnWifi",
133 first_byte_after_connection_change_);
134 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnWifi",
135 fastest_RTT_since_last_connection_change_);
136 break;
137 case NetworkChangeNotifier::CONNECTION_2G:
138 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn2G",
139 first_byte_after_connection_change_);
140 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn2G",
141 fastest_RTT_since_last_connection_change_);
142 break;
143 case NetworkChangeNotifier::CONNECTION_3G:
144 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn3G",
145 first_byte_after_connection_change_);
146 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn3G",
147 fastest_RTT_since_last_connection_change_);
148 break;
149 case NetworkChangeNotifier::CONNECTION_4G:
150 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn4G",
151 first_byte_after_connection_change_);
152 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn4G",
153 fastest_RTT_since_last_connection_change_);
154 break;
155 case NetworkChangeNotifier::CONNECTION_NONE:
156 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnNone",
157 first_byte_after_connection_change_);
158 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnNone",
159 fastest_RTT_since_last_connection_change_);
160 break;
161 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
162 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnBluetooth",
163 first_byte_after_connection_change_);
164 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnBluetooth",
165 fastest_RTT_since_last_connection_change_);
168 if (peak_kbps_since_last_connection_change_) {
169 switch (last_connection_type_) {
170 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
171 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnUnknown",
172 peak_kbps_since_last_connection_change_);
173 break;
174 case NetworkChangeNotifier::CONNECTION_ETHERNET:
175 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnEthernet",
176 peak_kbps_since_last_connection_change_);
177 break;
178 case NetworkChangeNotifier::CONNECTION_WIFI:
179 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnWifi",
180 peak_kbps_since_last_connection_change_);
181 break;
182 case NetworkChangeNotifier::CONNECTION_2G:
183 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn2G",
184 peak_kbps_since_last_connection_change_);
185 break;
186 case NetworkChangeNotifier::CONNECTION_3G:
187 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn3G",
188 peak_kbps_since_last_connection_change_);
189 break;
190 case NetworkChangeNotifier::CONNECTION_4G:
191 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn4G",
192 peak_kbps_since_last_connection_change_);
193 break;
194 case NetworkChangeNotifier::CONNECTION_NONE:
195 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnNone",
196 peak_kbps_since_last_connection_change_);
197 break;
198 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
199 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnBluetooth",
200 peak_kbps_since_last_connection_change_);
201 break;
204 switch (last_connection_type_) {
205 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
206 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnUnknown", state_duration);
207 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnUnknown", kilobytes_read);
208 break;
209 case NetworkChangeNotifier::CONNECTION_ETHERNET:
210 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnEthernet", state_duration);
211 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnEthernet", kilobytes_read);
212 break;
213 case NetworkChangeNotifier::CONNECTION_WIFI:
214 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnWifi", state_duration);
215 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnWifi", kilobytes_read);
216 break;
217 case NetworkChangeNotifier::CONNECTION_2G:
218 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn2G", state_duration);
219 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn2G", kilobytes_read);
220 break;
221 case NetworkChangeNotifier::CONNECTION_3G:
222 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn3G", state_duration);
223 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn3G", kilobytes_read);
224 break;
225 case NetworkChangeNotifier::CONNECTION_4G:
226 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn4G", state_duration);
227 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn4G", kilobytes_read);
228 break;
229 case NetworkChangeNotifier::CONNECTION_NONE:
230 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnNone", state_duration);
231 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnNone", kilobytes_read);
232 break;
233 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
234 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnBluetooth", state_duration);
235 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnBluetooth", kilobytes_read);
236 break;
239 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
240 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", state_duration);
242 if (offline_packets_received_) {
243 if ((now - last_offline_packet_received_) <
244 base::TimeDelta::FromSeconds(5)) {
245 // We can compare this sum with the sum of NCN.OfflineDataRecv.
246 UMA_HISTOGRAM_COUNTS_10000(
247 "NCN.OfflineDataRecvAny5sBeforeOnline",
248 offline_packets_received_);
251 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline",
252 now - last_offline_packet_received_);
254 } else {
255 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", state_duration);
258 NetworkChangeNotifier::LogOperatorCodeHistogram(type);
260 UMA_HISTOGRAM_MEDIUM_TIMES(
261 "NCN.IPAddressChangeToConnectionTypeChange",
262 now - last_ip_address_change_);
264 offline_packets_received_ = 0;
265 bytes_read_since_last_connection_change_ = 0;
266 peak_kbps_since_last_connection_change_ = 0;
267 last_connection_type_ = type;
268 polling_interval_ = base::TimeDelta::FromSeconds(1);
271 // NetworkChangeNotifier::DNSObserver implementation.
272 void OnDNSChanged() override {
273 DCHECK(thread_checker_.CalledOnValidThread());
274 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange",
275 SinceLast(&last_dns_change_));
278 // NetworkChangeNotifier::NetworkChangeObserver implementation.
279 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
280 DCHECK(thread_checker_.CalledOnValidThread());
281 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
282 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange",
283 SinceLast(&last_network_change_));
284 } else {
285 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange",
286 SinceLast(&last_network_change_));
290 // Record histogram data whenever we receive a packet. Should only be called
291 // from the network thread.
292 void NotifyDataReceived(const URLRequest& request, int bytes_read) {
293 DCHECK(thread_checker_.CalledOnValidThread());
294 if (IsLocalhost(request.url().host()) ||
295 !request.url().SchemeIsHTTPOrHTTPS()) {
296 return;
299 base::TimeTicks now = base::TimeTicks::Now();
300 base::TimeDelta request_duration = now - request.creation_time();
301 if (bytes_read_since_last_connection_change_ == 0) {
302 first_byte_after_connection_change_ = now - last_connection_change_;
303 fastest_RTT_since_last_connection_change_ = request_duration;
305 bytes_read_since_last_connection_change_ += bytes_read;
306 if (request_duration < fastest_RTT_since_last_connection_change_)
307 fastest_RTT_since_last_connection_change_ = request_duration;
308 // Ignore tiny transfers which will not produce accurate rates.
309 // Ignore zero duration transfers which might cause divide by zero.
310 if (bytes_read > 10000 &&
311 request_duration > base::TimeDelta::FromMilliseconds(1) &&
312 request.creation_time() > last_connection_change_) {
313 int32_t kbps = static_cast<int32_t>(bytes_read * 8 /
314 request_duration.InMilliseconds());
315 if (kbps > peak_kbps_since_last_connection_change_)
316 peak_kbps_since_last_connection_change_ = kbps;
319 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE)
320 return;
322 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv",
323 now - last_connection_change_);
324 offline_packets_received_++;
325 last_offline_packet_received_ = now;
327 if ((now - last_polled_connection_) > polling_interval_) {
328 polling_interval_ *= 2;
329 last_polled_connection_ = now;
330 last_polled_connection_type_ =
331 NetworkChangeNotifier::GetConnectionType();
333 if (last_polled_connection_type_ ==
334 NetworkChangeNotifier::CONNECTION_NONE) {
335 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.PollingOfflineDataRecv",
336 now - last_connection_change_);
340 private:
341 static base::TimeDelta SinceLast(base::TimeTicks *last_time) {
342 base::TimeTicks current_time = base::TimeTicks::Now();
343 base::TimeDelta delta = current_time - *last_time;
344 *last_time = current_time;
345 return delta;
348 base::TimeTicks last_ip_address_change_;
349 base::TimeTicks last_connection_change_;
350 base::TimeTicks last_dns_change_;
351 base::TimeTicks last_network_change_;
352 base::TimeTicks last_offline_packet_received_;
353 base::TimeTicks last_polled_connection_;
354 // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our
355 // first transition to offline and on subsequent transitions. Once offline,
356 // |polling_interval_| doubles as offline data is received and we poll
357 // with |NetworkChangeNotifier::GetConnectionType| to verify the connection
358 // state.
359 base::TimeDelta polling_interval_;
360 // |last_connection_type_| is the last value passed to
361 // |OnConnectionTypeChanged|.
362 NetworkChangeNotifier::ConnectionType last_connection_type_;
363 // |last_polled_connection_type_| is last result from calling
364 // |NetworkChangeNotifier::GetConnectionType| in |NotifyDataReceived|.
365 NetworkChangeNotifier::ConnectionType last_polled_connection_type_;
366 // Count of how many times NotifyDataReceived() has been called while the
367 // NetworkChangeNotifier thought network connection was offline.
368 int32_t offline_packets_received_;
369 // Number of bytes of network data received since last connectivity change.
370 int32_t bytes_read_since_last_connection_change_;
371 // Fastest round-trip-time (RTT) since last connectivity change. RTT measured
372 // from URLRequest creation until first byte received.
373 base::TimeDelta fastest_RTT_since_last_connection_change_;
374 // Time between connectivity change and first network data byte received.
375 base::TimeDelta first_byte_after_connection_change_;
376 // Rough measurement of peak KB/s witnessed since last connectivity change.
377 // The accuracy is decreased by ignoring these factors:
378 // 1) Multiple URLRequests can occur concurrently.
379 // 2) NotifyDataReceived() may be called repeatedly for one URLRequest.
380 // 3) The transfer time includes at least one RTT while no bytes are read.
381 // Erring on the conservative side is hopefully offset by taking the maximum.
382 int32_t peak_kbps_since_last_connection_change_;
384 base::ThreadChecker thread_checker_;
386 DISALLOW_COPY_AND_ASSIGN(HistogramWatcher);
389 // NetworkState is thread safe.
390 class NetworkChangeNotifier::NetworkState {
391 public:
392 NetworkState() {}
393 ~NetworkState() {}
395 void GetDnsConfig(DnsConfig* config) const {
396 base::AutoLock lock(lock_);
397 *config = dns_config_;
400 void SetDnsConfig(const DnsConfig& dns_config) {
401 base::AutoLock lock(lock_);
402 dns_config_ = dns_config;
405 private:
406 mutable base::Lock lock_;
407 DnsConfig dns_config_;
410 NetworkChangeNotifier::NetworkChangeCalculatorParams::
411 NetworkChangeCalculatorParams() {
414 // Calculates NetworkChange signal from IPAddress and ConnectionType signals.
415 class NetworkChangeNotifier::NetworkChangeCalculator
416 : public ConnectionTypeObserver,
417 public IPAddressObserver {
418 public:
419 NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
420 : params_(params),
421 have_announced_(false),
422 last_announced_connection_type_(CONNECTION_NONE),
423 pending_connection_type_(CONNECTION_NONE) {}
425 void Init() {
426 DCHECK(thread_checker_.CalledOnValidThread());
427 DCHECK(g_network_change_notifier);
428 AddConnectionTypeObserver(this);
429 AddIPAddressObserver(this);
432 ~NetworkChangeCalculator() override {
433 DCHECK(thread_checker_.CalledOnValidThread());
434 DCHECK(g_network_change_notifier);
435 RemoveConnectionTypeObserver(this);
436 RemoveIPAddressObserver(this);
439 // NetworkChangeNotifier::IPAddressObserver implementation.
440 void OnIPAddressChanged() override {
441 DCHECK(thread_checker_.CalledOnValidThread());
442 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
443 ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_;
444 // Cancels any previous timer.
445 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
448 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
449 void OnConnectionTypeChanged(ConnectionType type) override {
450 DCHECK(thread_checker_.CalledOnValidThread());
451 pending_connection_type_ = type;
452 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
453 ? params_.connection_type_offline_delay_
454 : params_.connection_type_online_delay_;
455 // Cancels any previous timer.
456 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
459 private:
460 void Notify() {
461 DCHECK(thread_checker_.CalledOnValidThread());
462 // Don't bother signaling about dead connections.
463 if (have_announced_ &&
464 (last_announced_connection_type_ == CONNECTION_NONE) &&
465 (pending_connection_type_ == CONNECTION_NONE)) {
466 return;
468 have_announced_ = true;
469 last_announced_connection_type_ = pending_connection_type_;
470 // Immediately before sending out an online signal, send out an offline
471 // signal to perform any destructive actions before constructive actions.
472 if (pending_connection_type_ != CONNECTION_NONE)
473 NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE);
474 NetworkChangeNotifier::NotifyObserversOfNetworkChange(
475 pending_connection_type_);
478 const NetworkChangeCalculatorParams params_;
480 // Indicates if NotifyObserversOfNetworkChange has been called yet.
481 bool have_announced_;
482 // Last value passed to NotifyObserversOfNetworkChange.
483 ConnectionType last_announced_connection_type_;
484 // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
485 ConnectionType pending_connection_type_;
486 // Used to delay notifications so duplicates can be combined.
487 base::OneShotTimer<NetworkChangeCalculator> timer_;
489 base::ThreadChecker thread_checker_;
491 DISALLOW_COPY_AND_ASSIGN(NetworkChangeCalculator);
494 NetworkChangeNotifier::~NetworkChangeNotifier() {
495 network_change_calculator_.reset();
496 DCHECK_EQ(this, g_network_change_notifier);
497 g_network_change_notifier = NULL;
500 // static
501 void NetworkChangeNotifier::SetFactory(
502 NetworkChangeNotifierFactory* factory) {
503 CHECK(!g_network_change_notifier_factory);
504 g_network_change_notifier_factory = factory;
507 // static
508 NetworkChangeNotifier* NetworkChangeNotifier::Create() {
509 if (g_network_change_notifier_factory)
510 return g_network_change_notifier_factory->CreateInstance();
512 #if defined(OS_WIN)
513 NetworkChangeNotifierWin* network_change_notifier =
514 new NetworkChangeNotifierWin();
515 network_change_notifier->WatchForAddressChange();
516 return network_change_notifier;
517 #elif defined(OS_CHROMEOS) || defined(OS_ANDROID)
518 // ChromeOS and Android builds MUST use their own class factory.
519 #if !defined(OS_CHROMEOS)
520 // TODO(oshima): ash_shell do not have access to chromeos'es
521 // notifier yet. Re-enable this when chromeos'es notifier moved to
522 // chromeos root directory. crbug.com/119298.
523 CHECK(false);
524 #endif
525 return NULL;
526 #elif defined(OS_LINUX)
527 return new NetworkChangeNotifierLinux(base::hash_set<std::string>());
528 #elif defined(OS_MACOSX)
529 return new NetworkChangeNotifierMac();
530 #else
531 NOTIMPLEMENTED();
532 return NULL;
533 #endif
536 // static
537 NetworkChangeNotifier::ConnectionType
538 NetworkChangeNotifier::GetConnectionType() {
539 return g_network_change_notifier ?
540 g_network_change_notifier->GetCurrentConnectionType() :
541 CONNECTION_UNKNOWN;
544 // static
545 double NetworkChangeNotifier::GetMaxBandwidth() {
546 return g_network_change_notifier ?
547 g_network_change_notifier->GetCurrentMaxBandwidth() :
548 std::numeric_limits<double>::infinity();
551 // static
552 void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) {
553 if (!g_network_change_notifier) {
554 *config = DnsConfig();
555 } else {
556 g_network_change_notifier->network_state_->GetDnsConfig(config);
560 // static
561 const char* NetworkChangeNotifier::ConnectionTypeToString(
562 ConnectionType type) {
563 static const char* const kConnectionTypeNames[] = {
564 "CONNECTION_UNKNOWN",
565 "CONNECTION_ETHERNET",
566 "CONNECTION_WIFI",
567 "CONNECTION_2G",
568 "CONNECTION_3G",
569 "CONNECTION_4G",
570 "CONNECTION_NONE",
571 "CONNECTION_BLUETOOTH"
573 static_assert(arraysize(kConnectionTypeNames) ==
574 NetworkChangeNotifier::CONNECTION_LAST + 1,
575 "ConnectionType name count should match");
576 if (type < CONNECTION_UNKNOWN || type > CONNECTION_LAST) {
577 NOTREACHED();
578 return "CONNECTION_INVALID";
580 return kConnectionTypeNames[type];
583 // static
584 void NetworkChangeNotifier::NotifyDataReceived(const URLRequest& request,
585 int bytes_read) {
586 if (!g_network_change_notifier ||
587 !g_network_change_notifier->histogram_watcher_) {
588 return;
590 g_network_change_notifier->histogram_watcher_->NotifyDataReceived(request,
591 bytes_read);
594 // static
595 void NetworkChangeNotifier::InitHistogramWatcher() {
596 if (!g_network_change_notifier)
597 return;
598 g_network_change_notifier->histogram_watcher_.reset(new HistogramWatcher());
599 g_network_change_notifier->histogram_watcher_->Init();
602 // static
603 void NetworkChangeNotifier::ShutdownHistogramWatcher() {
604 if (!g_network_change_notifier)
605 return;
606 g_network_change_notifier->histogram_watcher_.reset();
609 // static
610 void NetworkChangeNotifier::LogOperatorCodeHistogram(ConnectionType type) {
611 #if defined(OS_ANDROID)
612 // On a connection type change to 2/3/4G, log the network operator MCC/MNC.
613 // Log zero in other cases.
614 unsigned mcc_mnc = 0;
615 if (type == NetworkChangeNotifier::CONNECTION_2G ||
616 type == NetworkChangeNotifier::CONNECTION_3G ||
617 type == NetworkChangeNotifier::CONNECTION_4G) {
618 // Log zero if not perfectly converted.
619 if (!base::StringToUint(android::GetTelephonyNetworkOperator(), &mcc_mnc)) {
620 mcc_mnc = 0;
623 UMA_HISTOGRAM_SPARSE_SLOWLY("NCN.NetworkOperatorMCCMNC", mcc_mnc);
624 #endif
627 #if defined(OS_LINUX)
628 // static
629 const internal::AddressTrackerLinux*
630 NetworkChangeNotifier::GetAddressTracker() {
631 return g_network_change_notifier ?
632 g_network_change_notifier->GetAddressTrackerInternal() : NULL;
634 #endif
636 // static
637 bool NetworkChangeNotifier::IsOffline() {
638 return GetConnectionType() == CONNECTION_NONE;
641 // static
642 bool NetworkChangeNotifier::IsConnectionCellular(ConnectionType type) {
643 bool is_cellular = false;
644 switch (type) {
645 case CONNECTION_2G:
646 case CONNECTION_3G:
647 case CONNECTION_4G:
648 is_cellular = true;
649 break;
650 case CONNECTION_UNKNOWN:
651 case CONNECTION_ETHERNET:
652 case CONNECTION_WIFI:
653 case CONNECTION_NONE:
654 case CONNECTION_BLUETOOTH:
655 is_cellular = false;
656 break;
658 return is_cellular;
661 // static
662 NetworkChangeNotifier::ConnectionType
663 NetworkChangeNotifier::ConnectionTypeFromInterfaceList(
664 const NetworkInterfaceList& interfaces) {
665 bool first = true;
666 ConnectionType result = CONNECTION_NONE;
667 for (size_t i = 0; i < interfaces.size(); ++i) {
668 #if defined(OS_WIN)
669 if (interfaces[i].friendly_name == "Teredo Tunneling Pseudo-Interface")
670 continue;
671 #endif
672 // Remove VMware network interfaces as they're internal and should not be
673 // used to determine the network connection type.
674 if (base::ToLowerASCII(interfaces[i].friendly_name).find("vmnet") !=
675 std::string::npos) {
676 continue;
678 if (first) {
679 first = false;
680 result = interfaces[i].type;
681 } else if (result != interfaces[i].type) {
682 return CONNECTION_UNKNOWN;
685 return result;
688 // static
689 NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() {
690 return new MockNetworkChangeNotifier();
693 void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) {
694 if (g_network_change_notifier)
695 g_network_change_notifier->ip_address_observer_list_->AddObserver(observer);
698 void NetworkChangeNotifier::AddConnectionTypeObserver(
699 ConnectionTypeObserver* observer) {
700 if (g_network_change_notifier) {
701 g_network_change_notifier->connection_type_observer_list_->AddObserver(
702 observer);
706 void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) {
707 if (g_network_change_notifier) {
708 g_network_change_notifier->resolver_state_observer_list_->AddObserver(
709 observer);
713 void NetworkChangeNotifier::AddNetworkChangeObserver(
714 NetworkChangeObserver* observer) {
715 if (g_network_change_notifier) {
716 g_network_change_notifier->network_change_observer_list_->AddObserver(
717 observer);
721 void NetworkChangeNotifier::AddMaxBandwidthObserver(
722 MaxBandwidthObserver* observer) {
723 if (g_network_change_notifier) {
724 g_network_change_notifier->max_bandwidth_observer_list_->AddObserver(
725 observer);
729 void NetworkChangeNotifier::RemoveIPAddressObserver(
730 IPAddressObserver* observer) {
731 if (g_network_change_notifier) {
732 g_network_change_notifier->ip_address_observer_list_->RemoveObserver(
733 observer);
737 void NetworkChangeNotifier::RemoveConnectionTypeObserver(
738 ConnectionTypeObserver* observer) {
739 if (g_network_change_notifier) {
740 g_network_change_notifier->connection_type_observer_list_->RemoveObserver(
741 observer);
745 void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) {
746 if (g_network_change_notifier) {
747 g_network_change_notifier->resolver_state_observer_list_->RemoveObserver(
748 observer);
752 void NetworkChangeNotifier::RemoveNetworkChangeObserver(
753 NetworkChangeObserver* observer) {
754 if (g_network_change_notifier) {
755 g_network_change_notifier->network_change_observer_list_->RemoveObserver(
756 observer);
760 void NetworkChangeNotifier::RemoveMaxBandwidthObserver(
761 MaxBandwidthObserver* observer) {
762 if (g_network_change_notifier) {
763 g_network_change_notifier->max_bandwidth_observer_list_->RemoveObserver(
764 observer);
768 // static
769 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() {
770 if (g_network_change_notifier)
771 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
774 // static
775 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
776 ConnectionType type) {
777 if (g_network_change_notifier)
778 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(type);
781 // static
782 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
783 ConnectionType type) {
784 if (g_network_change_notifier)
785 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
788 // static
789 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests() {
790 if (g_network_change_notifier)
791 g_network_change_notifier->NotifyObserversOfInitialDNSConfigReadImpl();
794 // static
795 void NetworkChangeNotifier::SetTestNotificationsOnly(bool test_only) {
796 DCHECK(!g_network_change_notifier);
797 NetworkChangeNotifier::test_notifications_only_ = test_only;
800 NetworkChangeNotifier::NetworkChangeNotifier(
801 const NetworkChangeCalculatorParams& params
802 /*= NetworkChangeCalculatorParams()*/)
803 : ip_address_observer_list_(
804 new base::ObserverListThreadSafe<IPAddressObserver>(
805 base::ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)),
806 connection_type_observer_list_(
807 new base::ObserverListThreadSafe<ConnectionTypeObserver>(
808 base::ObserverListBase<
809 ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)),
810 resolver_state_observer_list_(
811 new base::ObserverListThreadSafe<DNSObserver>(
812 base::ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)),
813 network_change_observer_list_(new base::ObserverListThreadSafe<
814 NetworkChangeObserver>(
815 base::ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)),
816 max_bandwidth_observer_list_(new base::ObserverListThreadSafe<
817 MaxBandwidthObserver>(
818 base::ObserverListBase<MaxBandwidthObserver>::NOTIFY_EXISTING_ONLY)),
819 network_state_(new NetworkState()),
820 network_change_calculator_(new NetworkChangeCalculator(params)) {
821 DCHECK(!g_network_change_notifier);
822 g_network_change_notifier = this;
823 network_change_calculator_->Init();
826 #if defined(OS_LINUX)
827 const internal::AddressTrackerLinux*
828 NetworkChangeNotifier::GetAddressTrackerInternal() const {
829 return NULL;
831 #endif
833 double NetworkChangeNotifier::GetCurrentMaxBandwidth() const {
834 // This default implementation conforms to the NetInfo V3 specification but
835 // should be overridden to provide specific bandwidth data based on the
836 // platform.
837 if (GetCurrentConnectionType() == CONNECTION_NONE)
838 return 0.0;
839 return std::numeric_limits<double>::infinity();
842 // static
843 double NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
844 ConnectionSubtype subtype) {
845 switch (subtype) {
846 case SUBTYPE_GSM:
847 return 0.01;
848 case SUBTYPE_IDEN:
849 return 0.064;
850 case SUBTYPE_CDMA:
851 return 0.115;
852 case SUBTYPE_1XRTT:
853 return 0.153;
854 case SUBTYPE_GPRS:
855 return 0.237;
856 case SUBTYPE_EDGE:
857 return 0.384;
858 case SUBTYPE_UMTS:
859 return 2.0;
860 case SUBTYPE_EVDO_REV_0:
861 return 2.46;
862 case SUBTYPE_EVDO_REV_A:
863 return 3.1;
864 case SUBTYPE_HSPA:
865 return 3.6;
866 case SUBTYPE_EVDO_REV_B:
867 return 14.7;
868 case SUBTYPE_HSDPA:
869 return 14.3;
870 case SUBTYPE_HSUPA:
871 return 14.4;
872 case SUBTYPE_EHRPD:
873 return 21.0;
874 case SUBTYPE_HSPAP:
875 return 42.0;
876 case SUBTYPE_LTE:
877 return 100.0;
878 case SUBTYPE_LTE_ADVANCED:
879 return 100.0;
880 case SUBTYPE_BLUETOOTH_1_2:
881 return 1.0;
882 case SUBTYPE_BLUETOOTH_2_1:
883 return 3.0;
884 case SUBTYPE_BLUETOOTH_3_0:
885 return 24.0;
886 case SUBTYPE_BLUETOOTH_4_0:
887 return 1.0;
888 case SUBTYPE_ETHERNET:
889 return 10.0;
890 case SUBTYPE_FAST_ETHERNET:
891 return 100.0;
892 case SUBTYPE_GIGABIT_ETHERNET:
893 return 1000.0;
894 case SUBTYPE_10_GIGABIT_ETHERNET:
895 return 10000.0;
896 case SUBTYPE_WIFI_B:
897 return 11.0;
898 case SUBTYPE_WIFI_G:
899 return 54.0;
900 case SUBTYPE_WIFI_N:
901 return 600.0;
902 case SUBTYPE_WIFI_AC:
903 return 1300.0;
904 case SUBTYPE_WIFI_AD:
905 return 7000.0;
906 case SUBTYPE_UNKNOWN:
907 return std::numeric_limits<double>::infinity();
908 case SUBTYPE_NONE:
909 return 0.0;
910 case SUBTYPE_OTHER:
911 return std::numeric_limits<double>::infinity();
913 NOTREACHED();
914 return std::numeric_limits<double>::infinity();
917 // static
918 void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() {
919 if (g_network_change_notifier &&
920 !NetworkChangeNotifier::test_notifications_only_) {
921 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
925 // static
926 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
927 if (g_network_change_notifier &&
928 !NetworkChangeNotifier::test_notifications_only_) {
929 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(
930 GetConnectionType());
934 // static
935 void NetworkChangeNotifier::NotifyObserversOfNetworkChange(
936 ConnectionType type) {
937 if (g_network_change_notifier &&
938 !NetworkChangeNotifier::test_notifications_only_) {
939 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
943 // static
944 void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(
945 double max_bandwidth_mbps) {
946 if (g_network_change_notifier &&
947 !NetworkChangeNotifier::test_notifications_only_) {
948 g_network_change_notifier->NotifyObserversOfMaxBandwidthChangeImpl(
949 max_bandwidth_mbps);
953 // static
954 void NetworkChangeNotifier::NotifyObserversOfDNSChange() {
955 if (g_network_change_notifier &&
956 !NetworkChangeNotifier::test_notifications_only_) {
957 g_network_change_notifier->NotifyObserversOfDNSChangeImpl();
961 // static
962 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigRead() {
963 if (g_network_change_notifier &&
964 !NetworkChangeNotifier::test_notifications_only_) {
965 g_network_change_notifier->NotifyObserversOfInitialDNSConfigReadImpl();
969 // static
970 void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) {
971 if (!g_network_change_notifier)
972 return;
973 g_network_change_notifier->network_state_->SetDnsConfig(config);
974 NotifyObserversOfDNSChange();
977 // static
978 void NetworkChangeNotifier::SetInitialDnsConfig(const DnsConfig& config) {
979 if (!g_network_change_notifier)
980 return;
981 #if DCHECK_IS_ON()
982 // Verify we've never received a valid DnsConfig previously.
983 DnsConfig old_config;
984 g_network_change_notifier->network_state_->GetDnsConfig(&old_config);
985 DCHECK(!old_config.IsValid());
986 #endif
987 g_network_change_notifier->network_state_->SetDnsConfig(config);
988 NotifyObserversOfInitialDNSConfigRead();
991 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() {
992 ip_address_observer_list_->Notify(FROM_HERE,
993 &IPAddressObserver::OnIPAddressChanged);
996 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl(
997 ConnectionType type) {
998 connection_type_observer_list_->Notify(
999 FROM_HERE, &ConnectionTypeObserver::OnConnectionTypeChanged, type);
1002 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl(
1003 ConnectionType type) {
1004 network_change_observer_list_->Notify(
1005 FROM_HERE, &NetworkChangeObserver::OnNetworkChanged, type);
1008 void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() {
1009 resolver_state_observer_list_->Notify(FROM_HERE, &DNSObserver::OnDNSChanged);
1012 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadImpl() {
1013 resolver_state_observer_list_->Notify(FROM_HERE,
1014 &DNSObserver::OnInitialDNSConfigRead);
1017 void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeImpl(
1018 double max_bandwidth_mbps) {
1019 max_bandwidth_observer_list_->Notify(
1020 FROM_HERE, &MaxBandwidthObserver::OnMaxBandwidthChanged,
1021 max_bandwidth_mbps);
1024 NetworkChangeNotifier::DisableForTest::DisableForTest()
1025 : network_change_notifier_(g_network_change_notifier) {
1026 DCHECK(g_network_change_notifier);
1027 g_network_change_notifier = NULL;
1030 NetworkChangeNotifier::DisableForTest::~DisableForTest() {
1031 DCHECK(!g_network_change_notifier);
1032 g_network_change_notifier = network_change_notifier_;
1035 void NetworkChangeNotifier::DNSObserver::OnInitialDNSConfigRead() {
1038 } // namespace net