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