Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / network / host_resolver_impl_chromeos.cc
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