| 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 // | 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" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 | 81 |
| 82 // Must be called by the helper thread's CleanUp() method. | 82 // Must be called by the helper thread's CleanUp() method. |
| 83 void CleanUp(); | 83 void CleanUp(); |
| 84 | 84 |
| 85 // Implementation of NetworkChangeNotifierLinux::IsCurrentlyOffline(). | 85 // Implementation of NetworkChangeNotifierLinux::IsCurrentlyOffline(). |
| 86 // Safe to call from any thread, but will block until Init() has completed. | 86 // Safe to call from any thread, but will block until Init() has completed. |
| 87 bool IsCurrentlyOffline(); | 87 bool IsCurrentlyOffline(); |
| 88 | 88 |
| 89 private: | 89 private: |
| 90 // Callbacks for D-Bus API. | 90 // Callbacks for D-Bus API. |
| 91 void OnStateChanged(dbus::Message* message); | 91 void OnInitialResponse(dbus::Response* response) { |
| 92 | 92 HandleResponse(response); |
| 93 void OnResponse(dbus::Response* response) { | |
| 94 OnStateChanged(response); | |
| 95 offline_state_initialized_.Signal(); | 93 offline_state_initialized_.Signal(); |
| 96 } | 94 } |
| 97 | 95 |
| 98 void OnSignaled(dbus::Signal* signal) { | 96 void OnSignaled(dbus::Signal* signal); |
| 99 OnStateChanged(signal); | |
| 100 } | |
| 101 | 97 |
| 102 void OnConnected(const std::string&, const std::string&, bool success) { | 98 void OnConnected(const std::string&, const std::string&, bool success) { |
| 103 if (!success) { | 99 if (!success) { |
| 104 DLOG(WARNING) << "Failed to set up offline state detection"; | 100 DLOG(WARNING) << "Failed to set up offline state detection"; |
| 105 offline_state_initialized_.Signal(); | 101 offline_state_initialized_.Signal(); |
| 106 } | 102 } |
| 107 } | 103 } |
| 108 | 104 |
| 105 // Helper for OnInitialResponse. |
| 106 void HandleResponse(dbus::Response* response); |
| 107 |
| 109 // Converts a NetworkManager state uint to a bool. | 108 // Converts a NetworkManager state uint to a bool. |
| 110 static bool StateIsOffline(uint32 state); | 109 static bool StateIsOffline(uint32 state); |
| 111 | 110 |
| 112 bool is_offline_; | 111 bool is_offline_; |
| 113 base::Lock is_offline_lock_; | 112 base::Lock is_offline_lock_; |
| 114 base::WaitableEvent offline_state_initialized_; | 113 base::WaitableEvent offline_state_initialized_; |
| 115 | 114 |
| 116 base::Closure notification_callback_; | 115 base::Closure notification_callback_; |
| 117 | 116 |
| 118 base::PlatformThreadId helper_thread_id_; | 117 base::PlatformThreadId helper_thread_id_; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 140 system_bus_->GetObjectProxy(kNetworkManagerServiceName, | 139 system_bus_->GetObjectProxy(kNetworkManagerServiceName, |
| 141 kNetworkManagerPath); | 140 kNetworkManagerPath); |
| 142 | 141 |
| 143 // Get the initial state asynchronously. | 142 // Get the initial state asynchronously. |
| 144 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get"); | 143 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get"); |
| 145 dbus::MessageWriter builder(&method_call); | 144 dbus::MessageWriter builder(&method_call); |
| 146 builder.AppendString(kNetworkManagerInterface); | 145 builder.AppendString(kNetworkManagerInterface); |
| 147 builder.AppendString("State"); | 146 builder.AppendString("State"); |
| 148 proxy->CallMethod( | 147 proxy->CallMethod( |
| 149 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 148 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 150 base::Bind(&NetworkManagerApi::OnResponse, ptr_factory_.GetWeakPtr())); | 149 base::Bind(&NetworkManagerApi::OnInitialResponse, |
| 150 ptr_factory_.GetWeakPtr())); |
| 151 | 151 |
| 152 // And sign up for notifications. | 152 // And sign up for notifications. |
| 153 proxy->ConnectToSignal( | 153 proxy->ConnectToSignal( |
| 154 kNetworkManagerInterface, | 154 kNetworkManagerInterface, |
| 155 "StateChanged", | 155 "StateChanged", |
| 156 base::Bind(&NetworkManagerApi::OnSignaled, ptr_factory_.GetWeakPtr()), | 156 base::Bind(&NetworkManagerApi::OnSignaled, ptr_factory_.GetWeakPtr()), |
| 157 base::Bind(&NetworkManagerApi::OnConnected, ptr_factory_.GetWeakPtr())); | 157 base::Bind(&NetworkManagerApi::OnConnected, ptr_factory_.GetWeakPtr())); |
| 158 } | 158 } |
| 159 | 159 |
| 160 void NetworkManagerApi::CleanUp() { | 160 void NetworkManagerApi::CleanUp() { |
| 161 DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); | 161 DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); |
| 162 ptr_factory_.InvalidateWeakPtrs(); | 162 ptr_factory_.InvalidateWeakPtrs(); |
| 163 } | 163 } |
| 164 | 164 |
| 165 void NetworkManagerApi::OnStateChanged(dbus::Message* message) { | 165 void NetworkManagerApi::HandleResponse(dbus::Response* response) { |
| 166 DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); | 166 DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); |
| 167 if (!message) { | 167 if (!response) { |
| 168 DLOG(WARNING) << "No response received for initial state request"; | 168 DLOG(WARNING) << "No response received for initial state request"; |
| 169 return; | 169 return; |
| 170 } | 170 } |
| 171 dbus::MessageReader reader(message); | 171 dbus::MessageReader reader(response); |
| 172 uint32 state = 0; | 172 uint32 state = 0; |
| 173 if (!reader.HasMoreData() || !reader.PopUint32(&state)) { | 173 if (!reader.PopVariantOfUint32(&state)) { |
| 174 DLOG(WARNING) << "Unexpected response for NetworkManager State request: " | 174 DLOG(WARNING) << "Unexpected response for NetworkManager State request: " |
| 175 << message->ToString(); | 175 << response->ToString(); |
| 176 return; |
| 177 } |
| 178 { |
| 179 base::AutoLock lock(is_offline_lock_); |
| 180 is_offline_ = StateIsOffline(state); |
| 181 } |
| 182 } |
| 183 |
| 184 void NetworkManagerApi::OnSignaled(dbus::Signal* signal) { |
| 185 DCHECK_EQ(helper_thread_id_, base::PlatformThread::CurrentId()); |
| 186 dbus::MessageReader reader(signal); |
| 187 uint32 state = 0; |
| 188 if (!reader.PopUint32(&state)) { |
| 189 DLOG(WARNING) << "Unexpected signal for NetworkManager StateChanged: " |
| 190 << signal->ToString(); |
| 176 return; | 191 return; |
| 177 } | 192 } |
| 178 bool new_is_offline = StateIsOffline(state); | 193 bool new_is_offline = StateIsOffline(state); |
| 179 { | 194 { |
| 180 base::AutoLock lock(is_offline_lock_); | 195 base::AutoLock lock(is_offline_lock_); |
| 181 if (is_offline_ != new_is_offline) | 196 if (is_offline_ != new_is_offline) |
| 182 is_offline_ = new_is_offline; | 197 is_offline_ = new_is_offline; |
| 183 else | 198 else |
| 184 return; | 199 return; |
| 185 } | 200 } |
| 186 if (offline_state_initialized_.IsSignaled()) | 201 notification_callback_.Run(); |
| 187 notification_callback_.Run(); | |
| 188 } | 202 } |
| 189 | 203 |
| 190 bool NetworkManagerApi::StateIsOffline(uint32 state) { | 204 bool NetworkManagerApi::StateIsOffline(uint32 state) { |
| 191 switch (state) { | 205 switch (state) { |
| 192 case NM_LEGACY_STATE_CONNECTED: | 206 case NM_LEGACY_STATE_CONNECTED: |
| 193 case NM_STATE_CONNECTED_SITE: | 207 case NM_STATE_CONNECTED_SITE: |
| 194 case NM_STATE_CONNECTED_GLOBAL: | 208 case NM_STATE_CONNECTED_GLOBAL: |
| 195 // Definitely connected | 209 // Definitely connected |
| 196 return false; | 210 return false; |
| 197 case NM_LEGACY_STATE_DISCONNECTED: | 211 case NM_LEGACY_STATE_DISCONNECTED: |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // Stopping from here allows us to sanity- check that the notifier | 457 // Stopping from here allows us to sanity- check that the notifier |
| 444 // thread shut down properly. | 458 // thread shut down properly. |
| 445 notifier_thread_->Stop(); | 459 notifier_thread_->Stop(); |
| 446 } | 460 } |
| 447 | 461 |
| 448 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { | 462 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { |
| 449 return notifier_thread_->IsCurrentlyOffline(); | 463 return notifier_thread_->IsCurrentlyOffline(); |
| 450 } | 464 } |
| 451 | 465 |
| 452 } // namespace net | 466 } // namespace net |
| OLD | NEW |