Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / base / network_change_notifier.h
blobdf6792f7dcfe6c172fe1a78a326a3a88308f8f16
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 // 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
193 // strength changes.
194 // TODO(jkarlin): This is currently only implemented for Android. Implement
195 // on every platform.
196 virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps) = 0;
198 protected:
199 MaxBandwidthObserver() {}
200 virtual ~MaxBandwidthObserver() {}
202 private:
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
242 // information.
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();
252 #endif
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.
316 static void SetTestNotificationsOnly(bool test_only);
318 // Return a string equivalent to |type|.
319 static const char* ConnectionTypeToString(ConnectionType type);
321 // Let the NetworkChangeNotifier know we received some data.
322 // This is used for producing histogram data about the accuracy of
323 // the NetworkChangenotifier's online detection and rough network
324 // connection measurements.
325 static void NotifyDataReceived(const URLRequest& request, int bytes_read);
327 // Register the Observer callbacks for producing histogram data. This
328 // should be called from the network thread to avoid race conditions.
329 // ShutdownHistogramWatcher() must be called prior to NetworkChangeNotifier
330 // destruction.
331 static void InitHistogramWatcher();
333 // Unregister the Observer callbacks for producing histogram data. This
334 // should be called from the network thread to avoid race conditions.
335 static void ShutdownHistogramWatcher();
337 // Log the |NCN.NetworkOperatorMCCMNC| histogram.
338 static void LogOperatorCodeHistogram(ConnectionType type);
340 // Allows a second NetworkChangeNotifier to be created for unit testing, so
341 // the test suite can create a MockNetworkChangeNotifier, but platform
342 // specific NetworkChangeNotifiers can also be created for testing. To use,
343 // create an DisableForTest object, and then create the new
344 // NetworkChangeNotifier object. The NetworkChangeNotifier must be
345 // destroyed before the DisableForTest object, as its destruction will restore
346 // the original NetworkChangeNotifier.
347 class NET_EXPORT DisableForTest {
348 public:
349 DisableForTest();
350 ~DisableForTest();
352 private:
353 // The original NetworkChangeNotifier to be restored on destruction.
354 NetworkChangeNotifier* network_change_notifier_;
357 protected:
358 // NetworkChanged signal is calculated from the IPAddressChanged and
359 // ConnectionTypeChanged signals. Delay parameters control how long to delay
360 // producing NetworkChanged signal after particular input signals so as to
361 // combine duplicates. In other words if an input signal is repeated within
362 // the corresponding delay period, only one resulting NetworkChange signal is
363 // produced.
364 struct NET_EXPORT NetworkChangeCalculatorParams {
365 NetworkChangeCalculatorParams();
366 // Controls delay after OnIPAddressChanged when transitioning from an
367 // offline state.
368 base::TimeDelta ip_address_offline_delay_;
369 // Controls delay after OnIPAddressChanged when transitioning from an
370 // online state.
371 base::TimeDelta ip_address_online_delay_;
372 // Controls delay after OnConnectionTypeChanged when transitioning from an
373 // offline state.
374 base::TimeDelta connection_type_offline_delay_;
375 // Controls delay after OnConnectionTypeChanged when transitioning from an
376 // online state.
377 base::TimeDelta connection_type_online_delay_;
380 explicit NetworkChangeNotifier(
381 const NetworkChangeCalculatorParams& params =
382 NetworkChangeCalculatorParams());
384 #if defined(OS_LINUX)
385 // Returns the AddressTrackerLinux if present.
386 // TODO(szym): Retrieve AddressMap from NetworkState. http://crbug.com/144212
387 virtual const internal::AddressTrackerLinux*
388 GetAddressTrackerInternal() const;
389 #endif
391 // See the description of NetworkChangeNotifier::GetMaxBandwidth().
392 // Implementations must be thread-safe. Implementations must also be
393 // cheap as it is called often.
394 virtual double GetCurrentMaxBandwidth() const;
396 // Returns a theoretical upper limit on download bandwidth given a connection
397 // subtype. The mapping of connection type to maximum bandwidth is provided in
398 // the NetInfo spec: http://w3c.github.io/netinfo/.
399 static double GetMaxBandwidthForConnectionSubtype(ConnectionSubtype subtype);
401 // Broadcasts a notification to all registered observers. Note that this
402 // happens asynchronously, even for observers on the current thread, even in
403 // tests.
404 static void NotifyObserversOfIPAddressChange();
405 static void NotifyObserversOfConnectionTypeChange();
406 static void NotifyObserversOfDNSChange();
407 static void NotifyObserversOfInitialDNSConfigRead();
408 static void NotifyObserversOfNetworkChange(ConnectionType type);
409 static void NotifyObserversOfMaxBandwidthChange(double max_bandwidth_mbps);
411 // Stores |config| in NetworkState and notifies OnDNSChanged observers.
412 static void SetDnsConfig(const DnsConfig& config);
413 // Stores |config| in NetworkState and notifies OnInitialDNSConfigRead
414 // observers.
415 static void SetInitialDnsConfig(const DnsConfig& config);
417 private:
418 friend class HostResolverImplDnsTest;
419 friend class NetworkChangeNotifierAndroidTest;
420 friend class NetworkChangeNotifierLinuxTest;
421 friend class NetworkChangeNotifierWinTest;
423 class NetworkState;
424 class NetworkChangeCalculator;
426 void NotifyObserversOfIPAddressChangeImpl();
427 void NotifyObserversOfConnectionTypeChangeImpl(ConnectionType type);
428 void NotifyObserversOfDNSChangeImpl();
429 void NotifyObserversOfInitialDNSConfigReadImpl();
430 void NotifyObserversOfNetworkChangeImpl(ConnectionType type);
431 void NotifyObserversOfMaxBandwidthChangeImpl(double max_bandwidth_mbps);
433 const scoped_refptr<base::ObserverListThreadSafe<IPAddressObserver>>
434 ip_address_observer_list_;
435 const scoped_refptr<base::ObserverListThreadSafe<ConnectionTypeObserver>>
436 connection_type_observer_list_;
437 const scoped_refptr<base::ObserverListThreadSafe<DNSObserver>>
438 resolver_state_observer_list_;
439 const scoped_refptr<base::ObserverListThreadSafe<NetworkChangeObserver>>
440 network_change_observer_list_;
441 const scoped_refptr<base::ObserverListThreadSafe<MaxBandwidthObserver>>
442 max_bandwidth_observer_list_;
444 // The current network state. Hosts DnsConfig, exposed via GetDnsConfig.
445 scoped_ptr<NetworkState> network_state_;
447 // A little-piggy-back observer that simply logs UMA histogram data.
448 scoped_ptr<HistogramWatcher> histogram_watcher_;
450 // Computes NetworkChange signal from IPAddress and ConnectionType signals.
451 scoped_ptr<NetworkChangeCalculator> network_change_calculator_;
453 // Set true to disable non-test notifications (to prevent flakes in tests).
454 bool test_notifications_only_;
456 DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier);
459 } // namespace net
461 #endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_H_