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/location.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/sys_info.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/values.h"
12 #include "chromeos/network/device_state.h"
13 #include "chromeos/network/network_handler.h"
14 #include "chromeos/network/network_state.h"
15 #include "chromeos/network/network_state_handler.h"
16 #include "chromeos/network/network_state_handler_observer.h"
17 #include "net/base/address_list.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/net_util.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
24 // HostResolverImplChromeOS::NetworkStateHandlerObserver
26 // An instance of this class is created on the NetworkHandler (UI) thread and
27 // manages its own lifetime, destroying itself when NetworkStateHandlerObserver
28 // ::IsShuttingDown() gets called.
30 class HostResolverImplChromeOS::NetworkObserver
31 : public chromeos::NetworkStateHandlerObserver
{
34 const base::WeakPtr
<HostResolverImplChromeOS
>& resolver
,
35 scoped_refptr
<base::SingleThreadTaskRunner
> resolver_task_runner
,
36 NetworkStateHandler
* network_state_handler
) {
37 new NetworkObserver(resolver
, resolver_task_runner
, network_state_handler
);
41 const base::WeakPtr
<HostResolverImplChromeOS
>& resolver
,
42 scoped_refptr
<base::SingleThreadTaskRunner
> resolver_task_runner
,
43 NetworkStateHandler
* network_state_handler
)
44 : resolver_(resolver
),
45 resolver_task_runner_(resolver_task_runner
),
46 network_state_handler_(network_state_handler
),
47 weak_ptr_factory_resolver_thread_(this) {
48 network_state_handler_
->AddObserver(this, FROM_HERE
);
49 DefaultNetworkChanged(network_state_handler_
->DefaultNetwork());
53 ~NetworkObserver() override
{
54 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
57 // NetworkStateHandlerObserver
58 void DefaultNetworkChanged(const NetworkState
* network
) override
{
60 DVLOG(2) << "DefaultNetworkChanged: No Network.";
61 CallResolverSetIpAddress("", "");
64 std::string ipv4_address
, ipv6_address
;
65 const DeviceState
* device_state
=
66 network_state_handler_
->GetDeviceState(network
->device_path());
68 LOG_IF(ERROR
, base::SysInfo::IsRunningOnChromeOS())
69 << "DefaultNetworkChanged: Network missing device: "
71 CallResolverSetIpAddress("", "");
74 for (base::DictionaryValue::Iterator
iter(device_state
->ip_configs());
75 !iter
.IsAtEnd(); iter
.Advance()) {
76 const base::DictionaryValue
* ip_config
;
77 if (!iter
.value().GetAsDictionary(&ip_config
)) {
78 LOG(ERROR
) << "Badly formatted IPConfigs: " << network
->path();
81 std::string method
, address
;
82 if (ip_config
->GetString(shill::kMethodProperty
, &method
) &&
83 ip_config
->GetString(shill::kAddressProperty
, &address
)) {
84 if (method
== shill::kTypeIPv4
|| method
== shill::kTypeDHCP
)
85 ipv4_address
= address
;
86 else if (method
== shill::kTypeIPv6
|| method
== shill::kTypeDHCP6
)
87 ipv6_address
= address
;
89 LOG(ERROR
) << "DefaultNetworkChanged: IPConfigs missing properties: "
93 DVLOG(2) << "DefaultNetworkChanged: " << network
->name()
94 << " IPv4: " << ipv4_address
<< " IPv6: " << ipv6_address
;
95 CallResolverSetIpAddress(ipv4_address
, ipv6_address
);
98 void IsShuttingDown() override
{ delete this; }
100 void CallResolverSetIpAddress(const std::string
& ipv4_address
,
101 const std::string
& ipv6_address
) {
102 resolver_task_runner_
->PostTask(
103 FROM_HERE
, 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::SingleThreadTaskRunner
> resolver_task_runner_
;
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::SingleThreadTaskRunner
> network_handler_task_runner
,
126 NetworkStateHandler
* network_state_handler
,
127 const Options
& options
,
128 net::NetLog
* net_log
)
129 : HostResolverImpl(options
, net_log
),
130 network_handler_task_runner_(network_handler_task_runner
),
131 weak_ptr_factory_(this) {
132 network_handler_task_runner
->PostTask(
134 base::Bind(&NetworkObserver::Create
, weak_ptr_factory_
.GetWeakPtr(),
135 base::ThreadTaskRunnerHandle::Get(), network_state_handler
));
138 HostResolverImplChromeOS::~HostResolverImplChromeOS() {
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
))
150 return net::HostResolverImpl::Resolve(
151 info
, priority
, addresses
, callback
, out_req
, source_net_log
);
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
;
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())
168 // Use IPConfig data for localhost address lookup.
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));
178 net::IPAddressNumber ipv4
;
179 if (net::ParseIPLiteralToNumber(ipv4_address_
, &ipv4
))
180 addresses
->push_back(net::IPEndPoint(ipv4
, 0));
182 DVLOG(2) << "ResolveLocalIPAddress("
183 << static_cast<int>(info
.address_family()) << "): "
185 << " IPv4: " << ipv4_address_
<< " IPv6: " << ipv6_address_
;
186 addresses
->SetDefaultCanonicalName();
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()->task_runner(),
196 NetworkHandler::Get()->network_state_handler(), options
, net_log
));
200 scoped_ptr
<net::HostResolver
>
201 HostResolverImplChromeOS::CreateHostResolverForTest(
202 scoped_refptr
<base::SingleThreadTaskRunner
> network_handler_task_runner
,
203 NetworkStateHandler
* network_state_handler
) {
205 return scoped_ptr
<net::HostResolver
>(new HostResolverImplChromeOS(
206 network_handler_task_runner
, network_state_handler
, options
, NULL
));
209 } // namespace chromeos