OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #ifndef NET_BASE_NETWORK_CHANGE_NOTIFIER_H_ | |
6 #define NET_BASE_NETWORK_CHANGE_NOTIFIER_H_ | |
7 | |
8 #include <vector> | |
9 | |
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" | |
14 | |
15 class GURL; | |
16 | |
17 namespace net { | |
18 | |
19 struct DnsConfig; | |
20 class HistogramWatcher; | |
21 class NetworkChangeNotifierFactory; | |
22 struct NetworkInterface; | |
23 typedef std::vector<NetworkInterface> NetworkInterfaceList; | |
24 class URLRequest; | |
25 | |
26 #if defined(OS_LINUX) | |
27 namespace internal { | |
28 class AddressTrackerLinux; | |
29 } | |
30 #endif | |
31 | |
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/. | |
41 // | |
42 // A Java counterpart will be generated for this enum. | |
43 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net | |
44 enum ConnectionType { | |
45 CONNECTION_UNKNOWN = 0, // A connection exists, but its type is unknown. | |
46 // Also used as a default value. | |
47 CONNECTION_ETHERNET = 1, | |
48 CONNECTION_WIFI = 2, | |
49 CONNECTION_2G = 3, | |
50 CONNECTION_3G = 4, | |
51 CONNECTION_4G = 5, | |
52 CONNECTION_NONE = 6, // No connection. | |
53 CONNECTION_BLUETOOTH = 7, | |
54 CONNECTION_LAST = CONNECTION_BLUETOOTH | |
55 }; | |
56 | |
57 // This is the NetInfo v3 set of connection technologies as seen in | |
58 // http://w3c.github.io/netinfo/. This enum is copied in | |
59 // NetworkChangeNotifier.java so be sure to change both at once. | |
60 // | |
61 // A Java counterpart will be generated for this enum. | |
62 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net | |
63 enum ConnectionSubtype { | |
64 SUBTYPE_GSM = 0, | |
65 SUBTYPE_IDEN, | |
66 SUBTYPE_CDMA, | |
67 SUBTYPE_1XRTT, | |
68 SUBTYPE_GPRS, | |
69 SUBTYPE_EDGE, | |
70 SUBTYPE_UMTS, | |
71 SUBTYPE_EVDO_REV_0, | |
72 SUBTYPE_EVDO_REV_A, | |
73 SUBTYPE_HSPA, | |
74 SUBTYPE_EVDO_REV_B, | |
75 SUBTYPE_HSDPA, | |
76 SUBTYPE_HSUPA, | |
77 SUBTYPE_EHRPD, | |
78 SUBTYPE_HSPAP, | |
79 SUBTYPE_LTE, | |
80 SUBTYPE_LTE_ADVANCED, | |
81 SUBTYPE_BLUETOOTH_1_2, | |
82 SUBTYPE_BLUETOOTH_2_1, | |
83 SUBTYPE_BLUETOOTH_3_0, | |
84 SUBTYPE_BLUETOOTH_4_0, | |
85 SUBTYPE_ETHERNET, | |
86 SUBTYPE_FAST_ETHERNET, | |
87 SUBTYPE_GIGABIT_ETHERNET, | |
88 SUBTYPE_10_GIGABIT_ETHERNET, | |
89 SUBTYPE_WIFI_B, | |
90 SUBTYPE_WIFI_G, | |
91 SUBTYPE_WIFI_N, | |
92 SUBTYPE_WIFI_AC, | |
93 SUBTYPE_WIFI_AD, | |
94 SUBTYPE_UNKNOWN, | |
95 SUBTYPE_NONE, | |
96 SUBTYPE_OTHER, | |
97 SUBTYPE_LAST = SUBTYPE_OTHER | |
98 }; | |
99 | |
100 class NET_EXPORT IPAddressObserver { | |
101 public: | |
102 // Will be called when the IP address of the primary interface changes. | |
103 // This includes when the primary interface itself changes. | |
104 virtual void OnIPAddressChanged() = 0; | |
105 | |
106 protected: | |
107 IPAddressObserver() {} | |
108 virtual ~IPAddressObserver() {} | |
109 | |
110 private: | |
111 DISALLOW_COPY_AND_ASSIGN(IPAddressObserver); | |
112 }; | |
113 | |
114 class NET_EXPORT ConnectionTypeObserver { | |
115 public: | |
116 // Will be called when the connection type of the system has changed. | |
117 // See NetworkChangeNotifier::GetConnectionType() for important caveats | |
118 // about the unreliability of using this signal to infer the ability to | |
119 // reach remote sites. | |
120 virtual void OnConnectionTypeChanged(ConnectionType type) = 0; | |
121 | |
122 protected: | |
123 ConnectionTypeObserver() {} | |
124 virtual ~ConnectionTypeObserver() {} | |
125 | |
126 private: | |
127 DISALLOW_COPY_AND_ASSIGN(ConnectionTypeObserver); | |
128 }; | |
129 | |
130 class NET_EXPORT DNSObserver { | |
131 public: | |
132 // Will be called when the DNS settings of the system may have changed. | |
133 // Use GetDnsConfig to obtain the current settings. | |
134 virtual void OnDNSChanged() = 0; | |
135 | |
136 protected: | |
137 DNSObserver() {} | |
138 virtual ~DNSObserver() {} | |
139 | |
140 private: | |
141 DISALLOW_COPY_AND_ASSIGN(DNSObserver); | |
142 }; | |
143 | |
144 class NET_EXPORT NetworkChangeObserver { | |
145 public: | |
146 // OnNetworkChanged will be called when a change occurs to the host | |
147 // computer's hardware or software that affects the route network packets | |
148 // take to any network server. Some examples: | |
149 // 1. A network connection becoming available or going away. For example | |
150 // plugging or unplugging an Ethernet cable, WiFi or cellular modem | |
151 // connecting or disconnecting from a network, or a VPN tunnel being | |
152 // established or taken down. | |
153 // 2. An active network connection's IP address changes. | |
154 // 3. A change to the local IP routing tables. | |
155 // The signal shall only be produced when the change is complete. For | |
156 // example if a new network connection has become available, only give the | |
157 // signal once we think the O/S has finished establishing the connection | |
158 // (i.e. DHCP is done) to the point where the new connection is usable. | |
159 // The signal shall not be produced spuriously as it will be triggering some | |
160 // expensive operations, like socket pools closing all connections and | |
161 // sockets and then re-establishing them. | |
162 // |type| indicates the type of the active primary network connection after | |
163 // the change. Observers performing "constructive" activities like trying | |
164 // to establish a connection to a server should only do so when | |
165 // |type != CONNECTION_NONE|. Observers performing "destructive" activities | |
166 // like resetting already established server connections should only do so | |
167 // when |type == CONNECTION_NONE|. OnNetworkChanged will always be called | |
168 // with CONNECTION_NONE immediately prior to being called with an online | |
169 // state; this is done to make sure that destructive actions take place | |
170 // prior to constructive actions. | |
171 virtual void OnNetworkChanged(ConnectionType type) = 0; | |
172 | |
173 protected: | |
174 NetworkChangeObserver() {} | |
175 virtual ~NetworkChangeObserver() {} | |
176 | |
177 private: | |
178 DISALLOW_COPY_AND_ASSIGN(NetworkChangeObserver); | |
179 }; | |
180 | |
181 class NET_EXPORT MaxBandwidthObserver { | |
182 public: | |
183 // Will be called when a change occurs to the network's maximum bandwidth as | |
184 // defined in http://w3c.github.io/netinfo/. Generally this will only be | |
185 // called on bandwidth changing network connection/disconnection events. | |
186 // Some platforms may call it more frequently, such as when WiFi signal | |
187 // strength changes. | |
188 // TODO(jkarlin): This is currently only implemented for Android. Implement | |
189 // on every platform. | |
190 virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps) = 0; | |
191 | |
192 protected: | |
193 MaxBandwidthObserver() {} | |
194 virtual ~MaxBandwidthObserver() {} | |
195 | |
196 private: | |
197 DISALLOW_COPY_AND_ASSIGN(MaxBandwidthObserver); | |
198 }; | |
199 | |
200 virtual ~NetworkChangeNotifier(); | |
201 | |
202 // See the description of NetworkChangeNotifier::GetConnectionType(). | |
203 // Implementations must be thread-safe. Implementations must also be | |
204 // cheap as it is called often. | |
205 virtual ConnectionType GetCurrentConnectionType() const = 0; | |
206 | |
207 // Replaces the default class factory instance of NetworkChangeNotifier class. | |
208 // The method will take over the ownership of |factory| object. | |
209 static void SetFactory(NetworkChangeNotifierFactory* factory); | |
210 | |
211 // Creates the process-wide, platform-specific NetworkChangeNotifier. The | |
212 // caller owns the returned pointer. You may call this on any thread. You | |
213 // may also avoid creating this entirely (in which case nothing will be | |
214 // monitored), but if you do create it, you must do so before any other | |
215 // threads try to access the API below, and it must outlive all other threads | |
216 // which might try to use it. | |
217 static NetworkChangeNotifier* Create(); | |
218 | |
219 // Returns the connection type. | |
220 // A return value of |CONNECTION_NONE| is a pretty strong indicator that the | |
221 // user won't be able to connect to remote sites. However, another return | |
222 // value doesn't imply that the user will be able to connect to remote sites; | |
223 // even if some link is up, it is uncertain whether a particular connection | |
224 // attempt to a particular remote site will be successful. | |
225 // The returned value only describes the connection currently used by the | |
226 // device, and does not take into account other machines on the network. For | |
227 // example, if the device is connected using Wifi to a 3G gateway to access | |
228 // the internet, the connection type is CONNECTION_WIFI. | |
229 static ConnectionType GetConnectionType(); | |
230 | |
231 // Returns a theoretical upper limit on download bandwidth, potentially based | |
232 // on underlying connection type, signal strength, or some other signal. The | |
233 // default mapping of connection type to maximum bandwidth is provided in the | |
234 // NetInfo spec: http://w3c.github.io/netinfo/. Host-specific application | |
235 // permissions may be required, please see host-specific declaration for more | |
236 // information. | |
237 static double GetMaxBandwidth(); | |
238 | |
239 // Retrieve the last read DnsConfig. This could be expensive if the system has | |
240 // a large HOSTS file. | |
241 static void GetDnsConfig(DnsConfig* config); | |
242 | |
243 #if defined(OS_LINUX) | |
244 // Returns the AddressTrackerLinux if present. | |
245 static const internal::AddressTrackerLinux* GetAddressTracker(); | |
246 #endif | |
247 | |
248 // Convenience method to determine if the user is offline. | |
249 // Returns true if there is currently no internet connection. | |
250 // | |
251 // A return value of |true| is a pretty strong indicator that the user | |
252 // won't be able to connect to remote sites. However, a return value of | |
253 // |false| is inconclusive; even if some link is up, it is uncertain | |
254 // whether a particular connection attempt to a particular remote site | |
255 // will be successfully. | |
256 static bool IsOffline(); | |
257 | |
258 // Returns true if |type| is a cellular connection. | |
259 // Returns false if |type| is CONNECTION_UNKNOWN, and thus, depending on the | |
260 // implementation of GetConnectionType(), it is possible that | |
261 // IsConnectionCellular(GetConnectionType()) returns false even if the | |
262 // current connection is cellular. | |
263 static bool IsConnectionCellular(ConnectionType type); | |
264 | |
265 // Gets the current connection type based on |interfaces|. Returns | |
266 // CONNECTION_NONE if there are no interfaces, CONNECTION_UNKNOWN if two | |
267 // interfaces have different connection types or the connection type of all | |
268 // interfaces if they have the same interface type. | |
269 static ConnectionType ConnectionTypeFromInterfaceList( | |
270 const NetworkInterfaceList& interfaces); | |
271 | |
272 // Like Create(), but for use in tests. The mock object doesn't monitor any | |
273 // events, it merely rebroadcasts notifications when requested. | |
274 static NetworkChangeNotifier* CreateMock(); | |
275 | |
276 // Registers |observer| to receive notifications of network changes. The | |
277 // thread on which this is called is the thread on which |observer| will be | |
278 // called back with notifications. This is safe to call if Create() has not | |
279 // been called (as long as it doesn't race the Create() call on another | |
280 // thread), in which case it will simply do nothing. | |
281 static void AddIPAddressObserver(IPAddressObserver* observer); | |
282 static void AddConnectionTypeObserver(ConnectionTypeObserver* observer); | |
283 static void AddDNSObserver(DNSObserver* observer); | |
284 static void AddNetworkChangeObserver(NetworkChangeObserver* observer); | |
285 static void AddMaxBandwidthObserver(MaxBandwidthObserver* observer); | |
286 | |
287 // Unregisters |observer| from receiving notifications. This must be called | |
288 // on the same thread on which AddObserver() was called. Like AddObserver(), | |
289 // this is safe to call if Create() has not been called (as long as it doesn't | |
290 // race the Create() call on another thread), in which case it will simply do | |
291 // nothing. Technically, it's also safe to call after the notifier object has | |
292 // been destroyed, if the call doesn't race the notifier's destruction, but | |
293 // there's no reason to use the API in this risky way, so don't do it. | |
294 static void RemoveIPAddressObserver(IPAddressObserver* observer); | |
295 static void RemoveConnectionTypeObserver(ConnectionTypeObserver* observer); | |
296 static void RemoveDNSObserver(DNSObserver* observer); | |
297 static void RemoveNetworkChangeObserver(NetworkChangeObserver* observer); | |
298 static void RemoveMaxBandwidthObserver(MaxBandwidthObserver* observer); | |
299 | |
300 // Allow unit tests to trigger notifications. | |
301 static void NotifyObserversOfIPAddressChangeForTests(); | |
302 static void NotifyObserversOfConnectionTypeChangeForTests( | |
303 ConnectionType type); | |
304 static void NotifyObserversOfNetworkChangeForTests(ConnectionType type); | |
305 | |
306 // Enable or disable notifications from the host. After setting to true, be | |
307 // sure to pump the RunLoop until idle to finish any preexisting | |
308 // notifications. | |
309 static void SetTestNotificationsOnly(bool test_only); | |
310 | |
311 // Return a string equivalent to |type|. | |
312 static const char* ConnectionTypeToString(ConnectionType type); | |
313 | |
314 // Let the NetworkChangeNotifier know we received some data. | |
315 // This is used for producing histogram data about the accuracy of | |
316 // the NetworkChangenotifier's online detection and rough network | |
317 // connection measurements. | |
318 static void NotifyDataReceived(const URLRequest& request, int bytes_read); | |
319 | |
320 // Register the Observer callbacks for producing histogram data. This | |
321 // should be called from the network thread to avoid race conditions. | |
322 // ShutdownHistogramWatcher() must be called prior to NetworkChangeNotifier | |
323 // destruction. | |
324 static void InitHistogramWatcher(); | |
325 | |
326 // Unregister the Observer callbacks for producing histogram data. This | |
327 // should be called from the network thread to avoid race conditions. | |
328 static void ShutdownHistogramWatcher(); | |
329 | |
330 // Log the |NCN.NetworkOperatorMCCMNC| histogram. | |
331 static void LogOperatorCodeHistogram(ConnectionType type); | |
332 | |
333 // Allows a second NetworkChangeNotifier to be created for unit testing, so | |
334 // the test suite can create a MockNetworkChangeNotifier, but platform | |
335 // specific NetworkChangeNotifiers can also be created for testing. To use, | |
336 // create an DisableForTest object, and then create the new | |
337 // NetworkChangeNotifier object. The NetworkChangeNotifier must be | |
338 // destroyed before the DisableForTest object, as its destruction will restore | |
339 // the original NetworkChangeNotifier. | |
340 class NET_EXPORT DisableForTest { | |
341 public: | |
342 DisableForTest(); | |
343 ~DisableForTest(); | |
344 | |
345 private: | |
346 // The original NetworkChangeNotifier to be restored on destruction. | |
347 NetworkChangeNotifier* network_change_notifier_; | |
348 }; | |
349 | |
350 protected: | |
351 // NetworkChanged signal is calculated from the IPAddressChanged and | |
352 // ConnectionTypeChanged signals. Delay parameters control how long to delay | |
353 // producing NetworkChanged signal after particular input signals so as to | |
354 // combine duplicates. In other words if an input signal is repeated within | |
355 // the corresponding delay period, only one resulting NetworkChange signal is | |
356 // produced. | |
357 struct NET_EXPORT NetworkChangeCalculatorParams { | |
358 NetworkChangeCalculatorParams(); | |
359 // Controls delay after OnIPAddressChanged when transitioning from an | |
360 // offline state. | |
361 base::TimeDelta ip_address_offline_delay_; | |
362 // Controls delay after OnIPAddressChanged when transitioning from an | |
363 // online state. | |
364 base::TimeDelta ip_address_online_delay_; | |
365 // Controls delay after OnConnectionTypeChanged when transitioning from an | |
366 // offline state. | |
367 base::TimeDelta connection_type_offline_delay_; | |
368 // Controls delay after OnConnectionTypeChanged when transitioning from an | |
369 // online state. | |
370 base::TimeDelta connection_type_online_delay_; | |
371 }; | |
372 | |
373 explicit NetworkChangeNotifier( | |
374 const NetworkChangeCalculatorParams& params = | |
375 NetworkChangeCalculatorParams()); | |
376 | |
377 #if defined(OS_LINUX) | |
378 // Returns the AddressTrackerLinux if present. | |
379 // TODO(szym): Retrieve AddressMap from NetworkState. http://crbug.com/144212 | |
380 virtual const internal::AddressTrackerLinux* | |
381 GetAddressTrackerInternal() const; | |
382 #endif | |
383 | |
384 // See the description of NetworkChangeNotifier::GetMaxBandwidth(). | |
385 // Implementations must be thread-safe. Implementations must also be | |
386 // cheap as it is called often. | |
387 virtual double GetCurrentMaxBandwidth() const; | |
388 | |
389 // Returns a theoretical upper limit on download bandwidth given a connection | |
390 // subtype. The mapping of connection type to maximum bandwidth is provided in | |
391 // the NetInfo spec: http://w3c.github.io/netinfo/. | |
392 static double GetMaxBandwidthForConnectionSubtype(ConnectionSubtype subtype); | |
393 | |
394 // Broadcasts a notification to all registered observers. Note that this | |
395 // happens asynchronously, even for observers on the current thread, even in | |
396 // tests. | |
397 static void NotifyObserversOfIPAddressChange(); | |
398 static void NotifyObserversOfConnectionTypeChange(); | |
399 static void NotifyObserversOfDNSChange(); | |
400 static void NotifyObserversOfNetworkChange(ConnectionType type); | |
401 static void NotifyObserversOfMaxBandwidthChange(double max_bandwidth_mbps); | |
402 | |
403 // Stores |config| in NetworkState and notifies observers. | |
404 static void SetDnsConfig(const DnsConfig& config); | |
405 | |
406 private: | |
407 friend class HostResolverImplDnsTest; | |
408 friend class NetworkChangeNotifierAndroidTest; | |
409 friend class NetworkChangeNotifierLinuxTest; | |
410 friend class NetworkChangeNotifierWinTest; | |
411 | |
412 class NetworkState; | |
413 class NetworkChangeCalculator; | |
414 | |
415 void NotifyObserversOfIPAddressChangeImpl(); | |
416 void NotifyObserversOfConnectionTypeChangeImpl(ConnectionType type); | |
417 void NotifyObserversOfDNSChangeImpl(); | |
418 void NotifyObserversOfNetworkChangeImpl(ConnectionType type); | |
419 void NotifyObserversOfMaxBandwidthChangeImpl(double max_bandwidth_mbps); | |
420 | |
421 const scoped_refptr<ObserverListThreadSafe<IPAddressObserver>> | |
422 ip_address_observer_list_; | |
423 const scoped_refptr<ObserverListThreadSafe<ConnectionTypeObserver>> | |
424 connection_type_observer_list_; | |
425 const scoped_refptr<ObserverListThreadSafe<DNSObserver>> | |
426 resolver_state_observer_list_; | |
427 const scoped_refptr<ObserverListThreadSafe<NetworkChangeObserver>> | |
428 network_change_observer_list_; | |
429 const scoped_refptr<ObserverListThreadSafe<MaxBandwidthObserver>> | |
430 max_bandwidth_observer_list_; | |
431 | |
432 // The current network state. Hosts DnsConfig, exposed via GetDnsConfig. | |
433 scoped_ptr<NetworkState> network_state_; | |
434 | |
435 // A little-piggy-back observer that simply logs UMA histogram data. | |
436 scoped_ptr<HistogramWatcher> histogram_watcher_; | |
437 | |
438 // Computes NetworkChange signal from IPAddress and ConnectionType signals. | |
439 scoped_ptr<NetworkChangeCalculator> network_change_calculator_; | |
440 | |
441 // Set true to disable non-test notifications (to prevent flakes in tests). | |
442 bool test_notifications_only_; | |
443 | |
444 DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier); | |
445 }; | |
446 | |
447 } // namespace net | |
448 | |
449 #endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_H_ | |
OLD | NEW |