Support symlinks in tools/vim/chromium.ycm_extra_conf.py
[chromium-blink-merge.git] / net / base / network_change_notifier.cc
blob34ec592f8fa27c412d3bda8f0f6fd8e504d1c561
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.h"
10 #include "base/synchronization/lock.h"
11 #include "base/threading/thread_checker.h"
12 #include "build/build_config.h"
13 #include "net/base/net_util.h"
14 #include "net/base/network_change_notifier_factory.h"
15 #include "net/dns/dns_config_service.h"
16 #include "net/url_request/url_request.h"
17 #include "url/gurl.h"
19 #if defined(OS_ANDROID)
20 #include "base/metrics/sparse_histogram.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "net/android/network_library.h"
23 #endif
25 #if defined(OS_WIN)
26 #include "net/base/network_change_notifier_win.h"
27 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
28 #include "net/base/network_change_notifier_linux.h"
29 #elif defined(OS_MACOSX)
30 #include "net/base/network_change_notifier_mac.h"
31 #endif
33 namespace net {
35 namespace {
37 // The actual singleton notifier. The class contract forbids usage of the API
38 // in ways that would require us to place locks around access to this object.
39 // (The prohibition on global non-POD objects makes it tricky to do such a thing
40 // anyway.)
41 NetworkChangeNotifier* g_network_change_notifier = NULL;
43 // Class factory singleton.
44 NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL;
46 class MockNetworkChangeNotifier : public NetworkChangeNotifier {
47 public:
48 ConnectionType GetCurrentConnectionType() const override {
49 return CONNECTION_UNKNOWN;
53 } // namespace
55 // The main observer class that records UMAs for network events.
56 class HistogramWatcher
57 : public NetworkChangeNotifier::ConnectionTypeObserver,
58 public NetworkChangeNotifier::IPAddressObserver,
59 public NetworkChangeNotifier::DNSObserver,
60 public NetworkChangeNotifier::NetworkChangeObserver {
61 public:
62 HistogramWatcher()
63 : last_ip_address_change_(base::TimeTicks::Now()),
64 last_connection_change_(base::TimeTicks::Now()),
65 last_dns_change_(base::TimeTicks::Now()),
66 last_network_change_(base::TimeTicks::Now()),
67 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
68 offline_packets_received_(0),
69 bytes_read_since_last_connection_change_(0),
70 peak_kbps_since_last_connection_change_(0) {}
72 // Registers our three Observer implementations. This is called from the
73 // network thread so that our Observer implementations are also called
74 // from the network thread. This avoids multi-threaded race conditions
75 // because the only other interface, |NotifyDataReceived| is also
76 // only called from the network thread.
77 void Init() {
78 DCHECK(thread_checker_.CalledOnValidThread());
79 DCHECK(g_network_change_notifier);
80 NetworkChangeNotifier::AddConnectionTypeObserver(this);
81 NetworkChangeNotifier::AddIPAddressObserver(this);
82 NetworkChangeNotifier::AddDNSObserver(this);
83 NetworkChangeNotifier::AddNetworkChangeObserver(this);
86 ~HistogramWatcher() override {
87 DCHECK(thread_checker_.CalledOnValidThread());
88 DCHECK(g_network_change_notifier);
89 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
90 NetworkChangeNotifier::RemoveIPAddressObserver(this);
91 NetworkChangeNotifier::RemoveDNSObserver(this);
92 NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
95 // NetworkChangeNotifier::IPAddressObserver implementation.
96 void OnIPAddressChanged() override {
97 DCHECK(thread_checker_.CalledOnValidThread());
98 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
99 SinceLast(&last_ip_address_change_));
100 UMA_HISTOGRAM_MEDIUM_TIMES(
101 "NCN.ConnectionTypeChangeToIPAddressChange",
102 last_ip_address_change_ - last_connection_change_);
105 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
106 void OnConnectionTypeChanged(
107 NetworkChangeNotifier::ConnectionType type) override {
108 DCHECK(thread_checker_.CalledOnValidThread());
109 base::TimeTicks now = base::TimeTicks::Now();
110 int32 kilobytes_read = bytes_read_since_last_connection_change_ / 1000;
111 base::TimeDelta state_duration = SinceLast(&last_connection_change_);
112 if (bytes_read_since_last_connection_change_) {
113 switch (last_connection_type_) {
114 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
115 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnUnknown",
116 first_byte_after_connection_change_);
117 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnUnknown",
118 fastest_RTT_since_last_connection_change_);
119 break;
120 case NetworkChangeNotifier::CONNECTION_ETHERNET:
121 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnEthernet",
122 first_byte_after_connection_change_);
123 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnEthernet",
124 fastest_RTT_since_last_connection_change_);
125 break;
126 case NetworkChangeNotifier::CONNECTION_WIFI:
127 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnWifi",
128 first_byte_after_connection_change_);
129 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnWifi",
130 fastest_RTT_since_last_connection_change_);
131 break;
132 case NetworkChangeNotifier::CONNECTION_2G:
133 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn2G",
134 first_byte_after_connection_change_);
135 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn2G",
136 fastest_RTT_since_last_connection_change_);
137 break;
138 case NetworkChangeNotifier::CONNECTION_3G:
139 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn3G",
140 first_byte_after_connection_change_);
141 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn3G",
142 fastest_RTT_since_last_connection_change_);
143 break;
144 case NetworkChangeNotifier::CONNECTION_4G:
145 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn4G",
146 first_byte_after_connection_change_);
147 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn4G",
148 fastest_RTT_since_last_connection_change_);
149 break;
150 case NetworkChangeNotifier::CONNECTION_NONE:
151 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnNone",
152 first_byte_after_connection_change_);
153 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnNone",
154 fastest_RTT_since_last_connection_change_);
155 break;
156 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
157 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnBluetooth",
158 first_byte_after_connection_change_);
159 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnBluetooth",
160 fastest_RTT_since_last_connection_change_);
163 if (peak_kbps_since_last_connection_change_) {
164 switch (last_connection_type_) {
165 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
166 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnUnknown",
167 peak_kbps_since_last_connection_change_);
168 break;
169 case NetworkChangeNotifier::CONNECTION_ETHERNET:
170 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnEthernet",
171 peak_kbps_since_last_connection_change_);
172 break;
173 case NetworkChangeNotifier::CONNECTION_WIFI:
174 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnWifi",
175 peak_kbps_since_last_connection_change_);
176 break;
177 case NetworkChangeNotifier::CONNECTION_2G:
178 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn2G",
179 peak_kbps_since_last_connection_change_);
180 break;
181 case NetworkChangeNotifier::CONNECTION_3G:
182 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn3G",
183 peak_kbps_since_last_connection_change_);
184 break;
185 case NetworkChangeNotifier::CONNECTION_4G:
186 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn4G",
187 peak_kbps_since_last_connection_change_);
188 break;
189 case NetworkChangeNotifier::CONNECTION_NONE:
190 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnNone",
191 peak_kbps_since_last_connection_change_);
192 break;
193 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
194 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnBluetooth",
195 peak_kbps_since_last_connection_change_);
196 break;
199 switch (last_connection_type_) {
200 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
201 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnUnknown", state_duration);
202 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnUnknown", kilobytes_read);
203 break;
204 case NetworkChangeNotifier::CONNECTION_ETHERNET:
205 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnEthernet", state_duration);
206 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnEthernet", kilobytes_read);
207 break;
208 case NetworkChangeNotifier::CONNECTION_WIFI:
209 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnWifi", state_duration);
210 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnWifi", kilobytes_read);
211 break;
212 case NetworkChangeNotifier::CONNECTION_2G:
213 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn2G", state_duration);
214 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn2G", kilobytes_read);
215 break;
216 case NetworkChangeNotifier::CONNECTION_3G:
217 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn3G", state_duration);
218 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn3G", kilobytes_read);
219 break;
220 case NetworkChangeNotifier::CONNECTION_4G:
221 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn4G", state_duration);
222 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn4G", kilobytes_read);
223 break;
224 case NetworkChangeNotifier::CONNECTION_NONE:
225 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnNone", state_duration);
226 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnNone", kilobytes_read);
227 break;
228 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
229 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnBluetooth", state_duration);
230 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnBluetooth", kilobytes_read);
231 break;
234 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
235 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", state_duration);
237 if (offline_packets_received_) {
238 if ((now - last_offline_packet_received_) <
239 base::TimeDelta::FromSeconds(5)) {
240 // We can compare this sum with the sum of NCN.OfflineDataRecv.
241 UMA_HISTOGRAM_COUNTS_10000(
242 "NCN.OfflineDataRecvAny5sBeforeOnline",
243 offline_packets_received_);
246 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline",
247 now - last_offline_packet_received_);
249 } else {
250 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", state_duration);
253 NetworkChangeNotifier::LogOperatorCodeHistogram(type);
255 UMA_HISTOGRAM_MEDIUM_TIMES(
256 "NCN.IPAddressChangeToConnectionTypeChange",
257 now - last_ip_address_change_);
259 offline_packets_received_ = 0;
260 bytes_read_since_last_connection_change_ = 0;
261 peak_kbps_since_last_connection_change_ = 0;
262 last_connection_type_ = type;
263 polling_interval_ = base::TimeDelta::FromSeconds(1);
266 // NetworkChangeNotifier::DNSObserver implementation.
267 void OnDNSChanged() override {
268 DCHECK(thread_checker_.CalledOnValidThread());
269 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange",
270 SinceLast(&last_dns_change_));
273 // NetworkChangeNotifier::NetworkChangeObserver implementation.
274 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
275 DCHECK(thread_checker_.CalledOnValidThread());
276 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
277 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange",
278 SinceLast(&last_network_change_));
279 } else {
280 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange",
281 SinceLast(&last_network_change_));
285 // Record histogram data whenever we receive a packet. Should only be called
286 // from the network thread.
287 void NotifyDataReceived(const URLRequest& request, int bytes_read) {
288 DCHECK(thread_checker_.CalledOnValidThread());
289 if (IsLocalhost(request.url().host()) ||
290 !request.url().SchemeIsHTTPOrHTTPS()) {
291 return;
294 base::TimeTicks now = base::TimeTicks::Now();
295 base::TimeDelta request_duration = now - request.creation_time();
296 if (bytes_read_since_last_connection_change_ == 0) {
297 first_byte_after_connection_change_ = now - last_connection_change_;
298 fastest_RTT_since_last_connection_change_ = request_duration;
300 bytes_read_since_last_connection_change_ += bytes_read;
301 if (request_duration < fastest_RTT_since_last_connection_change_)
302 fastest_RTT_since_last_connection_change_ = request_duration;
303 // Ignore tiny transfers which will not produce accurate rates.
304 // Ignore zero duration transfers which might cause divide by zero.
305 if (bytes_read > 10000 &&
306 request_duration > base::TimeDelta::FromMilliseconds(1) &&
307 request.creation_time() > last_connection_change_) {
308 int32 kbps = static_cast<int32>(
309 bytes_read * 8 / request_duration.InMilliseconds());
310 if (kbps > peak_kbps_since_last_connection_change_)
311 peak_kbps_since_last_connection_change_ = kbps;
314 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE)
315 return;
317 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv",
318 now - last_connection_change_);
319 offline_packets_received_++;
320 last_offline_packet_received_ = now;
322 if ((now - last_polled_connection_) > polling_interval_) {
323 polling_interval_ *= 2;
324 last_polled_connection_ = now;
325 last_polled_connection_type_ =
326 NetworkChangeNotifier::GetConnectionType();
328 if (last_polled_connection_type_ ==
329 NetworkChangeNotifier::CONNECTION_NONE) {
330 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.PollingOfflineDataRecv",
331 now - last_connection_change_);
335 private:
336 static base::TimeDelta SinceLast(base::TimeTicks *last_time) {
337 base::TimeTicks current_time = base::TimeTicks::Now();
338 base::TimeDelta delta = current_time - *last_time;
339 *last_time = current_time;
340 return delta;
343 base::TimeTicks last_ip_address_change_;
344 base::TimeTicks last_connection_change_;
345 base::TimeTicks last_dns_change_;
346 base::TimeTicks last_network_change_;
347 base::TimeTicks last_offline_packet_received_;
348 base::TimeTicks last_polled_connection_;
349 // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our
350 // first transition to offline and on subsequent transitions. Once offline,
351 // |polling_interval_| doubles as offline data is received and we poll
352 // with |NetworkChangeNotifier::GetConnectionType| to verify the connection
353 // state.
354 base::TimeDelta polling_interval_;
355 // |last_connection_type_| is the last value passed to
356 // |OnConnectionTypeChanged|.
357 NetworkChangeNotifier::ConnectionType last_connection_type_;
358 // |last_polled_connection_type_| is last result from calling
359 // |NetworkChangeNotifier::GetConnectionType| in |NotifyDataReceived|.
360 NetworkChangeNotifier::ConnectionType last_polled_connection_type_;
361 // Count of how many times NotifyDataReceived() has been called while the
362 // NetworkChangeNotifier thought network connection was offline.
363 int32 offline_packets_received_;
364 // Number of bytes of network data received since last connectivity change.
365 int32 bytes_read_since_last_connection_change_;
366 // Fastest round-trip-time (RTT) since last connectivity change. RTT measured
367 // from URLRequest creation until first byte received.
368 base::TimeDelta fastest_RTT_since_last_connection_change_;
369 // Time between connectivity change and first network data byte received.
370 base::TimeDelta first_byte_after_connection_change_;
371 // Rough measurement of peak KB/s witnessed since last connectivity change.
372 // The accuracy is decreased by ignoring these factors:
373 // 1) Multiple URLRequests can occur concurrently.
374 // 2) NotifyDataReceived() may be called repeatedly for one URLRequest.
375 // 3) The transfer time includes at least one RTT while no bytes are read.
376 // Erring on the conservative side is hopefully offset by taking the maximum.
377 int32 peak_kbps_since_last_connection_change_;
379 base::ThreadChecker thread_checker_;
381 DISALLOW_COPY_AND_ASSIGN(HistogramWatcher);
384 // NetworkState is thread safe.
385 class NetworkChangeNotifier::NetworkState {
386 public:
387 NetworkState() {}
388 ~NetworkState() {}
390 void GetDnsConfig(DnsConfig* config) const {
391 base::AutoLock lock(lock_);
392 *config = dns_config_;
395 void SetDnsConfig(const DnsConfig& dns_config) {
396 base::AutoLock lock(lock_);
397 dns_config_ = dns_config;
400 private:
401 mutable base::Lock lock_;
402 DnsConfig dns_config_;
405 NetworkChangeNotifier::NetworkChangeCalculatorParams::
406 NetworkChangeCalculatorParams() {
409 // Calculates NetworkChange signal from IPAddress and ConnectionType signals.
410 class NetworkChangeNotifier::NetworkChangeCalculator
411 : public ConnectionTypeObserver,
412 public IPAddressObserver {
413 public:
414 NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
415 : params_(params),
416 have_announced_(false),
417 last_announced_connection_type_(CONNECTION_NONE),
418 pending_connection_type_(CONNECTION_NONE) {}
420 void Init() {
421 DCHECK(thread_checker_.CalledOnValidThread());
422 DCHECK(g_network_change_notifier);
423 AddConnectionTypeObserver(this);
424 AddIPAddressObserver(this);
427 ~NetworkChangeCalculator() override {
428 DCHECK(thread_checker_.CalledOnValidThread());
429 DCHECK(g_network_change_notifier);
430 RemoveConnectionTypeObserver(this);
431 RemoveIPAddressObserver(this);
434 // NetworkChangeNotifier::IPAddressObserver implementation.
435 void OnIPAddressChanged() override {
436 DCHECK(thread_checker_.CalledOnValidThread());
437 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
438 ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_;
439 // Cancels any previous timer.
440 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
443 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
444 void OnConnectionTypeChanged(ConnectionType type) override {
445 DCHECK(thread_checker_.CalledOnValidThread());
446 pending_connection_type_ = type;
447 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
448 ? params_.connection_type_offline_delay_
449 : params_.connection_type_online_delay_;
450 // Cancels any previous timer.
451 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
454 private:
455 void Notify() {
456 DCHECK(thread_checker_.CalledOnValidThread());
457 // Don't bother signaling about dead connections.
458 if (have_announced_ &&
459 (last_announced_connection_type_ == CONNECTION_NONE) &&
460 (pending_connection_type_ == CONNECTION_NONE)) {
461 return;
463 have_announced_ = true;
464 last_announced_connection_type_ = pending_connection_type_;
465 // Immediately before sending out an online signal, send out an offline
466 // signal to perform any destructive actions before constructive actions.
467 if (pending_connection_type_ != CONNECTION_NONE)
468 NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE);
469 NetworkChangeNotifier::NotifyObserversOfNetworkChange(
470 pending_connection_type_);
473 const NetworkChangeCalculatorParams params_;
475 // Indicates if NotifyObserversOfNetworkChange has been called yet.
476 bool have_announced_;
477 // Last value passed to NotifyObserversOfNetworkChange.
478 ConnectionType last_announced_connection_type_;
479 // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
480 ConnectionType pending_connection_type_;
481 // Used to delay notifications so duplicates can be combined.
482 base::OneShotTimer<NetworkChangeCalculator> timer_;
484 base::ThreadChecker thread_checker_;
486 DISALLOW_COPY_AND_ASSIGN(NetworkChangeCalculator);
489 NetworkChangeNotifier::~NetworkChangeNotifier() {
490 network_change_calculator_.reset();
491 DCHECK_EQ(this, g_network_change_notifier);
492 g_network_change_notifier = NULL;
495 // static
496 void NetworkChangeNotifier::SetFactory(
497 NetworkChangeNotifierFactory* factory) {
498 CHECK(!g_network_change_notifier_factory);
499 g_network_change_notifier_factory = factory;
502 // static
503 NetworkChangeNotifier* NetworkChangeNotifier::Create() {
504 if (g_network_change_notifier_factory)
505 return g_network_change_notifier_factory->CreateInstance();
507 #if defined(OS_WIN)
508 NetworkChangeNotifierWin* network_change_notifier =
509 new NetworkChangeNotifierWin();
510 network_change_notifier->WatchForAddressChange();
511 return network_change_notifier;
512 #elif defined(OS_CHROMEOS) || defined(OS_ANDROID)
513 // ChromeOS and Android builds MUST use their own class factory.
514 #if !defined(OS_CHROMEOS)
515 // TODO(oshima): ash_shell do not have access to chromeos'es
516 // notifier yet. Re-enable this when chromeos'es notifier moved to
517 // chromeos root directory. crbug.com/119298.
518 CHECK(false);
519 #endif
520 return NULL;
521 #elif defined(OS_LINUX)
522 return NetworkChangeNotifierLinux::Create();
523 #elif defined(OS_MACOSX)
524 return new NetworkChangeNotifierMac();
525 #else
526 NOTIMPLEMENTED();
527 return NULL;
528 #endif
531 // static
532 NetworkChangeNotifier::ConnectionType
533 NetworkChangeNotifier::GetConnectionType() {
534 return g_network_change_notifier ?
535 g_network_change_notifier->GetCurrentConnectionType() :
536 CONNECTION_UNKNOWN;
539 // static
540 double NetworkChangeNotifier::GetMaxBandwidth() {
541 return g_network_change_notifier ?
542 g_network_change_notifier->GetCurrentMaxBandwidth() :
543 std::numeric_limits<double>::infinity();
546 // static
547 void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) {
548 if (!g_network_change_notifier) {
549 *config = DnsConfig();
550 } else {
551 g_network_change_notifier->network_state_->GetDnsConfig(config);
555 // static
556 const char* NetworkChangeNotifier::ConnectionTypeToString(
557 ConnectionType type) {
558 static const char* kConnectionTypeNames[] = {
559 "CONNECTION_UNKNOWN",
560 "CONNECTION_ETHERNET",
561 "CONNECTION_WIFI",
562 "CONNECTION_2G",
563 "CONNECTION_3G",
564 "CONNECTION_4G",
565 "CONNECTION_NONE",
566 "CONNECTION_BLUETOOTH"
568 static_assert(arraysize(kConnectionTypeNames) ==
569 NetworkChangeNotifier::CONNECTION_LAST + 1,
570 "ConnectionType name count should match");
571 if (type < CONNECTION_UNKNOWN || type > CONNECTION_LAST) {
572 NOTREACHED();
573 return "CONNECTION_INVALID";
575 return kConnectionTypeNames[type];
578 // static
579 void NetworkChangeNotifier::NotifyDataReceived(const URLRequest& request,
580 int bytes_read) {
581 if (!g_network_change_notifier ||
582 !g_network_change_notifier->histogram_watcher_) {
583 return;
585 g_network_change_notifier->histogram_watcher_->NotifyDataReceived(request,
586 bytes_read);
589 // static
590 void NetworkChangeNotifier::InitHistogramWatcher() {
591 if (!g_network_change_notifier)
592 return;
593 g_network_change_notifier->histogram_watcher_.reset(new HistogramWatcher());
594 g_network_change_notifier->histogram_watcher_->Init();
597 // static
598 void NetworkChangeNotifier::ShutdownHistogramWatcher() {
599 if (!g_network_change_notifier)
600 return;
601 g_network_change_notifier->histogram_watcher_.reset();
604 // static
605 void NetworkChangeNotifier::LogOperatorCodeHistogram(ConnectionType type) {
606 #if defined(OS_ANDROID)
607 // On a connection type change to 2/3/4G, log the network operator MCC/MNC.
608 // Log zero in other cases.
609 unsigned mcc_mnc = 0;
610 if (type == NetworkChangeNotifier::CONNECTION_2G ||
611 type == NetworkChangeNotifier::CONNECTION_3G ||
612 type == NetworkChangeNotifier::CONNECTION_4G) {
613 // Log zero if not perfectly converted.
614 if (!base::StringToUint(
615 net::android::GetTelephonyNetworkOperator(), &mcc_mnc)) {
616 mcc_mnc = 0;
619 UMA_HISTOGRAM_SPARSE_SLOWLY("NCN.NetworkOperatorMCCMNC", mcc_mnc);
620 #endif
623 #if defined(OS_LINUX)
624 // static
625 const internal::AddressTrackerLinux*
626 NetworkChangeNotifier::GetAddressTracker() {
627 return g_network_change_notifier ?
628 g_network_change_notifier->GetAddressTrackerInternal() : NULL;
630 #endif
632 // static
633 bool NetworkChangeNotifier::IsOffline() {
634 return GetConnectionType() == CONNECTION_NONE;
637 // static
638 bool NetworkChangeNotifier::IsConnectionCellular(ConnectionType type) {
639 bool is_cellular = false;
640 switch (type) {
641 case CONNECTION_2G:
642 case CONNECTION_3G:
643 case CONNECTION_4G:
644 is_cellular = true;
645 break;
646 case CONNECTION_UNKNOWN:
647 case CONNECTION_ETHERNET:
648 case CONNECTION_WIFI:
649 case CONNECTION_NONE:
650 case CONNECTION_BLUETOOTH:
651 is_cellular = false;
652 break;
654 return is_cellular;
657 // static
658 NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() {
659 return new MockNetworkChangeNotifier();
662 void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) {
663 if (g_network_change_notifier)
664 g_network_change_notifier->ip_address_observer_list_->AddObserver(observer);
667 void NetworkChangeNotifier::AddConnectionTypeObserver(
668 ConnectionTypeObserver* observer) {
669 if (g_network_change_notifier) {
670 g_network_change_notifier->connection_type_observer_list_->AddObserver(
671 observer);
675 void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) {
676 if (g_network_change_notifier) {
677 g_network_change_notifier->resolver_state_observer_list_->AddObserver(
678 observer);
682 void NetworkChangeNotifier::AddNetworkChangeObserver(
683 NetworkChangeObserver* observer) {
684 if (g_network_change_notifier) {
685 g_network_change_notifier->network_change_observer_list_->AddObserver(
686 observer);
690 void NetworkChangeNotifier::AddMaxBandwidthObserver(
691 MaxBandwidthObserver* observer) {
692 if (g_network_change_notifier) {
693 g_network_change_notifier->max_bandwidth_observer_list_->AddObserver(
694 observer);
698 void NetworkChangeNotifier::RemoveIPAddressObserver(
699 IPAddressObserver* observer) {
700 if (g_network_change_notifier) {
701 g_network_change_notifier->ip_address_observer_list_->RemoveObserver(
702 observer);
706 void NetworkChangeNotifier::RemoveConnectionTypeObserver(
707 ConnectionTypeObserver* observer) {
708 if (g_network_change_notifier) {
709 g_network_change_notifier->connection_type_observer_list_->RemoveObserver(
710 observer);
714 void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) {
715 if (g_network_change_notifier) {
716 g_network_change_notifier->resolver_state_observer_list_->RemoveObserver(
717 observer);
721 void NetworkChangeNotifier::RemoveNetworkChangeObserver(
722 NetworkChangeObserver* observer) {
723 if (g_network_change_notifier) {
724 g_network_change_notifier->network_change_observer_list_->RemoveObserver(
725 observer);
729 void NetworkChangeNotifier::RemoveMaxBandwidthObserver(
730 MaxBandwidthObserver* observer) {
731 if (g_network_change_notifier) {
732 g_network_change_notifier->max_bandwidth_observer_list_->RemoveObserver(
733 observer);
737 // static
738 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() {
739 if (g_network_change_notifier)
740 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
743 // static
744 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
745 ConnectionType type) {
746 if (g_network_change_notifier)
747 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(type);
750 // static
751 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
752 ConnectionType type) {
753 if (g_network_change_notifier)
754 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
757 // static
758 void NetworkChangeNotifier::SetTestNotificationsOnly(bool test_only) {
759 if (g_network_change_notifier)
760 g_network_change_notifier->test_notifications_only_ = test_only;
763 NetworkChangeNotifier::NetworkChangeNotifier(
764 const NetworkChangeCalculatorParams& params
765 /*= NetworkChangeCalculatorParams()*/)
766 : ip_address_observer_list_(new ObserverListThreadSafe<IPAddressObserver>(
767 ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)),
768 connection_type_observer_list_(
769 new ObserverListThreadSafe<ConnectionTypeObserver>(
770 ObserverListBase<ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)),
771 resolver_state_observer_list_(new ObserverListThreadSafe<DNSObserver>(
772 ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)),
773 network_change_observer_list_(
774 new ObserverListThreadSafe<NetworkChangeObserver>(
775 ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)),
776 max_bandwidth_observer_list_(
777 new ObserverListThreadSafe<MaxBandwidthObserver>(
778 ObserverListBase<MaxBandwidthObserver>::NOTIFY_EXISTING_ONLY)),
779 network_state_(new NetworkState()),
780 network_change_calculator_(new NetworkChangeCalculator(params)),
781 test_notifications_only_(false) {
782 DCHECK(!g_network_change_notifier);
783 g_network_change_notifier = this;
784 network_change_calculator_->Init();
787 #if defined(OS_LINUX)
788 const internal::AddressTrackerLinux*
789 NetworkChangeNotifier::GetAddressTrackerInternal() const {
790 return NULL;
792 #endif
794 double NetworkChangeNotifier::GetCurrentMaxBandwidth() const {
795 // This default implementation conforms to the NetInfo V3 specification but
796 // should be overridden to provide specific bandwidth data based on the
797 // platform.
798 if (GetCurrentConnectionType() == CONNECTION_NONE)
799 return 0.0;
800 return std::numeric_limits<double>::infinity();
803 // static
804 double NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
805 ConnectionSubtype subtype) {
806 switch (subtype) {
807 case SUBTYPE_GSM:
808 return 0.01;
809 case SUBTYPE_IDEN:
810 return 0.064;
811 case SUBTYPE_CDMA:
812 return 0.115;
813 case SUBTYPE_1XRTT:
814 return 0.153;
815 case SUBTYPE_GPRS:
816 return 0.237;
817 case SUBTYPE_EDGE:
818 return 0.384;
819 case SUBTYPE_UMTS:
820 return 2.0;
821 case SUBTYPE_EVDO_REV_0:
822 return 2.46;
823 case SUBTYPE_EVDO_REV_A:
824 return 3.1;
825 case SUBTYPE_HSPA:
826 return 3.6;
827 case SUBTYPE_EVDO_REV_B:
828 return 14.7;
829 case SUBTYPE_HSDPA:
830 return 14.3;
831 case SUBTYPE_HSUPA:
832 return 14.4;
833 case SUBTYPE_EHRPD:
834 return 21.0;
835 case SUBTYPE_HSPAP:
836 return 42.0;
837 case SUBTYPE_LTE:
838 return 100.0;
839 case SUBTYPE_LTE_ADVANCED:
840 return 100.0;
841 case SUBTYPE_BLUETOOTH_1_2:
842 return 1.0;
843 case SUBTYPE_BLUETOOTH_2_1:
844 return 3.0;
845 case SUBTYPE_BLUETOOTH_3_0:
846 return 24.0;
847 case SUBTYPE_BLUETOOTH_4_0:
848 return 1.0;
849 case SUBTYPE_ETHERNET:
850 return 10.0;
851 case SUBTYPE_FAST_ETHERNET:
852 return 100.0;
853 case SUBTYPE_GIGABIT_ETHERNET:
854 return 1000.0;
855 case SUBTYPE_10_GIGABIT_ETHERNET:
856 return 10000.0;
857 case SUBTYPE_WIFI_B:
858 return 11.0;
859 case SUBTYPE_WIFI_G:
860 return 54.0;
861 case SUBTYPE_WIFI_N:
862 return 600.0;
863 case SUBTYPE_WIFI_AC:
864 return 1300.0;
865 case SUBTYPE_WIFI_AD:
866 return 7000.0;
867 case SUBTYPE_UNKNOWN:
868 return std::numeric_limits<double>::infinity();
869 case SUBTYPE_NONE:
870 return 0.0;
871 case SUBTYPE_OTHER:
872 return std::numeric_limits<double>::infinity();
874 NOTREACHED();
875 return std::numeric_limits<double>::infinity();
878 // static
879 void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() {
880 if (g_network_change_notifier &&
881 !g_network_change_notifier->test_notifications_only_) {
882 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
886 // static
887 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
888 if (g_network_change_notifier &&
889 !g_network_change_notifier->test_notifications_only_) {
890 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(
891 GetConnectionType());
895 // static
896 void NetworkChangeNotifier::NotifyObserversOfNetworkChange(
897 ConnectionType type) {
898 if (g_network_change_notifier &&
899 !g_network_change_notifier->test_notifications_only_) {
900 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
904 // static
905 void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(
906 double max_bandwidth_mbps) {
907 if (g_network_change_notifier &&
908 !g_network_change_notifier->test_notifications_only_) {
909 g_network_change_notifier->NotifyObserversOfMaxBandwidthChangeImpl(
910 max_bandwidth_mbps);
914 // static
915 void NetworkChangeNotifier::NotifyObserversOfDNSChange() {
916 if (g_network_change_notifier &&
917 !g_network_change_notifier->test_notifications_only_) {
918 g_network_change_notifier->NotifyObserversOfDNSChangeImpl();
922 // static
923 void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) {
924 if (!g_network_change_notifier)
925 return;
926 g_network_change_notifier->network_state_->SetDnsConfig(config);
927 NotifyObserversOfDNSChange();
930 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() {
931 ip_address_observer_list_->Notify(&IPAddressObserver::OnIPAddressChanged);
934 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl(
935 ConnectionType type) {
936 connection_type_observer_list_->Notify(
937 &ConnectionTypeObserver::OnConnectionTypeChanged, type);
940 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl(
941 ConnectionType type) {
942 network_change_observer_list_->Notify(
943 &NetworkChangeObserver::OnNetworkChanged, type);
946 void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() {
947 resolver_state_observer_list_->Notify(&DNSObserver::OnDNSChanged);
950 void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeImpl(
951 double max_bandwidth_mbps) {
952 max_bandwidth_observer_list_->Notify(
953 &MaxBandwidthObserver::OnMaxBandwidthChanged, max_bandwidth_mbps);
956 NetworkChangeNotifier::DisableForTest::DisableForTest()
957 : network_change_notifier_(g_network_change_notifier) {
958 DCHECK(g_network_change_notifier);
959 g_network_change_notifier = NULL;
962 NetworkChangeNotifier::DisableForTest::~DisableForTest() {
963 DCHECK(!g_network_change_notifier);
964 g_network_change_notifier = network_change_notifier_;
967 } // namespace net