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