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/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"
21 // HostResolverImplChromeOS::NetworkStateHandlerObserver
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.
27 class HostResolverImplChromeOS::NetworkObserver
28 : public chromeos::NetworkStateHandlerObserver
{
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
);
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());
49 virtual ~NetworkObserver() {
50 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
53 // NetworkStateHandlerObserver
54 virtual void DefaultNetworkChanged(const NetworkState
* network
) OVERRIDE
{
56 DVLOG(2) << "DefaultNetworkChanged: No Network.";
57 CallResolverSetIpAddress("", "");
60 std::string ipv4_address
, ipv6_address
;
61 const DeviceState
* device_state
=
62 network_state_handler_
->GetDeviceState(network
->device_path());
64 LOG(ERROR
) << "DefaultNetworkChanged: Network missing device: "
66 CallResolverSetIpAddress("", "");
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();
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
;
84 LOG(ERROR
) << "DefaultNetworkChanged: IPConfigs missing properties: "
88 DVLOG(2) << "DefaultNetworkChanged: " << network
->name()
89 << " IPv4: " << ipv4_address
<< " IPv6: " << ipv6_address
;
90 CallResolverSetIpAddress(ipv4_address
, ipv6_address
);
93 virtual void IsShuttingDown() OVERRIDE
{
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