| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/base/network_change_notifier_win.h" | 5 #include "net/base/network_change_notifier_win.h" |
| 6 | 6 |
| 7 #include <iphlpapi.h> | 7 #include <iphlpapi.h> |
| 8 #include <winsock2.h> | 8 #include <winsock2.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/time.h" | 13 #include "base/time.h" |
| 14 #include "net/base/winsock_init.h" | 14 #include "net/base/winsock_init.h" |
| 15 | 15 |
| 16 #pragma comment(lib, "iphlpapi.lib") | 16 #pragma comment(lib, "iphlpapi.lib") |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 // Time between NotifyAddrChange retries, on failure. | 20 // Time between NotifyAddrChange retries, on failure. |
| 21 const int kWatchForAddressChangeRetryIntervalMs = 500; | 21 const int kWatchForAddressChangeRetryIntervalMs = 500; |
| 22 | 22 |
| 23 } // namespace | 23 } // namespace |
| 24 | 24 |
| 25 namespace net { | 25 namespace net { |
| 26 | 26 |
| 27 NetworkChangeNotifierWin::NetworkChangeNotifierWin() | 27 NetworkChangeNotifierWin::NetworkChangeNotifierWin() |
| 28 : is_watching_(false), | 28 : is_watching_(false), |
| 29 sequential_failures_(0), | 29 sequential_failures_(0), |
| 30 dns_policy_watcher_(this), |
| 31 dns_dnscache_watcher_(this), |
| 32 dns_tcpip_watcher_(this), |
| 30 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 33 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 31 memset(&addr_overlapped_, 0, sizeof addr_overlapped_); | 34 memset(&addr_overlapped_, 0, sizeof addr_overlapped_); |
| 32 addr_overlapped_.hEvent = WSACreateEvent(); | 35 addr_overlapped_.hEvent = WSACreateEvent(); |
| 36 |
| 37 WatchForDNSChanges(); |
| 33 } | 38 } |
| 34 | 39 |
| 35 NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { | 40 NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { |
| 36 if (is_watching_) { | 41 if (is_watching_) { |
| 37 CancelIPChangeNotify(&addr_overlapped_); | 42 CancelIPChangeNotify(&addr_overlapped_); |
| 38 addr_watcher_.StopWatching(); | 43 addr_watcher_.StopWatching(); |
| 39 } | 44 } |
| 40 WSACloseEvent(addr_overlapped_.hEvent); | 45 WSACloseEvent(addr_overlapped_.hEvent); |
| 41 } | 46 } |
| 42 | 47 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 } | 155 } |
| 151 } | 156 } |
| 152 | 157 |
| 153 result = WSALookupServiceEnd(ws_handle); | 158 result = WSALookupServiceEnd(ws_handle); |
| 154 LOG_IF(ERROR, result != 0) | 159 LOG_IF(ERROR, result != 0) |
| 155 << "WSALookupServiceEnd() failed with: " << result; | 160 << "WSALookupServiceEnd() failed with: " << result; |
| 156 | 161 |
| 157 return !found_connection; | 162 return !found_connection; |
| 158 } | 163 } |
| 159 | 164 |
| 165 |
| 166 bool NetworkChangeNotifierWin::IsCurrentlyWatchingDNS() const { |
| 167 return watching_dns_; |
| 168 } |
| 169 |
| 160 void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { | 170 void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { |
| 161 DCHECK(CalledOnValidThread()); | 171 DCHECK(CalledOnValidThread()); |
| 162 DCHECK(is_watching_); | 172 DCHECK(is_watching_); |
| 163 is_watching_ = false; | 173 is_watching_ = false; |
| 164 | 174 |
| 165 // Start watching for the next address change. | 175 // Start watching for the next address change. |
| 166 WatchForAddressChange(); | 176 WatchForAddressChange(); |
| 167 | 177 |
| 168 NotifyObservers(); | 178 NotifyObservers(); |
| 169 } | 179 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 DCHECK(CalledOnValidThread()); | 237 DCHECK(CalledOnValidThread()); |
| 228 HANDLE handle = NULL; | 238 HANDLE handle = NULL; |
| 229 DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_); | 239 DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_); |
| 230 if (ret != ERROR_IO_PENDING) | 240 if (ret != ERROR_IO_PENDING) |
| 231 return false; | 241 return false; |
| 232 | 242 |
| 233 addr_watcher_.StartWatching(addr_overlapped_.hEvent, this); | 243 addr_watcher_.StartWatching(addr_overlapped_.hEvent, this); |
| 234 return true; | 244 return true; |
| 235 } | 245 } |
| 236 | 246 |
| 247 void NetworkChangeNotifierWin::WatchForDNSChanges() { |
| 248 TCHAR buffer[MAX_PATH]; |
| 249 UINT rc = GetSystemDirectory(buffer, MAX_PATH); |
| 250 DCHECK(0 < rc && rc < MAX_PATH); |
| 251 FilePath hosts_path = FilePath(buffer). |
| 252 Append(FILE_PATH_LITERAL("drivers\\etc\\hosts")); |
| 253 |
| 254 // DNS suffix search list and devolution can be configured via group |
| 255 // policy which sets this registry key. If the key is missing, the policy |
| 256 // does not apply, and the DNS client uses Tcpip and Dnscache settings. |
| 257 // If a policy is installed, DnsConfigService will need to be restarted. |
| 258 // http://crbug.com/99509 |
| 259 dns_policy_watcher_.Watch( |
| 260 L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient"); |
| 261 dns_dnscache_watcher_.Watch( |
| 262 L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters"); |
| 263 if (!dns_tcpip_watcher_.Watch( |
| 264 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters") && |
| 265 hosts_watcher_.Watch( |
| 266 hosts_path, |
| 267 base::Bind(&NetworkChangeNotifierWin::OnDNSFileChanged, |
| 268 base::Unretained(this)))) { |
| 269 watching_dns_ = true; |
| 270 } else { |
| 271 watching_dns_ = false; |
| 272 LOG(ERROR) << "Failed to start DNS watch"; |
| 273 } |
| 274 } |
| 275 |
| 237 void NetworkChangeNotifierWin::NotifyParentOfOnlineStateChange() { | 276 void NetworkChangeNotifierWin::NotifyParentOfOnlineStateChange() { |
| 238 NotifyObserversOfOnlineStateChange(); | 277 NotifyObserversOfOnlineStateChange(); |
| 239 } | 278 } |
| 240 | 279 |
| 280 void NetworkChangeNotifierWin::OnRegistryChanged(bool watch_successful) { |
| 281 if (!watch_successful) { |
| 282 LOG(ERROR) << "DNS settings watch failed."; |
| 283 watching_dns_ = false; |
| 284 } |
| 285 // TODO(szym): depending on the key, we should indicate CHANGE_DNS_LOCALHOST. |
| 286 NotifyObserversOfDNSChange(CHANGE_DNS_SETTINGS); |
| 287 } |
| 288 |
| 289 void NetworkChangeNotifierWin::OnDNSFileChanged(bool watch_successful) { |
| 290 if (!watch_successful) { |
| 291 LOG(ERROR) << "DNS hosts watch failed."; |
| 292 watching_dns_ = false; |
| 293 } |
| 294 NotifyObserversOfDNSChange(CHANGE_DNS_HOSTS); |
| 295 } |
| 296 |
| 297 NetworkChangeNotifierWin::RegistryWatcher::RegistryWatcher( |
| 298 NetworkChangeNotifierWin* notifier) : notifier_(notifier) { |
| 299 } |
| 300 |
| 301 NetworkChangeNotifierWin::RegistryWatcher::~RegistryWatcher() { |
| 302 Cancel(); |
| 303 } |
| 304 |
| 305 bool NetworkChangeNotifierWin::RegistryWatcher::Watch(const wchar_t* key) { |
| 306 if (key_.Valid()) |
| 307 Cancel(); |
| 308 if (key_.Open(HKEY_LOCAL_MACHINE, key, |
| 309 KEY_NOTIFY | KEY_QUERY_VALUE) != ERROR_SUCCESS) |
| 310 return false; |
| 311 if (key_.StartWatching() != ERROR_SUCCESS) |
| 312 return false; |
| 313 if (!watcher_.StartWatching(key_.watch_event(), this)) |
| 314 return false; |
| 315 return true; |
| 316 } |
| 317 |
| 318 void NetworkChangeNotifierWin::RegistryWatcher::Cancel() { |
| 319 key_.StopWatching(); |
| 320 watcher_.StopWatching(); |
| 321 key_.Close(); |
| 322 } |
| 323 |
| 324 void NetworkChangeNotifierWin::RegistryWatcher::OnObjectSignaled( |
| 325 HANDLE object) { |
| 326 bool success = key_.StartWatching() && |
| 327 watcher_.StartWatching(key_.watch_event(), this); |
| 328 if (!success) |
| 329 Cancel(); |
| 330 notifier_->OnRegistryChanged(success); |
| 331 } |
| 332 |
| 241 } // namespace net | 333 } // namespace net |
| OLD | NEW |