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

Side by Side Diff: net/base/network_change_notifier_linux.cc

Issue 10377092: [net/dns] Isolate DnsConfigWatcher from DnsConfigService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments. Braces. Created 8 years, 7 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
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 // This implementation of NetworkChangeNotifier's offline state detection 5 // This implementation of NetworkChangeNotifier's offline state detection
6 // depends on D-Bus and NetworkManager, and is known to work on at least 6 // depends on D-Bus and NetworkManager, and is known to work on at least
7 // GNOME version 2.30. If D-Bus or NetworkManager are unavailable, this 7 // GNOME version 2.30. If D-Bus or NetworkManager are unavailable, this
8 // implementation will always behave as if it is online. 8 // implementation will always behave as if it is online.
9 9
10 #include "net/base/network_change_notifier_linux.h" 10 #include "net/base/network_change_notifier_linux.h"
11 11
12 #include <errno.h> 12 #include <errno.h>
13 #include <resolv.h>
13 #include <sys/socket.h> 14 #include <sys/socket.h>
14 15
15 #include "base/bind.h" 16 #include "base/bind.h"
16 #include "base/bind_helpers.h" 17 #include "base/bind_helpers.h"
17 #include "base/callback.h" 18 #include "base/callback.h"
18 #include "base/compiler_specific.h" 19 #include "base/compiler_specific.h"
19 #include "base/eintr_wrapper.h" 20 #include "base/eintr_wrapper.h"
20 #include "base/file_util.h"
21 #include "base/files/file_path_watcher.h"
22 #include "base/memory/weak_ptr.h" 21 #include "base/memory/weak_ptr.h"
23 #include "base/synchronization/lock.h" 22 #include "base/synchronization/lock.h"
24 #include "base/synchronization/waitable_event.h" 23 #include "base/synchronization/waitable_event.h"
25 #include "base/threading/platform_thread.h" 24 #include "base/threading/platform_thread.h"
26 #include "base/threading/thread.h" 25 #include "base/threading/thread.h"
27 #include "base/threading/thread_restrictions.h" 26 #include "base/threading/thread_restrictions.h"
28 #include "dbus/bus.h" 27 #include "dbus/bus.h"
29 #include "dbus/message.h" 28 #include "dbus/message.h"
30 #include "dbus/object_proxy.h" 29 #include "dbus/object_proxy.h"
31 #include "net/base/net_errors.h" 30 #include "net/base/net_errors.h"
32 #include "net/base/network_change_notifier_netlink_linux.h" 31 #include "net/base/network_change_notifier_netlink_linux.h"
33 32 #include "net/dns/dns_config_watcher.h"
34 using ::base::files::FilePathWatcher;
35 33
36 namespace net { 34 namespace net {
37 35
38 namespace { 36 namespace {
39 37
40 const int kInvalidSocket = -1; 38 const int kInvalidSocket = -1;
41 39
42 const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager"; 40 const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager";
43 const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager"; 41 const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager";
44 const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager"; 42 const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager";
(...skipping 12 matching lines...) Expand all
57 NM_STATE_UNKNOWN = 0, 55 NM_STATE_UNKNOWN = 0,
58 NM_STATE_ASLEEP = 10, 56 NM_STATE_ASLEEP = 10,
59 NM_STATE_DISCONNECTED = 20, 57 NM_STATE_DISCONNECTED = 20,
60 NM_STATE_DISCONNECTING = 30, 58 NM_STATE_DISCONNECTING = 30,
61 NM_STATE_CONNECTING = 40, 59 NM_STATE_CONNECTING = 40,
62 NM_STATE_CONNECTED_LOCAL = 50, 60 NM_STATE_CONNECTED_LOCAL = 50,
63 NM_STATE_CONNECTED_SITE = 60, 61 NM_STATE_CONNECTED_SITE = 60,
64 NM_STATE_CONNECTED_GLOBAL = 70 62 NM_STATE_CONNECTED_GLOBAL = 70
65 }; 63 };
66 64
67 class DNSWatchDelegate : public FilePathWatcher::Delegate {
68 public:
69 explicit DNSWatchDelegate(const base::Closure& callback)
70 : callback_(callback) {}
71 virtual ~DNSWatchDelegate() {}
72 // FilePathWatcher::Delegate interface
73 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE;
74 virtual void OnFilePathError(const FilePath& path) OVERRIDE;
75 private:
76 base::Closure callback_;
77 DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate);
78 };
79
80 void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) {
81 // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange().
82 callback_.Run();
83 }
84
85 void DNSWatchDelegate::OnFilePathError(const FilePath& path) {
86 LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value();
87 }
88
89 } // namespace 65 } // namespace
90 66
91 // A wrapper around NetworkManager's D-Bus API. 67 // A wrapper around NetworkManager's D-Bus API.
92 class NetworkManagerApi { 68 class NetworkManagerApi {
93 public: 69 public:
94 NetworkManagerApi(const base::Closure& notification_callback, dbus::Bus* bus) 70 NetworkManagerApi(const base::Closure& notification_callback, dbus::Bus* bus)
95 : is_offline_(false), 71 : is_offline_(false),
96 offline_state_initialized_(true /*manual_reset*/, false), 72 offline_state_initialized_(true /*manual_reset*/, false),
97 notification_callback_(notification_callback), 73 notification_callback_(notification_callback),
98 helper_thread_id_(base::kInvalidThreadId), 74 helper_thread_id_(base::kInvalidThreadId),
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 return is_offline_; 240 return is_offline_;
265 } 241 }
266 242
267 class NetworkChangeNotifierLinux::Thread 243 class NetworkChangeNotifierLinux::Thread
268 : public base::Thread, public MessageLoopForIO::Watcher { 244 : public base::Thread, public MessageLoopForIO::Watcher {
269 public: 245 public:
270 explicit Thread(dbus::Bus* bus); 246 explicit Thread(dbus::Bus* bus);
271 virtual ~Thread(); 247 virtual ~Thread();
272 248
273 // MessageLoopForIO::Watcher: 249 // MessageLoopForIO::Watcher:
274 virtual void OnFileCanReadWithoutBlocking(int fd); 250 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
275 virtual void OnFileCanWriteWithoutBlocking(int /* fd */); 251 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE;
276 252
277 // Plumbing for NetworkChangeNotifier::IsCurrentlyOffline. 253 // Plumbing for NetworkChangeNotifier::IsCurrentlyOffline.
278 // Safe to call from any thread. 254 // Safe to call from any thread.
279 bool IsCurrentlyOffline() { 255 bool IsCurrentlyOffline() {
280 return network_manager_api_.IsCurrentlyOffline(); 256 return network_manager_api_.IsCurrentlyOffline();
281 } 257 }
282 258
283 protected: 259 protected:
284 // base::Thread 260 // base::Thread
285 virtual void Init(); 261 virtual void Init() OVERRIDE;
286 virtual void CleanUp(); 262 virtual void CleanUp() OVERRIDE;
287 263
288 private: 264 private:
289 // Starts listening for netlink messages. Also handles the messages if there 265 // Starts listening for netlink messages. Also handles the messages if there
290 // are any available on the netlink socket. 266 // are any available on the netlink socket.
291 void ListenForNotifications(); 267 void ListenForNotifications();
292 268
293 // Attempts to read from the netlink socket into |buf| of length |len|. 269 // Attempts to read from the netlink socket into |buf| of length |len|.
294 // Returns the bytes read on synchronous success and ERR_IO_PENDING if the 270 // Returns the bytes read on synchronous success and ERR_IO_PENDING if the
295 // recv() would block. Otherwise, it returns a net error code. 271 // recv() would block. Otherwise, it returns a net error code.
296 int ReadNotificationMessage(char* buf, size_t len); 272 int ReadNotificationMessage(char* buf, size_t len);
297 273
298 // The netlink socket descriptor. 274 // The netlink socket descriptor.
299 int netlink_fd_; 275 int netlink_fd_;
300 MessageLoopForIO::FileDescriptorWatcher netlink_watcher_; 276 MessageLoopForIO::FileDescriptorWatcher netlink_watcher_;
301 277
302 // Technically only needed for ChromeOS, but it's ugly to #ifdef out.
303 base::WeakPtrFactory<Thread> ptr_factory_;
304
305 // Used to watch for changes to /etc/resolv.conf and /etc/hosts.
306 scoped_ptr<base::files::FilePathWatcher> resolv_file_watcher_;
307 scoped_ptr<base::files::FilePathWatcher> hosts_file_watcher_;
308 scoped_refptr<DNSWatchDelegate> resolv_watcher_delegate_;
309 scoped_refptr<DNSWatchDelegate> hosts_watcher_delegate_;
310
311 // Used to detect online/offline state changes. 278 // Used to detect online/offline state changes.
312 NetworkManagerApi network_manager_api_; 279 NetworkManagerApi network_manager_api_;
313 280
281 internal::DnsConfigWatcher dns_watcher_;
282
314 DISALLOW_COPY_AND_ASSIGN(Thread); 283 DISALLOW_COPY_AND_ASSIGN(Thread);
315 }; 284 };
316 285
317 NetworkChangeNotifierLinux::Thread::Thread(dbus::Bus* bus) 286 NetworkChangeNotifierLinux::Thread::Thread(dbus::Bus* bus)
318 : base::Thread("NetworkChangeNotifier"), 287 : base::Thread("NetworkChangeNotifier"),
319 netlink_fd_(kInvalidSocket), 288 netlink_fd_(kInvalidSocket),
320 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)),
321 network_manager_api_( 289 network_manager_api_(
322 base::Bind(&NetworkChangeNotifier 290 base::Bind(&NetworkChangeNotifier
323 ::NotifyObserversOfOnlineStateChange), 291 ::NotifyObserversOfOnlineStateChange),
324 bus) { 292 bus) {
325 } 293 }
326 294
327 NetworkChangeNotifierLinux::Thread::~Thread() { 295 NetworkChangeNotifierLinux::Thread::~Thread() {
328 DCHECK(!Thread::IsRunning()); 296 DCHECK(!Thread::IsRunning());
329 } 297 }
330 298
331 void NetworkChangeNotifierLinux::Thread::Init() { 299 void NetworkChangeNotifierLinux::Thread::Init() {
332 resolv_file_watcher_.reset(new FilePathWatcher);
333 hosts_file_watcher_.reset(new FilePathWatcher);
334 resolv_watcher_delegate_ = new DNSWatchDelegate(base::Bind(
335 &NetworkChangeNotifier::NotifyObserversOfDNSChange,
336 static_cast<unsigned>(CHANGE_DNS_SETTINGS)));
337 hosts_watcher_delegate_ = new DNSWatchDelegate(base::Bind(
338 &NetworkChangeNotifier::NotifyObserversOfDNSChange,
339 static_cast<unsigned>(CHANGE_DNS_HOSTS)));
340 if (!resolv_file_watcher_->Watch(
341 FilePath(FILE_PATH_LITERAL("/etc/resolv.conf")),
342 resolv_watcher_delegate_.get())) {
343 LOG(ERROR) << "Failed to setup watch for /etc/resolv.conf";
344 }
345 if (!hosts_file_watcher_->Watch(FilePath(FILE_PATH_LITERAL("/etc/hosts")),
346 hosts_watcher_delegate_.get())) {
347 LOG(ERROR) << "Failed to setup watch for /etc/hosts";
348 }
349 netlink_fd_ = InitializeNetlinkSocket(); 300 netlink_fd_ = InitializeNetlinkSocket();
350 if (netlink_fd_ < 0) { 301 if (netlink_fd_ < 0) {
351 netlink_fd_ = kInvalidSocket; 302 netlink_fd_ = kInvalidSocket;
352 return; 303 return;
353 } 304 }
354 ListenForNotifications(); 305 ListenForNotifications();
355 306
356 network_manager_api_.Init(); 307 network_manager_api_.Init();
308
309 dns_watcher_.Init();
357 } 310 }
358 311
359 void NetworkChangeNotifierLinux::Thread::CleanUp() { 312 void NetworkChangeNotifierLinux::Thread::CleanUp() {
360 if (netlink_fd_ != kInvalidSocket) { 313 if (netlink_fd_ != kInvalidSocket) {
361 if (HANDLE_EINTR(close(netlink_fd_)) != 0) 314 if (HANDLE_EINTR(close(netlink_fd_)) != 0)
362 PLOG(ERROR) << "Failed to close socket"; 315 PLOG(ERROR) << "Failed to close socket";
363 netlink_fd_ = kInvalidSocket; 316 netlink_fd_ = kInvalidSocket;
364 netlink_watcher_.StopWatchingFileDescriptor(); 317 netlink_watcher_.StopWatchingFileDescriptor();
365 } 318 }
366 // Kill watchers early to make sure they won't try to call 319 network_manager_api_.CleanUp();
367 // into us via the delegate during destruction.
368 resolv_file_watcher_.reset();
369 hosts_file_watcher_.reset();
370 320
371 network_manager_api_.CleanUp(); 321 dns_watcher_.CleanUp();
372 } 322 }
373 323
374 void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) { 324 void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) {
375 DCHECK_EQ(fd, netlink_fd_); 325 DCHECK_EQ(fd, netlink_fd_);
376 ListenForNotifications(); 326 ListenForNotifications();
377 } 327 }
378 328
379 void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking( 329 void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking(
380 int /* fd */) { 330 int /* fd */) {
381 NOTREACHED(); 331 NOTREACHED();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 // Stopping from here allows us to sanity- check that the notifier 390 // Stopping from here allows us to sanity- check that the notifier
441 // thread shut down properly. 391 // thread shut down properly.
442 notifier_thread_->Stop(); 392 notifier_thread_->Stop();
443 } 393 }
444 394
445 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { 395 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const {
446 return notifier_thread_->IsCurrentlyOffline(); 396 return notifier_thread_->IsCurrentlyOffline();
447 } 397 }
448 398
449 } // namespace net 399 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698