| OLD | NEW |
| 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 <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 class DnsConfigWatcher { | 54 class DnsConfigWatcher { |
| 55 public: | 55 public: |
| 56 typedef base::Callback<void(bool succeeded)> CallbackType; | 56 typedef base::Callback<void(bool succeeded)> CallbackType; |
| 57 | 57 |
| 58 bool Watch(const CallbackType& callback) { | 58 bool Watch(const CallbackType& callback) { |
| 59 return false; | 59 return false; |
| 60 } | 60 } |
| 61 }; | 61 }; |
| 62 | 62 |
| 63 #elif defined(OS_ANDROID) | 63 #elif defined(OS_ANDROID) |
| 64 |
| 64 // On Android, assume DNS config may have changed on every network change. | 65 // On Android, assume DNS config may have changed on every network change. |
| 65 class DnsConfigWatcher { | 66 class DnsConfigWatcher { |
| 66 public: | 67 public: |
| 67 bool Watch(const base::Callback<void(bool succeeded)>& callback) { | 68 bool Watch(const base::Callback<void(bool succeeded)>& callback) { |
| 68 callback_ = callback; | 69 callback_ = callback; |
| 69 return true; | 70 return true; |
| 70 } | 71 } |
| 71 | 72 |
| 72 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) { | 73 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) { |
| 73 if (!callback_.is_null() && type != NetworkChangeNotifier::CONNECTION_NONE) | 74 if (!callback_.is_null() && type != NetworkChangeNotifier::CONNECTION_NONE) |
| 74 callback_.Run(true); | 75 callback_.Run(true); |
| 75 } | 76 } |
| 76 | 77 |
| 77 private: | 78 private: |
| 78 base::Callback<void(bool succeeded)> callback_; | 79 base::Callback<void(bool succeeded)> callback_; |
| 79 }; | 80 }; |
| 80 #elif !defined(OS_MACOSX) | 81 |
| 82 #elif defined(OS_MACOSX) |
| 83 |
| 81 // DnsConfigWatcher for OS_MACOSX is in dns_config_watcher_mac.{hh,cc}. | 84 // DnsConfigWatcher for OS_MACOSX is in dns_config_watcher_mac.{hh,cc}. |
| 82 | 85 |
| 86 #else // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) |
| 87 |
| 83 #ifndef _PATH_RESCONF // Normally defined in <resolv.h> | 88 #ifndef _PATH_RESCONF // Normally defined in <resolv.h> |
| 84 #define _PATH_RESCONF "/etc/resolv.conf" | 89 #define _PATH_RESCONF "/etc/resolv.conf" |
| 85 #endif | 90 #endif |
| 86 | 91 |
| 87 static const base::FilePath::CharType* kFilePathConfig = | 92 static const base::FilePath::CharType* kFilePathConfig = |
| 88 FILE_PATH_LITERAL(_PATH_RESCONF); | 93 FILE_PATH_LITERAL(_PATH_RESCONF); |
| 89 | 94 |
| 90 class DnsConfigWatcher { | 95 class DnsConfigWatcher { |
| 91 public: | 96 public: |
| 92 typedef base::Callback<void(bool succeeded)> CallbackType; | 97 typedef base::Callback<void(bool succeeded)> CallbackType; |
| 93 | 98 |
| 94 bool Watch(const CallbackType& callback) { | 99 bool Watch(const CallbackType& callback) { |
| 95 callback_ = callback; | 100 callback_ = callback; |
| 96 return watcher_.Watch(base::FilePath(kFilePathConfig), false, | 101 return watcher_.Watch(base::FilePath(kFilePathConfig), false, |
| 97 base::Bind(&DnsConfigWatcher::OnCallback, | 102 base::Bind(&DnsConfigWatcher::OnCallback, |
| 98 base::Unretained(this))); | 103 base::Unretained(this))); |
| 99 } | 104 } |
| 100 | 105 |
| 101 private: | 106 private: |
| 102 void OnCallback(const base::FilePath& path, bool error) { | 107 void OnCallback(const base::FilePath& path, bool error) { |
| 103 callback_.Run(!error); | 108 callback_.Run(!error); |
| 104 } | 109 } |
| 105 | 110 |
| 106 base::FilePathWatcher watcher_; | 111 base::FilePathWatcher watcher_; |
| 107 CallbackType callback_; | 112 CallbackType callback_; |
| 108 }; | 113 }; |
| 114 |
| 109 #endif | 115 #endif |
| 110 | 116 |
| 111 #if !defined(OS_ANDROID) | 117 #if !defined(OS_ANDROID) |
| 112 ConfigParsePosixResult ReadDnsConfig(DnsConfig* config) { | 118 ConfigParsePosixResult ReadDnsConfig(DnsConfig* config) { |
| 113 ConfigParsePosixResult result; | 119 ConfigParsePosixResult result; |
| 114 config->unhandled_options = false; | 120 config->unhandled_options = false; |
| 115 #if defined(OS_OPENBSD) | 121 #if defined(OS_OPENBSD) |
| 116 // Note: res_ninit in glibc always returns 0 and sets RES_INIT. | 122 // Note: res_ninit in glibc always returns 0 and sets RES_INIT. |
| 117 // res_init behaves the same way. | 123 // res_init behaves the same way. |
| 118 memset(&_res, 0, sizeof(_res)); | 124 memset(&_res, 0, sizeof(_res)); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 bool Watch() { | 209 bool Watch() { |
| 204 bool success = true; | 210 bool success = true; |
| 205 if (!config_watcher_.Watch(base::Bind(&Watcher::OnConfigChanged, | 211 if (!config_watcher_.Watch(base::Bind(&Watcher::OnConfigChanged, |
| 206 base::Unretained(this)))) { | 212 base::Unretained(this)))) { |
| 207 LOG(ERROR) << "DNS config watch failed to start."; | 213 LOG(ERROR) << "DNS config watch failed to start."; |
| 208 success = false; | 214 success = false; |
| 209 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", | 215 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", |
| 210 DNS_CONFIG_WATCH_FAILED_TO_START_CONFIG, | 216 DNS_CONFIG_WATCH_FAILED_TO_START_CONFIG, |
| 211 DNS_CONFIG_WATCH_MAX); | 217 DNS_CONFIG_WATCH_MAX); |
| 212 } | 218 } |
| 213 #if !defined(OS_IOS) | 219 // Hosts file should never change on Android or iOS (and watching it on Android |
| 220 // is problematic; see http://crbug.com/600442), so don't watch it there. |
| 221 #if !defined(OS_ANDROID) && !defined(OS_IOS) |
| 214 if (!hosts_watcher_.Watch( | 222 if (!hosts_watcher_.Watch( |
| 215 base::FilePath(service_->file_path_hosts_), false, | 223 base::FilePath(service_->file_path_hosts_), false, |
| 216 base::Bind(&Watcher::OnHostsChanged, base::Unretained(this)))) { | 224 base::Bind(&Watcher::OnHostsChanged, base::Unretained(this)))) { |
| 217 LOG(ERROR) << "DNS hosts watch failed to start."; | 225 LOG(ERROR) << "DNS hosts watch failed to start."; |
| 218 success = false; | 226 success = false; |
| 219 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", | 227 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", |
| 220 DNS_CONFIG_WATCH_FAILED_TO_START_HOSTS, | 228 DNS_CONFIG_WATCH_FAILED_TO_START_HOSTS, |
| 221 DNS_CONFIG_WATCH_MAX); | 229 DNS_CONFIG_WATCH_MAX); |
| 222 } | 230 } |
| 223 #endif | 231 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) |
| 224 return success; | 232 return success; |
| 225 } | 233 } |
| 226 | 234 |
| 227 #if defined(OS_ANDROID) | 235 #if defined(OS_ANDROID) |
| 228 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) { | 236 void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) { |
| 229 config_watcher_.OnNetworkChanged(type); | 237 config_watcher_.OnNetworkChanged(type); |
| 230 } | 238 } |
| 231 #endif // defined(OS_ANDROID) | 239 #endif // defined(OS_ANDROID) |
| 232 | 240 |
| 233 private: | 241 private: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 244 } | 252 } |
| 245 void OnConfigChangedDelayed(bool succeeded) { | 253 void OnConfigChangedDelayed(bool succeeded) { |
| 246 service_->OnConfigChanged(succeeded); | 254 service_->OnConfigChanged(succeeded); |
| 247 } | 255 } |
| 248 void OnHostsChanged(const base::FilePath& path, bool error) { | 256 void OnHostsChanged(const base::FilePath& path, bool error) { |
| 249 service_->OnHostsChanged(!error); | 257 service_->OnHostsChanged(!error); |
| 250 } | 258 } |
| 251 | 259 |
| 252 DnsConfigServicePosix* service_; | 260 DnsConfigServicePosix* service_; |
| 253 DnsConfigWatcher config_watcher_; | 261 DnsConfigWatcher config_watcher_; |
| 254 #if !defined(OS_IOS) | 262 #if !defined(OS_ANDROID) && !defined(OS_IOS) |
| 255 base::FilePathWatcher hosts_watcher_; | 263 base::FilePathWatcher hosts_watcher_; |
| 256 #endif | 264 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) |
| 257 | 265 |
| 258 base::WeakPtrFactory<Watcher> weak_factory_; | 266 base::WeakPtrFactory<Watcher> weak_factory_; |
| 259 | 267 |
| 260 DISALLOW_COPY_AND_ASSIGN(Watcher); | 268 DISALLOW_COPY_AND_ASSIGN(Watcher); |
| 261 }; | 269 }; |
| 262 | 270 |
| 263 // A SerialWorker that uses libresolv to initialize res_state and converts | 271 // A SerialWorker that uses libresolv to initialize res_state and converts |
| 264 // it to DnsConfig (except on Android, where it reads system properties | 272 // it to DnsConfig (except on Android, where it reads system properties |
| 265 // net.dns1 and net.dns2; see #if around ReadDnsConfig above.) | 273 // net.dns1 and net.dns2; see #if around ReadDnsConfig above.) |
| 266 class DnsConfigServicePosix::ConfigReader : public SerialWorker { | 274 class DnsConfigServicePosix::ConfigReader : public SerialWorker { |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 return CONFIG_PARSE_POSIX_NULL_ADDRESS; | 555 return CONFIG_PARSE_POSIX_NULL_ADDRESS; |
| 548 } | 556 } |
| 549 return CONFIG_PARSE_POSIX_OK; | 557 return CONFIG_PARSE_POSIX_OK; |
| 550 } | 558 } |
| 551 | 559 |
| 552 #else // defined(OS_ANDROID) | 560 #else // defined(OS_ANDROID) |
| 553 | 561 |
| 554 bool DnsConfigServicePosix::SeenChangeSince( | 562 bool DnsConfigServicePosix::SeenChangeSince( |
| 555 const base::Time& since_time) const { | 563 const base::Time& since_time) const { |
| 556 DCHECK(CalledOnValidThread()); | 564 DCHECK(CalledOnValidThread()); |
| 557 if (seen_config_change_) | 565 return seen_config_change_; |
| 558 return true; | |
| 559 base::File hosts(base::FilePath(file_path_hosts_), | |
| 560 base::File::FLAG_OPEN | base::File::FLAG_READ); | |
| 561 base::File::Info hosts_info; | |
| 562 // File last modified times are not nearly as accurate as Time::Now() and are | |
| 563 // rounded down. This means a file modified at 1:23.456 might only | |
| 564 // be given a last modified time of 1:23.450. If we compared the last | |
| 565 // modified time directly to |since_time| we might miss changes to the hosts | |
| 566 // file because of this rounding down. To account for this the |since_time| | |
| 567 // is pushed back by 1s which should more than account for any rounding. | |
| 568 // In practice file modified times on Android are two orders of magnitude | |
| 569 // more accurate than this 1s. In practice the hosts file on Android always | |
| 570 // contains "127.0.0.1 localhost" and is never modified after Android is | |
| 571 // installed. | |
| 572 return !hosts.GetInfo(&hosts_info) || | |
| 573 hosts_info.last_modified >= | |
| 574 (since_time - base::TimeDelta::FromSeconds(1)); | |
| 575 } | 566 } |
| 576 | 567 |
| 577 void DnsConfigServicePosix::OnNetworkChanged( | 568 void DnsConfigServicePosix::OnNetworkChanged( |
| 578 NetworkChangeNotifier::ConnectionType type) { | 569 NetworkChangeNotifier::ConnectionType type) { |
| 579 DCHECK(CalledOnValidThread()); | 570 DCHECK(CalledOnValidThread()); |
| 580 DCHECK(watcher_); | 571 DCHECK(watcher_); |
| 581 watcher_->OnNetworkChanged(type); | 572 watcher_->OnNetworkChanged(type); |
| 582 } | 573 } |
| 583 #endif // defined(OS_ANDROID) | 574 #endif // defined(OS_ANDROID) |
| 584 | 575 |
| 585 } // namespace internal | 576 } // namespace internal |
| 586 | 577 |
| 587 // static | 578 // static |
| 588 std::unique_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { | 579 std::unique_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { |
| 589 return std::unique_ptr<DnsConfigService>( | 580 return std::unique_ptr<DnsConfigService>( |
| 590 new internal::DnsConfigServicePosix()); | 581 new internal::DnsConfigServicePosix()); |
| 591 } | 582 } |
| 592 | 583 |
| 593 } // namespace net | 584 } // namespace net |
| OLD | NEW |