summaryrefslogtreecommitdiffstats
path: root/chromeos/network
diff options
context:
space:
mode:
authorstevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-23 00:50:15 +0000
committerstevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-23 00:50:15 +0000
commita7f1d1b75611b9c3d8be54f472df9530a3c8ecdf (patch)
treea5386ae86f7fe2d198bb7a60c3556d4124d2d587 /chromeos/network
parentece17c74d2bbf99c129db6f09694638124386863 (diff)
downloadchromium_src-a7f1d1b75611b9c3d8be54f472df9530a3c8ecdf.zip
chromium_src-a7f1d1b75611b9c3d8be54f472df9530a3c8ecdf.tar.gz
chromium_src-a7f1d1b75611b9c3d8be54f472df9530a3c8ecdf.tar.bz2
Support kWifiHexSsid in NetworkState
BUG=chrome-os-partner:18659 Review URL: https://chromiumcodereview.appspot.com/14046032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195667 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/network')
-rw-r--r--chromeos/network/managed_state.cc3
-rw-r--r--chromeos/network/managed_state.h7
-rw-r--r--chromeos/network/network_event_log.cc4
-rw-r--r--chromeos/network/network_state.cc103
-rw-r--r--chromeos/network/network_state.h7
-rw-r--r--chromeos/network/network_state_handler.cc1
-rw-r--r--chromeos/network/network_state_unittest.cc121
7 files changed, 244 insertions, 2 deletions
diff --git a/chromeos/network/managed_state.cc b/chromeos/network/managed_state.cc
index 556d200..5d9ffe3 100644
--- a/chromeos/network/managed_state.cc
+++ b/chromeos/network/managed_state.cc
@@ -43,6 +43,9 @@ DeviceState* ManagedState::AsDeviceState() {
return NULL;
}
+void ManagedState::InitialPropertiesReceived() {
+}
+
bool ManagedState::ManagedStatePropertyChanged(const std::string& key,
const base::Value& value) {
if (key == flimflam::kNameProperty) {
diff --git a/chromeos/network/managed_state.h b/chromeos/network/managed_state.h
index a8176e5..c7964a3 100644
--- a/chromeos/network/managed_state.h
+++ b/chromeos/network/managed_state.h
@@ -45,6 +45,11 @@ class ManagedState {
virtual bool PropertyChanged(const std::string& key,
const base::Value& value) = 0;
+ // Called by NetworkStateHandler after all calls to PropertyChanged for the
+ // initial set of properties. Used to update state requiring multiple
+ // parsed properties, e.g. name from hex_ssid in NetworkState.
+ virtual void InitialPropertiesReceived();
+
const ManagedType managed_type() const { return managed_type_; }
const std::string& path() const { return path_; }
const std::string& name() const { return name_; }
@@ -70,6 +75,8 @@ class ManagedState {
const base::Value& value,
std::string* out_value);
+ void set_name(const std::string& name) { name_ = name; }
+
private:
friend class NetworkChangeNotifierChromeosUpdateTest;
diff --git a/chromeos/network/network_event_log.cc b/chromeos/network/network_event_log.cc
index be8d0cb..7cb9e84 100644
--- a/chromeos/network/network_event_log.cc
+++ b/chromeos/network/network_event_log.cc
@@ -91,7 +91,7 @@ void NetworkEventLog::AddEntry(const LogEntry& entry) {
if (entries_.size() >= kMaxNetworkEventLogEntries)
entries_.pop_front();
entries_.push_back(entry);
- VLOG(2) << entry.ToString();
+ VLOG(1) << entry.ToString();
}
std::string NetworkEventLog::GetAsString(StringOrder order,
@@ -146,7 +146,7 @@ void AddEntry(const std::string& module,
const std::string& description) {
LogEntry entry(module, event, description);
if (!g_network_event_log) {
- VLOG(2) << entry.ToString();
+ VLOG(1) << entry.ToString();
return;
}
g_network_event_log->AddEntry(entry);
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index 4ab8b17..3aa0472 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -4,12 +4,20 @@
#include "chromeos/network/network_state.h"
+#include "base/i18n/icu_encoding_detection.h"
+#include "base/i18n/icu_string_conversions.h"
+#include "base/string_util.h"
#include "base/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversion_utils.h"
#include "base/values.h"
+#include "chromeos/network/network_event_log.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace {
+const char kLogModule[] = "NetworkState";
+
bool ConvertListValueToStringVector(const base::ListValue& string_list,
std::vector<std::string>* result) {
for (size_t i = 0; i < string_list.GetSize(); ++i) {
@@ -21,6 +29,26 @@ bool ConvertListValueToStringVector(const base::ListValue& string_list,
return true;
}
+// Replace non UTF8 characters in |str| with a replacement character.
+std::string ValidateUTF8(const std::string& str) {
+ std::string result;
+ for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) {
+ uint32 code_point_out;
+ bool is_unicode_char = base::ReadUnicodeCharacter(str.c_str(), str.size(),
+ &index, &code_point_out);
+ const uint32 kFirstNonControlChar = 0x20;
+ if (is_unicode_char && (code_point_out >= kFirstNonControlChar)) {
+ base::WriteUnicodeCharacter(code_point_out, &result);
+ } else {
+ const uint32 kReplacementChar = 0xFFFD;
+ // Puts kReplacementChar if character is a control character [0,0x20)
+ // or is not readable UTF8.
+ base::WriteUnicodeCharacter(kReplacementChar, &result);
+ }
+ }
+ return result;
+}
+
} // namespace
namespace chromeos {
@@ -81,10 +109,22 @@ bool NetworkState::PropertyChanged(const std::string& key,
return GetBooleanValue(key, value, &activate_over_non_cellular_networks_);
} else if (key == shill::kOutOfCreditsProperty) {
return GetBooleanValue(key, value, &cellular_out_of_credits_);
+ } else if (key == flimflam::kWifiHexSsid) {
+ return GetStringValue(key, value, &hex_ssid_);
+ } else if (key == flimflam::kCountryProperty) {
+ // TODO(stevenjb): This is currently experimental. If we find a case where
+ // base::DetectEncoding() fails in UpdateName(), where country_code_ is
+ // set, figure out whether we can use country_code_ with ConvertToUtf8().
+ // crbug.com/233267.
+ return GetStringValue(key, value, &country_code_);
}
return false;
}
+void NetworkState::InitialPropertiesReceived() {
+ UpdateName();
+}
+
void NetworkState::GetProperties(base::DictionaryValue* dictionary) const {
// Keep care that these properties are the same as in |PropertyChanged|.
dictionary->SetStringWithoutPathExpansion(flimflam::kNameProperty, name());
@@ -140,6 +180,69 @@ bool NetworkState::IsConnectingState() const {
return StateIsConnecting(connection_state_);
}
+void NetworkState::UpdateName() {
+ if (hex_ssid_.empty()) {
+ // Validate name for UTF8.
+ std::string valid_ssid = ValidateUTF8(name());
+ if (valid_ssid != name()) {
+ set_name(valid_ssid);
+ network_event_log::AddEntry(
+ kLogModule, "UpdateName",
+ base::StringPrintf("%s: UTF8: %s", path().c_str(), name().c_str()));
+ }
+ return;
+ }
+
+ std::string ssid;
+ std::vector<uint8> raw_ssid_bytes;
+ if (base::HexStringToBytes(hex_ssid_, &raw_ssid_bytes)) {
+ ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end());
+ } else {
+ std::string desc = base::StringPrintf("%s: Error processing: %s",
+ path().c_str(), hex_ssid_.c_str());
+ network_event_log::AddEntry(kLogModule, "UpdateName", desc);
+ LOG(ERROR) << desc;
+ ssid = name();
+ }
+
+ if (IsStringUTF8(ssid)) {
+ if (ssid != name()) {
+ set_name(ssid);
+ network_event_log::AddEntry(
+ kLogModule, "UpdateName",
+ base::StringPrintf("%s: UTF8: %s", path().c_str(), name().c_str()));
+ }
+ return;
+ }
+
+ // Detect encoding and convert to UTF-8.
+ std::string encoding;
+ if (!base::DetectEncoding(ssid, &encoding)) {
+ // TODO(stevenjb): Test this. See comment in PropertyChanged() under
+ // flimflam::kCountryProperty.
+ encoding = country_code_;
+ }
+ if (!encoding.empty()) {
+ std::string utf8_ssid;
+ if (base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) {
+ set_name(utf8_ssid);
+ network_event_log::AddEntry(
+ kLogModule, "UpdateName",
+ base::StringPrintf("%s: Encoding=%s: %s", path().c_str(),
+ encoding.c_str(), name().c_str()));
+ return;
+ }
+ }
+
+ // Unrecognized encoding. Only use raw bytes if name_ is empty.
+ if (name().empty())
+ set_name(ssid);
+ network_event_log::AddEntry(
+ kLogModule, "UpdateName",
+ base::StringPrintf("%s: Unrecognized Encoding=%s: %s", path().c_str(),
+ encoding.c_str(), name().c_str()));
+}
+
// static
bool NetworkState::StateIsConnected(const std::string& connection_state) {
return (connection_state == flimflam::kStateReady ||
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index 3b7d283..1e89638 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -30,6 +30,7 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState {
// If you change this method, update GetProperties too.
virtual bool PropertyChanged(const std::string& key,
const base::Value& value) OVERRIDE;
+ virtual void InitialPropertiesReceived() OVERRIDE;
// Fills |dictionary| with the state properties. All the properties that are
// accepted by PropertyChanged are stored in |dictionary|, no other values are
@@ -74,6 +75,9 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState {
friend class NetworkStateHandler;
friend class NetworkChangeNotifierChromeosUpdateTest;
+ // Updates the name from hex_ssid_ if provided, and validates name_.
+ void UpdateName();
+
// Called by NetworkStateHandler when the ip config changes.
void set_ip_address(const std::string& ip_address) {
ip_address_ = ip_address;
@@ -99,6 +103,9 @@ class CHROMEOS_EXPORT NetworkState : public ManagedState {
std::vector<std::string> dns_servers_;
// Wireless properties
int signal_strength_;
+ // Wifi properties
+ std::string hex_ssid_;
+ std::string country_code_;
// Cellular properties
std::string technology_;
std::string activation_state_;
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index 75c3dcf..863e20f 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -399,6 +399,7 @@ void NetworkStateHandler::UpdateManagedStateProperties(
managed->PropertyChanged(iter.key(), iter.value());
}
}
+ managed->InitialPropertiesReceived();
network_event_log::AddEntry(
kLogModule, "PropertiesReceived",
base::StringPrintf("%s (%s)", path.c_str(), managed->name().c_str()));
diff --git a/chromeos/network/network_state_unittest.cc b/chromeos/network/network_state_unittest.cc
new file mode 100644
index 0000000..7c7bc41
--- /dev/null
+++ b/chromeos/network/network_state_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/network/network_state.h"
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+namespace {
+
+class TestStringValue : public base::Value {
+ public:
+ TestStringValue(const std::string& in_value)
+ : base::Value(TYPE_STRING),
+ value_(in_value) {
+ }
+
+ ~TestStringValue() {
+ }
+
+ // Overridden from Value:
+ virtual bool GetAsString(std::string* out_value) const OVERRIDE {
+ if (out_value)
+ *out_value = value_;
+ return true;
+ }
+
+ virtual TestStringValue* DeepCopy() const OVERRIDE {
+ return new TestStringValue(value_);
+ }
+
+ virtual bool Equals(const Value* other) const OVERRIDE {
+ if (other->GetType() != GetType())
+ return false;
+ std::string lhs, rhs;
+ return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs;
+ }
+
+ private:
+ std::string value_;
+};
+
+class NetworkStateTest : public testing::Test {
+ public:
+ NetworkStateTest() : network_state_("test_path") {
+ }
+
+ protected:
+ bool SetStringProperty(const std::string& key, const std::string& value) {
+ if (!network_state_.PropertyChanged(key, TestStringValue(value)))
+ return false;
+ network_state_.InitialPropertiesReceived();
+ return true;
+ }
+
+ NetworkState network_state_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkStateTest);
+};
+
+} // namespace
+
+// Seting kNameProperty should set network name after call to
+// InitialPropertiesReceived() in SetStringProperty().
+TEST_F(NetworkStateTest, SsidAscii) {
+ std::string wifi_setname = "SSID TEST";
+ std::string wifi_setname_result = "SSID TEST";
+ EXPECT_TRUE(SetStringProperty(flimflam::kNameProperty, wifi_setname));
+ EXPECT_EQ(network_state_.name(), wifi_setname_result);
+}
+
+TEST_F(NetworkStateTest, SsidAsciiWithNull) {
+ std::string wifi_setname = "SSID TEST\x00xxx";
+ std::string wifi_setname_result = "SSID TEST";
+ EXPECT_TRUE(SetStringProperty(flimflam::kNameProperty, wifi_setname));
+ EXPECT_EQ(network_state_.name(), wifi_setname_result);
+}
+
+// UTF8 SSID
+TEST_F(NetworkStateTest, SsidUtf8) {
+ std::string wifi_utf8 = "UTF-8 \u3042\u3044\u3046";
+ std::string wifi_utf8_result = "UTF-8 \xE3\x81\x82\xE3\x81\x84\xE3\x81\x86";
+ EXPECT_TRUE(SetStringProperty(flimflam::kNameProperty, wifi_utf8));
+ EXPECT_EQ(network_state_.name(), wifi_utf8_result);
+}
+
+// Truncates invalid UTF-8
+TEST_F(NetworkStateTest, SsidTruncateInvalid) {
+ std::string wifi_setname2 = "SSID TEST \x01\xff!";
+ std::string wifi_setname2_result = "SSID TEST \xEF\xBF\xBD\xEF\xBF\xBD!";
+ EXPECT_TRUE(SetStringProperty(flimflam::kNameProperty, wifi_setname2));
+ EXPECT_EQ(network_state_.name(), wifi_setname2_result);
+}
+
+// latin1 SSID -> UTF8 SSID (Hex)
+TEST_F(NetworkStateTest, SsidLatin) {
+ std::string wifi_latin1 = "latin-1 \xc0\xcb\xcc\xd6\xfb";
+ std::string wifi_latin1_hex =
+ base::HexEncode(wifi_latin1.c_str(), wifi_latin1.length());
+ std::string wifi_latin1_result = "latin-1 \u00c0\u00cb\u00cc\u00d6\u00fb";
+ EXPECT_TRUE(SetStringProperty(flimflam::kWifiHexSsid, wifi_latin1_hex));
+ EXPECT_EQ(network_state_.name(), wifi_latin1_result);
+}
+
+// Hex SSID
+TEST_F(NetworkStateTest, SsidHex) {
+ std::string wifi_hex = "5468697320697320484558205353494421";
+ std::string wifi_hex_result = "This is HEX SSID!";
+ SetStringProperty(flimflam::kWifiHexSsid, wifi_hex);
+ EXPECT_EQ(network_state_.name(), wifi_hex_result);
+}
+
+} // namespace chromeos