Chromium Code Reviews| Index: chromeos/network/host_resolver_impl_chromeos.cc |
| diff --git a/chromeos/network/host_resolver_impl_chromeos.cc b/chromeos/network/host_resolver_impl_chromeos.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..145de5de52ba6d05d5c2c3a287fa082f92ec3b36 |
| --- /dev/null |
| +++ b/chromeos/network/host_resolver_impl_chromeos.cc |
| @@ -0,0 +1,213 @@ |
| +// Copyright (c) 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>& owner, |
| + scoped_refptr<base::MessageLoopProxy> owner_message_loop, |
| + NetworkStateHandler* network_state_handler) { |
| + new NetworkObserver(owner, owner_message_loop, network_state_handler); |
| + } |
| + |
| + NetworkObserver(const base::WeakPtr<HostResolverImplChromeOS>& owner, |
| + scoped_refptr<base::MessageLoopProxy> owner_message_loop, |
| + NetworkStateHandler* network_state_handler) |
| + : owner_(owner), |
|
eroman
2014/06/16 22:37:48
nit: "owner" and "owner_message_loop" aren't the b
stevenjb
2014/06/16 23:03:53
Done. (owner -> resolver)
|
| + owner_message_loop_(owner_message_loop), |
| + network_state_handler_(network_state_handler), |
| + weak_ptr_factory_owner_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."; |
| + CallOwnerSetIpAddress("", ""); |
| + 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(); |
| + CallOwnerSetIpAddress("", ""); |
| + 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; |
| + CallOwnerSetIpAddress(ipv4_address, ipv6_address); |
| + } |
| + |
| + virtual void IsShuttingDown() OVERRIDE { |
| + delete this; |
| + } |
| + |
| + void CallOwnerSetIpAddress(const std::string& ipv4_address, |
| + const std::string& ipv6_address) { |
| + owner_message_loop_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&NetworkObserver::SetIpAddressOnOwnerThread, |
| + weak_ptr_factory_owner_thread_.GetWeakPtr(), |
| + ipv4_address, ipv6_address)); |
| + } |
| + |
| + void SetIpAddressOnOwnerThread(const std::string& ipv4_address, |
| + const std::string& ipv6_address) { |
| + if (owner_) |
| + owner_->SetIPAddresses(ipv4_address, ipv6_address); |
| + } |
| + |
| + base::WeakPtr<HostResolverImplChromeOS> owner_; |
| + scoped_refptr<base::MessageLoopProxy> owner_message_loop_; |
| + NetworkStateHandler* network_state_handler_; |
| + base::WeakPtrFactory<NetworkObserver> weak_ptr_factory_owner_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 |