Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(248)

Side by Side Diff: net/dns/dns_config_service_posix.cc

Issue 1047103002: Avoid initial NetworkChangeNotifier OnDNSChanged() signal on Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: revert an accidental test enabling Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/dns/dns_config_service_posix.h ('k') | net/dns/dns_config_service_posix_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/dns/dns_config_service_posix.h" 5 #include "net/dns/dns_config_service_posix.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/files/file.h"
11 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
12 #include "base/files/file_path_watcher.h" 13 #include "base/files/file_path_watcher.h"
13 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
14 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
16 #include "base/time/time.h" 17 #include "base/time/time.h"
17 #include "net/base/ip_endpoint.h" 18 #include "net/base/ip_endpoint.h"
18 #include "net/base/net_util.h" 19 #include "net/base/net_util.h"
19 #include "net/dns/dns_hosts.h" 20 #include "net/dns/dns_hosts.h"
20 #include "net/dns/dns_protocol.h" 21 #include "net/dns/dns_protocol.h"
(...skipping 30 matching lines...) Expand all
51 public: 52 public:
52 typedef base::Callback<void(bool succeeded)> CallbackType; 53 typedef base::Callback<void(bool succeeded)> CallbackType;
53 54
54 bool Watch(const CallbackType& callback) { 55 bool Watch(const CallbackType& callback) {
55 return false; 56 return false;
56 } 57 }
57 }; 58 };
58 59
59 #elif defined(OS_ANDROID) 60 #elif defined(OS_ANDROID)
60 // On Android, assume DNS config may have changed on every network change. 61 // On Android, assume DNS config may have changed on every network change.
61 class DnsConfigWatcher : public NetworkChangeNotifier::NetworkChangeObserver { 62 class DnsConfigWatcher {
62 public: 63 public:
63 DnsConfigWatcher() {
64 NetworkChangeNotifier::AddNetworkChangeObserver(this);
65 }
66
67 ~DnsConfigWatcher() override {
68 NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
69 }
70
71 bool Watch(const base::Callback<void(bool succeeded)>& callback) { 64 bool Watch(const base::Callback<void(bool succeeded)>& callback) {
72 callback_ = callback; 65 callback_ = callback;
73 return true; 66 return true;
74 } 67 }
75 68
76 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override { 69 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) {
77 if (!callback_.is_null() && type != NetworkChangeNotifier::CONNECTION_NONE) 70 if (!callback_.is_null() && type != NetworkChangeNotifier::CONNECTION_NONE)
78 callback_.Run(true); 71 callback_.Run(true);
79 } 72 }
80 73
81 private: 74 private:
82 base::Callback<void(bool succeeded)> callback_; 75 base::Callback<void(bool succeeded)> callback_;
83 }; 76 };
84 #elif !defined(OS_MACOSX) 77 #elif !defined(OS_MACOSX)
85 // DnsConfigWatcher for OS_MACOSX is in dns_config_watcher_mac.{hh,cc}. 78 // DnsConfigWatcher for OS_MACOSX is in dns_config_watcher_mac.{hh,cc}.
86 79
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 187
195 return CONFIG_PARSE_POSIX_OK; 188 return CONFIG_PARSE_POSIX_OK;
196 } 189 }
197 #endif 190 #endif
198 191
199 } // namespace 192 } // namespace
200 193
201 class DnsConfigServicePosix::Watcher { 194 class DnsConfigServicePosix::Watcher {
202 public: 195 public:
203 explicit Watcher(DnsConfigServicePosix* service) 196 explicit Watcher(DnsConfigServicePosix* service)
204 : service_(service), 197 : service_(service), weak_factory_(this) {}
205 weak_factory_(this) {}
206 ~Watcher() {} 198 ~Watcher() {}
207 199
208 bool Watch() { 200 bool Watch() {
209 bool success = true; 201 bool success = true;
210 if (!config_watcher_.Watch(base::Bind(&Watcher::OnConfigChanged, 202 if (!config_watcher_.Watch(base::Bind(&Watcher::OnConfigChanged,
211 base::Unretained(this)))) { 203 base::Unretained(this)))) {
212 LOG(ERROR) << "DNS config watch failed to start."; 204 LOG(ERROR) << "DNS config watch failed to start.";
213 success = false; 205 success = false;
214 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", 206 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus",
215 DNS_CONFIG_WATCH_FAILED_TO_START_CONFIG, 207 DNS_CONFIG_WATCH_FAILED_TO_START_CONFIG,
216 DNS_CONFIG_WATCH_MAX); 208 DNS_CONFIG_WATCH_MAX);
217 } 209 }
218 if (!hosts_watcher_.Watch(base::FilePath(kFilePathHosts), false, 210 if (!hosts_watcher_.Watch(
219 base::Bind(&Watcher::OnHostsChanged, 211 base::FilePath(service_->file_path_hosts_), false,
220 base::Unretained(this)))) { 212 base::Bind(&Watcher::OnHostsChanged, base::Unretained(this)))) {
221 LOG(ERROR) << "DNS hosts watch failed to start."; 213 LOG(ERROR) << "DNS hosts watch failed to start.";
222 success = false; 214 success = false;
223 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", 215 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus",
224 DNS_CONFIG_WATCH_FAILED_TO_START_HOSTS, 216 DNS_CONFIG_WATCH_FAILED_TO_START_HOSTS,
225 DNS_CONFIG_WATCH_MAX); 217 DNS_CONFIG_WATCH_MAX);
226 } 218 }
227 return success; 219 return success;
228 } 220 }
229 221
222 #if defined(OS_ANDROID)
223 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) {
224 config_watcher_.OnNetworkChanged(type);
225 }
226 #endif // defined(OS_ANDROID)
227
230 private: 228 private:
231 void OnConfigChanged(bool succeeded) { 229 void OnConfigChanged(bool succeeded) {
230 #if defined(OS_ANDROID)
231 service_->seen_config_change_ = true;
232 #endif // defined(OS_ANDROID)
232 // Ignore transient flutter of resolv.conf by delaying the signal a bit. 233 // Ignore transient flutter of resolv.conf by delaying the signal a bit.
233 const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(50); 234 const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(50);
234 base::MessageLoop::current()->PostDelayedTask( 235 base::MessageLoop::current()->PostDelayedTask(
235 FROM_HERE, 236 FROM_HERE,
236 base::Bind(&Watcher::OnConfigChangedDelayed, 237 base::Bind(&Watcher::OnConfigChangedDelayed,
237 weak_factory_.GetWeakPtr(), 238 weak_factory_.GetWeakPtr(),
238 succeeded), 239 succeeded),
239 kDelay); 240 kDelay);
240 } 241 }
241 void OnConfigChangedDelayed(bool succeeded) { 242 void OnConfigChangedDelayed(bool succeeded) {
(...skipping 16 matching lines...) Expand all
258 // it to DnsConfig (except on Android, where it reads system properties 259 // it to DnsConfig (except on Android, where it reads system properties
259 // net.dns1 and net.dns2; see #if around ReadDnsConfig above.) 260 // net.dns1 and net.dns2; see #if around ReadDnsConfig above.)
260 class DnsConfigServicePosix::ConfigReader : public SerialWorker { 261 class DnsConfigServicePosix::ConfigReader : public SerialWorker {
261 public: 262 public:
262 explicit ConfigReader(DnsConfigServicePosix* service) 263 explicit ConfigReader(DnsConfigServicePosix* service)
263 : service_(service), success_(false) {} 264 : service_(service), success_(false) {}
264 265
265 void DoWork() override { 266 void DoWork() override {
266 base::TimeTicks start_time = base::TimeTicks::Now(); 267 base::TimeTicks start_time = base::TimeTicks::Now();
267 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_); 268 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_);
269 if (service_->dns_config_for_testing_) {
270 dns_config_ = *service_->dns_config_for_testing_;
271 result = CONFIG_PARSE_POSIX_OK;
272 }
268 switch (result) { 273 switch (result) {
269 case CONFIG_PARSE_POSIX_MISSING_OPTIONS: 274 case CONFIG_PARSE_POSIX_MISSING_OPTIONS:
270 case CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS: 275 case CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS:
271 DCHECK(dns_config_.unhandled_options); 276 DCHECK(dns_config_.unhandled_options);
272 // Fall through. 277 // Fall through.
273 case CONFIG_PARSE_POSIX_OK: 278 case CONFIG_PARSE_POSIX_OK:
274 success_ = true; 279 success_ = true;
275 break; 280 break;
276 default: 281 default:
277 success_ = false; 282 success_ = false;
(...skipping 23 matching lines...) Expand all
301 DnsConfig dns_config_; 306 DnsConfig dns_config_;
302 bool success_; 307 bool success_;
303 308
304 DISALLOW_COPY_AND_ASSIGN(ConfigReader); 309 DISALLOW_COPY_AND_ASSIGN(ConfigReader);
305 }; 310 };
306 311
307 // A SerialWorker that reads the HOSTS file and runs Callback. 312 // A SerialWorker that reads the HOSTS file and runs Callback.
308 class DnsConfigServicePosix::HostsReader : public SerialWorker { 313 class DnsConfigServicePosix::HostsReader : public SerialWorker {
309 public: 314 public:
310 explicit HostsReader(DnsConfigServicePosix* service) 315 explicit HostsReader(DnsConfigServicePosix* service)
311 : service_(service), path_(kFilePathHosts), success_(false) {} 316 : service_(service), success_(false) {}
312 317
313 private: 318 private:
314 ~HostsReader() override {} 319 ~HostsReader() override {}
315 320
316 void DoWork() override { 321 void DoWork() override {
317 base::TimeTicks start_time = base::TimeTicks::Now(); 322 base::TimeTicks start_time = base::TimeTicks::Now();
318 success_ = ParseHostsFile(path_, &hosts_); 323 success_ =
324 ParseHostsFile(base::FilePath(service_->file_path_hosts_), &hosts_);
319 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostParseResult", success_); 325 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostParseResult", success_);
320 UMA_HISTOGRAM_TIMES("AsyncDNS.HostsParseDuration", 326 UMA_HISTOGRAM_TIMES("AsyncDNS.HostsParseDuration",
321 base::TimeTicks::Now() - start_time); 327 base::TimeTicks::Now() - start_time);
322 } 328 }
323 329
324 void OnWorkFinished() override { 330 void OnWorkFinished() override {
325 if (success_) { 331 if (success_) {
326 service_->OnHostsRead(hosts_); 332 service_->OnHostsRead(hosts_);
327 } else { 333 } else {
328 LOG(WARNING) << "Failed to read DnsHosts."; 334 LOG(WARNING) << "Failed to read DnsHosts.";
329 } 335 }
330 } 336 }
331 337
332 DnsConfigServicePosix* service_; 338 DnsConfigServicePosix* service_;
333 const base::FilePath path_;
334 // Written in DoWork, read in OnWorkFinished, no locking necessary. 339 // Written in DoWork, read in OnWorkFinished, no locking necessary.
335 DnsHosts hosts_; 340 DnsHosts hosts_;
336 bool success_; 341 bool success_;
337 342
338 DISALLOW_COPY_AND_ASSIGN(HostsReader); 343 DISALLOW_COPY_AND_ASSIGN(HostsReader);
339 }; 344 };
340 345
341 DnsConfigServicePosix::DnsConfigServicePosix() 346 DnsConfigServicePosix::DnsConfigServicePosix()
342 : config_reader_(new ConfigReader(this)), 347 : file_path_hosts_(kFilePathHosts),
343 hosts_reader_(new HostsReader(this)) {} 348 dns_config_for_testing_(nullptr),
349 config_reader_(new ConfigReader(this)),
350 hosts_reader_(new HostsReader(this))
351 #if defined(OS_ANDROID)
352 ,
353 seen_config_change_(false)
354 #endif // defined(OS_ANDROID)
355 {
356 }
344 357
345 DnsConfigServicePosix::~DnsConfigServicePosix() { 358 DnsConfigServicePosix::~DnsConfigServicePosix() {
346 config_reader_->Cancel(); 359 config_reader_->Cancel();
347 hosts_reader_->Cancel(); 360 hosts_reader_->Cancel();
348 } 361 }
349 362
350 void DnsConfigServicePosix::ReadNow() { 363 void DnsConfigServicePosix::ReadNow() {
351 config_reader_->WorkNow(); 364 config_reader_->WorkNow();
352 hosts_reader_->WorkNow(); 365 hosts_reader_->WorkNow();
353 } 366 }
(...skipping 25 matching lines...) Expand all
379 hosts_reader_->WorkNow(); 392 hosts_reader_->WorkNow();
380 } else { 393 } else {
381 LOG(ERROR) << "DNS hosts watch failed."; 394 LOG(ERROR) << "DNS hosts watch failed.";
382 set_watch_failed(true); 395 set_watch_failed(true);
383 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", 396 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus",
384 DNS_CONFIG_WATCH_FAILED_HOSTS, 397 DNS_CONFIG_WATCH_FAILED_HOSTS,
385 DNS_CONFIG_WATCH_MAX); 398 DNS_CONFIG_WATCH_MAX);
386 } 399 }
387 } 400 }
388 401
402 void DnsConfigServicePosix::SetDnsConfigForTesting(
403 const DnsConfig* dns_config) {
404 DCHECK(CalledOnValidThread());
405 dns_config_for_testing_ = dns_config;
406 }
407
389 #if !defined(OS_ANDROID) 408 #if !defined(OS_ANDROID)
390 ConfigParsePosixResult ConvertResStateToDnsConfig(const struct __res_state& res, 409 ConfigParsePosixResult ConvertResStateToDnsConfig(const struct __res_state& res,
391 DnsConfig* dns_config) { 410 DnsConfig* dns_config) {
392 CHECK(dns_config != NULL); 411 CHECK(dns_config != NULL);
393 if (!(res.options & RES_INIT)) 412 if (!(res.options & RES_INIT))
394 return CONFIG_PARSE_POSIX_RES_INIT_UNSET; 413 return CONFIG_PARSE_POSIX_RES_INIT_UNSET;
395 414
396 dns_config->nameservers.clear(); 415 dns_config->nameservers.clear();
397 416
398 #if defined(OS_MACOSX) || defined(OS_FREEBSD) 417 #if defined(OS_MACOSX) || defined(OS_FREEBSD)
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 505
487 // If any name server is 0.0.0.0, assume the configuration is invalid. 506 // If any name server is 0.0.0.0, assume the configuration is invalid.
488 // TODO(szym): Measure how often this happens. http://crbug.com/125599 507 // TODO(szym): Measure how often this happens. http://crbug.com/125599
489 const IPAddressNumber kEmptyAddress(kIPv4AddressSize); 508 const IPAddressNumber kEmptyAddress(kIPv4AddressSize);
490 for (unsigned i = 0; i < dns_config->nameservers.size(); ++i) { 509 for (unsigned i = 0; i < dns_config->nameservers.size(); ++i) {
491 if (dns_config->nameservers[i].address() == kEmptyAddress) 510 if (dns_config->nameservers[i].address() == kEmptyAddress)
492 return CONFIG_PARSE_POSIX_NULL_ADDRESS; 511 return CONFIG_PARSE_POSIX_NULL_ADDRESS;
493 } 512 }
494 return CONFIG_PARSE_POSIX_OK; 513 return CONFIG_PARSE_POSIX_OK;
495 } 514 }
496 #endif // !defined(OS_ANDROID) 515
516 #else // defined(OS_ANDROID)
517
518 bool DnsConfigServicePosix::SeenChangeSince(
519 const base::Time& since_time) const {
520 DCHECK(CalledOnValidThread());
521 if (seen_config_change_)
522 return true;
523 base::File hosts(base::FilePath(file_path_hosts_),
524 base::File::FLAG_OPEN | base::File::FLAG_READ);
525 base::File::Info hosts_info;
526 // File last modified times are not nearly as accurate as Time::Now() and are
527 // rounded down. This means a file modified at 1:23.456 might only
528 // be given a last modified time of 1:23.450. If we compared the last
529 // modified time directly to |since_time| we might miss changes to the hosts
530 // file because of this rounding down. To account for this the |since_time|
531 // is pushed back by 1s which should more than account for any rounding.
532 // In practice file modified times on Android are two orders of magnitude
533 // more accurate than this 1s. In practice the hosts file on Android always
534 // contains "127.0.0.1 localhost" and is never modified after Android is
535 // installed.
536 return !hosts.GetInfo(&hosts_info) ||
537 hosts_info.last_modified >=
538 (since_time - base::TimeDelta::FromSeconds(1));
539 }
540
541 void DnsConfigServicePosix::OnNetworkChanged(
542 NetworkChangeNotifier::ConnectionType type) {
543 DCHECK(CalledOnValidThread());
544 DCHECK(watcher_);
545 watcher_->OnNetworkChanged(type);
546 }
547 #endif // defined(OS_ANDROID)
497 548
498 } // namespace internal 549 } // namespace internal
499 550
500 // static 551 // static
501 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 552 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
502 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServicePosix()); 553 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServicePosix());
503 } 554 }
504 555
505 } // namespace net 556 } // namespace net
OLDNEW
« no previous file with comments | « net/dns/dns_config_service_posix.h ('k') | net/dns/dns_config_service_posix_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698