Use Persistent::Reset.
[chromium-blink-merge.git] / chromeos / network / network_state.cc
blob3aa0472174b3f2ed729e632706b11bd27498982d
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
3 // found in the LICENSE file.
5 #include "chromeos/network/network_state.h"
7 #include "base/i18n/icu_encoding_detection.h"
8 #include "base/i18n/icu_string_conversions.h"
9 #include "base/string_util.h"
10 #include "base/stringprintf.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversion_utils.h"
13 #include "base/values.h"
14 #include "chromeos/network/network_event_log.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
17 namespace {
19 const char kLogModule[] = "NetworkState";
21 bool ConvertListValueToStringVector(const base::ListValue& string_list,
22 std::vector<std::string>* result) {
23 for (size_t i = 0; i < string_list.GetSize(); ++i) {
24 std::string str;
25 if (!string_list.GetString(i, &str))
26 return false;
27 result->push_back(str);
29 return true;
32 // Replace non UTF8 characters in |str| with a replacement character.
33 std::string ValidateUTF8(const std::string& str) {
34 std::string result;
35 for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) {
36 uint32 code_point_out;
37 bool is_unicode_char = base::ReadUnicodeCharacter(str.c_str(), str.size(),
38 &index, &code_point_out);
39 const uint32 kFirstNonControlChar = 0x20;
40 if (is_unicode_char && (code_point_out >= kFirstNonControlChar)) {
41 base::WriteUnicodeCharacter(code_point_out, &result);
42 } else {
43 const uint32 kReplacementChar = 0xFFFD;
44 // Puts kReplacementChar if character is a control character [0,0x20)
45 // or is not readable UTF8.
46 base::WriteUnicodeCharacter(kReplacementChar, &result);
49 return result;
52 } // namespace
54 namespace chromeos {
56 NetworkState::NetworkState(const std::string& path)
57 : ManagedState(MANAGED_TYPE_NETWORK, path),
58 auto_connect_(false),
59 favorite_(false),
60 priority_(0),
61 signal_strength_(0),
62 activate_over_non_cellular_networks_(false),
63 cellular_out_of_credits_(false) {
66 NetworkState::~NetworkState() {
69 bool NetworkState::PropertyChanged(const std::string& key,
70 const base::Value& value) {
71 // Keep care that these properties are the same as in |GetProperties|.
72 if (ManagedStatePropertyChanged(key, value))
73 return true;
74 if (key == flimflam::kSignalStrengthProperty) {
75 return GetIntegerValue(key, value, &signal_strength_);
76 } else if (key == flimflam::kStateProperty) {
77 return GetStringValue(key, value, &connection_state_);
78 } else if (key == flimflam::kErrorProperty) {
79 return GetStringValue(key, value, &error_);
80 } else if (key == IPConfigProperty(flimflam::kAddressProperty)) {
81 return GetStringValue(key, value, &ip_address_);
82 } else if (key == IPConfigProperty(flimflam::kNameServersProperty)) {
83 dns_servers_.clear();
84 const base::ListValue* dns_servers;
85 if (value.GetAsList(&dns_servers) &&
86 ConvertListValueToStringVector(*dns_servers, &dns_servers_))
87 return true;
88 } else if (key == flimflam::kActivationStateProperty) {
89 return GetStringValue(key, value, &activation_state_);
90 } else if (key == flimflam::kRoamingStateProperty) {
91 return GetStringValue(key, value, &roaming_);
92 } else if (key == flimflam::kSecurityProperty) {
93 return GetStringValue(key, value, &security_);
94 } else if (key == flimflam::kAutoConnectProperty) {
95 return GetBooleanValue(key, value, &auto_connect_);
96 } else if (key == flimflam::kFavoriteProperty) {
97 return GetBooleanValue(key, value, &favorite_);
98 } else if (key == flimflam::kPriorityProperty) {
99 return GetIntegerValue(key, value, &priority_);
100 } else if (key == flimflam::kNetworkTechnologyProperty) {
101 return GetStringValue(key, value, &technology_);
102 } else if (key == flimflam::kDeviceProperty) {
103 return GetStringValue(key, value, &device_path_);
104 } else if (key == flimflam::kGuidProperty) {
105 return GetStringValue(key, value, &guid_);
106 } else if (key == flimflam::kProfileProperty) {
107 return GetStringValue(key, value, &profile_path_);
108 } else if (key == shill::kActivateOverNonCellularNetworkProperty) {
109 return GetBooleanValue(key, value, &activate_over_non_cellular_networks_);
110 } else if (key == shill::kOutOfCreditsProperty) {
111 return GetBooleanValue(key, value, &cellular_out_of_credits_);
112 } else if (key == flimflam::kWifiHexSsid) {
113 return GetStringValue(key, value, &hex_ssid_);
114 } else if (key == flimflam::kCountryProperty) {
115 // TODO(stevenjb): This is currently experimental. If we find a case where
116 // base::DetectEncoding() fails in UpdateName(), where country_code_ is
117 // set, figure out whether we can use country_code_ with ConvertToUtf8().
118 // crbug.com/233267.
119 return GetStringValue(key, value, &country_code_);
121 return false;
124 void NetworkState::InitialPropertiesReceived() {
125 UpdateName();
128 void NetworkState::GetProperties(base::DictionaryValue* dictionary) const {
129 // Keep care that these properties are the same as in |PropertyChanged|.
130 dictionary->SetStringWithoutPathExpansion(flimflam::kNameProperty, name());
131 dictionary->SetStringWithoutPathExpansion(flimflam::kTypeProperty, type());
132 dictionary->SetIntegerWithoutPathExpansion(flimflam::kSignalStrengthProperty,
133 signal_strength());
134 dictionary->SetStringWithoutPathExpansion(flimflam::kStateProperty,
135 connection_state());
136 dictionary->SetStringWithoutPathExpansion(flimflam::kErrorProperty,
137 error());
138 base::DictionaryValue* ipconfig_properties = new DictionaryValue;
139 ipconfig_properties->SetStringWithoutPathExpansion(flimflam::kAddressProperty,
140 ip_address());
141 base::ListValue* name_servers = new ListValue;
142 name_servers->AppendStrings(dns_servers());
143 ipconfig_properties->SetWithoutPathExpansion(flimflam::kNameServersProperty,
144 name_servers);
145 dictionary->SetWithoutPathExpansion(shill::kIPConfigProperty,
146 ipconfig_properties);
148 dictionary->SetStringWithoutPathExpansion(flimflam::kActivationStateProperty,
149 activation_state());
150 dictionary->SetStringWithoutPathExpansion(flimflam::kRoamingStateProperty,
151 roaming());
152 dictionary->SetStringWithoutPathExpansion(flimflam::kSecurityProperty,
153 security());
154 dictionary->SetBooleanWithoutPathExpansion(flimflam::kAutoConnectProperty,
155 auto_connect());
156 dictionary->SetBooleanWithoutPathExpansion(flimflam::kFavoriteProperty,
157 favorite());
158 dictionary->SetIntegerWithoutPathExpansion(flimflam::kPriorityProperty,
159 priority());
160 dictionary->SetStringWithoutPathExpansion(
161 flimflam::kNetworkTechnologyProperty,
162 technology());
163 dictionary->SetStringWithoutPathExpansion(flimflam::kDeviceProperty,
164 device_path());
165 dictionary->SetStringWithoutPathExpansion(flimflam::kGuidProperty, guid());
166 dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty,
167 profile_path());
168 dictionary->SetBooleanWithoutPathExpansion(
169 shill::kActivateOverNonCellularNetworkProperty,
170 activate_over_non_cellular_networks());
171 dictionary->SetBooleanWithoutPathExpansion(shill::kOutOfCreditsProperty,
172 cellular_out_of_credits());
175 bool NetworkState::IsConnectedState() const {
176 return StateIsConnected(connection_state_);
179 bool NetworkState::IsConnectingState() const {
180 return StateIsConnecting(connection_state_);
183 void NetworkState::UpdateName() {
184 if (hex_ssid_.empty()) {
185 // Validate name for UTF8.
186 std::string valid_ssid = ValidateUTF8(name());
187 if (valid_ssid != name()) {
188 set_name(valid_ssid);
189 network_event_log::AddEntry(
190 kLogModule, "UpdateName",
191 base::StringPrintf("%s: UTF8: %s", path().c_str(), name().c_str()));
193 return;
196 std::string ssid;
197 std::vector<uint8> raw_ssid_bytes;
198 if (base::HexStringToBytes(hex_ssid_, &raw_ssid_bytes)) {
199 ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end());
200 } else {
201 std::string desc = base::StringPrintf("%s: Error processing: %s",
202 path().c_str(), hex_ssid_.c_str());
203 network_event_log::AddEntry(kLogModule, "UpdateName", desc);
204 LOG(ERROR) << desc;
205 ssid = name();
208 if (IsStringUTF8(ssid)) {
209 if (ssid != name()) {
210 set_name(ssid);
211 network_event_log::AddEntry(
212 kLogModule, "UpdateName",
213 base::StringPrintf("%s: UTF8: %s", path().c_str(), name().c_str()));
215 return;
218 // Detect encoding and convert to UTF-8.
219 std::string encoding;
220 if (!base::DetectEncoding(ssid, &encoding)) {
221 // TODO(stevenjb): Test this. See comment in PropertyChanged() under
222 // flimflam::kCountryProperty.
223 encoding = country_code_;
225 if (!encoding.empty()) {
226 std::string utf8_ssid;
227 if (base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) {
228 set_name(utf8_ssid);
229 network_event_log::AddEntry(
230 kLogModule, "UpdateName",
231 base::StringPrintf("%s: Encoding=%s: %s", path().c_str(),
232 encoding.c_str(), name().c_str()));
233 return;
237 // Unrecognized encoding. Only use raw bytes if name_ is empty.
238 if (name().empty())
239 set_name(ssid);
240 network_event_log::AddEntry(
241 kLogModule, "UpdateName",
242 base::StringPrintf("%s: Unrecognized Encoding=%s: %s", path().c_str(),
243 encoding.c_str(), name().c_str()));
246 // static
247 bool NetworkState::StateIsConnected(const std::string& connection_state) {
248 return (connection_state == flimflam::kStateReady ||
249 connection_state == flimflam::kStateOnline ||
250 connection_state == flimflam::kStatePortal);
253 // static
254 bool NetworkState::StateIsConnecting(const std::string& connection_state) {
255 return (connection_state == flimflam::kStateAssociation ||
256 connection_state == flimflam::kStateConfiguration ||
257 connection_state == flimflam::kStateCarrier);
260 // static
261 std::string NetworkState::IPConfigProperty(const char* key) {
262 return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key);
265 } // namespace chromeos