shill_property_util.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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) ||
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      string_value.empty())
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  dest->SetStringWithoutPathExpansion(key, string_value);
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return true;
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string GetNameFromProperties(const std::string& service_path,
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  const base::DictionaryValue& properties) {
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string name, hex_ssid;
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  properties.GetStringWithoutPathExpansion(flimflam::kNameProperty, &name);
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  properties.GetStringWithoutPathExpansion(flimflam::kWifiHexSsid, &hex_ssid);
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (hex_ssid.empty()) {
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (name.empty())
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return name;
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Validate name for UTF8.
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string valid_ssid = ValidateUTF8(name);
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (valid_ssid != name) {
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      NET_LOG_DEBUG(
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          "GetNameFromProperties",
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          base::StringPrintf(
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)              "%s: UTF8: %s", service_path.c_str(), valid_ssid.c_str()));
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return valid_ssid;
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string ssid;
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::vector<uint8> raw_ssid_bytes;
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (base::HexStringToBytes(hex_ssid, &raw_ssid_bytes)) {
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end());
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NET_LOG_DEBUG("GetNameFromProperties",
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  base::StringPrintf("%s: %s, SSID: %s",
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                     service_path.c_str(),
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                     hex_ssid.c_str(),
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                     ssid.c_str()));
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NET_LOG_ERROR("GetNameFromProperties",
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  base::StringPrintf("%s: Error processing: %s",
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                     service_path.c_str(),
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                     hex_ssid.c_str()));
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return name;
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (IsStringUTF8(ssid)) {
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (ssid != name) {
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      NET_LOG_DEBUG("GetNameFromProperties",
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    base::StringPrintf(
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        "%s: UTF8: %s", service_path.c_str(), ssid.c_str()));
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return ssid;
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Detect encoding and convert to UTF-8.
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string country_code;
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  properties.GetStringWithoutPathExpansion(flimflam::kCountryProperty,
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                           &country_code);
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string encoding;
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!base::DetectEncoding(ssid, &encoding)) {
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // TODO(stevenjb): This is currently experimental. If we find a case where
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // base::DetectEncoding() fails, we need to figure out whether we can use
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // country_code with ConvertToUtf8(). crbug.com/233267.
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    encoding = country_code;
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!encoding.empty()) {
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string utf8_ssid;
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) {
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (utf8_ssid != name) {
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        NET_LOG_DEBUG("GetNameFromProperties",
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      base::StringPrintf("%s: Encoding=%s: %s",
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                         service_path.c_str(),
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                         encoding.c_str(),
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                         utf8_ssid.c_str()));
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return utf8_ssid;
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Unrecognized encoding. Only use raw bytes if name_ is empty.
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NET_LOG_DEBUG("GetNameFromProperties",
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                base::StringPrintf("%s: Unrecognized Encoding=%s: %s",
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   service_path.c_str(),
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   encoding.c_str(),
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   ssid.c_str()));
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (name.empty() && !ssid.empty())
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return ssid;
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return name;
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<NetworkUIData> GetUIDataFromValue(const base::Value& ui_data_value) {
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string ui_data_str;
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!ui_data_value.GetAsString(&ui_data_str))
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return scoped_ptr<NetworkUIData>();
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (ui_data_str.empty())
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return make_scoped_ptr(new NetworkUIData());
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> ui_data_dict(
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      chromeos::onc::ReadDictionaryFromJson(ui_data_str));
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!ui_data_dict)
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return scoped_ptr<NetworkUIData>();
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return make_scoped_ptr(new NetworkUIData(*ui_data_dict));
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<NetworkUIData> GetUIDataFromProperties(
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const base::DictionaryValue& shill_dictionary) {
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const base::Value* ui_data_value = NULL;
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  shill_dictionary.GetWithoutPathExpansion(flimflam::kUIDataProperty,
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                           &ui_data_value);
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!ui_data_value) {
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    VLOG(2) << "Dictionary has no UIData entry.";
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return scoped_ptr<NetworkUIData>();
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<NetworkUIData> ui_data = GetUIDataFromValue(*ui_data_value);
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!ui_data)
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    LOG(ERROR) << "UIData is not a valid JSON dictionary.";
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return ui_data.Pass();
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SetUIData(const NetworkUIData& ui_data,
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)               base::DictionaryValue* shill_dictionary) {
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::DictionaryValue ui_data_dict;
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ui_data.FillDictionary(&ui_data_dict);
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string ui_data_blob;
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::JSONWriter::Write(&ui_data_dict, &ui_data_blob);
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  shill_dictionary->SetStringWithoutPathExpansion(flimflam::kUIDataProperty,
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                  ui_data_blob);
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool CopyIdentifyingProperties(const base::DictionaryValue& service_properties,
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                               base::DictionaryValue* dest) {
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool success = true;
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // GUID is optional.
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CopyStringFromDictionary(service_properties, flimflam::kGuidProperty, dest);
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string type;
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  service_properties.GetStringWithoutPathExpansion(flimflam::kTypeProperty,
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                   &type);
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  success &= !type.empty();
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  dest->SetStringWithoutPathExpansion(flimflam::kTypeProperty, type);
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (type == flimflam::kTypeWifi) {
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    success &= CopyStringFromDictionary(
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        service_properties, flimflam::kSecurityProperty, dest);
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    success &= CopyStringFromDictionary(
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        service_properties, flimflam::kSSIDProperty, dest);
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    success &= CopyStringFromDictionary(
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        service_properties, flimflam::kModeProperty, dest);
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else if (type == flimflam::kTypeVPN) {
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    success &= CopyStringFromDictionary(
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        service_properties, flimflam::kNameProperty, dest);
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // VPN Provider values are read from the "Provider" dictionary, but written
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // with the keys "Provider.Type" and "Provider.Host".
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const base::DictionaryValue* provider_properties = NULL;
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!service_properties.GetDictionaryWithoutPathExpansion(
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             flimflam::kProviderProperty, &provider_properties)) {
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      NET_LOG_ERROR("CopyIdentifyingProperties", "Missing VPN provider dict");
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return false;
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string vpn_provider_type;
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    provider_properties->GetStringWithoutPathExpansion(flimflam::kTypeProperty,
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                       &vpn_provider_type);
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    success &= !vpn_provider_type.empty();
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    dest->SetStringWithoutPathExpansion(flimflam::kProviderTypeProperty,
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                        vpn_provider_type);
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::string vpn_provider_host;
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    provider_properties->GetStringWithoutPathExpansion(flimflam::kHostProperty,
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                       &vpn_provider_host);
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    success &= !vpn_provider_host.empty();
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    dest->SetStringWithoutPathExpansion(flimflam::kProviderHostProperty,
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                        vpn_provider_host);
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else if (type == flimflam::kTypeEthernet ||
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             type == shill::kTypeEthernetEap) {
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Ethernet and EthernetEAP don't have any additional identifying
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // properties.
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NOTREACHED() << "Unsupported network type " << type;
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    success = false;
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!success)
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NET_LOG_ERROR("CopyIdentifyingProperties", "Missing required properties");
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return success;
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace shill_property_util
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kPatternDefault[] = "PatternDefault";
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kPatternEthernet[] = "PatternEthernet";
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kPatternWireless[] = "PatternWireless";
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kPatternMobile[] = "PatternMobile";
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kPatternNonVirtual[] = "PatternNonVirtual";
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)enum NetworkTypeBitFlag {
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kNetworkTypeNone = 0,
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kNetworkTypeEthernet = 1 << 0,
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kNetworkTypeWifi = 1 << 1,
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kNetworkTypeWimax = 1 << 2,
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kNetworkTypeCellular = 1 << 3,
25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kNetworkTypeVPN = 1 << 4,
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kNetworkTypeEthernetEap = 1 << 5
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)struct ShillToBitFlagEntry {
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const char* shill_network_type;
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NetworkTypeBitFlag bit_flag;
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} shill_type_to_flag[] = {
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  { flimflam::kTypeEthernet, kNetworkTypeEthernet },
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  { shill::kTypeEthernetEap, kNetworkTypeEthernetEap },
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  { flimflam::kTypeWifi, kNetworkTypeWifi },
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  { flimflam::kTypeWimax, kNetworkTypeWimax },
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  { flimflam::kTypeCellular, kNetworkTypeCellular },
26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  { flimflam::kTypeVPN, kNetworkTypeVPN }
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypeBitFlag ShillNetworkTypeToFlag(const std::string& shill_type) {
27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < arraysize(shill_type_to_flag); ++i) {
27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (shill_type_to_flag[i].shill_network_type == shill_type)
27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return shill_type_to_flag[i].bit_flag;
27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NET_LOG_ERROR("ShillNetworkTypeToFlag", "Unknown type: " + shill_type);
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return kNetworkTypeNone;
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::Default() {
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(~0);
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::Wireless() {
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeWimax |
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                            kNetworkTypeCellular);
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::Mobile() {
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(kNetworkTypeCellular | kNetworkTypeWimax);
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::NonVirtual() {
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(~kNetworkTypeVPN);
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::Ethernet() {
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(kNetworkTypeEthernet);
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::WiFi() {
30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(kNetworkTypeWifi);
30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::Cellular() {
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(kNetworkTypeCellular);
31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::VPN() {
31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(kNetworkTypeVPN);
31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::Wimax() {
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(kNetworkTypeWimax);
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// static
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern NetworkTypePattern::Primitive(
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& shill_network_type) {
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return NetworkTypePattern(ShillNetworkTypeToFlag(shill_network_type));
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool NetworkTypePattern::Equals(const NetworkTypePattern& other) const {
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return pattern_ == other.pattern_;
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool NetworkTypePattern::MatchesType(
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& shill_network_type) const {
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return MatchesPattern(Primitive(shill_network_type));
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool NetworkTypePattern::MatchesPattern(
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& other_pattern) const {
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Equals(other_pattern))
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return pattern_ & other_pattern.pattern_;
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string NetworkTypePattern::ToDebugString() const {
35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Equals(Default()))
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return kPatternDefault;
35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Equals(Ethernet()))
35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return kPatternEthernet;
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Equals(Wireless()))
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return kPatternWireless;
35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Equals(Mobile()))
35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return kPatternMobile;
35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Equals(NonVirtual()))
35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return kPatternNonVirtual;
36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string str;
36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < arraysize(shill_type_to_flag); ++i) {
36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!(pattern_ & shill_type_to_flag[i].bit_flag))
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      continue;
36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!str.empty())
36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      str += "|";
36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    str += shill_type_to_flag[i].shill_network_type;
36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return str;
37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)NetworkTypePattern::NetworkTypePattern(int pattern) : pattern_(pattern) {}
37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace chromeos
375