| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/network/network_state.h" | 5 #include "chromeos/network/network_state.h" |
| 6 | 6 |
| 7 #include "base/i18n/icu_encoding_detection.h" | |
| 8 #include "base/i18n/icu_string_conversions.h" | |
| 9 #include "base/json/json_writer.h" | |
| 10 #include "base/strings/string_number_conversions.h" | |
| 11 #include "base/strings/string_util.h" | |
| 12 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 13 #include "base/strings/utf_string_conversion_utils.h" | |
| 14 #include "chromeos/network/network_event_log.h" | 8 #include "chromeos/network/network_event_log.h" |
| 15 #include "chromeos/network/network_profile_handler.h" | 9 #include "chromeos/network/network_profile_handler.h" |
| 16 #include "chromeos/network/network_util.h" | 10 #include "chromeos/network/network_util.h" |
| 17 #include "chromeos/network/onc/onc_utils.h" | 11 #include "chromeos/network/onc/onc_utils.h" |
| 12 #include "chromeos/network/shill_property_util.h" |
| 18 #include "third_party/cros_system_api/dbus/service_constants.h" | 13 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 19 | 14 |
| 20 namespace { | 15 namespace { |
| 21 | 16 |
| 22 const char kErrorUnknown[] = "Unknown"; | 17 const char kErrorUnknown[] = "Unknown"; |
| 23 | 18 |
| 24 bool ConvertListValueToStringVector(const base::ListValue& string_list, | 19 bool ConvertListValueToStringVector(const base::ListValue& string_list, |
| 25 std::vector<std::string>* result) { | 20 std::vector<std::string>* result) { |
| 26 for (size_t i = 0; i < string_list.GetSize(); ++i) { | 21 for (size_t i = 0; i < string_list.GetSize(); ++i) { |
| 27 std::string str; | 22 std::string str; |
| 28 if (!string_list.GetString(i, &str)) | 23 if (!string_list.GetString(i, &str)) |
| 29 return false; | 24 return false; |
| 30 result->push_back(str); | 25 result->push_back(str); |
| 31 } | 26 } |
| 32 return true; | 27 return true; |
| 33 } | 28 } |
| 34 | 29 |
| 35 // Replace non UTF8 characters in |str| with a replacement character. | |
| 36 std::string ValidateUTF8(const std::string& str) { | |
| 37 std::string result; | |
| 38 for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) { | |
| 39 uint32 code_point_out; | |
| 40 bool is_unicode_char = base::ReadUnicodeCharacter(str.c_str(), str.size(), | |
| 41 &index, &code_point_out); | |
| 42 const uint32 kFirstNonControlChar = 0x20; | |
| 43 if (is_unicode_char && (code_point_out >= kFirstNonControlChar)) { | |
| 44 base::WriteUnicodeCharacter(code_point_out, &result); | |
| 45 } else { | |
| 46 const uint32 kReplacementChar = 0xFFFD; | |
| 47 // Puts kReplacementChar if character is a control character [0,0x20) | |
| 48 // or is not readable UTF8. | |
| 49 base::WriteUnicodeCharacter(kReplacementChar, &result); | |
| 50 } | |
| 51 } | |
| 52 return result; | |
| 53 } | |
| 54 | |
| 55 bool IsCaCertNssSet(const base::DictionaryValue& properties) { | 30 bool IsCaCertNssSet(const base::DictionaryValue& properties) { |
| 56 std::string ca_cert_nss; | 31 std::string ca_cert_nss; |
| 57 if (properties.GetStringWithoutPathExpansion(flimflam::kEapCaCertNssProperty, | 32 if (properties.GetStringWithoutPathExpansion(flimflam::kEapCaCertNssProperty, |
| 58 &ca_cert_nss) && | 33 &ca_cert_nss) && |
| 59 !ca_cert_nss.empty()) { | 34 !ca_cert_nss.empty()) { |
| 60 return true; | 35 return true; |
| 61 } | 36 } |
| 62 | 37 |
| 63 const base::DictionaryValue* provider = NULL; | 38 const base::DictionaryValue* provider = NULL; |
| 64 properties.GetDictionaryWithoutPathExpansion(flimflam::kProviderProperty, | 39 properties.GetDictionaryWithoutPathExpansion(flimflam::kProviderProperty, |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 // Warning: The DictionaryValue returned from | 152 // Warning: The DictionaryValue returned from |
| 178 // ReadDictionaryFromJson/JSONParser is an optimized derived class that | 153 // ReadDictionaryFromJson/JSONParser is an optimized derived class that |
| 179 // doesn't allow releasing ownership of nested values. A Swap in the wrong | 154 // doesn't allow releasing ownership of nested values. A Swap in the wrong |
| 180 // order leads to memory access errors. | 155 // order leads to memory access errors. |
| 181 proxy_config_.MergeDictionary(proxy_config_dict.get()); | 156 proxy_config_.MergeDictionary(proxy_config_dict.get()); |
| 182 } else { | 157 } else { |
| 183 NET_LOG_ERROR("Failed to parse " + key, path()); | 158 NET_LOG_ERROR("Failed to parse " + key, path()); |
| 184 } | 159 } |
| 185 return true; | 160 return true; |
| 186 } else if (key == flimflam::kUIDataProperty) { | 161 } else if (key == flimflam::kUIDataProperty) { |
| 187 if (!GetUIDataFromValue(value, &ui_data_)) { | 162 scoped_ptr<NetworkUIData> new_ui_data = |
| 163 shill_property_util::GetUIDataFromValue(value); |
| 164 if (!new_ui_data) { |
| 188 NET_LOG_ERROR("Failed to parse " + key, path()); | 165 NET_LOG_ERROR("Failed to parse " + key, path()); |
| 189 return false; | 166 return false; |
| 190 } | 167 } |
| 168 ui_data_ = *new_ui_data; |
| 191 return true; | 169 return true; |
| 192 } else if (key == flimflam::kNetworkTechnologyProperty) { | 170 } else if (key == flimflam::kNetworkTechnologyProperty) { |
| 193 return GetStringValue(key, value, &network_technology_); | 171 return GetStringValue(key, value, &network_technology_); |
| 194 } else if (key == flimflam::kDeviceProperty) { | 172 } else if (key == flimflam::kDeviceProperty) { |
| 195 return GetStringValue(key, value, &device_path_); | 173 return GetStringValue(key, value, &device_path_); |
| 196 } else if (key == flimflam::kGuidProperty) { | 174 } else if (key == flimflam::kGuidProperty) { |
| 197 return GetStringValue(key, value, &guid_); | 175 return GetStringValue(key, value, &guid_); |
| 198 } else if (key == flimflam::kProfileProperty) { | 176 } else if (key == flimflam::kProfileProperty) { |
| 199 return GetStringValue(key, value, &profile_path_); | 177 return GetStringValue(key, value, &profile_path_); |
| 200 } else if (key == shill::kActivateOverNonCellularNetworkProperty) { | 178 } else if (key == shill::kActivateOverNonCellularNetworkProperty) { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 result += dns_servers_[i]; | 310 result += dns_servers_[i]; |
| 333 } | 311 } |
| 334 return result; | 312 return result; |
| 335 } | 313 } |
| 336 | 314 |
| 337 std::string NetworkState::GetNetmask() const { | 315 std::string NetworkState::GetNetmask() const { |
| 338 return network_util::PrefixLengthToNetmask(prefix_length_); | 316 return network_util::PrefixLengthToNetmask(prefix_length_); |
| 339 } | 317 } |
| 340 | 318 |
| 341 bool NetworkState::UpdateName(const base::DictionaryValue& properties) { | 319 bool NetworkState::UpdateName(const base::DictionaryValue& properties) { |
| 342 std::string updated_name = GetNameFromProperties(path(), properties); | 320 std::string updated_name = |
| 321 shill_property_util::GetNameFromProperties(path(), properties); |
| 343 if (updated_name != name()) { | 322 if (updated_name != name()) { |
| 344 set_name(updated_name); | 323 set_name(updated_name); |
| 345 return true; | 324 return true; |
| 346 } | 325 } |
| 347 return false; | 326 return false; |
| 348 } | 327 } |
| 349 | 328 |
| 350 // static | 329 // static |
| 351 std::string NetworkState::GetNameFromProperties( | |
| 352 const std::string& service_path, | |
| 353 const base::DictionaryValue& properties) { | |
| 354 std::string name, hex_ssid; | |
| 355 properties.GetStringWithoutPathExpansion(flimflam::kNameProperty, &name); | |
| 356 properties.GetStringWithoutPathExpansion(flimflam::kWifiHexSsid, &hex_ssid); | |
| 357 | |
| 358 if (hex_ssid.empty()) { | |
| 359 if (name.empty()) | |
| 360 return name; | |
| 361 // Validate name for UTF8. | |
| 362 std::string valid_ssid = ValidateUTF8(name); | |
| 363 if (valid_ssid != name) { | |
| 364 NET_LOG_DEBUG("GetNameFromProperties", base::StringPrintf( | |
| 365 "%s: UTF8: %s", service_path.c_str(), valid_ssid.c_str())); | |
| 366 } | |
| 367 return valid_ssid; | |
| 368 } | |
| 369 | |
| 370 std::string ssid; | |
| 371 std::vector<uint8> raw_ssid_bytes; | |
| 372 if (base::HexStringToBytes(hex_ssid, &raw_ssid_bytes)) { | |
| 373 ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end()); | |
| 374 NET_LOG_DEBUG("GetNameFromProperties", base::StringPrintf( | |
| 375 "%s: %s, SSID: %s", service_path.c_str(), | |
| 376 hex_ssid.c_str(), ssid.c_str())); | |
| 377 } else { | |
| 378 NET_LOG_ERROR("GetNameFromProperties", | |
| 379 base::StringPrintf("%s: Error processing: %s", | |
| 380 service_path.c_str(), hex_ssid.c_str())); | |
| 381 return name; | |
| 382 } | |
| 383 | |
| 384 if (IsStringUTF8(ssid)) { | |
| 385 if (ssid != name) { | |
| 386 NET_LOG_DEBUG("GetNameFromProperties", base::StringPrintf( | |
| 387 "%s: UTF8: %s", service_path.c_str(), ssid.c_str())); | |
| 388 } | |
| 389 return ssid; | |
| 390 } | |
| 391 | |
| 392 // Detect encoding and convert to UTF-8. | |
| 393 std::string country_code; | |
| 394 properties.GetStringWithoutPathExpansion( | |
| 395 flimflam::kCountryProperty, &country_code); | |
| 396 std::string encoding; | |
| 397 if (!base::DetectEncoding(ssid, &encoding)) { | |
| 398 // TODO(stevenjb): This is currently experimental. If we find a case where | |
| 399 // base::DetectEncoding() fails, we need to figure out whether we can use | |
| 400 // country_code with ConvertToUtf8(). crbug.com/233267. | |
| 401 encoding = country_code; | |
| 402 } | |
| 403 if (!encoding.empty()) { | |
| 404 std::string utf8_ssid; | |
| 405 if (base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) { | |
| 406 if (utf8_ssid != name) { | |
| 407 NET_LOG_DEBUG("GetNameFromProperties", base::StringPrintf( | |
| 408 "%s: Encoding=%s: %s", service_path.c_str(), | |
| 409 encoding.c_str(), utf8_ssid.c_str())); | |
| 410 } | |
| 411 return utf8_ssid; | |
| 412 } | |
| 413 } | |
| 414 | |
| 415 // Unrecognized encoding. Only use raw bytes if name_ is empty. | |
| 416 NET_LOG_DEBUG("GetNameFromProperties", base::StringPrintf( | |
| 417 "%s: Unrecognized Encoding=%s: %s", service_path.c_str(), | |
| 418 encoding.c_str(), ssid.c_str())); | |
| 419 if (name.empty() && !ssid.empty()) | |
| 420 return ssid; | |
| 421 return name; | |
| 422 } | |
| 423 | |
| 424 // static | |
| 425 bool NetworkState::StateIsConnected(const std::string& connection_state) { | 330 bool NetworkState::StateIsConnected(const std::string& connection_state) { |
| 426 return (connection_state == flimflam::kStateReady || | 331 return (connection_state == flimflam::kStateReady || |
| 427 connection_state == flimflam::kStateOnline || | 332 connection_state == flimflam::kStateOnline || |
| 428 connection_state == flimflam::kStatePortal); | 333 connection_state == flimflam::kStatePortal); |
| 429 } | 334 } |
| 430 | 335 |
| 431 // static | 336 // static |
| 432 bool NetworkState::StateIsConnecting(const std::string& connection_state) { | 337 bool NetworkState::StateIsConnecting(const std::string& connection_state) { |
| 433 return (connection_state == flimflam::kStateAssociation || | 338 return (connection_state == flimflam::kStateAssociation || |
| 434 connection_state == flimflam::kStateConfiguration || | 339 connection_state == flimflam::kStateConfiguration || |
| 435 connection_state == flimflam::kStateCarrier); | 340 connection_state == flimflam::kStateCarrier); |
| 436 } | 341 } |
| 437 | 342 |
| 438 // static | 343 // static |
| 439 std::string NetworkState::IPConfigProperty(const char* key) { | 344 std::string NetworkState::IPConfigProperty(const char* key) { |
| 440 return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key); | 345 return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key); |
| 441 } | 346 } |
| 442 | 347 |
| 443 // static | |
| 444 bool NetworkState::GetUIDataFromValue(const base::Value& ui_data_value, | |
| 445 NetworkUIData* out) { | |
| 446 std::string ui_data_str; | |
| 447 if (!ui_data_value.GetAsString(&ui_data_str)) | |
| 448 return false; | |
| 449 if (ui_data_str.empty()) { | |
| 450 *out = NetworkUIData(); | |
| 451 return true; | |
| 452 } | |
| 453 scoped_ptr<base::DictionaryValue> ui_data_dict( | |
| 454 chromeos::onc::ReadDictionaryFromJson(ui_data_str)); | |
| 455 if (!ui_data_dict) | |
| 456 return false; | |
| 457 *out = NetworkUIData(*ui_data_dict); | |
| 458 return true; | |
| 459 } | |
| 460 | |
| 461 } // namespace chromeos | 348 } // namespace chromeos |
| OLD | NEW |