diff options
author | adamk@chromium.org <adamk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-16 19:51:53 +0000 |
---|---|---|
committer | adamk@chromium.org <adamk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-16 19:51:53 +0000 |
commit | b383640dbf09a7696e65a8ebe50711562c9943b4 (patch) | |
tree | 9f1d74c24ceb995763f2943ffb987d29ca4712aa /net | |
parent | 75d0966eae4cc84e57a99fd5049d8644b93e6142 (diff) | |
download | chromium_src-b383640dbf09a7696e65a8ebe50711562c9943b4.zip chromium_src-b383640dbf09a7696e65a8ebe50711562c9943b4.tar.gz chromium_src-b383640dbf09a7696e65a8ebe50711562c9943b4.tar.bz2 |
Offline state detection for linux, using new D-Bus library.
BUG=53473
TEST=see attachment on bug 7469
Review URL: http://codereview.chromium.org/8249008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110344 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/DEPS | 1 | ||||
-rw-r--r-- | net/base/network_change_notifier.cc | 2 | ||||
-rw-r--r-- | net/base/network_change_notifier.h | 1 | ||||
-rw-r--r-- | net/base/network_change_notifier_linux.cc | 243 | ||||
-rw-r--r-- | net/base/network_change_notifier_linux.h | 10 | ||||
-rw-r--r-- | net/base/network_change_notifier_linux_unittest.cc | 227 | ||||
-rw-r--r-- | net/net.gyp | 15 |
7 files changed, 487 insertions, 12 deletions
@@ -1,5 +1,6 @@ include_rules = [ "+crypto", + "+dbus", "+jni", "+third_party/apple_apsl", "+third_party/libevent", diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 00e6f0d..ea4f96c 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc @@ -60,7 +60,7 @@ NetworkChangeNotifier* NetworkChangeNotifier::Create() { CHECK(false); return NULL; #elif defined(OS_LINUX) || defined(OS_ANDROID) - return new NetworkChangeNotifierLinux(); + return NetworkChangeNotifierLinux::Create(); #elif defined(OS_MACOSX) return new NetworkChangeNotifierMac(); #else diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h index 85fff2c9..94e23a9 100644 --- a/net/base/network_change_notifier.h +++ b/net/base/network_change_notifier.h @@ -136,6 +136,7 @@ class NET_EXPORT NetworkChangeNotifier { static void NotifyObserversOfDNSChange(); private: + friend class NetworkChangeNotifierLinuxTest; friend class NetworkChangeNotifierWinTest; // Allows a second NetworkChangeNotifier to be created for unit testing, so diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc index 1e6db14..95f54e2 100644 --- a/net/base/network_change_notifier_linux.cc +++ b/net/base/network_change_notifier_linux.cc @@ -1,6 +1,11 @@ // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// +// This implementation of NetworkChangeNotifier's offline state detection +// depends on D-Bus and NetworkManager, and is known to work on at least +// GNOME version 2.30. If D-Bus or NetworkManager are unavailable, this +// implementation will always behave as if it is online. #include "net/base/network_change_notifier_linux.h" @@ -15,7 +20,13 @@ #include "base/file_util.h" #include "base/files/file_path_watcher.h" #include "base/memory/weak_ptr.h" +#include "base/synchronization/lock.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/platform_thread.h" #include "base/threading/thread.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" #include "net/base/net_errors.h" #include "net/base/network_change_notifier_netlink_linux.h" @@ -27,6 +38,190 @@ namespace { const int kInvalidSocket = -1; +const char kNetworkManagerServiceName[] = "org.freedesktop.NetworkManager"; +const char kNetworkManagerPath[] = "/org/freedesktop/NetworkManager"; +const char kNetworkManagerInterface[] = "org.freedesktop.NetworkManager"; + +// http://projects.gnome.org/NetworkManager/developers/spec-08.html#type-NM_STATE +enum { + NM_LEGACY_STATE_UNKNOWN = 0, + NM_LEGACY_STATE_ASLEEP = 1, + NM_LEGACY_STATE_CONNECTING = 2, + NM_LEGACY_STATE_CONNECTED = 3, + NM_LEGACY_STATE_DISCONNECTED = 4 +}; + +// http://projects.gnome.org/NetworkManager/developers/migrating-to-09/spec.html#type-NM_STATE +enum { + NM_STATE_UNKNOWN = 0, + NM_STATE_ASLEEP = 10, + NM_STATE_DISCONNECTED = 20, + NM_STATE_DISCONNECTING = 30, + NM_STATE_CONNECTING = 40, + NM_STATE_CONNECTED_LOCAL = 50, + NM_STATE_CONNECTED_SITE = 60, + NM_STATE_CONNECTED_GLOBAL = 70 +}; + +// A wrapper around NetworkManager's D-Bus API. +class NetworkManagerApi { + public: + NetworkManagerApi(const base::Closure& notification_callback, dbus::Bus* bus) + : is_offline_(false), + offline_state_initialized_(true /*manual_reset*/, false), + notification_callback_(notification_callback), + helper_thread_id_(base::kInvalidThreadId), + ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)), + system_bus_(bus) { } + + ~NetworkManagerApi() { } + + // Should be called on a helper thread which must be of type IO. + void Init(); + + // Must be called by the helper thread's CleanUp() method. + void CleanUp(); + + // Implementation of NetworkChangeNotifierLinux::IsCurrentlyOffline(). + // Safe to call from any thread, but will block until Init() has completed. + bool IsCurrentlyOffline(); + + private: + // Callbacks for D-Bus API. + void OnStateChanged(dbus::Message* message); + + void OnResponse(dbus::Response* response) { + OnStateChanged(response); + offline_state_initialized_.Signal(); + } + + void OnSignaled(dbus::Signal* signal) { + OnStateChanged(signal); + } + + void OnConnected(const std::string&, const std::string&, bool success) { + if (!success) { + DLOG(WARNING) << "Failed to set up offline state detection"; + offline_state_initialized_.Signal(); + } + } + + // Converts a NetworkManager state uint to a bool. + static bool StateIsOffline(uint32 state); + + bool is_offline_; + base::Lock is_offline_lock_; + base::WaitableEvent offline_state_initialized_; + + base::Closure notification_callback_; + + base::PlatformThreadId helper_thread_id_; + + base::WeakPtrFactory<NetworkManagerApi> ptr_factory_; + + scoped_refptr<dbus::Bus> system_bus_; + + DISALLOW_COPY_AND_ASSIGN(NetworkManagerApi); +}; + +void NetworkManagerApi::Init() { + // D-Bus requires an IO MessageLoop. + DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_IO); + helper_thread_id_ = base::PlatformThread::CurrentId(); + + if (!system_bus_) { + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SYSTEM; + options.connection_type = dbus::Bus::PRIVATE; + system_bus_ = new dbus::Bus(options); + } + + dbus::ObjectProxy* proxy = + system_bus_->GetObjectProxy(kNetworkManagerServiceName, + kNetworkManagerPath); + + // Get the initial state asynchronously. + dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get"); + dbus::MessageWriter builder(&method_call); + builder.AppendString(kNetworkManagerInterface); + builder.AppendString("State"); + proxy->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&NetworkManagerApi::OnResponse, ptr_factory_.GetWeakPtr())); + + // And sign up for notifications. + proxy->ConnectToSignal( + kNetworkManagerInterface, + "StateChanged", + base::Bind(&NetworkManagerApi::OnSignaled, ptr_factory_.GetWeakPtr()), + base::Bind(&NetworkManagerApi::OnConnected, ptr_factory_.GetWeakPtr())); +} + +void NetworkManagerApi::CleanUp() { + DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); + ptr_factory_.InvalidateWeakPtrs(); +} + +void NetworkManagerApi::OnStateChanged(dbus::Message* message) { + DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); + if (!message) { + DLOG(WARNING) << "No response received for initial state request"; + return; + } + dbus::MessageReader reader(message); + uint32 state = 0; + if (!reader.HasMoreData() || !reader.PopUint32(&state)) { + DLOG(WARNING) << "Unexpected response for NetworkManager State request: " + << message->ToString(); + return; + } + bool new_is_offline = StateIsOffline(state); + { + base::AutoLock lock(is_offline_lock_); + if (is_offline_ != new_is_offline) + is_offline_ = new_is_offline; + else + return; + } + if (offline_state_initialized_.IsSignaled()) + notification_callback_.Run(); +} + +bool NetworkManagerApi::StateIsOffline(uint32 state) { + switch (state) { + case NM_LEGACY_STATE_CONNECTED: + case NM_STATE_CONNECTED_SITE: + case NM_STATE_CONNECTED_GLOBAL: + // Definitely connected + return false; + case NM_LEGACY_STATE_DISCONNECTED: + case NM_STATE_DISCONNECTED: + // Definitely disconnected + return true; + case NM_STATE_CONNECTED_LOCAL: + // Local networking only; I'm treating this as offline (keybuk) + return true; + case NM_LEGACY_STATE_CONNECTING: + case NM_STATE_DISCONNECTING: + case NM_STATE_CONNECTING: + // In-flight change to connection status currently underway + return true; + case NM_LEGACY_STATE_ASLEEP: + case NM_STATE_ASLEEP: + // Networking disabled or no devices on system + return true; + default: + // Unknown status + return false; + } +} + +bool NetworkManagerApi::IsCurrentlyOffline() { + offline_state_initialized_.Wait(); + base::AutoLock lock(is_offline_lock_); + return is_offline_; +} + class DNSWatchDelegate : public FilePathWatcher::Delegate { public: explicit DNSWatchDelegate(const base::Closure& callback) @@ -54,13 +249,19 @@ void DNSWatchDelegate::OnFilePathError(const FilePath& path) { class NetworkChangeNotifierLinux::Thread : public base::Thread, public MessageLoopForIO::Watcher { public: - Thread(); + explicit Thread(dbus::Bus* bus); virtual ~Thread(); // MessageLoopForIO::Watcher: virtual void OnFileCanReadWithoutBlocking(int fd); virtual void OnFileCanWriteWithoutBlocking(int /* fd */); + // Plumbing for NetworkChangeNotifier::IsCurrentlyOffline. + // Safe to call from any thread. + bool IsCurrentlyOffline() { + return network_manager_api_.IsCurrentlyOffline(); + } + protected: // base::Thread virtual void Init(); @@ -71,10 +272,14 @@ class NetworkChangeNotifierLinux::Thread NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); } - void NotifyObserversOfDNSChange() { + static void NotifyObserversOfDNSChange() { NetworkChangeNotifier::NotifyObserversOfDNSChange(); } + static void NotifyObserversOfOnlineStateChange() { + NetworkChangeNotifier::NotifyObserversOfOnlineStateChange(); + } + // Starts listening for netlink messages. Also handles the messages if there // are any available on the netlink socket. void ListenForNotifications(); @@ -96,13 +301,20 @@ class NetworkChangeNotifierLinux::Thread scoped_ptr<base::files::FilePathWatcher> hosts_file_watcher_; scoped_refptr<DNSWatchDelegate> file_watcher_delegate_; + // Used to detect online/offline state changes. + NetworkManagerApi network_manager_api_; + DISALLOW_COPY_AND_ASSIGN(Thread); }; -NetworkChangeNotifierLinux::Thread::Thread() +NetworkChangeNotifierLinux::Thread::Thread(dbus::Bus* bus) : base::Thread("NetworkChangeNotifier"), netlink_fd_(kInvalidSocket), - ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) { + ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)), + network_manager_api_( + base::Bind(&NetworkChangeNotifierLinux::Thread + ::NotifyObserversOfOnlineStateChange), + bus) { } NetworkChangeNotifierLinux::Thread::~Thread() { @@ -113,8 +325,7 @@ void NetworkChangeNotifierLinux::Thread::Init() { resolv_file_watcher_.reset(new FilePathWatcher); hosts_file_watcher_.reset(new FilePathWatcher); file_watcher_delegate_ = new DNSWatchDelegate(base::Bind( - &NetworkChangeNotifierLinux::Thread::NotifyObserversOfDNSChange, - base::Unretained(this))); + &NetworkChangeNotifierLinux::Thread::NotifyObserversOfDNSChange)); if (!resolv_file_watcher_->Watch( FilePath(FILE_PATH_LITERAL("/etc/resolv.conf")), file_watcher_delegate_.get())) { @@ -130,6 +341,8 @@ void NetworkChangeNotifierLinux::Thread::Init() { return; } ListenForNotifications(); + + network_manager_api_.Init(); } void NetworkChangeNotifierLinux::Thread::CleanUp() { @@ -143,6 +356,8 @@ void NetworkChangeNotifierLinux::Thread::CleanUp() { // into us via the delegate during destruction. resolv_file_watcher_.reset(); hosts_file_watcher_.reset(); + + network_manager_api_.CleanUp(); } void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) { @@ -206,8 +421,17 @@ int NetworkChangeNotifierLinux::Thread::ReadNotificationMessage( return ERR_IO_PENDING; } -NetworkChangeNotifierLinux::NetworkChangeNotifierLinux() - : notifier_thread_(new Thread) { +NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::Create() { + return new NetworkChangeNotifierLinux(NULL); +} + +NetworkChangeNotifierLinux* NetworkChangeNotifierLinux::CreateForTest( + dbus::Bus* bus) { + return new NetworkChangeNotifierLinux(bus); +} + +NetworkChangeNotifierLinux::NetworkChangeNotifierLinux(dbus::Bus* bus) + : notifier_thread_(new Thread(bus)) { // We create this notifier thread because the notification implementation // needs a MessageLoopForIO, and there's no guarantee that // MessageLoop::current() meets that criterion. @@ -222,8 +446,7 @@ NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() { } bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { - // TODO(eroman): http://crbug.com/53473 - return false; + return notifier_thread_->IsCurrentlyOffline(); } } // namespace net diff --git a/net/base/network_change_notifier_linux.h b/net/base/network_change_notifier_linux.h index 89b0545..083454f 100644 --- a/net/base/network_change_notifier_linux.h +++ b/net/base/network_change_notifier_linux.h @@ -11,15 +11,23 @@ #include "base/memory/scoped_ptr.h" #include "net/base/network_change_notifier.h" +namespace dbus { +class Bus; +} + namespace net { class NetworkChangeNotifierLinux : public NetworkChangeNotifier { public: - NetworkChangeNotifierLinux(); + static NetworkChangeNotifierLinux* Create(); + + // Unittests inject a mock bus. + static NetworkChangeNotifierLinux* CreateForTest(dbus::Bus* bus); private: class Thread; + explicit NetworkChangeNotifierLinux(dbus::Bus* bus); virtual ~NetworkChangeNotifierLinux(); // NetworkChangeNotifier: diff --git a/net/base/network_change_notifier_linux_unittest.cc b/net/base/network_change_notifier_linux_unittest.cc new file mode 100644 index 0000000..c97092a --- /dev/null +++ b/net/base/network_change_notifier_linux_unittest.cc @@ -0,0 +1,227 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/network_change_notifier_linux.h" + +#include "base/bind.h" +#include "base/message_loop_proxy.h" +#include "base/synchronization/waitable_event.h" +#include "dbus/mock_bus.h" +#include "dbus/mock_object_proxy.h" +#include "dbus/message.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +using testing::_; +using testing::DoAll; +using testing::InvokeWithoutArgs; +using testing::Return; +using testing::SaveArg; + +class NetworkChangeNotifierLinuxTest : public testing::Test { + protected: + // A subset of the NetworkManager-defined constants used in + // the tests below. See network_change_notifier_linux.cc + // for the full list. + enum { + NM_STATE_DISCONNECTED = 20, + NM_STATE_DISCONNECTING = 30, + NM_STATE_CONNECTED_SITE = 70, + NM_STATE_CONNECTED_GLOBAL = 70 + }; + + NetworkChangeNotifierLinuxTest() + : initialized_(false, false) {} + + virtual void SetUp() { + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SYSTEM; + mock_bus_ = new dbus::MockBus(options); + + mock_object_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(), + "service_name", + "service_path"); + EXPECT_CALL(*mock_bus_, GetObjectProxy(_, _)) + .WillOnce(Return(mock_object_proxy_.get())); + + EXPECT_CALL(*mock_object_proxy_, CallMethod(_, _, _)) + .WillOnce(SaveArg<2>(&response_callback_)); + EXPECT_CALL(*mock_object_proxy_, ConnectToSignal(_, _, _, _)) + .WillOnce( + DoAll( + SaveArg<2>(&signal_callback_), + InvokeWithoutArgs( + this, + &NetworkChangeNotifierLinuxTest::Initialize))); + + notifier_.reset(NetworkChangeNotifierLinux::CreateForTest(mock_bus_.get())); + + initialized_.Wait(); + } + + void Initialize() { + notifier_thread_proxy_ = base::MessageLoopProxy::current(); + initialized_.Signal(); + } + + void RunOnNotifierThread(const base::Closure& callback) { + base::WaitableEvent event(false, false); + notifier_thread_proxy_->PostTask(FROM_HERE, base::Bind( + &RunOnNotifierThreadHelper, callback, &event)); + event.Wait(); + // Run any tasks queued on the main thread, e.g. by + // ObserverListThreadSafe. + MessageLoop::current()->RunAllPending(); + } + + void SendResponse(uint32 state) { + scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); + dbus::MessageWriter writer(response.get()); + writer.AppendUint32(state); + RunOnNotifierThread(base::Bind(response_callback_, response.get())); + } + + void SendSignal(uint32 state) { + dbus::Signal signal("org.freedesktop.NetworkManager", "StateChanged"); + dbus::MessageWriter writer(&signal); + writer.AppendUint32(state); + RunOnNotifierThread(base::Bind(signal_callback_, &signal)); + } + + dbus::ObjectProxy::ResponseCallback response_callback_; + dbus::ObjectProxy::SignalCallback signal_callback_; + + // Allows creating a new NetworkChangeNotifier. Must be created before + // |notifier_| and destroyed after it to avoid DCHECK failures. + NetworkChangeNotifier::DisableForTest disable_for_test_; + scoped_ptr<NetworkChangeNotifier> notifier_; + + private: + static void RunOnNotifierThreadHelper(const base::Closure& callback, + base::WaitableEvent* event) { + callback.Run(); + event->Signal(); + } + + base::WaitableEvent initialized_; + + // Valid only after initialized_ is signaled. + scoped_refptr<base::MessageLoopProxy> notifier_thread_proxy_; + + scoped_refptr<dbus::MockBus> mock_bus_; + scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_; +}; + +namespace { + +class OfflineObserver : public NetworkChangeNotifier::OnlineStateObserver { + public: + OfflineObserver() + : notification_count(0), + last_online_value(true) { + NetworkChangeNotifier::AddOnlineStateObserver(this); + } + + ~OfflineObserver() { + NetworkChangeNotifier::RemoveOnlineStateObserver(this); + } + + virtual void OnOnlineStateChanged(bool online) OVERRIDE { + notification_count++; + last_online_value = online; + } + + int notification_count; + bool last_online_value; +}; + +TEST_F(NetworkChangeNotifierLinuxTest, Offline) { + SendResponse(NM_STATE_DISCONNECTED); + EXPECT_TRUE(NetworkChangeNotifier::IsOffline()); +} + +TEST_F(NetworkChangeNotifierLinuxTest, Online) { + SendResponse(NM_STATE_CONNECTED_GLOBAL); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); +} + +TEST_F(NetworkChangeNotifierLinuxTest, OfflineThenOnline) { + OfflineObserver observer; + + SendResponse(NM_STATE_DISCONNECTED); + EXPECT_TRUE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(0, observer.notification_count); + + SendSignal(NM_STATE_CONNECTED_GLOBAL); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(1, observer.notification_count); + EXPECT_TRUE(observer.last_online_value); +} + +TEST_F(NetworkChangeNotifierLinuxTest, MultipleStateChanges) { + OfflineObserver observer; + + SendResponse(NM_STATE_CONNECTED_GLOBAL); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(0, observer.notification_count); + + SendSignal(NM_STATE_DISCONNECTED); + EXPECT_TRUE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(1, observer.notification_count); + EXPECT_FALSE(observer.last_online_value); + + SendSignal(NM_STATE_CONNECTED_GLOBAL); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(2, observer.notification_count); + EXPECT_TRUE(observer.last_online_value); +} + +TEST_F(NetworkChangeNotifierLinuxTest, IgnoreContinuedOnlineState) { + OfflineObserver observer; + + SendResponse(NM_STATE_CONNECTED_SITE); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(0, observer.notification_count); + + SendSignal(NM_STATE_CONNECTED_GLOBAL); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(0, observer.notification_count); +} + +TEST_F(NetworkChangeNotifierLinuxTest, IgnoreContinuedOfflineState) { + OfflineObserver observer; + + SendResponse(NM_STATE_DISCONNECTING); + EXPECT_TRUE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(0, observer.notification_count); + + SendSignal(NM_STATE_DISCONNECTED); + EXPECT_TRUE(NetworkChangeNotifier::IsOffline()); + EXPECT_EQ(0, observer.notification_count); +} + +TEST_F(NetworkChangeNotifierLinuxTest, NullResponse) { + RunOnNotifierThread(base::Bind( + response_callback_, static_cast<dbus::Response*>(NULL))); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); +} + +TEST_F(NetworkChangeNotifierLinuxTest, EmptyResponse) { + scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); + RunOnNotifierThread(base::Bind(response_callback_, response.get())); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); +} + +TEST_F(NetworkChangeNotifierLinuxTest, InvalidResponse) { + scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); + dbus::MessageWriter writer(response.get()); + writer.AppendUint16(20); // Uint16 instead of the expected Uint32 + RunOnNotifierThread(base::Bind(response_callback_, response.get())); + EXPECT_FALSE(NetworkChangeNotifier::IsOffline()); +} + +} // namespace +} // namespace net diff --git a/net/net.gyp b/net/net.gyp index 628bb69..e0b467c 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -939,6 +939,13 @@ ], }, ], + [ 'OS == "linux"', { + 'dependencies': [ + '../build/linux/system.gyp:dbus', + '../dbus/dbus.gyp:dbus', + ], + }, + ], ], }, { @@ -989,6 +996,7 @@ 'base/net_log_unittest.cc', 'base/net_log_unittest.h', 'base/net_util_unittest.cc', + 'base/network_change_notifier_linux_unittest.cc', 'base/network_change_notifier_win_unittest.cc', 'base/origin_bound_cert_service_unittest.cc', 'base/pem_tokenizer_unittest.cc', @@ -1224,6 +1232,13 @@ ], }, ], + [ 'OS == "linux"', { + 'dependencies': [ + '../build/linux/system.gyp:dbus', + '../dbus/dbus.gyp:dbus_test_support', + ], + }, + ], ], }, { |