158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file. 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chromeos/network/shill_property_util.h" 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/i18n/icu_encoding_detection.h" 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/i18n/icu_string_conversions.h" 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/json/json_writer.h" 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/string_util.h" 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/stringprintf.h" 1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversion_utils.h" 1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/values.h" 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chromeos/network/network_event_log.h" 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chromeos/network/network_ui_data.h" 1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chromeos/network/onc/onc_utils.h" 1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h" 1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace chromeos { 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace shill_property_util { 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace { 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Replace non UTF8 characters in |str| with a replacement character. 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string ValidateUTF8(const std::string& str) { 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string result; 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) { 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) uint32 code_point_out; 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool is_unicode_char = base::ReadUnicodeCharacter( 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) str.c_str(), str.size(), &index, &code_point_out); 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const uint32 kFirstNonControlChar = 0x20; 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (is_unicode_char && (code_point_out >= kFirstNonControlChar)) { 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::WriteUnicodeCharacter(code_point_out, &result); 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const uint32 kReplacementChar = 0xFFFD; 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Puts kReplacementChar if character is a control character [0,0x20) 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // or is not readable UTF8. 4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::WriteUnicodeCharacter(kReplacementChar, &result); 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return result; 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// If existent and non-empty, copies the string at |key| from |source| to 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// |dest|. Returns true if the string was copied. 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool CopyStringFromDictionary(const base::DictionaryValue& source, 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& key, 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::DictionaryValue* dest) { 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string string_value; 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!source.GetStringWithoutPathExpansion(key, &string_value) || 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) string_value.empty()) { 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) dest->SetStringWithoutPathExpansion(key, string_value); 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return true; 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This is the same normalization that Shill applies to security types for the 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// sake of comparing/identifying WiFi networks. See Shill's 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// WiFiService::GetSecurityClass. 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string GetSecurityClass(const std::string& security) { 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (security == shill::kSecurityRsn || security == shill::kSecurityWpa) 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return shill::kSecurityPsk; 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return security; 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void SetSSID(const std::string ssid, base::DictionaryValue* properties) { 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string hex_ssid = base::HexEncode(ssid.c_str(), ssid.size()); 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) properties->SetStringWithoutPathExpansion(shill::kWifiHexSsid, hex_ssid); 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::string GetSSIDFromProperties(const base::DictionaryValue& properties, 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* unknown_encoding) { 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool verbose_logging = false; 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (unknown_encoding) { 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *unknown_encoding = false; 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch verbose_logging = true; 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Get name for debugging. 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string name; 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string hex_ssid; 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) properties.GetStringWithoutPathExpansion(shill::kWifiHexSsid, &hex_ssid); 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (hex_ssid.empty()) { 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (verbose_logging) 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NET_LOG_DEBUG("GetSSIDFromProperties: No HexSSID set.", name); 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return std::string(); 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string ssid; 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<uint8> raw_ssid_bytes; 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (base::HexStringToBytes(hex_ssid, &raw_ssid_bytes)) { 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end()); 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (verbose_logging) { 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NET_LOG_DEBUG(base::StringPrintf("GetSSIDFromProperties: %s, SSID: %s", 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch hex_ssid.c_str(), ssid.c_str()), name); 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NET_LOG_ERROR( 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringPrintf("GetSSIDFromProperties: Error processing: %s", 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch hex_ssid.c_str()), name); 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return std::string(); 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (base::IsStringUTF8(ssid)) 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return ssid; 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Detect encoding and convert to UTF-8. 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string encoding; 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!base::DetectEncoding(ssid, &encoding)) { 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(stevenjb): This is currently experimental. If we find a case where 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // base::DetectEncoding() fails, we need to figure out whether we can use 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // country_code with ConvertToUtf8(). crbug.com/233267. 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) properties.GetStringWithoutPathExpansion(shill::kCountryProperty, 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &encoding); 12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string utf8_ssid; 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!encoding.empty() && 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) { 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (utf8_ssid != ssid) { 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (verbose_logging) { 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NET_LOG_DEBUG( 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringPrintf("GetSSIDFromProperties: Encoding=%s: %s", 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch encoding.c_str(), utf8_ssid.c_str()), name); 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return utf8_ssid; 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (unknown_encoding) 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *unknown_encoding = true; 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (verbose_logging) { 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NET_LOG_DEBUG( 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringPrintf("GetSSIDFromProperties: Unrecognized Encoding=%s", 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch encoding.c_str()), name); 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return ssid; 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::string GetNetworkIdFromProperties( 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const base::DictionaryValue& properties) { 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (properties.empty()) 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return "EmptyProperties"; 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string result; 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &result)) 154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return result; 155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (properties.GetStringWithoutPathExpansion(shill::kSSIDProperty, &result)) 156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return result; 157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (properties.GetStringWithoutPathExpansion(shill::kNameProperty, &result)) 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return result; 159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string type = "UnknownType"; 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); 161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return "Unidentified " + type; 162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::string GetNameFromProperties(const std::string& service_path, 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::DictionaryValue& properties) { 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string name; 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name); 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string validated_name = ValidateUTF8(name); 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (validated_name != name) { 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NET_LOG_DEBUG("GetNameFromProperties", 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringPrintf("Validated name %s: UTF8: %s", 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) service_path.c_str(), 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) validated_name.c_str())); 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string type; 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); 179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (type.empty()) { 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NET_LOG_ERROR("GetNameFromProperties: No type", service_path); 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return validated_name; 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!NetworkTypePattern::WiFi().MatchesType(type)) 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return validated_name; 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool unknown_ssid_encoding = false; 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string ssid = GetSSIDFromProperties(properties, &unknown_ssid_encoding); 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (ssid.empty()) 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NET_LOG_ERROR("GetNameFromProperties", "No SSID set: " + service_path); 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Use |validated_name| if |ssid| is empty. 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // And if the encoding of the SSID is unknown, use |ssid|, which contains raw 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // bytes in that case, only if |validated_name| is empty. 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (ssid.empty() || (unknown_ssid_encoding && !validated_name.empty())) 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return validated_name; 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (ssid != validated_name) { 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NET_LOG_DEBUG("GetNameFromProperties", 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::StringPrintf("%s: SSID: %s, Name: %s", 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) service_path.c_str(), 2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ssid.c_str(), 2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) validated_name.c_str())); 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return ssid; 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<NetworkUIData> GetUIDataFromValue(const base::Value& ui_data_value) { 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string ui_data_str; 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!ui_data_value.GetAsString(&ui_data_str)) 21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<NetworkUIData>(); 21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (ui_data_str.empty()) 21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return make_scoped_ptr(new NetworkUIData()); 21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<base::DictionaryValue> ui_data_dict( 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) chromeos::onc::ReadDictionaryFromJson(ui_data_str)); 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!ui_data_dict) 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<NetworkUIData>(); 21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return make_scoped_ptr(new NetworkUIData(*ui_data_dict)); 21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<NetworkUIData> GetUIDataFromProperties( 22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const base::DictionaryValue& shill_dictionary) { 22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const base::Value* ui_data_value = NULL; 22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) shill_dictionary.GetWithoutPathExpansion(shill::kUIDataProperty, 22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &ui_data_value); 22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!ui_data_value) { 22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) VLOG(2) << "Dictionary has no UIData entry."; 22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<NetworkUIData>(); 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<NetworkUIData> ui_data = GetUIDataFromValue(*ui_data_value); 23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!ui_data) 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LOG(ERROR) << "UIData is not a valid JSON dictionary."; 23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return ui_data.Pass(); 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SetUIData(const NetworkUIData& ui_data, 23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::DictionaryValue* shill_dictionary) { 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::DictionaryValue ui_data_dict; 23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ui_data.FillDictionary(&ui_data_dict); 23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string ui_data_blob; 24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::JSONWriter::Write(&ui_data_dict, &ui_data_blob); 24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) shill_dictionary->SetStringWithoutPathExpansion(shill::kUIDataProperty, 24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ui_data_blob); 24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool CopyIdentifyingProperties(const base::DictionaryValue& service_properties, 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const bool properties_read_from_shill, 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::DictionaryValue* dest) { 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool success = true; 24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // GUID is optional. 25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) CopyStringFromDictionary(service_properties, shill::kGuidProperty, dest); 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string type; 25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) service_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) success &= !type.empty(); 25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dest->SetStringWithoutPathExpansion(shill::kTypeProperty, type); 25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (type == shill::kTypeWifi) { 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string security; 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) service_properties.GetStringWithoutPathExpansion(shill::kSecurityProperty, 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &security); 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (security.empty()) { 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) success = false; 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dest->SetStringWithoutPathExpansion(shill::kSecurityProperty, 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetSecurityClass(security)); 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) success &= 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CopyStringFromDictionary(service_properties, shill::kWifiHexSsid, dest); 26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) success &= CopyStringFromDictionary( 27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) service_properties, shill::kModeProperty, dest); 27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if (type == shill::kTypeVPN) { 27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) success &= CopyStringFromDictionary( 27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) service_properties, shill::kNameProperty, dest); 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // VPN Provider values are read from the "Provider" dictionary, but written 27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // with the keys "Provider.Type" and "Provider.Host". 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(pneubeck): Simplify this once http://crbug.com/381135 is fixed. 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string vpn_provider_type; 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::string vpn_provider_host; 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (properties_read_from_shill) { 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::DictionaryValue* provider_properties = NULL; 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!service_properties.GetDictionaryWithoutPathExpansion( 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) shill::kProviderProperty, &provider_properties)) { 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NET_LOG_ERROR("Missing VPN provider dict", 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetNetworkIdFromProperties(service_properties)); 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) provider_properties->GetStringWithoutPathExpansion(shill::kTypeProperty, 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &vpn_provider_type); 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) provider_properties->GetStringWithoutPathExpansion(shill::kHostProperty, 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &vpn_provider_host); 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) service_properties.GetStringWithoutPathExpansion( 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) shill::kProviderTypeProperty, &vpn_provider_type); 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) service_properties.GetStringWithoutPathExpansion( 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) shill::kProviderHostProperty, &vpn_provider_host); 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) success &= !vpn_provider_type.empty(); 29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dest->SetStringWithoutPathExpansion(shill::kProviderTypeProperty, 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) vpn_provider_type); 30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) success &= !vpn_provider_host.empty(); 30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) dest->SetStringWithoutPathExpansion(shill::kProviderHostProperty, 30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) vpn_provider_host); 30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if (type == shill::kTypeEthernet || type == shill::kTypeEthernetEap) { 30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Ethernet and EthernetEAP don't have any additional identifying 30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // properties. 30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NOTREACHED() << "Unsupported network type " << type; 30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) success = false; 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!success) { 312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NET_LOG_ERROR("Missing required properties", 313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GetNetworkIdFromProperties(service_properties)); 314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return success; 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool DoIdentifyingPropertiesMatch(const base::DictionaryValue& new_properties, 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::DictionaryValue& old_properties) { 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::DictionaryValue new_identifying; 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!CopyIdentifyingProperties( 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new_properties, 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) false /* properties were not read from Shill */, 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &new_identifying)) { 325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::DictionaryValue old_identifying; 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!CopyIdentifyingProperties(old_properties, 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) true /* properties were read from Shill */, 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &old_identifying)) { 331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return new_identifying.Equals(&old_identifying); 335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool IsPassphraseKey(const std::string& key) { 338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return key == shill::kEapPrivateKeyPasswordProperty || 339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kEapPasswordProperty || 340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kL2tpIpsecPasswordProperty || 341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kOpenVPNPasswordProperty || 342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kOpenVPNAuthUserPassProperty || 343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kOpenVPNTLSAuthContentsProperty || 344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kPassphraseProperty || 345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kOpenVPNOTPProperty || 346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kEapPrivateKeyProperty || 347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kEapPinProperty || 348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key == shill::kApnPasswordProperty; 349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool GetHomeProviderFromProperty(const base::Value& value, 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string* home_provider_id) { 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::DictionaryValue* dict = NULL; 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!value.GetAsDictionary(&dict)) 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string home_provider_country; 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string home_provider_name; 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dict->GetStringWithoutPathExpansion(shill::kOperatorCountryKey, 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &home_provider_country); 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dict->GetStringWithoutPathExpansion(shill::kOperatorNameKey, 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &home_provider_name); 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Set home_provider_id 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!home_provider_name.empty() && !home_provider_country.empty()) { 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *home_provider_id = base::StringPrintf( 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "%s (%s)", home_provider_name.c_str(), home_provider_country.c_str()); 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!dict->GetStringWithoutPathExpansion(shill::kOperatorCodeKey, 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) home_provider_id)) { 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(WARNING) 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << "Provider name and country not defined, using code instead: " 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << *home_provider_id; 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace shill_property_util 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace chromeos 381