Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / base / network_change_notifier.h
blob143abdcb6a71ead74b63c5b13c9ef068ae32ecd5
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_
8 #include <vector>
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"
15 class GURL;
17 namespace net {
19 struct DnsConfig;
20 class HistogramWatcher;
21 class NetworkChangeNotifierFactory;
22 struct NetworkInterface;
23 typedef std::vector<NetworkInterface> NetworkInterfaceList;
24 class URLRequest;
26 #if defined(OS_LINUX)
27 namespace internal {
28 class AddressTrackerLinux;
30 #endif
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 {
38 public:
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.
47 enum ConnectionType {
48 CONNECTION_UNKNOWN = 0, // A connection exists, but its type is unknown.
49 // Also used as a default value.
50 CONNECTION_ETHERNET = 1,
51 CONNECTION_WIFI = 2,
52 CONNECTION_2G = 3,
53 CONNECTION_3G = 4,
54 CONNECTION_4G = 5,
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 {
67 SUBTYPE_GSM = 0,
68 SUBTYPE_IDEN,
69 SUBTYPE_CDMA,
70 SUBTYPE_1XRTT,
71 SUBTYPE_GPRS,
72 SUBTYPE_EDGE,
73 SUBTYPE_UMTS,
74 SUBTYPE_EVDO_REV_0,
75 SUBTYPE_EVDO_REV_A,
76 SUBTYPE_HSPA,
77 SUBTYPE_EVDO_REV_B,
78 SUBTYPE_HSDPA,
79 SUBTYPE_HSUPA,
80 SUBTYPE_EHRPD,
81 SUBTYPE_HSPAP,
82 SUBTYPE_LTE,
83 SUBTYPE_LTE_ADVANCED,
84 SUBTYPE_BLUETOOTH_1_2,
85 SUBTYPE_BLUETOOTH_2_1,
86 SUBTYPE_BLUETOOTH_3_0,
87 SUBTYPE_BLUETOOTH_4_0,
88 SUBTYPE_ETHERNET,
89 SUBTYPE_FAST_ETHERNET,
90 SUBTYPE_GIGABIT_ETHERNET,
91 SUBTYPE_10_GIGABIT_ETHERNET,
92 SUBTYPE_WIFI_B,
93 SUBTYPE_WIFI_G,
94 SUBTYPE_WIFI_N,
95 SUBTYPE_WIFI_AC,
96 SUBTYPE_WIFI_AD,
97 SUBTYPE_UNKNOWN,
98 SUBTYPE_NONE,
99 SUBTYPE_OTHER,
100 SUBTYPE_LAST = SUBTYPE_OTHER
103 class NET_EXPORT IPAddressObserver {
104 public:
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;
109 protected:
110 IPAddressObserver() {}
111 virtual ~IPAddressObserver() {}
113 private:
114 DISALLOW_COPY_AND_ASSIGN(IPAddressObserver);
117 class NET_EXPORT ConnectionTypeObserver {
118 public:
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;
125 protected:
126 ConnectionTypeObserver() {}
127 virtual ~ConnectionTypeObserver() {}
129 private:
130 DISALLOW_COPY_AND_ASSIGN(ConnectionTypeObserver);
133 class NET_EXPORT DNSObserver {
134 public:
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();
142 protected:
143 DNSObserver() {}
144 virtual ~DNSObserver() {}
146 private:
147 DISALLOW_COPY_AND_ASSIGN(DNSObserver);
150 class NET_EXPORT NetworkChangeObserver {
151 public:
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;
179 protected:
180 NetworkChangeObserver() {}
181 virtual ~NetworkChangeObserver() {}
183 private:
184 DISALLOW_COPY_AND_ASSIGN(NetworkChangeObserver);
187 class NET_EXPORT MaxBandwidthObserver {
188 public:
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;
197 protected:
198 MaxBandwidthObserver() {}
199 virtual ~MaxBandwidthObserver() {}
201 private:
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
246 // type.
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();
263 #endif
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
345 // destruction.
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 {
363 public:
364 DisableForTest();
365 ~DisableForTest();
367 private:
368 // The original NetworkChangeNotifier to be restored on destruction.
369 NetworkChangeNotifier* network_change_notifier_;
372 protected:
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
378 // produced.
379 struct NET_EXPORT NetworkChangeCalculatorParams {
380 NetworkChangeCalculatorParams();
381 // Controls delay after OnIPAddressChanged when transitioning from an
382 // offline state.
383 base::TimeDelta ip_address_offline_delay_;
384 // Controls delay after OnIPAddressChanged when transitioning from an
385 // online state.
386 base::TimeDelta ip_address_online_delay_;
387 // Controls delay after OnConnectionTypeChanged when transitioning from an
388 // offline state.
389 base::TimeDelta connection_type_offline_delay_;
390 // Controls delay after OnConnectionTypeChanged when transitioning from an
391 // online state.
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;
404 #endif
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
415 // tests.
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
427 // observers.
428 static void SetInitialDnsConfig(const DnsConfig& config);
430 private:
431 friend class HostResolverImplDnsTest;
432 friend class NetworkChangeNotifierAndroidTest;
433 friend class NetworkChangeNotifierLinuxTest;
434 friend class NetworkChangeNotifierWinTest;
436 class NetworkState;
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);
473 } // namespace net
475 #endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_H_