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"
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"
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"
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"
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
42 NetworkChangeNotifier
* g_network_change_notifier
= NULL
;
44 // Class factory singleton.
45 NetworkChangeNotifierFactory
* g_network_change_notifier_factory
= NULL
;
47 class MockNetworkChangeNotifier
: public NetworkChangeNotifier
{
49 ConnectionType
GetCurrentConnectionType() const override
{
50 return CONNECTION_UNKNOWN
;
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
{
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.
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_
);
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_
);
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_
);
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_
);
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_
);
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_
);
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_
);
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_
);
170 case NetworkChangeNotifier::CONNECTION_ETHERNET
:
171 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnEthernet",
172 peak_kbps_since_last_connection_change_
);
174 case NetworkChangeNotifier::CONNECTION_WIFI
:
175 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnWifi",
176 peak_kbps_since_last_connection_change_
);
178 case NetworkChangeNotifier::CONNECTION_2G
:
179 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn2G",
180 peak_kbps_since_last_connection_change_
);
182 case NetworkChangeNotifier::CONNECTION_3G
:
183 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn3G",
184 peak_kbps_since_last_connection_change_
);
186 case NetworkChangeNotifier::CONNECTION_4G
:
187 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOn4G",
188 peak_kbps_since_last_connection_change_
);
190 case NetworkChangeNotifier::CONNECTION_NONE
:
191 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnNone",
192 peak_kbps_since_last_connection_change_
);
194 case NetworkChangeNotifier::CONNECTION_BLUETOOTH
:
195 UMA_HISTOGRAM_COUNTS("NCN.CM.PeakKbpsOnBluetooth",
196 peak_kbps_since_last_connection_change_
);
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
);
205 case NetworkChangeNotifier::CONNECTION_ETHERNET
:
206 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnEthernet", state_duration
);
207 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnEthernet", kilobytes_read
);
209 case NetworkChangeNotifier::CONNECTION_WIFI
:
210 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnWifi", state_duration
);
211 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnWifi", kilobytes_read
);
213 case NetworkChangeNotifier::CONNECTION_2G
:
214 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn2G", state_duration
);
215 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn2G", kilobytes_read
);
217 case NetworkChangeNotifier::CONNECTION_3G
:
218 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn3G", state_duration
);
219 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn3G", kilobytes_read
);
221 case NetworkChangeNotifier::CONNECTION_4G
:
222 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOn4G", state_duration
);
223 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOn4G", kilobytes_read
);
225 case NetworkChangeNotifier::CONNECTION_NONE
:
226 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnNone", state_duration
);
227 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnNone", kilobytes_read
);
229 case NetworkChangeNotifier::CONNECTION_BLUETOOTH
:
230 UMA_HISTOGRAM_LONG_TIMES("NCN.CM.TimeOnBluetooth", state_duration
);
231 UMA_HISTOGRAM_COUNTS("NCN.CM.KBTransferedOnBluetooth", kilobytes_read
);
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_
);
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_
));
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()) {
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
)
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_
);
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
;
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
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
{
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
;
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
{
415 NetworkChangeCalculator(const NetworkChangeCalculatorParams
& params
)
417 have_announced_(false),
418 last_announced_connection_type_(CONNECTION_NONE
),
419 pending_connection_type_(CONNECTION_NONE
) {}
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
);
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
)) {
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
;
497 void NetworkChangeNotifier::SetFactory(
498 NetworkChangeNotifierFactory
* factory
) {
499 CHECK(!g_network_change_notifier_factory
);
500 g_network_change_notifier_factory
= factory
;
504 NetworkChangeNotifier
* NetworkChangeNotifier::Create() {
505 if (g_network_change_notifier_factory
)
506 return g_network_change_notifier_factory
->CreateInstance();
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.
522 #elif defined(OS_LINUX)
523 return new NetworkChangeNotifierLinux(base::hash_set
<std::string
>());
524 #elif defined(OS_MACOSX)
525 return new NetworkChangeNotifierMac();
533 NetworkChangeNotifier::ConnectionType
534 NetworkChangeNotifier::GetConnectionType() {
535 return g_network_change_notifier
?
536 g_network_change_notifier
->GetCurrentConnectionType() :
541 double NetworkChangeNotifier::GetMaxBandwidth() {
542 return g_network_change_notifier
?
543 g_network_change_notifier
->GetCurrentMaxBandwidth() :
544 std::numeric_limits
<double>::infinity();
548 void NetworkChangeNotifier::GetDnsConfig(DnsConfig
* config
) {
549 if (!g_network_change_notifier
) {
550 *config
= DnsConfig();
552 g_network_change_notifier
->network_state_
->GetDnsConfig(config
);
557 const char* NetworkChangeNotifier::ConnectionTypeToString(
558 ConnectionType type
) {
559 static const char* const kConnectionTypeNames
[] = {
560 "CONNECTION_UNKNOWN",
561 "CONNECTION_ETHERNET",
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
) {
574 return "CONNECTION_INVALID";
576 return kConnectionTypeNames
[type
];
580 void NetworkChangeNotifier::NotifyDataReceived(const URLRequest
& request
,
582 if (!g_network_change_notifier
||
583 !g_network_change_notifier
->histogram_watcher_
) {
586 g_network_change_notifier
->histogram_watcher_
->NotifyDataReceived(request
,
591 void NetworkChangeNotifier::InitHistogramWatcher() {
592 if (!g_network_change_notifier
)
594 g_network_change_notifier
->histogram_watcher_
.reset(new HistogramWatcher());
595 g_network_change_notifier
->histogram_watcher_
->Init();
599 void NetworkChangeNotifier::ShutdownHistogramWatcher() {
600 if (!g_network_change_notifier
)
602 g_network_change_notifier
->histogram_watcher_
.reset();
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
)) {
619 UMA_HISTOGRAM_SPARSE_SLOWLY("NCN.NetworkOperatorMCCMNC", mcc_mnc
);
623 #if defined(OS_LINUX)
625 const internal::AddressTrackerLinux
*
626 NetworkChangeNotifier::GetAddressTracker() {
627 return g_network_change_notifier
?
628 g_network_change_notifier
->GetAddressTrackerInternal() : NULL
;
633 bool NetworkChangeNotifier::IsOffline() {
634 return GetConnectionType() == CONNECTION_NONE
;
638 bool NetworkChangeNotifier::IsConnectionCellular(ConnectionType type
) {
639 bool is_cellular
= false;
646 case CONNECTION_UNKNOWN
:
647 case CONNECTION_ETHERNET
:
648 case CONNECTION_WIFI
:
649 case CONNECTION_NONE
:
650 case CONNECTION_BLUETOOTH
:
658 NetworkChangeNotifier::ConnectionType
659 NetworkChangeNotifier::ConnectionTypeFromInterfaceList(
660 const NetworkInterfaceList
& interfaces
) {
662 ConnectionType result
= CONNECTION_NONE
;
663 for (size_t i
= 0; i
< interfaces
.size(); ++i
) {
665 if (interfaces
[i
].friendly_name
== "Teredo Tunneling Pseudo-Interface")
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") !=
676 result
= interfaces
[i
].type
;
677 } else if (result
!= interfaces
[i
].type
) {
678 return CONNECTION_UNKNOWN
;
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(
702 void NetworkChangeNotifier::AddDNSObserver(DNSObserver
* observer
) {
703 if (g_network_change_notifier
) {
704 g_network_change_notifier
->resolver_state_observer_list_
->AddObserver(
709 void NetworkChangeNotifier::AddNetworkChangeObserver(
710 NetworkChangeObserver
* observer
) {
711 if (g_network_change_notifier
) {
712 g_network_change_notifier
->network_change_observer_list_
->AddObserver(
717 void NetworkChangeNotifier::AddMaxBandwidthObserver(
718 MaxBandwidthObserver
* observer
) {
719 if (g_network_change_notifier
) {
720 g_network_change_notifier
->max_bandwidth_observer_list_
->AddObserver(
725 void NetworkChangeNotifier::RemoveIPAddressObserver(
726 IPAddressObserver
* observer
) {
727 if (g_network_change_notifier
) {
728 g_network_change_notifier
->ip_address_observer_list_
->RemoveObserver(
733 void NetworkChangeNotifier::RemoveConnectionTypeObserver(
734 ConnectionTypeObserver
* observer
) {
735 if (g_network_change_notifier
) {
736 g_network_change_notifier
->connection_type_observer_list_
->RemoveObserver(
741 void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver
* observer
) {
742 if (g_network_change_notifier
) {
743 g_network_change_notifier
->resolver_state_observer_list_
->RemoveObserver(
748 void NetworkChangeNotifier::RemoveNetworkChangeObserver(
749 NetworkChangeObserver
* observer
) {
750 if (g_network_change_notifier
) {
751 g_network_change_notifier
->network_change_observer_list_
->RemoveObserver(
756 void NetworkChangeNotifier::RemoveMaxBandwidthObserver(
757 MaxBandwidthObserver
* observer
) {
758 if (g_network_change_notifier
) {
759 g_network_change_notifier
->max_bandwidth_observer_list_
->RemoveObserver(
765 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests() {
766 if (g_network_change_notifier
)
767 g_network_change_notifier
->NotifyObserversOfIPAddressChangeImpl();
771 void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
772 ConnectionType type
) {
773 if (g_network_change_notifier
)
774 g_network_change_notifier
->NotifyObserversOfConnectionTypeChangeImpl(type
);
778 void NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
779 ConnectionType type
) {
780 if (g_network_change_notifier
)
781 g_network_change_notifier
->NotifyObserversOfNetworkChangeImpl(type
);
785 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests() {
786 if (g_network_change_notifier
)
787 g_network_change_notifier
->NotifyObserversOfInitialDNSConfigReadImpl();
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 {
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
834 if (GetCurrentConnectionType() == CONNECTION_NONE
)
836 return std::numeric_limits
<double>::infinity();
840 double NetworkChangeNotifier::GetMaxBandwidthForConnectionSubtype(
841 ConnectionSubtype subtype
) {
857 case SUBTYPE_EVDO_REV_0
:
859 case SUBTYPE_EVDO_REV_A
:
863 case SUBTYPE_EVDO_REV_B
:
875 case SUBTYPE_LTE_ADVANCED
:
877 case SUBTYPE_BLUETOOTH_1_2
:
879 case SUBTYPE_BLUETOOTH_2_1
:
881 case SUBTYPE_BLUETOOTH_3_0
:
883 case SUBTYPE_BLUETOOTH_4_0
:
885 case SUBTYPE_ETHERNET
:
887 case SUBTYPE_FAST_ETHERNET
:
889 case SUBTYPE_GIGABIT_ETHERNET
:
891 case SUBTYPE_10_GIGABIT_ETHERNET
:
899 case SUBTYPE_WIFI_AC
:
901 case SUBTYPE_WIFI_AD
:
903 case SUBTYPE_UNKNOWN
:
904 return std::numeric_limits
<double>::infinity();
908 return std::numeric_limits
<double>::infinity();
911 return std::numeric_limits
<double>::infinity();
915 void NetworkChangeNotifier::NotifyObserversOfIPAddressChange() {
916 if (g_network_change_notifier
&&
917 !g_network_change_notifier
->test_notifications_only_
) {
918 g_network_change_notifier
->NotifyObserversOfIPAddressChangeImpl();
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());
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
);
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(
951 void NetworkChangeNotifier::NotifyObserversOfDNSChange() {
952 if (g_network_change_notifier
&&
953 !g_network_change_notifier
->test_notifications_only_
) {
954 g_network_change_notifier
->NotifyObserversOfDNSChangeImpl();
959 void NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigRead() {
960 if (g_network_change_notifier
&&
961 !g_network_change_notifier
->test_notifications_only_
) {
962 g_network_change_notifier
->NotifyObserversOfInitialDNSConfigReadImpl();
967 void NetworkChangeNotifier::SetDnsConfig(const DnsConfig
& config
) {
968 if (!g_network_change_notifier
)
970 g_network_change_notifier
->network_state_
->SetDnsConfig(config
);
971 NotifyObserversOfDNSChange();
975 void NetworkChangeNotifier::SetInitialDnsConfig(const DnsConfig
& config
) {
976 if (!g_network_change_notifier
)
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());
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() {