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 // Will be called when a change occurs to the network's maximum bandwidth as
190 // defined in http://w3c.github.io/netinfo/. Generally this will only be
191 // called on bandwidth changing network connection/disconnection events.
192 // Some platforms may call it more frequently, such as when WiFi signal
194 // TODO(jkarlin): This is currently only implemented for Android. Implement
195 // on every platform.
196 virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps
) = 0;
199 MaxBandwidthObserver() {}
200 virtual ~MaxBandwidthObserver() {}
203 DISALLOW_COPY_AND_ASSIGN(MaxBandwidthObserver
);
206 virtual ~NetworkChangeNotifier();
208 // See the description of NetworkChangeNotifier::GetConnectionType().
209 // Implementations must be thread-safe. Implementations must also be
210 // cheap as it is called often.
211 virtual ConnectionType
GetCurrentConnectionType() const = 0;
213 // Replaces the default class factory instance of NetworkChangeNotifier class.
214 // The method will take over the ownership of |factory| object.
215 static void SetFactory(NetworkChangeNotifierFactory
* factory
);
217 // Creates the process-wide, platform-specific NetworkChangeNotifier. The
218 // caller owns the returned pointer. You may call this on any thread. You
219 // may also avoid creating this entirely (in which case nothing will be
220 // monitored), but if you do create it, you must do so before any other
221 // threads try to access the API below, and it must outlive all other threads
222 // which might try to use it.
223 static NetworkChangeNotifier
* Create();
225 // Returns the connection type.
226 // A return value of |CONNECTION_NONE| is a pretty strong indicator that the
227 // user won't be able to connect to remote sites. However, another return
228 // value doesn't imply that the user will be able to connect to remote sites;
229 // even if some link is up, it is uncertain whether a particular connection
230 // attempt to a particular remote site will be successful.
231 // The returned value only describes the connection currently used by the
232 // device, and does not take into account other machines on the network. For
233 // example, if the device is connected using Wifi to a 3G gateway to access
234 // the internet, the connection type is CONNECTION_WIFI.
235 static ConnectionType
GetConnectionType();
237 // Returns a theoretical upper limit on download bandwidth, potentially based
238 // on underlying connection type, signal strength, or some other signal. The
239 // default mapping of connection type to maximum bandwidth is provided in the
240 // NetInfo spec: http://w3c.github.io/netinfo/. Host-specific application
241 // permissions may be required, please see host-specific declaration for more
243 static double GetMaxBandwidth();
245 // Retrieve the last read DnsConfig. This could be expensive if the system has
246 // a large HOSTS file.
247 static void GetDnsConfig(DnsConfig
* config
);
249 #if defined(OS_LINUX)
250 // Returns the AddressTrackerLinux if present.
251 static const internal::AddressTrackerLinux
* GetAddressTracker();
254 // Convenience method to determine if the user is offline.
255 // Returns true if there is currently no internet connection.
257 // A return value of |true| is a pretty strong indicator that the user
258 // won't be able to connect to remote sites. However, a return value of
259 // |false| is inconclusive; even if some link is up, it is uncertain
260 // whether a particular connection attempt to a particular remote site
261 // will be successfully.
262 static bool IsOffline();
264 // Returns true if |type| is a cellular connection.
265 // Returns false if |type| is CONNECTION_UNKNOWN, and thus, depending on the
266 // implementation of GetConnectionType(), it is possible that
267 // IsConnectionCellular(GetConnectionType()) returns false even if the
268 // current connection is cellular.
269 static bool IsConnectionCellular(ConnectionType type
);
271 // Gets the current connection type based on |interfaces|. Returns
272 // CONNECTION_NONE if there are no interfaces, CONNECTION_UNKNOWN if two
273 // interfaces have different connection types or the connection type of all
274 // interfaces if they have the same interface type.
275 static ConnectionType
ConnectionTypeFromInterfaceList(
276 const NetworkInterfaceList
& interfaces
);
278 // Like Create(), but for use in tests. The mock object doesn't monitor any
279 // events, it merely rebroadcasts notifications when requested.
280 static NetworkChangeNotifier
* CreateMock();
282 // Registers |observer| to receive notifications of network changes. The
283 // thread on which this is called is the thread on which |observer| will be
284 // called back with notifications. This is safe to call if Create() has not
285 // been called (as long as it doesn't race the Create() call on another
286 // thread), in which case it will simply do nothing.
287 static void AddIPAddressObserver(IPAddressObserver
* observer
);
288 static void AddConnectionTypeObserver(ConnectionTypeObserver
* observer
);
289 static void AddDNSObserver(DNSObserver
* observer
);
290 static void AddNetworkChangeObserver(NetworkChangeObserver
* observer
);
291 static void AddMaxBandwidthObserver(MaxBandwidthObserver
* observer
);
293 // Unregisters |observer| from receiving notifications. This must be called
294 // on the same thread on which AddObserver() was called. Like AddObserver(),
295 // this is safe to call if Create() has not been called (as long as it doesn't
296 // race the Create() call on another thread), in which case it will simply do
297 // nothing. Technically, it's also safe to call after the notifier object has
298 // been destroyed, if the call doesn't race the notifier's destruction, but
299 // there's no reason to use the API in this risky way, so don't do it.
300 static void RemoveIPAddressObserver(IPAddressObserver
* observer
);
301 static void RemoveConnectionTypeObserver(ConnectionTypeObserver
* observer
);
302 static void RemoveDNSObserver(DNSObserver
* observer
);
303 static void RemoveNetworkChangeObserver(NetworkChangeObserver
* observer
);
304 static void RemoveMaxBandwidthObserver(MaxBandwidthObserver
* observer
);
306 // Allow unit tests to trigger notifications.
307 static void NotifyObserversOfIPAddressChangeForTests();
308 static void NotifyObserversOfConnectionTypeChangeForTests(
309 ConnectionType type
);
310 static void NotifyObserversOfNetworkChangeForTests(ConnectionType type
);
311 static void NotifyObserversOfInitialDNSConfigReadForTests();
313 // Enable or disable notifications from the host. After setting to true, be
314 // sure to pump the RunLoop until idle to finish any preexisting
315 // notifications. To use this, it must must be called before a
316 // NetworkChangeNotifier is created.
317 static void SetTestNotificationsOnly(bool test_only
);
319 // Return a string equivalent to |type|.
320 static const char* ConnectionTypeToString(ConnectionType type
);
322 // Let the NetworkChangeNotifier know we received some data.
323 // This is used for producing histogram data about the accuracy of
324 // the NetworkChangenotifier's online detection and rough network
325 // connection measurements.
326 static void NotifyDataReceived(const URLRequest
& request
, int bytes_read
);
328 // Register the Observer callbacks for producing histogram data. This
329 // should be called from the network thread to avoid race conditions.
330 // ShutdownHistogramWatcher() must be called prior to NetworkChangeNotifier
332 static void InitHistogramWatcher();
334 // Unregister the Observer callbacks for producing histogram data. This
335 // should be called from the network thread to avoid race conditions.
336 static void ShutdownHistogramWatcher();
338 // Log the |NCN.NetworkOperatorMCCMNC| histogram.
339 static void LogOperatorCodeHistogram(ConnectionType type
);
341 // Allows a second NetworkChangeNotifier to be created for unit testing, so
342 // the test suite can create a MockNetworkChangeNotifier, but platform
343 // specific NetworkChangeNotifiers can also be created for testing. To use,
344 // create an DisableForTest object, and then create the new
345 // NetworkChangeNotifier object. The NetworkChangeNotifier must be
346 // destroyed before the DisableForTest object, as its destruction will restore
347 // the original NetworkChangeNotifier.
348 class NET_EXPORT DisableForTest
{
354 // The original NetworkChangeNotifier to be restored on destruction.
355 NetworkChangeNotifier
* network_change_notifier_
;
359 // NetworkChanged signal is calculated from the IPAddressChanged and
360 // ConnectionTypeChanged signals. Delay parameters control how long to delay
361 // producing NetworkChanged signal after particular input signals so as to
362 // combine duplicates. In other words if an input signal is repeated within
363 // the corresponding delay period, only one resulting NetworkChange signal is
365 struct NET_EXPORT NetworkChangeCalculatorParams
{
366 NetworkChangeCalculatorParams();
367 // Controls delay after OnIPAddressChanged when transitioning from an
369 base::TimeDelta ip_address_offline_delay_
;
370 // Controls delay after OnIPAddressChanged when transitioning from an
372 base::TimeDelta ip_address_online_delay_
;
373 // Controls delay after OnConnectionTypeChanged when transitioning from an
375 base::TimeDelta connection_type_offline_delay_
;
376 // Controls delay after OnConnectionTypeChanged when transitioning from an
378 base::TimeDelta connection_type_online_delay_
;
381 explicit NetworkChangeNotifier(
382 const NetworkChangeCalculatorParams
& params
=
383 NetworkChangeCalculatorParams());
385 #if defined(OS_LINUX)
386 // Returns the AddressTrackerLinux if present.
387 // TODO(szym): Retrieve AddressMap from NetworkState. http://crbug.com/144212
388 virtual const internal::AddressTrackerLinux
*
389 GetAddressTrackerInternal() const;
392 // See the description of NetworkChangeNotifier::GetMaxBandwidth().
393 // Implementations must be thread-safe. Implementations must also be
394 // cheap as it is called often.
395 virtual double GetCurrentMaxBandwidth() const;
397 // Returns a theoretical upper limit on download bandwidth given a connection
398 // subtype. The mapping of connection type to maximum bandwidth is provided in
399 // the NetInfo spec: http://w3c.github.io/netinfo/.
400 static double GetMaxBandwidthForConnectionSubtype(ConnectionSubtype subtype
);
402 // Broadcasts a notification to all registered observers. Note that this
403 // happens asynchronously, even for observers on the current thread, even in
405 static void NotifyObserversOfIPAddressChange();
406 static void NotifyObserversOfConnectionTypeChange();
407 static void NotifyObserversOfDNSChange();
408 static void NotifyObserversOfInitialDNSConfigRead();
409 static void NotifyObserversOfNetworkChange(ConnectionType type
);
410 static void NotifyObserversOfMaxBandwidthChange(double max_bandwidth_mbps
);
412 // Stores |config| in NetworkState and notifies OnDNSChanged observers.
413 static void SetDnsConfig(const DnsConfig
& config
);
414 // Stores |config| in NetworkState and notifies OnInitialDNSConfigRead
416 static void SetInitialDnsConfig(const DnsConfig
& config
);
419 friend class HostResolverImplDnsTest
;
420 friend class NetworkChangeNotifierAndroidTest
;
421 friend class NetworkChangeNotifierLinuxTest
;
422 friend class NetworkChangeNotifierWinTest
;
425 class NetworkChangeCalculator
;
427 void NotifyObserversOfIPAddressChangeImpl();
428 void NotifyObserversOfConnectionTypeChangeImpl(ConnectionType type
);
429 void NotifyObserversOfDNSChangeImpl();
430 void NotifyObserversOfInitialDNSConfigReadImpl();
431 void NotifyObserversOfNetworkChangeImpl(ConnectionType type
);
432 void NotifyObserversOfMaxBandwidthChangeImpl(double max_bandwidth_mbps
);
434 const scoped_refptr
<base::ObserverListThreadSafe
<IPAddressObserver
>>
435 ip_address_observer_list_
;
436 const scoped_refptr
<base::ObserverListThreadSafe
<ConnectionTypeObserver
>>
437 connection_type_observer_list_
;
438 const scoped_refptr
<base::ObserverListThreadSafe
<DNSObserver
>>
439 resolver_state_observer_list_
;
440 const scoped_refptr
<base::ObserverListThreadSafe
<NetworkChangeObserver
>>
441 network_change_observer_list_
;
442 const scoped_refptr
<base::ObserverListThreadSafe
<MaxBandwidthObserver
>>
443 max_bandwidth_observer_list_
;
445 // The current network state. Hosts DnsConfig, exposed via GetDnsConfig.
446 scoped_ptr
<NetworkState
> network_state_
;
448 // A little-piggy-back observer that simply logs UMA histogram data.
449 scoped_ptr
<HistogramWatcher
> histogram_watcher_
;
451 // Computes NetworkChange signal from IPAddress and ConnectionType signals.
452 scoped_ptr
<NetworkChangeCalculator
> network_change_calculator_
;
454 // Set true to disable non-test notifications (to prevent flakes in tests).
455 static bool test_notifications_only_
;
457 DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier
);
462 #endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_H_