summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorstevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-17 09:21:00 +0000
committerstevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-17 09:21:00 +0000
commit106ccd2ccd1ac30217f27541b515c4bb93f10707 (patch)
tree5e1051f37501d9894d47853529a8b564dd8da614 /chromeos
parentecf56301956369d9fa0f341a0001efe9efbc1cbd (diff)
downloadchromium_src-106ccd2ccd1ac30217f27541b515c4bb93f10707.zip
chromium_src-106ccd2ccd1ac30217f27541b515c4bb93f10707.tar.gz
chromium_src-106ccd2ccd1ac30217f27541b515c4bb93f10707.tar.bz2
Provide Shill IP Address to myIpAddress()
On Chrome OS we need to get the IP Address to use for myIpAddress() from Shill since gethostname() returns localhost. BUG=175652 TBR=sky@chromium.org Review URL: https://codereview.chromium.org/238433003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277679 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r--chromeos/chromeos.gyp3
-rw-r--r--chromeos/network/device_state.h4
-rw-r--r--chromeos/network/host_resolver_impl_chromeos.cc214
-rw-r--r--chromeos/network/host_resolver_impl_chromeos.h80
-rw-r--r--chromeos/network/host_resolver_impl_chromeos_unittest.cc171
-rw-r--r--chromeos/network/network_state_handler.cc9
-rw-r--r--chromeos/network/network_state_handler_observer.cc3
-rw-r--r--chromeos/network/network_state_handler_observer.h4
8 files changed, 487 insertions, 1 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 686b7ae..58aea83 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -276,6 +276,8 @@
'network/device_state.h',
'network/geolocation_handler.cc',
'network/geolocation_handler.h',
+ 'network/host_resolver_impl_chromeos.cc',
+ 'network/host_resolver_impl_chromeos.h',
'network/managed_network_configuration_handler.cc',
'network/managed_network_configuration_handler.h',
'network/managed_network_configuration_handler_impl.cc',
@@ -520,6 +522,7 @@
'login/login_state_unittest.cc',
'network/client_cert_resolver_unittest.cc',
'network/geolocation_handler_unittest.cc',
+ 'network/host_resolver_impl_chromeos_unittest.cc',
'network/managed_network_configuration_handler_unittest.cc',
'network/network_cert_migrator_unittest.cc',
'network/network_change_notifier_chromeos_unittest.cc',
diff --git a/chromeos/network/device_state.h b/chromeos/network/device_state.h
index 5f4486d..3e8195b 100644
--- a/chromeos/network/device_state.h
+++ b/chromeos/network/device_state.h
@@ -49,10 +49,12 @@ class CHROMEOS_EXPORT DeviceState : public ManagedState {
const std::string& mdn() const { return mdn_; }
const CellularScanResults& scan_results() const { return scan_results_; }
+ // |ip_configs_| is kept up to date by NetworkStateHandler.
+ const base::DictionaryValue& ip_configs() const { return ip_configs_; }
+
// Do not use this. It exists temporarily for internet_options_handler.cc
// which is being deprecated.
const base::DictionaryValue& properties() const { return properties_; }
- const base::DictionaryValue& ip_configs() const { return ip_configs_; }
// Ethernet specific accessors
bool eap_authentication_completed() const {
diff --git a/chromeos/network/host_resolver_impl_chromeos.cc b/chromeos/network/host_resolver_impl_chromeos.cc
new file mode 100644
index 0000000..ad946e5
--- /dev/null
+++ b/chromeos/network/host_resolver_impl_chromeos.cc
@@ -0,0 +1,214 @@
+// Copyright 2014 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/host_resolver_impl_chromeos.h"
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/values.h"
+#include "chromeos/network/device_state.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_state_handler_observer.h"
+#include "net/base/address_list.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+// HostResolverImplChromeOS::NetworkStateHandlerObserver
+//
+// An instance of this class is created on the NetworkHandler (UI) thread and
+// manages its own lifetime, destroying itself when NetworkStateHandlerObserver
+// ::IsShuttingDown() gets called.
+
+class HostResolverImplChromeOS::NetworkObserver
+ : public chromeos::NetworkStateHandlerObserver {
+ public:
+ static void Create(
+ const base::WeakPtr<HostResolverImplChromeOS>& resolver,
+ scoped_refptr<base::MessageLoopProxy> resolver_message_loop,
+ NetworkStateHandler* network_state_handler) {
+ new NetworkObserver(resolver, resolver_message_loop, network_state_handler);
+ }
+
+ NetworkObserver(const base::WeakPtr<HostResolverImplChromeOS>& resolver,
+ scoped_refptr<base::MessageLoopProxy> resolver_message_loop,
+ NetworkStateHandler* network_state_handler)
+ : resolver_(resolver),
+ resolver_message_loop_(resolver_message_loop),
+ network_state_handler_(network_state_handler),
+ weak_ptr_factory_resolver_thread_(this) {
+ network_state_handler_->AddObserver(this, FROM_HERE);
+ DefaultNetworkChanged(network_state_handler_->DefaultNetwork());
+ }
+
+ private:
+ virtual ~NetworkObserver() {
+ network_state_handler_->RemoveObserver(this, FROM_HERE);
+ }
+
+ // NetworkStateHandlerObserver
+ virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE {
+ if (!network) {
+ DVLOG(2) << "DefaultNetworkChanged: No Network.";
+ CallResolverSetIpAddress("", "");
+ return;
+ }
+ std::string ipv4_address, ipv6_address;
+ const DeviceState* device_state =
+ network_state_handler_->GetDeviceState(network->device_path());
+ if (!device_state) {
+ LOG(ERROR) << "DefaultNetworkChanged: Network missing device: "
+ << network->path();
+ CallResolverSetIpAddress("", "");
+ return;
+ }
+ for (base::DictionaryValue::Iterator iter(device_state->ip_configs());
+ !iter.IsAtEnd(); iter.Advance()) {
+ const base::DictionaryValue* ip_config;
+ if (!iter.value().GetAsDictionary(&ip_config)) {
+ LOG(ERROR) << "Badly formatted IPConfigs: " << network->path();
+ continue;
+ }
+ std::string method, address;
+ if (ip_config->GetString(shill::kMethodProperty, &method) &&
+ ip_config->GetString(shill::kAddressProperty, &address)) {
+ if (method == shill::kTypeIPv4 || method == shill::kTypeDHCP)
+ ipv4_address = address;
+ else if (method == shill::kTypeIPv6 || method == shill::kTypeDHCP6)
+ ipv6_address = address;
+ } else {
+ LOG(ERROR) << "DefaultNetworkChanged: IPConfigs missing properties: "
+ << network->path();
+ }
+ }
+ DVLOG(2) << "DefaultNetworkChanged: " << network->name()
+ << " IPv4: " << ipv4_address << " IPv6: " << ipv6_address;
+ CallResolverSetIpAddress(ipv4_address, ipv6_address);
+ }
+
+ virtual void IsShuttingDown() OVERRIDE {
+ delete this;
+ }
+
+ void CallResolverSetIpAddress(const std::string& ipv4_address,
+ const std::string& ipv6_address) {
+ resolver_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&NetworkObserver::SetIpAddressOnResolverThread,
+ weak_ptr_factory_resolver_thread_.GetWeakPtr(),
+ ipv4_address, ipv6_address));
+ }
+
+ void SetIpAddressOnResolverThread(const std::string& ipv4_address,
+ const std::string& ipv6_address) {
+ if (resolver_)
+ resolver_->SetIPAddresses(ipv4_address, ipv6_address);
+ }
+
+ base::WeakPtr<HostResolverImplChromeOS> resolver_;
+ scoped_refptr<base::MessageLoopProxy> resolver_message_loop_;
+ NetworkStateHandler* network_state_handler_;
+ base::WeakPtrFactory<NetworkObserver> weak_ptr_factory_resolver_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkObserver);
+};
+
+// HostResolverImplChromeOS
+
+HostResolverImplChromeOS::HostResolverImplChromeOS(
+ scoped_refptr<base::MessageLoopProxy> network_handler_message_loop,
+ NetworkStateHandler* network_state_handler,
+ const Options& options,
+ net::NetLog* net_log)
+ : HostResolverImpl(options, net_log),
+ network_handler_message_loop_(network_handler_message_loop),
+ weak_ptr_factory_(this) {
+ network_handler_message_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&NetworkObserver::Create,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::MessageLoopProxy::current(),
+ network_state_handler));
+}
+
+HostResolverImplChromeOS::~HostResolverImplChromeOS() {
+}
+
+int HostResolverImplChromeOS::Resolve(const RequestInfo& info,
+ net::RequestPriority priority,
+ net::AddressList* addresses,
+ const net::CompletionCallback& callback,
+ RequestHandle* out_req,
+ const net::BoundNetLog& source_net_log) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (ResolveLocalIPAddress(info, addresses))
+ return net::OK;
+ return net::HostResolverImpl::Resolve(
+ info, priority, addresses, callback, out_req, source_net_log);
+}
+
+void HostResolverImplChromeOS::SetIPAddresses(const std::string& ipv4_address,
+ const std::string& ipv6_address) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ipv4_address_ = ipv4_address;
+ ipv6_address_ = ipv6_address;
+}
+
+bool HostResolverImplChromeOS::ResolveLocalIPAddress(
+ const RequestInfo& info,
+ net::AddressList* addresses) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (info.hostname() != net::GetHostName() || ipv4_address_.empty())
+ return false;
+
+ // Use IPConfig data for localhost address lookup.
+ addresses->clear();
+
+ if (info.address_family() != net::ADDRESS_FAMILY_IPV4 &&
+ !ipv6_address_.empty()) {
+ net::IPAddressNumber ipv6;
+ if (net::ParseIPLiteralToNumber(ipv6_address_, &ipv6))
+ addresses->push_back(net::IPEndPoint(ipv6, 0));
+ }
+
+ net::IPAddressNumber ipv4;
+ if (net::ParseIPLiteralToNumber(ipv4_address_, &ipv4))
+ addresses->push_back(net::IPEndPoint(ipv4, 0));
+
+ DVLOG(2) << "ResolveLocalIPAddress("
+ << static_cast<int>(info.address_family()) << "): "
+ << addresses->size()
+ << " IPv4: " << ipv4_address_ << " IPv6: " << ipv6_address_;
+ addresses->SetDefaultCanonicalName();
+ return true;
+}
+
+// static
+scoped_ptr<net::HostResolver> HostResolverImplChromeOS::CreateSystemResolver(
+ const Options& options,
+ net::NetLog* net_log) {
+ return scoped_ptr<net::HostResolver>(new HostResolverImplChromeOS(
+ NetworkHandler::Get()->message_loop(),
+ NetworkHandler::Get()->network_state_handler(),
+ options,
+ net_log));
+}
+
+// static
+scoped_ptr<net::HostResolver>
+HostResolverImplChromeOS::CreateHostResolverForTest(
+ scoped_refptr<base::MessageLoopProxy> network_handler_message_loop,
+ NetworkStateHandler* network_state_handler) {
+ Options options;
+ return scoped_ptr<net::HostResolver>(new HostResolverImplChromeOS(
+ network_handler_message_loop,
+ network_state_handler,
+ options,
+ NULL));
+}
+
+} // namespace chromeos
diff --git a/chromeos/network/host_resolver_impl_chromeos.h b/chromeos/network/host_resolver_impl_chromeos.h
new file mode 100644
index 0000000..94f7712
--- /dev/null
+++ b/chromeos/network/host_resolver_impl_chromeos.h
@@ -0,0 +1,80 @@
+// Copyright 2014 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_HOST_RESOLVER_IMPL_CHROMEOS_H_
+#define CHROMEOS_NETWORK_HOST_RESOLVER_IMPL_CHROMEOS_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "chromeos/chromeos_export.h"
+#include "net/dns/host_resolver_impl.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace chromeos {
+class NetworkStateHandler;
+}
+
+namespace chromeos {
+
+// HostResolverImplChromeOS overrides HostResolverImpl::Resolve in order to
+// provide the correct IP addresses for localhost using the chromeos
+// NetworkHandler interface. ('hostname' only returns 'localhost' on cros).
+
+class CHROMEOS_EXPORT HostResolverImplChromeOS : public net::HostResolverImpl {
+ public:
+ // ChromeOS specific implementation of HostResolver::CreateSystemResolver.
+ // Assumes NetworkHandler has been initialized.
+ // This is expected to be constructed on the same thread that Resolve() is
+ // called from, i.e. the IO thread, which is presumed to differ from the
+ // thread that NetworkStateHandler is called on, i.e. the UI thread.
+ static scoped_ptr<net::HostResolver> CreateSystemResolver(
+ const Options& options,
+ net::NetLog* net_log);
+
+ // Creates a host resolver instance for testing.
+ static scoped_ptr<net::HostResolver> CreateHostResolverForTest(
+ scoped_refptr<base::MessageLoopProxy> network_handler_message_loop,
+ NetworkStateHandler* network_state_handler);
+
+ virtual ~HostResolverImplChromeOS();
+
+ // HostResolverImpl
+ virtual int Resolve(const RequestInfo& info,
+ net::RequestPriority priority,
+ net::AddressList* addresses,
+ const net::CompletionCallback& callback,
+ RequestHandle* out_req,
+ const net::BoundNetLog& source_net_log) OVERRIDE;
+
+ private:
+ friend class net::HostResolver;
+ class NetworkObserver;
+
+ HostResolverImplChromeOS(
+ scoped_refptr<base::MessageLoopProxy> network_handler_message_loop,
+ NetworkStateHandler* network_state_handler,
+ const Options& options,
+ net::NetLog* net_log);
+
+ void SetIPAddresses(const std::string& ipv4_address,
+ const std::string& ipv6_address);
+
+ bool ResolveLocalIPAddress(const RequestInfo& info,
+ net::AddressList* addresses);
+
+ std::string ipv4_address_;
+ std::string ipv6_address_;
+ base::ThreadChecker thread_checker_;
+ scoped_refptr<base::MessageLoopProxy> network_handler_message_loop_;
+ base::WeakPtrFactory<HostResolverImplChromeOS> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostResolverImplChromeOS);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_NETWORK_HOST_RESOLVER_IMPL_CHROMEOS_H_
diff --git a/chromeos/network/host_resolver_impl_chromeos_unittest.cc b/chromeos/network/host_resolver_impl_chromeos_unittest.cc
new file mode 100644
index 0000000..535eec9
--- /dev/null
+++ b/chromeos/network/host_resolver_impl_chromeos_unittest.cc
@@ -0,0 +1,171 @@
+// Copyright 2014 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/host_resolver_impl_chromeos.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill_device_client.h"
+#include "chromeos/dbus/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/network/device_state.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "dbus/object_path.h"
+#include "net/base/net_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace {
+
+const char kTestIPv4Address[] = "1.2.3.4";
+const char kTestIPv6Address[] = "1:2:3:4:5:6:7:8";
+
+void DoNothingWithCallStatus(chromeos::DBusMethodCallStatus call_status) {}
+void ErrorCallbackFunction(const std::string& error_name,
+ const std::string& error_message) {
+ LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
+}
+void ResolveCompletionCallback(int result) {}
+
+} // namespace
+
+class HostResolverImplChromeOSTest : public testing::Test {
+ public:
+ HostResolverImplChromeOSTest() {}
+
+ virtual ~HostResolverImplChromeOSTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ chromeos::DBusThreadManager::InitializeWithStub();
+
+ network_state_handler_.reset(
+ chromeos::NetworkStateHandler::InitializeForTest());
+ base::RunLoop().RunUntilIdle();
+
+ const chromeos::NetworkState* default_network =
+ network_state_handler_->DefaultNetwork();
+ ASSERT_TRUE(default_network);
+ const chromeos::DeviceState* default_device =
+ network_state_handler_->GetDeviceState(default_network->device_path());
+ ASSERT_TRUE(default_device);
+ SetDefaultIPConfigs(default_device->path());
+
+ // Create the host resolver from the IO message loop.
+ io_message_loop_.PostTask(
+ FROM_HERE,
+ base::Bind(&HostResolverImplChromeOSTest::InitializeHostResolver,
+ base::Unretained(this)));
+ io_message_loop_.RunUntilIdle();
+
+ // Run the main message loop to create the network observer and initialize
+ // the ip address values.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ network_state_handler_.reset();
+ chromeos::DBusThreadManager::Shutdown();
+ }
+
+ protected:
+ // Run from main (UI) message loop, calls Resolve on IO message loop.
+ int CallResolve(net::HostResolver::RequestInfo& info) {
+ io_message_loop_.PostTask(
+ FROM_HERE,
+ base::Bind(&HostResolverImplChromeOSTest::Resolve,
+ base::Unretained(this),
+ info));
+ io_message_loop_.RunUntilIdle();
+ return result_;
+ }
+
+ net::AddressList addresses_;
+ int result_;
+
+ private:
+ // Run from IO message loop.
+ void InitializeHostResolver() {
+ net::HostResolver::Options options;
+ host_resolver_ =
+ chromeos::HostResolverImplChromeOS::CreateHostResolverForTest(
+ base::MessageLoopProxy::current(),
+ network_state_handler_.get());
+ }
+
+ // Run from IO message loop.
+ void Resolve(net::HostResolver::RequestInfo info) {
+ result_ = host_resolver_->Resolve(
+ info,
+ net::DEFAULT_PRIORITY,
+ &addresses_,
+ base::Bind(&ResolveCompletionCallback),
+ NULL,
+ net_log_);
+ }
+
+ void SetDefaultIPConfigs(const std::string& default_device_path) {
+ const std::string kTestIPv4ConfigPath("test_ip_v4_config_path");
+ const std::string kTestIPv6ConfigPath("test_ip_v6_config_path");
+
+ SetIPConfig(kTestIPv4ConfigPath, shill::kTypeIPv4, kTestIPv4Address);
+ SetIPConfig(kTestIPv6ConfigPath, shill::kTypeIPv6, kTestIPv6Address);
+ base::RunLoop().RunUntilIdle();
+
+ base::ListValue ip_configs;
+ ip_configs.AppendString(kTestIPv4ConfigPath);
+ ip_configs.AppendString(kTestIPv6ConfigPath);
+
+ chromeos::DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
+ dbus::ObjectPath(default_device_path),
+ shill::kIPConfigsProperty,
+ ip_configs,
+ base::Bind(&base::DoNothing),
+ base::Bind(&ErrorCallbackFunction));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void SetIPConfig(const std::string& path,
+ const std::string& method,
+ const std::string& address) {
+ chromeos::DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty(
+ dbus::ObjectPath(path),
+ shill::kAddressProperty,
+ base::StringValue(address),
+ base::Bind(&DoNothingWithCallStatus));
+ chromeos::DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty(
+ dbus::ObjectPath(path),
+ shill::kMethodProperty,
+ base::StringValue(method),
+ base::Bind(&DoNothingWithCallStatus));
+ }
+
+ scoped_ptr<chromeos::NetworkStateHandler> network_state_handler_;
+ scoped_ptr<net::HostResolver> host_resolver_;
+ base::MessageLoop io_message_loop_;
+ net::BoundNetLog net_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostResolverImplChromeOSTest);
+};
+
+TEST_F(HostResolverImplChromeOSTest, Resolve) {
+ net::HostResolver::RequestInfo info(
+ net::HostPortPair(net::GetHostName(), 80));
+ info.set_address_family(net::ADDRESS_FAMILY_IPV4);
+ EXPECT_EQ(net::OK, CallResolve(info));
+ ASSERT_EQ(1u, addresses_.size());
+ std::string expected = base::StringPrintf("%s:%d", kTestIPv4Address, 0);
+ EXPECT_EQ(expected, addresses_[0].ToString());
+
+ info.set_address_family(net::ADDRESS_FAMILY_IPV6);
+ EXPECT_EQ(net::OK, CallResolve(info));
+ ASSERT_EQ(2u, addresses_.size());
+ expected = base::StringPrintf("[%s]:%d", kTestIPv6Address, 0);
+ EXPECT_EQ(expected, addresses_[0].ToString());
+ expected = base::StringPrintf("%s:%d", kTestIPv4Address, 0);
+ EXPECT_EQ(expected, addresses_[1].ToString());
+}
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index aa91883..e4e5f6e 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -60,6 +60,7 @@ NetworkStateHandler::NetworkStateHandler() {
}
NetworkStateHandler::~NetworkStateHandler() {
+ FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, IsShuttingDown());
STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
}
@@ -658,11 +659,19 @@ void NetworkStateHandler::UpdateIPConfigProperties(
if (!network)
return;
network->IPConfigPropertiesChanged(properties);
+ if (network->path() == default_network_path_)
+ NotifyDefaultNetworkChanged(network);
} else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
DeviceState* device = GetModifiableDeviceState(path);
if (!device)
return;
device->IPConfigPropertiesChanged(ip_config_path, properties);
+ if (!default_network_path_.empty()) {
+ const NetworkState* default_network =
+ GetNetworkState(default_network_path_);
+ if (default_network && default_network->device_path() == path)
+ NotifyDefaultNetworkChanged(default_network);
+ }
}
}
diff --git a/chromeos/network/network_state_handler_observer.cc b/chromeos/network/network_state_handler_observer.cc
index b0cab57..0914e6b 100644
--- a/chromeos/network/network_state_handler_observer.cc
+++ b/chromeos/network/network_state_handler_observer.cc
@@ -30,4 +30,7 @@ void NetworkStateHandlerObserver::NetworkPropertiesUpdated(
const NetworkState* network) {
}
+void NetworkStateHandlerObserver::IsShuttingDown() {
+}
+
} // namespace chromeos
diff --git a/chromeos/network/network_state_handler_observer.h b/chromeos/network/network_state_handler_observer.h
index ef33c6f..63910c4 100644
--- a/chromeos/network/network_state_handler_observer.h
+++ b/chromeos/network/network_state_handler_observer.h
@@ -44,6 +44,10 @@ class CHROMEOS_EXPORT NetworkStateHandlerObserver {
// wifi strength.
virtual void NetworkPropertiesUpdated(const NetworkState* network);
+ // Called just before NetworkStateHandler is destroyed so that observers
+ // can safely stop observing.
+ virtual void IsShuttingDown();
+
private:
DISALLOW_COPY_AND_ASSIGN(NetworkStateHandlerObserver);
};