| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // | |
| 5 // This implementation of NetworkChangeNotifier's offline state detection | |
| 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 | |
| 8 // implementation will always behave as if it is online. | |
| 9 | 4 |
| 10 #include "net/base/network_change_notifier_linux.h" | 5 #include "net/base/network_change_notifier_linux.h" |
| 11 | 6 |
| 12 #include <errno.h> | 7 #include <errno.h> |
| 13 #include <sys/socket.h> | 8 #include <sys/socket.h> |
| 14 | 9 |
| 15 #include "base/bind.h" | 10 #include "base/bind.h" |
| 16 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 17 #include "base/callback.h" | 12 #include "base/callback.h" |
| 18 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 19 #include "base/eintr_wrapper.h" | 14 #include "base/eintr_wrapper.h" |
| 20 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 21 #include "base/files/file_path_watcher.h" | 16 #include "base/files/file_path_watcher.h" |
| 22 #include "base/memory/weak_ptr.h" | 17 #include "base/memory/weak_ptr.h" |
| 23 #include "base/synchronization/lock.h" | |
| 24 #include "base/synchronization/waitable_event.h" | |
| 25 #include "base/threading/platform_thread.h" | |
| 26 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
| 27 #include "dbus/bus.h" | |
| 28 #include "dbus/message.h" | |
| 29 #include "dbus/object_proxy.h" | |
| 30 #include "net/base/net_errors.h" | 19 #include "net/base/net_errors.h" |
| 31 #include "net/base/network_change_notifier_netlink_linux.h" | 20 #include "net/base/network_change_notifier_netlink_linux.h" |
| 32 | 21 |
| 33 using ::base::files::FilePathWatcher; | 22 using ::base::files::FilePathWatcher; |
| 34 | 23 |
| 35 namespace net { | 24 namespace net { |
| 36 | 25 |
| 37 namespace { | 26 namespace { |
| 38 | 27 |
| 39 const int kInvalidSocket = -1; | 28 const int kInvalidSocket = -1; |
| 40 | 29 |
| 41 const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager"; | |
| 42 const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager"; | |
| 43 const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager"; | |
| 44 | |
| 45 // http://projects.gnome.org/NetworkManager/developers/spec-08.html#type-NM_STAT
E | |
| 46 enum { | |
| 47 NM_LEGACY_STATE_UNKNOWN = 0, | |
| 48 NM_LEGACY_STATE_ASLEEP = 1, | |
| 49 NM_LEGACY_STATE_CONNECTING = 2, | |
| 50 NM_LEGACY_STATE_CONNECTED = 3, | |
| 51 NM_LEGACY_STATE_DISCONNECTED = 4 | |
| 52 }; | |
| 53 | |
| 54 // http://projects.gnome.org/NetworkManager/developers/migrating-to-09/spec.html
#type-NM_STATE | |
| 55 enum { | |
| 56 NM_STATE_UNKNOWN = 0, | |
| 57 NM_STATE_ASLEEP = 10, | |
| 58 NM_STATE_DISCONNECTED = 20, | |
| 59 NM_STATE_DISCONNECTING = 30, | |
| 60 NM_STATE_CONNECTING = 40, | |
| 61 NM_STATE_CONNECTED_LOCAL = 50, | |
| 62 NM_STATE_CONNECTED_SITE = 60, | |
| 63 NM_STATE_CONNECTED_GLOBAL = 70 | |
| 64 }; | |
| 65 | |
| 66 // A wrapper around NetworkManager's D-Bus API. | |
| 67 class NetworkManagerApi { | |
| 68 public: | |
| 69 NetworkManagerApi(const base::Closure& notification_callback, dbus::Bus* bus) | |
| 70 : is_offline_(false), | |
| 71 offline_state_initialized_(true /*manual_reset*/, false), | |
| 72 notification_callback_(notification_callback), | |
| 73 helper_thread_id_(base::kInvalidThreadId), | |
| 74 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)), | |
| 75 system_bus_(bus) { } | |
| 76 | |
| 77 ~NetworkManagerApi() { } | |
| 78 | |
| 79 // Should be called on a helper thread which must be of type IO. | |
| 80 void Init(); | |
| 81 | |
| 82 // Must be called by the helper thread's CleanUp() method. | |
| 83 void CleanUp(); | |
| 84 | |
| 85 // Implementation of NetworkChangeNotifierLinux::IsCurrentlyOffline(). | |
| 86 // Safe to call from any thread, but will block until Init() has completed. | |
| 87 bool IsCurrentlyOffline(); | |
| 88 | |
| 89 private: | |
| 90 // Callbacks for D-Bus API. | |
| 91 void OnStateChanged(dbus::Message* message); | |
| 92 | |
| 93 void OnResponse(dbus::Response* response) { | |
| 94 OnStateChanged(response); | |
| 95 offline_state_initialized_.Signal(); | |
| 96 } | |
| 97 | |
| 98 void OnSignaled(dbus::Signal* signal) { | |
| 99 OnStateChanged(signal); | |
| 100 } | |
| 101 | |
| 102 void OnConnected(const std::string&, const std::string&, bool success) { | |
| 103 if (!success) { | |
| 104 DLOG(WARNING) << "Failed to set up offline state detection"; | |
| 105 offline_state_initialized_.Signal(); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 // Converts a NetworkManager state uint to a bool. | |
| 110 static bool StateIsOffline(uint32 state); | |
| 111 | |
| 112 bool is_offline_; | |
| 113 base::Lock is_offline_lock_; | |
| 114 base::WaitableEvent offline_state_initialized_; | |
| 115 | |
| 116 base::Closure notification_callback_; | |
| 117 | |
| 118 base::PlatformThreadId helper_thread_id_; | |
| 119 | |
| 120 base::WeakPtrFactory<NetworkManagerApi> ptr_factory_; | |
| 121 | |
| 122 scoped_refptr<dbus::Bus> system_bus_; | |
| 123 | |
| 124 DISALLOW_COPY_AND_ASSIGN(NetworkManagerApi); | |
| 125 }; | |
| 126 | |
| 127 void NetworkManagerApi::Init() { | |
| 128 // D-Bus requires an IO MessageLoop. | |
| 129 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_IO); | |
| 130 helper_thread_id_ = base::PlatformThread::CurrentId(); | |
| 131 | |
| 132 if (!system_bus_) { | |
| 133 dbus::Bus::Options options; | |
| 134 options.bus_type = dbus::Bus::SYSTEM; | |
| 135 options.connection_type = dbus::Bus::PRIVATE; | |
| 136 system_bus_ = new dbus::Bus(options); | |
| 137 } | |
| 138 | |
| 139 dbus::ObjectProxy* proxy = | |
| 140 system_bus_->GetObjectProxy(kNetworkManagerServiceName, | |
| 141 kNetworkManagerPath); | |
| 142 | |
| 143 // Get the initial state asynchronously. | |
| 144 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get"); | |
| 145 dbus::MessageWriter builder(&method_call); | |
| 146 builder.AppendString(kNetworkManagerInterface); | |
| 147 builder.AppendString("State"); | |
| 148 proxy->CallMethod( | |
| 149 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
| 150 base::Bind(&NetworkManagerApi::OnResponse, ptr_factory_.GetWeakPtr())); | |
| 151 | |
| 152 // And sign up for notifications. | |
| 153 proxy->ConnectToSignal( | |
| 154 kNetworkManagerInterface, | |
| 155 "StateChanged", | |
| 156 base::Bind(&NetworkManagerApi::OnSignaled, ptr_factory_.GetWeakPtr()), | |
| 157 base::Bind(&NetworkManagerApi::OnConnected, ptr_factory_.GetWeakPtr())); | |
| 158 } | |
| 159 | |
| 160 void NetworkManagerApi::CleanUp() { | |
| 161 DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); | |
| 162 ptr_factory_.InvalidateWeakPtrs(); | |
| 163 } | |
| 164 | |
| 165 void NetworkManagerApi::OnStateChanged(dbus::Message* message) { | |
| 166 DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); | |
| 167 if (!message) { | |
| 168 DLOG(WARNING) << "No response received for initial state request"; | |
| 169 return; | |
| 170 } | |
| 171 dbus::MessageReader reader(message); | |
| 172 uint32 state = 0; | |
| 173 if (!reader.HasMoreData() || !reader.PopUint32(&state)) { | |
| 174 DLOG(WARNING) << "Unexpected response for NetworkManager State request: " | |
| 175 << message->ToString(); | |
| 176 return; | |
| 177 } | |
| 178 bool new_is_offline = StateIsOffline(state); | |
| 179 { | |
| 180 base::AutoLock lock(is_offline_lock_); | |
| 181 if (is_offline_ != new_is_offline) | |
| 182 is_offline_ = new_is_offline; | |
| 183 else | |
| 184 return; | |
| 185 } | |
| 186 if (offline_state_initialized_.IsSignaled()) | |
| 187 notification_callback_.Run(); | |
| 188 } | |
| 189 | |
| 190 bool NetworkManagerApi::StateIsOffline(uint32 state) { | |
| 191 switch (state) { | |
| 192 case NM_LEGACY_STATE_CONNECTED: | |
| 193 case NM_STATE_CONNECTED_SITE: | |
| 194 case NM_STATE_CONNECTED_GLOBAL: | |
| 195 // Definitely connected | |
| 196 return false; | |
| 197 case NM_LEGACY_STATE_DISCONNECTED: | |
| 198 case NM_STATE_DISCONNECTED: | |
| 199 // Definitely disconnected | |
| 200 return true; | |
| 201 case NM_STATE_CONNECTED_LOCAL: | |
| 202 // Local networking only; I'm treating this as offline (keybuk) | |
| 203 return true; | |
| 204 case NM_LEGACY_STATE_CONNECTING: | |
| 205 case NM_STATE_DISCONNECTING: | |
| 206 case NM_STATE_CONNECTING: | |
| 207 // In-flight change to connection status currently underway | |
| 208 return true; | |
| 209 case NM_LEGACY_STATE_ASLEEP: | |
| 210 case NM_STATE_ASLEEP: | |
| 211 // Networking disabled or no devices on system | |
| 212 return true; | |
| 213 default: | |
| 214 // Unknown status | |
| 215 return false; | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 bool NetworkManagerApi::IsCurrentlyOffline() { | |
| 220 offline_state_initialized_.Wait(); | |
| 221 base::AutoLock lock(is_offline_lock_); | |
| 222 return is_offline_; | |
| 223 } | |
| 224 | |
| 225 class DNSWatchDelegate : public FilePathWatcher::Delegate { | 30 class DNSWatchDelegate : public FilePathWatcher::Delegate { |
| 226 public: | 31 public: |
| 227 explicit DNSWatchDelegate(const base::Closure& callback) | 32 explicit DNSWatchDelegate(const base::Closure& callback) |
| 228 : callback_(callback) {} | 33 : callback_(callback) {} |
| 229 virtual ~DNSWatchDelegate() {} | 34 virtual ~DNSWatchDelegate() {} |
| 230 // FilePathWatcher::Delegate interface | 35 // FilePathWatcher::Delegate interface |
| 231 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE; | 36 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE; |
| 232 virtual void OnFilePathError(const FilePath& path) OVERRIDE; | 37 virtual void OnFilePathError(const FilePath& path) OVERRIDE; |
| 233 private: | 38 private: |
| 234 base::Closure callback_; | 39 base::Closure callback_; |
| 235 DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate); | 40 DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate); |
| 236 }; | 41 }; |
| 237 | 42 |
| 238 void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) { | 43 void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) { |
| 239 // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange(). | 44 // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange(). |
| 240 callback_.Run(); | 45 callback_.Run(); |
| 241 } | 46 } |
| 242 | 47 |
| 243 void DNSWatchDelegate::OnFilePathError(const FilePath& path) { | 48 void DNSWatchDelegate::OnFilePathError(const FilePath& path) { |
| 244 LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value(); | 49 LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value(); |
| 245 } | 50 } |
| 246 | 51 |
| 247 } // namespace | 52 } // namespace |
| 248 | 53 |
| 249 class NetworkChangeNotifierLinux::Thread | 54 class NetworkChangeNotifierLinux::Thread |
| 250 : public base::Thread, public MessageLoopForIO::Watcher { | 55 : public base::Thread, public MessageLoopForIO::Watcher { |
| 251 public: | 56 public: |
| 252 explicit Thread(dbus::Bus* bus); | 57 Thread(); |
| 253 virtual ~Thread(); | 58 virtual ~Thread(); |
| 254 | 59 |
| 255 // MessageLoopForIO::Watcher: | 60 // MessageLoopForIO::Watcher: |
| 256 virtual void OnFileCanReadWithoutBlocking(int fd); | 61 virtual void OnFileCanReadWithoutBlocking(int fd); |
| 257 virtual void OnFileCanWriteWithoutBlocking(int /* fd */); | 62 virtual void OnFileCanWriteWithoutBlocking(int /* fd */); |
| 258 | 63 |
| 259 // Plumbing for NetworkChangeNotifier::IsCurrentlyOffline. | |
| 260 // Safe to call from any thread. | |
| 261 bool IsCurrentlyOffline() { | |
| 262 return network_manager_api_.IsCurrentlyOffline(); | |
| 263 } | |
| 264 | |
| 265 protected: | 64 protected: |
| 266 // base::Thread | 65 // base::Thread |
| 267 virtual void Init(); | 66 virtual void Init(); |
| 268 virtual void CleanUp(); | 67 virtual void CleanUp(); |
| 269 | 68 |
| 270 private: | 69 private: |
| 271 void NotifyObserversOfIPAddressChange() { | 70 void NotifyObserversOfIPAddressChange() { |
| 272 NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); | 71 NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); |
| 273 } | 72 } |
| 274 | 73 |
| 275 static void NotifyObserversOfDNSChange() { | 74 void NotifyObserversOfDNSChange() { |
| 276 NetworkChangeNotifier::NotifyObserversOfDNSChange(); | 75 NetworkChangeNotifier::NotifyObserversOfDNSChange(); |
| 277 } | 76 } |
| 278 | 77 |
| 279 static void NotifyObserversOfOnlineStateChange() { | |
| 280 NetworkChangeNotifier::NotifyObserversOfOnlineStateChange(); | |
| 281 } | |
| 282 | |
| 283 // Starts listening for netlink messages. Also handles the messages if there | 78 // Starts listening for netlink messages. Also handles the messages if there |
| 284 // are any available on the netlink socket. | 79 // are any available on the netlink socket. |
| 285 void ListenForNotifications(); | 80 void ListenForNotifications(); |
| 286 | 81 |
| 287 // Attempts to read from the netlink socket into |buf| of length |len|. | 82 // Attempts to read from the netlink socket into |buf| of length |len|. |
| 288 // Returns the bytes read on synchronous success and ERR_IO_PENDING if the | 83 // Returns the bytes read on synchronous success and ERR_IO_PENDING if the |
| 289 // recv() would block. Otherwise, it returns a net error code. | 84 // recv() would block. Otherwise, it returns a net error code. |
| 290 int ReadNotificationMessage(char* buf, size_t len); | 85 int ReadNotificationMessage(char* buf, size_t len); |
| 291 | 86 |
| 292 // The netlink socket descriptor. | 87 // The netlink socket descriptor. |
| 293 int netlink_fd_; | 88 int netlink_fd_; |
| 294 MessageLoopForIO::FileDescriptorWatcher netlink_watcher_; | 89 MessageLoopForIO::FileDescriptorWatcher netlink_watcher_; |
| 295 | 90 |
| 296 // Technically only needed for ChromeOS, but it's ugly to #ifdef out. | 91 // Technically only needed for ChromeOS, but it's ugly to #ifdef out. |
| 297 base::WeakPtrFactory<Thread> ptr_factory_; | 92 base::WeakPtrFactory<Thread> ptr_factory_; |
| 298 | 93 |
| 299 // Used to watch for changes to /etc/resolv.conf and /etc/hosts. | 94 // Used to watch for changes to /etc/resolv.conf and /etc/hosts. |
| 300 scoped_ptr<base::files::FilePathWatcher> resolv_file_watcher_; | 95 scoped_ptr<base::files::FilePathWatcher> resolv_file_watcher_; |
| 301 scoped_ptr<base::files::FilePathWatcher> hosts_file_watcher_; | 96 scoped_ptr<base::files::FilePathWatcher> hosts_file_watcher_; |
| 302 scoped_refptr<DNSWatchDelegate> file_watcher_delegate_; | 97 scoped_refptr<DNSWatchDelegate> file_watcher_delegate_; |
| 303 | 98 |
| 304 // Used to detect online/offline state changes. | |
| 305 NetworkManagerApi network_manager_api_; | |
| 306 | |
| 307 DISALLOW_COPY_AND_ASSIGN(Thread); | 99 DISALLOW_COPY_AND_ASSIGN(Thread); |
| 308 }; | 100 }; |
| 309 | 101 |
| 310 NetworkChangeNotifierLinux::Thread::Thread(dbus::Bus* bus) | 102 NetworkChangeNotifierLinux::Thread::Thread() |
| 311 : base::Thread("NetworkChangeNotifier"), | 103 : base::Thread("NetworkChangeNotifier"), |
| 312 netlink_fd_(kInvalidSocket), | 104 netlink_fd_(kInvalidSocket), |
| 313 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)), | 105 ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) { |
| 314 network_manager_api_( | |
| 315 base::Bind(&NetworkChangeNotifierLinux::Thread | |
| 316 ::NotifyObserversOfOnlineStateChange), | |
| 317 bus) { | |
| 318 } | 106 } |
| 319 | 107 |
| 320 NetworkChangeNotifierLinux::Thread::~Thread() { | 108 NetworkChangeNotifierLinux::Thread::~Thread() { |
| 321 DCHECK(!Thread::IsRunning()); | 109 DCHECK(!Thread::IsRunning()); |
| 322 } | 110 } |
| 323 | 111 |
| 324 void NetworkChangeNotifierLinux::Thread::Init() { | 112 void NetworkChangeNotifierLinux::Thread::Init() { |
| 325 resolv_file_watcher_.reset(new FilePathWatcher); | 113 resolv_file_watcher_.reset(new FilePathWatcher); |
| 326 hosts_file_watcher_.reset(new FilePathWatcher); | 114 hosts_file_watcher_.reset(new FilePathWatcher); |
| 327 file_watcher_delegate_ = new DNSWatchDelegate(base::Bind( | 115 file_watcher_delegate_ = new DNSWatchDelegate(base::Bind( |
| 328 &NetworkChangeNotifierLinux::Thread::NotifyObserversOfDNSChange)); | 116 &NetworkChangeNotifierLinux::Thread::NotifyObserversOfDNSChange, |
| 117 base::Unretained(this))); |
| 329 if (!resolv_file_watcher_->Watch( | 118 if (!resolv_file_watcher_->Watch( |
| 330 FilePath(FILE_PATH_LITERAL("/etc/resolv.conf")), | 119 FilePath(FILE_PATH_LITERAL("/etc/resolv.conf")), |
| 331 file_watcher_delegate_.get())) { | 120 file_watcher_delegate_.get())) { |
| 332 LOG(ERROR) << "Failed to setup watch for /etc/resolv.conf"; | 121 LOG(ERROR) << "Failed to setup watch for /etc/resolv.conf"; |
| 333 } | 122 } |
| 334 if (!hosts_file_watcher_->Watch(FilePath(FILE_PATH_LITERAL("/etc/hosts")), | 123 if (!hosts_file_watcher_->Watch(FilePath(FILE_PATH_LITERAL("/etc/hosts")), |
| 335 file_watcher_delegate_.get())) { | 124 file_watcher_delegate_.get())) { |
| 336 LOG(ERROR) << "Failed to setup watch for /etc/hosts"; | 125 LOG(ERROR) << "Failed to setup watch for /etc/hosts"; |
| 337 } | 126 } |
| 338 netlink_fd_ = InitializeNetlinkSocket(); | 127 netlink_fd_ = InitializeNetlinkSocket(); |
| 339 if (netlink_fd_ < 0) { | 128 if (netlink_fd_ < 0) { |
| 340 netlink_fd_ = kInvalidSocket; | 129 netlink_fd_ = kInvalidSocket; |
| 341 return; | 130 return; |
| 342 } | 131 } |
| 343 ListenForNotifications(); | 132 ListenForNotifications(); |
| 344 | |
| 345 network_manager_api_.Init(); | |
| 346 } | 133 } |
| 347 | 134 |
| 348 void NetworkChangeNotifierLinux::Thread::CleanUp() { | 135 void NetworkChangeNotifierLinux::Thread::CleanUp() { |
| 349 if (netlink_fd_ != kInvalidSocket) { | 136 if (netlink_fd_ != kInvalidSocket) { |
| 350 if (HANDLE_EINTR(close(netlink_fd_)) != 0) | 137 if (HANDLE_EINTR(close(netlink_fd_)) != 0) |
| 351 PLOG(ERROR) << "Failed to close socket"; | 138 PLOG(ERROR) << "Failed to close socket"; |
| 352 netlink_fd_ = kInvalidSocket; | 139 netlink_fd_ = kInvalidSocket; |
| 353 netlink_watcher_.StopWatchingFileDescriptor(); | 140 netlink_watcher_.StopWatchingFileDescriptor(); |
| 354 } | 141 } |
| 355 // Kill watchers early to make sure they won't try to call | 142 // Kill watchers early to make sure they won't try to call |
| 356 // into us via the delegate during destruction. | 143 // into us via the delegate during destruction. |
| 357 resolv_file_watcher_.reset(); | 144 resolv_file_watcher_.reset(); |
| 358 hosts_file_watcher_.reset(); | 145 hosts_file_watcher_.reset(); |
| 359 | |
| 360 network_manager_api_.CleanUp(); | |
| 361 } | 146 } |
| 362 | 147 |
| 363 void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) { | 148 void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) { |
| 364 DCHECK_EQ(fd, netlink_fd_); | 149 DCHECK_EQ(fd, netlink_fd_); |
| 365 ListenForNotifications(); | 150 ListenForNotifications(); |
| 366 } | 151 } |
| 367 | 152 |
| 368 void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking( | 153 void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking( |
| 369 int /* fd */) { | 154 int /* fd */) { |
| 370 NOTREACHED(); | 155 NOTREACHED(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 | 199 |
| 415 DCHECK_NE(rv, 0); | 200 DCHECK_NE(rv, 0); |
| 416 if (errno != EAGAIN && errno != EWOULDBLOCK) { | 201 if (errno != EAGAIN && errno != EWOULDBLOCK) { |
| 417 PLOG(DFATAL) << "recv"; | 202 PLOG(DFATAL) << "recv"; |
| 418 return ERR_FAILED; | 203 return ERR_FAILED; |
| 419 } | 204 } |
| 420 | 205 |
| 421 return ERR_IO_PENDING; | 206 return ERR_IO_PENDING; |
| 422 } | 207 } |
| 423 | 208 |
| 424 NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::Create() { | 209 NetworkChangeNotifierLinux::NetworkChangeNotifierLinux() |
| 425 return new NetworkChangeNotifierLinux(NULL); | 210 : notifier_thread_(new Thread) { |
| 426 } | |
| 427 | |
| 428 NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::CreateForTest( | |
| 429 dbus::Bus* bus) { | |
| 430 return new NetworkChangeNotifierLinux(bus); | |
| 431 } | |
| 432 | |
| 433 NetworkChangeNotifierLinux::NetworkChangeNotifierLinux(dbus::Bus* bus) | |
| 434 : notifier_thread_(new Thread(bus)) { | |
| 435 // We create this notifier thread because the notification implementation | 211 // We create this notifier thread because the notification implementation |
| 436 // needs a MessageLoopForIO, and there's no guarantee that | 212 // needs a MessageLoopForIO, and there's no guarantee that |
| 437 // MessageLoop::current() meets that criterion. | 213 // MessageLoop::current() meets that criterion. |
| 438 base::Thread::Options thread_options(MessageLoop::TYPE_IO, 0); | 214 base::Thread::Options thread_options(MessageLoop::TYPE_IO, 0); |
| 439 notifier_thread_->StartWithOptions(thread_options); | 215 notifier_thread_->StartWithOptions(thread_options); |
| 440 } | 216 } |
| 441 | 217 |
| 442 NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() { | 218 NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() { |
| 443 // Stopping from here allows us to sanity- check that the notifier | 219 // Stopping from here allows us to sanity- check that the notifier |
| 444 // thread shut down properly. | 220 // thread shut down properly. |
| 445 notifier_thread_->Stop(); | 221 notifier_thread_->Stop(); |
| 446 } | 222 } |
| 447 | 223 |
| 448 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { | 224 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { |
| 449 return notifier_thread_->IsCurrentlyOffline(); | 225 // TODO(eroman): http://crbug.com/53473 |
| 226 return false; |
| 450 } | 227 } |
| 451 | 228 |
| 452 } // namespace net | 229 } // namespace net |
| OLD | NEW |