Index: net/dns/dns_config_service_win.cc |
diff --git a/net/dns/dns_config_service_win.cc b/net/dns/dns_config_service_win.cc |
index 327ea2a22712a30323a3c5fdfba1c668627de180..c64f65142953f0db124604f2e0c3378028086973 100644 |
--- a/net/dns/dns_config_service_win.cc |
+++ b/net/dns/dns_config_service_win.cc |
@@ -19,14 +19,12 @@ |
#include "base/threading/non_thread_safe.h" |
#include "base/threading/thread_restrictions.h" |
#include "base/utf_string_conversions.h" |
-#include "base/win/object_watcher.h" |
#include "base/win/registry.h" |
#include "base/win/windows_version.h" |
#include "googleurl/src/url_canon.h" |
#include "net/base/net_util.h" |
#include "net/base/network_change_notifier.h" |
#include "net/dns/dns_protocol.h" |
-#include "net/dns/file_path_watcher_wrapper.h" |
#include "net/dns/serial_worker.h" |
#pragma comment(lib, "iphlpapi.lib") |
@@ -37,15 +35,6 @@ namespace internal { |
namespace { |
-// Registry key paths. |
-const wchar_t* const kTcpipPath = |
- L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"; |
-const wchar_t* const kTcpip6Path = |
- L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters"; |
-const wchar_t* const kDnscachePath = |
- L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters"; |
-const wchar_t* const kPolicyPath = |
- L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient"; |
const wchar_t* const kPrimaryDnsSuffixPath = |
L"SOFTWARE\\Policies\\Microsoft\\System\\DNSClient"; |
@@ -95,62 +84,6 @@ class RegistryReader : public base::NonThreadSafe { |
DISALLOW_COPY_AND_ASSIGN(RegistryReader); |
}; |
- |
-// Watches a single registry key for changes. |
-class RegistryWatcher : public base::win::ObjectWatcher::Delegate, |
- public base::NonThreadSafe { |
- public: |
- typedef base::Callback<void(bool succeeded)> CallbackType; |
- RegistryWatcher() {} |
- |
- bool Watch(const wchar_t* key, const CallbackType& callback) { |
- DCHECK(CalledOnValidThread()); |
- DCHECK(!callback.is_null()); |
- Cancel(); |
- if (key_.Open(HKEY_LOCAL_MACHINE, key, KEY_NOTIFY) != ERROR_SUCCESS) |
- return false; |
- if (key_.StartWatching() != ERROR_SUCCESS) |
- return false; |
- if (!watcher_.StartWatching(key_.watch_event(), this)) |
- return false; |
- callback_ = callback; |
- return true; |
- } |
- |
- bool IsWatching() const { |
- DCHECK(CalledOnValidThread()); |
- return !callback_.is_null(); |
- } |
- |
- void Cancel() { |
- DCHECK(CalledOnValidThread()); |
- callback_.Reset(); |
- if (key_.Valid()) { |
- watcher_.StopWatching(); |
- key_.StopWatching(); |
- key_.Close(); |
- } |
- } |
- |
- virtual void OnObjectSignaled(HANDLE object) OVERRIDE { |
- DCHECK(CalledOnValidThread()); |
- bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) && |
- watcher_.StartWatching(key_.watch_event(), this); |
- CallbackType callback = callback_; |
- if (!succeeded) |
- Cancel(); |
- if (!callback.is_null()) |
- callback.Run(succeeded); |
- } |
- |
- private: |
- CallbackType callback_; |
- base::win::RegKey key_; |
- base::win::ObjectWatcher watcher_; |
- |
- DISALLOW_COPY_AND_ASSIGN(RegistryWatcher); |
-}; |
- |
// Returns NULL if failed. |
scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> ReadIpHelper(ULONG flags) { |
base::ThreadRestrictions::AssertIOAllowed(); |
@@ -200,6 +133,13 @@ bool ParseDomainASCII(const string16& widestr, std::string* domain) { |
} // namespace |
+FilePath GetHostsPath() { |
+ TCHAR buffer[MAX_PATH]; |
+ UINT rc = GetSystemDirectory(buffer, MAX_PATH); |
+ DCHECK(0 < rc && rc < MAX_PATH); |
+ return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts")); |
+} |
+ |
bool ParseSearchList(const string16& value, std::vector<std::string>* output) { |
DCHECK(output); |
if (value.empty()) |
@@ -378,58 +318,7 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker { |
: service_(service), |
success_(false) {} |
- bool Watch() { |
- DCHECK(loop()->BelongsToCurrentThread()); |
- |
- RegistryWatcher::CallbackType callback = |
- base::Bind(&ConfigReader::OnChange, base::Unretained(this)); |
- |
- // The Tcpip key must be present. |
- if (!tcpip_watcher_.Watch(kTcpipPath, callback)) |
- return false; |
- |
- // Watch for IPv6 nameservers. |
- tcpip6_watcher_.Watch(kTcpip6Path, callback); |
- |
- // DNS suffix search list and devolution can be configured via group |
- // policy which sets this registry key. If the key is missing, the policy |
- // does not apply, and the DNS client uses Tcpip and Dnscache settings. |
- // If a policy is installed, DnsConfigService will need to be restarted. |
- // BUG=99509 |
- |
- dnscache_watcher_.Watch(kDnscachePath, callback); |
- policy_watcher_.Watch(kPolicyPath, callback); |
- |
- WorkNow(); |
- return true; |
- } |
- |
- void Cancel() { |
- DCHECK(loop()->BelongsToCurrentThread()); |
- SerialWorker::Cancel(); |
- policy_watcher_.Cancel(); |
- dnscache_watcher_.Cancel(); |
- tcpip6_watcher_.Cancel(); |
- tcpip_watcher_.Cancel(); |
- } |
- |
private: |
- virtual ~ConfigReader() { |
- DCHECK(IsCancelled()); |
- } |
- |
- void OnChange(bool succeeded) { |
- DCHECK(loop()->BelongsToCurrentThread()); |
- if (!IsCancelled()) |
- service_->InvalidateConfig(); |
- // We don't trust a config that we cannot watch in the future. |
- // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139 |
- if (succeeded) |
- WorkNow(); |
- else |
- LOG(ERROR) << "Failed to watch DNS config"; |
- } |
- |
bool ReadDevolutionSetting(const RegistryReader& reader, |
DnsSystemSettings::DevolutionSetting& setting) { |
return reader.ReadDword(L"UseDomainNameDevolution", &setting.enabled) && |
@@ -500,73 +389,18 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker { |
// Written in DoRead(), read in OnReadFinished(). No locking required. |
DnsConfig dns_config_; |
bool success_; |
- |
- RegistryWatcher tcpip_watcher_; |
- RegistryWatcher tcpip6_watcher_; |
- RegistryWatcher dnscache_watcher_; |
- RegistryWatcher policy_watcher_; |
}; |
-FilePath GetHostsPath() { |
- TCHAR buffer[MAX_PATH]; |
- UINT rc = GetSystemDirectory(buffer, MAX_PATH); |
- DCHECK(0 < rc && rc < MAX_PATH); |
- return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts")); |
-} |
- |
// An extension for DnsHostsReader which also watches the HOSTS file, |
// reads local name from GetComputerNameEx, local IP from GetAdaptersAddresses, |
// and observes changes to local IP address. |
-class DnsConfigServiceWin::HostsReader |
- : public DnsHostsReader, |
- public NetworkChangeNotifier::IPAddressObserver { |
+class DnsConfigServiceWin::HostsReader : public DnsHostsReader { |
public: |
explicit HostsReader(DnsConfigServiceWin* service) |
: DnsHostsReader(GetHostsPath()), service_(service) { |
} |
- bool Watch() { |
- DCHECK(loop()->BelongsToCurrentThread()); |
- DCHECK(!IsCancelled()); |
- |
- // In case the reader is restarted, remove it from the observer list. |
- NetworkChangeNotifier::RemoveIPAddressObserver(this); |
- |
- if (!hosts_watcher_.Watch(path(), |
- base::Bind(&HostsReader::OnHostsChanged, |
- base::Unretained(this)))) { |
- return false; |
- } |
- NetworkChangeNotifier::AddIPAddressObserver(this); |
- WorkNow(); |
- return true; |
- } |
- |
- // Cancels the underlying SerialWorker. Cannot be undone. |
- void Cancel() { |
- DnsHostsReader::Cancel(); |
- hosts_watcher_.Cancel(); |
- NetworkChangeNotifier::RemoveIPAddressObserver(this); |
- } |
- |
private: |
- virtual void OnIPAddressChanged() OVERRIDE { |
- DCHECK(loop()->BelongsToCurrentThread()); |
- service_->InvalidateHosts(); |
- if (!hosts_watcher_.IsWatching()) |
- return; |
- WorkNow(); |
- } |
- |
- void OnHostsChanged(bool succeeded) { |
- DCHECK(loop()->BelongsToCurrentThread()); |
- service_->InvalidateHosts(); |
- if (succeeded) |
- WorkNow(); |
- else |
- LOG(ERROR) << "Failed to watch DNS hosts"; |
- } |
- |
virtual void DoWork() OVERRIDE { |
DnsHostsReader::DoWork(); |
@@ -658,18 +492,18 @@ class DnsConfigServiceWin::HostsReader |
virtual void OnWorkFinished() OVERRIDE { |
DCHECK(loop()->BelongsToCurrentThread()); |
- if (!success_ || !hosts_watcher_.IsWatching()) |
- return; |
- service_->OnHostsRead(dns_hosts_); |
+ if (success_) { |
+ service_->OnHostsRead(dns_hosts_); |
+ } else { |
+ LOG(WARNING) << "Failed to read hosts."; |
+ } |
} |
DnsConfigServiceWin* service_; |
- FilePathWatcherWrapper hosts_watcher_; |
DISALLOW_COPY_AND_ASSIGN(HostsReader); |
}; |
- |
DnsConfigServiceWin::DnsConfigServiceWin() |
: config_reader_(new ConfigReader(this)), |
hosts_reader_(new HostsReader(this)) {} |
@@ -678,29 +512,42 @@ DnsConfigServiceWin::~DnsConfigServiceWin() { |
DCHECK(CalledOnValidThread()); |
config_reader_->Cancel(); |
hosts_reader_->Cancel(); |
+ NetworkChangeNotifier::RemoveIPAddressObserver(this); |
} |
void DnsConfigServiceWin::Watch(const CallbackType& callback) { |
- DCHECK(CalledOnValidThread()); |
- DCHECK(!callback.is_null()); |
- set_callback(callback); |
- |
- // This is done only once per lifetime so open the keys and file watcher |
- // handles on this thread. |
- // TODO(szym): Should/can this be avoided? http://crbug.com/114223 |
- base::ThreadRestrictions::ScopedAllowIO allow_io; |
+ DnsConfigService::Watch(callback); |
+ // Also need to observe changes to local non-loopback IP for DnsHosts. |
+ NetworkChangeNotifier::AddIPAddressObserver(this); |
+} |
- if (!config_reader_->Watch()) { |
- LOG(ERROR) << "Failed to start watching DNS config"; |
+void DnsConfigServiceWin::OnDNSChanged(unsigned detail) { |
+ if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_FAILED) { |
InvalidateConfig(); |
+ InvalidateHosts(); |
+ // We don't trust a config that we cannot watch in the future. |
+ config_reader_->Cancel(); |
+ hosts_reader_->Cancel(); |
+ return; |
} |
- |
- if (!hosts_reader_->Watch()) { |
- LOG(ERROR) << "Failed to start watching HOSTS"; |
+ if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_STARTED) |
+ detail = ~0; // Assume everything changed. |
+ if (detail & NetworkChangeNotifier::CHANGE_DNS_SETTINGS) { |
+ InvalidateConfig(); |
+ config_reader_->WorkNow(); |
+ } |
+ if (detail & NetworkChangeNotifier::CHANGE_DNS_HOSTS) { |
InvalidateHosts(); |
+ hosts_reader_->WorkNow(); |
} |
} |
+void DnsConfigServiceWin::OnIPAddressChanged() { |
+ // Need to update non-loopback IP of local host. |
+ if (NetworkChangeNotifier::IsWatchingDNS()) |
+ OnDNSChanged(NetworkChangeNotifier::CHANGE_DNS_HOSTS); |
+} |
+ |
} // namespace internal |
// static |