| Index: net/base/network_change_notifier_linux.cc
|
| diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
|
| index 92eec2d0044f115329376692e170b8b86722865e..be6f3dabb6cd16ef748009fbb67a5342f2731725 100644
|
| --- a/net/base/network_change_notifier_linux.cc
|
| +++ b/net/base/network_change_notifier_linux.cc
|
| @@ -10,6 +10,7 @@
|
| #include "net/base/network_change_notifier_linux.h"
|
|
|
| #include <errno.h>
|
| +#include <resolv.h>
|
| #include <sys/socket.h>
|
|
|
| #include "base/bind.h"
|
| @@ -27,11 +28,16 @@
|
| #include "dbus/bus.h"
|
| #include "dbus/message.h"
|
| #include "dbus/object_proxy.h"
|
| +#include "net/base/file_path_watcher_callback.h"
|
| #include "net/base/net_errors.h"
|
| #include "net/base/network_change_notifier_netlink_linux.h"
|
|
|
| using ::base::files::FilePathWatcher;
|
|
|
| +#ifndef _PATH_RESCONF // Normally defined in <resolv.h>
|
| +#define _PATH_RESCONF "/etc/resolv.conf"
|
| +#endif
|
| +
|
| namespace net {
|
|
|
| namespace {
|
| @@ -237,28 +243,6 @@ bool NetworkManagerApi::IsCurrentlyOffline() {
|
| return is_offline_;
|
| }
|
|
|
| -class DNSWatchDelegate : public FilePathWatcher::Delegate {
|
| - public:
|
| - explicit DNSWatchDelegate(const base::Closure& callback)
|
| - : callback_(callback) {}
|
| - virtual ~DNSWatchDelegate() {}
|
| - // FilePathWatcher::Delegate interface
|
| - virtual void OnFilePathChanged(const FilePath& path) OVERRIDE;
|
| - virtual void OnFilePathError(const FilePath& path) OVERRIDE;
|
| - private:
|
| - base::Closure callback_;
|
| - DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate);
|
| -};
|
| -
|
| -void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) {
|
| - // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange().
|
| - callback_.Run();
|
| -}
|
| -
|
| -void DNSWatchDelegate::OnFilePathError(const FilePath& path) {
|
| - LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value();
|
| -}
|
| -
|
| } // namespace
|
|
|
| class NetworkChangeNotifierLinux::Thread
|
| @@ -277,6 +261,11 @@ class NetworkChangeNotifierLinux::Thread
|
| return network_manager_api_.IsCurrentlyOffline();
|
| }
|
|
|
| + bool IsCurrentlyWatchingDNS() {
|
| + base::AutoLock lock(watching_dns_lock_);
|
| + return watching_dns_;
|
| + }
|
| +
|
| protected:
|
| // base::Thread
|
| virtual void Init();
|
| @@ -292,18 +281,19 @@ class NetworkChangeNotifierLinux::Thread
|
| // recv() would block. Otherwise, it returns a net error code.
|
| int ReadNotificationMessage(char* buf, size_t len);
|
|
|
| + // Called from FilePathWatcherCallback.
|
| + void OnDNSFileChanged(unsigned detail, bool watch_success);
|
| +
|
| // The netlink socket descriptor.
|
| int netlink_fd_;
|
| MessageLoopForIO::FileDescriptorWatcher netlink_watcher_;
|
|
|
| - // Technically only needed for ChromeOS, but it's ugly to #ifdef out.
|
| - base::WeakPtrFactory<Thread> ptr_factory_;
|
| -
|
| // Used to watch for changes to /etc/resolv.conf and /etc/hosts.
|
| - scoped_ptr<base::files::FilePathWatcher> resolv_file_watcher_;
|
| - scoped_ptr<base::files::FilePathWatcher> hosts_file_watcher_;
|
| - scoped_refptr<DNSWatchDelegate> resolv_watcher_delegate_;
|
| - scoped_refptr<DNSWatchDelegate> hosts_watcher_delegate_;
|
| + FilePathWatcherCallback resolv_watcher_;
|
| + FilePathWatcherCallback hosts_watcher_;
|
| +
|
| + base::Lock watching_dns_lock_;
|
| + bool watching_dns_;
|
|
|
| // Used to detect online/offline state changes.
|
| NetworkManagerApi network_manager_api_;
|
| @@ -314,7 +304,7 @@ class NetworkChangeNotifierLinux::Thread
|
| NetworkChangeNotifierLinux::Thread::Thread(dbus::Bus* bus)
|
| : base::Thread("NetworkChangeNotifier"),
|
| netlink_fd_(kInvalidSocket),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)),
|
| + watching_dns_(false),
|
| network_manager_api_(
|
| base::Bind(&NetworkChangeNotifier
|
| ::NotifyObserversOfOnlineStateChange),
|
| @@ -326,22 +316,23 @@ NetworkChangeNotifierLinux::Thread::~Thread() {
|
| }
|
|
|
| void NetworkChangeNotifierLinux::Thread::Init() {
|
| - resolv_file_watcher_.reset(new FilePathWatcher);
|
| - hosts_file_watcher_.reset(new FilePathWatcher);
|
| - resolv_watcher_delegate_ = new DNSWatchDelegate(base::Bind(
|
| - &NetworkChangeNotifier::NotifyObserversOfDNSChange,
|
| - static_cast<unsigned>(CHANGE_DNS_SETTINGS)));
|
| - hosts_watcher_delegate_ = new DNSWatchDelegate(base::Bind(
|
| - &NetworkChangeNotifier::NotifyObserversOfDNSChange,
|
| - static_cast<unsigned>(CHANGE_DNS_HOSTS)));
|
| - if (!resolv_file_watcher_->Watch(
|
| - FilePath(FILE_PATH_LITERAL("/etc/resolv.conf")),
|
| - resolv_watcher_delegate_.get())) {
|
| + base::AutoLock lock(watching_dns_lock_);
|
| + watching_dns_ = true;
|
| + if (!resolv_watcher_.Watch(
|
| + FilePath(FILE_PATH_LITERAL(_PATH_RESCONF)),
|
| + base::Bind(&Thread::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_file_watcher_->Watch(FilePath(FILE_PATH_LITERAL("/etc/hosts")),
|
| - hosts_watcher_delegate_.get())) {
|
| + if (!hosts_watcher_.Watch(
|
| + FilePath(FILE_PATH_LITERAL("/etc/hosts")),
|
| + base::Bind(&Thread::OnDNSFileChanged,
|
| + base::Unretained(this),
|
| + static_cast<unsigned>(CHANGE_DNS_HOSTS)))) {
|
| LOG(ERROR) << "Failed to setup watch for /etc/hosts";
|
| + watching_dns_ = false;
|
| }
|
| netlink_fd_ = InitializeNetlinkSocket();
|
| if (netlink_fd_ < 0) {
|
| @@ -362,8 +353,8 @@ void NetworkChangeNotifierLinux::Thread::CleanUp() {
|
| }
|
| // Kill watchers early to make sure they won't try to call
|
| // into us via the delegate during destruction.
|
| - resolv_file_watcher_.reset();
|
| - hosts_file_watcher_.reset();
|
| + resolv_watcher_.Cancel();
|
| + hosts_watcher_.Cancel();
|
|
|
| network_manager_api_.CleanUp();
|
| }
|
| @@ -384,19 +375,7 @@ void NetworkChangeNotifierLinux::Thread::ListenForNotifications() {
|
| while (rv > 0) {
|
| if (HandleNetlinkMessage(buf, rv)) {
|
| VLOG(1) << "Detected IP address changes.";
|
| -#if defined(OS_CHROMEOS)
|
| - // TODO(oshima): chromium-os:8285 - introduced artificial delay to
|
| - // work around the issue of network load issue after connection
|
| - // restored. See the bug for more details.
|
| - // This should be removed once this bug is properly fixed.
|
| - const int kObserverNotificationDelayMS = 200;
|
| - message_loop()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&NetworkChangeNotifier::NotifyObserversOfIPAddressChange),
|
| - kObserverNotificationDelayMS);
|
| -#else
|
| NotifyObserversOfIPAddressChange();
|
| -#endif
|
| }
|
| rv = ReadNotificationMessage(buf, arraysize(buf));
|
| }
|
| @@ -427,6 +406,17 @@ int NetworkChangeNotifierLinux::Thread::ReadNotificationMessage(
|
| return ERR_IO_PENDING;
|
| }
|
|
|
| +void NetworkChangeNotifierLinux::Thread::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);
|
| +}
|
| +
|
| NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::Create() {
|
| return new NetworkChangeNotifierLinux(NULL);
|
| }
|
| @@ -455,4 +445,8 @@ bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const {
|
| return notifier_thread_->IsCurrentlyOffline();
|
| }
|
|
|
| +bool NetworkChangeNotifierLinux::IsCurrentlyWatchingDNS() const {
|
| + return notifier_thread_->IsCurrentlyWatchingDNS();
|
| +}
|
| +
|
| } // namespace net
|
|
|