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 #ifndef NET_BASE_NETWORK_CHANGE_NOTIFIER_H_
6 #define NET_BASE_NETWORK_CHANGE_NOTIFIER_H_
10 #include "base/basictypes.h"
11 #include "base/observer_list_threadsafe.h"
12 #include "base/time/time.h"
13 #include "net/base/net_export.h"
20 class HistogramWatcher
;
21 class NetworkChangeNotifierFactory
;
22 struct NetworkInterface
;
23 typedef std::vector
<NetworkInterface
> NetworkInterfaceList
;
28 class AddressTrackerLinux
;
32 // NetworkChangeNotifier monitors the system for network changes, and notifies
33 // registered observers of those events. Observers may register on any thread,
34 // and will be called back on the thread from which they registered.
35 // NetworkChangeNotifiers are threadsafe, though they must be created and
36 // destroyed on the same thread.
37 class NET_EXPORT NetworkChangeNotifier
{
39 // This is a superset of the connection types in the NetInfo v3 specification:
40 // http://w3c.github.io/netinfo/.
42 // A Java counterpart will be generated for this enum.
43 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net
45 // New enum values should only be added to the end of the enum and no values
46 // should be modified or reused, as this is reported via UMA.
48 CONNECTION_UNKNOWN
= 0, // A connection exists, but its type is unknown.
49 // Also used as a default value.
50 CONNECTION_ETHERNET
= 1,
55 CONNECTION_NONE
= 6, // No connection.
56 CONNECTION_BLUETOOTH
= 7,
57 CONNECTION_LAST
= CONNECTION_BLUETOOTH
60 // This is the NetInfo v3 set of connection technologies as seen in
61 // http://w3c.github.io/netinfo/. This enum is copied in
62 // NetworkChangeNotifier.java so be sure to change both at once.
64 // A Java counterpart will be generated for this enum.
65 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net
66 enum ConnectionSubtype
{
84 SUBTYPE_BLUETOOTH_1_2
,
85 SUBTYPE_BLUETOOTH_2_1
,
86 SUBTYPE_BLUETOOTH_3_0
,
87 SUBTYPE_BLUETOOTH_4_0
,
89 SUBTYPE_FAST_ETHERNET
,
90 SUBTYPE_GIGABIT_ETHERNET
,
91 SUBTYPE_10_GIGABIT_ETHERNET
,
100 SUBTYPE_LAST
= SUBTYPE_OTHER
103 class NET_EXPORT IPAddressObserver
{
105 // Will be called when the IP address of the primary interface changes.
106 // This includes when the primary interface itself changes.
107 virtual void OnIPAddressChanged() = 0;
110 IPAddressObserver() {}
111 virtual ~IPAddressObserver() {}
114 DISALLOW_COPY_AND_ASSIGN(IPAddressObserver
);
117 class NET_EXPORT ConnectionTypeObserver
{
119 // Will be called when the connection type of the system has changed.
120 // See NetworkChangeNotifier::GetConnectionType() for important caveats
121 // about the unreliability of using this signal to infer the ability to
122 // reach remote sites.
123 virtual void OnConnectionTypeChanged(ConnectionType type
) = 0;
126 ConnectionTypeObserver() {}
127 virtual ~ConnectionTypeObserver() {}
130 DISALLOW_COPY_AND_ASSIGN(ConnectionTypeObserver
);
133 class NET_EXPORT DNSObserver
{
135 // Will be called when the DNS settings of the system may have changed.
136 // Use GetDnsConfig to obtain the current settings.
137 virtual void OnDNSChanged() = 0;
138 // Will be called when DNS settings of the system have been loaded.
139 // Use GetDnsConfig to obtain the current settings.
140 virtual void OnInitialDNSConfigRead();
144 virtual ~DNSObserver() {}
147 DISALLOW_COPY_AND_ASSIGN(DNSObserver
);
150 class NET_EXPORT NetworkChangeObserver
{
152 // OnNetworkChanged will be called when a change occurs to the host
153 // computer's hardware or software that affects the route network packets
154 // take to any network server. Some examples:
155 // 1. A network connection becoming available or going away. For example
156 // plugging or unplugging an Ethernet cable, WiFi or cellular modem
157 // connecting or disconnecting from a network, or a VPN tunnel being
158 // established or taken down.
159 // 2. An active network connection's IP address changes.
160 // 3. A change to the local IP routing tables.
161 // The signal shall only be produced when the change is complete. For
162 // example if a new network connection has become available, only give the
163 // signal once we think the O/S has finished establishing the connection
164 // (i.e. DHCP is done) to the point where the new connection is usable.
165 // The signal shall not be produced spuriously as it will be triggering some
166 // expensive operations, like socket pools closing all connections and
167 // sockets and then re-establishing them.
168 // |type| indicates the type of the active primary network connection after
169 // the change. Observers performing "constructive" activities like trying
170 // to establish a connection to a server should only do so when
171 // |type != CONNECTION_NONE|. Observers performing "destructive" activities
172 // like resetting already established server connections should only do so
173 // when |type == CONNECTION_NONE|. OnNetworkChanged will always be called
174 // with CONNECTION_NONE immediately prior to being called with an online
175 // state; this is done to make sure that destructive actions take place
176 // prior to constructive actions.
177 virtual void OnNetworkChanged(ConnectionType type
) = 0;
180 NetworkChangeObserver() {}
181 virtual ~NetworkChangeObserver() {}
184 DISALLOW_COPY_AND_ASSIGN(NetworkChangeObserver
);
187 class NET_EXPORT MaxBandwidthObserver
{
189 // Called when a change occurs to the network's maximum bandwidth as
190 // defined in http://w3c.github.io/netinfo/. Also called on type change,
191 // even if the maximum bandwidth doesn't change. See the documentation of
192 // GetMaxBanwidthAndConnectionType for what to expect for the values of
193 // |max_bandwidth_mbps|.
194 virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps
,
195 ConnectionType type
) = 0;
198 MaxBandwidthObserver() {}
199 virtual ~MaxBandwidthObserver() {}
202 DISALLOW_COPY_AND_ASSIGN(MaxBandwidthObserver
);
205 virtual ~NetworkChangeNotifier();
207 // See the description of NetworkChangeNotifier::GetConnectionType().
208 // Implementations must be thread-safe. Implementations must also be
209 // cheap as it is called often.
210 virtual ConnectionType
GetCurrentConnectionType() const = 0;
212 // Replaces the default class factory instance of NetworkChangeNotifier class.
213 // The method will take over the ownership of |factory| object.
214 static void SetFactory(NetworkChangeNotifierFactory
* factory
);
216 // Creates the process-wide, platform-specific NetworkChangeNotifier. The
217 // caller owns the returned pointer. You may call this on any thread. You
218 // may also avoid creating this entirely (in which case nothing will be
219 // monitored), but if you do create it, you must do so before any other
220 // threads try to access the API below, and it must outlive all other threads
221 // which might try to use it.
222 static NetworkChangeNotifier
* Create();
224 // Returns the connection type.
225 // A return value of |CONNECTION_NONE| is a pretty strong indicator that the
226 // user won't be able to connect to remote sites. However, another return
227 // value doesn't imply that the user will be able to connect to remote sites;
228 // even if some link is up, it is uncertain whether a particular connection
229 // attempt to a particular remote site will be successful.
230 // The returned value only describes the connection currently used by the
231 // device, and does not take into account other machines on the network. For
232 // example, if the device is connected using Wifi to a 3G gateway to access
233 // the internet, the connection type is CONNECTION_WIFI.
234 static ConnectionType
GetConnectionType();
236 // Sets |max_bandwidth_mbps| to a theoretical upper limit on download
237 // bandwidth, potentially based on underlying connection type, signal
238 // strength, or some other signal. If the network subtype is unknown then
239 // |max_bandwidth_mbps| is set to +Infinity and if there is no network
240 // connection then it is set to 0.0. The circumstances in which a more
241 // specific value is given are: when an Android device is connected to a
242 // cellular or WiFi network, and when a ChromeOS device is connected to a
243 // cellular network. See the NetInfo spec for the mapping of
244 // specific subtypes to bandwidth values: http://w3c.github.io/netinfo/.
245 // |connection_type| is set to the current active default network's connection
247 static void GetMaxBandwidthAndConnectionType(double* max_bandwidth_mbps
,
248 ConnectionType
* connection_type
);
250 // Returns a theoretical upper limit (in Mbps) on download bandwidth given a
251 // connection subtype. The mapping of connection type to maximum bandwidth is
252 // provided in the NetInfo spec: http://w3c.github.io/netinfo/.
253 // TODO(jkarlin): Rename to GetMaxBandwidthMbpsForConnectionSubtype.
254 static double GetMaxBandwidthForConnectionSubtype(ConnectionSubtype subtype
);
256 // Retrieve the last read DnsConfig. This could be expensive if the system has
257 // a large HOSTS file.
258 static void GetDnsConfig(DnsConfig
* config
);
260 #if defined(OS_LINUX)
261 // Returns the AddressTrackerLinux if present.
262 static const internal::AddressTrackerLinux
* GetAddressTracker();
265 // Convenience method to determine if the user is offline.
266 // Returns true if there is currently no internet connection.
268 // A return value of |true| is a pretty strong indicator that the user
269 // won't be able to connect to remote sites. However, a return value of
270 // |false| is inconclusive; even if some link is up, it is uncertain
271 // whether a particular connection attempt to a particular remote site
272 // will be successfully.
273 static bool IsOffline();
275 // Returns true if |type| is a cellular connection.
276 // Returns false if |type| is CONNECTION_UNKNOWN, and thus, depending on the
277 // implementation of GetConnectionType(), it is possible that
278 // IsConnectionCellular(GetConnectionType()) returns false even if the
279 // current connection is cellular.
280 static bool IsConnectionCellular(ConnectionType type
);
282 // Gets the current connection type based on |interfaces|. Returns
283 // CONNECTION_NONE if there are no interfaces, CONNECTION_UNKNOWN if two
284 // interfaces have different connection types or the connection type of all
285 // interfaces if they have the same interface type.
286 static ConnectionType
ConnectionTypeFromInterfaceList(
287 const NetworkInterfaceList
& interfaces
);
289 // Like Create(), but for use in tests. The mock object doesn't monitor any
290 // events, it merely rebroadcasts notifications when requested.
291 static NetworkChangeNotifier
* CreateMock();
293 // Registers |observer| to receive notifications of network changes. The
294 // thread on which this is called is the thread on which |observer| will be
295 // called back with notifications. This is safe to call if Create() has not
296 // been called (as long as it doesn't race the Create() call on another
297 // thread), in which case it will simply do nothing.
298 static void AddIPAddressObserver(IPAddressObserver
* observer
);
299 static void AddConnectionTypeObserver(ConnectionTypeObserver
* observer
);
300 static void AddDNSObserver(DNSObserver
* observer
);
301 static void AddNetworkChangeObserver(NetworkChangeObserver
* observer
);
302 static void AddMaxBandwidthObserver(MaxBandwidthObserver
* observer
);
304 // Unregisters |observer| from receiving notifications. This must be called
305 // on the same thread on which AddObserver() was called. Like AddObserver(),
306 // this is safe to call if Create() has not been called (as long as it doesn't
307 // race the Create() call on another thread), in which case it will simply do
308 // nothing. Technically, it's also safe to call after the notifier object has
309 // been destroyed, if the call doesn't race the notifier's destruction, but
310 // there's no reason to use the API in this risky way, so don't do it.
311 static void RemoveIPAddressObserver(IPAddressObserver
* observer
);
312 static void RemoveConnectionTypeObserver(ConnectionTypeObserver
* observer
);
313 static void RemoveDNSObserver(DNSObserver
* observer
);
314 static void RemoveNetworkChangeObserver(NetworkChangeObserver
* observer
);
315 static void RemoveMaxBandwidthObserver(MaxBandwidthObserver
* observer
);
317 // Allow unit tests to trigger notifications.
318 static void NotifyObserversOfIPAddressChangeForTests();
319 static void NotifyObserversOfConnectionTypeChangeForTests(
320 ConnectionType type
);
321 static void NotifyObserversOfNetworkChangeForTests(ConnectionType type
);
322 static void NotifyObserversOfInitialDNSConfigReadForTests();
323 static void NotifyObserversOfMaxBandwidthChangeForTests(
324 double max_bandwidth_mbps
,
325 ConnectionType type
);
327 // Enable or disable notifications from the host. After setting to true, be
328 // sure to pump the RunLoop until idle to finish any preexisting
329 // notifications. To use this, it must must be called before a
330 // NetworkChangeNotifier is created.
331 static void SetTestNotificationsOnly(bool test_only
);
333 // Return a string equivalent to |type|.
334 static const char* ConnectionTypeToString(ConnectionType type
);
336 // Let the NetworkChangeNotifier know we received some data.
337 // This is used for producing histogram data about the accuracy of
338 // the NetworkChangenotifier's online detection and rough network
339 // connection measurements.
340 static void NotifyDataReceived(const URLRequest
& request
, int bytes_read
);
342 // Register the Observer callbacks for producing histogram data. This
343 // should be called from the network thread to avoid race conditions.
344 // ShutdownHistogramWatcher() must be called prior to NetworkChangeNotifier
346 static void InitHistogramWatcher();
348 // Unregister the Observer callbacks for producing histogram data. This
349 // should be called from the network thread to avoid race conditions.
350 static void ShutdownHistogramWatcher();
352 // Log the |NCN.NetworkOperatorMCCMNC| histogram.
353 static void LogOperatorCodeHistogram(ConnectionType type
);
355 // Allows a second NetworkChangeNotifier to be created for unit testing, so
356 // the test suite can create a MockNetworkChangeNotifier, but platform
357 // specific NetworkChangeNotifiers can also be created for testing. To use,
358 // create an DisableForTest object, and then create the new
359 // NetworkChangeNotifier object. The NetworkChangeNotifier must be
360 // destroyed before the DisableForTest object, as its destruction will restore
361 // the original NetworkChangeNotifier.
362 class NET_EXPORT DisableForTest
{
368 // The original NetworkChangeNotifier to be restored on destruction.
369 NetworkChangeNotifier
* network_change_notifier_
;
373 // NetworkChanged signal is calculated from the IPAddressChanged and
374 // ConnectionTypeChanged signals. Delay parameters control how long to delay
375 // producing NetworkChanged signal after particular input signals so as to
376 // combine duplicates. In other words if an input signal is repeated within
377 // the corresponding delay period, only one resulting NetworkChange signal is
379 struct NET_EXPORT NetworkChangeCalculatorParams
{
380 NetworkChangeCalculatorParams();
381 // Controls delay after OnIPAddressChanged when transitioning from an
383 base::TimeDelta ip_address_offline_delay_
;
384 // Controls delay after OnIPAddressChanged when transitioning from an
386 base::TimeDelta ip_address_online_delay_
;
387 // Controls delay after OnConnectionTypeChanged when transitioning from an
389 base::TimeDelta connection_type_offline_delay_
;
390 // Controls delay after OnConnectionTypeChanged when transitioning from an
392 base::TimeDelta connection_type_online_delay_
;
395 explicit NetworkChangeNotifier(
396 const NetworkChangeCalculatorParams
& params
=
397 NetworkChangeCalculatorParams());
399 #if defined(OS_LINUX)
400 // Returns the AddressTrackerLinux if present.
401 // TODO(szym): Retrieve AddressMap from NetworkState. http://crbug.com/144212
402 virtual const internal::AddressTrackerLinux
*
403 GetAddressTrackerInternal() const;
406 // See the description of NetworkChangeNotifier::GetMaxBandwidth().
407 // Implementations must be thread-safe. Implementations must also be
408 // cheap as it is called often.
409 virtual void GetCurrentMaxBandwidthAndConnectionType(
410 double* max_bandwidth_mbps
,
411 ConnectionType
* connection_type
) const;
413 // Broadcasts a notification to all registered observers. Note that this
414 // happens asynchronously, even for observers on the current thread, even in
416 static void NotifyObserversOfIPAddressChange();
417 static void NotifyObserversOfConnectionTypeChange();
418 static void NotifyObserversOfDNSChange();
419 static void NotifyObserversOfInitialDNSConfigRead();
420 static void NotifyObserversOfNetworkChange(ConnectionType type
);
421 static void NotifyObserversOfMaxBandwidthChange(double max_bandwidth_mbps
,
422 ConnectionType type
);
424 // Stores |config| in NetworkState and notifies OnDNSChanged observers.
425 static void SetDnsConfig(const DnsConfig
& config
);
426 // Stores |config| in NetworkState and notifies OnInitialDNSConfigRead
428 static void SetInitialDnsConfig(const DnsConfig
& config
);
431 friend class HostResolverImplDnsTest
;
432 friend class NetworkChangeNotifierAndroidTest
;
433 friend class NetworkChangeNotifierLinuxTest
;
434 friend class NetworkChangeNotifierWinTest
;
437 class NetworkChangeCalculator
;
439 void NotifyObserversOfIPAddressChangeImpl();
440 void NotifyObserversOfConnectionTypeChangeImpl(ConnectionType type
);
441 void NotifyObserversOfDNSChangeImpl();
442 void NotifyObserversOfInitialDNSConfigReadImpl();
443 void NotifyObserversOfNetworkChangeImpl(ConnectionType type
);
444 void NotifyObserversOfMaxBandwidthChangeImpl(double max_bandwidth_mbps
,
445 ConnectionType type
);
447 const scoped_refptr
<base::ObserverListThreadSafe
<IPAddressObserver
>>
448 ip_address_observer_list_
;
449 const scoped_refptr
<base::ObserverListThreadSafe
<ConnectionTypeObserver
>>
450 connection_type_observer_list_
;
451 const scoped_refptr
<base::ObserverListThreadSafe
<DNSObserver
>>
452 resolver_state_observer_list_
;
453 const scoped_refptr
<base::ObserverListThreadSafe
<NetworkChangeObserver
>>
454 network_change_observer_list_
;
455 const scoped_refptr
<base::ObserverListThreadSafe
<MaxBandwidthObserver
>>
456 max_bandwidth_observer_list_
;
458 // The current network state. Hosts DnsConfig, exposed via GetDnsConfig.
459 scoped_ptr
<NetworkState
> network_state_
;
461 // A little-piggy-back observer that simply logs UMA histogram data.
462 scoped_ptr
<HistogramWatcher
> histogram_watcher_
;
464 // Computes NetworkChange signal from IPAddress and ConnectionType signals.
465 scoped_ptr
<NetworkChangeCalculator
> network_change_calculator_
;
467 // Set true to disable non-test notifications (to prevent flakes in tests).
468 static bool test_notifications_only_
;
470 DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier
);
475 #endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_H_