ebeb27aa30471e960f58dc53e858e328f637ee7f
[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/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"
18
19 namespace chromeos {
20
21 // HostResolverImplChromeOS::NetworkStateHandlerObserver
22 //
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.
26
27 class HostResolverImplChromeOS::NetworkObserver
28     : public chromeos::NetworkStateHandlerObserver {
29  public:
30   static void Create(
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);
35   }
36
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());
46   }
47
48  private:
49   virtual ~NetworkObserver() {
50     network_state_handler_->RemoveObserver(this, FROM_HERE);
51   }
52
53   // NetworkStateHandlerObserver
54   virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE {
55     if (!network) {
56       DVLOG(2) << "DefaultNetworkChanged: No Network.";
57       CallResolverSetIpAddress("", "");
58       return;
59     }
60     std::string ipv4_address, ipv6_address;
61     const DeviceState* device_state =
62         network_state_handler_->GetDeviceState(network->device_path());
63     if (!device_state) {
64       LOG(ERROR) << "DefaultNetworkChanged: Network missing device: "
65                  << network->path();
66       CallResolverSetIpAddress("", "");
67       return;
68     }
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();
74         continue;
75       }
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;
83       } else {
84         LOG(ERROR) << "DefaultNetworkChanged: IPConfigs missing properties: "
85                    << network->path();
86       }
87     }
88     DVLOG(2) << "DefaultNetworkChanged: " << network->name()
89              << " IPv4: " << ipv4_address << " IPv6: " << ipv6_address;
90     CallResolverSetIpAddress(ipv4_address, ipv6_address);
91   }
92
93   virtual void IsShuttingDown() OVERRIDE {
94     delete this;
95   }
96
97   void CallResolverSetIpAddress(const std::string& ipv4_address,
98                                 const std::string& ipv6_address) {
99     resolver_message_loop_->PostTask(
100         FROM_HERE,
101         base::Bind(&NetworkObserver::SetIpAddressOnResolverThread,
102                    weak_ptr_factory_resolver_thread_.GetWeakPtr(),
103                    ipv4_address, ipv6_address));
104   }
105
106   void SetIpAddressOnResolverThread(const std::string& ipv4_address,
107                                     const std::string& ipv6_address) {
108     if (resolver_)
109       resolver_->SetIPAddresses(ipv4_address, ipv6_address);
110   }
111
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_;
116
117   DISALLOW_COPY_AND_ASSIGN(NetworkObserver);
118 };
119
120 // HostResolverImplChromeOS
121
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(
131       FROM_HERE,
132       base::Bind(&NetworkObserver::Create,
133                  weak_ptr_factory_.GetWeakPtr(),
134                  base::MessageLoopProxy::current(),
135                  network_state_handler));
136 }
137
138 HostResolverImplChromeOS::~HostResolverImplChromeOS() {
139 }
140
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))
149     return net::OK;
150   return net::HostResolverImpl::Resolve(
151       info, priority, addresses, callback, out_req, source_net_log);
152 }
153
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;
159 }
160
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())
166     return false;
167
168   // Use IPConfig data for localhost address lookup.
169   addresses->clear();
170
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));
176   }
177
178   net::IPAddressNumber ipv4;
179   if (net::ParseIPLiteralToNumber(ipv4_address_, &ipv4))
180     addresses->push_back(net::IPEndPoint(ipv4, 0));
181
182   DVLOG(2) << "ResolveLocalIPAddress("
183            << static_cast<int>(info.address_family()) << "): "
184            << addresses->size()
185            << " IPv4: " << ipv4_address_ << " IPv6: " << ipv6_address_;
186   addresses->SetDefaultCanonicalName();
187   return true;
188 }
189
190 // static
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(),
197       options,
198       net_log));
199 }
200
201 // static
202 scoped_ptr<net::HostResolver>
203 HostResolverImplChromeOS::CreateHostResolverForTest(
204     scoped_refptr<base::MessageLoopProxy> network_handler_message_loop,
205     NetworkStateHandler* network_state_handler) {
206   Options options;
207   return scoped_ptr<net::HostResolver>(new HostResolverImplChromeOS(
208       network_handler_message_loop,
209       network_state_handler,
210       options,
211       NULL));
212 }
213
214 }  // namespace chromeos