Home | History | Annotate | Download | only in network
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chromeos/network/host_resolver_impl_chromeos.h"
      6 
      7 #include "base/message_loop/message_loop_proxy.h"
      8 #include "base/sys_info.h"
      9 #include "base/values.h"
     10 #include "chromeos/network/device_state.h"
     11 #include "chromeos/network/network_handler.h"
     12 #include "chromeos/network/network_state.h"
     13 #include "chromeos/network/network_state_handler.h"
     14 #include "chromeos/network/network_state_handler_observer.h"
     15 #include "net/base/address_list.h"
     16 #include "net/base/net_errors.h"
     17 #include "net/base/net_util.h"
     18 #include "third_party/cros_system_api/dbus/service_constants.h"
     19 
     20 namespace chromeos {
     21 
     22 // HostResolverImplChromeOS::NetworkStateHandlerObserver
     23 //
     24 // An instance of this class is created on the NetworkHandler (UI) thread and
     25 // manages its own lifetime, destroying itself when NetworkStateHandlerObserver
     26 // ::IsShuttingDown() gets called.
     27 
     28 class HostResolverImplChromeOS::NetworkObserver
     29     : public chromeos::NetworkStateHandlerObserver {
     30  public:
     31   static void Create(
     32       const base::WeakPtr<HostResolverImplChromeOS>& resolver,
     33       scoped_refptr<base::MessageLoopProxy> resolver_message_loop,
     34       NetworkStateHandler* network_state_handler) {
     35     new NetworkObserver(resolver, resolver_message_loop, network_state_handler);
     36   }
     37 
     38   NetworkObserver(const base::WeakPtr<HostResolverImplChromeOS>& resolver,
     39                   scoped_refptr<base::MessageLoopProxy> resolver_message_loop,
     40                   NetworkStateHandler* network_state_handler)
     41       : resolver_(resolver),
     42         resolver_message_loop_(resolver_message_loop),
     43         network_state_handler_(network_state_handler),
     44         weak_ptr_factory_resolver_thread_(this) {
     45     network_state_handler_->AddObserver(this, FROM_HERE);
     46     DefaultNetworkChanged(network_state_handler_->DefaultNetwork());
     47   }
     48 
     49  private:
     50   virtual ~NetworkObserver() {
     51     network_state_handler_->RemoveObserver(this, FROM_HERE);
     52   }
     53 
     54   // NetworkStateHandlerObserver
     55   virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE {
     56     if (!network) {
     57       DVLOG(2) << "DefaultNetworkChanged: No Network.";
     58       CallResolverSetIpAddress("", "");
     59       return;
     60     }
     61     std::string ipv4_address, ipv6_address;
     62     const DeviceState* device_state =
     63         network_state_handler_->GetDeviceState(network->device_path());
     64     if (!device_state) {
     65       LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS())
     66           << "DefaultNetworkChanged: Network missing device: "
     67           << network->path();
     68       CallResolverSetIpAddress("", "");
     69       return;
     70     }
     71     for (base::DictionaryValue::Iterator iter(device_state->ip_configs());
     72          !iter.IsAtEnd(); iter.Advance()) {
     73       const base::DictionaryValue* ip_config;
     74       if (!iter.value().GetAsDictionary(&ip_config)) {
     75         LOG(ERROR) << "Badly formatted IPConfigs: " << network->path();
     76         continue;
     77       }
     78       std::string method, address;
     79       if (ip_config->GetString(shill::kMethodProperty, &method) &&
     80           ip_config->GetString(shill::kAddressProperty, &address)) {
     81         if (method == shill::kTypeIPv4 || method == shill::kTypeDHCP)
     82           ipv4_address = address;
     83         else if (method == shill::kTypeIPv6 || method == shill::kTypeDHCP6)
     84           ipv6_address = address;
     85       } else {
     86         LOG(ERROR) << "DefaultNetworkChanged: IPConfigs missing properties: "
     87                    << network->path();
     88       }
     89     }
     90     DVLOG(2) << "DefaultNetworkChanged: " << network->name()
     91              << " IPv4: " << ipv4_address << " IPv6: " << ipv6_address;
     92     CallResolverSetIpAddress(ipv4_address, ipv6_address);
     93   }
     94 
     95   virtual void IsShuttingDown() OVERRIDE {
     96     delete this;
     97   }
     98 
     99   void CallResolverSetIpAddress(const std::string& ipv4_address,
    100                                 const std::string& ipv6_address) {
    101     resolver_message_loop_->PostTask(
    102         FROM_HERE,
    103         base::Bind(&NetworkObserver::SetIpAddressOnResolverThread,
    104                    weak_ptr_factory_resolver_thread_.GetWeakPtr(),
    105                    ipv4_address, ipv6_address));
    106   }
    107 
    108   void SetIpAddressOnResolverThread(const std::string& ipv4_address,
    109                                     const std::string& ipv6_address) {
    110     if (resolver_)
    111       resolver_->SetIPAddresses(ipv4_address, ipv6_address);
    112   }
    113 
    114   base::WeakPtr<HostResolverImplChromeOS> resolver_;
    115   scoped_refptr<base::MessageLoopProxy> resolver_message_loop_;
    116   NetworkStateHandler* network_state_handler_;
    117   base::WeakPtrFactory<NetworkObserver> weak_ptr_factory_resolver_thread_;
    118 
    119   DISALLOW_COPY_AND_ASSIGN(NetworkObserver);
    120 };
    121 
    122 // HostResolverImplChromeOS
    123 
    124 HostResolverImplChromeOS::HostResolverImplChromeOS(
    125     scoped_refptr<base::MessageLoopProxy> network_handler_message_loop,
    126     NetworkStateHandler* network_state_handler,
    127     const Options& options,
    128     net::NetLog* net_log)
    129     : HostResolverImpl(options, net_log),
    130       network_handler_message_loop_(network_handler_message_loop),
    131       weak_ptr_factory_(this) {
    132   network_handler_message_loop->PostTask(
    133       FROM_HERE,
    134       base::Bind(&NetworkObserver::Create,
    135                  weak_ptr_factory_.GetWeakPtr(),
    136                  base::MessageLoopProxy::current(),
    137                  network_state_handler));
    138 }
    139 
    140 HostResolverImplChromeOS::~HostResolverImplChromeOS() {
    141 }
    142 
    143 int HostResolverImplChromeOS::Resolve(const RequestInfo& info,
    144                                       net::RequestPriority priority,
    145                                       net::AddressList* addresses,
    146                                       const net::CompletionCallback& callback,
    147                                       RequestHandle* out_req,
    148                                       const net::BoundNetLog& source_net_log) {
    149   DCHECK(thread_checker_.CalledOnValidThread());
    150   if (ResolveLocalIPAddress(info, addresses))
    151     return net::OK;
    152   return net::HostResolverImpl::Resolve(
    153       info, priority, addresses, callback, out_req, source_net_log);
    154 }
    155 
    156 void HostResolverImplChromeOS::SetIPAddresses(const std::string& ipv4_address,
    157                                               const std::string& ipv6_address) {
    158   DCHECK(thread_checker_.CalledOnValidThread());
    159   ipv4_address_ = ipv4_address;
    160   ipv6_address_ = ipv6_address;
    161 }
    162 
    163 bool HostResolverImplChromeOS::ResolveLocalIPAddress(
    164     const RequestInfo& info,
    165     net::AddressList* addresses) {
    166   DCHECK(thread_checker_.CalledOnValidThread());
    167   if (!info.is_my_ip_address() || ipv4_address_.empty())
    168     return false;
    169 
    170   // Use IPConfig data for localhost address lookup.
    171   addresses->clear();
    172 
    173   if (info.address_family() != net::ADDRESS_FAMILY_IPV4 &&
    174       !ipv6_address_.empty()) {
    175     net::IPAddressNumber ipv6;
    176     if (net::ParseIPLiteralToNumber(ipv6_address_, &ipv6))
    177       addresses->push_back(net::IPEndPoint(ipv6, 0));
    178   }
    179 
    180   net::IPAddressNumber ipv4;
    181   if (net::ParseIPLiteralToNumber(ipv4_address_, &ipv4))
    182     addresses->push_back(net::IPEndPoint(ipv4, 0));
    183 
    184   DVLOG(2) << "ResolveLocalIPAddress("
    185            << static_cast<int>(info.address_family()) << "): "
    186            << addresses->size()
    187            << " IPv4: " << ipv4_address_ << " IPv6: " << ipv6_address_;
    188   addresses->SetDefaultCanonicalName();
    189   return true;
    190 }
    191 
    192 // static
    193 scoped_ptr<net::HostResolver> HostResolverImplChromeOS::CreateSystemResolver(
    194     const Options& options,
    195     net::NetLog* net_log) {
    196   return scoped_ptr<net::HostResolver>(new HostResolverImplChromeOS(
    197       NetworkHandler::Get()->message_loop(),
    198       NetworkHandler::Get()->network_state_handler(),
    199       options,
    200       net_log));
    201 }
    202 
    203 // static
    204 scoped_ptr<net::HostResolver>
    205 HostResolverImplChromeOS::CreateHostResolverForTest(
    206     scoped_refptr<base::MessageLoopProxy> network_handler_message_loop,
    207     NetworkStateHandler* network_state_handler) {
    208   Options options;
    209   return scoped_ptr<net::HostResolver>(new HostResolverImplChromeOS(
    210       network_handler_message_loop,
    211       network_state_handler,
    212       options,
    213       NULL));
    214 }
    215 
    216 }  // namespace chromeos
    217