| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/extensions/api/networking_private/networking_private_li
nux.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "base/callback.h" | |
| 10 #include "base/message_loop/message_loop.h" | |
| 11 #include "base/strings/string16.h" | |
| 12 #include "base/strings/string_split.h" | |
| 13 #include "base/strings/utf_string_conversions.h" | |
| 14 #include "base/threading/sequenced_worker_pool.h" | |
| 15 #include "chrome/browser/extensions/api/networking_private/network_config_dbus_c
onstants_linux.h" | |
| 16 #include "chrome/browser/extensions/api/networking_private/networking_private_ap
i.h" | |
| 17 #include "chrome/browser/extensions/api/networking_private/networking_private_de
legate_observer.h" | |
| 18 #include "components/onc/onc_constants.h" | |
| 19 #include "content/public/browser/browser_context.h" | |
| 20 #include "content/public/browser/browser_thread.h" | |
| 21 #include "dbus/bus.h" | |
| 22 #include "dbus/message.h" | |
| 23 #include "dbus/object_path.h" | |
| 24 #include "dbus/object_proxy.h" | |
| 25 | |
| 26 //////////////////////////////////////////////////////////////////////////////// | |
| 27 | |
| 28 namespace extensions { | |
| 29 | |
| 30 namespace { | |
| 31 // Access Point info strings. | |
| 32 const char kAccessPointInfoName[] = "Name"; | |
| 33 const char kAccessPointInfoGuid[] = "GUID"; | |
| 34 const char kAccessPointInfoConnectable[] = "Connectable"; | |
| 35 const char kAccessPointInfoConnectionState[] = "ConnectionState"; | |
| 36 const char kAccessPointInfoType[] = "Type"; | |
| 37 const char kAccessPointInfoTypeWifi[] = "WiFi"; | |
| 38 const char kAccessPointInfoWifiSignalStrengthDotted[] = "WiFi.SignalStrength"; | |
| 39 const char kAccessPointInfoWifiSecurityDotted[] = "WiFi.Security"; | |
| 40 | |
| 41 // Access point security type strings. | |
| 42 const char kAccessPointSecurityNone[] = "None"; | |
| 43 const char kAccessPointSecurityUnknown[] = "Unknown"; | |
| 44 const char kAccessPointSecurityWpaPsk[] = "WPA-PSK"; | |
| 45 const char kAccessPointSecurity9021X[] = "WEP-8021X"; | |
| 46 | |
| 47 // Parses the GUID which contains 3 pieces of relevant information. The | |
| 48 // object path to the network device, the object path of the access point, | |
| 49 // and the ssid. | |
| 50 bool ParseNetworkGuid(const std::string& guid, | |
| 51 std::string* device_path, | |
| 52 std::string* access_point_path, | |
| 53 std::string* ssid) { | |
| 54 std::vector<std::string> guid_parts; | |
| 55 | |
| 56 base::SplitString(guid, '|', &guid_parts); | |
| 57 | |
| 58 if (guid_parts.size() != 3) { | |
| 59 return false; | |
| 60 } | |
| 61 | |
| 62 *device_path = guid_parts[0]; | |
| 63 *access_point_path = guid_parts[1]; | |
| 64 *ssid = guid_parts[2]; | |
| 65 | |
| 66 if (device_path->empty() || access_point_path->empty() || ssid->empty()) { | |
| 67 return false; | |
| 68 } | |
| 69 | |
| 70 return true; | |
| 71 } | |
| 72 | |
| 73 // Simplified helper to parse the SSID from the GUID. | |
| 74 bool GuidToSsid(const std::string& guid, std::string* ssid) { | |
| 75 std::string unused_1; | |
| 76 std::string unused_2; | |
| 77 return ParseNetworkGuid(guid, &unused_1, &unused_2, ssid); | |
| 78 } | |
| 79 | |
| 80 // Iterates over the map cloning the contained networks to a | |
| 81 // list then returns the list. | |
| 82 scoped_ptr<base::ListValue> CopyNetworkMapToList( | |
| 83 const NetworkingPrivateLinux::NetworkMap& network_map) { | |
| 84 scoped_ptr<base::ListValue> network_list(new base::ListValue); | |
| 85 | |
| 86 for (const auto& network : network_map) { | |
| 87 network_list->Append(network.second->DeepCopy()); | |
| 88 } | |
| 89 | |
| 90 return network_list.Pass(); | |
| 91 } | |
| 92 | |
| 93 // Constructs a network guid from its constituent parts. | |
| 94 std::string ConstructNetworkGuid(const dbus::ObjectPath& device_path, | |
| 95 const dbus::ObjectPath& access_point_path, | |
| 96 const std::string& ssid) { | |
| 97 return device_path.value() + "|" + access_point_path.value() + "|" + ssid; | |
| 98 } | |
| 99 | |
| 100 // Logs that the method is not implemented and reports |kErrorNotSupported| | |
| 101 // to the failure callback. | |
| 102 void ReportNotSupported( | |
| 103 const std::string& method_name, | |
| 104 const NetworkingPrivateDelegate::FailureCallback& failure_callback) { | |
| 105 LOG(WARNING) << method_name << " is not supported"; | |
| 106 failure_callback.Run(extensions::networking_private::kErrorNotSupported); | |
| 107 } | |
| 108 | |
| 109 // Fires the appropriate callback when the network connect operation succeeds | |
| 110 // or fails. | |
| 111 void OnNetworkConnectOperationCompleted( | |
| 112 scoped_ptr<std::string> error, | |
| 113 const NetworkingPrivateDelegate::VoidCallback& success_callback, | |
| 114 const NetworkingPrivateDelegate::FailureCallback& failure_callback) { | |
| 115 if (!error->empty()) { | |
| 116 failure_callback.Run(*error); | |
| 117 return; | |
| 118 } | |
| 119 success_callback.Run(); | |
| 120 } | |
| 121 | |
| 122 // Fires the appropriate callback when the network properties are returned | |
| 123 // from the |dbus_thread_|. | |
| 124 void GetCachedNetworkPropertiesCallback( | |
| 125 scoped_ptr<std::string> error, | |
| 126 scoped_ptr<base::DictionaryValue> properties, | |
| 127 const NetworkingPrivateDelegate::DictionaryCallback& success_callback, | |
| 128 const NetworkingPrivateDelegate::FailureCallback& failure_callback) { | |
| 129 if (!error->empty()) { | |
| 130 failure_callback.Run(*error); | |
| 131 return; | |
| 132 } | |
| 133 success_callback.Run(properties.Pass()); | |
| 134 } | |
| 135 | |
| 136 } // namespace | |
| 137 | |
| 138 NetworkingPrivateLinux::NetworkingPrivateLinux( | |
| 139 content::BrowserContext* browser_context, | |
| 140 scoped_ptr<VerifyDelegate> verify_delegate) | |
| 141 : NetworkingPrivateDelegate(verify_delegate.Pass()), | |
| 142 browser_context_(browser_context), | |
| 143 dbus_thread_("Networking Private DBus"), | |
| 144 network_manager_proxy_(NULL) { | |
| 145 base::Thread::Options thread_options(base::MessageLoop::Type::TYPE_IO, 0); | |
| 146 | |
| 147 dbus_thread_.StartWithOptions(thread_options); | |
| 148 dbus_thread_.task_runner()->PostTask( | |
| 149 FROM_HERE, | |
| 150 base::Bind(&NetworkingPrivateLinux::Initialize, base::Unretained(this))); | |
| 151 } | |
| 152 | |
| 153 NetworkingPrivateLinux::~NetworkingPrivateLinux() { | |
| 154 dbus_thread_.Stop(); | |
| 155 } | |
| 156 | |
| 157 void NetworkingPrivateLinux::AssertOnDBusThread() { | |
| 158 DCHECK(dbus_task_runner_->RunsTasksOnCurrentThread()); | |
| 159 } | |
| 160 | |
| 161 void NetworkingPrivateLinux::Initialize() { | |
| 162 dbus_task_runner_ = dbus_thread_.task_runner(); | |
| 163 // This has to be called after the task runner is initialized. | |
| 164 AssertOnDBusThread(); | |
| 165 | |
| 166 dbus::Bus::Options dbus_options; | |
| 167 dbus_options.bus_type = dbus::Bus::SYSTEM; | |
| 168 dbus_options.connection_type = dbus::Bus::PRIVATE; | |
| 169 dbus_options.dbus_task_runner = dbus_task_runner_; | |
| 170 | |
| 171 dbus_ = new dbus::Bus(dbus_options); | |
| 172 network_manager_proxy_ = dbus_->GetObjectProxy( | |
| 173 networking_private::kNetworkManagerNamespace, | |
| 174 dbus::ObjectPath(networking_private::kNetworkManagerPath)); | |
| 175 | |
| 176 if (!network_manager_proxy_) { | |
| 177 LOG(ERROR) << "Platform does not support NetworkManager over DBUS"; | |
| 178 } | |
| 179 | |
| 180 network_map_.reset(new NetworkMap()); | |
| 181 } | |
| 182 | |
| 183 bool NetworkingPrivateLinux::CheckNetworkManagerSupported( | |
| 184 const FailureCallback& failure_callback) { | |
| 185 if (!network_manager_proxy_) { | |
| 186 ReportNotSupported("NetworkManager over DBus", failure_callback); | |
| 187 return false; | |
| 188 } | |
| 189 | |
| 190 return true; | |
| 191 } | |
| 192 | |
| 193 void NetworkingPrivateLinux::GetProperties( | |
| 194 const std::string& guid, | |
| 195 const DictionaryCallback& success_callback, | |
| 196 const FailureCallback& failure_callback) { | |
| 197 GetState(guid, success_callback, failure_callback); | |
| 198 } | |
| 199 | |
| 200 void NetworkingPrivateLinux::GetManagedProperties( | |
| 201 const std::string& guid, | |
| 202 const DictionaryCallback& success_callback, | |
| 203 const FailureCallback& failure_callback) { | |
| 204 ReportNotSupported("GetManagedProperties", failure_callback); | |
| 205 } | |
| 206 | |
| 207 void NetworkingPrivateLinux::GetState( | |
| 208 const std::string& guid, | |
| 209 const DictionaryCallback& success_callback, | |
| 210 const FailureCallback& failure_callback) { | |
| 211 if (!CheckNetworkManagerSupported(failure_callback)) | |
| 212 return; | |
| 213 | |
| 214 scoped_ptr<std::string> error(new std::string); | |
| 215 scoped_ptr<base::DictionaryValue> network_properties( | |
| 216 new base::DictionaryValue); | |
| 217 | |
| 218 // Runs GetCachedNetworkProperties on |dbus_thread|. | |
| 219 dbus_thread_.task_runner()->PostTaskAndReply( | |
| 220 FROM_HERE, base::Bind(&NetworkingPrivateLinux::GetCachedNetworkProperties, | |
| 221 base::Unretained(this), guid, | |
| 222 base::Unretained(network_properties.get()), | |
| 223 base::Unretained(error.get())), | |
| 224 base::Bind(&GetCachedNetworkPropertiesCallback, base::Passed(&error), | |
| 225 base::Passed(&network_properties), success_callback, | |
| 226 failure_callback)); | |
| 227 } | |
| 228 | |
| 229 void NetworkingPrivateLinux::GetCachedNetworkProperties( | |
| 230 const std::string& guid, | |
| 231 base::DictionaryValue* properties, | |
| 232 std::string* error) { | |
| 233 AssertOnDBusThread(); | |
| 234 std::string ssid; | |
| 235 | |
| 236 if (!GuidToSsid(guid, &ssid)) { | |
| 237 *error = "Invalid Network GUID format"; | |
| 238 return; | |
| 239 } | |
| 240 | |
| 241 NetworkMap::const_iterator network_iter = | |
| 242 network_map_->find(base::UTF8ToUTF16(ssid)); | |
| 243 if (network_iter == network_map_->end()) { | |
| 244 *error = "Unknown network GUID"; | |
| 245 return; | |
| 246 } | |
| 247 | |
| 248 // Make a copy of the properties out of the cached map. | |
| 249 scoped_ptr<base::DictionaryValue> temp_properties( | |
| 250 network_iter->second->DeepCopy()); | |
| 251 | |
| 252 // Swap the new copy into the dictionary that is shared with the reply. | |
| 253 properties->Swap(temp_properties.get()); | |
| 254 } | |
| 255 | |
| 256 void NetworkingPrivateLinux::SetProperties( | |
| 257 const std::string& guid, | |
| 258 scoped_ptr<base::DictionaryValue> properties, | |
| 259 const VoidCallback& success_callback, | |
| 260 const FailureCallback& failure_callback) { | |
| 261 ReportNotSupported("SetProperties", failure_callback); | |
| 262 } | |
| 263 | |
| 264 void NetworkingPrivateLinux::CreateNetwork( | |
| 265 bool shared, | |
| 266 scoped_ptr<base::DictionaryValue> properties, | |
| 267 const StringCallback& success_callback, | |
| 268 const FailureCallback& failure_callback) { | |
| 269 ReportNotSupported("CreateNetwork", failure_callback); | |
| 270 } | |
| 271 | |
| 272 void NetworkingPrivateLinux::GetNetworks( | |
| 273 const std::string& network_type, | |
| 274 bool configured_only, | |
| 275 bool visible_only, | |
| 276 int limit, | |
| 277 const NetworkListCallback& success_callback, | |
| 278 const FailureCallback& failure_callback) { | |
| 279 if (!CheckNetworkManagerSupported(failure_callback)) { | |
| 280 return; | |
| 281 } | |
| 282 | |
| 283 scoped_ptr<NetworkMap> network_map(new NetworkMap); | |
| 284 | |
| 285 if (!(network_type == ::onc::network_type::kWiFi || | |
| 286 network_type == ::onc::network_type::kWireless || | |
| 287 network_type == ::onc::network_type::kAllTypes)) { | |
| 288 // Only enumerating WiFi networks is supported on linux. | |
| 289 ReportNotSupported("GetNetworks with network_type=" + network_type, | |
| 290 failure_callback); | |
| 291 return; | |
| 292 } | |
| 293 | |
| 294 // Runs GetAllWiFiAccessPoints on the dbus_thread and returns the | |
| 295 // results back to OnAccessPointsFound where the callback is fired. | |
| 296 dbus_thread_.task_runner()->PostTaskAndReply( | |
| 297 FROM_HERE, | |
| 298 base::Bind(&NetworkingPrivateLinux::GetAllWiFiAccessPoints, | |
| 299 base::Unretained(this), configured_only, visible_only, limit, | |
| 300 base::Unretained(network_map.get())), | |
| 301 base::Bind(&NetworkingPrivateLinux::OnAccessPointsFound, | |
| 302 base::Unretained(this), base::Passed(&network_map), | |
| 303 success_callback, failure_callback)); | |
| 304 } | |
| 305 | |
| 306 bool NetworkingPrivateLinux::GetNetworksForScanRequest() { | |
| 307 if (!network_manager_proxy_) { | |
| 308 return false; | |
| 309 } | |
| 310 | |
| 311 scoped_ptr<NetworkMap> network_map(new NetworkMap); | |
| 312 | |
| 313 // Runs GetAllWiFiAccessPoints on the dbus_thread and returns the | |
| 314 // results back to SendNetworkListChangedEvent to fire the event. No | |
| 315 // callbacks are used in this case. | |
| 316 dbus_thread_.task_runner()->PostTaskAndReply( | |
| 317 FROM_HERE, base::Bind(&NetworkingPrivateLinux::GetAllWiFiAccessPoints, | |
| 318 base::Unretained(this), false /* configured_only */, | |
| 319 false /* visible_only */, 0 /* limit */, | |
| 320 base::Unretained(network_map.get())), | |
| 321 base::Bind(&NetworkingPrivateLinux::OnAccessPointsFoundViaScan, | |
| 322 base::Unretained(this), base::Passed(&network_map))); | |
| 323 | |
| 324 return true; | |
| 325 } | |
| 326 | |
| 327 // Constructs the network configuration message and connects to the network. | |
| 328 // The message is of the form: | |
| 329 // { | |
| 330 // '802-11-wireless': { | |
| 331 // 'ssid': 'FooNetwork' | |
| 332 // } | |
| 333 // } | |
| 334 void NetworkingPrivateLinux::ConnectToNetwork(const std::string& guid, | |
| 335 std::string* error) { | |
| 336 AssertOnDBusThread(); | |
| 337 std::string device_path_str; | |
| 338 std::string access_point_path_str; | |
| 339 std::string ssid; | |
| 340 DVLOG(1) << "Connecting to network GUID " << guid; | |
| 341 | |
| 342 if (!ParseNetworkGuid(guid, &device_path_str, &access_point_path_str, | |
| 343 &ssid)) { | |
| 344 *error = "Invalid Network GUID format"; | |
| 345 return; | |
| 346 } | |
| 347 | |
| 348 // Set the connection state to connecting in the map. | |
| 349 if (!SetConnectionStateAndPostEvent(guid, ssid, | |
| 350 ::onc::connection_state::kConnecting)) { | |
| 351 *error = "Unknown network GUID"; | |
| 352 return; | |
| 353 } | |
| 354 | |
| 355 dbus::ObjectPath device_path(device_path_str); | |
| 356 dbus::ObjectPath access_point_path(access_point_path_str); | |
| 357 | |
| 358 dbus::MethodCall method_call( | |
| 359 networking_private::kNetworkManagerNamespace, | |
| 360 networking_private::kNetworkManagerAddAndActivateConnectionMethod); | |
| 361 dbus::MessageWriter builder(&method_call); | |
| 362 | |
| 363 // Build up the settings nested dictionary. | |
| 364 dbus::MessageWriter array_writer(&method_call); | |
| 365 builder.OpenArray("{sa{sv}}", &array_writer); | |
| 366 | |
| 367 dbus::MessageWriter dict_writer(&method_call); | |
| 368 array_writer.OpenDictEntry(&dict_writer); | |
| 369 // TODO(zentaro): Support other network types. Currently only WiFi is | |
| 370 // supported. | |
| 371 dict_writer.AppendString( | |
| 372 networking_private::kNetworkManagerConnectionConfig80211Wireless); | |
| 373 | |
| 374 dbus::MessageWriter wifi_array(&method_call); | |
| 375 dict_writer.OpenArray("{sv}", &wifi_array); | |
| 376 | |
| 377 dbus::MessageWriter wifi_dict_writer(&method_call); | |
| 378 wifi_array.OpenDictEntry(&wifi_dict_writer); | |
| 379 wifi_dict_writer.AppendString( | |
| 380 networking_private::kNetworkManagerConnectionConfigSsid); | |
| 381 | |
| 382 dbus::MessageWriter variant_writer(&method_call); | |
| 383 wifi_dict_writer.OpenVariant("ay", &variant_writer); | |
| 384 variant_writer.AppendArrayOfBytes( | |
| 385 reinterpret_cast<const uint8*>(ssid.c_str()), ssid.size()); | |
| 386 | |
| 387 // Close all the arrays and dicts. | |
| 388 wifi_dict_writer.CloseContainer(&variant_writer); | |
| 389 wifi_array.CloseContainer(&wifi_dict_writer); | |
| 390 dict_writer.CloseContainer(&wifi_array); | |
| 391 array_writer.CloseContainer(&dict_writer); | |
| 392 builder.CloseContainer(&array_writer); | |
| 393 | |
| 394 builder.AppendObjectPath(device_path); | |
| 395 builder.AppendObjectPath(access_point_path); | |
| 396 | |
| 397 scoped_ptr<dbus::Response> response( | |
| 398 network_manager_proxy_->CallMethodAndBlock( | |
| 399 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 400 if (!response) { | |
| 401 LOG(ERROR) << "Failed to add a new connection"; | |
| 402 *error = "Failed to connect."; | |
| 403 | |
| 404 // Set the connection state to NotConnected in the map. | |
| 405 SetConnectionStateAndPostEvent(guid, ssid, | |
| 406 ::onc::connection_state::kNotConnected); | |
| 407 return; | |
| 408 } | |
| 409 | |
| 410 dbus::MessageReader reader(response.get()); | |
| 411 dbus::ObjectPath connection_settings_path; | |
| 412 dbus::ObjectPath active_connection_path; | |
| 413 | |
| 414 if (!reader.PopObjectPath(&connection_settings_path)) { | |
| 415 LOG(ERROR) << "Unexpected response for add connection path " | |
| 416 << ": " << response->ToString(); | |
| 417 *error = "Failed to connect."; | |
| 418 | |
| 419 // Set the connection state to NotConnected in the map. | |
| 420 SetConnectionStateAndPostEvent(guid, ssid, | |
| 421 ::onc::connection_state::kNotConnected); | |
| 422 return; | |
| 423 } | |
| 424 | |
| 425 if (!reader.PopObjectPath(&active_connection_path)) { | |
| 426 LOG(ERROR) << "Unexpected response for connection path " | |
| 427 << ": " << response->ToString(); | |
| 428 *error = "Failed to connect."; | |
| 429 | |
| 430 // Set the connection state to NotConnected in the map. | |
| 431 SetConnectionStateAndPostEvent(guid, ssid, | |
| 432 ::onc::connection_state::kNotConnected); | |
| 433 return; | |
| 434 } | |
| 435 | |
| 436 // Set the connection state to Connected in the map. | |
| 437 SetConnectionStateAndPostEvent(guid, ssid, | |
| 438 ::onc::connection_state::kConnected); | |
| 439 return; | |
| 440 } | |
| 441 | |
| 442 void NetworkingPrivateLinux::DisconnectFromNetwork(const std::string& guid, | |
| 443 std::string* error) { | |
| 444 AssertOnDBusThread(); | |
| 445 std::string device_path_str; | |
| 446 std::string access_point_path_str; | |
| 447 std::string ssid; | |
| 448 DVLOG(1) << "Disconnecting from network GUID " << guid; | |
| 449 | |
| 450 if (!ParseNetworkGuid(guid, &device_path_str, &access_point_path_str, | |
| 451 &ssid)) { | |
| 452 *error = "Invalid Network GUID format"; | |
| 453 return; | |
| 454 } | |
| 455 | |
| 456 scoped_ptr<NetworkMap> network_map(new NetworkMap); | |
| 457 GetAllWiFiAccessPoints(false /* configured_only */, false /* visible_only */, | |
| 458 0 /* limit */, network_map.get()); | |
| 459 | |
| 460 NetworkMap::const_iterator network_iter = | |
| 461 network_map->find(base::UTF8ToUTF16(ssid)); | |
| 462 if (network_iter == network_map->end()) { | |
| 463 // This network doesn't exist so there's nothing to do. | |
| 464 return; | |
| 465 } | |
| 466 | |
| 467 std::string connection_state; | |
| 468 network_iter->second->GetString(kAccessPointInfoConnectionState, | |
| 469 &connection_state); | |
| 470 if (connection_state == ::onc::connection_state::kNotConnected) { | |
| 471 // Already disconnected so nothing to do. | |
| 472 return; | |
| 473 } | |
| 474 | |
| 475 // It's not disconnected so disconnect it. | |
| 476 dbus::ObjectProxy* device_proxy = | |
| 477 dbus_->GetObjectProxy(networking_private::kNetworkManagerNamespace, | |
| 478 dbus::ObjectPath(device_path_str)); | |
| 479 dbus::MethodCall method_call( | |
| 480 networking_private::kNetworkManagerDeviceNamespace, | |
| 481 networking_private::kNetworkManagerDisconnectMethod); | |
| 482 scoped_ptr<dbus::Response> response(device_proxy->CallMethodAndBlock( | |
| 483 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 484 | |
| 485 if (!response) { | |
| 486 LOG(WARNING) << "Failed to disconnect network on device " | |
| 487 << device_path_str; | |
| 488 *error = "Failed to disconnect network"; | |
| 489 } | |
| 490 } | |
| 491 | |
| 492 void NetworkingPrivateLinux::StartConnect( | |
| 493 const std::string& guid, | |
| 494 const VoidCallback& success_callback, | |
| 495 const FailureCallback& failure_callback) { | |
| 496 if (!CheckNetworkManagerSupported(failure_callback)) | |
| 497 return; | |
| 498 | |
| 499 scoped_ptr<std::string> error(new std::string); | |
| 500 | |
| 501 // Runs ConnectToNetwork on |dbus_thread|. | |
| 502 dbus_thread_.task_runner()->PostTaskAndReply( | |
| 503 FROM_HERE, | |
| 504 base::Bind(&NetworkingPrivateLinux::ConnectToNetwork, | |
| 505 base::Unretained(this), guid, base::Unretained(error.get())), | |
| 506 base::Bind(&OnNetworkConnectOperationCompleted, base::Passed(&error), | |
| 507 success_callback, failure_callback)); | |
| 508 } | |
| 509 | |
| 510 void NetworkingPrivateLinux::StartDisconnect( | |
| 511 const std::string& guid, | |
| 512 const VoidCallback& success_callback, | |
| 513 const FailureCallback& failure_callback) { | |
| 514 if (!CheckNetworkManagerSupported(failure_callback)) | |
| 515 return; | |
| 516 | |
| 517 scoped_ptr<std::string> error(new std::string); | |
| 518 | |
| 519 // Runs DisconnectFromNetwork on |dbus_thread|. | |
| 520 dbus_thread_.task_runner()->PostTaskAndReply( | |
| 521 FROM_HERE, | |
| 522 base::Bind(&NetworkingPrivateLinux::DisconnectFromNetwork, | |
| 523 base::Unretained(this), guid, base::Unretained(error.get())), | |
| 524 base::Bind(&OnNetworkConnectOperationCompleted, base::Passed(&error), | |
| 525 success_callback, failure_callback)); | |
| 526 } | |
| 527 | |
| 528 void NetworkingPrivateLinux::SetWifiTDLSEnabledState( | |
| 529 const std::string& ip_or_mac_address, | |
| 530 bool enabled, | |
| 531 const StringCallback& success_callback, | |
| 532 const FailureCallback& failure_callback) { | |
| 533 ReportNotSupported("SetWifiTDLSEnabledState", failure_callback); | |
| 534 } | |
| 535 | |
| 536 void NetworkingPrivateLinux::GetWifiTDLSStatus( | |
| 537 const std::string& ip_or_mac_address, | |
| 538 const StringCallback& success_callback, | |
| 539 const FailureCallback& failure_callback) { | |
| 540 ReportNotSupported("GetWifiTDLSStatus", failure_callback); | |
| 541 } | |
| 542 | |
| 543 void NetworkingPrivateLinux::GetCaptivePortalStatus( | |
| 544 const std::string& guid, | |
| 545 const StringCallback& success_callback, | |
| 546 const FailureCallback& failure_callback) { | |
| 547 ReportNotSupported("GetCaptivePortalStatus", failure_callback); | |
| 548 } | |
| 549 | |
| 550 scoped_ptr<base::ListValue> NetworkingPrivateLinux::GetEnabledNetworkTypes() { | |
| 551 scoped_ptr<base::ListValue> network_list(new base::ListValue); | |
| 552 return network_list.Pass(); | |
| 553 } | |
| 554 | |
| 555 bool NetworkingPrivateLinux::EnableNetworkType(const std::string& type) { | |
| 556 return false; | |
| 557 } | |
| 558 | |
| 559 bool NetworkingPrivateLinux::DisableNetworkType(const std::string& type) { | |
| 560 return false; | |
| 561 } | |
| 562 | |
| 563 bool NetworkingPrivateLinux::RequestScan() { | |
| 564 return GetNetworksForScanRequest(); | |
| 565 } | |
| 566 | |
| 567 void NetworkingPrivateLinux::AddObserver( | |
| 568 NetworkingPrivateDelegateObserver* observer) { | |
| 569 network_events_observers_.AddObserver(observer); | |
| 570 } | |
| 571 | |
| 572 void NetworkingPrivateLinux::RemoveObserver( | |
| 573 NetworkingPrivateDelegateObserver* observer) { | |
| 574 network_events_observers_.RemoveObserver(observer); | |
| 575 } | |
| 576 | |
| 577 void NetworkingPrivateLinux::OnAccessPointsFound( | |
| 578 scoped_ptr<NetworkMap> network_map, | |
| 579 const NetworkListCallback& success_callback, | |
| 580 const FailureCallback& failure_callback) { | |
| 581 scoped_ptr<base::ListValue> network_list = CopyNetworkMapToList(*network_map); | |
| 582 // Give ownership to the member variable. | |
| 583 network_map_.swap(network_map); | |
| 584 SendNetworkListChangedEvent(*network_list); | |
| 585 success_callback.Run(network_list.Pass()); | |
| 586 } | |
| 587 | |
| 588 void NetworkingPrivateLinux::OnAccessPointsFoundViaScan( | |
| 589 scoped_ptr<NetworkMap> network_map) { | |
| 590 scoped_ptr<base::ListValue> network_list = CopyNetworkMapToList(*network_map); | |
| 591 // Give ownership to the member variable. | |
| 592 network_map_.swap(network_map); | |
| 593 SendNetworkListChangedEvent(*network_list); | |
| 594 } | |
| 595 | |
| 596 void NetworkingPrivateLinux::SendNetworkListChangedEvent( | |
| 597 const base::ListValue& network_list) { | |
| 598 GuidList guidsForEventCallback; | |
| 599 | |
| 600 for (const auto& network : network_list) { | |
| 601 std::string guid; | |
| 602 base::DictionaryValue* dict; | |
| 603 if (network->GetAsDictionary(&dict)) { | |
| 604 if (dict->GetString(kAccessPointInfoGuid, &guid)) { | |
| 605 guidsForEventCallback.push_back(guid); | |
| 606 } | |
| 607 } | |
| 608 } | |
| 609 | |
| 610 OnNetworkListChangedEventOnUIThread(guidsForEventCallback); | |
| 611 } | |
| 612 | |
| 613 bool NetworkingPrivateLinux::GetNetworkDevices( | |
| 614 std::vector<dbus::ObjectPath>* device_paths) { | |
| 615 AssertOnDBusThread(); | |
| 616 dbus::MethodCall method_call( | |
| 617 networking_private::kNetworkManagerNamespace, | |
| 618 networking_private::kNetworkManagerGetDevicesMethod); | |
| 619 | |
| 620 scoped_ptr<dbus::Response> device_response( | |
| 621 network_manager_proxy_->CallMethodAndBlock( | |
| 622 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 623 | |
| 624 if (!device_response) { | |
| 625 return false; | |
| 626 } | |
| 627 | |
| 628 dbus::MessageReader reader(device_response.get()); | |
| 629 if (!reader.PopArrayOfObjectPaths(device_paths)) { | |
| 630 LOG(WARNING) << "Unexpected response: " << device_response->ToString(); | |
| 631 return false; | |
| 632 } | |
| 633 | |
| 634 return true; | |
| 635 } | |
| 636 | |
| 637 NetworkingPrivateLinux::DeviceType NetworkingPrivateLinux::GetDeviceType( | |
| 638 const dbus::ObjectPath& device_path) { | |
| 639 AssertOnDBusThread(); | |
| 640 dbus::ObjectProxy* device_proxy = dbus_->GetObjectProxy( | |
| 641 networking_private::kNetworkManagerNamespace, device_path); | |
| 642 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
| 643 networking_private::kNetworkManagerGetMethod); | |
| 644 dbus::MessageWriter builder(&method_call); | |
| 645 builder.AppendString(networking_private::kNetworkManagerDeviceNamespace); | |
| 646 builder.AppendString(networking_private::kNetworkManagerDeviceType); | |
| 647 | |
| 648 scoped_ptr<dbus::Response> response(device_proxy->CallMethodAndBlock( | |
| 649 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 650 | |
| 651 if (!response) { | |
| 652 LOG(ERROR) << "Failed to get the device type for device " | |
| 653 << device_path.value(); | |
| 654 return NetworkingPrivateLinux::NM_DEVICE_TYPE_UNKNOWN; | |
| 655 } | |
| 656 | |
| 657 dbus::MessageReader reader(response.get()); | |
| 658 uint32 device_type = 0; | |
| 659 if (!reader.PopVariantOfUint32(&device_type)) { | |
| 660 LOG(ERROR) << "Unexpected response for device " << device_type << ": " | |
| 661 << response->ToString(); | |
| 662 return NM_DEVICE_TYPE_UNKNOWN; | |
| 663 } | |
| 664 | |
| 665 return static_cast<NetworkingPrivateLinux::DeviceType>(device_type); | |
| 666 } | |
| 667 | |
| 668 void NetworkingPrivateLinux::GetAllWiFiAccessPoints(bool configured_only, | |
| 669 bool visible_only, | |
| 670 int limit, | |
| 671 NetworkMap* network_map) { | |
| 672 AssertOnDBusThread(); | |
| 673 // TODO(zentaro): The filters are not implemented and are ignored. | |
| 674 std::vector<dbus::ObjectPath> device_paths; | |
| 675 if (!GetNetworkDevices(&device_paths)) { | |
| 676 LOG(ERROR) << "Failed to enumerate network devices"; | |
| 677 return; | |
| 678 } | |
| 679 | |
| 680 for (const auto& device_path : device_paths) { | |
| 681 NetworkingPrivateLinux::DeviceType device_type = GetDeviceType(device_path); | |
| 682 | |
| 683 // Get the access points for each WiFi adapter. Other network types are | |
| 684 // ignored. | |
| 685 if (device_type != NetworkingPrivateLinux::NM_DEVICE_TYPE_WIFI) | |
| 686 continue; | |
| 687 | |
| 688 // Found a wlan adapter | |
| 689 if (!AddAccessPointsFromDevice(device_path, network_map)) { | |
| 690 // Ignore devices we can't enumerate. | |
| 691 LOG(WARNING) << "Failed to add access points from device " | |
| 692 << device_path.value(); | |
| 693 } | |
| 694 } | |
| 695 } | |
| 696 | |
| 697 scoped_ptr<dbus::Response> NetworkingPrivateLinux::GetAccessPointProperty( | |
| 698 dbus::ObjectProxy* access_point_proxy, | |
| 699 const std::string& property_name) { | |
| 700 AssertOnDBusThread(); | |
| 701 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
| 702 networking_private::kNetworkManagerGetMethod); | |
| 703 dbus::MessageWriter builder(&method_call); | |
| 704 builder.AppendString(networking_private::kNetworkManagerAccessPointNamespace); | |
| 705 builder.AppendString(property_name); | |
| 706 scoped_ptr<dbus::Response> response = access_point_proxy->CallMethodAndBlock( | |
| 707 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); | |
| 708 if (!response) { | |
| 709 LOG(ERROR) << "Failed to get property for " << property_name; | |
| 710 } | |
| 711 return response.Pass(); | |
| 712 } | |
| 713 | |
| 714 bool NetworkingPrivateLinux::GetAccessPointInfo( | |
| 715 const dbus::ObjectPath& access_point_path, | |
| 716 const scoped_ptr<base::DictionaryValue>& access_point_info) { | |
| 717 AssertOnDBusThread(); | |
| 718 dbus::ObjectProxy* access_point_proxy = dbus_->GetObjectProxy( | |
| 719 networking_private::kNetworkManagerNamespace, access_point_path); | |
| 720 | |
| 721 // Read the SSID. The GUID is derived from the Ssid. | |
| 722 { | |
| 723 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
| 724 access_point_proxy, networking_private::kNetworkManagerSsidProperty)); | |
| 725 | |
| 726 if (!response) { | |
| 727 return false; | |
| 728 } | |
| 729 | |
| 730 // The response should contain a variant that contains an array of bytes. | |
| 731 dbus::MessageReader reader(response.get()); | |
| 732 dbus::MessageReader variant_reader(response.get()); | |
| 733 if (!reader.PopVariant(&variant_reader)) { | |
| 734 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
| 735 << ": " << response->ToString(); | |
| 736 return false; | |
| 737 } | |
| 738 | |
| 739 const uint8* ssid_bytes = NULL; | |
| 740 size_t ssid_length = 0; | |
| 741 if (!variant_reader.PopArrayOfBytes(&ssid_bytes, &ssid_length)) { | |
| 742 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
| 743 << ": " << response->ToString(); | |
| 744 return false; | |
| 745 } | |
| 746 | |
| 747 std::string ssidUTF8(ssid_bytes, ssid_bytes + ssid_length); | |
| 748 base::string16 ssid = base::UTF8ToUTF16(ssidUTF8); | |
| 749 | |
| 750 access_point_info->SetString(kAccessPointInfoName, ssid); | |
| 751 } | |
| 752 | |
| 753 // Read signal strength. | |
| 754 { | |
| 755 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
| 756 access_point_proxy, | |
| 757 networking_private::kNetworkManagerStrengthProperty)); | |
| 758 if (!response) { | |
| 759 return false; | |
| 760 } | |
| 761 | |
| 762 dbus::MessageReader reader(response.get()); | |
| 763 uint8 strength = 0; | |
| 764 if (!reader.PopVariantOfByte(&strength)) { | |
| 765 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
| 766 << ": " << response->ToString(); | |
| 767 return false; | |
| 768 } | |
| 769 | |
| 770 access_point_info->SetInteger(kAccessPointInfoWifiSignalStrengthDotted, | |
| 771 strength); | |
| 772 } | |
| 773 | |
| 774 // Read the security type. This is from the WpaFlags and RsnFlags property | |
| 775 // which are of the same type and can be OR'd together to find all supported | |
| 776 // security modes. | |
| 777 | |
| 778 uint32 wpa_security_flags = 0; | |
| 779 { | |
| 780 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
| 781 access_point_proxy, | |
| 782 networking_private::kNetworkManagerWpaFlagsProperty)); | |
| 783 if (!response) { | |
| 784 return false; | |
| 785 } | |
| 786 | |
| 787 dbus::MessageReader reader(response.get()); | |
| 788 | |
| 789 if (!reader.PopVariantOfUint32(&wpa_security_flags)) { | |
| 790 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
| 791 << ": " << response->ToString(); | |
| 792 return false; | |
| 793 } | |
| 794 } | |
| 795 | |
| 796 uint32 rsn_security_flags = 0; | |
| 797 { | |
| 798 scoped_ptr<dbus::Response> response(GetAccessPointProperty( | |
| 799 access_point_proxy, | |
| 800 networking_private::kNetworkManagerRsnFlagsProperty)); | |
| 801 if (!response) { | |
| 802 return false; | |
| 803 } | |
| 804 | |
| 805 dbus::MessageReader reader(response.get()); | |
| 806 | |
| 807 if (!reader.PopVariantOfUint32(&rsn_security_flags)) { | |
| 808 LOG(ERROR) << "Unexpected response for " << access_point_path.value() | |
| 809 << ": " << response->ToString(); | |
| 810 return false; | |
| 811 } | |
| 812 } | |
| 813 | |
| 814 std::string security; | |
| 815 MapSecurityFlagsToString(rsn_security_flags | wpa_security_flags, &security); | |
| 816 access_point_info->SetString(kAccessPointInfoWifiSecurityDotted, security); | |
| 817 access_point_info->SetString(kAccessPointInfoType, kAccessPointInfoTypeWifi); | |
| 818 access_point_info->SetBoolean(kAccessPointInfoConnectable, true); | |
| 819 return true; | |
| 820 } | |
| 821 | |
| 822 bool NetworkingPrivateLinux::AddAccessPointsFromDevice( | |
| 823 const dbus::ObjectPath& device_path, | |
| 824 NetworkMap* network_map) { | |
| 825 AssertOnDBusThread(); | |
| 826 dbus::ObjectPath connected_access_point; | |
| 827 if (!GetConnectedAccessPoint(device_path, &connected_access_point)) { | |
| 828 return false; | |
| 829 } | |
| 830 | |
| 831 dbus::ObjectProxy* device_proxy = dbus_->GetObjectProxy( | |
| 832 networking_private::kNetworkManagerNamespace, device_path); | |
| 833 dbus::MethodCall method_call( | |
| 834 networking_private::kNetworkManagerWirelessDeviceNamespace, | |
| 835 networking_private::kNetworkManagerGetAccessPointsMethod); | |
| 836 scoped_ptr<dbus::Response> response(device_proxy->CallMethodAndBlock( | |
| 837 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 838 | |
| 839 if (!response) { | |
| 840 LOG(WARNING) << "Failed to get access points data for " | |
| 841 << device_path.value(); | |
| 842 return false; | |
| 843 } | |
| 844 | |
| 845 dbus::MessageReader reader(response.get()); | |
| 846 std::vector<dbus::ObjectPath> access_point_paths; | |
| 847 if (!reader.PopArrayOfObjectPaths(&access_point_paths)) { | |
| 848 LOG(ERROR) << "Unexpected response for " << device_path.value() << ": " | |
| 849 << response->ToString(); | |
| 850 return false; | |
| 851 } | |
| 852 | |
| 853 for (const auto& access_point_path : access_point_paths) { | |
| 854 scoped_ptr<base::DictionaryValue> access_point(new base::DictionaryValue); | |
| 855 | |
| 856 if (GetAccessPointInfo(access_point_path, access_point)) { | |
| 857 std::string connection_state = | |
| 858 (access_point_path == connected_access_point) | |
| 859 ? ::onc::connection_state::kConnected | |
| 860 : ::onc::connection_state::kNotConnected; | |
| 861 | |
| 862 access_point->SetString(kAccessPointInfoConnectionState, | |
| 863 connection_state); | |
| 864 std::string ssid; | |
| 865 access_point->GetString(kAccessPointInfoName, &ssid); | |
| 866 | |
| 867 std::string network_guid = | |
| 868 ConstructNetworkGuid(device_path, access_point_path, ssid); | |
| 869 | |
| 870 // Adds the network to the map. Since each SSID can actually have multiple | |
| 871 // access point paths, this consolidates them. If it is already | |
| 872 // in the map it updates the signal strength and GUID paths if this | |
| 873 // network is stronger or the one that is connected. | |
| 874 AddOrUpdateAccessPoint(network_map, network_guid, access_point); | |
| 875 } | |
| 876 } | |
| 877 | |
| 878 return true; | |
| 879 } | |
| 880 | |
| 881 void NetworkingPrivateLinux::AddOrUpdateAccessPoint( | |
| 882 NetworkMap* network_map, | |
| 883 const std::string& network_guid, | |
| 884 scoped_ptr<base::DictionaryValue>& access_point) { | |
| 885 base::string16 ssid; | |
| 886 std::string connection_state; | |
| 887 int signal_strength; | |
| 888 | |
| 889 access_point->GetString(kAccessPointInfoConnectionState, &connection_state); | |
| 890 access_point->GetInteger(kAccessPointInfoWifiSignalStrengthDotted, | |
| 891 &signal_strength); | |
| 892 access_point->GetString(kAccessPointInfoName, &ssid); | |
| 893 access_point->SetString(kAccessPointInfoGuid, network_guid); | |
| 894 | |
| 895 NetworkMap::iterator existing_access_point_iter = network_map->find(ssid); | |
| 896 | |
| 897 if (existing_access_point_iter == network_map->end()) { | |
| 898 // Unseen access point. Add it to the map. | |
| 899 network_map->insert(NetworkMap::value_type( | |
| 900 ssid, linked_ptr<base::DictionaryValue>(access_point.release()))); | |
| 901 } else { | |
| 902 // Already seen access point. Update the record if this is the connected | |
| 903 // record or if the signal strength is higher. But don't override a weaker | |
| 904 // access point if that is the one that is connected. | |
| 905 int existing_signal_strength; | |
| 906 linked_ptr<base::DictionaryValue>& existing_access_point = | |
| 907 existing_access_point_iter->second; | |
| 908 existing_access_point->GetInteger(kAccessPointInfoWifiSignalStrengthDotted, | |
| 909 &existing_signal_strength); | |
| 910 | |
| 911 std::string existing_connection_state; | |
| 912 existing_access_point->GetString(kAccessPointInfoConnectionState, | |
| 913 &existing_connection_state); | |
| 914 | |
| 915 if ((connection_state == ::onc::connection_state::kConnected) || | |
| 916 (!(existing_connection_state == ::onc::connection_state::kConnected) && | |
| 917 signal_strength > existing_signal_strength)) { | |
| 918 existing_access_point->SetString(kAccessPointInfoConnectionState, | |
| 919 connection_state); | |
| 920 existing_access_point->SetInteger( | |
| 921 kAccessPointInfoWifiSignalStrengthDotted, signal_strength); | |
| 922 existing_access_point->SetString(kAccessPointInfoGuid, network_guid); | |
| 923 } | |
| 924 } | |
| 925 } | |
| 926 | |
| 927 void NetworkingPrivateLinux::MapSecurityFlagsToString(uint32 security_flags, | |
| 928 std::string* security) { | |
| 929 // Valid values are None, WEP-PSK, WEP-8021X, WPA-PSK, WPA-EAP | |
| 930 if (security_flags == NetworkingPrivateLinux::NM_802_11_AP_SEC_NONE) { | |
| 931 *security = kAccessPointSecurityNone; | |
| 932 } else if (security_flags & | |
| 933 NetworkingPrivateLinux::NM_802_11_AP_SEC_KEY_MGMT_PSK) { | |
| 934 *security = kAccessPointSecurityWpaPsk; | |
| 935 } else if (security_flags & | |
| 936 NetworkingPrivateLinux::NM_802_11_AP_SEC_KEY_MGMT_802_1X) { | |
| 937 *security = kAccessPointSecurity9021X; | |
| 938 } else { | |
| 939 DVLOG(1) << "Security flag mapping is missing. Found " << security_flags; | |
| 940 *security = kAccessPointSecurityUnknown; | |
| 941 } | |
| 942 | |
| 943 DVLOG(1) << "Network security setting " << *security; | |
| 944 } | |
| 945 | |
| 946 bool NetworkingPrivateLinux::GetConnectedAccessPoint( | |
| 947 dbus::ObjectPath device_path, | |
| 948 dbus::ObjectPath* access_point_path) { | |
| 949 AssertOnDBusThread(); | |
| 950 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
| 951 networking_private::kNetworkManagerGetMethod); | |
| 952 dbus::MessageWriter builder(&method_call); | |
| 953 builder.AppendString(networking_private::kNetworkManagerNamespace); | |
| 954 builder.AppendString(networking_private::kNetworkManagerActiveConnections); | |
| 955 | |
| 956 scoped_ptr<dbus::Response> response( | |
| 957 network_manager_proxy_->CallMethodAndBlock( | |
| 958 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 959 | |
| 960 if (!response) { | |
| 961 LOG(WARNING) << "Failed to get a list of active connections"; | |
| 962 return false; | |
| 963 } | |
| 964 | |
| 965 dbus::MessageReader reader(response.get()); | |
| 966 dbus::MessageReader variant_reader(response.get()); | |
| 967 if (!reader.PopVariant(&variant_reader)) { | |
| 968 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
| 969 return false; | |
| 970 } | |
| 971 | |
| 972 std::vector<dbus::ObjectPath> connection_paths; | |
| 973 if (!variant_reader.PopArrayOfObjectPaths(&connection_paths)) { | |
| 974 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
| 975 return false; | |
| 976 } | |
| 977 | |
| 978 for (const auto& connection_path : connection_paths) { | |
| 979 dbus::ObjectPath connections_device_path; | |
| 980 if (!GetDeviceOfConnection(connection_path, &connections_device_path)) { | |
| 981 return false; | |
| 982 } | |
| 983 | |
| 984 if (connections_device_path == device_path) { | |
| 985 if (!GetAccessPointForConnection(connection_path, access_point_path)) { | |
| 986 return false; | |
| 987 } | |
| 988 | |
| 989 break; | |
| 990 } | |
| 991 } | |
| 992 | |
| 993 return true; | |
| 994 } | |
| 995 | |
| 996 bool NetworkingPrivateLinux::GetDeviceOfConnection( | |
| 997 dbus::ObjectPath connection_path, | |
| 998 dbus::ObjectPath* device_path) { | |
| 999 AssertOnDBusThread(); | |
| 1000 dbus::ObjectProxy* connection_proxy = dbus_->GetObjectProxy( | |
| 1001 networking_private::kNetworkManagerNamespace, connection_path); | |
| 1002 | |
| 1003 if (!connection_proxy) { | |
| 1004 return false; | |
| 1005 } | |
| 1006 | |
| 1007 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
| 1008 networking_private::kNetworkManagerGetMethod); | |
| 1009 dbus::MessageWriter builder(&method_call); | |
| 1010 builder.AppendString( | |
| 1011 networking_private::kNetworkManagerActiveConnectionNamespace); | |
| 1012 builder.AppendString("Devices"); | |
| 1013 | |
| 1014 scoped_ptr<dbus::Response> response(connection_proxy->CallMethodAndBlock( | |
| 1015 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 1016 | |
| 1017 if (!response) { | |
| 1018 LOG(ERROR) << "Failed to get devices"; | |
| 1019 return false; | |
| 1020 } | |
| 1021 | |
| 1022 dbus::MessageReader reader(response.get()); | |
| 1023 dbus::MessageReader variant_reader(response.get()); | |
| 1024 if (!reader.PopVariant(&variant_reader)) { | |
| 1025 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
| 1026 return false; | |
| 1027 } | |
| 1028 | |
| 1029 std::vector<dbus::ObjectPath> device_paths; | |
| 1030 if (!variant_reader.PopArrayOfObjectPaths(&device_paths)) { | |
| 1031 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
| 1032 return false; | |
| 1033 } | |
| 1034 | |
| 1035 if (device_paths.size() == 1) { | |
| 1036 *device_path = device_paths[0]; | |
| 1037 | |
| 1038 return true; | |
| 1039 } | |
| 1040 | |
| 1041 return false; | |
| 1042 } | |
| 1043 | |
| 1044 bool NetworkingPrivateLinux::GetAccessPointForConnection( | |
| 1045 dbus::ObjectPath connection_path, | |
| 1046 dbus::ObjectPath* access_point_path) { | |
| 1047 AssertOnDBusThread(); | |
| 1048 dbus::ObjectProxy* connection_proxy = dbus_->GetObjectProxy( | |
| 1049 networking_private::kNetworkManagerNamespace, connection_path); | |
| 1050 | |
| 1051 if (!connection_proxy) { | |
| 1052 return false; | |
| 1053 } | |
| 1054 | |
| 1055 dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, | |
| 1056 networking_private::kNetworkManagerGetMethod); | |
| 1057 dbus::MessageWriter builder(&method_call); | |
| 1058 builder.AppendString( | |
| 1059 networking_private::kNetworkManagerActiveConnectionNamespace); | |
| 1060 builder.AppendString(networking_private::kNetworkManagerSpecificObject); | |
| 1061 | |
| 1062 scoped_ptr<dbus::Response> response(connection_proxy->CallMethodAndBlock( | |
| 1063 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); | |
| 1064 | |
| 1065 if (!response) { | |
| 1066 LOG(WARNING) << "Failed to get access point from active connection"; | |
| 1067 return false; | |
| 1068 } | |
| 1069 | |
| 1070 dbus::MessageReader reader(response.get()); | |
| 1071 dbus::MessageReader variant_reader(response.get()); | |
| 1072 if (!reader.PopVariant(&variant_reader)) { | |
| 1073 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
| 1074 return false; | |
| 1075 } | |
| 1076 | |
| 1077 if (!variant_reader.PopObjectPath(access_point_path)) { | |
| 1078 LOG(ERROR) << "Unexpected response: " << response->ToString(); | |
| 1079 return false; | |
| 1080 } | |
| 1081 | |
| 1082 return true; | |
| 1083 } | |
| 1084 | |
| 1085 bool NetworkingPrivateLinux::SetConnectionStateAndPostEvent( | |
| 1086 const std::string& guid, | |
| 1087 const std::string& ssid, | |
| 1088 const std::string& connection_state) { | |
| 1089 AssertOnDBusThread(); | |
| 1090 | |
| 1091 NetworkMap::iterator network_iter = | |
| 1092 network_map_->find(base::UTF8ToUTF16(ssid)); | |
| 1093 if (network_iter == network_map_->end()) { | |
| 1094 return false; | |
| 1095 } | |
| 1096 | |
| 1097 DVLOG(1) << "Setting connection state of " << ssid << " to " | |
| 1098 << connection_state; | |
| 1099 | |
| 1100 // If setting this network to connected, find the previously connected network | |
| 1101 // and disconnect that one. Also retain the guid of that network to fire a | |
| 1102 // changed event. | |
| 1103 std::string connected_network_guid; | |
| 1104 if (connection_state == ::onc::connection_state::kConnected) { | |
| 1105 for (auto& network : *network_map_) { | |
| 1106 std::string other_connection_state; | |
| 1107 if (network.second->GetString(kAccessPointInfoConnectionState, | |
| 1108 &other_connection_state)) { | |
| 1109 if (other_connection_state == ::onc::connection_state::kConnected) { | |
| 1110 network.second->GetString(kAccessPointInfoGuid, | |
| 1111 &connected_network_guid); | |
| 1112 network.second->SetString(kAccessPointInfoConnectionState, | |
| 1113 ::onc::connection_state::kNotConnected); | |
| 1114 } | |
| 1115 } | |
| 1116 } | |
| 1117 } | |
| 1118 | |
| 1119 // Set the status. | |
| 1120 network_iter->second->SetString(kAccessPointInfoConnectionState, | |
| 1121 connection_state); | |
| 1122 | |
| 1123 scoped_ptr<GuidList> changed_networks(new GuidList()); | |
| 1124 changed_networks->push_back(guid); | |
| 1125 | |
| 1126 // Only add a second network if it exists and it is not the same as the | |
| 1127 // network already being added to the list. | |
| 1128 if (!connected_network_guid.empty() && connected_network_guid != guid) { | |
| 1129 changed_networks->push_back(connected_network_guid); | |
| 1130 } | |
| 1131 | |
| 1132 PostOnNetworksChangedToUIThread(changed_networks.Pass()); | |
| 1133 return true; | |
| 1134 } | |
| 1135 | |
| 1136 void NetworkingPrivateLinux::OnNetworksChangedEventOnUIThread( | |
| 1137 const GuidList& network_guids) { | |
| 1138 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 1139 FOR_EACH_OBSERVER(NetworkingPrivateDelegateObserver, | |
| 1140 network_events_observers_, | |
| 1141 OnNetworksChangedEvent(network_guids)); | |
| 1142 } | |
| 1143 | |
| 1144 void NetworkingPrivateLinux::OnNetworkListChangedEventOnUIThread( | |
| 1145 const GuidList& network_guids) { | |
| 1146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 1147 FOR_EACH_OBSERVER(NetworkingPrivateDelegateObserver, | |
| 1148 network_events_observers_, | |
| 1149 OnNetworkListChangedEvent(network_guids)); | |
| 1150 } | |
| 1151 | |
| 1152 void NetworkingPrivateLinux::PostOnNetworksChangedToUIThread( | |
| 1153 scoped_ptr<GuidList> guid_list) { | |
| 1154 AssertOnDBusThread(); | |
| 1155 | |
| 1156 content::BrowserThread::PostTask( | |
| 1157 content::BrowserThread::UI, FROM_HERE, | |
| 1158 base::Bind(&NetworkingPrivateLinux::OnNetworksChangedEventTask, | |
| 1159 base::Unretained(this), base::Passed(&guid_list))); | |
| 1160 } | |
| 1161 | |
| 1162 void NetworkingPrivateLinux::OnNetworksChangedEventTask( | |
| 1163 scoped_ptr<GuidList> guid_list) { | |
| 1164 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 1165 OnNetworksChangedEventOnUIThread(*guid_list); | |
| 1166 } | |
| 1167 | |
| 1168 } // namespace extensions | |
| OLD | NEW |