summaryrefslogtreecommitdiffstats
path: root/net/base/network_change_notifier_linux.cc
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-21 20:45:25 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-21 20:45:25 +0000
commitb5e0b76de03fd53043b65a0524ab1150edb31d8c (patch)
treeec31d520c9c0c8a8a64d25c0a1db8c77006dca2f /net/base/network_change_notifier_linux.cc
parent3520b16bdefeece3a46ca1ddfb8f3187508c3d9f (diff)
downloadchromium_src-b5e0b76de03fd53043b65a0524ab1150edb31d8c.zip
chromium_src-b5e0b76de03fd53043b65a0524ab1150edb31d8c.tar.gz
chromium_src-b5e0b76de03fd53043b65a0524ab1150edb31d8c.tar.bz2
Refactor to avoid using DestructionObserver in NetworkChangeNotifierLinux.
BUG=none TEST=none Review URL: http://codereview.chromium.org/3879003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63413 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/network_change_notifier_linux.cc')
-rw-r--r--net/base/network_change_notifier_linux.cc142
1 files changed, 83 insertions, 59 deletions
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
index 7131845..95f230d 100644
--- a/net/base/network_change_notifier_linux.cc
+++ b/net/base/network_change_notifier_linux.cc
@@ -7,15 +7,13 @@
#include <errno.h>
#include <sys/socket.h>
+#include "base/compiler_specific.h"
#include "base/eintr_wrapper.h"
#include "base/task.h"
#include "base/thread.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier_netlink_linux.h"
-// We only post tasks to a child thread we own, so we don't need refcounting.
-DISABLE_RUNNABLE_METHOD_REFCOUNT(net::NetworkChangeNotifierLinux);
-
namespace net {
namespace {
@@ -24,75 +22,80 @@ const int kInvalidSocket = -1;
} // namespace
-NetworkChangeNotifierLinux::NetworkChangeNotifierLinux()
- : notifier_thread_(new base::Thread("NetworkChangeNotifier")),
- netlink_fd_(kInvalidSocket) {
- // We create this notifier thread because the notification implementation
- // needs a MessageLoopForIO, and there's no guarantee that
- // MessageLoop::current() meets that criterion.
- base::Thread::Options thread_options(MessageLoop::TYPE_IO, 0);
- notifier_thread_->StartWithOptions(thread_options);
- notifier_thread_->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &NetworkChangeNotifierLinux::Init));
-}
+class NetworkChangeNotifierLinux::Thread
+ : public base::Thread, public MessageLoopForIO::Watcher {
+ public:
+ Thread();
+ virtual ~Thread();
-NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() {
- // We don't need to explicitly Stop(), but doing so allows us to sanity-
- // check that the notifier thread shut down properly.
- notifier_thread_->Stop();
- DCHECK_EQ(kInvalidSocket, netlink_fd_);
-}
+ // MessageLoopForIO::Watcher:
+ virtual void OnFileCanReadWithoutBlocking(int fd);
+ virtual void OnFileCanWriteWithoutBlocking(int /* fd */);
-bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const {
- // TODO(eroman): http://crbug.com/53473
- return false;
-}
+ protected:
+ // base::Thread
+ virtual void Init();
+ virtual void CleanUp();
-void NetworkChangeNotifierLinux::WillDestroyCurrentMessageLoop() {
- DCHECK(notifier_thread_ != NULL);
- // We can't check the notifier_thread_'s message_loop(), as it's now 0.
- // DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
-
- if (netlink_fd_ != kInvalidSocket) {
- if (HANDLE_EINTR(close(netlink_fd_)) != 0)
- PLOG(ERROR) << "Failed to close socket";
- netlink_fd_ = kInvalidSocket;
- netlink_watcher_.StopWatchingFileDescriptor();
+ private:
+ void NotifyObserversOfIPAddressChange() {
+ NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
}
-}
-void NetworkChangeNotifierLinux::OnFileCanReadWithoutBlocking(int fd) {
- DCHECK(notifier_thread_ != NULL);
- DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
+ // Starts listening for netlink messages. Also handles the messages if there
+ // are any available on the netlink socket.
+ void ListenForNotifications();
- DCHECK_EQ(fd, netlink_fd_);
- ListenForNotifications();
-}
+ // Attempts to read from the netlink socket into |buf| of length |len|.
+ // Returns the bytes read on synchronous success and ERR_IO_PENDING if the
+ // recv() would block. Otherwise, it returns a net error code.
+ int ReadNotificationMessage(char* buf, size_t len);
-void NetworkChangeNotifierLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {
- DCHECK(notifier_thread_ != NULL);
- DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
+ // The netlink socket descriptor.
+ int netlink_fd_;
+ MessageLoopForIO::FileDescriptorWatcher netlink_watcher_;
- NOTREACHED();
-}
+ // Technically only needed for ChromeOS, but it's ugly to #ifdef out.
+ ScopedRunnableMethodFactory<Thread> method_factory_;
-void NetworkChangeNotifierLinux::Init() {
- DCHECK(notifier_thread_ != NULL);
- DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
+ DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+NetworkChangeNotifierLinux::Thread::Thread()
+ : base::Thread("NetworkChangeNotifier"),
+ netlink_fd_(kInvalidSocket),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {}
+
+NetworkChangeNotifierLinux::Thread::~Thread() {}
+
+void NetworkChangeNotifierLinux::Thread::Init() {
netlink_fd_ = InitializeNetlinkSocket();
if (netlink_fd_ < 0) {
netlink_fd_ = kInvalidSocket;
return;
}
- MessageLoop::current()->AddDestructionObserver(this);
ListenForNotifications();
}
-void NetworkChangeNotifierLinux::ListenForNotifications() {
- DCHECK(notifier_thread_ != NULL);
- DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
+void NetworkChangeNotifierLinux::Thread::CleanUp() {
+ if (netlink_fd_ != kInvalidSocket) {
+ if (HANDLE_EINTR(close(netlink_fd_)) != 0)
+ PLOG(ERROR) << "Failed to close socket";
+ netlink_fd_ = kInvalidSocket;
+ netlink_watcher_.StopWatchingFileDescriptor();
+ }
+}
+
+void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) {
+ DCHECK_EQ(fd, netlink_fd_);
+ ListenForNotifications();
+}
+
+void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking(int /* fd */) {
+ NOTREACHED();
+}
+void NetworkChangeNotifierLinux::Thread::ListenForNotifications() {
char buf[4096];
int rv = ReadNotificationMessage(buf, arraysize(buf));
while (rv > 0) {
@@ -104,8 +107,10 @@ void NetworkChangeNotifierLinux::ListenForNotifications() {
// is functional in ChromeOS. This should be removed once this bug
// is properly fixed.
const int kObserverNotificationDelayMS = 500;
- MessageLoop::current()->PostDelayedTask(FROM_HERE, NewRunnableFunction(
- &NetworkChangeNotifier::NotifyObserversOfIPAddressChange),
+ message_loop()->PostDelayedTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &Thread::NotifyObserversOfIPAddressChange),
kObserverNotificationDelayMS);
#else
NotifyObserversOfIPAddressChange();
@@ -121,10 +126,9 @@ void NetworkChangeNotifierLinux::ListenForNotifications() {
}
}
-int NetworkChangeNotifierLinux::ReadNotificationMessage(char* buf, size_t len) {
- DCHECK(notifier_thread_ != NULL);
- DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current());
-
+int NetworkChangeNotifierLinux::Thread::ReadNotificationMessage(
+ char* buf,
+ size_t len) {
DCHECK_NE(len, 0u);
DCHECK(buf);
memset(buf, 0, sizeof(buf));
@@ -141,4 +145,24 @@ int NetworkChangeNotifierLinux::ReadNotificationMessage(char* buf, size_t len) {
return ERR_IO_PENDING;
}
+NetworkChangeNotifierLinux::NetworkChangeNotifierLinux()
+ : notifier_thread_(new Thread) {
+ // We create this notifier thread because the notification implementation
+ // needs a MessageLoopForIO, and there's no guarantee that
+ // MessageLoop::current() meets that criterion.
+ base::Thread::Options thread_options(MessageLoop::TYPE_IO, 0);
+ notifier_thread_->StartWithOptions(thread_options);
+}
+
+NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() {
+ // We don't need to explicitly Stop(), but doing so allows us to sanity-
+ // check that the notifier thread shut down properly.
+ notifier_thread_->Stop();
+}
+
+bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const {
+ // TODO(eroman): http://crbug.com/53473
+ return false;
+}
+
} // namespace net