[Android WebView] Fix webview perf bot switchover to use org.chromium.webview_shell...
[chromium-blink-merge.git] / net / base / network_change_notifier.cc
blob85321892a823a830b22a56047add217a68971ba4
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/dns/dns_config_service.h"
17 #include "net/url_request/url_request.h"
18 #include "url/gurl.h"
20 #if defined(OS_ANDROID)
21 #include "base/metrics/sparse_histogram.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "net/android/network_library.h"
24 #endif
26 #if defined(OS_WIN)
27 #include "net/base/network_change_notifier_win.h"
28 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
29 #include "net/base/network_change_notifier_linux.h"
30 #elif defined(OS_MACOSX)
31 #include "net/base/network_change_notifier_mac.h"
32 #endif
34 namespace net {
36 namespace {
38 // The actual singleton notifier. The class contract forbids usage of the API
39 // in ways that would require us to place locks around access to this object.
40 // (The prohibition on global non-POD objects makes it tricky to do such a thing
41 // anyway.)
42 NetworkChangeNotifier* g_network_change_notifier = NULL;
44 // Class factory singleton.
45 NetworkChangeNotifierFactory* g_network_change_notifier_factory = NULL;
47 class MockNetworkChangeNotifier : public NetworkChangeNotifier {
48 public:
49 ConnectionType GetCurrentConnectionType() const override {
50 return CONNECTION_UNKNOWN;
54 } // namespace
56 // The main observer class that records UMAs for network events.
57 class HistogramWatcher
58 : public NetworkChangeNotifier::ConnectionTypeObserver,
59 public NetworkChangeNotifier::IPAddressObserver,
60 public NetworkChangeNotifier::DNSObserver,
61 public NetworkChangeNotifier::NetworkChangeObserver {
62 public:
63 HistogramWatcher()
64 : last_ip_address_change_(base::TimeTicks::Now()),
65 last_connection_change_(base::TimeTicks::Now()),
66 last_dns_change_(base::TimeTicks::Now()),
67 last_network_change_(base::TimeTicks::Now()),
68 last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
69 offline_packets_received_(0),
70 bytes_read_since_last_connection_change_(0),
71 peak_kbps_since_last_connection_change_(0) {}
73 // Registers our three Observer implementations. This is called from the
74 // network thread so that our Observer implementations are also called
75 // from the network thread. This avoids multi-threaded race conditions
76 // because the only other interface, |NotifyDataReceived| is also
77 // only called from the network thread.
78 void Init() {
79 DCHECK(thread_checker_.CalledOnValidThread());
80 DCHECK(g_network_change_notifier);
81 NetworkChangeNotifier::AddConnectionTypeObserver(this);
82 NetworkChangeNotifier::AddIPAddressObserver(this);
83 NetworkChangeNotifier::AddDNSObserver(this);
84 NetworkChangeNotifier::AddNetworkChangeObserver(this);
87 ~HistogramWatcher() override {
88 DCHECK(thread_checker_.CalledOnValidThread());
89 DCHECK(g_network_change_notifier);
90 NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
91 NetworkChangeNotifier::RemoveIPAddressObserver(this);
92 NetworkChangeNotifier::RemoveDNSObserver(this);
93 NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
96 // NetworkChangeNotifier::IPAddressObserver implementation.
97 void OnIPAddressChanged() override {
98 DCHECK(thread_checker_.CalledOnValidThread());
99 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
100 SinceLast(&last_ip_address_change_));
101 UMA_HISTOGRAM_MEDIUM_TIMES(
102 "NCN.ConnectionTypeChangeToIPAddressChange",
103 last_ip_address_change_ - last_connection_change_);
106 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
107 void OnConnectionTypeChanged(
108 NetworkChangeNotifier::ConnectionType type) override {
109 DCHECK(thread_checker_.CalledOnValidThread());
110 base::TimeTicks now = base::TimeTicks::Now();
111 int32_t kilobytes_read = bytes_read_since_last_connection_change_ / 1000;
112 base::TimeDelta state_duration = SinceLast(&last_connection_change_);
113 if (bytes_read_since_last_connection_change_) {
114 switch (last_connection_type_) {
115 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
116 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnUnknown",
117 first_byte_after_connection_change_);
118 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnUnknown",
119 fastest_RTT_since_last_connection_change_);
120 break;
121 case NetworkChangeNotifier::CONNECTION_ETHERNET:
122 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnEthernet",
123 first_byte_after_connection_change_);
124 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnEthernet",
125 fastest_RTT_since_last_connection_change_);
126 break;
127 case NetworkChangeNotifier::CONNECTION_WIFI:
128 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnWifi",
129 first_byte_after_connection_change_);
130 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnWifi",
131 fastest_RTT_since_last_connection_change_);
132 break;
133 case NetworkChangeNotifier::CONNECTION_2G:
134 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn2G",
135 first_byte_after_connection_change_);
136 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn2G",
137 fastest_RTT_since_last_connection_change_);
138 break;
139 case NetworkChangeNotifier::CONNECTION_3G:
140 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn3G",
141 first_byte_after_connection_change_);
142 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn3G",
143 fastest_RTT_since_last_connection_change_);
144 break;
145 case NetworkChangeNotifier::CONNECTION_4G:
146 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOn4G",
147 first_byte_after_connection_change_);
148 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOn4G",
149 fastest_RTT_since_last_connection_change_);
150 break;
151 case NetworkChangeNotifier::CONNECTION_NONE:
152 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnNone",
153 first_byte_after_connection_change_);
154 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnNone",
155 fastest_RTT_since_last_connection_change_);
156 break;
157 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
158 UMA_HISTOGRAM_TIMES("NCN.CM.FirstReadOnBluetooth",
159 first_byte_after_connection_change_);
160 UMA_HISTOGRAM_TIMES("NCN.CM.FastestRTTOnBluetooth",
161 fastest_RTT_since_last_connection_change_);
164 if (peak_kbps_since_last_connection_change_) {
165 switch (last_connection_type_) {
166 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
167 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnUnknown",
168 peak_kbps_since_last_connection_change_);
169 break;
170 case NetworkChangeNotifier::CONNECTION_ETHERNET:
171 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnEthernet",
172 peak_kbps_since_last_connection_change_);
173 break;
174 case NetworkChangeNotifier::CONNECTION_WIFI:
175 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnWifi",
176 peak_kbps_since_last_connection_change_);
177 break;
178 case NetworkChangeNotifier::CONNECTION_2G:
179 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn2G",
180 peak_kbps_since_last_connection_change_);
181 break;
182 case NetworkChangeNotifier::CONNECTION_3G:
183 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn3G",
184 peak_kbps_since_last_connection_change_);
185 break;
186 case NetworkChangeNotifier::CONNECTION_4G:
187 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn4G",
188 peak_kbps_since_last_connection_change_);
189 break;
190 case NetworkChangeNotifier::CONNECTION_NONE:
191 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnNone",
192 peak_kbps_since_last_connection_change_);
193 break;
194 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
195 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnBluetooth",
196 peak_kbps_since_last_connection_change_);
197 break;
200 switch (last_connection_type_) {
201 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
202 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnUnknown", state_duration);
203 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnUnknown", kilobytes_read);
204 break;
205 case NetworkChangeNotifier::CONNECTION_ETHERNET:
206 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnEthernet", state_duration);
207 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnEthernet", kilobytes_read);
208 break;
209 case NetworkChangeNotifier::CONNECTION_WIFI:
210 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnWifi", state_duration);
211 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnWifi", kilobytes_read);
212 break;
213 case NetworkChangeNotifier::CONNECTION_2G:
214 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn2G", state_duration);
215 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn2G", kilobytes_read);
216 break;
217 case NetworkChangeNotifier::CONNECTION_3G:
218 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn3G", state_duration);
219 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn3G", kilobytes_read);
220 break;
221 case NetworkChangeNotifier::CONNECTION_4G:
222 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn4G", state_duration);
223 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn4G", kilobytes_read);
224 break;
225 case NetworkChangeNotifier::CONNECTION_NONE:
226 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnNone", state_duration);
227 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnNone", kilobytes_read);
228 break;
229 case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
230 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnBluetooth", state_duration);
231 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnBluetooth", kilobytes_read);
232 break;
235 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
236 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OnlineChange", state_duration);
238 if (offline_packets_received_) {
239 if ((now - last_offline_packet_received_) <
240 base::TimeDelta::FromSeconds(5)) {
241 // We can compare this sum with the sum of NCN.OfflineDataRecv.
242 UMA_HISTOGRAM_COUNTS_10000(
243 "NCN.OfflineDataRecvAny5sBeforeOnline",
244 offline_packets_received_);
247 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecvUntilOnline",
248 now - last_offline_packet_received_);
250 } else {
251 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange", state_duration);
254 NetworkChangeNotifier::LogOperatorCodeHistogram(type);
256 UMA_HISTOGRAM_MEDIUM_TIMES(
257 "NCN.IPAddressChangeToConnectionTypeChange",
258 now - last_ip_address_change_);
260 offline_packets_received_ = 0;
261 bytes_read_since_last_connection_change_ = 0;
262 peak_kbps_since_last_connection_change_ = 0;
263 last_connection_type_ = type;
264 polling_interval_ = base::TimeDelta::FromSeconds(1);
267 // NetworkChangeNotifier::DNSObserver implementation.
268 void OnDNSChanged() override {
269 DCHECK(thread_checker_.CalledOnValidThread());
270 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.DNSConfigChange",
271 SinceLast(&last_dns_change_));
274 // NetworkChangeNotifier::NetworkChangeObserver implementation.
275 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
276 DCHECK(thread_checker_.CalledOnValidThread());
277 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
278 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange",
279 SinceLast(&last_network_change_));
280 } else {
281 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange",
282 SinceLast(&last_network_change_));
286 // Record histogram data whenever we receive a packet. Should only be called
287 // from the network thread.
288 void NotifyDataReceived(const URLRequest& request, int bytes_read) {
289 DCHECK(thread_checker_.CalledOnValidThread());
290 if (IsLocalhost(request.url().host()) ||
291 !request.url().SchemeIsHTTPOrHTTPS()) {
292 return;
295 base::TimeTicks now = base::TimeTicks::Now();
296 base::TimeDelta request_duration = now - request.creation_time();
297 if (bytes_read_since_last_connection_change_ == 0) {
298 first_byte_after_connection_change_ = now - last_connection_change_;
299 fastest_RTT_since_last_connection_change_ = request_duration;
301 bytes_read_since_last_connection_change_ += bytes_read;
302 if (request_duration < fastest_RTT_since_last_connection_change_)
303 fastest_RTT_since_last_connection_change_ = request_duration;
304 // Ignore tiny transfers which will not produce accurate rates.
305 // Ignore zero duration transfers which might cause divide by zero.
306 if (bytes_read > 10000 &&
307 request_duration > base::TimeDelta::FromMilliseconds(1) &&
308 request.creation_time() > last_connection_change_) {
309 int32_t kbps = static_cast<int32_t>(bytes_read * 8 /
310 request_duration.InMilliseconds());
311 if (kbps > peak_kbps_since_last_connection_change_)
312 peak_kbps_since_last_connection_change_ = kbps;
315 if (last_connection_type_ != NetworkChangeNotifier::CONNECTION_NONE)
316 return;
318 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineDataRecv",
319 now - last_connection_change_);
320 offline_packets_received_++;
321 last_offline_packet_received_ = now;
323 if ((now - last_polled_connection_) > polling_interval_) {
324 polling_interval_ *= 2;
325 last_polled_connection_ = now;
326 last_polled_connection_type_ =
327 NetworkChangeNotifier::GetConnectionType();
329 if (last_polled_connection_type_ ==
330 NetworkChangeNotifier::CONNECTION_NONE) {
331 UMA_HISTOGRAM_MEDIUM_TIMES("NCN.PollingOfflineDataRecv",
332 now - last_connection_change_);
336 private:
337 static base::TimeDelta SinceLast(base::TimeTicks *last_time) {
338 base::TimeTicks current_time = base::TimeTicks::Now();
339 base::TimeDelta delta = current_time - *last_time;
340 *last_time = current_time;
341 return delta;
344 base::TimeTicks last_ip_address_change_;
345 base::TimeTicks last_connection_change_;
346 base::TimeTicks last_dns_change_;
347 base::TimeTicks last_network_change_;
348 base::TimeTicks last_offline_packet_received_;
349 base::TimeTicks last_polled_connection_;
350 // |polling_interval_| is initialized by |OnConnectionTypeChanged| on our
351 // first transition to offline and on subsequent transitions. Once offline,
352 // |polling_interval_| doubles as offline data is received and we poll
353 // with |NetworkChangeNotifier::GetConnectionType| to verify the connection
354 // state.
355 base::TimeDelta polling_interval_;
356 // |last_connection_type_| is the last value passed to
357 // |OnConnectionTypeChanged|.
358 NetworkChangeNotifier::ConnectionType last_connection_type_;
359 // |last_polled_connection_type_| is last result from calling
360 // |NetworkChangeNotifier::GetConnectionType| in |NotifyDataReceived|.
361 NetworkChangeNotifier::ConnectionType last_polled_connection_type_;
362 // Count of how many times NotifyDataReceived() has been called while the
363 // NetworkChangeNotifier thought network connection was offline.
364 int32_t offline_packets_received_;
365 // Number of bytes of network data received since last connectivity change.
366 int32_t bytes_read_since_last_connection_change_;
367 // Fastest round-trip-time (RTT) since last connectivity change. RTT measured
368 // from URLRequest creation until first byte received.
369 base::TimeDelta fastest_RTT_since_last_connection_change_;
370 // Time between connectivity change and first network data byte received.
371 base::TimeDelta first_byte_after_connection_change_;
372 // Rough measurement of peak KB/s witnessed since last connectivity change.
373 // The accuracy is decreased by ignoring these factors:
374 // 1) Multiple URLRequests can occur concurrently.
375 // 2) NotifyDataReceived() may be called repeatedly for one URLRequest.
376 // 3) The transfer time includes at least one RTT while no bytes are read.
377 // Erring on the conservative side is hopefully offset by taking the maximum.
378 int32_t peak_kbps_since_last_connection_change_;
380 base::ThreadChecker thread_checker_;
382 DISALLOW_COPY_AND_ASSIGN(HistogramWatcher);
385 // NetworkState is thread safe.
386 class NetworkChangeNotifier::NetworkState {
387 public:
388 NetworkState() {}
389 ~NetworkState() {}
391 void GetDnsConfig(DnsConfig* config) const {
392 base::AutoLock lock(lock_);
393 *config = dns_config_;
396 void SetDnsConfig(const DnsConfig& dns_config) {
397 base::AutoLock lock(lock_);
398 dns_config_ = dns_config;
401 private:
402 mutable base::Lock lock_;
403 DnsConfig dns_config_;
406 NetworkChangeNotifier::NetworkChangeCalculatorParams::
407 NetworkChangeCalculatorParams() {
410 // Calculates NetworkChange signal from IPAddress and ConnectionType signals.
411 class NetworkChangeNotifier::NetworkChangeCalculator
412 : public ConnectionTypeObserver,
413 public IPAddressObserver {
414 public:
415 NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
416 : params_(params),
417 have_announced_(false),
418 last_announced_connection_type_(CONNECTION_NONE),
419 pending_connection_type_(CONNECTION_NONE) {}
421 void Init() {
422 DCHECK(thread_checker_.CalledOnValidThread());
423 DCHECK(g_network_change_notifier);
424 AddConnectionTypeObserver(this);
425 AddIPAddressObserver(this);
428 ~NetworkChangeCalculator() override {
429 DCHECK(thread_checker_.CalledOnValidThread());
430 DCHECK(g_network_change_notifier);
431 RemoveConnectionTypeObserver(this);
432 RemoveIPAddressObserver(this);
435 // NetworkChangeNotifier::IPAddressObserver implementation.
436 void OnIPAddressChanged() override {
437 DCHECK(thread_checker_.CalledOnValidThread());
438 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
439 ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_;
440 // Cancels any previous timer.
441 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
444 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
445 void OnConnectionTypeChanged(ConnectionType type) override {
446 DCHECK(thread_checker_.CalledOnValidThread());
447 pending_connection_type_ = type;
448 base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
449 ? params_.connection_type_offline_delay_
450 : params_.connection_type_online_delay_;
451 // Cancels any previous timer.
452 timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
455 private:
456 void Notify() {
457 DCHECK(thread_checker_.CalledOnValidThread());
458 // Don't bother signaling about dead connections.
459 if (have_announced_ &&
460 (last_announced_connection_type_ == CONNECTION_NONE) &&
461 (pending_connection_type_ == CONNECTION_NONE)) {
462 return;
464 have_announced_ = true;
465 last_announced_connection_type_ = pending_connection_type_;
466 // Immediately before sending out an online signal, send out an offline
467 // signal to perform any destructive actions before constructive actions.
468 if (pending_connection_type_ != CONNECTION_NONE)
469 NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE);
470 NetworkChangeNotifier::NotifyObserversOfNetworkChange(
471 pending_connection_type_);
474 const NetworkChangeCalculatorParams params_;
476 // Indicates if NotifyObserversOfNetworkChange has been called yet.
477 bool have_announced_;
478 // Last value passed to NotifyObserversOfNetworkChange.
479 ConnectionType last_announced_connection_type_;
480 // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
481 ConnectionType pending_connection_type_;
482 // Used to delay notifications so duplicates can be combined.
483 base::OneShotTimer<NetworkChangeCalculator> timer_;
485 base::ThreadChecker thread_checker_;
487 DISALLOW_COPY_AND_ASSIGN(NetworkChangeCalculator);
490 NetworkChangeNotifier::~NetworkChangeNotifier() {
491 network_change_calculator_.reset();
492 DCHECK_EQ(this, g_network_change_notifier);
493 g_network_change_notifier = NULL;
496 // static
497 void NetworkChangeNotifier::SetFactory(
498 NetworkChangeNotifierFactory* factory) {
499 CHECK(!g_network_change_notifier_factory);
500 g_network_change_notifier_factory = factory;
503 // static
504 NetworkChangeNotifier* NetworkChangeNotifier::Create() {
505 if (g_network_change_notifier_factory)
506 return g_network_change_notifier_factory->CreateInstance();
508 #if defined(OS_WIN)
509 NetworkChangeNotifierWin* network_change_notifier =
510 new NetworkChangeNotifierWin();
511 network_change_notifier->WatchForAddressChange();
512 return network_change_notifier;
513 #elif defined(OS_CHROMEOS) || defined(OS_ANDROID)
514 // ChromeOS and Android builds MUST use their own class factory.
515 #if !defined(OS_CHROMEOS)
516 // TODO(oshima): ash_shell do not have access to chromeos'es
517 // notifier yet. Re-enable this when chromeos'es notifier moved to
518 // chromeos root directory. crbug.com/119298.
519 CHECK(false);
520 #endif
521 return NULL;
522 #elif defined(OS_LINUX)
523 return new NetworkChangeNotifierLinux(base::hash_set<std::string>());
524 #elif defined(OS_MACOSX)
525 return new NetworkChangeNotifierMac();
526 #else
527 NOTIMPLEMENTED();
528 return NULL;
529 #endif
532 // static
533 NetworkChangeNotifier::ConnectionType
534 NetworkChangeNotifier::GetConnectionType() {
535 return g_network_change_notifier ?
536 g_network_change_notifier->GetCurrentConnectionType() :
537 CONNECTION_UNKNOWN;
540 // static
541 double NetworkChangeNotifier::GetMaxBandwidth() {
542 return g_network_change_notifier ?
543 g_network_change_notifier->GetCurrentMaxBandwidth() :
544 std::numeric_limits<double>::infinity();
547 // static
548 void NetworkChangeNotifier::GetDnsConfig(DnsConfig* config) {
549 if (!g_network_change_notifier) {
550 *config = DnsConfig();
551 } else {
552 g_network_change_notifier->network_state_->GetDnsConfig(config);
556 // static
557 const char* NetworkChangeNotifier::ConnectionTypeToString(
558 ConnectionType type) {
559 static const char* const kConnectionTypeNames[] = {
560 "CONNECTION_UNKNOWN",
561 "CONNECTION_ETHERNET",
562 "CONNECTION_WIFI",
563 "CONNECTION_2G",
564 "CONNECTION_3G",
565 "CONNECTION_4G",
566 "CONNECTION_NONE",
567 "CONNECTION_BLUETOOTH"
569 static_assert(arraysize(kConnectionTypeNames) ==
570 NetworkChangeNotifier::CONNECTION_LAST + 1,
571 "ConnectionType name count should match");
572 if (type < CONNECTION_UNKNOWN || type > CONNECTION_LAST) {
573 NOTREACHED();
574 return "CONNECTION_INVALID";
576 return kConnectionTypeNames[type];
579 // static
580 void NetworkChangeNotifier::NotifyDataReceived(const URLRequest& request,
581 int bytes_read) {
582 if (!g_network_change_notifier ||
583 !g_network_change_notifier->histogram_watcher_) {
584 return;
586 g_network_change_notifier->histogram_watcher_->NotifyDataReceived(request,
587 bytes_read);
590 // static
591 void NetworkChangeNotifier::InitHistogramWatcher() {
592 if (!g_network_change_notifier)
593 return;
594 g_network_change_notifier->histogram_watcher_.reset(new HistogramWatcher());
595 g_network_change_notifier->histogram_watcher_->Init();
598 // static
599 void NetworkChangeNotifier::ShutdownHistogramWatcher() {
600 if (!g_network_change_notifier)
601 return;
602 g_network_change_notifier->histogram_watcher_.reset();
605 // static
606 void NetworkChangeNotifier::LogOperatorCodeHistogram(ConnectionType type) {
607 #if defined(OS_ANDROID)
608 // On a connection type change to 2/3/4G, log the network operator MCC/MNC.
609 // Log zero in other cases.
610 unsigned mcc_mnc = 0;
611 if (type == NetworkChangeNotifier::CONNECTION_2G ||
612 type == NetworkChangeNotifier::CONNECTION_3G ||
613 type == NetworkChangeNotifier::CONNECTION_4G) {
614 // Log zero if not perfectly converted.
615 if (!base::StringToUint(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::ConnectionType
659 NetworkChangeNotifier::ConnectionTypeFromInterfaceList(
660 const NetworkInterfaceList& interfaces) {
661 bool first = true;
662 ConnectionType result = CONNECTION_NONE;
663 for (size_t i = 0; i < interfaces.size(); ++i) {
664 #if defined(OS_WIN)
665 if (interfaces[i].friendly_name == "Teredo Tunneling Pseudo-Interface")
666 continue;
667 #endif
668 // Remove VMware network interfaces as they're internal and should not be
669 // used to determine the network connection type.
670 if (base::StringToLowerASCII(interfaces[i].friendly_name).find("vmnet") !=
671 std::string::npos) {
672 continue;
674 if (first) {
675 first = false;
676 result = interfaces[i].type;
677 } else if (result != interfaces[i].type) {
678 return CONNECTION_UNKNOWN;
681 return result;
684 // static
685 NetworkChangeNotifier* NetworkChangeNotifier::CreateMock() {
686 return new MockNetworkChangeNotifier();
689 void NetworkChangeNotifier::AddIPAddressObserver(IPAddressObserver* observer) {
690 if (g_network_change_notifier)
691 g_network_change_notifier->ip_address_observer_list_->AddObserver(observer);
694 void NetworkChangeNotifier::AddConnectionTypeObserver(
695 ConnectionTypeObserver* observer) {
696 if (g_network_change_notifier) {
697 g_network_change_notifier->connection_type_observer_list_->AddObserver(
698 observer);
702 void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) {
703 if (g_network_change_notifier) {
704 g_network_change_notifier->resolver_state_observer_list_->AddObserver(
705 observer);
709 void NetworkChangeNotifier::AddNetworkChangeObserver(
710 NetworkChangeObserver* observer) {
711 if (g_network_change_notifier) {
712 g_network_change_notifier->network_change_observer_list_->AddObserver(
713 observer);
717 void NetworkChangeNotifier::AddMaxBandwidthObserver(
718 MaxBandwidthObserver* observer) {
719 if (g_network_change_notifier) {
720 g_network_change_notifier->max_bandwidth_observer_list_->AddObserver(
721 observer);
725 void NetworkChangeNotifier::RemoveIPAddressObserver(
726 IPAddressObserver* observer) {
727 if (g_network_change_notifier) {
728 g_network_change_notifier->ip_address_observer_list_->RemoveObserver(
729 observer);
733 void NetworkChangeNotifier::RemoveConnectionTypeObserver(
734 ConnectionTypeObserver* observer) {
735 if (g_network_change_notifier) {
736 g_network_change_notifier->connection_type_observer_list_->RemoveObserver(
737 observer);
741 void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) {
742 if (g_network_change_notifier) {
743 g_network_change_notifier->resolver_state_observer_list_->RemoveObserver(
744 observer);
748 void NetworkChangeNotifier::RemoveNetworkChangeObserver(
749 NetworkChangeObserver* observer) {
750 if (g_network_change_notifier) {
751 g_network_change_notifier->network_change_observer_list_->RemoveObserver(
752 observer);
756 void NetworkChangeNotifier::RemoveMaxBandwidthObserver(
757 MaxBandwidthObserver* observer) {
758 if (g_network_change_notifier) {
759 g_network_change_notifier->max_bandwidth_observer_list_->RemoveObserver(
760 observer);
764 // static
765 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() {
766 if (g_network_change_notifier)
767 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
770 // static
771 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
772 ConnectionType type) {
773 if (g_network_change_notifier)
774 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(type);
777 // static
778 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
779 ConnectionType type) {
780 if (g_network_change_notifier)
781 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
784 // static
785 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests() {
786 if (g_network_change_notifier)
787 g_network_change_notifier->NotifyObserversOfInitialDNSConfigReadImpl();
790 // static
791 void NetworkChangeNotifier::SetTestNotificationsOnly(bool test_only) {
792 if (g_network_change_notifier)
793 g_network_change_notifier->test_notifications_only_ = test_only;
796 NetworkChangeNotifier::NetworkChangeNotifier(
797 const NetworkChangeCalculatorParams& params
798 /*= NetworkChangeCalculatorParams()*/)
799 : ip_address_observer_list_(
800 new base::ObserverListThreadSafe<IPAddressObserver>(
801 base::ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)),
802 connection_type_observer_list_(
803 new base::ObserverListThreadSafe<ConnectionTypeObserver>(
804 base::ObserverListBase<
805 ConnectionTypeObserver>::NOTIFY_EXISTING_ONLY)),
806 resolver_state_observer_list_(
807 new base::ObserverListThreadSafe<DNSObserver>(
808 base::ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)),
809 network_change_observer_list_(new base::ObserverListThreadSafe<
810 NetworkChangeObserver>(
811 base::ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)),
812 max_bandwidth_observer_list_(new base::ObserverListThreadSafe<
813 MaxBandwidthObserver>(
814 base::ObserverListBase<MaxBandwidthObserver>::NOTIFY_EXISTING_ONLY)),
815 network_state_(new NetworkState()),
816 network_change_calculator_(new NetworkChangeCalculator(params)),
817 test_notifications_only_(false) {
818 DCHECK(!g_network_change_notifier);
819 g_network_change_notifier = this;
820 network_change_calculator_->Init();
823 #if defined(OS_LINUX)
824 const internal::AddressTrackerLinux*
825 NetworkChangeNotifier::GetAddressTrackerInternal() const {
826 return NULL;
828 #endif
830 double NetworkChangeNotifier::GetCurrentMaxBandwidth() const {
831 // This default implementation conforms to the NetInfo V3 specification but
832 // should be overridden to provide specific bandwidth data based on the
833 // platform.
834 if (GetCurrentConnectionType() == CONNECTION_NONE)
835 return 0.0;
836 return std::numeric_limits<double>::infinity();
839 // static
840 double NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
841 ConnectionSubtype subtype) {
842 switch (subtype) {
843 case SUBTYPE_GSM:
844 return 0.01;
845 case SUBTYPE_IDEN:
846 return 0.064;
847 case SUBTYPE_CDMA:
848 return 0.115;
849 case SUBTYPE_1XRTT:
850 return 0.153;
851 case SUBTYPE_GPRS:
852 return 0.237;
853 case SUBTYPE_EDGE:
854 return 0.384;
855 case SUBTYPE_UMTS:
856 return 2.0;
857 case SUBTYPE_EVDO_REV_0:
858 return 2.46;
859 case SUBTYPE_EVDO_REV_A:
860 return 3.1;
861 case SUBTYPE_HSPA:
862 return 3.6;
863 case SUBTYPE_EVDO_REV_B:
864 return 14.7;
865 case SUBTYPE_HSDPA:
866 return 14.3;
867 case SUBTYPE_HSUPA:
868 return 14.4;
869 case SUBTYPE_EHRPD:
870 return 21.0;
871 case SUBTYPE_HSPAP:
872 return 42.0;
873 case SUBTYPE_LTE:
874 return 100.0;
875 case SUBTYPE_LTE_ADVANCED:
876 return 100.0;
877 case SUBTYPE_BLUETOOTH_1_2:
878 return 1.0;
879 case SUBTYPE_BLUETOOTH_2_1:
880 return 3.0;
881 case SUBTYPE_BLUETOOTH_3_0:
882 return 24.0;
883 case SUBTYPE_BLUETOOTH_4_0:
884 return 1.0;
885 case SUBTYPE_ETHERNET:
886 return 10.0;
887 case SUBTYPE_FAST_ETHERNET:
888 return 100.0;
889 case SUBTYPE_GIGABIT_ETHERNET:
890 return 1000.0;
891 case SUBTYPE_10_GIGABIT_ETHERNET:
892 return 10000.0;
893 case SUBTYPE_WIFI_B:
894 return 11.0;
895 case SUBTYPE_WIFI_G:
896 return 54.0;
897 case SUBTYPE_WIFI_N:
898 return 600.0;
899 case SUBTYPE_WIFI_AC:
900 return 1300.0;
901 case SUBTYPE_WIFI_AD:
902 return 7000.0;
903 case SUBTYPE_UNKNOWN:
904 return std::numeric_limits<double>::infinity();
905 case SUBTYPE_NONE:
906 return 0.0;
907 case SUBTYPE_OTHER:
908 return std::numeric_limits<double>::infinity();
910 NOTREACHED();
911 return std::numeric_limits<double>::infinity();
914 // static
915 void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() {
916 if (g_network_change_notifier &&
917 !g_network_change_notifier->test_notifications_only_) {
918 g_network_change_notifier->NotifyObserversOfIPAddressChangeImpl();
922 // static
923 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
924 if (g_network_change_notifier &&
925 !g_network_change_notifier->test_notifications_only_) {
926 g_network_change_notifier->NotifyObserversOfConnectionTypeChangeImpl(
927 GetConnectionType());
931 // static
932 void NetworkChangeNotifier::NotifyObserversOfNetworkChange(
933 ConnectionType type) {
934 if (g_network_change_notifier &&
935 !g_network_change_notifier->test_notifications_only_) {
936 g_network_change_notifier->NotifyObserversOfNetworkChangeImpl(type);
940 // static
941 void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(
942 double max_bandwidth_mbps) {
943 if (g_network_change_notifier &&
944 !g_network_change_notifier->test_notifications_only_) {
945 g_network_change_notifier->NotifyObserversOfMaxBandwidthChangeImpl(
946 max_bandwidth_mbps);
950 // static
951 void NetworkChangeNotifier::NotifyObserversOfDNSChange() {
952 if (g_network_change_notifier &&
953 !g_network_change_notifier->test_notifications_only_) {
954 g_network_change_notifier->NotifyObserversOfDNSChangeImpl();
958 // static
959 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigRead() {
960 if (g_network_change_notifier &&
961 !g_network_change_notifier->test_notifications_only_) {
962 g_network_change_notifier->NotifyObserversOfInitialDNSConfigReadImpl();
966 // static
967 void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) {
968 if (!g_network_change_notifier)
969 return;
970 g_network_change_notifier->network_state_->SetDnsConfig(config);
971 NotifyObserversOfDNSChange();
974 // static
975 void NetworkChangeNotifier::SetInitialDnsConfig(const DnsConfig& config) {
976 if (!g_network_change_notifier)
977 return;
978 #if DCHECK_IS_ON()
979 // Verify we've never received a valid DnsConfig previously.
980 DnsConfig old_config;
981 g_network_change_notifier->network_state_->GetDnsConfig(&old_config);
982 DCHECK(!old_config.IsValid());
983 #endif
984 g_network_change_notifier->network_state_->SetDnsConfig(config);
985 NotifyObserversOfInitialDNSConfigRead();
988 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() {
989 ip_address_observer_list_->Notify(FROM_HERE,
990 &IPAddressObserver::OnIPAddressChanged);
993 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl(
994 ConnectionType type) {
995 connection_type_observer_list_->Notify(
996 FROM_HERE, &ConnectionTypeObserver::OnConnectionTypeChanged, type);
999 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl(
1000 ConnectionType type) {
1001 network_change_observer_list_->Notify(
1002 FROM_HERE, &NetworkChangeObserver::OnNetworkChanged, type);
1005 void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() {
1006 resolver_state_observer_list_->Notify(FROM_HERE, &DNSObserver::OnDNSChanged);
1009 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadImpl() {
1010 resolver_state_observer_list_->Notify(FROM_HERE,
1011 &DNSObserver::OnInitialDNSConfigRead);
1014 void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeImpl(
1015 double max_bandwidth_mbps) {
1016 max_bandwidth_observer_list_->Notify(
1017 FROM_HERE, &MaxBandwidthObserver::OnMaxBandwidthChanged,
1018 max_bandwidth_mbps);
1021 NetworkChangeNotifier::DisableForTest::DisableForTest()
1022 : network_change_notifier_(g_network_change_notifier) {
1023 DCHECK(g_network_change_notifier);
1024 g_network_change_notifier = NULL;
1027 NetworkChangeNotifier::DisableForTest::~DisableForTest() {
1028 DCHECK(!g_network_change_notifier);
1029 g_network_change_notifier = network_change_notifier_;
1032 void NetworkChangeNotifier::DNSObserver::OnInitialDNSConfigRead() {
1035 } // namespace net