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.
5 #include "chromeos/network/host_resolver_impl_chromeos.h"
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"
22 // HostResolverImplChromeOS::NetworkStateHandlerObserver
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.
28 class HostResolverImplChromeOS::NetworkObserver
29 : public chromeos::NetworkStateHandlerObserver
{
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
);
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());
50 virtual ~NetworkObserver() {
51 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
54 // NetworkStateHandlerObserver
55 virtual void DefaultNetworkChanged(const NetworkState
* network
) OVERRIDE
{
57 DVLOG(2) << "DefaultNetworkChanged: No Network.";
58 CallResolverSetIpAddress("", "");
61 std::string ipv4_address
, ipv6_address
;
62 const DeviceState
* device_state
=
63 network_state_handler_
->GetDeviceState(network
->device_path());
65 LOG_IF(ERROR
, base::SysInfo::IsRunningOnChromeOS())
66 << "DefaultNetworkChanged: Network missing device: "
68 CallResolverSetIpAddress("", "");
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();
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
;
86 LOG(ERROR
) << "DefaultNetworkChanged: IPConfigs missing properties: "
90 DVLOG(2) << "DefaultNetworkChanged: " << network
->name()
91 << " IPv4: " << ipv4_address
<< " IPv6: " << ipv6_address
;
92 CallResolverSetIpAddress(ipv4_address
, ipv6_address
);
95 virtual void IsShuttingDown() OVERRIDE
{
99 void CallResolverSetIpAddress(const std::string
& ipv4_address
,
100 const std::string
& ipv6_address
) {
101 resolver_message_loop_
->PostTask(
103 base::Bind(&NetworkObserver::SetIpAddressOnResolverThread
,
104 weak_ptr_factory_resolver_thread_
.GetWeakPtr(),
105 ipv4_address
, ipv6_address
));
108 void SetIpAddressOnResolverThread(const std::string
& ipv4_address
,
109 const std::string
& ipv6_address
) {
111 resolver_
->SetIPAddresses(ipv4_address
, ipv6_address
);
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_
;
119 DISALLOW_COPY_AND_ASSIGN(NetworkObserver
);
122 // HostResolverImplChromeOS
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(
134 base::Bind(&NetworkObserver::Create
,
135 weak_ptr_factory_
.GetWeakPtr(),
136 base::MessageLoopProxy::current(),
137 network_state_handler
));
140 HostResolverImplChromeOS::~HostResolverImplChromeOS() {
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
))
152 return net::HostResolverImpl::Resolve(
153 info
, priority
, addresses
, callback
, out_req
, source_net_log
);
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
;
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())
170 // Use IPConfig data for localhost address lookup.
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));
180 net::IPAddressNumber ipv4
;
181 if (net::ParseIPLiteralToNumber(ipv4_address_
, &ipv4
))
182 addresses
->push_back(net::IPEndPoint(ipv4
, 0));
184 DVLOG(2) << "ResolveLocalIPAddress("
185 << static_cast<int>(info
.address_family()) << "): "
187 << " IPv4: " << ipv4_address_
<< " IPv6: " << ipv6_address_
;
188 addresses
->SetDefaultCanonicalName();
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(),
204 scoped_ptr
<net::HostResolver
>
205 HostResolverImplChromeOS::CreateHostResolverForTest(
206 scoped_refptr
<base::MessageLoopProxy
> network_handler_message_loop
,
207 NetworkStateHandler
* network_state_handler
) {
209 return scoped_ptr
<net::HostResolver
>(new HostResolverImplChromeOS(
210 network_handler_message_loop
,
211 network_state_handler
,
216 } // namespace chromeos