Add very simple loading test for non-SFI NaCl.
[chromium-blink-merge.git] / chromeos / network / shill_property_util.cc
blobd0d33d3a6742f4e62509375f7b0ba980b35e6584
1 // Copyright 2013 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.
5 #include "chromeos/network/shill_property_util.h"
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"
13 #include "base/strings/utf_string_conversion_utils.h"
14 #include "base/values.h"
15 #include "chromeos/network/network_event_log.h"
16 #include "chromeos/network/network_ui_data.h"
17 #include "chromeos/network/onc/onc_utils.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
20 namespace chromeos {
22 namespace shill_property_util {
24 namespace {
26 // Replace non UTF8 characters in |str| with a replacement character.
27 std::string ValidateUTF8(const std::string& str) {
28 std::string result;
29 for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) {
30 uint32 code_point_out;
31 bool is_unicode_char = base::ReadUnicodeCharacter(
32 str.c_str(), str.size(), &index, &code_point_out);
33 const uint32 kFirstNonControlChar = 0x20;
34 if (is_unicode_char && (code_point_out >= kFirstNonControlChar)) {
35 base::WriteUnicodeCharacter(code_point_out, &result);
36 } else {
37 const uint32 kReplacementChar = 0xFFFD;
38 // Puts kReplacementChar if character is a control character [0,0x20)
39 // or is not readable UTF8.
40 base::WriteUnicodeCharacter(kReplacementChar, &result);
43 return result;
46 // If existent and non-empty, copies the string at |key| from |source| to
47 // |dest|. Returns true if the string was copied.
48 bool CopyStringFromDictionary(const base::DictionaryValue& source,
49 const std::string& key,
50 base::DictionaryValue* dest) {
51 std::string string_value;
52 if (!source.GetStringWithoutPathExpansion(key, &string_value) ||
53 string_value.empty())
54 return false;
55 dest->SetStringWithoutPathExpansion(key, string_value);
56 return true;
59 } // namespace
61 void SetSSID(const std::string ssid, base::DictionaryValue* properties) {
62 std::string hex_ssid = base::HexEncode(ssid.c_str(), ssid.size());
63 properties->SetStringWithoutPathExpansion(shill::kWifiHexSsid, hex_ssid);
66 std::string GetSSIDFromProperties(const base::DictionaryValue& properties,
67 bool* unknown_encoding) {
68 if (unknown_encoding)
69 *unknown_encoding = false;
70 std::string hex_ssid;
71 properties.GetStringWithoutPathExpansion(shill::kWifiHexSsid, &hex_ssid);
73 if (hex_ssid.empty()) {
74 NET_LOG_ERROR("GetSSIDFromProperties", "No HexSSID set.");
75 return std::string();
78 std::string ssid;
79 std::vector<uint8> raw_ssid_bytes;
80 if (base::HexStringToBytes(hex_ssid, &raw_ssid_bytes)) {
81 ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end());
82 NET_LOG_DEBUG(
83 "GetSSIDFromProperties",
84 base::StringPrintf("%s, SSID: %s", hex_ssid.c_str(), ssid.c_str()));
85 } else {
86 NET_LOG_ERROR("GetSSIDFromProperties",
87 base::StringPrintf("Error processing: %s", hex_ssid.c_str()));
88 return std::string();
91 if (IsStringUTF8(ssid))
92 return ssid;
94 // Detect encoding and convert to UTF-8.
95 std::string encoding;
96 if (!base::DetectEncoding(ssid, &encoding)) {
97 // TODO(stevenjb): This is currently experimental. If we find a case where
98 // base::DetectEncoding() fails, we need to figure out whether we can use
99 // country_code with ConvertToUtf8(). crbug.com/233267.
100 properties.GetStringWithoutPathExpansion(shill::kCountryProperty,
101 &encoding);
103 std::string utf8_ssid;
104 if (!encoding.empty() &&
105 base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) {
106 if (utf8_ssid != ssid) {
107 NET_LOG_DEBUG(
108 "GetSSIDFromProperties",
109 base::StringPrintf(
110 "Encoding=%s: %s", encoding.c_str(), utf8_ssid.c_str()));
112 return utf8_ssid;
115 if (unknown_encoding)
116 *unknown_encoding = true;
117 NET_LOG_DEBUG(
118 "GetSSIDFromProperties",
119 base::StringPrintf("Unrecognized Encoding=%s", encoding.c_str()));
120 return ssid;
123 std::string GetNameFromProperties(const std::string& service_path,
124 const base::DictionaryValue& properties) {
125 std::string name;
126 properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name);
128 std::string validated_name = ValidateUTF8(name);
129 if (validated_name != name) {
130 NET_LOG_DEBUG("GetNameFromProperties",
131 base::StringPrintf("Validated name %s: UTF8: %s",
132 service_path.c_str(),
133 validated_name.c_str()));
136 std::string type;
137 properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
138 if (!NetworkTypePattern::WiFi().MatchesType(type))
139 return validated_name;
141 bool unknown_ssid_encoding = false;
142 std::string ssid = GetSSIDFromProperties(properties, &unknown_ssid_encoding);
143 if (ssid.empty())
144 NET_LOG_ERROR("GetNameFromProperties", "No SSID set: " + service_path);
146 // Use |validated_name| if |ssid| is empty.
147 // And if the encoding of the SSID is unknown, use |ssid|, which contains raw
148 // bytes in that case, only if |validated_name| is empty.
149 if (ssid.empty() || (unknown_ssid_encoding && !validated_name.empty()))
150 return validated_name;
152 if (ssid != validated_name) {
153 NET_LOG_DEBUG("GetNameFromProperties",
154 base::StringPrintf("%s: SSID: %s, Name: %s",
155 service_path.c_str(),
156 ssid.c_str(),
157 validated_name.c_str()));
159 return ssid;
162 scoped_ptr<NetworkUIData> GetUIDataFromValue(const base::Value& ui_data_value) {
163 std::string ui_data_str;
164 if (!ui_data_value.GetAsString(&ui_data_str))
165 return scoped_ptr<NetworkUIData>();
166 if (ui_data_str.empty())
167 return make_scoped_ptr(new NetworkUIData());
168 scoped_ptr<base::DictionaryValue> ui_data_dict(
169 chromeos::onc::ReadDictionaryFromJson(ui_data_str));
170 if (!ui_data_dict)
171 return scoped_ptr<NetworkUIData>();
172 return make_scoped_ptr(new NetworkUIData(*ui_data_dict));
175 scoped_ptr<NetworkUIData> GetUIDataFromProperties(
176 const base::DictionaryValue& shill_dictionary) {
177 const base::Value* ui_data_value = NULL;
178 shill_dictionary.GetWithoutPathExpansion(shill::kUIDataProperty,
179 &ui_data_value);
180 if (!ui_data_value) {
181 VLOG(2) << "Dictionary has no UIData entry.";
182 return scoped_ptr<NetworkUIData>();
184 scoped_ptr<NetworkUIData> ui_data = GetUIDataFromValue(*ui_data_value);
185 if (!ui_data)
186 LOG(ERROR) << "UIData is not a valid JSON dictionary.";
187 return ui_data.Pass();
190 void SetUIData(const NetworkUIData& ui_data,
191 base::DictionaryValue* shill_dictionary) {
192 base::DictionaryValue ui_data_dict;
193 ui_data.FillDictionary(&ui_data_dict);
194 std::string ui_data_blob;
195 base::JSONWriter::Write(&ui_data_dict, &ui_data_blob);
196 shill_dictionary->SetStringWithoutPathExpansion(shill::kUIDataProperty,
197 ui_data_blob);
200 bool CopyIdentifyingProperties(const base::DictionaryValue& service_properties,
201 base::DictionaryValue* dest) {
202 bool success = true;
204 // GUID is optional.
205 CopyStringFromDictionary(service_properties, shill::kGuidProperty, dest);
207 std::string type;
208 service_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
209 success &= !type.empty();
210 dest->SetStringWithoutPathExpansion(shill::kTypeProperty, type);
211 if (type == shill::kTypeWifi) {
212 success &= CopyStringFromDictionary(
213 service_properties, shill::kSecurityProperty, dest);
214 success &=
215 CopyStringFromDictionary(service_properties, shill::kWifiHexSsid, dest);
216 success &= CopyStringFromDictionary(
217 service_properties, shill::kModeProperty, dest);
218 } else if (type == shill::kTypeVPN) {
219 success &= CopyStringFromDictionary(
220 service_properties, shill::kNameProperty, dest);
221 // VPN Provider values are read from the "Provider" dictionary, but written
222 // with the keys "Provider.Type" and "Provider.Host".
223 const base::DictionaryValue* provider_properties = NULL;
224 if (!service_properties.GetDictionaryWithoutPathExpansion(
225 shill::kProviderProperty, &provider_properties)) {
226 NET_LOG_ERROR("CopyIdentifyingProperties", "Missing VPN provider dict");
227 return false;
229 std::string vpn_provider_type;
230 provider_properties->GetStringWithoutPathExpansion(shill::kTypeProperty,
231 &vpn_provider_type);
232 success &= !vpn_provider_type.empty();
233 dest->SetStringWithoutPathExpansion(shill::kProviderTypeProperty,
234 vpn_provider_type);
236 std::string vpn_provider_host;
237 provider_properties->GetStringWithoutPathExpansion(shill::kHostProperty,
238 &vpn_provider_host);
239 success &= !vpn_provider_host.empty();
240 dest->SetStringWithoutPathExpansion(shill::kProviderHostProperty,
241 vpn_provider_host);
242 } else if (type == shill::kTypeEthernet || type == shill::kTypeEthernetEap) {
243 // Ethernet and EthernetEAP don't have any additional identifying
244 // properties.
245 } else {
246 NOTREACHED() << "Unsupported network type " << type;
247 success = false;
249 if (!success)
250 NET_LOG_ERROR("CopyIdentifyingProperties", "Missing required properties");
251 return success;
254 bool DoIdentifyingPropertiesMatch(const base::DictionaryValue& properties_a,
255 const base::DictionaryValue& properties_b) {
256 base::DictionaryValue identifying_a;
257 if (!CopyIdentifyingProperties(properties_a, &identifying_a))
258 return false;
259 base::DictionaryValue identifying_b;
260 if (!CopyIdentifyingProperties(properties_b, &identifying_b))
261 return false;
263 return identifying_a.Equals(&identifying_b);
266 } // namespace shill_property_util
268 namespace {
270 const char kPatternDefault[] = "PatternDefault";
271 const char kPatternEthernet[] = "PatternEthernet";
272 const char kPatternWireless[] = "PatternWireless";
273 const char kPatternMobile[] = "PatternMobile";
274 const char kPatternNonVirtual[] = "PatternNonVirtual";
276 enum NetworkTypeBitFlag {
277 kNetworkTypeNone = 0,
278 kNetworkTypeEthernet = 1 << 0,
279 kNetworkTypeWifi = 1 << 1,
280 kNetworkTypeWimax = 1 << 2,
281 kNetworkTypeCellular = 1 << 3,
282 kNetworkTypeVPN = 1 << 4,
283 kNetworkTypeEthernetEap = 1 << 5,
284 kNetworkTypeBluetooth = 1 << 6
287 struct ShillToBitFlagEntry {
288 const char* shill_network_type;
289 NetworkTypeBitFlag bit_flag;
290 } shill_type_to_flag[] = {
291 { shill::kTypeEthernet, kNetworkTypeEthernet },
292 { shill::kTypeEthernetEap, kNetworkTypeEthernetEap },
293 { shill::kTypeWifi, kNetworkTypeWifi },
294 { shill::kTypeWimax, kNetworkTypeWimax },
295 { shill::kTypeCellular, kNetworkTypeCellular },
296 { shill::kTypeVPN, kNetworkTypeVPN },
297 { shill::kTypeBluetooth, kNetworkTypeBluetooth }
300 NetworkTypeBitFlag ShillNetworkTypeToFlag(const std::string& shill_type) {
301 for (size_t i = 0; i < arraysize(shill_type_to_flag); ++i) {
302 if (shill_type_to_flag[i].shill_network_type == shill_type)
303 return shill_type_to_flag[i].bit_flag;
305 NET_LOG_ERROR("ShillNetworkTypeToFlag", "Unknown type: " + shill_type);
306 return kNetworkTypeNone;
309 } // namespace
311 // static
312 NetworkTypePattern NetworkTypePattern::Default() {
313 return NetworkTypePattern(~0);
316 // static
317 NetworkTypePattern NetworkTypePattern::Wireless() {
318 return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeWimax |
319 kNetworkTypeCellular);
322 // static
323 NetworkTypePattern NetworkTypePattern::Mobile() {
324 return NetworkTypePattern(kNetworkTypeCellular | kNetworkTypeWimax);
327 // static
328 NetworkTypePattern NetworkTypePattern::NonVirtual() {
329 return NetworkTypePattern(~kNetworkTypeVPN);
332 // static
333 NetworkTypePattern NetworkTypePattern::Ethernet() {
334 return NetworkTypePattern(kNetworkTypeEthernet);
337 // static
338 NetworkTypePattern NetworkTypePattern::WiFi() {
339 return NetworkTypePattern(kNetworkTypeWifi);
342 // static
343 NetworkTypePattern NetworkTypePattern::Cellular() {
344 return NetworkTypePattern(kNetworkTypeCellular);
347 // static
348 NetworkTypePattern NetworkTypePattern::VPN() {
349 return NetworkTypePattern(kNetworkTypeVPN);
352 // static
353 NetworkTypePattern NetworkTypePattern::Wimax() {
354 return NetworkTypePattern(kNetworkTypeWimax);
357 // static
358 NetworkTypePattern NetworkTypePattern::Primitive(
359 const std::string& shill_network_type) {
360 return NetworkTypePattern(ShillNetworkTypeToFlag(shill_network_type));
363 bool NetworkTypePattern::Equals(const NetworkTypePattern& other) const {
364 return pattern_ == other.pattern_;
367 bool NetworkTypePattern::MatchesType(
368 const std::string& shill_network_type) const {
369 return MatchesPattern(Primitive(shill_network_type));
372 bool NetworkTypePattern::MatchesPattern(
373 const NetworkTypePattern& other_pattern) const {
374 if (Equals(other_pattern))
375 return true;
377 return pattern_ & other_pattern.pattern_;
380 std::string NetworkTypePattern::ToDebugString() const {
381 if (Equals(Default()))
382 return kPatternDefault;
383 if (Equals(Ethernet()))
384 return kPatternEthernet;
385 if (Equals(Wireless()))
386 return kPatternWireless;
387 if (Equals(Mobile()))
388 return kPatternMobile;
389 if (Equals(NonVirtual()))
390 return kPatternNonVirtual;
392 std::string str;
393 for (size_t i = 0; i < arraysize(shill_type_to_flag); ++i) {
394 if (!(pattern_ & shill_type_to_flag[i].bit_flag))
395 continue;
396 if (!str.empty())
397 str += "|";
398 str += shill_type_to_flag[i].shill_network_type;
400 return str;
403 NetworkTypePattern::NetworkTypePattern(int pattern) : pattern_(pattern) {}
405 } // namespace chromeos