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

Side by Side 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, 3 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 unified diff | Download patch | Annotate | Revision Log
« 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/dns/dns_config_service_win.h" 5 #include "net/dns/dns_config_service_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/files/file_path_watcher.h"
13 #include "base/file_path.h" 14 #include "base/file_path.h"
14 #include "base/logging.h" 15 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
17 #include "base/string_split.h" 18 #include "base/string_split.h"
18 #include "base/string_util.h" 19 #include "base/string_util.h"
19 #include "base/synchronization/lock.h" 20 #include "base/synchronization/lock.h"
20 #include "base/threading/non_thread_safe.h" 21 #include "base/threading/non_thread_safe.h"
21 #include "base/threading/thread_restrictions.h" 22 #include "base/threading/thread_restrictions.h"
22 #include "base/time.h" 23 #include "base/time.h"
23 #include "base/utf_string_conversions.h" 24 #include "base/utf_string_conversions.h"
25 #include "base/win/object_watcher.h"
24 #include "base/win/registry.h" 26 #include "base/win/registry.h"
25 #include "base/win/windows_version.h" 27 #include "base/win/windows_version.h"
26 #include "googleurl/src/url_canon.h" 28 #include "googleurl/src/url_canon.h"
27 #include "net/base/net_util.h" 29 #include "net/base/net_util.h"
28 #include "net/base/network_change_notifier.h" 30 #include "net/base/network_change_notifier.h"
29 #include "net/dns/dns_hosts.h" 31 #include "net/dns/dns_hosts.h"
30 #include "net/dns/dns_protocol.h" 32 #include "net/dns/dns_protocol.h"
31 #include "net/dns/serial_worker.h" 33 #include "net/dns/serial_worker.h"
32 34
33 #pragma comment(lib, "iphlpapi.lib") 35 #pragma comment(lib, "iphlpapi.lib")
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 (*hosts)[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] = ipe.address(); 267 (*hosts)[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] = ipe.address();
266 } else if (!have_ipv6 && (ipe.GetFamily() == AF_INET6)) { 268 } else if (!have_ipv6 && (ipe.GetFamily() == AF_INET6)) {
267 have_ipv6 = true; 269 have_ipv6 = true;
268 (*hosts)[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] = ipe.address(); 270 (*hosts)[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] = ipe.address();
269 } 271 }
270 } 272 }
271 } 273 }
272 return HOSTS_PARSE_WIN_OK; 274 return HOSTS_PARSE_WIN_OK;
273 } 275 }
274 276
277 // Watches a single registry key for changes.
278 class RegistryWatcher : public base::win::ObjectWatcher::Delegate,
279 public base::NonThreadSafe {
280 public:
281 typedef base::Callback<void(bool succeeded)> CallbackType;
282 RegistryWatcher() {}
283
284 bool Watch(const wchar_t* key, const CallbackType& callback) {
285 DCHECK(CalledOnValidThread());
286 DCHECK(!callback.is_null());
287 DCHECK(callback_.is_null());
288 callback_ = callback;
289 if (key_.Open(HKEY_LOCAL_MACHINE, key, KEY_NOTIFY) != ERROR_SUCCESS)
290 return false;
291 if (key_.StartWatching() != ERROR_SUCCESS)
292 return false;
293 if (!watcher_.StartWatching(key_.watch_event(), this))
294 return false;
295 return true;
296 }
297
298 virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
299 DCHECK(CalledOnValidThread());
300 bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
301 watcher_.StartWatching(key_.watch_event(), this);
302 if (!succeeded && key_.Valid()) {
303 watcher_.StopWatching();
304 key_.StopWatching();
305 key_.Close();
306 }
307 if (!callback_.is_null())
308 callback_.Run(succeeded);
309 }
310
311 private:
312 CallbackType callback_;
313 base::win::RegKey key_;
314 base::win::ObjectWatcher watcher_;
315
316 DISALLOW_COPY_AND_ASSIGN(RegistryWatcher);
317 };
318
275 } // namespace 319 } // namespace
276 320
277 FilePath GetHostsPath() { 321 FilePath GetHostsPath() {
278 TCHAR buffer[MAX_PATH]; 322 TCHAR buffer[MAX_PATH];
279 UINT rc = GetSystemDirectory(buffer, MAX_PATH); 323 UINT rc = GetSystemDirectory(buffer, MAX_PATH);
280 DCHECK(0 < rc && rc < MAX_PATH); 324 DCHECK(0 < rc && rc < MAX_PATH);
281 return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts")); 325 return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
282 } 326 }
283 327
284 bool ParseSearchList(const string16& value, std::vector<std::string>* output) { 328 bool ParseSearchList(const string16& value, std::vector<std::string>* output) {
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 unsigned num_dots = std::count(primary_suffix.begin(), 487 unsigned num_dots = std::count(primary_suffix.begin(),
444 primary_suffix.end(), '.'); 488 primary_suffix.end(), '.');
445 489
446 for (size_t offset = 0; num_dots >= devolution.level.value; --num_dots) { 490 for (size_t offset = 0; num_dots >= devolution.level.value; --num_dots) {
447 offset = primary_suffix.find('.', offset + 1); 491 offset = primary_suffix.find('.', offset + 1);
448 config->search.push_back(primary_suffix.substr(offset + 1)); 492 config->search.push_back(primary_suffix.substr(offset + 1));
449 } 493 }
450 return CONFIG_PARSE_WIN_OK; 494 return CONFIG_PARSE_WIN_OK;
451 } 495 }
452 496
497 // Watches registry and HOSTS file for changes. Must live on a thread which
498 // allows IO.
499 class DnsConfigServiceWin::Watcher
500 : public NetworkChangeNotifier::IPAddressObserver {
501 public:
502 explicit Watcher(DnsConfigServiceWin* service) : service_(service) {}
503 ~Watcher() {
504 NetworkChangeNotifier::RemoveIPAddressObserver(this);
505 }
506
507 bool Watch() {
508 RegistryWatcher::CallbackType callback =
509 base::Bind(&DnsConfigServiceWin::OnConfigChanged,
510 base::Unretained(service_));
511
512 bool success = true;
513
514 // The Tcpip key must be present.
515 if (!tcpip_watcher_.Watch(kTcpipPath, callback)) {
516 LOG(ERROR) << "DNS registry watch failed to start.";
517 success = false;
518 }
519
520 // Watch for IPv6 nameservers.
521 tcpip6_watcher_.Watch(kTcpip6Path, callback);
522
523 // DNS suffix search list and devolution can be configured via group
524 // policy which sets this registry key. If the key is missing, the policy
525 // does not apply, and the DNS client uses Tcpip and Dnscache settings.
526 // If a policy is installed, DnsConfigService will need to be restarted.
527 // BUG=99509
528
529 dnscache_watcher_.Watch(kDnscachePath, callback);
530 policy_watcher_.Watch(kPolicyPath, callback);
531
532 if (!hosts_watcher_.Watch(GetHostsPath(),
533 base::Bind(&Watcher::OnHostsChanged,
534 base::Unretained(this)))) {
535 LOG(ERROR) << "DNS hosts watch failed to start.";
536 success = false;
537 } else {
538 // Also need to observe changes to local non-loopback IP for DnsHosts.
539 NetworkChangeNotifier::AddIPAddressObserver(this);
540 }
541 return success;
542 }
543
544 private:
545 void OnHostsChanged(const FilePath& path, bool error) {
546 if (error)
547 NetworkChangeNotifier::RemoveIPAddressObserver(this);
548 service_->OnHostsChanged(!error);
549 }
550
551 // NetworkChangeNotifier::IPAddressObserver:
552 virtual void OnIPAddressChanged() OVERRIDE {
553 // Need to update non-loopback IP of local host.
554 service_->OnHostsChanged(true);
555 }
556
557 DnsConfigServiceWin* service_;
558
559 RegistryWatcher tcpip_watcher_;
560 RegistryWatcher tcpip6_watcher_;
561 RegistryWatcher dnscache_watcher_;
562 RegistryWatcher policy_watcher_;
563 base::files::FilePathWatcher hosts_watcher_;
564
565 DISALLOW_COPY_AND_ASSIGN(Watcher);
566 };
567
453 // Reads config from registry and IpHelper. All work performed on WorkerPool. 568 // Reads config from registry and IpHelper. All work performed on WorkerPool.
454 class DnsConfigServiceWin::ConfigReader : public SerialWorker { 569 class DnsConfigServiceWin::ConfigReader : public SerialWorker {
455 public: 570 public:
456 explicit ConfigReader(DnsConfigServiceWin* service) 571 explicit ConfigReader(DnsConfigServiceWin* service)
457 : service_(service), 572 : service_(service),
458 success_(false) {} 573 success_(false) {}
459 574
460 private: 575 private:
461 virtual ~ConfigReader() {} 576 virtual ~ConfigReader() {}
462 577
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 const FilePath path_; 649 const FilePath path_;
535 DnsConfigServiceWin* service_; 650 DnsConfigServiceWin* service_;
536 // Written in DoWork, read in OnWorkFinished, no locking necessary. 651 // Written in DoWork, read in OnWorkFinished, no locking necessary.
537 DnsHosts hosts_; 652 DnsHosts hosts_;
538 bool success_; 653 bool success_;
539 654
540 DISALLOW_COPY_AND_ASSIGN(HostsReader); 655 DISALLOW_COPY_AND_ASSIGN(HostsReader);
541 }; 656 };
542 657
543 DnsConfigServiceWin::DnsConfigServiceWin() 658 DnsConfigServiceWin::DnsConfigServiceWin()
544 : config_reader_(new ConfigReader(this)), 659 : watcher_(new Watcher(this)),
660 config_reader_(new ConfigReader(this)),
545 hosts_reader_(new HostsReader(this)) {} 661 hosts_reader_(new HostsReader(this)) {}
546 662
547 DnsConfigServiceWin::~DnsConfigServiceWin() { 663 DnsConfigServiceWin::~DnsConfigServiceWin() {
548 config_reader_->Cancel(); 664 config_reader_->Cancel();
549 hosts_reader_->Cancel(); 665 hosts_reader_->Cancel();
550 NetworkChangeNotifier::RemoveIPAddressObserver(this);
551 } 666 }
552 667
553 void DnsConfigServiceWin::Watch(const CallbackType& callback) { 668 void DnsConfigServiceWin::ReadNow() {
554 DnsConfigService::Watch(callback); 669 config_reader_->WorkNow();
555 // Also need to observe changes to local non-loopback IP for DnsHosts. 670 hosts_reader_->WorkNow();
556 NetworkChangeNotifier::AddIPAddressObserver(this);
557 } 671 }
558 672
559 void DnsConfigServiceWin::OnDNSChanged(unsigned detail) { 673 bool DnsConfigServiceWin::StartWatching() {
560 if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_FAILED) { 674 // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139
561 InvalidateConfig(); 675 return watcher_->Watch();
562 InvalidateHosts(); 676 }
563 // We don't trust a config that we cannot watch in the future. 677
564 config_reader_->Cancel(); 678 void DnsConfigServiceWin::OnConfigChanged(bool succeeded) {
565 hosts_reader_->Cancel(); 679 InvalidateConfig();
566 return; 680 if (succeeded) {
567 }
568 if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_STARTED)
569 detail = ~0; // Assume everything changed.
570 if (detail & NetworkChangeNotifier::CHANGE_DNS_SETTINGS) {
571 InvalidateConfig();
572 config_reader_->WorkNow(); 681 config_reader_->WorkNow();
573 } 682 } else {
574 if (detail & NetworkChangeNotifier::CHANGE_DNS_HOSTS) { 683 LOG(ERROR) << "DNS config watch failed.";
575 InvalidateHosts(); 684 set_watch_failed(true);
576 hosts_reader_->WorkNow();
577 } 685 }
578 } 686 }
579 687
580 void DnsConfigServiceWin::OnIPAddressChanged() { 688 void DnsConfigServiceWin::OnHostsChanged(bool succeeded) {
581 // Need to update non-loopback IP of local host. 689 InvalidateHosts();
582 if (NetworkChangeNotifier::IsWatchingDNS()) 690 if (succeeded) {
583 OnDNSChanged(NetworkChangeNotifier::CHANGE_DNS_HOSTS); 691 hosts_reader_->WorkNow();
692 } else {
693 LOG(ERROR) << "DNS hosts watch failed.";
694 set_watch_failed(true);
695 }
584 } 696 }
585 697
586 } // namespace internal 698 } // namespace internal
587 699
588 // static 700 // static
589 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 701 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
590 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin()); 702 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin());
591 } 703 }
592 704
593 } // namespace net 705 } // namespace net
594 706
OLDNEW
« 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