summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/chrome_browser_main_chromeos.cc28
-rw-r--r--chromeos/chromeos.gyp5
-rw-r--r--chromeos/network/managed_state.h2
-rw-r--r--chromeos/network/network_change_notifier_chromeos.cc191
-rw-r--r--chromeos/network/network_change_notifier_chromeos.h81
-rw-r--r--chromeos/network/network_change_notifier_chromeos_unittest.cc185
-rw-r--r--chromeos/network/network_change_notifier_factory_chromeos.cc30
-rw-r--r--chromeos/network/network_change_notifier_factory_chromeos.h30
-rw-r--r--chromeos/network/network_state.h1
9 files changed, 548 insertions, 5 deletions
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 7dfe1d7..f549ab0 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -85,6 +85,8 @@
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/disks/disk_mount_manager.h"
#include "chromeos/display/output_configurator.h"
+#include "chromeos/network/network_change_notifier_chromeos.h"
+#include "chromeos/network/network_change_notifier_factory_chromeos.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state_handler.h"
@@ -254,7 +256,10 @@ class DBusServices {
// Initialize the network change notifier for Chrome OS. The network
// change notifier starts to monitor changes from the power manager and
// the network manager.
- CrosNetworkChangeNotifierFactory::GetInstance()->Init();
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kEnableNewNetworkHandlers)) {
+ CrosNetworkChangeNotifierFactory::GetInstance()->Init();
+ }
// Likewise, initialize the upgrade detector for Chrome OS. The upgrade
// detector starts to monitor changes from the update engine.
@@ -287,6 +292,9 @@ class DBusServices {
chromeos::NetworkStateHandler::Initialize();
chromeos::NetworkConfigurationHandler::Initialize();
network_handlers_initialized_ = true;
+ // TODO(gauravsh): This needs re-factoring. NetworkChangeNotifier choice
+ // needs to be made before about:flags are processed.
+ NetworkChangeNotifierFactoryChromeos::GetInstance()->Initialize();
}
~DBusServices() {
@@ -382,9 +390,18 @@ void ChromeBrowserMainPartsChromeos::PreMainMessageLoopStart() {
// Replace the default NetworkChangeNotifierFactory with ChromeOS specific
// implementation. This must be done before BrowserMainLoop calls
// net::NetworkChangeNotifier::Create() in MainMessageLoopStart().
- net::NetworkChangeNotifier::SetFactory(
- new CrosNetworkChangeNotifierFactory());
-
+ net::NetworkChangeNotifierFactory* network_change_factory;
+ // Note: At the time this is called, we have not processed about:flags
+ // so this requires that the network handler flag was passed in at the command
+ // line.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kEnableNewNetworkHandlers)) {
+ network_change_factory = new CrosNetworkChangeNotifierFactory();
+ } else {
+ LOG(WARNING) << "Using new connection change notifier.";
+ network_change_factory = new NetworkChangeNotifierFactoryChromeos();
+ }
+ net::NetworkChangeNotifier::SetFactory(network_change_factory);
ChromeBrowserMainPartsLinux::PreMainMessageLoopStart();
}
@@ -399,7 +416,6 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopStart() {
// Threads are initialized between MainMessageLoopStart and MainMessageLoopRun.
// about_flags settings are applied in ChromeBrowserMainParts::PreCreateThreads.
-
void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
// Must be called after about_flags settings are applied (see note above).
dbus_services_->InitializeNetworkHandlers();
@@ -641,6 +657,8 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
// the network manager.
if (CrosNetworkChangeNotifierFactory::GetInstance())
CrosNetworkChangeNotifierFactory::GetInstance()->Shutdown();
+ if (NetworkChangeNotifierFactoryChromeos::GetInstance())
+ NetworkChangeNotifierFactoryChromeos::GetInstance()->Shutdown();
if (chromeos::NetworkPortalDetector::IsEnabled() &&
chromeos::NetworkPortalDetector::GetInstance()) {
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index fbe4497..670fac3 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -129,6 +129,10 @@
'network/device_state.h',
'network/managed_state.cc',
'network/managed_state.h',
+ 'network/network_change_notifier_chromeos.cc',
+ 'network/network_change_notifier_chromeos.h',
+ 'network/network_change_notifier_factory_chromeos.cc',
+ 'network/network_change_notifier_factory_chromeos.h',
'network/network_configuration_handler.cc',
'network/network_configuration_handler.h',
'network/network_event_log.cc',
@@ -321,6 +325,7 @@
'dbus/introspectable_client_unittest.cc',
'dbus/modem_messaging_client_unittest.cc',
'disks/disk_mount_manager_unittest.cc',
+ 'network/network_change_notifier_chromeos_unittest.cc',
'network/network_configuration_handler_unittest.cc',
'network/network_event_log_unittest.cc',
'network/network_sms_handler_unittest.cc',
diff --git a/chromeos/network/managed_state.h b/chromeos/network/managed_state.h
index 0138df64..a8176e5 100644
--- a/chromeos/network/managed_state.h
+++ b/chromeos/network/managed_state.h
@@ -71,6 +71,8 @@ class ManagedState {
std::string* out_value);
private:
+ friend class NetworkChangeNotifierChromeosUpdateTest;
+
ManagedType managed_type_;
// The path (e.g. service path or device path) of the managed state object.
diff --git a/chromeos/network/network_change_notifier_chromeos.cc b/chromeos/network/network_change_notifier_chromeos.cc
new file mode 100644
index 0000000..00fab2d
--- /dev/null
+++ b/chromeos/network/network_change_notifier_chromeos.cc
@@ -0,0 +1,191 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "chromeos/network/network_change_notifier_chromeos.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "net/base/network_change_notifier.h"
+#include "net/dns/dns_config_service_posix.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+// DNS config services on Chrome OS are signalled by the network state handler
+// rather than relying on watching files in /etc.
+class NetworkChangeNotifierChromeos::DnsConfigService
+ : public net::internal::DnsConfigServicePosix {
+ public:
+ DnsConfigService();
+ virtual ~DnsConfigService();
+
+ // net::internal::DnsConfigService() overrides.
+ virtual bool StartWatching() OVERRIDE;
+
+ virtual void OnNetworkChange();
+};
+
+NetworkChangeNotifierChromeos::DnsConfigService::DnsConfigService() {
+}
+
+NetworkChangeNotifierChromeos::DnsConfigService::~DnsConfigService() {
+}
+
+bool NetworkChangeNotifierChromeos::DnsConfigService::StartWatching() {
+ // DNS config changes are handled and notified by the network state handlers.
+ return true;
+}
+
+void NetworkChangeNotifierChromeos::DnsConfigService::OnNetworkChange() {
+ InvalidateConfig();
+ InvalidateHosts();
+ ReadNow();
+}
+
+NetworkChangeNotifierChromeos::NetworkChangeNotifierChromeos()
+ : NetworkChangeNotifier(NetworkChangeCalculatorParamsChromeos()),
+ connection_type_(CONNECTION_NONE) {
+}
+
+NetworkChangeNotifierChromeos::~NetworkChangeNotifierChromeos() {
+}
+
+void NetworkChangeNotifierChromeos::Initialize() {
+ NetworkStateHandler::Get()->AddObserver(this);
+
+ dns_config_service_.reset(new DnsConfigService());
+ dns_config_service_->WatchConfig(
+ base::Bind(net::NetworkChangeNotifier::SetDnsConfig));
+
+ // Update initial connection state.
+ DefaultNetworkChanged(NetworkStateHandler::Get()->DefaultNetwork());
+}
+
+void NetworkChangeNotifierChromeos::Shutdown() {
+ dns_config_service_.reset();
+ if (NetworkStateHandler::Get())
+ NetworkStateHandler::Get()->RemoveObserver(this);
+}
+
+net::NetworkChangeNotifier::ConnectionType
+NetworkChangeNotifierChromeos::GetCurrentConnectionType() const {
+ return connection_type_;
+}
+
+void NetworkChangeNotifierChromeos::DefaultNetworkChanged(
+ const chromeos::NetworkState* default_network) {
+ bool connection_type_changed = false;
+ bool ip_address_changed = false;
+ bool dns_changed = false;
+
+ UpdateState(default_network, &connection_type_changed,
+ &ip_address_changed, &dns_changed);
+
+ if (connection_type_changed)
+ NetworkChangeNotifierChromeos:: NotifyObserversOfConnectionTypeChange();
+ if (ip_address_changed)
+ NetworkChangeNotifierChromeos::NotifyObserversOfIPAddressChange();
+ if (dns_changed)
+ dns_config_service_->OnNetworkChange();
+}
+
+void NetworkChangeNotifierChromeos::UpdateState(
+ const chromeos::NetworkState* default_network,
+ bool* connection_type_changed,
+ bool* ip_address_changed,
+ bool* dns_changed) {
+ *connection_type_changed = false;
+ *ip_address_changed = false;
+ *dns_changed = false;
+ // TODO(gauravsh): DNS changes will be detected once ip config
+ // support is hooked into NetworkStateHandler. For now,
+ // we report a DNS change on changes to the default network (including
+ // loss).
+ if (!default_network || !default_network->IsConnectedState()) {
+ // If we lost a default network, we must update our state and notify
+ // observers, otherwise we have nothing do. (Under normal circumstances,
+ // we should never get duplicate no default network notifications).
+ if (connection_type_ != CONNECTION_NONE) {
+ *ip_address_changed = true;
+ *dns_changed = true;
+ *connection_type_changed = true;
+ connection_type_ = CONNECTION_NONE;
+ service_path_.clear();
+ ip_address_.clear();
+ }
+ return;
+ }
+
+ // We do have a default network and it is connected.
+ net::NetworkChangeNotifier::ConnectionType new_connection_type =
+ ConnectionTypeFromShill(default_network->type(),
+ default_network->technology());
+ if (new_connection_type != connection_type_) {
+ VLOG(1) << "Connection type changed from " << connection_type_ << " -> "
+ << new_connection_type;
+ *connection_type_changed = true;
+ *dns_changed = true;
+ }
+ if (default_network->path() != service_path_ ||
+ default_network->ip_address() != ip_address_) {
+ VLOG(1) << "Service path changed from " << service_path_ << " -> "
+ << default_network->path();
+ VLOG(1) << "IP Address changed from " << ip_address_ << " -> "
+ << default_network->ip_address();
+ *ip_address_changed = true;
+ *dns_changed = true;
+ }
+ connection_type_ = new_connection_type;
+ service_path_ = default_network->path();
+ ip_address_ = default_network->ip_address();
+}
+
+// static
+net::NetworkChangeNotifier::ConnectionType
+NetworkChangeNotifierChromeos::ConnectionTypeFromShill(
+ const std::string& type, const std::string& technology) {
+ if (type == flimflam::kTypeEthernet)
+ return CONNECTION_ETHERNET;
+ else if (type == flimflam::kTypeWifi)
+ return CONNECTION_WIFI;
+ else if (type == flimflam::kTypeWimax)
+ return CONNECTION_4G;
+
+ if (type != flimflam::kTypeCellular)
+ return CONNECTION_UNKNOWN;
+
+ // For cellular types, mapping depends on the technology.
+ if (technology == flimflam::kNetworkTechnologyEvdo ||
+ technology == flimflam::kNetworkTechnologyGsm ||
+ technology == flimflam::kNetworkTechnologyUmts ||
+ technology == flimflam::kNetworkTechnologyHspa) {
+ return CONNECTION_3G;
+ } else if (technology == flimflam::kNetworkTechnologyHspaPlus ||
+ technology == flimflam::kNetworkTechnologyLte ||
+ technology == flimflam::kNetworkTechnologyLteAdvanced) {
+ return CONNECTION_4G;
+ } else {
+ return CONNECTION_2G; // Default cellular type is 2G.
+ }
+}
+
+// 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(500);
+ params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500);
+ return params;
+}
+
+} // namespace chromeos
+
diff --git a/chromeos/network/network_change_notifier_chromeos.h b/chromeos/network/network_change_notifier_chromeos.h
new file mode 100644
index 0000000..c0dc28e
--- /dev/null
+++ b/chromeos/network/network_change_notifier_chromeos.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
+#define CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/network/network_state_handler_observer.h"
+#include "net/base/network_change_notifier.h"
+
+namespace chromeos {
+
+class CHROMEOS_EXPORT NetworkChangeNotifierChromeos
+ : public net::NetworkChangeNotifier,
+ public chromeos::NetworkStateHandlerObserver {
+ public:
+ NetworkChangeNotifierChromeos();
+ virtual ~NetworkChangeNotifierChromeos();
+
+ // Starts observing changes from the network state handler.
+ void Initialize();
+
+ // Stops observing changes from the network state handler.
+ void Shutdown();
+
+ // NetworkChangeNotifier overrides.
+ virtual net::NetworkChangeNotifier::ConnectionType
+ GetCurrentConnectionType() const OVERRIDE;
+
+ // NetworkStateHandlerObserver overrides.
+ virtual void DefaultNetworkChanged(
+ const chromeos::NetworkState* default_network) OVERRIDE;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(NetworkChangeNotifierChromeosTest,
+ ConnectionTypeFromShill);
+ friend class NetworkChangeNotifierChromeosUpdateTest;
+
+ class DnsConfigService;
+
+ // Updates the notifier state based on a default network update.
+ // |connection_type_changed| is set to true if we must report a connection
+ // type change.
+ // |ip_address_changed| is set to true if we must report an IP address change.
+ // |dns_changed| is set to true if we must report a DNS config change.
+ void UpdateState(const chromeos::NetworkState* default_network,
+ bool* connection_type_changed,
+ bool* ip_address_changed,
+ bool* dns_changed);
+
+ // Maps the shill network type and technology to its NetworkChangeNotifier
+ // equivalent.
+ static net::NetworkChangeNotifier::ConnectionType
+ ConnectionTypeFromShill(const std::string& type,
+ const std::string& technology);
+
+ // Calculates parameters used for network change notifier online/offline
+ // signals.
+ static net::NetworkChangeNotifier::NetworkChangeCalculatorParams
+ NetworkChangeCalculatorParamsChromeos();
+
+ NetworkChangeNotifier::ConnectionType connection_type_;
+ // IP address for the current default network.
+ std::string ip_address_;
+ // Service path for the current default network.
+ std::string service_path_;
+
+ scoped_ptr<DnsConfigService> dns_config_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierChromeos);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
diff --git a/chromeos/network/network_change_notifier_chromeos_unittest.cc b/chromeos/network/network_change_notifier_chromeos_unittest.cc
new file mode 100644
index 0000000..1771322
--- /dev/null
+++ b/chromeos/network/network_change_notifier_chromeos_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/network/network_change_notifier_chromeos.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "chromeos/network/network_change_notifier_factory_chromeos.h"
+#include "chromeos/network/network_state.h"
+#include "net/base/network_change_notifier.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+using net::NetworkChangeNotifier;
+
+TEST(NetworkChangeNotifierChromeosTest, ConnectionTypeFromShill) {
+ struct TypeMapping {
+ const char* shill_type;
+ const char* technology;
+ NetworkChangeNotifier::ConnectionType connection_type;
+ };
+ TypeMapping type_mappings[] = {
+ { flimflam::kTypeEthernet, "", NetworkChangeNotifier::CONNECTION_ETHERNET },
+ { flimflam::kTypeWifi, "", NetworkChangeNotifier::CONNECTION_WIFI },
+ { flimflam::kTypeWimax, "", NetworkChangeNotifier::CONNECTION_4G },
+ { "unknown type", "unknown technology",
+ NetworkChangeNotifier::CONNECTION_UNKNOWN },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnology1Xrtt,
+ NetworkChangeNotifier::CONNECTION_2G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyGprs,
+ NetworkChangeNotifier::CONNECTION_2G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyEdge,
+ NetworkChangeNotifier::CONNECTION_2G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyEvdo,
+ NetworkChangeNotifier::CONNECTION_3G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyGsm,
+ NetworkChangeNotifier::CONNECTION_3G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyUmts,
+ NetworkChangeNotifier::CONNECTION_3G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyHspa,
+ NetworkChangeNotifier::CONNECTION_3G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyHspaPlus,
+ NetworkChangeNotifier::CONNECTION_4G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyLte,
+ NetworkChangeNotifier::CONNECTION_4G },
+ { flimflam::kTypeCellular, flimflam::kNetworkTechnologyLteAdvanced,
+ NetworkChangeNotifier::CONNECTION_4G },
+ { flimflam::kTypeCellular, "unknown technology",
+ NetworkChangeNotifier::CONNECTION_2G }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(type_mappings); ++i) {
+ NetworkChangeNotifier::ConnectionType type =
+ NetworkChangeNotifierChromeos::ConnectionTypeFromShill(
+ type_mappings[i].shill_type, type_mappings[i].technology);
+ EXPECT_EQ(type_mappings[i].connection_type, type);
+ }
+}
+
+class NetworkChangeNotifierChromeosUpdateTest : public testing::Test {
+ protected:
+ NetworkChangeNotifierChromeosUpdateTest() : default_network_("") {
+ }
+ virtual ~NetworkChangeNotifierChromeosUpdateTest() {}
+
+ void SetNotifierState(NetworkChangeNotifier::ConnectionType type,
+ std::string service_path,
+ std::string ip_address) {
+ notifier_.ip_address_ = ip_address;
+ notifier_.service_path_ = service_path;
+ notifier_.connection_type_ = type;
+ }
+
+ void VerifyNotifierState(NetworkChangeNotifier::ConnectionType expected_type,
+ std::string expected_service_path,
+ std::string expected_ip_address) {
+ EXPECT_EQ(expected_type, notifier_.connection_type_);
+ EXPECT_EQ(expected_ip_address, notifier_.ip_address_);
+ EXPECT_EQ(expected_service_path, notifier_.service_path_);
+ }
+
+ // Sets the default network state used for notifier updates.
+ void SetDefaultNetworkState(bool is_connected,
+ std::string type,
+ std::string technology,
+ std::string service_path,
+ std::string ip_address) {
+ if (is_connected)
+ default_network_.connection_state_ = flimflam::kStateOnline;
+ else
+ default_network_.connection_state_ = flimflam::kStateConfiguration;
+ default_network_.type_ = type;
+ default_network_.technology_ = technology;
+ default_network_.path_ = service_path;
+ default_network_.ip_address_ = ip_address;
+ }
+
+ // Process an default network update based on the state of |default_network_|.
+ void ProcessDefaultNetworkUpdate(bool* type_changed,
+ bool* ip_changed,
+ bool* dns_changed) {
+ notifier_.UpdateState(&default_network_, type_changed, ip_changed,
+ dns_changed);
+ }
+
+ private:
+ NetworkState default_network_;
+ NetworkChangeNotifierChromeos notifier_;
+};
+
+TEST_F(NetworkChangeNotifierChromeosUpdateTest, UpdateDefaultNetworkOffline) {
+ // Test that Online to Offline transitions are correctly handled.
+ SetNotifierState(NetworkChangeNotifier::CONNECTION_ETHERNET, "/service/1",
+ "192.168.1.1");
+ SetDefaultNetworkState(false, // offline.
+ flimflam::kTypeEthernet, "", "/service/1", "");
+ bool type_changed = false, ip_changed = false, dns_changed = false;
+ ProcessDefaultNetworkUpdate(&type_changed, &ip_changed, &dns_changed);
+ VerifyNotifierState(NetworkChangeNotifier::CONNECTION_NONE, "", "");
+ EXPECT_TRUE(type_changed);
+ EXPECT_TRUE(ip_changed);
+ EXPECT_TRUE(dns_changed);
+}
+
+TEST_F(NetworkChangeNotifierChromeosUpdateTest, UpdateDefaultNetworkOnline) {
+ // Test that Offline to Online transitions are correctly handled.
+ SetNotifierState(NetworkChangeNotifier::CONNECTION_NONE, "", "");
+
+ SetDefaultNetworkState(false, // offline.
+ flimflam::kTypeEthernet, "",
+ "192.168.0.1", "/service/1");
+ bool type_changed = false, ip_changed = false, dns_changed = false;
+ ProcessDefaultNetworkUpdate(&type_changed, &ip_changed, &dns_changed);
+ // If the new default network is still offline, nothing should have changed.
+ VerifyNotifierState(NetworkChangeNotifier::CONNECTION_NONE, "", "");
+ EXPECT_FALSE(type_changed);
+ EXPECT_FALSE(ip_changed);
+ EXPECT_FALSE(dns_changed);
+
+ SetDefaultNetworkState(true, // online.
+ flimflam::kTypeEthernet, "", "/service/1",
+ "192.168.0.1");
+ ProcessDefaultNetworkUpdate(&type_changed, &ip_changed, &dns_changed);
+ // Now the new default network is online, so this should trigger a notifier
+ // state change.
+ VerifyNotifierState(NetworkChangeNotifier::CONNECTION_ETHERNET, "/service/1",
+ "192.168.0.1");
+ EXPECT_TRUE(type_changed);
+ EXPECT_TRUE(ip_changed);
+ EXPECT_TRUE(dns_changed);
+}
+
+TEST_F(NetworkChangeNotifierChromeosUpdateTest, UpdateDefaultNetworkChanged) {
+ // Test that Online to Online transitions (default network changes) are
+ // correctly handled.
+ SetNotifierState(NetworkChangeNotifier::CONNECTION_ETHERNET, "/service/1",
+ "192.168.1.1");
+
+ SetDefaultNetworkState(true, // online.
+ flimflam::kTypeWifi, "", "/service/2", "192.168.1.2");
+ bool type_changed = false, ip_changed = false, dns_changed = false;
+ ProcessDefaultNetworkUpdate(&type_changed, &ip_changed, &dns_changed);
+ VerifyNotifierState(NetworkChangeNotifier::CONNECTION_WIFI, "/service/2",
+ "192.168.1.2" );
+ EXPECT_TRUE(type_changed);
+ EXPECT_TRUE(ip_changed);
+ EXPECT_TRUE(dns_changed);
+
+ SetDefaultNetworkState(true, // online.
+ flimflam::kTypeWifi, "", "/service/3", "192.168.1.2");
+ ProcessDefaultNetworkUpdate(&type_changed, &ip_changed, &dns_changed);
+ VerifyNotifierState(NetworkChangeNotifier::CONNECTION_WIFI, "/service/3",
+ "192.168.1.2" );
+ EXPECT_FALSE(type_changed);
+ // A service path change (even with a corresponding IP change) should still
+ // trigger an IP address update to observers.
+ EXPECT_TRUE(ip_changed);
+ EXPECT_TRUE(dns_changed);
+}
+
+} // namespace chromeos
diff --git a/chromeos/network/network_change_notifier_factory_chromeos.cc b/chromeos/network/network_change_notifier_factory_chromeos.cc
new file mode 100644
index 0000000..1d73c3e
--- /dev/null
+++ b/chromeos/network/network_change_notifier_factory_chromeos.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/network/network_change_notifier_factory_chromeos.h"
+
+#include "chromeos/network/network_change_notifier_chromeos.h"
+
+namespace chromeos {
+
+namespace {
+
+NetworkChangeNotifierChromeos* g_network_change_notifier_chromeos = NULL;
+
+} // namespace
+
+net::NetworkChangeNotifier*
+NetworkChangeNotifierFactoryChromeos::CreateInstance() {
+ DCHECK(!g_network_change_notifier_chromeos);
+ g_network_change_notifier_chromeos = new NetworkChangeNotifierChromeos();
+ return g_network_change_notifier_chromeos;
+}
+
+// static
+NetworkChangeNotifierChromeos*
+NetworkChangeNotifierFactoryChromeos::GetInstance() {
+ return g_network_change_notifier_chromeos;
+}
+
+} // namespace chromeos
diff --git a/chromeos/network/network_change_notifier_factory_chromeos.h b/chromeos/network/network_change_notifier_factory_chromeos.h
new file mode 100644
index 0000000..51366da
--- /dev/null
+++ b/chromeos/network/network_change_notifier_factory_chromeos.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_FACTORY_CHROMEOS_H_
+#define CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_FACTORY_CHROMEOS_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chromeos/chromeos_export.h"
+#include "net/base/network_change_notifier_factory.h"
+
+namespace chromeos {
+
+class NetworkChangeNotifierChromeos;
+
+class CHROMEOS_EXPORT NetworkChangeNotifierFactoryChromeos
+ : public net::NetworkChangeNotifierFactory {
+ public:
+ NetworkChangeNotifierFactoryChromeos() {}
+
+ // net::NetworkChangeNotifierFactory overrides.
+ virtual net::NetworkChangeNotifier* CreateInstance() OVERRIDE;
+
+ static NetworkChangeNotifierChromeos* GetInstance();
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_NETWORK_NETWORK_CHANGE_NOTIFIER_FACTORY_CHROMEOS_H_
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index c5fa66d..30228f8 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -43,6 +43,7 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState {
private:
friend class NetworkStateHandler;
+ friend class NetworkChangeNotifierChromeosUpdateTest;
// Called by NetworkStateHandler when the ip config changes.
void set_ip_address(const std::string& ip_address) {