summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-08 02:46:41 +0000
committerpauljensen@chromium.org <pauljensen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-08 02:46:41 +0000
commit03848873c71fa2092017260d0234461efd300a79 (patch)
tree48cfacc64925b6e4b011db3ba5fa6aa1a58c6600
parentf89842386a4f5ba78e6816739584107d1cbe6964 (diff)
downloadchromium_src-03848873c71fa2092017260d0234461efd300a79.zip
chromium_src-03848873c71fa2092017260d0234461efd300a79.tar.gz
chromium_src-03848873c71fa2092017260d0234461efd300a79.tar.bz2
Start calculating new combined NetworkChangeNotifier signal from previous OnIPAddressChanged and OnConnectionTypeChanged signals. For now it uses delay constants chosen by experimentation but this commit includes histograms to tune the constants.
Review URL: https://chromiumcodereview.appspot.com/11360108 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171920 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/net/network_change_notifier_chromeos.cc16
-rw-r--r--chrome/browser/chromeos/net/network_change_notifier_chromeos.h3
-rw-r--r--chrome/browser/io_thread.cc20
-rw-r--r--net/android/network_change_notifier_android.cc17
-rw-r--r--net/android/network_change_notifier_android.h2
-rw-r--r--net/base/net_log_event_type_list.h7
-rw-r--r--net/base/network_change_notifier.cc133
-rw-r--r--net/base/network_change_notifier.h73
-rw-r--r--net/base/network_change_notifier_linux.cc17
-rw-r--r--net/base/network_change_notifier_linux.h1
-rw-r--r--net/base/network_change_notifier_mac.cc17
-rw-r--r--net/base/network_change_notifier_mac.h2
-rw-r--r--net/base/network_change_notifier_win.cc17
-rw-r--r--net/base/network_change_notifier_win.h2
-rw-r--r--net/tools/net_watcher/net_watcher.cc10
15 files changed, 327 insertions, 10 deletions
diff --git a/chrome/browser/chromeos/net/network_change_notifier_chromeos.cc b/chrome/browser/chromeos/net/network_change_notifier_chromeos.cc
index 78d62be..4cc06a4 100644
--- a/chrome/browser/chromeos/net/network_change_notifier_chromeos.cc
+++ b/chrome/browser/chromeos/net/network_change_notifier_chromeos.cc
@@ -52,7 +52,8 @@ class NetworkChangeNotifierChromeos::DnsConfigServiceChromeos
};
NetworkChangeNotifierChromeos::NetworkChangeNotifierChromeos()
- : has_active_network_(false),
+ : NetworkChangeNotifier(NetworkChangeCalculatorParamsChromeos()),
+ has_active_network_(false),
connection_state_(chromeos::STATE_UNKNOWN),
connection_type_(CONNECTION_NONE),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
@@ -333,4 +334,17 @@ NetworkChangeNotifierChromeos::GetNetworkConnectionType(
return net::NetworkChangeNotifier::CONNECTION_UNKNOWN;
}
+// static
+net::NetworkChangeNotifier::NetworkChangeCalculatorParams
+NetworkChangeNotifierChromeos::NetworkChangeCalculatorParamsChromeos() {
+ NetworkChangeCalculatorParams params;
+ // Delay values arrived at by simple experimentation and adjusted so as to
+ // produce a single signal when switching between network connections.
+ params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(4000);
+ params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(1000);
+ params.connection_type_offline_delay_ = base::TimeDelta::FromMilliseconds(0);
+ params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(0);
+ return params;
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_change_notifier_chromeos.h b/chrome/browser/chromeos/net/network_change_notifier_chromeos.h
index cae489e..4a9ccf0 100644
--- a/chrome/browser/chromeos/net/network_change_notifier_chromeos.h
+++ b/chrome/browser/chromeos/net/network_change_notifier_chromeos.h
@@ -81,6 +81,9 @@ class NetworkChangeNotifierChromeos
static net::NetworkChangeNotifier::ConnectionType GetNetworkConnectionType(
const chromeos::Network* network);
+ // Get parameters for calculating new combined signal.
+ static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsChromeos();
+
// True if we previously had an active network around.
bool has_active_network_;
// Current active network's connection state.
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 0812638..53d184f 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -235,26 +235,31 @@ int GetSwitchValueAsInt(const CommandLine& command_line,
class IOThread::LoggingNetworkChangeObserver
: public net::NetworkChangeNotifier::IPAddressObserver,
- public net::NetworkChangeNotifier::ConnectionTypeObserver {
+ public net::NetworkChangeNotifier::ConnectionTypeObserver,
+ public net::NetworkChangeNotifier::NetworkChangeObserver {
public:
// |net_log| must remain valid throughout our lifetime.
explicit LoggingNetworkChangeObserver(net::NetLog* net_log)
: net_log_(net_log) {
net::NetworkChangeNotifier::AddIPAddressObserver(this);
net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+ net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
}
~LoggingNetworkChangeObserver() {
net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
+ net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}
+ // NetworkChangeNotifier::IPAddressObserver implementation.
virtual void OnIPAddressChanged() OVERRIDE {
VLOG(1) << "Observed a change to the network IP addresses";
net_log_->AddGlobalEntry(net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED);
}
+ // NetworkChangeNotifier::ConnectionTypeObserver implementation.
virtual void OnConnectionTypeChanged(
net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
std::string type_as_string =
@@ -268,6 +273,19 @@ class IOThread::LoggingNetworkChangeObserver
net::NetLog::StringCallback("new_connection_type", &type_as_string));
}
+ // NetworkChangeNotifier::NetworkChangeObserver implementation.
+ virtual void OnNetworkChanged(
+ net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
+ std::string type_as_string =
+ net::NetworkChangeNotifier::ConnectionTypeToString(type);
+
+ VLOG(1) << "Observed a network change to state " << type_as_string;
+
+ net_log_->AddGlobalEntry(
+ net::NetLog::TYPE_NETWORK_CHANGED,
+ net::NetLog::StringCallback("new_connection_type", &type_as_string));
+ }
+
private:
net::NetLog* net_log_;
DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver);
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc
index b765c85..6dce669 100644
--- a/net/android/network_change_notifier_android.cc
+++ b/net/android/network_change_notifier_android.cc
@@ -85,11 +85,26 @@ bool NetworkChangeNotifierAndroid::Register(JNIEnv* env) {
NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid(
NetworkChangeNotifierDelegateAndroid* delegate)
- : delegate_(delegate) {
+ : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()),
+ delegate_(delegate) {
SetConnectionType(NetworkChangeNotifier::CONNECTION_UNKNOWN);
delegate_->AddObserver(this);
}
+// static
+NetworkChangeNotifier::NetworkChangeCalculatorParams
+NetworkChangeNotifierAndroid::NetworkChangeCalculatorParamsAndroid() {
+ NetworkChangeCalculatorParams params;
+ // IPAddressChanged is produced immediately prior to ConnectionTypeChanged
+ // so delay IPAddressChanged so they get merged with the following
+ // ConnectionTypeChanged signal.
+ params.ip_address_offline_delay_ = base::TimeDelta::FromSeconds(1);
+ params.ip_address_online_delay_ = base::TimeDelta::FromSeconds(1);
+ params.connection_type_offline_delay_ = base::TimeDelta::FromSeconds(0);
+ params.connection_type_online_delay_ = base::TimeDelta::FromSeconds(0);
+ return params;
+}
+
void NetworkChangeNotifierAndroid::SetConnectionType(
ConnectionType new_connection_type) {
base::AutoLock auto_lock(connection_type_lock_);
diff --git a/net/android/network_change_notifier_android.h b/net/android/network_change_notifier_android.h
index 35c9b46..4f6180f 100644
--- a/net/android/network_change_notifier_android.h
+++ b/net/android/network_change_notifier_android.h
@@ -63,6 +63,8 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid
void SetConnectionType(ConnectionType new_connection_type);
+ static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsAndroid();
+
NetworkChangeNotifierDelegateAndroid* const delegate_;
mutable base::Lock connection_type_lock_; // Protects the state below.
ConnectionType connection_type_;
diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h
index d564e08..776efd2 100644
--- a/net/base/net_log_event_type_list.h
+++ b/net/base/net_log_event_type_list.h
@@ -1311,6 +1311,13 @@ EVENT_TYPE(NETWORK_IP_ADDRESSES_CHANGED)
// }
EVENT_TYPE(NETWORK_CONNECTIVITY_CHANGED)
+// This event is emitted whenever NetworkChangeNotifier determines that a change
+// occurs to the host computer's hardware or software that affects the route
+// network packets take to any network server.
+// {
+// "new_connection_type": <Type of the new connection>
+// }
+EVENT_TYPE(NETWORK_CHANGED)
// This event is emitted whenever HostResolverImpl receives a new DnsConfig
// from the DnsConfigService.
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index e8dd120..cf5557c 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -46,12 +46,14 @@ class MockNetworkChangeNotifier : public NetworkChangeNotifier {
class HistogramWatcher
: public NetworkChangeNotifier::ConnectionTypeObserver,
public NetworkChangeNotifier::IPAddressObserver,
- public NetworkChangeNotifier::DNSObserver {
+ public NetworkChangeNotifier::DNSObserver,
+ public NetworkChangeNotifier::NetworkChangeObserver {
public:
HistogramWatcher()
: last_ip_address_change_(base::TimeTicks::Now()),
last_connection_change_(base::TimeTicks::Now()),
last_dns_change_(base::TimeTicks::Now()),
+ last_network_change_(base::TimeTicks::Now()),
last_connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
offline_packets_received_(0) {}
@@ -64,6 +66,7 @@ class HistogramWatcher
NetworkChangeNotifier::AddConnectionTypeObserver(this);
NetworkChangeNotifier::AddIPAddressObserver(this);
NetworkChangeNotifier::AddDNSObserver(this);
+ NetworkChangeNotifier::AddNetworkChangeObserver(this);
}
virtual ~HistogramWatcher() {}
@@ -72,6 +75,9 @@ class HistogramWatcher
virtual void OnIPAddressChanged() OVERRIDE {
UMA_HISTOGRAM_MEDIUM_TIMES("NCN.IPAddressChange",
SinceLast(&last_ip_address_change_));
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "NCN.ConnectionTypeChangeToIPAddressChange",
+ last_ip_address_change_ - last_connection_change_);
}
// NetworkChangeNotifier::ConnectionTypeObserver implementation.
@@ -98,6 +104,9 @@ class HistogramWatcher
UMA_HISTOGRAM_MEDIUM_TIMES("NCN.OfflineChange",
SinceLast(&last_connection_change_));
}
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "NCN.IPAddressChangeToConnectionTypeChange",
+ last_connection_change_ - last_ip_address_change_);
offline_packets_received_ = 0;
last_connection_type_ = type;
@@ -110,6 +119,18 @@ class HistogramWatcher
SinceLast(&last_dns_change_));
}
+ // NetworkChangeNotifier::NetworkChangeObserver implementation.
+ virtual void OnNetworkChanged(
+ NetworkChangeNotifier::ConnectionType type) OVERRIDE {
+ if (type != NetworkChangeNotifier::CONNECTION_NONE) {
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOnlineChange",
+ SinceLast(&last_network_change_));
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES("NCN.NetworkOfflineChange",
+ SinceLast(&last_network_change_));
+ }
+ }
+
// Record histogram data whenever we receive a packet but think we're
// offline. Should only be called from the network thread.
void NotifyDataReceived(const GURL& source) {
@@ -153,6 +174,7 @@ class HistogramWatcher
base::TimeTicks last_ip_address_change_;
base::TimeTicks last_connection_change_;
base::TimeTicks last_dns_change_;
+ base::TimeTicks last_network_change_;
base::TimeTicks last_offline_packet_received_;
base::TimeTicks last_polled_connection_;
// |polling_interval_| is initialized by |OnConnectionTypeChanged| on our
@@ -193,6 +215,79 @@ class NetworkChangeNotifier::NetworkState {
DnsConfig dns_config_;
};
+NetworkChangeNotifier::NetworkChangeCalculatorParams::
+ NetworkChangeCalculatorParams() {
+}
+
+// Calculates NetworkChange signal from IPAddress and ConnectionType signals.
+class NetworkChangeNotifier::NetworkChangeCalculator
+ : public ConnectionTypeObserver,
+ public IPAddressObserver {
+ public:
+ NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
+ : params_(params),
+ have_announced_(false),
+ last_announced_connection_type_(CONNECTION_NONE),
+ pending_connection_type_(CONNECTION_NONE) {}
+
+ void Init() {
+ AddConnectionTypeObserver(this);
+ AddIPAddressObserver(this);
+ }
+
+ virtual ~NetworkChangeCalculator() {
+ RemoveConnectionTypeObserver(this);
+ RemoveIPAddressObserver(this);
+ }
+
+ // NetworkChangeNotifier::IPAddressObserver implementation.
+ virtual void OnIPAddressChanged() OVERRIDE {
+ base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
+ ? params_.ip_address_offline_delay_ : params_.ip_address_online_delay_;
+ // Cancels any previous timer.
+ timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
+ }
+
+ // NetworkChangeNotifier::ConnectionTypeObserver implementation.
+ virtual void OnConnectionTypeChanged(ConnectionType type) OVERRIDE {
+ pending_connection_type_ = type;
+ base::TimeDelta delay = last_announced_connection_type_ == CONNECTION_NONE
+ ? params_.connection_type_offline_delay_
+ : params_.connection_type_online_delay_;
+ // Cancels any previous timer.
+ timer_.Start(FROM_HERE, delay, this, &NetworkChangeCalculator::Notify);
+ }
+
+ private:
+ void Notify() {
+ // Don't bother signaling about dead connections.
+ if (have_announced_ &&
+ (last_announced_connection_type_ == CONNECTION_NONE) &&
+ (pending_connection_type_ == CONNECTION_NONE)) {
+ return;
+ }
+ have_announced_ = true;
+ last_announced_connection_type_ = pending_connection_type_;
+ // Immediately before sending out an online signal, send out an offline
+ // signal to perform any destructive actions before constructive actions.
+ if (pending_connection_type_ != CONNECTION_NONE)
+ NetworkChangeNotifier::NotifyObserversOfNetworkChange(CONNECTION_NONE);
+ NetworkChangeNotifier::NotifyObserversOfNetworkChange(
+ pending_connection_type_);
+ }
+
+ const NetworkChangeCalculatorParams params_;
+
+ // Indicates if NotifyObserversOfNetworkChange has been called yet.
+ bool have_announced_;
+ // Last value passed to NotifyObserversOfNetworkChange.
+ ConnectionType last_announced_connection_type_;
+ // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
+ ConnectionType pending_connection_type_;
+ // Used to delay notifications so duplicates can be combined.
+ base::OneShotTimer<NetworkChangeCalculator> timer_;
+};
+
NetworkChangeNotifier::~NetworkChangeNotifier() {
DCHECK_EQ(this, g_network_change_notifier);
g_network_change_notifier = NULL;
@@ -346,6 +441,14 @@ void NetworkChangeNotifier::AddDNSObserver(DNSObserver* observer) {
}
}
+void NetworkChangeNotifier::AddNetworkChangeObserver(
+ NetworkChangeObserver* observer) {
+ if (g_network_change_notifier) {
+ g_network_change_notifier->network_change_observer_list_->AddObserver(
+ observer);
+ }
+}
+
void NetworkChangeNotifier::RemoveIPAddressObserver(
IPAddressObserver* observer) {
if (g_network_change_notifier) {
@@ -369,7 +472,17 @@ void NetworkChangeNotifier::RemoveDNSObserver(DNSObserver* observer) {
}
}
-NetworkChangeNotifier::NetworkChangeNotifier()
+void NetworkChangeNotifier::RemoveNetworkChangeObserver(
+ NetworkChangeObserver* observer) {
+ if (g_network_change_notifier) {
+ g_network_change_notifier->network_change_observer_list_->RemoveObserver(
+ observer);
+ }
+}
+
+NetworkChangeNotifier::NetworkChangeNotifier(
+ const NetworkChangeCalculatorParams& params
+ /*= NetworkChangeCalculatorParams()*/)
: ip_address_observer_list_(
new ObserverListThreadSafe<IPAddressObserver>(
ObserverListBase<IPAddressObserver>::NOTIFY_EXISTING_ONLY)),
@@ -379,10 +492,15 @@ NetworkChangeNotifier::NetworkChangeNotifier()
resolver_state_observer_list_(
new ObserverListThreadSafe<DNSObserver>(
ObserverListBase<DNSObserver>::NOTIFY_EXISTING_ONLY)),
+ network_change_observer_list_(
+ new ObserverListThreadSafe<NetworkChangeObserver>(
+ ObserverListBase<NetworkChangeObserver>::NOTIFY_EXISTING_ONLY)),
network_state_(new NetworkState()),
- histogram_watcher_(new HistogramWatcher()) {
+ histogram_watcher_(new HistogramWatcher()),
+ network_change_calculator_(new NetworkChangeCalculator(params)) {
DCHECK(!g_network_change_notifier);
g_network_change_notifier = this;
+ network_change_calculator_->Init();
}
#if defined(OS_LINUX)
@@ -424,6 +542,15 @@ void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange() {
}
}
+void NetworkChangeNotifier::NotifyObserversOfNetworkChange(
+ ConnectionType type) {
+ if (g_network_change_notifier) {
+ g_network_change_notifier->network_change_observer_list_->Notify(
+ &NetworkChangeObserver::OnNetworkChanged,
+ type);
+ }
+}
+
NetworkChangeNotifier::DisableForTest::DisableForTest()
: network_change_notifier_(g_network_change_notifier) {
DCHECK(g_network_change_notifier);
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index 84e399e..fe8d091 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/observer_list_threadsafe.h"
+#include "base/time.h"
#include "net/base/net_export.h"
class GURL;
@@ -86,6 +87,43 @@ class NET_EXPORT NetworkChangeNotifier {
DISALLOW_COPY_AND_ASSIGN(DNSObserver);
};
+ class NET_EXPORT NetworkChangeObserver {
+ public:
+ // OnNetworkChanged will be called when a change occurs to the host
+ // computer's hardware or software that affects the route network packets
+ // take to any network server. Some examples:
+ // 1. A network connection becoming available or going away. For example
+ // plugging or unplugging an Ethernet cable, WiFi or cellular modem
+ // connecting or disconnecting from a network, or a VPN tunnel being
+ // established or taken down.
+ // 2. An active network connection's IP address changes.
+ // 3. A change to the local IP routing tables.
+ // The signal shall only be produced when the change is complete. For
+ // example if a new network connection has become available, only give the
+ // signal once we think the O/S has finished establishing the connection
+ // (i.e. DHCP is done) to the point where the new connection is usable.
+ // The signal shall not be produced spuriously as it will be triggering some
+ // expensive operations, like socket pools closing all connections and
+ // sockets and then re-establishing them.
+ // |type| indicates the type of the active primary network connection after
+ // the change. Observers performing "constructive" activities like trying
+ // to establish a connection to a server should only do so when
+ // |type != CONNECTION_NONE|. Observers performing "destructive" activities
+ // like resetting already established server connections should only do so
+ // when |type == CONNECTION_NONE|. OnNetworkChanged will always be called
+ // with CONNECTION_NONE immediately prior to being called with an online
+ // state; this is done to make sure that destructive actions take place
+ // prior to constructive actions.
+ virtual void OnNetworkChanged(ConnectionType type) = 0;
+
+ protected:
+ NetworkChangeObserver() {}
+ virtual ~NetworkChangeObserver() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkChangeObserver);
+ };
+
virtual ~NetworkChangeNotifier();
// See the description of NetworkChangeNotifier::GetConnectionType().
@@ -155,6 +193,7 @@ class NET_EXPORT NetworkChangeNotifier {
static void AddIPAddressObserver(IPAddressObserver* observer);
static void AddConnectionTypeObserver(ConnectionTypeObserver* observer);
static void AddDNSObserver(DNSObserver* observer);
+ static void AddNetworkChangeObserver(NetworkChangeObserver* observer);
// Unregisters |observer| from receiving notifications. This must be called
// on the same thread on which AddObserver() was called. Like AddObserver(),
@@ -166,6 +205,7 @@ class NET_EXPORT NetworkChangeNotifier {
static void RemoveIPAddressObserver(IPAddressObserver* observer);
static void RemoveConnectionTypeObserver(ConnectionTypeObserver* observer);
static void RemoveDNSObserver(DNSObserver* observer);
+ static void RemoveNetworkChangeObserver(NetworkChangeObserver* observer);
// Allow unit tests to trigger notifications.
static void NotifyObserversOfIPAddressChangeForTests() {
@@ -185,7 +225,31 @@ class NET_EXPORT NetworkChangeNotifier {
static void InitHistogramWatcher();
protected:
- NetworkChangeNotifier();
+ // NetworkChanged signal is calculated from the IPAddressChanged and
+ // ConnectionTypeChanged signals. Delay parameters control how long to delay
+ // producing NetworkChanged signal after particular input signals so as to
+ // combine duplicates. In other words if an input signal is repeated within
+ // the corresponding delay period, only one resulting NetworkChange signal is
+ // produced.
+ struct NET_EXPORT NetworkChangeCalculatorParams {
+ NetworkChangeCalculatorParams();
+ // Controls delay after OnIPAddressChanged when transitioning from an
+ // offline state.
+ base::TimeDelta ip_address_offline_delay_;
+ // Controls delay after OnIPAddressChanged when transitioning from an
+ // online state.
+ base::TimeDelta ip_address_online_delay_;
+ // Controls delay after OnConnectionTypeChanged when transitioning from an
+ // offline state.
+ base::TimeDelta connection_type_offline_delay_;
+ // Controls delay after OnConnectionTypeChanged when transitioning from an
+ // online state.
+ base::TimeDelta connection_type_online_delay_;
+ };
+
+ explicit NetworkChangeNotifier(
+ const NetworkChangeCalculatorParams& params =
+ NetworkChangeCalculatorParams());
#if defined(OS_LINUX)
// Returns the AddressTrackerLinux if present.
@@ -200,6 +264,7 @@ class NET_EXPORT NetworkChangeNotifier {
static void NotifyObserversOfIPAddressChange();
static void NotifyObserversOfConnectionTypeChange();
static void NotifyObserversOfDNSChange();
+ static void NotifyObserversOfNetworkChange(ConnectionType type);
// Stores |config| in NetworkState and notifies observers.
static void SetDnsConfig(const DnsConfig& config);
@@ -211,6 +276,7 @@ class NET_EXPORT NetworkChangeNotifier {
friend class NetworkChangeNotifierWinTest;
class NetworkState;
+ class NetworkChangeCalculator;
// Allows a second NetworkChangeNotifier to be created for unit testing, so
// the test suite can create a MockNetworkChangeNotifier, but platform
@@ -235,6 +301,8 @@ class NET_EXPORT NetworkChangeNotifier {
connection_type_observer_list_;
const scoped_refptr<ObserverListThreadSafe<DNSObserver> >
resolver_state_observer_list_;
+ const scoped_refptr<ObserverListThreadSafe<NetworkChangeObserver> >
+ network_change_observer_list_;
// The current network state. Hosts DnsConfig, exposed via GetDnsConfig.
scoped_ptr<NetworkState> network_state_;
@@ -242,6 +310,9 @@ class NET_EXPORT NetworkChangeNotifier {
// A little-piggy-back observer that simply logs UMA histogram data.
scoped_ptr<HistogramWatcher> histogram_watcher_;
+ // Computes NetworkChange signal from IPAddress and ConnectionType signals.
+ scoped_ptr<NetworkChangeCalculator> network_change_calculator_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifier);
};
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
index fc2b372..1a16f04 100644
--- a/net/base/network_change_notifier_linux.cc
+++ b/net/base/network_change_notifier_linux.cc
@@ -69,7 +69,8 @@ NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::Create() {
}
NetworkChangeNotifierLinux::NetworkChangeNotifierLinux()
- : notifier_thread_(new Thread()) {
+ : NetworkChangeNotifier(NetworkChangeCalculatorParamsLinux()),
+ notifier_thread_(new Thread()) {
// We create this notifier thread because the notification implementation
// needs a MessageLoopForIO, and there's no guarantee that
// MessageLoop::current() meets that criterion.
@@ -83,6 +84,20 @@ NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() {
notifier_thread_->Stop();
}
+// static
+NetworkChangeNotifier::NetworkChangeCalculatorParams
+NetworkChangeNotifierLinux::NetworkChangeCalculatorParamsLinux() {
+ NetworkChangeCalculatorParams params;
+ // Delay values arrived at by simple experimentation and adjusted so as to
+ // produce a single signal when switching between network connections.
+ params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(2000);
+ params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(2000);
+ params.connection_type_offline_delay_ =
+ base::TimeDelta::FromMilliseconds(1500);
+ params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500);
+ return params;
+}
+
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierLinux::GetCurrentConnectionType() const {
return notifier_thread_->GetCurrentConnectionType();
diff --git a/net/base/network_change_notifier_linux.h b/net/base/network_change_notifier_linux.h
index 6e10854..a7080d9 100644
--- a/net/base/network_change_notifier_linux.h
+++ b/net/base/network_change_notifier_linux.h
@@ -23,6 +23,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux
NetworkChangeNotifierLinux();
virtual ~NetworkChangeNotifierLinux();
+ static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsLinux();
// NetworkChangeNotifier:
virtual ConnectionType GetCurrentConnectionType() const OVERRIDE;
diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc
index 515cbd0..2c350df 100644
--- a/net/base/network_change_notifier_mac.cc
+++ b/net/base/network_change_notifier_mac.cc
@@ -63,7 +63,8 @@ class NetworkChangeNotifierMac::DnsConfigServiceThread : public base::Thread {
};
NetworkChangeNotifierMac::NetworkChangeNotifierMac()
- : connection_type_(CONNECTION_UNKNOWN),
+ : NetworkChangeNotifier(NetworkChangeCalculatorParamsMac()),
+ connection_type_(CONNECTION_UNKNOWN),
connection_type_initialized_(false),
initial_connection_type_cv_(&connection_type_lock_),
forwarder_(this),
@@ -89,6 +90,20 @@ NetworkChangeNotifierMac::~NetworkChangeNotifierMac() {
}
}
+// static
+NetworkChangeNotifier::NetworkChangeCalculatorParams
+NetworkChangeNotifierMac::NetworkChangeCalculatorParamsMac() {
+ NetworkChangeCalculatorParams params;
+ // Delay values arrived at by simple experimentation and adjusted so as to
+ // produce a single signal when switching between network connections.
+ params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(500);
+ params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(500);
+ params.connection_type_offline_delay_ =
+ base::TimeDelta::FromMilliseconds(1000);
+ params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500);
+ return params;
+}
+
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierMac::GetCurrentConnectionType() const {
base::AutoLock lock(connection_type_lock_);
diff --git a/net/base/network_change_notifier_mac.h b/net/base/network_change_notifier_mac.h
index 9a9e6bf..ad9429a 100644
--- a/net/base/network_change_notifier_mac.h
+++ b/net/base/network_change_notifier_mac.h
@@ -59,6 +59,8 @@ class NetworkChangeNotifierMac: public NetworkChangeNotifier {
SCNetworkConnectionFlags flags,
void* notifier);
+ static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsMac();
+
// These must be constructed before config_watcher_ to ensure
// the lock is in a valid state when Forwarder::Init is called.
ConnectionType connection_type_;
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc
index a32a84d..d891ecc 100644
--- a/net/base/network_change_notifier_win.cc
+++ b/net/base/network_change_notifier_win.cc
@@ -52,7 +52,8 @@ class NetworkChangeNotifierWin::DnsConfigServiceThread : public base::Thread {
};
NetworkChangeNotifierWin::NetworkChangeNotifierWin()
- : is_watching_(false),
+ : NetworkChangeNotifier(NetworkChangeCalculatorParamsWin()),
+ is_watching_(false),
sequential_failures_(0),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
dns_config_service_thread_(new DnsConfigServiceThread()),
@@ -71,6 +72,20 @@ NetworkChangeNotifierWin::~NetworkChangeNotifierWin() {
WSACloseEvent(addr_overlapped_.hEvent);
}
+// static
+NetworkChangeNotifier::NetworkChangeCalculatorParams
+NetworkChangeNotifierWin::NetworkChangeCalculatorParamsWin() {
+ NetworkChangeCalculatorParams params;
+ // Delay values arrived at by simple experimentation and adjusted so as to
+ // produce a single signal when switching between network connections.
+ params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(1500);
+ params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(1500);
+ params.connection_type_offline_delay_ =
+ base::TimeDelta::FromMilliseconds(1500);
+ params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500);
+ return params;
+}
+
// This implementation does not return the actual connection type but merely
// determines if the user is "online" (in which case it returns
// CONNECTION_UNKNOWN) or "offline" (and then it returns CONNECTION_NONE).
diff --git a/net/base/network_change_notifier_win.h b/net/base/network_change_notifier_win.h
index 6af7f06..ef239aa 100644
--- a/net/base/network_change_notifier_win.h
+++ b/net/base/network_change_notifier_win.h
@@ -71,6 +71,8 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin
// created on.
virtual bool WatchForAddressChangeInternal();
+ static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsWin();
+
// All member variables may only be accessed on the thread |this| was created
// on.
diff --git a/net/tools/net_watcher/net_watcher.cc b/net/tools/net_watcher/net_watcher.cc
index b5aa4e3..6950b5d 100644
--- a/net/tools/net_watcher/net_watcher.cc
+++ b/net/tools/net_watcher/net_watcher.cc
@@ -81,6 +81,7 @@ class NetWatcher :
public net::NetworkChangeNotifier::IPAddressObserver,
public net::NetworkChangeNotifier::ConnectionTypeObserver,
public net::NetworkChangeNotifier::DNSObserver,
+ public net::NetworkChangeNotifier::NetworkChangeObserver,
public net::ProxyConfigService::Observer {
public:
NetWatcher() {}
@@ -104,6 +105,13 @@ class NetWatcher :
LOG(INFO) << "OnDNSChanged()";
}
+ // net::NetworkChangeNotifier::NetworkChangeObserver implementation.
+ virtual void OnNetworkChanged(
+ net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
+ LOG(INFO) << "OnNetworkChanged("
+ << ConnectionTypeToString(type) << ")";
+ }
+
// net::ProxyConfigService::Observer implementation.
virtual void OnProxyConfigChanged(
const net::ProxyConfig& config,
@@ -155,6 +163,7 @@ int main(int argc, char* argv[]) {
net::NetworkChangeNotifier::AddIPAddressObserver(&net_watcher);
net::NetworkChangeNotifier::AddConnectionTypeObserver(&net_watcher);
net::NetworkChangeNotifier::AddDNSObserver(&net_watcher);
+ net::NetworkChangeNotifier::AddNetworkChangeObserver(&net_watcher);
proxy_config_service->AddObserver(&net_watcher);
@@ -182,6 +191,7 @@ int main(int argc, char* argv[]) {
net::NetworkChangeNotifier::RemoveDNSObserver(&net_watcher);
net::NetworkChangeNotifier::RemoveConnectionTypeObserver(&net_watcher);
net::NetworkChangeNotifier::RemoveIPAddressObserver(&net_watcher);
+ net::NetworkChangeNotifier::RemoveNetworkChangeObserver(&net_watcher);
return 0;
}