| 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 |