| Index: net/base/network_change_notifier_win.cc
|
| diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc
|
| index e1307447bc326ce2d2a47152175ab400f6cd7ee2..5c04820768366b3b737e405ab731d9000ac61ccf 100644
|
| --- a/net/base/network_change_notifier_win.cc
|
| +++ b/net/base/network_change_notifier_win.cc
|
| @@ -27,9 +27,14 @@ namespace net {
|
| NetworkChangeNotifierWin::NetworkChangeNotifierWin()
|
| : is_watching_(false),
|
| sequential_failures_(0),
|
| + dns_policy_watcher_(this),
|
| + dns_dnscache_watcher_(this),
|
| + dns_tcpip_watcher_(this),
|
| ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
| memset(&addr_overlapped_, 0, sizeof addr_overlapped_);
|
| addr_overlapped_.hEvent = WSACreateEvent();
|
| +
|
| + WatchForDNSChanges();
|
| }
|
|
|
| NetworkChangeNotifierWin::~NetworkChangeNotifierWin() {
|
| @@ -157,6 +162,11 @@ bool NetworkChangeNotifierWin::IsCurrentlyOffline() const {
|
| return !found_connection;
|
| }
|
|
|
| +
|
| +bool NetworkChangeNotifierWin::IsCurrentlyWatchingDNS() const {
|
| + return watching_dns_;
|
| +}
|
| +
|
| void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) {
|
| DCHECK(CalledOnValidThread());
|
| DCHECK(is_watching_);
|
| @@ -234,8 +244,90 @@ bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() {
|
| return true;
|
| }
|
|
|
| +void NetworkChangeNotifierWin::WatchForDNSChanges() {
|
| + 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"));
|
| +
|
| + // 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.
|
| + // http://crbug.com/99509
|
| + dns_policy_watcher_.Watch(
|
| + L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient");
|
| + dns_dnscache_watcher_.Watch(
|
| + L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters");
|
| + if (!dns_tcpip_watcher_.Watch(
|
| + L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters") &&
|
| + hosts_watcher_.Watch(
|
| + hosts_path,
|
| + base::Bind(&NetworkChangeNotifierWin::OnDNSFileChanged,
|
| + base::Unretained(this)))) {
|
| + watching_dns_ = true;
|
| + } else {
|
| + watching_dns_ = false;
|
| + LOG(ERROR) << "Failed to start DNS watch";
|
| + }
|
| +}
|
| +
|
| void NetworkChangeNotifierWin::NotifyParentOfOnlineStateChange() {
|
| NotifyObserversOfOnlineStateChange();
|
| }
|
|
|
| +void NetworkChangeNotifierWin::OnRegistryChanged(bool watch_successful) {
|
| + if (!watch_successful) {
|
| + LOG(ERROR) << "DNS settings watch failed.";
|
| + watching_dns_ = false;
|
| + }
|
| + // TODO(szym): depending on the key, we should indicate CHANGE_DNS_LOCALHOST.
|
| + NotifyObserversOfDNSChange(CHANGE_DNS_SETTINGS);
|
| +}
|
| +
|
| +void NetworkChangeNotifierWin::OnDNSFileChanged(bool watch_successful) {
|
| + if (!watch_successful) {
|
| + LOG(ERROR) << "DNS hosts watch failed.";
|
| + watching_dns_ = false;
|
| + }
|
| + NotifyObserversOfDNSChange(CHANGE_DNS_HOSTS);
|
| +}
|
| +
|
| +NetworkChangeNotifierWin::RegistryWatcher::RegistryWatcher(
|
| + NetworkChangeNotifierWin* notifier) : notifier_(notifier) {
|
| +}
|
| +
|
| +NetworkChangeNotifierWin::RegistryWatcher::~RegistryWatcher() {
|
| + Cancel();
|
| +}
|
| +
|
| +bool NetworkChangeNotifierWin::RegistryWatcher::Watch(const wchar_t* key) {
|
| + if (key_.Valid())
|
| + Cancel();
|
| + 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;
|
| + return true;
|
| +}
|
| +
|
| +void NetworkChangeNotifierWin::RegistryWatcher::Cancel() {
|
| + key_.StopWatching();
|
| + watcher_.StopWatching();
|
| + key_.Close();
|
| +}
|
| +
|
| +void NetworkChangeNotifierWin::RegistryWatcher::OnObjectSignaled(
|
| + HANDLE object) {
|
| + bool success = key_.StartWatching() &&
|
| + watcher_.StartWatching(key_.watch_event(), this);
|
| + if (!success)
|
| + Cancel();
|
| + notifier_->OnRegistryChanged(success);
|
| +}
|
| +
|
| } // namespace net
|
|
|