Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / net / dns / mock_host_resolver.cc
blobff5ffbc2f75082cbd83aae9a512cd7096d895b26
1 // Copyright (c) 2012 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 "net/dns/mock_host_resolver.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/threading/platform_thread.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/net_util.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/dns/host_cache.h"
22 #if defined(OS_WIN)
23 #include "net/base/winsock_init.h"
24 #endif
26 namespace net {
28 namespace {
30 // Cache size for the MockCachingHostResolver.
31 const unsigned kMaxCacheEntries = 100;
32 // TTL for the successful resolutions. Failures are not cached.
33 const unsigned kCacheEntryTTLSeconds = 60;
35 } // namespace
37 int ParseAddressList(const std::string& host_list,
38 const std::string& canonical_name,
39 AddressList* addrlist) {
40 *addrlist = AddressList();
41 std::vector<std::string> addresses;
42 base::SplitString(host_list, ',', &addresses);
43 addrlist->set_canonical_name(canonical_name);
44 for (size_t index = 0; index < addresses.size(); ++index) {
45 IPAddressNumber ip_number;
46 if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) {
47 LOG(WARNING) << "Not a supported IP literal: " << addresses[index];
48 return ERR_UNEXPECTED;
50 addrlist->push_back(IPEndPoint(ip_number, -1));
52 return OK;
55 struct MockHostResolverBase::Request {
56 Request(const RequestInfo& req_info,
57 AddressList* addr,
58 const CompletionCallback& cb)
59 : info(req_info), addresses(addr), callback(cb) {}
60 RequestInfo info;
61 AddressList* addresses;
62 CompletionCallback callback;
65 MockHostResolverBase::~MockHostResolverBase() {
66 STLDeleteValues(&requests_);
69 int MockHostResolverBase::Resolve(const RequestInfo& info,
70 RequestPriority priority,
71 AddressList* addresses,
72 const CompletionCallback& callback,
73 RequestHandle* handle,
74 const BoundNetLog& net_log) {
75 DCHECK(CalledOnValidThread());
76 last_request_priority_ = priority;
77 num_resolve_++;
78 size_t id = next_request_id_++;
79 int rv = ResolveFromIPLiteralOrCache(info, addresses);
80 if (rv != ERR_DNS_CACHE_MISS) {
81 return rv;
83 if (synchronous_mode_) {
84 return ResolveProc(id, info, addresses);
86 // Store the request for asynchronous resolution
87 Request* req = new Request(info, addresses, callback);
88 requests_[id] = req;
89 if (handle)
90 *handle = reinterpret_cast<RequestHandle>(id);
92 if (!ondemand_mode_) {
93 base::MessageLoop::current()->PostTask(
94 FROM_HERE,
95 base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), id));
98 return ERR_IO_PENDING;
101 int MockHostResolverBase::ResolveFromCache(const RequestInfo& info,
102 AddressList* addresses,
103 const BoundNetLog& net_log) {
104 num_resolve_from_cache_++;
105 DCHECK(CalledOnValidThread());
106 next_request_id_++;
107 int rv = ResolveFromIPLiteralOrCache(info, addresses);
108 return rv;
111 void MockHostResolverBase::CancelRequest(RequestHandle handle) {
112 DCHECK(CalledOnValidThread());
113 size_t id = reinterpret_cast<size_t>(handle);
114 RequestMap::iterator it = requests_.find(id);
115 if (it != requests_.end()) {
116 scoped_ptr<Request> req(it->second);
117 requests_.erase(it);
118 } else {
119 NOTREACHED() << "CancelRequest must NOT be called after request is "
120 "complete or canceled.";
124 HostCache* MockHostResolverBase::GetHostCache() {
125 return cache_.get();
128 void MockHostResolverBase::ResolveAllPending() {
129 DCHECK(CalledOnValidThread());
130 DCHECK(ondemand_mode_);
131 for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i) {
132 base::MessageLoop::current()->PostTask(
133 FROM_HERE,
134 base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), i->first));
138 // start id from 1 to distinguish from NULL RequestHandle
139 MockHostResolverBase::MockHostResolverBase(bool use_caching)
140 : last_request_priority_(DEFAULT_PRIORITY),
141 synchronous_mode_(false),
142 ondemand_mode_(false),
143 next_request_id_(1),
144 num_resolve_(0),
145 num_resolve_from_cache_(0) {
146 rules_ = CreateCatchAllHostResolverProc();
148 if (use_caching) {
149 cache_.reset(new HostCache(kMaxCacheEntries));
153 int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info,
154 AddressList* addresses) {
155 IPAddressNumber ip;
156 if (ParseIPLiteralToNumber(info.hostname(), &ip)) {
157 *addresses = AddressList::CreateFromIPAddress(ip, info.port());
158 if (info.host_resolver_flags() & HOST_RESOLVER_CANONNAME)
159 addresses->SetDefaultCanonicalName();
160 return OK;
162 int rv = ERR_DNS_CACHE_MISS;
163 if (cache_.get() && info.allow_cached_response()) {
164 HostCache::Key key(info.hostname(),
165 info.address_family(),
166 info.host_resolver_flags());
167 const HostCache::Entry* entry = cache_->Lookup(key, base::TimeTicks::Now());
168 if (entry) {
169 rv = entry->error;
170 if (rv == OK)
171 *addresses = AddressList::CopyWithPort(entry->addrlist, info.port());
174 return rv;
177 int MockHostResolverBase::ResolveProc(size_t id,
178 const RequestInfo& info,
179 AddressList* addresses) {
180 AddressList addr;
181 int rv = rules_->Resolve(info.hostname(),
182 info.address_family(),
183 info.host_resolver_flags(),
184 &addr,
185 NULL);
186 if (cache_.get()) {
187 HostCache::Key key(info.hostname(),
188 info.address_family(),
189 info.host_resolver_flags());
190 // Storing a failure with TTL 0 so that it overwrites previous value.
191 base::TimeDelta ttl;
192 if (rv == OK)
193 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
194 cache_->Set(key, HostCache::Entry(rv, addr), base::TimeTicks::Now(), ttl);
196 if (rv == OK)
197 *addresses = AddressList::CopyWithPort(addr, info.port());
198 return rv;
201 void MockHostResolverBase::ResolveNow(size_t id) {
202 RequestMap::iterator it = requests_.find(id);
203 if (it == requests_.end())
204 return; // was canceled
206 scoped_ptr<Request> req(it->second);
207 requests_.erase(it);
208 int rv = ResolveProc(id, req->info, req->addresses);
209 if (!req->callback.is_null())
210 req->callback.Run(rv);
213 //-----------------------------------------------------------------------------
215 struct RuleBasedHostResolverProc::Rule {
216 enum ResolverType {
217 kResolverTypeFail,
218 kResolverTypeSystem,
219 kResolverTypeIPLiteral,
222 ResolverType resolver_type;
223 std::string host_pattern;
224 AddressFamily address_family;
225 HostResolverFlags host_resolver_flags;
226 std::string replacement;
227 std::string canonical_name;
228 int latency_ms; // In milliseconds.
230 Rule(ResolverType resolver_type,
231 const std::string& host_pattern,
232 AddressFamily address_family,
233 HostResolverFlags host_resolver_flags,
234 const std::string& replacement,
235 const std::string& canonical_name,
236 int latency_ms)
237 : resolver_type(resolver_type),
238 host_pattern(host_pattern),
239 address_family(address_family),
240 host_resolver_flags(host_resolver_flags),
241 replacement(replacement),
242 canonical_name(canonical_name),
243 latency_ms(latency_ms) {}
246 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
247 : HostResolverProc(previous) {
250 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
251 const std::string& replacement) {
252 AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
253 replacement);
256 void RuleBasedHostResolverProc::AddRuleForAddressFamily(
257 const std::string& host_pattern,
258 AddressFamily address_family,
259 const std::string& replacement) {
260 DCHECK(!replacement.empty());
261 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
262 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
263 Rule rule(Rule::kResolverTypeSystem,
264 host_pattern,
265 address_family,
266 flags,
267 replacement,
268 std::string(),
270 rules_.push_back(rule);
273 void RuleBasedHostResolverProc::AddIPLiteralRule(
274 const std::string& host_pattern,
275 const std::string& ip_literal,
276 const std::string& canonical_name) {
277 // Literals are always resolved to themselves by HostResolverImpl,
278 // consequently we do not support remapping them.
279 IPAddressNumber ip_number;
280 DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number));
281 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
282 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
283 if (!canonical_name.empty())
284 flags |= HOST_RESOLVER_CANONNAME;
285 Rule rule(Rule::kResolverTypeIPLiteral, host_pattern,
286 ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name,
288 rules_.push_back(rule);
291 void RuleBasedHostResolverProc::AddRuleWithLatency(
292 const std::string& host_pattern,
293 const std::string& replacement,
294 int latency_ms) {
295 DCHECK(!replacement.empty());
296 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
297 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
298 Rule rule(Rule::kResolverTypeSystem,
299 host_pattern,
300 ADDRESS_FAMILY_UNSPECIFIED,
301 flags,
302 replacement,
303 std::string(),
304 latency_ms);
305 rules_.push_back(rule);
308 void RuleBasedHostResolverProc::AllowDirectLookup(
309 const std::string& host_pattern) {
310 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
311 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
312 Rule rule(Rule::kResolverTypeSystem,
313 host_pattern,
314 ADDRESS_FAMILY_UNSPECIFIED,
315 flags,
316 std::string(),
317 std::string(),
319 rules_.push_back(rule);
322 void RuleBasedHostResolverProc::AddSimulatedFailure(
323 const std::string& host_pattern) {
324 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
325 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
326 Rule rule(Rule::kResolverTypeFail,
327 host_pattern,
328 ADDRESS_FAMILY_UNSPECIFIED,
329 flags,
330 std::string(),
331 std::string(),
333 rules_.push_back(rule);
336 void RuleBasedHostResolverProc::ClearRules() {
337 rules_.clear();
340 int RuleBasedHostResolverProc::Resolve(const std::string& host,
341 AddressFamily address_family,
342 HostResolverFlags host_resolver_flags,
343 AddressList* addrlist,
344 int* os_error) {
345 RuleList::iterator r;
346 for (r = rules_.begin(); r != rules_.end(); ++r) {
347 bool matches_address_family =
348 r->address_family == ADDRESS_FAMILY_UNSPECIFIED ||
349 r->address_family == address_family;
350 // Ignore HOST_RESOLVER_SYSTEM_ONLY, since it should have no impact on
351 // whether a rule matches.
352 HostResolverFlags flags = host_resolver_flags & ~HOST_RESOLVER_SYSTEM_ONLY;
353 // Flags match if all of the bitflags in host_resolver_flags are enabled
354 // in the rule's host_resolver_flags. However, the rule may have additional
355 // flags specified, in which case the flags should still be considered a
356 // match.
357 bool matches_flags = (r->host_resolver_flags & flags) == flags;
358 if (matches_flags && matches_address_family &&
359 MatchPattern(host, r->host_pattern)) {
360 if (r->latency_ms != 0) {
361 base::PlatformThread::Sleep(
362 base::TimeDelta::FromMilliseconds(r->latency_ms));
365 // Remap to a new host.
366 const std::string& effective_host =
367 r->replacement.empty() ? host : r->replacement;
369 // Apply the resolving function to the remapped hostname.
370 switch (r->resolver_type) {
371 case Rule::kResolverTypeFail:
372 return ERR_NAME_NOT_RESOLVED;
373 case Rule::kResolverTypeSystem:
374 #if defined(OS_WIN)
375 net::EnsureWinsockInit();
376 #endif
377 return SystemHostResolverCall(effective_host,
378 address_family,
379 host_resolver_flags,
380 addrlist, os_error);
381 case Rule::kResolverTypeIPLiteral:
382 return ParseAddressList(effective_host,
383 r->canonical_name,
384 addrlist);
385 default:
386 NOTREACHED();
387 return ERR_UNEXPECTED;
391 return ResolveUsingPrevious(host, address_family,
392 host_resolver_flags, addrlist, os_error);
395 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
398 RuleBasedHostResolverProc* CreateCatchAllHostResolverProc() {
399 RuleBasedHostResolverProc* catchall = new RuleBasedHostResolverProc(NULL);
400 catchall->AddIPLiteralRule("*", "127.0.0.1", "localhost");
402 // Next add a rules-based layer the use controls.
403 return new RuleBasedHostResolverProc(catchall);
406 //-----------------------------------------------------------------------------
408 int HangingHostResolver::Resolve(const RequestInfo& info,
409 RequestPriority priority,
410 AddressList* addresses,
411 const CompletionCallback& callback,
412 RequestHandle* out_req,
413 const BoundNetLog& net_log) {
414 return ERR_IO_PENDING;
417 int HangingHostResolver::ResolveFromCache(const RequestInfo& info,
418 AddressList* addresses,
419 const BoundNetLog& net_log) {
420 return ERR_DNS_CACHE_MISS;
423 //-----------------------------------------------------------------------------
425 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
427 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
428 HostResolverProc* proc) {
429 Init(proc);
432 ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
433 HostResolverProc* old_proc =
434 HostResolverProc::SetDefault(previous_proc_.get());
435 // The lifetimes of multiple instances must be nested.
436 CHECK_EQ(old_proc, current_proc_);
439 void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) {
440 current_proc_ = proc;
441 previous_proc_ = HostResolverProc::SetDefault(current_proc_.get());
442 current_proc_->SetLastProc(previous_proc_.get());
445 } // namespace net