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 "base/basictypes.h"
9
#include "base/observer_list_threadsafe.h"
10
#include "base/time/time.h"
11
#include "net/base/net_export.h"
18
class HistogramWatcher;
19
class NetworkChangeNotifierFactory;
24
class AddressTrackerLinux;
28
// NetworkChangeNotifier monitors the system for network changes, and notifies
29
// registered observers of those events. Observers may register on any thread,
30
// and will be called back on the thread from which they registered.
31
// NetworkChangeNotifiers are threadsafe, though they must be created and
32
// destroyed on the same thread.
33
class NET_EXPORT NetworkChangeNotifier {
35
// Using the terminology of the Network Information API:
36
// http://www.w3.org/TR/netinfo-api.
38
CONNECTION_UNKNOWN = 0, // A connection exists, but its type is unknown.
39
CONNECTION_ETHERNET = 1,
44
CONNECTION_NONE = 6 // No connection.
47
class NET_EXPORT IPAddressObserver {
49
// Will be called when the IP address of the primary interface changes.
50
// This includes when the primary interface itself changes.
51
virtual void OnIPAddressChanged() = 0;
54
IPAddressObserver() {}
55
virtual ~IPAddressObserver() {}
58
DISALLOW_COPY_AND_ASSIGN(IPAddressObserver);
61
class NET_EXPORT ConnectionTypeObserver {
63
// Will be called when the connection type of the system has changed.
64
// See NetworkChangeNotifier::GetConnectionType() for important caveats
65
// about the unreliability of using this signal to infer the ability to
66
// reach remote sites.
67
virtual void OnConnectionTypeChanged(ConnectionType type) = 0;
70
ConnectionTypeObserver() {}
71
virtual ~ConnectionTypeObserver() {}
74
DISALLOW_COPY_AND_ASSIGN(ConnectionTypeObserver);
77
class NET_EXPORT DNSObserver {
79
// Will be called when the DNS settings of the system may have changed.
80
// Use GetDnsConfig to obtain the current settings.
81
virtual void OnDNSChanged() = 0;
85
virtual ~DNSObserver() {}
88
DISALLOW_COPY_AND_ASSIGN(DNSObserver);
91
class NET_EXPORT NetworkChangeObserver {
93
// OnNetworkChanged will be called when a change occurs to the host
94
// computer's hardware or software that affects the route network packets
95
// take to any network server. Some examples:
96
// 1. A network connection becoming available or going away. For example
97
// plugging or unplugging an Ethernet cable, WiFi or cellular modem
98
// connecting or disconnecting from a network, or a VPN tunnel being
99
// established or taken down.
100
// 2. An active network connection's IP address changes.
101
// 3. A change to the local IP routing tables.
102
// The signal shall only be produced when the change is complete. For
103
// example if a new network connection has become available, only give the
104
// signal once we think the O/S has finished establishing the connection
105
// (i.e. DHCP is done) to the point where the new connection is usable.
106
// The signal shall not be produced spuriously as it will be triggering some
107
// expensive operations, like socket pools closing all connections and
108
// sockets and then re-establishing them.
109
// |type| indicates the type of the active primary network connection after
110
// the change. Observers performing "constructive" activities like trying
111
// to establish a connection to a server should only do so when
112
// |type != CONNECTION_NONE|. Observers performing "destructive" activities
113
// like resetting already established server connections should only do so
114
// when |type == CONNECTION_NONE|. OnNetworkChanged will always be called
115
// with CONNECTION_NONE immediately prior to being called with an online
116
// state; this is done to make sure that destructive actions take place
117
// prior to constructive actions.
118
virtual void OnNetworkChanged(ConnectionType type) = 0;
121
NetworkChangeObserver() {}
122
virtual ~NetworkChangeObserver() {}
125
DISALLOW_COPY_AND_ASSIGN(NetworkChangeObserver);
128
virtual ~NetworkChangeNotifier();
130
// See the description of NetworkChangeNotifier::GetConnectionType().
131
// Implementations must be thread-safe. Implementations must also be
132
// cheap as this could be called (repeatedly) from the network thread.
133
virtual ConnectionType GetCurrentConnectionType() const = 0;
135
// Replaces the default class factory instance of NetworkChangeNotifier class.
136
// The method will take over the ownership of |factory| object.
137
static void SetFactory(NetworkChangeNotifierFactory* factory);
139
// Creates the process-wide, platform-specific NetworkChangeNotifier. The
140
// caller owns the returned pointer. You may call this on any thread. You
141
// may also avoid creating this entirely (in which case nothing will be
142
// monitored), but if you do create it, you must do so before any other
143
// threads try to access the API below, and it must outlive all other threads
144
// which might try to use it.
145
static NetworkChangeNotifier* Create();
147
// Returns the connection type.
148
// A return value of |CONNECTION_NONE| is a pretty strong indicator that the
149
// user won't be able to connect to remote sites. However, another return
150
// value doesn't imply that the user will be able to connect to remote sites;
151
// even if some link is up, it is uncertain whether a particular connection
152
// attempt to a particular remote site will be successful.
153
// The returned value only describes the connection currently used by the
154
// device, and does not take into account other machines on the network. For
155
// example, if the device is connected using Wifi to a 3G gateway to access
156
// the internet, the connection type is CONNECTION_WIFI.
157
static ConnectionType GetConnectionType();
159
// Retrieve the last read DnsConfig. This could be expensive if the system has
160
// a large HOSTS file.
161
static void GetDnsConfig(DnsConfig* config);
163
#if defined(OS_LINUX)
164
// Returns the AddressTrackerLinux if present.
165
static const internal::AddressTrackerLinux* GetAddressTracker();
168
// Convenience method to determine if the user is offline.
169
// Returns true if there is currently no internet connection.
171
// A return value of |true| is a pretty strong indicator that the user
172
// won't be able to connect to remote sites. However, a return value of
173
// |false| is inconclusive; even if some link is up, it is uncertain
174
// whether a particular connection attempt to a particular remote site
175
// will be successfully.
176
static bool IsOffline();
178
// Returns true if |type| is a cellular connection.
179
// Returns false if |type| is CONNECTION_UNKNOWN, and thus, depending on the
180
// implementation of GetConnectionType(), it is possible that
181
// IsConnectionCellular(GetConnectionType()) returns false even if the
182
// current connection is cellular.
183
static bool IsConnectionCellular(ConnectionType type);
185
// Like Create(), but for use in tests. The mock object doesn't monitor any
186
// events, it merely rebroadcasts notifications when requested.
187
static NetworkChangeNotifier* CreateMock();
189
// Registers |observer| to receive notifications of network changes. The
190
// thread on which this is called is the thread on which |observer| will be
191
// called back with notifications. This is safe to call if Create() has not
192
// been called (as long as it doesn't race the Create() call on another
193
// thread), in which case it will simply do nothing.
194
static void AddIPAddressObserver(IPAddressObserver* observer);
195
static void AddConnectionTypeObserver(ConnectionTypeObserver* observer);
196
static void AddDNSObserver(DNSObserver* observer);
197
static void AddNetworkChangeObserver(NetworkChangeObserver* observer);
199
// Unregisters |observer| from receiving notifications. This must be called
200
// on the same thread on which AddObserver() was called. Like AddObserver(),
201
// this is safe to call if Create() has not been called (as long as it doesn't
202
// race the Create() call on another thread), in which case it will simply do
203
// nothing. Technically, it's also safe to call after the notifier object has
204
// been destroyed, if the call doesn't race the notifier's destruction, but
205
// there's no reason to use the API in this risky way, so don't do it.
206
static void RemoveIPAddressObserver(IPAddressObserver* observer);
207
static void RemoveConnectionTypeObserver(ConnectionTypeObserver* observer);
208
static void RemoveDNSObserver(DNSObserver* observer);
209
static void RemoveNetworkChangeObserver(NetworkChangeObserver* observer);
211
// Allow unit tests to trigger notifications.
212
static void NotifyObserversOfIPAddressChangeForTests() {
213
NotifyObserversOfIPAddressChange();
216
// Return a string equivalent to |type|.
217
static const char* ConnectionTypeToString(ConnectionType type);
219
// Let the NetworkChangeNotifier know we received some data.
220
// This is used for producing histogram data about the accuracy of
221
// the NetworkChangenotifier's online detection and rough network
222
// connection measurements.
223
static void NotifyDataReceived(const URLRequest& request, int bytes_read);
225
// Register the Observer callbacks for producing histogram data. This
226
// should be called from the network thread to avoid race conditions.
227
static void InitHistogramWatcher();
229
// Allows a second NetworkChangeNotifier to be created for unit testing, so
230
// the test suite can create a MockNetworkChangeNotifier, but platform
231
// specific NetworkChangeNotifiers can also be created for testing. To use,
232
// create an DisableForTest object, and then create the new
233
// NetworkChangeNotifier object. The NetworkChangeNotifier must be
234
// destroyed before the DisableForTest object, as its destruction will restore
235
// the original NetworkChangeNotifier.
236
class NET_EXPORT DisableForTest {
242
// The original NetworkChangeNotifier to be restored on destruction.
243
NetworkChangeNotifier* network_change_notifier_;
247
// NetworkChanged signal is calculated from the IPAddressChanged and
248
// ConnectionTypeChanged signals. Delay parameters control how long to delay
249
// producing NetworkChanged signal after particular input signals so as to
250
// combine duplicates. In other words if an input signal is repeated within
251
// the corresponding delay period, only one resulting NetworkChange signal is
253
struct NET_EXPORT NetworkChangeCalculatorParams {
254
NetworkChangeCalculatorParams();
255
// Controls delay after OnIPAddressChanged when transitioning from an
257
base::TimeDelta ip_address_offline_delay_;
258
// Controls delay after OnIPAddressChanged when transitioning from an
260
base::TimeDelta ip_address_online_delay_;
261
// Controls delay after OnConnectionTypeChanged when transitioning from an
263
base::TimeDelta connection_type_offline_delay_;
264
// Controls delay after OnConnectionTypeChanged when transitioning from an
266
base::TimeDelta connection_type_online_delay_;
269
explicit NetworkChangeNotifier(
270
const NetworkChangeCalculatorParams& params =
271
NetworkChangeCalculatorParams());
273
#if defined(OS_LINUX)
274
// Returns the AddressTrackerLinux if present.
275
// TODO(szym): Retrieve AddressMap from NetworkState. http://crbug.com/144212
276
virtual const internal::AddressTrackerLinux*
277
GetAddressTrackerInternal() const;
280
// Broadcasts a notification to all registered observers. Note that this
281
// happens asynchronously, even for observers on the current thread, even in
283
static void NotifyObserversOfIPAddressChange();
284
static void NotifyObserversOfConnectionTypeChange();
285
static void NotifyObserversOfDNSChange();
286
static void NotifyObserversOfNetworkChange(ConnectionType type);
288
// Stores |config| in NetworkState and notifies observers.
289
static void SetDnsConfig(const DnsConfig& config);
292
friend class HostResolverImplDnsTest;
293
friend class NetworkChangeNotifierAndroidTest;
294
friend class NetworkChangeNotifierLinuxTest;
295
friend class NetworkChangeNotifierWinTest;
298
class NetworkChangeCalculator;
300
const scoped_refptr<ObserverListThreadSafe<IPAddressObserver> >
301
ip_address_observer_list_;
302
const scoped_refptr<ObserverListThreadSafe<ConnectionTypeObserver> >
303
connection_type_observer_list_;
304
const scoped_refptr<ObserverListThreadSafe<DNSObserver> >
305
resolver_state_observer_list_;
306
const scoped_refptr<ObserverListThreadSafe<NetworkChangeObserver> >
307
network_change_observer_list_;
309
// The current network state. Hosts DnsConfig, exposed via GetDnsConfig.
310
scoped_ptr<NetworkState> network_state_;
312
// A little-piggy-back observer that simply logs UMA histogram data.
313
scoped_ptr<HistogramWatcher> histogram_watcher_;
315
// Computes NetworkChange signal from IPAddress and ConnectionType signals.
316
scoped_ptr<NetworkChangeCalculator> network_change_calculator_;
318
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier);
323
#endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_H_