diff options
author | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-17 09:21:00 +0000 |
---|---|---|
committer | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-17 09:21:00 +0000 |
commit | 106ccd2ccd1ac30217f27541b515c4bb93f10707 (patch) | |
tree | 5e1051f37501d9894d47853529a8b564dd8da614 /chromeos/network/host_resolver_impl_chromeos.cc | |
parent | ecf56301956369d9fa0f341a0001efe9efbc1cbd (diff) | |
download | chromium_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/network/host_resolver_impl_chromeos.cc')
-rw-r--r-- | chromeos/network/host_resolver_impl_chromeos.cc | 214 |
1 files changed, 214 insertions, 0 deletions
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 |