| Index: net/base/network_change_notifier_mac.cc
|
| diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc
|
| index ca314a199f9f6343b105a034bde290f5c55d3e72..702cc2e6c372f3b1b8f9cdf766c425e426856c4b 100644
|
| --- a/net/base/network_change_notifier_mac.cc
|
| +++ b/net/base/network_change_notifier_mac.cc
|
| @@ -5,6 +5,13 @@
|
| #include "net/base/network_change_notifier_mac.h"
|
|
|
| #include <netinet/in.h>
|
| +#include <resolv.h>
|
| +
|
| +#include "base/threading/thread.h"
|
| +
|
| +#ifndef _PATH_RESCONF // Normally defined in <resolv.h>
|
| +#define _PATH_RESCONF "/etc/resolv.conf"
|
| +#endif
|
|
|
| namespace net {
|
|
|
| @@ -14,6 +21,62 @@ static bool CalculateReachability(SCNetworkConnectionFlags flags) {
|
| return reachable && !connection_required;
|
| }
|
|
|
| +class NetworkChangeNotifierMac::DNSWatcher : public base::Thread {
|
| + public:
|
| + DNSWatcher() : watching_dns_(false) {}
|
| +
|
| + virtual void Init() OVERRIDE {
|
| + base::AutoLock lock(watching_dns_lock_);
|
| + watching_dns_ = true;
|
| + if (!resolv_watcher_.Watch(
|
| + FilePath(FILE_PATH_LITERAL(_PATH_RESCONF)),
|
| + base::Bind(&DNSWatcher::OnDNSFileChanged,
|
| + base::Unretained(this),
|
| + static_cast<unsigned>(CHANGE_DNS_SETTINGS)))) {
|
| + LOG(ERROR) << "Failed to setup watch for /etc/resolv.conf";
|
| + watching_dns_ = false;
|
| + }
|
| + if (!hosts_watcher_.Watch(
|
| + FilePath(FILE_PATH_LITERAL("/etc/hosts")),
|
| + base::Bind(&DNSWatcher::OnDNSFileChanged,
|
| + base::Unretained(this),
|
| + static_cast<unsigned>(CHANGE_DNS_HOSTS)))) {
|
| + LOG(ERROR) << "Failed to setup watch for /etc/hosts";
|
| + watching_dns_ = false;
|
| + }
|
| + }
|
| +
|
| + virtual void CleanUp() OVERRIDE {
|
| + base::AutoLock lock(watching_dns_lock_);
|
| + watching_dns_ = false;
|
| + resolv_watcher_.Cancel();
|
| + hosts_watcher_.Cancel();
|
| + }
|
| +
|
| + bool IsWatching() const {
|
| + base::AutoLock lock(watching_dns_lock_);
|
| + return watching_dns_;
|
| + }
|
| +
|
| + private:
|
| + // Called from FilePathWatcherCallback.
|
| + void OnDNSFileChanged(unsigned detail, bool watch_success) {
|
| + if (!watch_success) {
|
| + LOG(ERROR) << "DNS watch failed.";
|
| + base::AutoLock lock(watching_dns_lock_);
|
| + watching_dns_ = false;
|
| + }
|
| + // Always notify observers so that they can check IsWatchingDNS().
|
| + NetworkChangeNotifier::NotifyObserversOfDNSChange(detail);
|
| + }
|
| +
|
| + FilePathWatcherCallback resolv_watcher_;
|
| + FilePathWatcherCallback hosts_watcher_;
|
| +
|
| + bool watching_dns_;
|
| + mutable base::Lock watching_dns_lock_;
|
| +};
|
| +
|
| NetworkChangeNotifierMac::NetworkChangeNotifierMac()
|
| : online_state_(UNINITIALIZED),
|
| initial_state_cv_(&online_state_lock_),
|
| @@ -21,6 +84,10 @@ NetworkChangeNotifierMac::NetworkChangeNotifierMac()
|
| // Must be initialized after the rest of this object, as it may call back into
|
| // SetInitialState().
|
| config_watcher_.reset(new NetworkConfigWatcherMac(&forwarder_));
|
| +
|
| + dns_watcher_.reset(new DNSWatcher());
|
| + dns_watcher_->StartWithOptions(
|
| + base::Thread::Options(MessageLoop::TYPE_IO, 0));
|
| }
|
|
|
| NetworkChangeNotifierMac::~NetworkChangeNotifierMac() {
|
| @@ -46,6 +113,10 @@ bool NetworkChangeNotifierMac::IsCurrentlyOffline() const {
|
| return online_state_ == OFFLINE;
|
| }
|
|
|
| +bool NetworkChangeNotifierMac::IsCurrentlyWatchingDNS() const {
|
| + return dns_watcher_->IsWatching();
|
| +}
|
| +
|
| void NetworkChangeNotifierMac::SetInitialState() {
|
| // Called on notifier thread.
|
|
|
|
|