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 ~NetworkObserver() override
{
51 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
54 // NetworkStateHandlerObserver
55 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 void IsShuttingDown() override
{ delete this; }
97 void CallResolverSetIpAddress(const std::string
& ipv4_address
,
98 const std::string
& ipv6_address
) {
99 resolver_message_loop_
->PostTask(
101 base::Bind(&NetworkObserver::SetIpAddressOnResolverThread
,
102 weak_ptr_factory_resolver_thread_
.GetWeakPtr(),
103 ipv4_address
, ipv6_address
));
106 void SetIpAddressOnResolverThread(const std::string
& ipv4_address
,
107 const std::string
& ipv6_address
) {
109 resolver_
->SetIPAddresses(ipv4_address
, ipv6_address
);
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_
;
117 DISALLOW_COPY_AND_ASSIGN(NetworkObserver
);
120 // HostResolverImplChromeOS
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(
132 base::Bind(&NetworkObserver::Create
,
133 weak_ptr_factory_
.GetWeakPtr(),
134 base::MessageLoopProxy::current(),
135 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()->message_loop(),
196 NetworkHandler::Get()->network_state_handler(),
202 scoped_ptr
<net::HostResolver
>
203 HostResolverImplChromeOS::CreateHostResolverForTest(
204 scoped_refptr
<base::MessageLoopProxy
> network_handler_message_loop
,
205 NetworkStateHandler
* network_state_handler
) {
207 return scoped_ptr
<net::HostResolver
>(new HostResolverImplChromeOS(
208 network_handler_message_loop
,
209 network_state_handler
,
214 } // namespace chromeos