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

Unified Diff: net/dns/dns_config_service_win.cc

Issue 9721002: [net/dns] Removes locking from DnsConfigServiceWin and adds local computer name. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 9 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_hosts.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 047b92dd03f8d3ecc5a5e77583655ffabeed7881..b85d192961cd55efb55764d16d75d34b8a279662 100644
--- a/net/dns/dns_config_service_win.cc
+++ b/net/dns/dns_config_service_win.cc
@@ -16,6 +16,7 @@
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/synchronization/lock.h"
+#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"
@@ -35,43 +36,27 @@ namespace internal {
namespace {
-// Watches a single registry key for changes. Thread-safe.
-class RegistryWatcher : public base::win::ObjectWatcher::Delegate {
+// 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";
+
+// Convenience for reading values using RegKey.
+class RegistryReader : public base::NonThreadSafe {
public:
- typedef base::Callback<void(bool succeeded)> CallbackType;
- RegistryWatcher() {}
-
- bool Watch(const wchar_t* key, const CallbackType& callback) {
- base::AutoLock lock(lock_);
- DCHECK(!callback.is_null());
- CancelLocked();
- if (key_.Open(HKEY_LOCAL_MACHINE, key,
- KEY_NOTIFY | KEY_QUERY_VALUE) != ERROR_SUCCESS)
- return false;
- if (key_.StartWatching() != ERROR_SUCCESS)
- return false;
- if (!watcher_.StartWatching(key_.watch_event(), this))
- return false;
- callback_ = callback;
- return true;
- }
-
- void Cancel() {
- base::AutoLock lock(lock_);
- CancelLocked();
- }
-
- virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
- base::AutoLock lock(lock_);
- bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
- watcher_.StartWatching(key_.watch_event(), this);
- if (!callback_.is_null())
- callback_.Run(succeeded);
+ explicit RegistryReader(const wchar_t* key) {
+ // Ignoring the result. |key_.Valid()| will catch failures.
+ key_.Open(HKEY_LOCAL_MACHINE, key, KEY_QUERY_VALUE);
}
bool ReadString(const wchar_t* name,
DnsSystemSettings::RegString* out) const {
- base::AutoLock lock(lock_);
+ DCHECK(CalledOnValidThread());
out->set = false;
if (!key_.Valid()) {
// Assume that if the |key_| is invalid then the key is missing.
@@ -87,7 +72,7 @@ class RegistryWatcher : public base::win::ObjectWatcher::Delegate {
bool ReadDword(const wchar_t* name,
DnsSystemSettings::RegDword* out) const {
- base::AutoLock lock(lock_);
+ DCHECK(CalledOnValidThread());
out->set = false;
if (!key_.Valid()) {
// Assume that if the |key_| is invalid then the key is missing.
@@ -102,8 +87,35 @@ class RegistryWatcher : public base::win::ObjectWatcher::Delegate {
}
private:
- void CancelLocked() {
- lock_.AssertAcquired();
+ base::win::RegKey key_;
+
+ 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;
+ }
+
+ void Cancel() {
+ DCHECK(CalledOnValidThread());
callback_.Reset();
if (key_.Valid()) {
watcher_.StopWatching();
@@ -111,7 +123,15 @@ class RegistryWatcher : public base::win::ObjectWatcher::Delegate {
}
}
- mutable base::Lock lock_;
+ virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
+ DCHECK(CalledOnValidThread());
+ bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
+ watcher_.StartWatching(key_.watch_event(), this);
mmenke 2012/03/19 15:18:01 nit: Think this should be indented one more space
+ if (!callback_.is_null())
+ callback_.Run(succeeded);
+ }
+
+ private:
CallbackType callback_;
base::win::RegKey key_;
base::win::ObjectWatcher watcher_;
@@ -323,15 +343,11 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker {
base::Bind(&ConfigReader::OnChange, base::Unretained(this));
// The Tcpip key must be present.
- if (!tcpip_watcher_.Watch(
- L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
- callback))
+ if (!tcpip_watcher_.Watch(kTcpipPath, callback))
return false;
// Watch for IPv6 nameservers.
- tcpip6_watcher_.Watch(
- L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters",
- callback);
+ 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
@@ -339,13 +355,8 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker {
// If a policy is installed, DnsConfigService will need to be restarted.
// BUG=99509
- dnscache_watcher_.Watch(
- L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters",
- callback);
-
- policy_watcher_.Watch(
- L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient",
- callback);
+ dnscache_watcher_.Watch(kDnscachePath, callback);
+ policy_watcher_.Watch(kPolicyPath, callback);
WorkNow();
return true;
@@ -398,10 +409,10 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker {
return (rv == NO_ERROR);
}
- bool ReadDevolutionSetting(const RegistryWatcher& watcher,
+ bool ReadDevolutionSetting(const RegistryReader& reader,
DnsSystemSettings::DevolutionSetting& setting) {
- return watcher.ReadDword(L"UseDomainNameDevolution", &setting.enabled) &&
- watcher.ReadDword(L"DomainNameDevolutionLevel", &setting.level);
+ return reader.ReadDword(L"UseDomainNameDevolution", &setting.enabled) &&
+ reader.ReadDword(L"DomainNameDevolutionLevel", &setting.level);
}
virtual void DoWork() OVERRIDE {
@@ -413,28 +424,33 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker {
if (!ReadIpHelper(&settings))
return; // no point reading the rest
- if (!policy_watcher_.ReadString(L"SearchList",
- &settings.policy_search_list))
+ RegistryReader tcpip_reader(kTcpipPath);
+ RegistryReader tcpip6_reader(kTcpip6Path);
+ RegistryReader dnscache_reader(kDnscachePath);
+ RegistryReader policy_reader(kPolicyPath);
+
+ if (!policy_reader.ReadString(L"SearchList",
+ &settings.policy_search_list))
return;
- if (!tcpip_watcher_.ReadString(L"SearchList", &settings.tcpip_search_list))
+ if (!tcpip_reader.ReadString(L"SearchList", &settings.tcpip_search_list))
return;
- if (!tcpip_watcher_.ReadString(L"Domain", &settings.tcpip_domain))
+ if (!tcpip_reader.ReadString(L"Domain", &settings.tcpip_domain))
return;
- if (!ReadDevolutionSetting(policy_watcher_, settings.policy_devolution))
+ if (!ReadDevolutionSetting(policy_reader, settings.policy_devolution))
return;
- if (!ReadDevolutionSetting(dnscache_watcher_,
+ if (!ReadDevolutionSetting(dnscache_reader,
settings.dnscache_devolution))
return;
- if (!ReadDevolutionSetting(tcpip_watcher_, settings.tcpip_devolution))
+ if (!ReadDevolutionSetting(tcpip_reader, settings.tcpip_devolution))
return;
- if (!policy_watcher_.ReadDword(L"AppendToMultiLabelName",
- &settings.append_to_multi_label_name))
+ if (!policy_reader.ReadDword(L"AppendToMultiLabelName",
+ &settings.append_to_multi_label_name))
return;
success_ = ConvertSettingsToDnsConfig(settings, &dns_config_);
@@ -461,15 +477,120 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker {
RegistryWatcher policy_watcher_;
};
+
+// An extension for DnsHostsReader which also reads local name from
+// GetComputerNameEx and watches registry for changes to local name.
+class DnsConfigServiceWin::HostsReader : public base::NonThreadSafe {
+ public:
+ explicit HostsReader(DnsConfigServiceWin* service) : service_(service) {
+ TCHAR buffer[MAX_PATH];
+ UINT rc = GetSystemDirectory(buffer, MAX_PATH);
+ DCHECK(0 < rc && rc < MAX_PATH);
+ FilePath hosts_path = FilePath(buffer).
+ Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
+ hosts_reader_ = new DnsHostsReader(
+ hosts_path,
+ base::Bind(&HostsReader::OnHostsRead, base::Unretained(this)));
+ }
+
+ bool Watch() {
+ DCHECK(CalledOnValidThread());
+ if (!hosts_watcher_.Watch(hosts_reader_->path(),
+ base::Bind(&HostsReader::OnHostsChanged,
+ base::Unretained(this)))) {
+ return false;
+ }
+ if (!registry_watcher_.Watch(kTcpipPath,
+ base::Bind(&HostsReader::OnNameChanged,
+ base::Unretained(this)))) {
mmenke 2012/03/19 15:18:01 nit: Indent this to the open paren, if it fits, s
+ return false;
+ }
+
+ hosts_reader_->WorkNow();
+ return true;
+ }
+
+ ~HostsReader() {
+ hosts_reader_->Cancel();
+ }
+
+ private:
+ void OnHostsChanged(bool succeeded) {
+ DCHECK(CalledOnValidThread());
+ service_->InvalidateHosts();
+ if (succeeded)
+ hosts_reader_->WorkNow();
+ else
+ LOG(ERROR) << "Failed to watch DNS hosts";
+ }
+
+ void OnHostsRead(const DnsHosts& hosts) {
+ DCHECK(CalledOnValidThread());
+ hosts_ = hosts;
+ UpdateService();
+ }
+
+ void OnNameChanged(bool succeeded) {
+ DCHECK(CalledOnValidThread());
+ if (!succeeded) {
+ LOG(ERROR) << "Failed to watch local computer name";
+ service_->InvalidateHosts();
+ return;
+ }
+ WCHAR buffer[MAX_PATH];
+ DWORD size = MAX_PATH;
+ std::string localname;
+ if (!GetComputerNameExW(ComputerNameDnsHostname, buffer, &size) ||
+ !ParseDomainASCII(buffer, &localname)) {
+ service_->InvalidateHosts();
+ LOG(ERROR) << "Failed to read local computer name";
+ return;
+ }
+
+ if (localname != localname_) {
+ localname_ = localname;
+ UpdateService();
mmenke 2012/03/19 15:18:01 What if the last call to OnHostsChanged failed? S
+ }
+ }
+
+ void UpdateService() {
+ DCHECK(CalledOnValidThread());
+ DnsHosts complete_hosts = hosts_;
+
+ const unsigned char kIPv4Localhost[] = { 127, 0, 0, 1 };
+ const unsigned char kIPv6Localhost[] = { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1 };
+
+ complete_hosts[DnsHostsKey(localname_, ADDRESS_FAMILY_IPV4)] =
+ IPAddressNumber(kIPv4Localhost,
+ kIPv4Localhost + arraysize(kIPv4Localhost));
+ complete_hosts[DnsHostsKey(localname_, ADDRESS_FAMILY_IPV6)] =
+ IPAddressNumber(kIPv6Localhost,
+ kIPv6Localhost + arraysize(kIPv6Localhost));
+ service_->OnHostsRead(complete_hosts);
+ }
+
+ DnsConfigServiceWin* service_;
+ FilePathWatcherWrapper hosts_watcher_;
+ RegistryWatcher registry_watcher_;
+ scoped_refptr<DnsHostsReader> hosts_reader_;
+
+ // Contents of the HOSTS file.
+ DnsHosts hosts_;
+ // Local computer name in ASCII.
+ std::string localname_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostsReader);
+};
+
+
DnsConfigServiceWin::DnsConfigServiceWin()
: config_reader_(new ConfigReader(this)),
- hosts_watcher_(new FilePathWatcherWrapper()) {}
+ hosts_reader_(new HostsReader(this)) {}
DnsConfigServiceWin::~DnsConfigServiceWin() {
DCHECK(CalledOnValidThread());
config_reader_->Cancel();
- if (hosts_reader_)
- hosts_reader_->Cancel();
}
void DnsConfigServiceWin::Watch(const CallbackType& callback) {
@@ -487,30 +608,12 @@ void DnsConfigServiceWin::Watch(const CallbackType& callback) {
InvalidateConfig();
}
- TCHAR buffer[MAX_PATH];
- UINT rc = GetSystemDirectory(buffer, MAX_PATH);
- DCHECK(0 < rc && rc < MAX_PATH);
- FilePath hosts_path = FilePath(buffer).
- Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
- hosts_reader_ = new DnsHostsReader(
- hosts_path,
- base::Bind(&DnsConfigServiceWin::OnHostsRead, base::Unretained(this)));
- if (hosts_watcher_->Watch(hosts_path,
- base::Bind(&DnsConfigServiceWin::OnHostsChanged,
- base::Unretained(this)))) {
- OnHostsChanged(true);
- } else {
- OnHostsChanged(false);
+ if (!hosts_reader_->Watch()) {
+ LOG(ERROR) << "Failed to start watching HOSTS";
+ InvalidateHosts();
}
}
-void DnsConfigServiceWin::OnHostsChanged(bool succeeded) {
- InvalidateHosts();
- if (succeeded)
- hosts_reader_->WorkNow();
- else
- LOG(ERROR) << "Failed to watch DNS hosts";
-}
mmenke 2012/03/19 15:18:01 nit: Remove extra blank line.
} // namespace internal
« no previous file with comments | « net/dns/dns_config_service_win.h ('k') | net/dns/dns_hosts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698