diff options
author | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-23 00:50:15 +0000 |
---|---|---|
committer | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-23 00:50:15 +0000 |
commit | a7f1d1b75611b9c3d8be54f472df9530a3c8ecdf (patch) | |
tree | a5386ae86f7fe2d198bb7a60c3556d4124d2d587 /chromeos/network | |
parent | ece17c74d2bbf99c129db6f09694638124386863 (diff) | |
download | chromium_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.cc | 3 | ||||
-rw-r--r-- | chromeos/network/managed_state.h | 7 | ||||
-rw-r--r-- | chromeos/network/network_event_log.cc | 4 | ||||
-rw-r--r-- | chromeos/network/network_state.cc | 103 | ||||
-rw-r--r-- | chromeos/network/network_state.h | 7 | ||||
-rw-r--r-- | chromeos/network/network_state_handler.cc | 1 | ||||
-rw-r--r-- | chromeos/network/network_state_unittest.cc | 121 |
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 |