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

Unified Diff: net/dns/dns_config_service_win.cc

Issue 10873018: [net] Move DnsConfigService to NetworkChangeNotifier. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add comment Created 8 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/dns/dns_config_service_win.h ('k') | net/dns/dns_config_watcher.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 54ef1c0d397fe2316df94e987235c34b89116698..8fa72090d2d91671d55616a775c9d15a394cc880 100644
--- a/net/dns/dns_config_service_win.cc
+++ b/net/dns/dns_config_service_win.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/files/file_path_watcher.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -21,6 +22,7 @@
#include "base/threading/thread_restrictions.h"
#include "base/time.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"
@@ -272,6 +274,48 @@ HostsParseWinResult AddLocalhostEntries(DnsHosts* hosts) {
return HOSTS_PARSE_WIN_OK;
}
+// 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());
+ DCHECK(callback_.is_null());
+ callback_ = callback;
+ 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;
+ return true;
+ }
+
+ virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
+ DCHECK(CalledOnValidThread());
+ bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
+ watcher_.StartWatching(key_.watch_event(), this);
+ if (!succeeded && key_.Valid()) {
+ watcher_.StopWatching();
+ key_.StopWatching();
+ key_.Close();
+ }
+ if (!callback_.is_null())
+ callback_.Run(succeeded);
+ }
+
+ private:
+ CallbackType callback_;
+ base::win::RegKey key_;
+ base::win::ObjectWatcher watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(RegistryWatcher);
+};
+
} // namespace
FilePath GetHostsPath() {
@@ -450,6 +494,77 @@ ConfigParseWinResult ConvertSettingsToDnsConfig(
return CONFIG_PARSE_WIN_OK;
}
+// Watches registry and HOSTS file for changes. Must live on a thread which
+// allows IO.
+class DnsConfigServiceWin::Watcher
+ : public NetworkChangeNotifier::IPAddressObserver {
+ public:
+ explicit Watcher(DnsConfigServiceWin* service) : service_(service) {}
+ ~Watcher() {
+ NetworkChangeNotifier::RemoveIPAddressObserver(this);
+ }
+
+ bool Watch() {
+ RegistryWatcher::CallbackType callback =
+ base::Bind(&DnsConfigServiceWin::OnConfigChanged,
+ base::Unretained(service_));
+
+ bool success = true;
+
+ // The Tcpip key must be present.
+ if (!tcpip_watcher_.Watch(kTcpipPath, callback)) {
+ LOG(ERROR) << "DNS registry watch failed to start.";
+ success = 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);
+
+ if (!hosts_watcher_.Watch(GetHostsPath(),
+ base::Bind(&Watcher::OnHostsChanged,
+ base::Unretained(this)))) {
+ LOG(ERROR) << "DNS hosts watch failed to start.";
+ success = false;
+ } else {
+ // Also need to observe changes to local non-loopback IP for DnsHosts.
+ NetworkChangeNotifier::AddIPAddressObserver(this);
+ }
+ return success;
+ }
+
+ private:
+ void OnHostsChanged(const FilePath& path, bool error) {
+ if (error)
+ NetworkChangeNotifier::RemoveIPAddressObserver(this);
+ service_->OnHostsChanged(!error);
+ }
+
+ // NetworkChangeNotifier::IPAddressObserver:
+ virtual void OnIPAddressChanged() OVERRIDE {
+ // Need to update non-loopback IP of local host.
+ service_->OnHostsChanged(true);
+ }
+
+ DnsConfigServiceWin* service_;
+
+ RegistryWatcher tcpip_watcher_;
+ RegistryWatcher tcpip6_watcher_;
+ RegistryWatcher dnscache_watcher_;
+ RegistryWatcher policy_watcher_;
+ base::files::FilePathWatcher hosts_watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(Watcher);
+};
+
// Reads config from registry and IpHelper. All work performed on WorkerPool.
class DnsConfigServiceWin::ConfigReader : public SerialWorker {
public:
@@ -541,46 +656,43 @@ class DnsConfigServiceWin::HostsReader : public SerialWorker {
};
DnsConfigServiceWin::DnsConfigServiceWin()
- : config_reader_(new ConfigReader(this)),
+ : watcher_(new Watcher(this)),
+ config_reader_(new ConfigReader(this)),
hosts_reader_(new HostsReader(this)) {}
DnsConfigServiceWin::~DnsConfigServiceWin() {
config_reader_->Cancel();
hosts_reader_->Cancel();
- NetworkChangeNotifier::RemoveIPAddressObserver(this);
}
-void DnsConfigServiceWin::Watch(const CallbackType& callback) {
- DnsConfigService::Watch(callback);
- // Also need to observe changes to local non-loopback IP for DnsHosts.
- NetworkChangeNotifier::AddIPAddressObserver(this);
+void DnsConfigServiceWin::ReadNow() {
+ config_reader_->WorkNow();
+ hosts_reader_->WorkNow();
}
-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 (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_STARTED)
- detail = ~0; // Assume everything changed.
- if (detail & NetworkChangeNotifier::CHANGE_DNS_SETTINGS) {
- InvalidateConfig();
+bool DnsConfigServiceWin::StartWatching() {
+ // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139
+ return watcher_->Watch();
+}
+
+void DnsConfigServiceWin::OnConfigChanged(bool succeeded) {
+ InvalidateConfig();
+ if (succeeded) {
config_reader_->WorkNow();
- }
- if (detail & NetworkChangeNotifier::CHANGE_DNS_HOSTS) {
- InvalidateHosts();
- hosts_reader_->WorkNow();
+ } else {
+ LOG(ERROR) << "DNS config watch failed.";
+ set_watch_failed(true);
}
}
-void DnsConfigServiceWin::OnIPAddressChanged() {
- // Need to update non-loopback IP of local host.
- if (NetworkChangeNotifier::IsWatchingDNS())
- OnDNSChanged(NetworkChangeNotifier::CHANGE_DNS_HOSTS);
+void DnsConfigServiceWin::OnHostsChanged(bool succeeded) {
+ InvalidateHosts();
+ if (succeeded) {
+ hosts_reader_->WorkNow();
+ } else {
+ LOG(ERROR) << "DNS hosts watch failed.";
+ set_watch_failed(true);
+ }
}
} // namespace internal
« no previous file with comments | « net/dns/dns_config_service_win.h ('k') | net/dns/dns_config_watcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698