Home | History | Annotate | Download | only in cros
      1 // Copyright (c) 2011 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.
      4 
      5 #include "chrome/browser/chromeos/cros/network_library.h"
      6 
      7 #include <algorithm>
      8 #include <map>
      9 
     10 #include "base/i18n/icu_encoding_detection.h"
     11 #include "base/i18n/icu_string_conversions.h"
     12 #include "base/i18n/time_formatting.h"
     13 #include "base/metrics/histogram.h"
     14 #include "base/stl_util-inl.h"
     15 #include "base/string_number_conversions.h"
     16 #include "base/string_util.h"
     17 #include "base/stringprintf.h"
     18 #include "base/utf_string_conversions.h"
     19 #include "base/utf_string_conversion_utils.h"
     20 #include "base/values.h"
     21 #include "chrome/browser/chromeos/cros/cros_library.h"
     22 #include "chrome/browser/chromeos/login/user_manager.h"
     23 #include "chrome/browser/chromeos/network_login_observer.h"
     24 #include "chrome/browser/chromeos/user_cros_settings_provider.h"
     25 #include "chrome/common/time_format.h"
     26 #include "content/browser/browser_thread.h"
     27 #include "grit/generated_resources.h"
     28 #include "ui/base/l10n/l10n_util.h"
     29 
     30 ////////////////////////////////////////////////////////////////////////////////
     31 // Implementation notes.
     32 // NetworkLibraryImpl manages a series of classes that describe network devices
     33 // and services:
     34 //
     35 // NetworkDevice: e.g. ethernet, wifi modem, cellular modem
     36 //  device_map_: canonical map<path,NetworkDevice*> for devices
     37 //
     38 // Network: a network service ("network").
     39 //  network_map_: canonical map<path,Network*> for all visible networks.
     40 //  EthernetNetwork
     41 //   ethernet_: EthernetNetwork* to the active ethernet network in network_map_.
     42 //  WirelessNetwork: a Wifi or Cellular Network.
     43 //  WifiNetwork
     44 //   active_wifi_: WifiNetwork* to the active wifi network in network_map_.
     45 //   wifi_networks_: ordered vector of WifiNetwork* entries in network_map_,
     46 //       in descending order of importance.
     47 //  CellularNetwork
     48 //   active_cellular_: Cellular version of wifi_.
     49 //   cellular_networks_: Cellular version of wifi_.
     50 // network_unique_id_map_: map<unique_id,Network*> for visible networks.
     51 // remembered_network_map_: a canonical map<path,Network*> for all networks
     52 //     remembered in the active Profile ("favorites").
     53 // remembered_wifi_networks_: ordered vector of WifiNetwork* entries in
     54 //     remembered_network_map_, in descending order of preference.
     55 //
     56 // network_manager_monitor_: a handle to the libcros network Manager handler.
     57 // NetworkManagerStatusChanged: This handles all messages from the Manager.
     58 //   Messages are parsed here and the appropriate updates are then requested.
     59 //
     60 // UpdateNetworkServiceList: This is the primary Manager handler. It handles
     61 //  the "Services" message which list all visible networks. The handler
     62 //  rebuilds the network lists without destroying existing Network structures,
     63 //  then requests neccessary updates to be fetched asynchronously from
     64 //  libcros (RequestNetworkServiceInfo).
     65 //
     66 // TODO(stevenjb): Document cellular data plan handlers.
     67 //
     68 // AddNetworkObserver: Adds an observer for a specific network.
     69 // NetworkObserverList: A monitor and list of observers of a network.
     70 // network_monitor_: a handle to the libcros network Service handler.
     71 // UpdateNetworkStatus: This handles changes to a monitored service, typically
     72 //     changes to transient states like Strength. (Note: also updates State).
     73 //
     74 // AddNetworkDeviceObserver: Adds an observer for a specific device.
     75 //                           Will be called on any device property change.
     76 // NetworkDeviceObserverList: A monitor and list of observers of a device.
     77 // UpdateNetworkDeviceStatus: Handles changes to a monitored device, like
     78 //     SIM lock state and updates device state.
     79 //
     80 // All *Pin(...) methods use internal callback that would update cellular
     81 //    device state once async call is completed and notify all device observers.
     82 //
     83 ////////////////////////////////////////////////////////////////////////////////
     84 
     85 namespace chromeos {
     86 
     87 // Local constants.
     88 namespace {
     89 
     90 // Only send network change notifications to observers once every 50ms.
     91 const int kNetworkNotifyDelayMs = 50;
     92 
     93 // How long we should remember that cellular plan payment was received.
     94 const int kRecentPlanPaymentHours = 6;
     95 
     96 // Default value of the SIM unlock retries count. It is updated to the real
     97 // retries count once cellular device with SIM card is initialized.
     98 // If cellular device doesn't have SIM card, then retries are never used.
     99 const int kDefaultSimUnlockRetriesCount = 999;
    100 
    101 // Format of the Carrier ID: <carrier name> (<carrier country>).
    102 const char* kCarrierIdFormat = "%s (%s)";
    103 
    104 // Type of a pending SIM operation.
    105 enum SimOperationType {
    106   SIM_OPERATION_NONE               = 0,
    107   SIM_OPERATION_CHANGE_PIN         = 1,
    108   SIM_OPERATION_CHANGE_REQUIRE_PIN = 2,
    109   SIM_OPERATION_ENTER_PIN          = 3,
    110   SIM_OPERATION_UNBLOCK_PIN        = 4,
    111 };
    112 
    113 // D-Bus interface string constants.
    114 
    115 // Flimflam property names.
    116 const char* kSecurityProperty = "Security";
    117 const char* kPassphraseProperty = "Passphrase";
    118 const char* kIdentityProperty = "Identity";
    119 const char* kCertPathProperty = "CertPath";
    120 const char* kPassphraseRequiredProperty = "PassphraseRequired";
    121 const char* kSaveCredentialsProperty = "SaveCredentials";
    122 const char* kProfilesProperty = "Profiles";
    123 const char* kServicesProperty = "Services";
    124 const char* kServiceWatchListProperty = "ServiceWatchList";
    125 const char* kAvailableTechnologiesProperty = "AvailableTechnologies";
    126 const char* kEnabledTechnologiesProperty = "EnabledTechnologies";
    127 const char* kConnectedTechnologiesProperty = "ConnectedTechnologies";
    128 const char* kDefaultTechnologyProperty = "DefaultTechnology";
    129 const char* kOfflineModeProperty = "OfflineMode";
    130 const char* kSignalStrengthProperty = "Strength";
    131 const char* kNameProperty = "Name";
    132 const char* kStateProperty = "State";
    133 const char* kConnectivityStateProperty = "ConnectivityState";
    134 const char* kTypeProperty = "Type";
    135 const char* kDeviceProperty = "Device";
    136 const char* kActivationStateProperty = "Cellular.ActivationState";
    137 const char* kNetworkTechnologyProperty = "Cellular.NetworkTechnology";
    138 const char* kRoamingStateProperty = "Cellular.RoamingState";
    139 const char* kOperatorNameProperty = "Cellular.OperatorName";
    140 const char* kOperatorCodeProperty = "Cellular.OperatorCode";
    141 const char* kServingOperatorProperty = "Cellular.ServingOperator";
    142 const char* kPaymentURLProperty = "Cellular.OlpUrl";
    143 const char* kUsageURLProperty = "Cellular.UsageUrl";
    144 const char* kCellularApnProperty = "Cellular.APN";
    145 const char* kCellularLastGoodApnProperty = "Cellular.LastGoodAPN";
    146 const char* kWifiHexSsid = "WiFi.HexSSID";
    147 const char* kWifiFrequency = "WiFi.Frequency";
    148 const char* kWifiHiddenSsid = "WiFi.HiddenSSID";
    149 const char* kWifiPhyMode = "WiFi.PhyMode";
    150 const char* kFavoriteProperty = "Favorite";
    151 const char* kConnectableProperty = "Connectable";
    152 const char* kAutoConnectProperty = "AutoConnect";
    153 const char* kIsActiveProperty = "IsActive";
    154 const char* kModeProperty = "Mode";
    155 const char* kErrorProperty = "Error";
    156 const char* kActiveProfileProperty = "ActiveProfile";
    157 const char* kEntriesProperty = "Entries";
    158 const char* kDevicesProperty = "Devices";
    159 const char* kProviderProperty = "Provider";
    160 const char* kHostProperty = "Host";
    161 
    162 // Flimflam property names for SIMLock status.
    163 const char* kSIMLockStatusProperty = "Cellular.SIMLockStatus";
    164 const char* kSIMLockTypeProperty = "LockType";
    165 const char* kSIMLockRetriesLeftProperty = "RetriesLeft";
    166 
    167 // Flimflam property names for Cellular.FoundNetworks.
    168 const char* kLongNameProperty = "long_name";
    169 const char* kStatusProperty = "status";
    170 const char* kShortNameProperty = "short_name";
    171 const char* kTechnologyProperty = "technology";
    172 
    173 // Flimflam SIMLock status types.
    174 const char* kSIMLockPin = "sim-pin";
    175 const char* kSIMLockPuk = "sim-puk";
    176 
    177 // APN info property names.
    178 const char* kApnProperty = "apn";
    179 const char* kNetworkIdProperty = "network_id";
    180 const char* kUsernameProperty = "username";
    181 const char* kPasswordProperty = "password";
    182 
    183 // Operator info property names.
    184 const char* kOperatorNameKey = "name";
    185 const char* kOperatorCodeKey = "code";
    186 const char* kOperatorCountryKey = "country";
    187 
    188 // Flimflam device info property names.
    189 const char* kScanningProperty = "Scanning";
    190 const char* kCarrierProperty = "Cellular.Carrier";
    191 const char* kCellularAllowRoamingProperty = "Cellular.AllowRoaming";
    192 const char* kHomeProviderProperty = "Cellular.HomeProvider";
    193 const char* kMeidProperty = "Cellular.MEID";
    194 const char* kImeiProperty = "Cellular.IMEI";
    195 const char* kImsiProperty = "Cellular.IMSI";
    196 const char* kEsnProperty = "Cellular.ESN";
    197 const char* kMdnProperty = "Cellular.MDN";
    198 const char* kMinProperty = "Cellular.MIN";
    199 const char* kModelIDProperty = "Cellular.ModelID";
    200 const char* kManufacturerProperty = "Cellular.Manufacturer";
    201 const char* kFirmwareRevisionProperty = "Cellular.FirmwareRevision";
    202 const char* kHardwareRevisionProperty = "Cellular.HardwareRevision";
    203 const char* kPoweredProperty = "Powered";
    204 const char* kPRLVersionProperty = "Cellular.PRLVersion"; // (INT16)
    205 const char* kSelectedNetworkProperty = "Cellular.SelectedNetwork";
    206 const char* kSupportNetworkScanProperty = "Cellular.SupportNetworkScan";
    207 const char* kFoundNetworksProperty = "Cellular.FoundNetworks";
    208 
    209 // Flimflam type options.
    210 const char* kTypeEthernet = "ethernet";
    211 const char* kTypeWifi = "wifi";
    212 const char* kTypeWimax = "wimax";
    213 const char* kTypeBluetooth = "bluetooth";
    214 const char* kTypeCellular = "cellular";
    215 const char* kTypeVPN = "vpn";
    216 
    217 // Flimflam mode options.
    218 const char* kModeManaged = "managed";
    219 const char* kModeAdhoc = "adhoc";
    220 
    221 // Flimflam security options.
    222 const char* kSecurityWpa = "wpa";
    223 const char* kSecurityWep = "wep";
    224 const char* kSecurityRsn = "rsn";
    225 const char* kSecurity8021x = "802_1x";
    226 const char* kSecurityPsk = "psk";
    227 const char* kSecurityNone = "none";
    228 
    229 // Flimflam L2TPIPsec property names.
    230 const char* kL2TPIPSecCACertProperty = "L2TPIPsec.CACert";
    231 const char* kL2TPIPSecCertProperty = "L2TPIPsec.Cert";
    232 const char* kL2TPIPSecKeyProperty = "L2TPIPsec.Key";
    233 const char* kL2TPIPSecPSKProperty = "L2TPIPsec.PSK";
    234 const char* kL2TPIPSecUserProperty = "L2TPIPsec.User";
    235 const char* kL2TPIPSecPasswordProperty = "L2TPIPsec.Password";
    236 
    237 // Flimflam EAP property names.
    238 // See src/third_party/flimflam/doc/service-api.txt.
    239 const char* kEapIdentityProperty = "EAP.Identity";
    240 const char* kEapMethodProperty = "EAP.EAP";
    241 const char* kEapPhase2AuthProperty = "EAP.InnerEAP";
    242 const char* kEapAnonymousIdentityProperty = "EAP.AnonymousIdentity";
    243 const char* kEapClientCertProperty = "EAP.ClientCert";  // path
    244 const char* kEapCertIDProperty = "EAP.CertID";  // PKCS#11 ID
    245 const char* kEapClientCertNssProperty = "EAP.ClientCertNSS";  // NSS nickname
    246 const char* kEapPrivateKeyProperty = "EAP.PrivateKey";
    247 const char* kEapPrivateKeyPasswordProperty = "EAP.PrivateKeyPassword";
    248 const char* kEapKeyIDProperty = "EAP.KeyID";
    249 const char* kEapCaCertProperty = "EAP.CACert";  // server CA cert path
    250 const char* kEapCaCertIDProperty = "EAP.CACertID";  // server CA PKCS#11 ID
    251 const char* kEapCaCertNssProperty = "EAP.CACertNSS";  // server CA NSS nickname
    252 const char* kEapUseSystemCAsProperty = "EAP.UseSystemCAs";
    253 const char* kEapPinProperty = "EAP.PIN";
    254 const char* kEapPasswordProperty = "EAP.Password";
    255 const char* kEapKeyMgmtProperty = "EAP.KeyMgmt";
    256 
    257 // Flimflam EAP method options.
    258 const std::string& kEapMethodPEAP = "PEAP";
    259 const std::string& kEapMethodTLS = "TLS";
    260 const std::string& kEapMethodTTLS = "TTLS";
    261 const std::string& kEapMethodLEAP = "LEAP";
    262 
    263 // Flimflam EAP phase 2 auth options.
    264 const std::string& kEapPhase2AuthPEAPMD5 = "auth=MD5";
    265 const std::string& kEapPhase2AuthPEAPMSCHAPV2 = "auth=MSCHAPV2";
    266 const std::string& kEapPhase2AuthTTLSMD5 = "autheap=MD5";
    267 const std::string& kEapPhase2AuthTTLSMSCHAPV2 = "autheap=MSCHAPV2";
    268 const std::string& kEapPhase2AuthTTLSMSCHAP = "autheap=MSCHAP";
    269 const std::string& kEapPhase2AuthTTLSPAP = "autheap=PAP";
    270 const std::string& kEapPhase2AuthTTLSCHAP = "autheap=CHAP";
    271 
    272 // Flimflam VPN provider types.
    273 const char* kProviderL2tpIpsec = "l2tpipsec";
    274 const char* kProviderOpenVpn = "openvpn";
    275 
    276 
    277 // Flimflam state options.
    278 const char* kStateIdle = "idle";
    279 const char* kStateCarrier = "carrier";
    280 const char* kStateAssociation = "association";
    281 const char* kStateConfiguration = "configuration";
    282 const char* kStateReady = "ready";
    283 const char* kStateDisconnect = "disconnect";
    284 const char* kStateFailure = "failure";
    285 const char* kStateActivationFailure = "activation-failure";
    286 
    287 // Flimflam connectivity state options.
    288 const char* kConnStateUnrestricted = "unrestricted";
    289 const char* kConnStateRestricted = "restricted";
    290 const char* kConnStateNone = "none";
    291 
    292 // Flimflam network technology options.
    293 const char* kNetworkTechnology1Xrtt = "1xRTT";
    294 const char* kNetworkTechnologyEvdo = "EVDO";
    295 const char* kNetworkTechnologyGprs = "GPRS";
    296 const char* kNetworkTechnologyEdge = "EDGE";
    297 const char* kNetworkTechnologyUmts = "UMTS";
    298 const char* kNetworkTechnologyHspa = "HSPA";
    299 const char* kNetworkTechnologyHspaPlus = "HSPA+";
    300 const char* kNetworkTechnologyLte = "LTE";
    301 const char* kNetworkTechnologyLteAdvanced = "LTE Advanced";
    302 
    303 // Flimflam roaming state options
    304 const char* kRoamingStateHome = "home";
    305 const char* kRoamingStateRoaming = "roaming";
    306 const char* kRoamingStateUnknown = "unknown";
    307 
    308 // Flimflam activation state options
    309 const char* kActivationStateActivated = "activated";
    310 const char* kActivationStateActivating = "activating";
    311 const char* kActivationStateNotActivated = "not-activated";
    312 const char* kActivationStatePartiallyActivated = "partially-activated";
    313 const char* kActivationStateUnknown = "unknown";
    314 
    315 // Flimflam error options.
    316 const char* kErrorOutOfRange = "out-of-range";
    317 const char* kErrorPinMissing = "pin-missing";
    318 const char* kErrorDhcpFailed = "dhcp-failed";
    319 const char* kErrorConnectFailed = "connect-failed";
    320 const char* kErrorBadPassphrase = "bad-passphrase";
    321 const char* kErrorBadWEPKey = "bad-wepkey";
    322 const char* kErrorActivationFailed = "activation-failed";
    323 const char* kErrorNeedEvdo = "need-evdo";
    324 const char* kErrorNeedHomeNetwork = "need-home-network";
    325 const char* kErrorOtaspFailed = "otasp-failed";
    326 const char* kErrorAaaFailed = "aaa-failed";
    327 
    328 // Flimflam error messages.
    329 const char* kErrorPassphraseRequiredMsg = "Passphrase required";
    330 const char* kErrorIncorrectPinMsg = "org.chromium.flimflam.Error.IncorrectPin";
    331 const char* kErrorPinBlockedMsg = "org.chromium.flimflam.Error.PinBlocked";
    332 const char* kErrorPinRequiredMsg = "org.chromium.flimflam.Error.PinRequired";
    333 
    334 const char* kUnknownString = "UNKNOWN";
    335 
    336 ////////////////////////////////////////////////////////////////////////////
    337 
    338 static const char* ConnectionTypeToString(ConnectionType type) {
    339   switch (type) {
    340     case TYPE_UNKNOWN:
    341       break;
    342     case TYPE_ETHERNET:
    343       return kTypeEthernet;
    344     case TYPE_WIFI:
    345       return kTypeWifi;
    346     case TYPE_WIMAX:
    347       return kTypeWimax;
    348     case TYPE_BLUETOOTH:
    349       return kTypeBluetooth;
    350     case TYPE_CELLULAR:
    351       return kTypeCellular;
    352     case TYPE_VPN:
    353       return kTypeVPN;
    354   }
    355   LOG(ERROR) << "ConnectionTypeToString called with unknown type: " << type;
    356   return kUnknownString;
    357 }
    358 
    359 // TODO(stevenjb/njw): Deprecate in favor of setting EAP properties.
    360 static const char* SecurityToString(ConnectionSecurity security) {
    361   switch (security) {
    362     case SECURITY_NONE:
    363       return kSecurityNone;
    364     case SECURITY_WEP:
    365       return kSecurityWep;
    366     case SECURITY_WPA:
    367       return kSecurityWpa;
    368     case SECURITY_RSN:
    369       return kSecurityRsn;
    370     case SECURITY_8021X:
    371       return kSecurity8021x;
    372     case SECURITY_PSK:
    373       return kSecurityPsk;
    374     case SECURITY_UNKNOWN:
    375       break;
    376   }
    377   LOG(ERROR) << "SecurityToString called with unknown type: " << security;
    378   return kUnknownString;
    379 }
    380 
    381 static const char* ProviderTypeToString(VirtualNetwork::ProviderType type) {
    382   switch (type) {
    383     case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK:
    384     case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
    385       return kProviderL2tpIpsec;
    386     case VirtualNetwork::PROVIDER_TYPE_OPEN_VPN:
    387       return kProviderOpenVpn;
    388     case VirtualNetwork::PROVIDER_TYPE_MAX:
    389       break;
    390   }
    391   LOG(ERROR) << "ProviderTypeToString called with unknown type: " << type;
    392   return kUnknownString;
    393 }
    394 
    395 ////////////////////////////////////////////////////////////////////////////
    396 
    397 // Helper class to cache maps of strings to enums.
    398 template <typename Type>
    399 class StringToEnum {
    400  public:
    401   struct Pair {
    402     const char* key;
    403     const Type value;
    404   };
    405 
    406   explicit StringToEnum(const Pair* list, size_t num_entries, Type unknown)
    407       : unknown_value_(unknown) {
    408     for (size_t i = 0; i < num_entries; ++i, ++list)
    409       enum_map_[list->key] = list->value;
    410   }
    411 
    412   Type Get(const std::string& type) const {
    413     EnumMapConstIter iter = enum_map_.find(type);
    414     if (iter != enum_map_.end())
    415       return iter->second;
    416     return unknown_value_;
    417   }
    418 
    419  private:
    420   typedef typename std::map<std::string, Type> EnumMap;
    421   typedef typename std::map<std::string, Type>::const_iterator EnumMapConstIter;
    422   EnumMap enum_map_;
    423   Type unknown_value_;
    424   DISALLOW_COPY_AND_ASSIGN(StringToEnum);
    425 };
    426 
    427 ////////////////////////////////////////////////////////////////////////////
    428 
    429 enum PropertyIndex {
    430   PROPERTY_INDEX_ACTIVATION_STATE,
    431   PROPERTY_INDEX_ACTIVE_PROFILE,
    432   PROPERTY_INDEX_AUTO_CONNECT,
    433   PROPERTY_INDEX_AVAILABLE_TECHNOLOGIES,
    434   PROPERTY_INDEX_CARRIER,
    435   PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING,
    436   PROPERTY_INDEX_CELLULAR_APN,
    437   PROPERTY_INDEX_CELLULAR_LAST_GOOD_APN,
    438   PROPERTY_INDEX_CERT_PATH,
    439   PROPERTY_INDEX_CONNECTABLE,
    440   PROPERTY_INDEX_CONNECTED_TECHNOLOGIES,
    441   PROPERTY_INDEX_CONNECTIVITY_STATE,
    442   PROPERTY_INDEX_DEFAULT_TECHNOLOGY,
    443   PROPERTY_INDEX_DEVICE,
    444   PROPERTY_INDEX_DEVICES,
    445   PROPERTY_INDEX_EAP_IDENTITY,
    446   PROPERTY_INDEX_EAP_METHOD,
    447   PROPERTY_INDEX_EAP_PHASE_2_AUTH,
    448   PROPERTY_INDEX_EAP_ANONYMOUS_IDENTITY,
    449   PROPERTY_INDEX_EAP_CLIENT_CERT,
    450   PROPERTY_INDEX_EAP_CERT_ID,
    451   PROPERTY_INDEX_EAP_CLIENT_CERT_NSS,
    452   PROPERTY_INDEX_EAP_PRIVATE_KEY,
    453   PROPERTY_INDEX_EAP_PRIVATE_KEY_PASSWORD,
    454   PROPERTY_INDEX_EAP_KEY_ID,
    455   PROPERTY_INDEX_EAP_CA_CERT,
    456   PROPERTY_INDEX_EAP_CA_CERT_ID,
    457   PROPERTY_INDEX_EAP_CA_CERT_NSS,
    458   PROPERTY_INDEX_EAP_USE_SYSTEM_CAS,
    459   PROPERTY_INDEX_EAP_PIN,
    460   PROPERTY_INDEX_EAP_PASSWORD,
    461   PROPERTY_INDEX_EAP_KEY_MGMT,
    462   PROPERTY_INDEX_ENABLED_TECHNOLOGIES,
    463   PROPERTY_INDEX_ERROR,
    464   PROPERTY_INDEX_ESN,
    465   PROPERTY_INDEX_FAVORITE,
    466   PROPERTY_INDEX_FIRMWARE_REVISION,
    467   PROPERTY_INDEX_FOUND_NETWORKS,
    468   PROPERTY_INDEX_HARDWARE_REVISION,
    469   PROPERTY_INDEX_HOME_PROVIDER,
    470   PROPERTY_INDEX_HOST,
    471   PROPERTY_INDEX_IDENTITY,
    472   PROPERTY_INDEX_IMEI,
    473   PROPERTY_INDEX_IMSI,
    474   PROPERTY_INDEX_IS_ACTIVE,
    475   PROPERTY_INDEX_L2TPIPSEC_CA_CERT,
    476   PROPERTY_INDEX_L2TPIPSEC_CERT,
    477   PROPERTY_INDEX_L2TPIPSEC_KEY,
    478   PROPERTY_INDEX_L2TPIPSEC_PASSWORD,
    479   PROPERTY_INDEX_L2TPIPSEC_PSK,
    480   PROPERTY_INDEX_L2TPIPSEC_USER,
    481   PROPERTY_INDEX_MANUFACTURER,
    482   PROPERTY_INDEX_MDN,
    483   PROPERTY_INDEX_MEID,
    484   PROPERTY_INDEX_MIN,
    485   PROPERTY_INDEX_MODE,
    486   PROPERTY_INDEX_MODEL_ID,
    487   PROPERTY_INDEX_NAME,
    488   PROPERTY_INDEX_NETWORK_TECHNOLOGY,
    489   PROPERTY_INDEX_OFFLINE_MODE,
    490   PROPERTY_INDEX_OPERATOR_CODE,
    491   PROPERTY_INDEX_OPERATOR_NAME,
    492   PROPERTY_INDEX_PASSPHRASE,
    493   PROPERTY_INDEX_PASSPHRASE_REQUIRED,
    494   PROPERTY_INDEX_PAYMENT_URL,
    495   PROPERTY_INDEX_POWERED,
    496   PROPERTY_INDEX_PRL_VERSION,
    497   PROPERTY_INDEX_PROFILES,
    498   PROPERTY_INDEX_PROVIDER,
    499   PROPERTY_INDEX_ROAMING_STATE,
    500   PROPERTY_INDEX_SAVE_CREDENTIALS,
    501   PROPERTY_INDEX_SCANNING,
    502   PROPERTY_INDEX_SECURITY,
    503   PROPERTY_INDEX_SELECTED_NETWORK,
    504   PROPERTY_INDEX_SERVICES,
    505   PROPERTY_INDEX_SERVICE_WATCH_LIST,
    506   PROPERTY_INDEX_SERVING_OPERATOR,
    507   PROPERTY_INDEX_SIGNAL_STRENGTH,
    508   PROPERTY_INDEX_SIM_LOCK,
    509   PROPERTY_INDEX_STATE,
    510   PROPERTY_INDEX_SUPPORT_NETWORK_SCAN,
    511   PROPERTY_INDEX_TYPE,
    512   PROPERTY_INDEX_UNKNOWN,
    513   PROPERTY_INDEX_USAGE_URL,
    514   PROPERTY_INDEX_WIFI_FREQUENCY,
    515   PROPERTY_INDEX_WIFI_HEX_SSID,
    516   PROPERTY_INDEX_WIFI_HIDDEN_SSID,
    517   PROPERTY_INDEX_WIFI_PHY_MODE,
    518 };
    519 
    520 StringToEnum<PropertyIndex>::Pair property_index_table[] = {
    521   { kActivationStateProperty, PROPERTY_INDEX_ACTIVATION_STATE },
    522   { kActiveProfileProperty, PROPERTY_INDEX_ACTIVE_PROFILE },
    523   { kAutoConnectProperty, PROPERTY_INDEX_AUTO_CONNECT },
    524   { kAvailableTechnologiesProperty, PROPERTY_INDEX_AVAILABLE_TECHNOLOGIES },
    525   { kCellularAllowRoamingProperty, PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING },
    526   { kCellularApnProperty, PROPERTY_INDEX_CELLULAR_APN },
    527   { kCellularLastGoodApnProperty, PROPERTY_INDEX_CELLULAR_LAST_GOOD_APN },
    528   { kCarrierProperty, PROPERTY_INDEX_CARRIER },
    529   { kCertPathProperty, PROPERTY_INDEX_CERT_PATH },
    530   { kConnectableProperty, PROPERTY_INDEX_CONNECTABLE },
    531   { kConnectedTechnologiesProperty, PROPERTY_INDEX_CONNECTED_TECHNOLOGIES },
    532   { kConnectivityStateProperty, PROPERTY_INDEX_CONNECTIVITY_STATE },
    533   { kDefaultTechnologyProperty, PROPERTY_INDEX_DEFAULT_TECHNOLOGY },
    534   { kDeviceProperty, PROPERTY_INDEX_DEVICE },
    535   { kDevicesProperty, PROPERTY_INDEX_DEVICES },
    536   { kEapIdentityProperty, PROPERTY_INDEX_EAP_IDENTITY },
    537   { kEapMethodProperty, PROPERTY_INDEX_EAP_METHOD },
    538   { kEapPhase2AuthProperty, PROPERTY_INDEX_EAP_PHASE_2_AUTH },
    539   { kEapAnonymousIdentityProperty, PROPERTY_INDEX_EAP_ANONYMOUS_IDENTITY },
    540   { kEapClientCertProperty, PROPERTY_INDEX_EAP_CLIENT_CERT },
    541   { kEapCertIDProperty, PROPERTY_INDEX_EAP_CERT_ID },
    542   { kEapClientCertNssProperty, PROPERTY_INDEX_EAP_CLIENT_CERT_NSS },
    543   { kEapPrivateKeyProperty, PROPERTY_INDEX_EAP_PRIVATE_KEY },
    544   { kEapPrivateKeyPasswordProperty, PROPERTY_INDEX_EAP_PRIVATE_KEY_PASSWORD },
    545   { kEapKeyIDProperty, PROPERTY_INDEX_EAP_KEY_ID },
    546   { kEapCaCertProperty, PROPERTY_INDEX_EAP_CA_CERT },
    547   { kEapCaCertIDProperty, PROPERTY_INDEX_EAP_CA_CERT_ID },
    548   { kEapCaCertNssProperty, PROPERTY_INDEX_EAP_CA_CERT_NSS },
    549   { kEapUseSystemCAsProperty, PROPERTY_INDEX_EAP_USE_SYSTEM_CAS },
    550   { kEapPinProperty, PROPERTY_INDEX_EAP_PIN },
    551   { kEapPasswordProperty, PROPERTY_INDEX_EAP_PASSWORD },
    552   { kEapKeyMgmtProperty, PROPERTY_INDEX_EAP_KEY_MGMT },
    553   { kEnabledTechnologiesProperty, PROPERTY_INDEX_ENABLED_TECHNOLOGIES },
    554   { kErrorProperty, PROPERTY_INDEX_ERROR },
    555   { kEsnProperty, PROPERTY_INDEX_ESN },
    556   { kFavoriteProperty, PROPERTY_INDEX_FAVORITE },
    557   { kFirmwareRevisionProperty, PROPERTY_INDEX_FIRMWARE_REVISION },
    558   { kFoundNetworksProperty, PROPERTY_INDEX_FOUND_NETWORKS },
    559   { kHardwareRevisionProperty, PROPERTY_INDEX_HARDWARE_REVISION },
    560   { kHomeProviderProperty, PROPERTY_INDEX_HOME_PROVIDER },
    561   { kHostProperty, PROPERTY_INDEX_HOST },
    562   { kIdentityProperty, PROPERTY_INDEX_IDENTITY },
    563   { kImeiProperty, PROPERTY_INDEX_IMEI },
    564   { kImsiProperty, PROPERTY_INDEX_IMSI },
    565   { kIsActiveProperty, PROPERTY_INDEX_IS_ACTIVE },
    566   { kL2TPIPSecCACertProperty, PROPERTY_INDEX_L2TPIPSEC_CA_CERT },
    567   { kL2TPIPSecCertProperty, PROPERTY_INDEX_L2TPIPSEC_CERT },
    568   { kL2TPIPSecKeyProperty, PROPERTY_INDEX_L2TPIPSEC_KEY },
    569   { kL2TPIPSecPasswordProperty, PROPERTY_INDEX_L2TPIPSEC_PASSWORD },
    570   { kL2TPIPSecPSKProperty, PROPERTY_INDEX_L2TPIPSEC_PSK },
    571   { kL2TPIPSecUserProperty, PROPERTY_INDEX_L2TPIPSEC_USER },
    572   { kManufacturerProperty, PROPERTY_INDEX_MANUFACTURER },
    573   { kMdnProperty, PROPERTY_INDEX_MDN },
    574   { kMeidProperty, PROPERTY_INDEX_MEID },
    575   { kMinProperty, PROPERTY_INDEX_MIN },
    576   { kModeProperty, PROPERTY_INDEX_MODE },
    577   { kModelIDProperty, PROPERTY_INDEX_MODEL_ID },
    578   { kNameProperty, PROPERTY_INDEX_NAME },
    579   { kNetworkTechnologyProperty, PROPERTY_INDEX_NETWORK_TECHNOLOGY },
    580   { kOfflineModeProperty, PROPERTY_INDEX_OFFLINE_MODE },
    581   { kOperatorCodeProperty, PROPERTY_INDEX_OPERATOR_CODE },
    582   { kOperatorNameProperty, PROPERTY_INDEX_OPERATOR_NAME },
    583   { kPRLVersionProperty, PROPERTY_INDEX_PRL_VERSION },
    584   { kPassphraseProperty, PROPERTY_INDEX_PASSPHRASE },
    585   { kPassphraseRequiredProperty, PROPERTY_INDEX_PASSPHRASE_REQUIRED },
    586   { kPaymentURLProperty, PROPERTY_INDEX_PAYMENT_URL },
    587   { kPoweredProperty, PROPERTY_INDEX_POWERED },
    588   { kProfilesProperty, PROPERTY_INDEX_PROFILES },
    589   { kProviderProperty, PROPERTY_INDEX_PROVIDER },
    590   { kRoamingStateProperty, PROPERTY_INDEX_ROAMING_STATE },
    591   { kSaveCredentialsProperty, PROPERTY_INDEX_SAVE_CREDENTIALS },
    592   { kScanningProperty, PROPERTY_INDEX_SCANNING },
    593   { kSecurityProperty, PROPERTY_INDEX_SECURITY },
    594   { kSelectedNetworkProperty, PROPERTY_INDEX_SELECTED_NETWORK },
    595   { kServiceWatchListProperty, PROPERTY_INDEX_SERVICE_WATCH_LIST },
    596   { kServicesProperty, PROPERTY_INDEX_SERVICES },
    597   { kServingOperatorProperty, PROPERTY_INDEX_SERVING_OPERATOR },
    598   { kSignalStrengthProperty, PROPERTY_INDEX_SIGNAL_STRENGTH },
    599   { kSIMLockStatusProperty, PROPERTY_INDEX_SIM_LOCK },
    600   { kStateProperty, PROPERTY_INDEX_STATE },
    601   { kSupportNetworkScanProperty, PROPERTY_INDEX_SUPPORT_NETWORK_SCAN },
    602   { kTypeProperty, PROPERTY_INDEX_TYPE },
    603   { kUsageURLProperty, PROPERTY_INDEX_USAGE_URL },
    604   { kWifiFrequency, PROPERTY_INDEX_WIFI_FREQUENCY },
    605   { kWifiHexSsid, PROPERTY_INDEX_WIFI_HEX_SSID },
    606   { kWifiHiddenSsid, PROPERTY_INDEX_WIFI_HIDDEN_SSID },
    607   { kWifiPhyMode, PROPERTY_INDEX_WIFI_PHY_MODE },
    608 };
    609 
    610 StringToEnum<PropertyIndex>& property_index_parser() {
    611   static StringToEnum<PropertyIndex> parser(property_index_table,
    612                                             arraysize(property_index_table),
    613                                             PROPERTY_INDEX_UNKNOWN);
    614   return parser;
    615 }
    616 
    617 ////////////////////////////////////////////////////////////////////////////
    618 // Parse strings from libcros.
    619 
    620 // Network.
    621 static ConnectionType ParseType(const std::string& type) {
    622   static StringToEnum<ConnectionType>::Pair table[] = {
    623     { kTypeEthernet, TYPE_ETHERNET },
    624     { kTypeWifi, TYPE_WIFI },
    625     { kTypeWimax, TYPE_WIMAX },
    626     { kTypeBluetooth, TYPE_BLUETOOTH },
    627     { kTypeCellular, TYPE_CELLULAR },
    628     { kTypeVPN, TYPE_VPN },
    629   };
    630   static StringToEnum<ConnectionType> parser(
    631       table, arraysize(table), TYPE_UNKNOWN);
    632   return parser.Get(type);
    633 }
    634 
    635 ConnectionType ParseTypeFromDictionary(const DictionaryValue* info) {
    636   std::string type_string;
    637   info->GetString(kTypeProperty, &type_string);
    638   return ParseType(type_string);
    639 }
    640 
    641 static ConnectionMode ParseMode(const std::string& mode) {
    642   static StringToEnum<ConnectionMode>::Pair table[] = {
    643     { kModeManaged, MODE_MANAGED },
    644     { kModeAdhoc, MODE_ADHOC },
    645   };
    646   static StringToEnum<ConnectionMode> parser(
    647       table, arraysize(table), MODE_UNKNOWN);
    648   return parser.Get(mode);
    649 }
    650 
    651 static ConnectionState ParseState(const std::string& state) {
    652   static StringToEnum<ConnectionState>::Pair table[] = {
    653     { kStateIdle, STATE_IDLE },
    654     { kStateCarrier, STATE_CARRIER },
    655     { kStateAssociation, STATE_ASSOCIATION },
    656     { kStateConfiguration, STATE_CONFIGURATION },
    657     { kStateReady, STATE_READY },
    658     { kStateDisconnect, STATE_DISCONNECT },
    659     { kStateFailure, STATE_FAILURE },
    660     { kStateActivationFailure, STATE_ACTIVATION_FAILURE },
    661   };
    662   static StringToEnum<ConnectionState> parser(
    663       table, arraysize(table), STATE_UNKNOWN);
    664   return parser.Get(state);
    665 }
    666 
    667 static ConnectionError ParseError(const std::string& error) {
    668   static StringToEnum<ConnectionError>::Pair table[] = {
    669     { kErrorOutOfRange, ERROR_OUT_OF_RANGE },
    670     { kErrorPinMissing, ERROR_PIN_MISSING },
    671     { kErrorDhcpFailed, ERROR_DHCP_FAILED },
    672     { kErrorConnectFailed, ERROR_CONNECT_FAILED },
    673     { kErrorBadPassphrase, ERROR_BAD_PASSPHRASE },
    674     { kErrorBadWEPKey, ERROR_BAD_WEPKEY },
    675     { kErrorActivationFailed, ERROR_ACTIVATION_FAILED },
    676     { kErrorNeedEvdo, ERROR_NEED_EVDO },
    677     { kErrorNeedHomeNetwork, ERROR_NEED_HOME_NETWORK },
    678     { kErrorOtaspFailed, ERROR_OTASP_FAILED },
    679     { kErrorAaaFailed, ERROR_AAA_FAILED },
    680   };
    681   static StringToEnum<ConnectionError> parser(
    682       table, arraysize(table), ERROR_NO_ERROR);
    683   return parser.Get(error);
    684 }
    685 
    686 // VirtualNetwork
    687 static VirtualNetwork::ProviderType ParseProviderType(const std::string& mode) {
    688   static StringToEnum<VirtualNetwork::ProviderType>::Pair table[] = {
    689     { kProviderL2tpIpsec, VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK },
    690     { kProviderOpenVpn, VirtualNetwork::PROVIDER_TYPE_OPEN_VPN },
    691   };
    692   static StringToEnum<VirtualNetwork::ProviderType> parser(
    693       table, arraysize(table), VirtualNetwork::PROVIDER_TYPE_MAX);
    694   return parser.Get(mode);
    695 }
    696 
    697 // CellularNetwork.
    698 static ActivationState ParseActivationState(const std::string& state) {
    699   static StringToEnum<ActivationState>::Pair table[] = {
    700     { kActivationStateActivated, ACTIVATION_STATE_ACTIVATED },
    701     { kActivationStateActivating, ACTIVATION_STATE_ACTIVATING },
    702     { kActivationStateNotActivated, ACTIVATION_STATE_NOT_ACTIVATED },
    703     { kActivationStatePartiallyActivated, ACTIVATION_STATE_PARTIALLY_ACTIVATED},
    704     { kActivationStateUnknown, ACTIVATION_STATE_UNKNOWN},
    705   };
    706   static StringToEnum<ActivationState> parser(
    707       table, arraysize(table), ACTIVATION_STATE_UNKNOWN);
    708   return parser.Get(state);
    709 }
    710 
    711 static ConnectivityState ParseConnectivityState(const std::string& state) {
    712   static StringToEnum<ConnectivityState>::Pair table[] = {
    713     { kConnStateUnrestricted, CONN_STATE_UNRESTRICTED },
    714     { kConnStateRestricted, CONN_STATE_RESTRICTED },
    715     { kConnStateNone, CONN_STATE_NONE },
    716   };
    717   static StringToEnum<ConnectivityState> parser(
    718       table, arraysize(table), CONN_STATE_UNKNOWN);
    719   return parser.Get(state);
    720 }
    721 
    722 static NetworkTechnology ParseNetworkTechnology(const std::string& technology) {
    723   static StringToEnum<NetworkTechnology>::Pair table[] = {
    724     { kNetworkTechnology1Xrtt, NETWORK_TECHNOLOGY_1XRTT },
    725     { kNetworkTechnologyEvdo, NETWORK_TECHNOLOGY_EVDO },
    726     { kNetworkTechnologyGprs, NETWORK_TECHNOLOGY_GPRS },
    727     { kNetworkTechnologyEdge, NETWORK_TECHNOLOGY_EDGE },
    728     { kNetworkTechnologyUmts, NETWORK_TECHNOLOGY_UMTS },
    729     { kNetworkTechnologyHspa, NETWORK_TECHNOLOGY_HSPA },
    730     { kNetworkTechnologyHspaPlus, NETWORK_TECHNOLOGY_HSPA_PLUS },
    731     { kNetworkTechnologyLte, NETWORK_TECHNOLOGY_LTE },
    732     { kNetworkTechnologyLteAdvanced, NETWORK_TECHNOLOGY_LTE_ADVANCED },
    733   };
    734   static StringToEnum<NetworkTechnology> parser(
    735       table, arraysize(table), NETWORK_TECHNOLOGY_UNKNOWN);
    736   return parser.Get(technology);
    737 }
    738 
    739 static SIMLockState ParseSimLockState(const std::string& state) {
    740   static StringToEnum<SIMLockState>::Pair table[] = {
    741     { "", SIM_UNLOCKED },
    742     { kSIMLockPin, SIM_LOCKED_PIN },
    743     { kSIMLockPuk, SIM_LOCKED_PUK },
    744   };
    745   static StringToEnum<SIMLockState> parser(
    746       table, arraysize(table), SIM_UNKNOWN);
    747   SIMLockState parsed_state = parser.Get(state);
    748   DCHECK(parsed_state != SIM_UNKNOWN) << "Unknown SIMLock state encountered";
    749   return parsed_state;
    750 }
    751 
    752 static bool ParseSimLockStateFromDictionary(const DictionaryValue* info,
    753                                             SIMLockState* out_state,
    754                                             int* out_retries) {
    755   std::string state_string;
    756   if (!info->GetString(kSIMLockTypeProperty, &state_string) ||
    757       !info->GetInteger(kSIMLockRetriesLeftProperty, out_retries)) {
    758     LOG(ERROR) << "Error parsing SIMLock state";
    759     return false;
    760   }
    761   *out_state = ParseSimLockState(state_string);
    762   return true;
    763 }
    764 
    765 static bool ParseFoundNetworksFromList(const ListValue* list,
    766                                        CellularNetworkList* found_networks_) {
    767   found_networks_->clear();
    768   found_networks_->reserve(list->GetSize());
    769   for (ListValue::const_iterator it = list->begin(); it != list->end(); ++it) {
    770     if ((*it)->IsType(Value::TYPE_DICTIONARY)) {
    771       found_networks_->resize(found_networks_->size() + 1);
    772       DictionaryValue* dict = static_cast<const DictionaryValue*>(*it);
    773       dict->GetStringWithoutPathExpansion(
    774           kStatusProperty, &found_networks_->back().status);
    775       dict->GetStringWithoutPathExpansion(
    776           kNetworkIdProperty, &found_networks_->back().network_id);
    777       dict->GetStringWithoutPathExpansion(
    778           kShortNameProperty, &found_networks_->back().short_name);
    779       dict->GetStringWithoutPathExpansion(
    780           kLongNameProperty, &found_networks_->back().long_name);
    781       dict->GetStringWithoutPathExpansion(
    782           kTechnologyProperty, &found_networks_->back().technology);
    783     } else {
    784       return false;
    785     }
    786   }
    787   return true;
    788 }
    789 
    790 static NetworkRoamingState ParseRoamingState(const std::string& roaming_state) {
    791   static StringToEnum<NetworkRoamingState>::Pair table[] = {
    792     { kRoamingStateHome, ROAMING_STATE_HOME },
    793     { kRoamingStateRoaming, ROAMING_STATE_ROAMING },
    794     { kRoamingStateUnknown, ROAMING_STATE_UNKNOWN },
    795   };
    796   static StringToEnum<NetworkRoamingState> parser(
    797       table, arraysize(table), ROAMING_STATE_UNKNOWN);
    798   return parser.Get(roaming_state);
    799 }
    800 
    801 // WifiNetwork
    802 static ConnectionSecurity ParseSecurity(const std::string& security) {
    803   static StringToEnum<ConnectionSecurity>::Pair table[] = {
    804     { kSecurityNone, SECURITY_NONE },
    805     { kSecurityWep, SECURITY_WEP },
    806     { kSecurityWpa, SECURITY_WPA },
    807     { kSecurityRsn, SECURITY_RSN },
    808     { kSecurityPsk, SECURITY_PSK },
    809     { kSecurity8021x, SECURITY_8021X },
    810   };
    811   static StringToEnum<ConnectionSecurity> parser(
    812       table, arraysize(table), SECURITY_UNKNOWN);
    813   return parser.Get(security);
    814 }
    815 
    816 static EAPMethod ParseEAPMethod(const std::string& method) {
    817   static StringToEnum<EAPMethod>::Pair table[] = {
    818     { kEapMethodPEAP.c_str(), EAP_METHOD_PEAP },
    819     { kEapMethodTLS.c_str(), EAP_METHOD_TLS },
    820     { kEapMethodTTLS.c_str(), EAP_METHOD_TTLS },
    821     { kEapMethodLEAP.c_str(), EAP_METHOD_LEAP },
    822   };
    823   static StringToEnum<EAPMethod> parser(
    824       table, arraysize(table), EAP_METHOD_UNKNOWN);
    825   return parser.Get(method);
    826 }
    827 
    828 static EAPPhase2Auth ParseEAPPhase2Auth(const std::string& auth) {
    829   static StringToEnum<EAPPhase2Auth>::Pair table[] = {
    830     { kEapPhase2AuthPEAPMD5.c_str(), EAP_PHASE_2_AUTH_MD5 },
    831     { kEapPhase2AuthPEAPMSCHAPV2.c_str(), EAP_PHASE_2_AUTH_MSCHAPV2 },
    832     { kEapPhase2AuthTTLSMD5.c_str(), EAP_PHASE_2_AUTH_MD5 },
    833     { kEapPhase2AuthTTLSMSCHAPV2.c_str(), EAP_PHASE_2_AUTH_MSCHAPV2 },
    834     { kEapPhase2AuthTTLSMSCHAP.c_str(), EAP_PHASE_2_AUTH_MSCHAP },
    835     { kEapPhase2AuthTTLSPAP.c_str(), EAP_PHASE_2_AUTH_PAP },
    836     { kEapPhase2AuthTTLSCHAP.c_str(), EAP_PHASE_2_AUTH_CHAP },
    837   };
    838   static StringToEnum<EAPPhase2Auth> parser(
    839       table, arraysize(table), EAP_PHASE_2_AUTH_AUTO);
    840   return parser.Get(auth);
    841 }
    842 
    843 ////////////////////////////////////////////////////////////////////////////////
    844 // Misc.
    845 
    846 // Safe string constructor since we can't rely on non NULL pointers
    847 // for string values from libcros.
    848 static std::string SafeString(const char* s) {
    849   return s ? std::string(s) : std::string();
    850 }
    851 
    852 // Erase the memory used by a string, then clear it.
    853 static void WipeString(std::string* str) {
    854   str->assign(str->size(), '\0');
    855   str->clear();
    856 }
    857 
    858 static bool EnsureCrosLoaded() {
    859   if (!CrosLibrary::Get()->EnsureLoaded()) {
    860     return false;
    861   } else {
    862     if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    863       LOG(ERROR) << "chromeos_library calls made from non UI thread!";
    864       NOTREACHED();
    865     }
    866     return true;
    867   }
    868 }
    869 
    870 static void ValidateUTF8(const std::string& str, std::string* output) {
    871   output->clear();
    872 
    873   for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) {
    874     uint32 code_point_out;
    875     bool is_unicode_char = base::ReadUnicodeCharacter(str.c_str(), str.size(),
    876                                                       &index, &code_point_out);
    877     if (is_unicode_char && (code_point_out >= 0x20))
    878       base::WriteUnicodeCharacter(code_point_out, output);
    879     else
    880       // Puts REPLACEMENT CHARACTER (U+FFFD) if character is not readable UTF-8
    881       base::WriteUnicodeCharacter(0xFFFD, output);
    882   }
    883 }
    884 
    885 }  // namespace
    886 
    887 ////////////////////////////////////////////////////////////////////////////////
    888 // NetworkDevice
    889 
    890 NetworkDevice::NetworkDevice(const std::string& device_path)
    891     : device_path_(device_path),
    892       type_(TYPE_UNKNOWN),
    893       scanning_(false),
    894       sim_lock_state_(SIM_UNKNOWN),
    895       sim_retries_left_(kDefaultSimUnlockRetriesCount),
    896       sim_pin_required_(SIM_PIN_REQUIRE_UNKNOWN),
    897       PRL_version_(0),
    898       data_roaming_allowed_(false),
    899       support_network_scan_(false) {
    900 }
    901 
    902 bool NetworkDevice::ParseValue(int index, const Value* value) {
    903   switch (index) {
    904     case PROPERTY_INDEX_TYPE: {
    905       std::string type_string;
    906       if (value->GetAsString(&type_string)) {
    907         type_ = ParseType(type_string);
    908         return true;
    909       }
    910       break;
    911     }
    912     case PROPERTY_INDEX_NAME:
    913       return value->GetAsString(&name_);
    914     case PROPERTY_INDEX_CARRIER:
    915       return value->GetAsString(&carrier_);
    916     case PROPERTY_INDEX_SCANNING:
    917       return value->GetAsBoolean(&scanning_);
    918     case PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING:
    919       return value->GetAsBoolean(&data_roaming_allowed_);
    920     case PROPERTY_INDEX_FOUND_NETWORKS:
    921       if (value->IsType(Value::TYPE_LIST)) {
    922         return ParseFoundNetworksFromList(
    923             static_cast<const ListValue*>(value),
    924             &found_cellular_networks_);
    925       }
    926       break;
    927     case PROPERTY_INDEX_HOME_PROVIDER: {
    928       if (value->IsType(Value::TYPE_DICTIONARY)) {
    929         const DictionaryValue *dict =
    930             static_cast<const DictionaryValue*>(value);
    931         home_provider_code_.clear();
    932         home_provider_country_.clear();
    933         home_provider_name_.clear();
    934         dict->GetStringWithoutPathExpansion(kOperatorCodeKey,
    935                                             &home_provider_code_);
    936         dict->GetStringWithoutPathExpansion(kOperatorCountryKey,
    937                                             &home_provider_country_);
    938         dict->GetStringWithoutPathExpansion(kOperatorNameKey,
    939                                             &home_provider_name_);
    940         if (!home_provider_name_.empty() && !home_provider_country_.empty()) {
    941           home_provider_id_ = base::StringPrintf(
    942               kCarrierIdFormat,
    943               home_provider_name_.c_str(),
    944               home_provider_country_.c_str());
    945         } else {
    946           home_provider_id_ = home_provider_code_;
    947           LOG(WARNING) << "Carrier ID not defined, using code instead: "
    948                        << home_provider_id_;
    949         }
    950         return true;
    951       }
    952       break;
    953     }
    954     case PROPERTY_INDEX_MEID:
    955       return value->GetAsString(&MEID_);
    956     case PROPERTY_INDEX_IMEI:
    957       return value->GetAsString(&IMEI_);
    958     case PROPERTY_INDEX_IMSI:
    959       return value->GetAsString(&IMSI_);
    960     case PROPERTY_INDEX_ESN:
    961       return value->GetAsString(&ESN_);
    962     case PROPERTY_INDEX_MDN:
    963       return value->GetAsString(&MDN_);
    964     case PROPERTY_INDEX_MIN:
    965       return value->GetAsString(&MIN_);
    966     case PROPERTY_INDEX_MODEL_ID:
    967       return value->GetAsString(&model_id_);
    968     case PROPERTY_INDEX_MANUFACTURER:
    969       return value->GetAsString(&manufacturer_);
    970     case PROPERTY_INDEX_SIM_LOCK:
    971       if (value->IsType(Value::TYPE_DICTIONARY)) {
    972         bool result = ParseSimLockStateFromDictionary(
    973             static_cast<const DictionaryValue*>(value),
    974             &sim_lock_state_,
    975             &sim_retries_left_);
    976         // Initialize PinRequired value only once.
    977         // See SIMPinRequire enum comments.
    978         if (sim_pin_required_ == SIM_PIN_REQUIRE_UNKNOWN) {
    979           if (sim_lock_state_ == SIM_UNLOCKED) {
    980             sim_pin_required_ = SIM_PIN_NOT_REQUIRED;
    981           } else if (sim_lock_state_ == SIM_LOCKED_PIN ||
    982                      sim_lock_state_ == SIM_LOCKED_PUK) {
    983             sim_pin_required_ = SIM_PIN_REQUIRED;
    984           }
    985         }
    986         return result;
    987       }
    988       break;
    989     case PROPERTY_INDEX_FIRMWARE_REVISION:
    990       return value->GetAsString(&firmware_revision_);
    991     case PROPERTY_INDEX_HARDWARE_REVISION:
    992       return value->GetAsString(&hardware_revision_);
    993     case PROPERTY_INDEX_POWERED:
    994       // we don't care about the value, just the fact that it changed
    995       return true;
    996     case PROPERTY_INDEX_PRL_VERSION:
    997       return value->GetAsInteger(&PRL_version_);
    998     case PROPERTY_INDEX_SELECTED_NETWORK:
    999       return value->GetAsString(&selected_cellular_network_);
   1000     case PROPERTY_INDEX_SUPPORT_NETWORK_SCAN:
   1001       return value->GetAsBoolean(&support_network_scan_);
   1002     default:
   1003       break;
   1004   }
   1005   return false;
   1006 }
   1007 
   1008 void NetworkDevice::ParseInfo(const DictionaryValue* info) {
   1009   for (DictionaryValue::key_iterator iter = info->begin_keys();
   1010        iter != info->end_keys(); ++iter) {
   1011     const std::string& key = *iter;
   1012     Value* value;
   1013     bool res = info->GetWithoutPathExpansion(key, &value);
   1014     DCHECK(res);
   1015     if (res) {
   1016       int index = property_index_parser().Get(key);
   1017       if (!ParseValue(index, value))
   1018         VLOG(1) << "NetworkDevice: Unhandled key: " << key;
   1019     }
   1020   }
   1021 }
   1022 
   1023 ////////////////////////////////////////////////////////////////////////////////
   1024 // Network
   1025 
   1026 void Network::SetName(const std::string& name) {
   1027   std::string name_utf8;
   1028   ValidateUTF8(name, &name_utf8);
   1029   set_name(name_utf8);
   1030 }
   1031 
   1032 bool Network::ParseValue(int index, const Value* value) {
   1033   switch (index) {
   1034     case PROPERTY_INDEX_TYPE: {
   1035       std::string type_string;
   1036       if (value->GetAsString(&type_string)) {
   1037         ConnectionType type = ParseType(type_string);
   1038         LOG_IF(ERROR, type != type_)
   1039             << "Network with mismatched type: " << service_path_
   1040             << " " << type << " != " << type_;
   1041         return true;
   1042       }
   1043       break;
   1044     }
   1045     case PROPERTY_INDEX_DEVICE:
   1046       return value->GetAsString(&device_path_);
   1047     case PROPERTY_INDEX_NAME: {
   1048       std::string name;
   1049       if (value->GetAsString(&name)) {
   1050         SetName(name);
   1051         return true;
   1052       }
   1053       break;
   1054     }
   1055     case PROPERTY_INDEX_STATE: {
   1056       std::string state_string;
   1057       if (value->GetAsString(&state_string)) {
   1058         ConnectionState prev_state = state_;
   1059         state_ = ParseState(state_string);
   1060         if (state_ != prev_state) {
   1061           // State changed, so refresh IP address.
   1062           // Note: blocking DBus call. TODO(stevenjb): refactor this.
   1063           InitIPAddress();
   1064         }
   1065         return true;
   1066       }
   1067       break;
   1068     }
   1069     case PROPERTY_INDEX_MODE: {
   1070       std::string mode_string;
   1071       if (value->GetAsString(&mode_string)) {
   1072         mode_ = ParseMode(mode_string);
   1073         return true;
   1074       }
   1075       break;
   1076     }
   1077     case PROPERTY_INDEX_ERROR: {
   1078       std::string error_string;
   1079       if (value->GetAsString(&error_string)) {
   1080         error_ = ParseError(error_string);
   1081         return true;
   1082       }
   1083       break;
   1084     }
   1085     case PROPERTY_INDEX_CONNECTABLE:
   1086       return value->GetAsBoolean(&connectable_);
   1087     case PROPERTY_INDEX_IS_ACTIVE:
   1088       return value->GetAsBoolean(&is_active_);
   1089     case PROPERTY_INDEX_FAVORITE:
   1090       return value->GetAsBoolean(&favorite_);
   1091     case PROPERTY_INDEX_AUTO_CONNECT:
   1092       return value->GetAsBoolean(&auto_connect_);
   1093     case PROPERTY_INDEX_CONNECTIVITY_STATE: {
   1094       std::string connectivity_state_string;
   1095       if (value->GetAsString(&connectivity_state_string)) {
   1096         connectivity_state_ = ParseConnectivityState(connectivity_state_string);
   1097         return true;
   1098       }
   1099       break;
   1100     }
   1101     default:
   1102       break;
   1103   }
   1104   return false;
   1105 }
   1106 
   1107 void Network::ParseInfo(const DictionaryValue* info) {
   1108   for (DictionaryValue::key_iterator iter = info->begin_keys();
   1109        iter != info->end_keys(); ++iter) {
   1110     const std::string& key = *iter;
   1111     Value* value;
   1112     bool res = info->GetWithoutPathExpansion(key, &value);
   1113     DCHECK(res);
   1114     if (res) {
   1115       int index = property_index_parser().Get(key);
   1116       if (!ParseValue(index, value))  // virtual.
   1117         VLOG(1) << "Network: " << name()
   1118                 << " Type: " << ConnectionTypeToString(type())
   1119                 << " Unhandled key: " << key;
   1120     }
   1121   }
   1122 }
   1123 
   1124 void Network::SetValueProperty(const char* prop, Value* val) {
   1125   DCHECK(prop);
   1126   DCHECK(val);
   1127   if (!EnsureCrosLoaded())
   1128     return;
   1129   SetNetworkServiceProperty(service_path_.c_str(), prop, val);
   1130 }
   1131 
   1132 void Network::ClearProperty(const char* prop) {
   1133   DCHECK(prop);
   1134   if (!EnsureCrosLoaded())
   1135     return;
   1136   ClearNetworkServiceProperty(service_path_.c_str(), prop);
   1137 }
   1138 
   1139 void Network::SetStringProperty(
   1140     const char* prop, const std::string& str, std::string* dest) {
   1141   if (dest)
   1142     *dest = str;
   1143   scoped_ptr<Value> value(Value::CreateStringValue(str));
   1144   SetValueProperty(prop, value.get());
   1145 }
   1146 
   1147 void Network::SetOrClearStringProperty(const char* prop,
   1148                                        const std::string& str,
   1149                                        std::string* dest) {
   1150   if (str.empty()) {
   1151     ClearProperty(prop);
   1152     if (dest)
   1153       dest->clear();
   1154   } else {
   1155     SetStringProperty(prop, str, dest);
   1156   }
   1157 }
   1158 
   1159 void Network::SetBooleanProperty(const char* prop, bool b, bool* dest) {
   1160   if (dest)
   1161     *dest = b;
   1162   scoped_ptr<Value> value(Value::CreateBooleanValue(b));
   1163   SetValueProperty(prop, value.get());
   1164 }
   1165 
   1166 void Network::SetIntegerProperty(const char* prop, int i, int* dest) {
   1167   if (dest)
   1168     *dest = i;
   1169   scoped_ptr<Value> value(Value::CreateIntegerValue(i));
   1170   SetValueProperty(prop, value.get());
   1171 }
   1172 
   1173 void Network::SetAutoConnect(bool auto_connect) {
   1174   SetBooleanProperty(kAutoConnectProperty, auto_connect, &auto_connect_);
   1175 }
   1176 
   1177 std::string Network::GetStateString() const {
   1178   switch (state_) {
   1179     case STATE_UNKNOWN:
   1180       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNKNOWN);
   1181     case STATE_IDLE:
   1182       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_IDLE);
   1183     case STATE_CARRIER:
   1184       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_CARRIER);
   1185     case STATE_ASSOCIATION:
   1186       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_ASSOCIATION);
   1187     case STATE_CONFIGURATION:
   1188       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_CONFIGURATION);
   1189     case STATE_READY:
   1190       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_READY);
   1191     case STATE_DISCONNECT:
   1192       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_DISCONNECT);
   1193     case STATE_FAILURE:
   1194       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_FAILURE);
   1195     case STATE_ACTIVATION_FAILURE:
   1196       return l10n_util::GetStringUTF8(
   1197           IDS_CHROMEOS_NETWORK_STATE_ACTIVATION_FAILURE);
   1198   }
   1199   return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED);
   1200 }
   1201 
   1202 std::string Network::GetErrorString() const {
   1203   switch (error_) {
   1204     case ERROR_NO_ERROR:
   1205       // TODO(nkostylev): Introduce new error message "None" instead.
   1206       return std::string();
   1207     case ERROR_OUT_OF_RANGE:
   1208       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE);
   1209     case ERROR_PIN_MISSING:
   1210       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_PIN_MISSING);
   1211     case ERROR_DHCP_FAILED:
   1212       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_DHCP_FAILED);
   1213     case ERROR_CONNECT_FAILED:
   1214       return l10n_util::GetStringUTF8(
   1215           IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
   1216     case ERROR_BAD_PASSPHRASE:
   1217       return l10n_util::GetStringUTF8(
   1218           IDS_CHROMEOS_NETWORK_ERROR_BAD_PASSPHRASE);
   1219     case ERROR_BAD_WEPKEY:
   1220       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_BAD_WEPKEY);
   1221     case ERROR_ACTIVATION_FAILED:
   1222       return l10n_util::GetStringUTF8(
   1223           IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
   1224     case ERROR_NEED_EVDO:
   1225       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_NEED_EVDO);
   1226     case ERROR_NEED_HOME_NETWORK:
   1227       return l10n_util::GetStringUTF8(
   1228           IDS_CHROMEOS_NETWORK_ERROR_NEED_HOME_NETWORK);
   1229     case ERROR_OTASP_FAILED:
   1230       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_OTASP_FAILED);
   1231     case ERROR_AAA_FAILED:
   1232       return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_AAA_FAILED);
   1233   }
   1234   return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED);
   1235 }
   1236 
   1237 void Network::InitIPAddress() {
   1238   ip_address_.clear();
   1239   // If connected, get ip config.
   1240   if (EnsureCrosLoaded() && connected() && !device_path_.empty()) {
   1241     IPConfigStatus* ipconfig_status = ListIPConfigs(device_path_.c_str());
   1242     if (ipconfig_status) {
   1243       for (int i = 0; i < ipconfig_status->size; i++) {
   1244         IPConfig ipconfig = ipconfig_status->ips[i];
   1245         if (strlen(ipconfig.address) > 0) {
   1246           ip_address_ = ipconfig.address;
   1247           break;
   1248         }
   1249       }
   1250       FreeIPConfigStatus(ipconfig_status);
   1251     }
   1252   }
   1253 }
   1254 
   1255 ////////////////////////////////////////////////////////////////////////////////
   1256 // VirtualNetwork
   1257 
   1258 bool VirtualNetwork::ParseProviderValue(int index, const Value* value) {
   1259   switch (index) {
   1260     case PROPERTY_INDEX_HOST:
   1261       return value->GetAsString(&server_hostname_);
   1262     case PROPERTY_INDEX_NAME:
   1263       // Note: shadows Network::name_ property.
   1264       return value->GetAsString(&name_);
   1265     case PROPERTY_INDEX_TYPE: {
   1266       std::string provider_type_string;
   1267       if (value->GetAsString(&provider_type_string)) {
   1268         provider_type_ = ParseProviderType(provider_type_string);
   1269         return true;
   1270       }
   1271       break;
   1272     }
   1273     default:
   1274       break;
   1275   }
   1276   return false;
   1277 }
   1278 
   1279 bool VirtualNetwork::ParseValue(int index, const Value* value) {
   1280   switch (index) {
   1281     case PROPERTY_INDEX_PROVIDER: {
   1282       DCHECK_EQ(value->GetType(), Value::TYPE_DICTIONARY);
   1283       const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
   1284       for (DictionaryValue::key_iterator iter = dict->begin_keys();
   1285            iter != dict->end_keys(); ++iter) {
   1286         const std::string& key = *iter;
   1287         Value* v;
   1288         bool res = dict->GetWithoutPathExpansion(key, &v);
   1289         DCHECK(res);
   1290         if (res) {
   1291           int index = property_index_parser().Get(key);
   1292           if (!ParseProviderValue(index, v))
   1293             VLOG(1) << name() << ": Provider unhandled key: " << key
   1294                     << " Type: " << v->GetType();
   1295         }
   1296       }
   1297       return true;
   1298     }
   1299     case PROPERTY_INDEX_L2TPIPSEC_CA_CERT:
   1300       return value->GetAsString(&ca_cert_);
   1301     case PROPERTY_INDEX_L2TPIPSEC_PSK:
   1302       return value->GetAsString(&psk_passphrase_);
   1303     case PROPERTY_INDEX_L2TPIPSEC_CERT:
   1304       return value->GetAsString(&user_cert_);
   1305     case PROPERTY_INDEX_L2TPIPSEC_KEY:
   1306       return value->GetAsString(&user_cert_key_);
   1307     case PROPERTY_INDEX_L2TPIPSEC_USER:
   1308       return value->GetAsString(&username_);
   1309     case PROPERTY_INDEX_L2TPIPSEC_PASSWORD:
   1310       return value->GetAsString(&user_passphrase_);
   1311     default:
   1312       return Network::ParseValue(index, value);
   1313       break;
   1314   }
   1315   return false;
   1316 }
   1317 
   1318 void VirtualNetwork::ParseInfo(const DictionaryValue* info) {
   1319   Network::ParseInfo(info);
   1320   VLOG(1) << "VPN: " << name()
   1321           << " Type: " << ProviderTypeToString(provider_type());
   1322   if (provider_type_ == PROVIDER_TYPE_L2TP_IPSEC_PSK) {
   1323     if (!user_cert_.empty())
   1324       provider_type_ = PROVIDER_TYPE_L2TP_IPSEC_USER_CERT;
   1325   }
   1326 }
   1327 
   1328 bool VirtualNetwork::NeedMoreInfoToConnect() const {
   1329   if (server_hostname_.empty() || username_.empty() || user_passphrase_.empty())
   1330     return true;
   1331   switch (provider_type_) {
   1332     case PROVIDER_TYPE_L2TP_IPSEC_PSK:
   1333       if (psk_passphrase_.empty())
   1334         return true;
   1335       break;
   1336     case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
   1337     case PROVIDER_TYPE_OPEN_VPN:
   1338       if (user_cert_.empty())
   1339         return true;
   1340       break;
   1341     case PROVIDER_TYPE_MAX:
   1342       break;
   1343   }
   1344   return false;
   1345 }
   1346 
   1347 void VirtualNetwork::SetCACert(const std::string& ca_cert) {
   1348   SetStringProperty(kL2TPIPSecCACertProperty, ca_cert, &ca_cert_);
   1349 }
   1350 
   1351 void VirtualNetwork::SetPSKPassphrase(const std::string& psk_passphrase) {
   1352   SetStringProperty(kL2TPIPSecPSKProperty, psk_passphrase,
   1353                            &psk_passphrase_);
   1354 }
   1355 
   1356 void VirtualNetwork::SetUserCert(const std::string& user_cert) {
   1357   SetStringProperty(kL2TPIPSecCertProperty, user_cert, &user_cert_);
   1358 }
   1359 
   1360 void VirtualNetwork::SetUserCertKey(const std::string& key) {
   1361   SetStringProperty(kL2TPIPSecKeyProperty, key, &user_cert_key_);
   1362 }
   1363 
   1364 void VirtualNetwork::SetUsername(const std::string& username) {
   1365   SetStringProperty(kL2TPIPSecUserProperty, username, &username_);
   1366 }
   1367 
   1368 void VirtualNetwork::SetUserPassphrase(const std::string& user_passphrase) {
   1369   SetStringProperty(kL2TPIPSecPasswordProperty, user_passphrase,
   1370                     &user_passphrase_);
   1371 }
   1372 
   1373 std::string VirtualNetwork::GetProviderTypeString() const {
   1374   switch (this->provider_type_) {
   1375     case PROVIDER_TYPE_L2TP_IPSEC_PSK:
   1376       return l10n_util::GetStringUTF8(
   1377           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK);
   1378       break;
   1379     case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
   1380       return l10n_util::GetStringUTF8(
   1381           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT);
   1382       break;
   1383     case PROVIDER_TYPE_OPEN_VPN:
   1384       return l10n_util::GetStringUTF8(
   1385           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN);
   1386       break;
   1387     default:
   1388       return l10n_util::GetStringUTF8(
   1389           IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
   1390       break;
   1391   }
   1392 }
   1393 
   1394 ////////////////////////////////////////////////////////////////////////////////
   1395 // WirelessNetwork
   1396 
   1397 bool WirelessNetwork::ParseValue(int index, const Value* value) {
   1398   switch (index) {
   1399     case PROPERTY_INDEX_SIGNAL_STRENGTH:
   1400       return value->GetAsInteger(&strength_);
   1401     default:
   1402       return Network::ParseValue(index, value);
   1403       break;
   1404   }
   1405   return false;
   1406 }
   1407 
   1408 ////////////////////////////////////////////////////////////////////////////////
   1409 // CellularDataPlan
   1410 
   1411 string16 CellularDataPlan::GetPlanDesciption() const {
   1412   switch (plan_type) {
   1413     case chromeos::CELLULAR_DATA_PLAN_UNLIMITED: {
   1414       return l10n_util::GetStringFUTF16(
   1415           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_UNLIMITED_DATA,
   1416           base::TimeFormatFriendlyDate(plan_start_time));
   1417       break;
   1418     }
   1419     case chromeos::CELLULAR_DATA_PLAN_METERED_PAID: {
   1420       return l10n_util::GetStringFUTF16(
   1421                 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_DATA,
   1422                 FormatBytes(plan_data_bytes,
   1423                             GetByteDisplayUnits(plan_data_bytes),
   1424                             true),
   1425                 base::TimeFormatFriendlyDate(plan_start_time));
   1426     }
   1427     case chromeos::CELLULAR_DATA_PLAN_METERED_BASE: {
   1428       return l10n_util::GetStringFUTF16(
   1429                 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_RECEIVED_FREE_DATA,
   1430                 FormatBytes(plan_data_bytes,
   1431                             GetByteDisplayUnits(plan_data_bytes),
   1432                             true),
   1433                 base::TimeFormatFriendlyDate(plan_start_time));
   1434     default:
   1435       break;
   1436     }
   1437   }
   1438   return string16();
   1439 }
   1440 
   1441 string16 CellularDataPlan::GetRemainingWarning() const {
   1442   if (plan_type == chromeos::CELLULAR_DATA_PLAN_UNLIMITED) {
   1443     // Time based plan. Show nearing expiration and data expiration.
   1444     if (remaining_time().InSeconds() <= chromeos::kCellularDataVeryLowSecs) {
   1445       return GetPlanExpiration();
   1446     }
   1447   } else if (plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_PAID ||
   1448              plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_BASE) {
   1449     // Metered plan. Show low data and out of data.
   1450     if (remaining_data() <= chromeos::kCellularDataVeryLowBytes) {
   1451       int64 remaining_mbytes = remaining_data() / (1024 * 1024);
   1452       return l10n_util::GetStringFUTF16(
   1453           IDS_NETWORK_DATA_REMAINING_MESSAGE,
   1454           UTF8ToUTF16(base::Int64ToString(remaining_mbytes)));
   1455     }
   1456   }
   1457   return string16();
   1458 }
   1459 
   1460 string16 CellularDataPlan::GetDataRemainingDesciption() const {
   1461   int64 remaining_bytes = remaining_data();
   1462   switch (plan_type) {
   1463     case chromeos::CELLULAR_DATA_PLAN_UNLIMITED: {
   1464       return l10n_util::GetStringUTF16(
   1465           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_UNLIMITED);
   1466     }
   1467     case chromeos::CELLULAR_DATA_PLAN_METERED_PAID: {
   1468       return FormatBytes(remaining_bytes,
   1469           GetByteDisplayUnits(remaining_bytes),
   1470           true);
   1471     }
   1472     case chromeos::CELLULAR_DATA_PLAN_METERED_BASE: {
   1473       return FormatBytes(remaining_bytes,
   1474           GetByteDisplayUnits(remaining_bytes),
   1475           true);
   1476     }
   1477     default:
   1478       break;
   1479   }
   1480   return string16();
   1481 }
   1482 
   1483 string16 CellularDataPlan::GetUsageInfo() const {
   1484   if (plan_type == chromeos::CELLULAR_DATA_PLAN_UNLIMITED) {
   1485     // Time based plan. Show nearing expiration and data expiration.
   1486     return GetPlanExpiration();
   1487   } else if (plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_PAID ||
   1488              plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_BASE) {
   1489     // Metered plan. Show low data and out of data.
   1490     int64 remaining_bytes = remaining_data();
   1491     if (remaining_bytes == 0) {
   1492       return l10n_util::GetStringUTF16(
   1493           IDS_NETWORK_DATA_NONE_AVAILABLE_MESSAGE);
   1494     } else if (remaining_bytes < 1024 * 1024) {
   1495       return l10n_util::GetStringUTF16(
   1496           IDS_NETWORK_DATA_LESS_THAN_ONE_MB_AVAILABLE_MESSAGE);
   1497     } else {
   1498       int64 remaining_mb = remaining_bytes / (1024 * 1024);
   1499       return l10n_util::GetStringFUTF16(
   1500           IDS_NETWORK_DATA_MB_AVAILABLE_MESSAGE,
   1501           UTF8ToUTF16(base::Int64ToString(remaining_mb)));
   1502     }
   1503   }
   1504   return string16();
   1505 }
   1506 
   1507 std::string CellularDataPlan::GetUniqueIdentifier() const {
   1508   // A cellular plan is uniquely described by the union of name, type,
   1509   // start time, end time, and max bytes.
   1510   // So we just return a union of all these variables.
   1511   return plan_name + "|" +
   1512       base::Int64ToString(plan_type) + "|" +
   1513       base::Int64ToString(plan_start_time.ToInternalValue()) + "|" +
   1514       base::Int64ToString(plan_end_time.ToInternalValue()) + "|" +
   1515       base::Int64ToString(plan_data_bytes);
   1516 }
   1517 
   1518 base::TimeDelta CellularDataPlan::remaining_time() const {
   1519   base::TimeDelta time = plan_end_time - base::Time::Now();
   1520   return time.InMicroseconds() < 0 ? base::TimeDelta() : time;
   1521 }
   1522 
   1523 int64 CellularDataPlan::remaining_minutes() const {
   1524   return remaining_time().InMinutes();
   1525 }
   1526 
   1527 int64 CellularDataPlan::remaining_data() const {
   1528   int64 data = plan_data_bytes - data_bytes_used;
   1529   return data < 0 ? 0 : data;
   1530 }
   1531 
   1532 string16 CellularDataPlan::GetPlanExpiration() const {
   1533   return TimeFormat::TimeRemaining(remaining_time());
   1534 }
   1535 
   1536 ////////////////////////////////////////////////////////////////////////////////
   1537 // CellularNetwork::Apn
   1538 
   1539 void CellularNetwork::Apn::Set(const DictionaryValue& dict) {
   1540   if (!dict.GetStringWithoutPathExpansion(kApnProperty, &apn))
   1541     apn.clear();
   1542   if (!dict.GetStringWithoutPathExpansion(kNetworkIdProperty, &network_id))
   1543     network_id.clear();
   1544   if (!dict.GetStringWithoutPathExpansion(kUsernameProperty, &username))
   1545     username.clear();
   1546   if (!dict.GetStringWithoutPathExpansion(kPasswordProperty, &password))
   1547     password.clear();
   1548 }
   1549 
   1550 ////////////////////////////////////////////////////////////////////////////////
   1551 // CellularNetwork
   1552 
   1553 CellularNetwork::~CellularNetwork() {
   1554 }
   1555 
   1556 bool CellularNetwork::ParseValue(int index, const Value* value) {
   1557   switch (index) {
   1558     case PROPERTY_INDEX_ACTIVATION_STATE: {
   1559       std::string activation_state_string;
   1560       if (value->GetAsString(&activation_state_string)) {
   1561         ActivationState prev_state = activation_state_;
   1562         activation_state_ = ParseActivationState(activation_state_string);
   1563         if (activation_state_ != prev_state)
   1564           RefreshDataPlansIfNeeded();
   1565         return true;
   1566       }
   1567       break;
   1568     }
   1569     case PROPERTY_INDEX_CELLULAR_APN: {
   1570       if (value->IsType(Value::TYPE_DICTIONARY)) {
   1571         apn_.Set(*static_cast<const DictionaryValue*>(value));
   1572         return true;
   1573       }
   1574       break;
   1575     }
   1576     case PROPERTY_INDEX_CELLULAR_LAST_GOOD_APN: {
   1577       if (value->IsType(Value::TYPE_DICTIONARY)) {
   1578         last_good_apn_.Set(*static_cast<const DictionaryValue*>(value));
   1579         return true;
   1580       }
   1581       break;
   1582     }
   1583     case PROPERTY_INDEX_NETWORK_TECHNOLOGY: {
   1584       std::string network_technology_string;
   1585       if (value->GetAsString(&network_technology_string)) {
   1586         network_technology_ = ParseNetworkTechnology(network_technology_string);
   1587         return true;
   1588       }
   1589       break;
   1590     }
   1591     case PROPERTY_INDEX_ROAMING_STATE: {
   1592       std::string roaming_state_string;
   1593       if (value->GetAsString(&roaming_state_string)) {
   1594         roaming_state_ = ParseRoamingState(roaming_state_string);
   1595         return true;
   1596       }
   1597       break;
   1598     }
   1599     case PROPERTY_INDEX_OPERATOR_NAME:
   1600       return value->GetAsString(&operator_name_);
   1601     case PROPERTY_INDEX_OPERATOR_CODE:
   1602       return value->GetAsString(&operator_code_);
   1603     case PROPERTY_INDEX_SERVING_OPERATOR: {
   1604       if (value->IsType(Value::TYPE_DICTIONARY)) {
   1605         const DictionaryValue *dict =
   1606             static_cast<const DictionaryValue*>(value);
   1607         operator_code_.clear();
   1608         operator_country_.clear();
   1609         operator_name_.clear();
   1610         dict->GetStringWithoutPathExpansion(kOperatorNameKey,
   1611                                             &operator_name_);
   1612         dict->GetStringWithoutPathExpansion(kOperatorCodeKey,
   1613                                             &operator_code_);
   1614         dict->GetStringWithoutPathExpansion(kOperatorCountryKey,
   1615                                             &operator_country_);
   1616         return true;
   1617       }
   1618       break;
   1619     }
   1620     case PROPERTY_INDEX_PAYMENT_URL:
   1621       return value->GetAsString(&payment_url_);
   1622     case PROPERTY_INDEX_USAGE_URL:
   1623       return value->GetAsString(&usage_url_);
   1624     case PROPERTY_INDEX_STATE: {
   1625       // Save previous state before calling WirelessNetwork::ParseValue.
   1626       ConnectionState prev_state = state_;
   1627       if (WirelessNetwork::ParseValue(index, value)) {
   1628         if (state_ != prev_state)
   1629           RefreshDataPlansIfNeeded();
   1630         return true;
   1631       }
   1632       break;
   1633     }
   1634     case PROPERTY_INDEX_CONNECTIVITY_STATE: {
   1635       // Save previous state before calling WirelessNetwork::ParseValue.
   1636       ConnectivityState prev_state = connectivity_state_;
   1637       if (WirelessNetwork::ParseValue(index, value)) {
   1638         if (connectivity_state_ != prev_state)
   1639           RefreshDataPlansIfNeeded();
   1640         return true;
   1641       }
   1642       break;
   1643     }
   1644     default:
   1645       return WirelessNetwork::ParseValue(index, value);
   1646   }
   1647   return false;
   1648 }
   1649 
   1650 bool CellularNetwork::StartActivation() const {
   1651   if (!EnsureCrosLoaded())
   1652     return false;
   1653   return ActivateCellularModem(service_path().c_str(), NULL);
   1654 }
   1655 
   1656 void CellularNetwork::RefreshDataPlansIfNeeded() const {
   1657   if (!EnsureCrosLoaded())
   1658     return;
   1659   if (connected() && activated())
   1660     RequestCellularDataPlanUpdate(service_path().c_str());
   1661 }
   1662 
   1663 void CellularNetwork::SetApn(const Apn& apn) {
   1664   if (!EnsureCrosLoaded())
   1665     return;
   1666 
   1667   if (!apn.apn.empty()) {
   1668     DictionaryValue value;
   1669     value.SetString(kApnProperty, apn.apn);
   1670     value.SetString(kNetworkIdProperty, apn.network_id);
   1671     value.SetString(kUsernameProperty, apn.username);
   1672     value.SetString(kPasswordProperty, apn.password);
   1673     SetValueProperty(kCellularApnProperty, &value);
   1674   } else {
   1675     ClearProperty(kCellularApnProperty);
   1676   }
   1677 }
   1678 
   1679 bool CellularNetwork::SupportsDataPlan() const {
   1680   // TODO(nkostylev): Are there cases when only one of this is defined?
   1681   return !usage_url().empty() || !payment_url().empty();
   1682 }
   1683 
   1684 std::string CellularNetwork::GetNetworkTechnologyString() const {
   1685   // No need to localize these cellular technology abbreviations.
   1686   switch (network_technology_) {
   1687     case NETWORK_TECHNOLOGY_1XRTT:
   1688       return "1xRTT";
   1689       break;
   1690     case NETWORK_TECHNOLOGY_EVDO:
   1691       return "EVDO";
   1692       break;
   1693     case NETWORK_TECHNOLOGY_GPRS:
   1694       return "GPRS";
   1695       break;
   1696     case NETWORK_TECHNOLOGY_EDGE:
   1697       return "EDGE";
   1698       break;
   1699     case NETWORK_TECHNOLOGY_UMTS:
   1700       return "UMTS";
   1701       break;
   1702     case NETWORK_TECHNOLOGY_HSPA:
   1703       return "HSPA";
   1704       break;
   1705     case NETWORK_TECHNOLOGY_HSPA_PLUS:
   1706       return "HSPA Plus";
   1707       break;
   1708     case NETWORK_TECHNOLOGY_LTE:
   1709       return "LTE";
   1710       break;
   1711     case NETWORK_TECHNOLOGY_LTE_ADVANCED:
   1712       return "LTE Advanced";
   1713       break;
   1714     default:
   1715       return l10n_util::GetStringUTF8(
   1716           IDS_CHROMEOS_NETWORK_CELLULAR_TECHNOLOGY_UNKNOWN);
   1717       break;
   1718   }
   1719 }
   1720 
   1721 std::string CellularNetwork::GetConnectivityStateString() const {
   1722   // These strings do not appear in the UI, so no need to localize them
   1723   switch (connectivity_state_) {
   1724     case CONN_STATE_UNRESTRICTED:
   1725       return "unrestricted";
   1726       break;
   1727     case CONN_STATE_RESTRICTED:
   1728       return "restricted";
   1729       break;
   1730     case CONN_STATE_NONE:
   1731       return "none";
   1732       break;
   1733     case CONN_STATE_UNKNOWN:
   1734     default:
   1735       return "unknown";
   1736   }
   1737 }
   1738 
   1739 std::string CellularNetwork::ActivationStateToString(
   1740     ActivationState activation_state) {
   1741   switch (activation_state) {
   1742     case ACTIVATION_STATE_ACTIVATED:
   1743       return l10n_util::GetStringUTF8(
   1744           IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATED);
   1745       break;
   1746     case ACTIVATION_STATE_ACTIVATING:
   1747       return l10n_util::GetStringUTF8(
   1748           IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATING);
   1749       break;
   1750     case ACTIVATION_STATE_NOT_ACTIVATED:
   1751       return l10n_util::GetStringUTF8(
   1752           IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_NOT_ACTIVATED);
   1753       break;
   1754     case ACTIVATION_STATE_PARTIALLY_ACTIVATED:
   1755       return l10n_util::GetStringUTF8(
   1756           IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_PARTIALLY_ACTIVATED);
   1757       break;
   1758     default:
   1759       return l10n_util::GetStringUTF8(
   1760           IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_UNKNOWN);
   1761       break;
   1762   }
   1763 }
   1764 
   1765 std::string CellularNetwork::GetActivationStateString() const {
   1766   return ActivationStateToString(this->activation_state_);
   1767 }
   1768 
   1769 std::string CellularNetwork::GetRoamingStateString() const {
   1770   switch (this->roaming_state_) {
   1771     case ROAMING_STATE_HOME:
   1772       return l10n_util::GetStringUTF8(
   1773           IDS_CHROMEOS_NETWORK_ROAMING_STATE_HOME);
   1774       break;
   1775     case ROAMING_STATE_ROAMING:
   1776       return l10n_util::GetStringUTF8(
   1777           IDS_CHROMEOS_NETWORK_ROAMING_STATE_ROAMING);
   1778       break;
   1779     default:
   1780       return l10n_util::GetStringUTF8(
   1781           IDS_CHROMEOS_NETWORK_ROAMING_STATE_UNKNOWN);
   1782       break;
   1783   }
   1784 }
   1785 
   1786 ////////////////////////////////////////////////////////////////////////////////
   1787 // WifiNetwork
   1788 
   1789 // Called from ParseNetwork after calling ParseInfo.
   1790 void WifiNetwork::CalculateUniqueId() {
   1791   ConnectionSecurity encryption = encryption_;
   1792   // Flimflam treats wpa and rsn as psk internally, so convert those types
   1793   // to psk for unique naming.
   1794   if (encryption == SECURITY_WPA || encryption == SECURITY_RSN)
   1795     encryption = SECURITY_PSK;
   1796   std::string security = std::string(SecurityToString(encryption));
   1797   unique_id_ = security + "|" + name_;
   1798 }
   1799 
   1800 bool WifiNetwork::SetSsid(const std::string& ssid) {
   1801   // Detects encoding and convert to UTF-8.
   1802   std::string ssid_utf8;
   1803   if (!IsStringUTF8(ssid)) {
   1804     std::string encoding;
   1805     if (base::DetectEncoding(ssid, &encoding)) {
   1806       if (!base::ConvertToUtf8AndNormalize(ssid, encoding, &ssid_utf8)) {
   1807         ssid_utf8.clear();
   1808       }
   1809     }
   1810   }
   1811 
   1812   if (ssid_utf8.empty())
   1813     SetName(ssid);
   1814   else
   1815     SetName(ssid_utf8);
   1816 
   1817   return true;
   1818 }
   1819 
   1820 bool WifiNetwork::SetHexSsid(const std::string& ssid_hex) {
   1821   // Converts ascii hex dump (eg. "49656c6c6f") to string (eg. "Hello").
   1822   std::vector<uint8> ssid_raw;
   1823   if (!base::HexStringToBytes(ssid_hex, &ssid_raw)) {
   1824     LOG(ERROR) << "Iligal hex char is found in WiFi.HexSSID.";
   1825     ssid_raw.clear();
   1826     return false;
   1827   }
   1828 
   1829   return SetSsid(std::string(ssid_raw.begin(), ssid_raw.end()));
   1830 }
   1831 
   1832 bool WifiNetwork::ParseValue(int index, const Value* value) {
   1833   switch (index) {
   1834     case PROPERTY_INDEX_WIFI_HEX_SSID: {
   1835       std::string ssid_hex;
   1836       if (!value->GetAsString(&ssid_hex))
   1837         return false;
   1838 
   1839       SetHexSsid(ssid_hex);
   1840       return true;
   1841     }
   1842     case PROPERTY_INDEX_NAME: {
   1843       // Does not change network name when it was already set by WiFi.HexSSID.
   1844       if (!name().empty())
   1845         return true;
   1846       else
   1847         return WirelessNetwork::ParseValue(index, value);
   1848     }
   1849     case PROPERTY_INDEX_SECURITY: {
   1850       std::string security_string;
   1851       if (value->GetAsString(&security_string)) {
   1852         encryption_ = ParseSecurity(security_string);
   1853         return true;
   1854       }
   1855       break;
   1856     }
   1857     case PROPERTY_INDEX_PASSPHRASE: {
   1858       std::string passphrase;
   1859       if (value->GetAsString(&passphrase)) {
   1860         // Only store the passphrase if we are the owner.
   1861         // TODO(stevenjb): Remove this when chromium-os:12948 is resolved.
   1862         if (chromeos::UserManager::Get()->current_user_is_owner())
   1863           passphrase_ = passphrase;
   1864         return true;
   1865       }
   1866       break;
   1867     }
   1868     case PROPERTY_INDEX_PASSPHRASE_REQUIRED:
   1869       return value->GetAsBoolean(&passphrase_required_);
   1870     case PROPERTY_INDEX_SAVE_CREDENTIALS:
   1871       return value->GetAsBoolean(&save_credentials_);
   1872     case PROPERTY_INDEX_IDENTITY:
   1873       return value->GetAsString(&identity_);
   1874     case PROPERTY_INDEX_CERT_PATH:
   1875       return value->GetAsString(&cert_path_);
   1876     case PROPERTY_INDEX_EAP_IDENTITY:
   1877       return value->GetAsString(&eap_identity_);
   1878     case PROPERTY_INDEX_EAP_METHOD: {
   1879       std::string method;
   1880       if (value->GetAsString(&method)) {
   1881         eap_method_ = ParseEAPMethod(method);
   1882         return true;
   1883       }
   1884       break;
   1885     }
   1886     case PROPERTY_INDEX_EAP_PHASE_2_AUTH: {
   1887       std::string auth;
   1888       if (value->GetAsString(&auth)) {
   1889         eap_phase_2_auth_ = ParseEAPPhase2Auth(auth);
   1890         return true;
   1891       }
   1892       break;
   1893     }
   1894     case PROPERTY_INDEX_EAP_ANONYMOUS_IDENTITY:
   1895       return value->GetAsString(&eap_anonymous_identity_);
   1896     case PROPERTY_INDEX_EAP_CERT_ID:
   1897       return value->GetAsString(&eap_client_cert_pkcs11_id_);
   1898     case PROPERTY_INDEX_EAP_CA_CERT_NSS:
   1899       return value->GetAsString(&eap_server_ca_cert_nss_nickname_);
   1900     case PROPERTY_INDEX_EAP_USE_SYSTEM_CAS:
   1901       return value->GetAsBoolean(&eap_use_system_cas_);
   1902     case PROPERTY_INDEX_EAP_PASSWORD:
   1903       return value->GetAsString(&eap_passphrase_);
   1904     case PROPERTY_INDEX_EAP_CLIENT_CERT:
   1905     case PROPERTY_INDEX_EAP_CLIENT_CERT_NSS:
   1906     case PROPERTY_INDEX_EAP_PRIVATE_KEY:
   1907     case PROPERTY_INDEX_EAP_PRIVATE_KEY_PASSWORD:
   1908     case PROPERTY_INDEX_EAP_KEY_ID:
   1909     case PROPERTY_INDEX_EAP_CA_CERT:
   1910     case PROPERTY_INDEX_EAP_CA_CERT_ID:
   1911     case PROPERTY_INDEX_EAP_PIN:
   1912     case PROPERTY_INDEX_EAP_KEY_MGMT:
   1913       // These properties are currently not used in the UI.
   1914       return true;
   1915     default:
   1916       return WirelessNetwork::ParseValue(index, value);
   1917   }
   1918   return false;
   1919 }
   1920 
   1921 void WifiNetwork::ParseInfo(const DictionaryValue* info) {
   1922   Network::ParseInfo(info);
   1923   CalculateUniqueId();
   1924 }
   1925 
   1926 const std::string& WifiNetwork::GetPassphrase() const {
   1927   if (!user_passphrase_.empty())
   1928     return user_passphrase_;
   1929   return passphrase_;
   1930 }
   1931 
   1932 void WifiNetwork::SetPassphrase(const std::string& passphrase) {
   1933   // Set the user_passphrase_ only; passphrase_ stores the flimflam value.
   1934   // If the user sets an empty passphrase, restore it to the passphrase
   1935   // remembered by flimflam.
   1936   if (!passphrase.empty()) {
   1937     user_passphrase_ = passphrase;
   1938     passphrase_ = passphrase;
   1939   } else {
   1940     user_passphrase_ = passphrase_;
   1941   }
   1942   // Send the change to flimflam. If the format is valid, it will propagate to
   1943   // passphrase_ with a service update.
   1944   SetOrClearStringProperty(kPassphraseProperty, passphrase, NULL);
   1945 }
   1946 
   1947 void WifiNetwork::SetSaveCredentials(bool save_credentials) {
   1948   SetBooleanProperty(kSaveCredentialsProperty, save_credentials,
   1949                      &save_credentials_);
   1950 }
   1951 
   1952 // See src/third_party/flimflam/doc/service-api.txt for properties that
   1953 // flimflam will forget when SaveCredentials is false.
   1954 void WifiNetwork::EraseCredentials() {
   1955   WipeString(&passphrase_);
   1956   WipeString(&user_passphrase_);
   1957   WipeString(&eap_client_cert_pkcs11_id_);
   1958   WipeString(&eap_identity_);
   1959   WipeString(&eap_anonymous_identity_);
   1960   WipeString(&eap_passphrase_);
   1961 }
   1962 
   1963 void WifiNetwork::SetIdentity(const std::string& identity) {
   1964   SetStringProperty(kIdentityProperty, identity, &identity_);
   1965 }
   1966 
   1967 void WifiNetwork::SetCertPath(const std::string& cert_path) {
   1968   SetStringProperty(kCertPathProperty, cert_path, &cert_path_);
   1969 }
   1970 
   1971 void WifiNetwork::SetEAPMethod(EAPMethod method) {
   1972   eap_method_ = method;
   1973   switch (method) {
   1974     case EAP_METHOD_PEAP:
   1975       SetStringProperty(kEapMethodProperty, kEapMethodPEAP, NULL);
   1976       break;
   1977     case EAP_METHOD_TLS:
   1978       SetStringProperty(kEapMethodProperty, kEapMethodTLS, NULL);
   1979       break;
   1980     case EAP_METHOD_TTLS:
   1981       SetStringProperty(kEapMethodProperty, kEapMethodTTLS, NULL);
   1982       break;
   1983     case EAP_METHOD_LEAP:
   1984       SetStringProperty(kEapMethodProperty, kEapMethodLEAP, NULL);
   1985       break;
   1986     default:
   1987       ClearProperty(kEapMethodProperty);
   1988       break;
   1989   }
   1990 }
   1991 
   1992 void WifiNetwork::SetEAPPhase2Auth(EAPPhase2Auth auth) {
   1993   eap_phase_2_auth_ = auth;
   1994   bool is_peap = (eap_method_ == EAP_METHOD_PEAP);
   1995   switch (auth) {
   1996     case EAP_PHASE_2_AUTH_AUTO:
   1997       ClearProperty(kEapPhase2AuthProperty);
   1998       break;
   1999     case EAP_PHASE_2_AUTH_MD5:
   2000       SetStringProperty(kEapPhase2AuthProperty,
   2001                         is_peap ? kEapPhase2AuthPEAPMD5
   2002                                 : kEapPhase2AuthTTLSMD5,
   2003                         NULL);
   2004       break;
   2005     case EAP_PHASE_2_AUTH_MSCHAPV2:
   2006       SetStringProperty(kEapPhase2AuthProperty,
   2007                         is_peap ? kEapPhase2AuthPEAPMSCHAPV2
   2008                                 : kEapPhase2AuthTTLSMSCHAPV2,
   2009                         NULL);
   2010       break;
   2011     case EAP_PHASE_2_AUTH_MSCHAP:
   2012       SetStringProperty(kEapPhase2AuthProperty, kEapPhase2AuthTTLSMSCHAP, NULL);
   2013       break;
   2014     case EAP_PHASE_2_AUTH_PAP:
   2015       SetStringProperty(kEapPhase2AuthProperty, kEapPhase2AuthTTLSPAP, NULL);
   2016       break;
   2017     case EAP_PHASE_2_AUTH_CHAP:
   2018       SetStringProperty(kEapPhase2AuthProperty, kEapPhase2AuthTTLSCHAP, NULL);
   2019       break;
   2020   }
   2021 }
   2022 
   2023 void WifiNetwork::SetEAPServerCaCertNssNickname(
   2024     const std::string& nss_nickname) {
   2025   VLOG(1) << "SetEAPServerCaCertNssNickname " << nss_nickname;
   2026   SetOrClearStringProperty(kEapCaCertNssProperty, nss_nickname,
   2027                            &eap_server_ca_cert_nss_nickname_);
   2028 }
   2029 
   2030 void WifiNetwork::SetEAPClientCertPkcs11Id(const std::string& pkcs11_id) {
   2031   VLOG(1) << "SetEAPClientCertPkcs11Id " << pkcs11_id;
   2032   SetOrClearStringProperty(kEapCertIDProperty, pkcs11_id,
   2033                            &eap_client_cert_pkcs11_id_);
   2034 }
   2035 
   2036 void WifiNetwork::SetEAPUseSystemCAs(bool use_system_cas) {
   2037   SetBooleanProperty(kEapUseSystemCAsProperty, use_system_cas,
   2038                      &eap_use_system_cas_);
   2039 }
   2040 
   2041 void WifiNetwork::SetEAPIdentity(const std::string& identity) {
   2042   SetOrClearStringProperty(kEapIdentityProperty, identity, &eap_identity_);
   2043 }
   2044 
   2045 void WifiNetwork::SetEAPAnonymousIdentity(const std::string& identity) {
   2046   SetOrClearStringProperty(kEapAnonymousIdentityProperty, identity,
   2047                            &eap_anonymous_identity_);
   2048 }
   2049 
   2050 void WifiNetwork::SetEAPPassphrase(const std::string& passphrase) {
   2051   SetOrClearStringProperty(kEapPasswordProperty, passphrase, &eap_passphrase_);
   2052 }
   2053 
   2054 std::string WifiNetwork::GetEncryptionString() const {
   2055   switch (encryption_) {
   2056     case SECURITY_UNKNOWN:
   2057       break;
   2058     case SECURITY_NONE:
   2059       return "";
   2060     case SECURITY_WEP:
   2061       return "WEP";
   2062     case SECURITY_WPA:
   2063       return "WPA";
   2064     case SECURITY_RSN:
   2065       return "RSN";
   2066     case SECURITY_8021X:
   2067       return "8021X";
   2068     case SECURITY_PSK:
   2069       return "PSK";
   2070   }
   2071   return "Unknown";
   2072 }
   2073 
   2074 bool WifiNetwork::IsPassphraseRequired() const {
   2075   // TODO(stevenjb): Remove error_ tests when fixed in flimflam
   2076   // (http://crosbug.com/10135).
   2077   if (error_ == ERROR_BAD_PASSPHRASE || error_ == ERROR_BAD_WEPKEY)
   2078     return true;
   2079   // For 802.1x networks, configuration is required if connectable is false.
   2080   if (encryption_ == SECURITY_8021X)
   2081     return !connectable_;
   2082   return passphrase_required_;
   2083 }
   2084 
   2085 // Parse 'path' to determine if the certificate is stored in a pkcs#11 device.
   2086 // flimflam recognizes the string "SETTINGS:" to specify authentication
   2087 // parameters. 'key_id=' indicates that the certificate is stored in a pkcs#11
   2088 // device. See src/third_party/flimflam/files/doc/service-api.txt.
   2089 bool WifiNetwork::IsCertificateLoaded() const {
   2090   static const std::string settings_string("SETTINGS:");
   2091   static const std::string pkcs11_key("key_id");
   2092   if (cert_path_.find(settings_string) == 0) {
   2093     std::string::size_type idx = cert_path_.find(pkcs11_key);
   2094     if (idx != std::string::npos)
   2095       idx = cert_path_.find_first_not_of(kWhitespaceASCII,
   2096                                          idx + pkcs11_key.length());
   2097     if (idx != std::string::npos && cert_path_[idx] == '=')
   2098       return true;
   2099   }
   2100   return false;
   2101 }
   2102 
   2103 ////////////////////////////////////////////////////////////////////////////////
   2104 // NetworkLibrary
   2105 
   2106 class NetworkLibraryImpl : public NetworkLibrary  {
   2107  public:
   2108   NetworkLibraryImpl()
   2109       : network_manager_monitor_(NULL),
   2110         data_plan_monitor_(NULL),
   2111         ethernet_(NULL),
   2112         active_wifi_(NULL),
   2113         active_cellular_(NULL),
   2114         active_virtual_(NULL),
   2115         available_devices_(0),
   2116         enabled_devices_(0),
   2117         connected_devices_(0),
   2118         wifi_scanning_(false),
   2119         offline_mode_(false),
   2120         is_locked_(false),
   2121         sim_operation_(SIM_OPERATION_NONE),
   2122         notify_task_(NULL) {
   2123     if (EnsureCrosLoaded()) {
   2124       Init();
   2125       network_manager_monitor_ =
   2126           MonitorNetworkManager(&NetworkManagerStatusChangedHandler,
   2127                                 this);
   2128       data_plan_monitor_ = MonitorCellularDataPlan(&DataPlanUpdateHandler,
   2129                                                    this);
   2130       network_login_observer_.reset(new NetworkLoginObserver(this));
   2131     } else {
   2132       InitTestData();
   2133     }
   2134   }
   2135 
   2136   virtual ~NetworkLibraryImpl() {
   2137     network_manager_observers_.Clear();
   2138     if (network_manager_monitor_)
   2139       DisconnectPropertyChangeMonitor(network_manager_monitor_);
   2140     data_plan_observers_.Clear();
   2141     pin_operation_observers_.Clear();
   2142     user_action_observers_.Clear();
   2143     if (data_plan_monitor_)
   2144       DisconnectDataPlanUpdateMonitor(data_plan_monitor_);
   2145     STLDeleteValues(&network_observers_);
   2146     STLDeleteValues(&network_device_observers_);
   2147     ClearNetworks(true /*delete networks*/);
   2148     ClearRememberedNetworks(true /*delete networks*/);
   2149     STLDeleteValues(&data_plan_map_);
   2150   }
   2151 
   2152   virtual void AddNetworkManagerObserver(NetworkManagerObserver* observer) {
   2153     if (!network_manager_observers_.HasObserver(observer))
   2154       network_manager_observers_.AddObserver(observer);
   2155   }
   2156 
   2157   virtual void RemoveNetworkManagerObserver(NetworkManagerObserver* observer) {
   2158     network_manager_observers_.RemoveObserver(observer);
   2159   }
   2160 
   2161   virtual void AddNetworkObserver(const std::string& service_path,
   2162                                   NetworkObserver* observer) {
   2163     DCHECK(observer);
   2164     if (!EnsureCrosLoaded())
   2165       return;
   2166     // First, add the observer to the callback map.
   2167     NetworkObserverMap::iterator iter = network_observers_.find(service_path);
   2168     NetworkObserverList* oblist;
   2169     if (iter != network_observers_.end()) {
   2170       oblist = iter->second;
   2171     } else {
   2172       oblist = new NetworkObserverList(this, service_path);
   2173       network_observers_[service_path] = oblist;
   2174     }
   2175     if (!oblist->HasObserver(observer))
   2176       oblist->AddObserver(observer);
   2177   }
   2178 
   2179   virtual void RemoveNetworkObserver(const std::string& service_path,
   2180                                      NetworkObserver* observer) {
   2181     DCHECK(observer);
   2182     DCHECK(service_path.size());
   2183     NetworkObserverMap::iterator map_iter =
   2184         network_observers_.find(service_path);
   2185     if (map_iter != network_observers_.end()) {
   2186       map_iter->second->RemoveObserver(observer);
   2187       if (!map_iter->second->size()) {
   2188         delete map_iter->second;
   2189         network_observers_.erase(map_iter);
   2190       }
   2191     }
   2192   }
   2193 
   2194   virtual void AddNetworkDeviceObserver(const std::string& device_path,
   2195                                         NetworkDeviceObserver* observer) {
   2196     DCHECK(observer);
   2197     if (!EnsureCrosLoaded())
   2198       return;
   2199     // First, add the observer to the callback map.
   2200     NetworkDeviceObserverMap::iterator iter =
   2201         network_device_observers_.find(device_path);
   2202     NetworkDeviceObserverList* oblist;
   2203     if (iter != network_device_observers_.end()) {
   2204       oblist = iter->second;
   2205       if (!oblist->HasObserver(observer))
   2206         oblist->AddObserver(observer);
   2207     } else {
   2208       LOG(WARNING) << "No NetworkDeviceObserverList found for "
   2209                    << device_path;
   2210     }
   2211   }
   2212 
   2213   virtual void RemoveNetworkDeviceObserver(const std::string& device_path,
   2214                                            NetworkDeviceObserver* observer) {
   2215     DCHECK(observer);
   2216     DCHECK(device_path.size());
   2217     NetworkDeviceObserverMap::iterator map_iter =
   2218         network_device_observers_.find(device_path);
   2219     if (map_iter != network_device_observers_.end()) {
   2220       map_iter->second->RemoveObserver(observer);
   2221     }
   2222   }
   2223 
   2224   virtual void RemoveObserverForAllNetworks(NetworkObserver* observer) {
   2225     DCHECK(observer);
   2226     NetworkObserverMap::iterator map_iter = network_observers_.begin();
   2227     while (map_iter != network_observers_.end()) {
   2228       map_iter->second->RemoveObserver(observer);
   2229       if (!map_iter->second->size()) {
   2230         delete map_iter->second;
   2231         network_observers_.erase(map_iter++);
   2232       } else {
   2233         ++map_iter;
   2234       }
   2235     }
   2236   }
   2237 
   2238   virtual void Lock() {
   2239     if (is_locked_)
   2240       return;
   2241     is_locked_ = true;
   2242     NotifyNetworkManagerChanged(true);  // Forced update.
   2243   }
   2244 
   2245   virtual void Unlock() {
   2246     DCHECK(is_locked_);
   2247     if (!is_locked_)
   2248       return;
   2249     is_locked_ = false;
   2250     NotifyNetworkManagerChanged(true);  // Forced update.
   2251   }
   2252 
   2253   virtual bool IsLocked() {
   2254     return is_locked_;
   2255   }
   2256 
   2257   virtual void AddCellularDataPlanObserver(CellularDataPlanObserver* observer) {
   2258     if (!data_plan_observers_.HasObserver(observer))
   2259       data_plan_observers_.AddObserver(observer);
   2260   }
   2261 
   2262   virtual void RemoveCellularDataPlanObserver(
   2263       CellularDataPlanObserver* observer) {
   2264     data_plan_observers_.RemoveObserver(observer);
   2265   }
   2266 
   2267   virtual void AddPinOperationObserver(PinOperationObserver* observer) {
   2268     if (!pin_operation_observers_.HasObserver(observer))
   2269       pin_operation_observers_.AddObserver(observer);
   2270   }
   2271 
   2272   virtual void RemovePinOperationObserver(PinOperationObserver* observer) {
   2273     pin_operation_observers_.RemoveObserver(observer);
   2274   }
   2275 
   2276   virtual void AddUserActionObserver(UserActionObserver* observer) {
   2277     if (!user_action_observers_.HasObserver(observer))
   2278       user_action_observers_.AddObserver(observer);
   2279   }
   2280 
   2281   virtual void RemoveUserActionObserver(UserActionObserver* observer) {
   2282     user_action_observers_.RemoveObserver(observer);
   2283   }
   2284 
   2285   virtual const EthernetNetwork* ethernet_network() const { return ethernet_; }
   2286   virtual bool ethernet_connecting() const {
   2287     return ethernet_ ? ethernet_->connecting() : false;
   2288   }
   2289   virtual bool ethernet_connected() const {
   2290     return ethernet_ ? ethernet_->connected() : false;
   2291   }
   2292 
   2293   virtual const WifiNetwork* wifi_network() const { return active_wifi_; }
   2294   virtual bool wifi_connecting() const {
   2295     return active_wifi_ ? active_wifi_->connecting() : false;
   2296   }
   2297   virtual bool wifi_connected() const {
   2298     return active_wifi_ ? active_wifi_->connected() : false;
   2299   }
   2300 
   2301   virtual const CellularNetwork* cellular_network() const {
   2302     return active_cellular_;
   2303   }
   2304   virtual bool cellular_connecting() const {
   2305     return active_cellular_ ? active_cellular_->connecting() : false;
   2306   }
   2307   virtual bool cellular_connected() const {
   2308     return active_cellular_ ? active_cellular_->connected() : false;
   2309   }
   2310   virtual const VirtualNetwork* virtual_network() const {
   2311     return active_virtual_;
   2312   }
   2313   virtual bool virtual_network_connecting() const {
   2314     return active_virtual_ ? active_virtual_->connecting() : false;
   2315   }
   2316   virtual bool virtual_network_connected() const {
   2317     return active_virtual_ ? active_virtual_->connected() : false;
   2318   }
   2319 
   2320   bool Connected() const {
   2321     return ethernet_connected() || wifi_connected() || cellular_connected();
   2322   }
   2323 
   2324   bool Connecting() const {
   2325     return ethernet_connecting() || wifi_connecting() || cellular_connecting();
   2326   }
   2327 
   2328   const std::string& IPAddress() const {
   2329     // Returns IP address for the active network.
   2330     // TODO(stevenjb): Fix this for VPNs. See chromium-os:13972.
   2331     const Network* result = active_network();
   2332     if (!result)
   2333       result = connected_network();  // happens if we are connected to a VPN.
   2334     if (!result)
   2335       result = ethernet_;  // Use non active ethernet addr if no active network.
   2336     if (result)
   2337       return result->ip_address();
   2338     static std::string null_address("0.0.0.0");
   2339     return null_address;
   2340   }
   2341 
   2342   virtual const WifiNetworkVector& wifi_networks() const {
   2343     return wifi_networks_;
   2344   }
   2345 
   2346   virtual const WifiNetworkVector& remembered_wifi_networks() const {
   2347     return remembered_wifi_networks_;
   2348   }
   2349 
   2350   virtual const CellularNetworkVector& cellular_networks() const {
   2351     return cellular_networks_;
   2352   }
   2353 
   2354   virtual const VirtualNetworkVector& virtual_networks() const {
   2355     return virtual_networks_;
   2356   }
   2357 
   2358   /////////////////////////////////////////////////////////////////////////////
   2359 
   2360   virtual const NetworkDevice* FindNetworkDeviceByPath(
   2361       const std::string& path) const {
   2362     NetworkDeviceMap::const_iterator iter = device_map_.find(path);
   2363     if (iter != device_map_.end())
   2364       return iter->second;
   2365     LOG(WARNING) << "Device path not found: " << path;
   2366     return NULL;
   2367   }
   2368 
   2369   virtual const NetworkDevice* FindCellularDevice() const {
   2370     for (NetworkDeviceMap::const_iterator iter = device_map_.begin();
   2371          iter != device_map_.end(); ++iter) {
   2372       if (iter->second->type() == TYPE_CELLULAR)
   2373         return iter->second;
   2374     }
   2375     return NULL;
   2376   }
   2377 
   2378   virtual const NetworkDevice* FindEthernetDevice() const {
   2379     for (NetworkDeviceMap::const_iterator iter = device_map_.begin();
   2380          iter != device_map_.end(); ++iter) {
   2381       if (iter->second->type() == TYPE_ETHERNET)
   2382         return iter->second;
   2383     }
   2384     return NULL;
   2385   }
   2386 
   2387   virtual const NetworkDevice* FindWifiDevice() const {
   2388     for (NetworkDeviceMap::const_iterator iter = device_map_.begin();
   2389          iter != device_map_.end(); ++iter) {
   2390       if (iter->second->type() == TYPE_WIFI)
   2391         return iter->second;
   2392     }
   2393     return NULL;
   2394   }
   2395 
   2396   virtual Network* FindNetworkByPath(const std::string& path) const {
   2397     NetworkMap::const_iterator iter = network_map_.find(path);
   2398     if (iter != network_map_.end())
   2399       return iter->second;
   2400     return NULL;
   2401   }
   2402 
   2403   WirelessNetwork* FindWirelessNetworkByPath(const std::string& path) const {
   2404     Network* network = FindNetworkByPath(path);
   2405     if (network &&
   2406         (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR))
   2407       return static_cast<WirelessNetwork*>(network);
   2408     return NULL;
   2409   }
   2410 
   2411   virtual WifiNetwork* FindWifiNetworkByPath(const std::string& path) const {
   2412     Network* network = FindNetworkByPath(path);
   2413     if (network && network->type() == TYPE_WIFI)
   2414       return static_cast<WifiNetwork*>(network);
   2415     return NULL;
   2416   }
   2417 
   2418   virtual CellularNetwork* FindCellularNetworkByPath(
   2419       const std::string& path) const {
   2420     Network* network = FindNetworkByPath(path);
   2421     if (network && network->type() == TYPE_CELLULAR)
   2422       return static_cast<CellularNetwork*>(network);
   2423     return NULL;
   2424   }
   2425 
   2426   virtual VirtualNetwork* FindVirtualNetworkByPath(
   2427       const std::string& path) const {
   2428     Network* network = FindNetworkByPath(path);
   2429     if (network && network->type() == TYPE_VPN)
   2430       return static_cast<VirtualNetwork*>(network);
   2431     return NULL;
   2432   }
   2433 
   2434   virtual Network* FindNetworkFromRemembered(
   2435       const Network* remembered) const {
   2436     NetworkMap::const_iterator found =
   2437         network_unique_id_map_.find(remembered->unique_id());
   2438     if (found != network_unique_id_map_.end())
   2439       return found->second;
   2440     return NULL;
   2441   }
   2442 
   2443   virtual const CellularDataPlanVector* GetDataPlans(
   2444       const std::string& path) const {
   2445     CellularDataPlanMap::const_iterator iter = data_plan_map_.find(path);
   2446     if (iter == data_plan_map_.end())
   2447       return NULL;
   2448     // If we need a new plan, then ignore any data plans we have.
   2449     CellularNetwork* cellular = FindCellularNetworkByPath(path);
   2450     if (cellular && cellular->needs_new_plan())
   2451       return NULL;
   2452     return iter->second;
   2453   }
   2454 
   2455   virtual const CellularDataPlan* GetSignificantDataPlan(
   2456       const std::string& path) const {
   2457     const CellularDataPlanVector* plans = GetDataPlans(path);
   2458     if (plans)
   2459       return GetSignificantDataPlanFromVector(plans);
   2460     return NULL;
   2461   }
   2462 
   2463   /////////////////////////////////////////////////////////////////////////////
   2464 
   2465   virtual void ChangePin(const std::string& old_pin,
   2466                          const std::string& new_pin) {
   2467     const NetworkDevice* cellular = FindCellularDevice();
   2468     if (!cellular) {
   2469       NOTREACHED() << "Calling ChangePin method w/o cellular device.";
   2470       return;
   2471     }
   2472     sim_operation_ = SIM_OPERATION_CHANGE_PIN;
   2473     chromeos::RequestChangePin(cellular->device_path().c_str(),
   2474                                old_pin.c_str(), new_pin.c_str(),
   2475                                PinOperationCallback, this);
   2476   }
   2477 
   2478   virtual void ChangeRequirePin(bool require_pin,
   2479                                 const std::string& pin) {
   2480     VLOG(1) << "ChangeRequirePin require_pin: " << require_pin
   2481             << " pin: " << pin;
   2482     const NetworkDevice* cellular = FindCellularDevice();
   2483     if (!cellular) {
   2484       NOTREACHED() << "Calling ChangeRequirePin method w/o cellular device.";
   2485       return;
   2486     }
   2487     sim_operation_ = SIM_OPERATION_CHANGE_REQUIRE_PIN;
   2488     chromeos::RequestRequirePin(cellular->device_path().c_str(),
   2489                                 pin.c_str(), require_pin,
   2490                                 PinOperationCallback, this);
   2491   }
   2492 
   2493   virtual void EnterPin(const std::string& pin) {
   2494     const NetworkDevice* cellular = FindCellularDevice();
   2495     if (!cellular) {
   2496       NOTREACHED() << "Calling EnterPin method w/o cellular device.";
   2497       return;
   2498     }
   2499     sim_operation_ = SIM_OPERATION_ENTER_PIN;
   2500     chromeos::RequestEnterPin(cellular->device_path().c_str(),
   2501                               pin.c_str(),
   2502                               PinOperationCallback, this);
   2503   }
   2504 
   2505   virtual void UnblockPin(const std::string& puk,
   2506                           const std::string& new_pin) {
   2507     const NetworkDevice* cellular = FindCellularDevice();
   2508     if (!cellular) {
   2509       NOTREACHED() << "Calling UnblockPin method w/o cellular device.";
   2510       return;
   2511     }
   2512     sim_operation_ = SIM_OPERATION_UNBLOCK_PIN;
   2513     chromeos::RequestUnblockPin(cellular->device_path().c_str(),
   2514                                 puk.c_str(), new_pin.c_str(),
   2515                                 PinOperationCallback, this);
   2516   }
   2517 
   2518   static void PinOperationCallback(void* object,
   2519                                    const char* path,
   2520                                    NetworkMethodErrorType error,
   2521                                    const char* error_message) {
   2522     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   2523     DCHECK(networklib);
   2524     PinOperationError pin_error;
   2525     VLOG(1) << "PinOperationCallback, error: " << error
   2526             << " error_msg: " << error_message;
   2527     if (error == chromeos::NETWORK_METHOD_ERROR_NONE) {
   2528       pin_error = PIN_ERROR_NONE;
   2529       VLOG(1) << "Pin operation completed successfuly";
   2530       // TODO(nkostylev): Might be cleaned up and exposed in flimflam API.
   2531       // http://crosbug.com/14253
   2532       // Since this option state is not exposed we have to update it manually.
   2533       networklib->FlipSimPinRequiredStateIfNeeded();
   2534     } else {
   2535       if (error_message &&
   2536             (strcmp(error_message, kErrorIncorrectPinMsg) == 0 ||
   2537              strcmp(error_message, kErrorPinRequiredMsg) == 0)) {
   2538         pin_error = PIN_ERROR_INCORRECT_CODE;
   2539       } else if (error_message &&
   2540                  strcmp(error_message, kErrorPinBlockedMsg) == 0) {
   2541         pin_error = PIN_ERROR_BLOCKED;
   2542       } else {
   2543         pin_error = PIN_ERROR_UNKNOWN;
   2544         NOTREACHED() << "Unknown PIN error: " << error_message;
   2545       }
   2546     }
   2547     networklib->NotifyPinOperationCompleted(pin_error);
   2548   }
   2549 
   2550   virtual void RequestCellularScan() {
   2551     const NetworkDevice* cellular = FindCellularDevice();
   2552     if (!cellular) {
   2553       NOTREACHED() << "Calling RequestCellularScan method w/o cellular device.";
   2554       return;
   2555     }
   2556     chromeos::ProposeScan(cellular->device_path().c_str());
   2557   }
   2558 
   2559   virtual void RequestCellularRegister(const std::string& network_id) {
   2560     const NetworkDevice* cellular = FindCellularDevice();
   2561     if (!cellular) {
   2562       NOTREACHED() << "Calling CellularRegister method w/o cellular device.";
   2563       return;
   2564     }
   2565     chromeos::RequestCellularRegister(cellular->device_path().c_str(),
   2566                                       network_id.c_str(),
   2567                                       CellularRegisterCallback,
   2568                                       this);
   2569   }
   2570 
   2571   static void CellularRegisterCallback(void* object,
   2572                                        const char* path,
   2573                                        NetworkMethodErrorType error,
   2574                                        const char* error_message) {
   2575     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   2576     DCHECK(networklib);
   2577     // TODO(dpolukhin): Notify observers about network registration status
   2578     // but not UI doesn't assume such notification so just ignore result.
   2579   }
   2580 
   2581   virtual void SetCellularDataRoamingAllowed(bool new_value) {
   2582     const NetworkDevice* cellular = FindCellularDevice();
   2583     if (!cellular) {
   2584       NOTREACHED() << "Calling SetCellularDataRoamingAllowed method "
   2585                       "w/o cellular device.";
   2586       return;
   2587     }
   2588     scoped_ptr<Value> value(Value::CreateBooleanValue(new_value));
   2589     chromeos::SetNetworkDeviceProperty(cellular->device_path().c_str(),
   2590                                        kCellularAllowRoamingProperty,
   2591                                        value.get());
   2592   }
   2593 
   2594   /////////////////////////////////////////////////////////////////////////////
   2595 
   2596   virtual void RequestNetworkScan() {
   2597     if (EnsureCrosLoaded()) {
   2598       if (wifi_enabled()) {
   2599         wifi_scanning_ = true;  // Cleared when updates are received.
   2600         chromeos::RequestNetworkScan(kTypeWifi);
   2601         RequestRememberedNetworksUpdate();
   2602       }
   2603       if (cellular_network())
   2604         cellular_network()->RefreshDataPlansIfNeeded();
   2605     }
   2606   }
   2607 
   2608   virtual bool GetWifiAccessPoints(WifiAccessPointVector* result) {
   2609     if (!EnsureCrosLoaded())
   2610       return false;
   2611     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   2612     DeviceNetworkList* network_list = GetDeviceNetworkList();
   2613     if (network_list == NULL)
   2614       return false;
   2615     result->clear();
   2616     result->reserve(network_list->network_size);
   2617     const base::Time now = base::Time::Now();
   2618     for (size_t i = 0; i < network_list->network_size; ++i) {
   2619       DCHECK(network_list->networks[i].address);
   2620       DCHECK(network_list->networks[i].name);
   2621       WifiAccessPoint ap;
   2622       ap.mac_address = SafeString(network_list->networks[i].address);
   2623       ap.name = SafeString(network_list->networks[i].name);
   2624       ap.timestamp = now -
   2625           base::TimeDelta::FromSeconds(network_list->networks[i].age_seconds);
   2626       ap.signal_strength = network_list->networks[i].strength;
   2627       ap.channel = network_list->networks[i].channel;
   2628       result->push_back(ap);
   2629     }
   2630     FreeDeviceNetworkList(network_list);
   2631     return true;
   2632   }
   2633 
   2634   static void NetworkConnectCallback(void *object,
   2635                                      const char *path,
   2636                                      NetworkMethodErrorType error,
   2637                                      const char* error_message) {
   2638     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   2639     DCHECK(networklib);
   2640 
   2641     Network* network = networklib->FindNetworkByPath(path);
   2642     if (!network) {
   2643       LOG(ERROR) << "No network for path: " << path;
   2644       return;
   2645     }
   2646 
   2647     if (error != NETWORK_METHOD_ERROR_NONE) {
   2648       LOG(WARNING) << "Error from ServiceConnect callback for: "
   2649                    << network->name()
   2650                    << " Error: " << error << " Message: " << error_message;
   2651       if (error_message &&
   2652           strcmp(error_message, kErrorPassphraseRequiredMsg) == 0) {
   2653         // This will trigger the connection failed notification.
   2654         // TODO(stevenjb): Remove if chromium-os:13203 gets fixed.
   2655         network->set_state(STATE_FAILURE);
   2656         network->set_error(ERROR_BAD_PASSPHRASE);
   2657         networklib->NotifyNetworkManagerChanged(true);  // Forced update.
   2658       }
   2659       return;
   2660     }
   2661 
   2662     VLOG(1) << "Connected to service: " << network->name();
   2663 
   2664     // Update local cache and notify listeners.
   2665     if (network->type() == TYPE_WIFI) {
   2666       WifiNetwork* wifi = static_cast<WifiNetwork *>(network);
   2667       // If the user asked not to save credentials, flimflam will have
   2668       // forgotten them.  Wipe our cache as well.
   2669       if (!wifi->save_credentials()) {
   2670         wifi->EraseCredentials();
   2671       }
   2672       networklib->active_wifi_ = wifi;
   2673     } else if (network->type() == TYPE_CELLULAR) {
   2674       networklib->active_cellular_ = static_cast<CellularNetwork *>(network);
   2675     } else if (network->type() == TYPE_VPN) {
   2676       networklib->active_virtual_ = static_cast<VirtualNetwork *>(network);
   2677     } else {
   2678       LOG(ERROR) << "Network of unexpected type: " << network->type();
   2679     }
   2680 
   2681     // If we succeed, this network will be remembered; request an update.
   2682     // TODO(stevenjb): flimflam should do this automatically.
   2683     networklib->RequestRememberedNetworksUpdate();
   2684     // Notify observers.
   2685     networklib->NotifyNetworkManagerChanged(true);  // Forced update.
   2686     networklib->NotifyUserConnectionInitiated(network);
   2687   }
   2688 
   2689 
   2690   void CallConnectToNetwork(Network* network) {
   2691     DCHECK(network);
   2692     if (!EnsureCrosLoaded() || !network)
   2693       return;
   2694     // In order to be certain to trigger any notifications, set the connecting
   2695     // state locally and notify observers. Otherwise there might be a state
   2696     // change without a forced notify.
   2697     network->set_connecting(true);
   2698     NotifyNetworkManagerChanged(true);  // Forced update.
   2699     RequestNetworkServiceConnect(network->service_path().c_str(),
   2700                                  NetworkConnectCallback, this);
   2701   }
   2702 
   2703   virtual void ConnectToWifiNetwork(WifiNetwork* wifi) {
   2704     // This will happen if a network resets or gets out of range.
   2705     if (wifi->user_passphrase_ != wifi->passphrase_ ||
   2706         wifi->passphrase_required())
   2707       wifi->SetPassphrase(wifi->user_passphrase_);
   2708     CallConnectToNetwork(wifi);
   2709   }
   2710 
   2711   // Use this to connect to a wifi network by service path.
   2712   virtual void ConnectToWifiNetwork(const std::string& service_path) {
   2713     WifiNetwork* wifi = FindWifiNetworkByPath(service_path);
   2714     if (!wifi) {
   2715       LOG(WARNING) << "Attempt to connect to non existing network: "
   2716                    << service_path;
   2717       return;
   2718     }
   2719     ConnectToWifiNetwork(wifi);
   2720   }
   2721 
   2722   // Use this to connect to an unlisted wifi network.
   2723   // This needs to request information about the named service.
   2724   // The connection attempt will occur in the callback.
   2725   virtual void ConnectToWifiNetwork(ConnectionSecurity security,
   2726                                     const std::string& ssid,
   2727                                     const std::string& passphrase,
   2728                                     const std::string& identity,
   2729                                     const std::string& certpath) {
   2730     if (!EnsureCrosLoaded())
   2731       return;
   2732     // Store the connection data to be used by the callback.
   2733     connect_data_.service_name = ssid;
   2734     connect_data_.passphrase = passphrase;
   2735     connect_data_.identity = identity;
   2736     connect_data_.cert_path = certpath;
   2737     // Asynchronously request service properties and call
   2738     // WifiServiceUpdateAndConnect.
   2739     RequestHiddenWifiNetwork(ssid.c_str(),
   2740                              SecurityToString(security),
   2741                              WifiServiceUpdateAndConnect,
   2742                              this);
   2743   }
   2744 
   2745   // Callback
   2746   static void WifiServiceUpdateAndConnect(void* object,
   2747                                           const char* service_path,
   2748                                           const Value* info) {
   2749     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   2750     DCHECK(networklib);
   2751     if (service_path && info) {
   2752       DCHECK_EQ(info->GetType(), Value::TYPE_DICTIONARY);
   2753       const DictionaryValue* dict = static_cast<const DictionaryValue*>(info);
   2754       Network* network =
   2755           networklib->ParseNetwork(std::string(service_path), dict);
   2756       DCHECK(network->type() == TYPE_WIFI);
   2757       networklib->ConnectToWifiNetworkUsingConnectData(
   2758           static_cast<WifiNetwork*>(network));
   2759     }
   2760   }
   2761 
   2762   void ConnectToWifiNetworkUsingConnectData(WifiNetwork* wifi) {
   2763     ConnectData& data = connect_data_;
   2764     if (wifi->name() != data.service_name) {
   2765       LOG(WARNING) << "Wifi network name does not match ConnectData: "
   2766                    << wifi->name() << " != " << data.service_name;
   2767       return;
   2768     }
   2769     wifi->set_added(true);
   2770     wifi->SetIdentity(data.identity);
   2771     wifi->SetPassphrase(data.passphrase);
   2772     if (!data.cert_path.empty())
   2773       wifi->SetCertPath(data.cert_path);
   2774 
   2775     ConnectToWifiNetwork(wifi);
   2776   }
   2777 
   2778   virtual void ConnectToCellularNetwork(CellularNetwork* cellular) {
   2779     CallConnectToNetwork(cellular);
   2780   }
   2781 
   2782   // Records information that cellular play payment had happened.
   2783   virtual void SignalCellularPlanPayment() {
   2784     DCHECK(!HasRecentCellularPlanPayment());
   2785     cellular_plan_payment_time_ = base::Time::Now();
   2786   }
   2787 
   2788   // Returns true if cellular plan payment had been recorded recently.
   2789   virtual bool HasRecentCellularPlanPayment() {
   2790     return (base::Time::Now() -
   2791             cellular_plan_payment_time_).InHours() < kRecentPlanPaymentHours;
   2792   }
   2793 
   2794   virtual void ConnectToVirtualNetwork(VirtualNetwork* vpn) {
   2795     CallConnectToNetwork(vpn);
   2796   }
   2797 
   2798   virtual void ConnectToVirtualNetworkPSK(
   2799       const std::string& service_name,
   2800       const std::string& server,
   2801       const std::string& psk,
   2802       const std::string& username,
   2803       const std::string& user_passphrase) {
   2804     if (!EnsureCrosLoaded())
   2805       return;
   2806     // Store the connection data to be used by the callback.
   2807     connect_data_.service_name = service_name;
   2808     connect_data_.psk_key = psk;
   2809     connect_data_.server_hostname = server;
   2810     connect_data_.identity = username;
   2811     connect_data_.passphrase = user_passphrase;
   2812     RequestVirtualNetwork(service_name.c_str(),
   2813                           server.c_str(),
   2814                           kProviderL2tpIpsec,
   2815                           VPNServiceUpdateAndConnect,
   2816                           this);
   2817   }
   2818 
   2819   // Callback
   2820   static void VPNServiceUpdateAndConnect(void* object,
   2821                                          const char* service_path,
   2822                                          const Value* info) {
   2823     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   2824     DCHECK(networklib);
   2825     if (service_path && info) {
   2826       VLOG(1) << "Connecting to new VPN Service: " << service_path;
   2827       DCHECK_EQ(info->GetType(), Value::TYPE_DICTIONARY);
   2828       const DictionaryValue* dict = static_cast<const DictionaryValue*>(info);
   2829       Network* network =
   2830           networklib->ParseNetwork(std::string(service_path), dict);
   2831       DCHECK(network->type() == TYPE_VPN);
   2832       networklib->ConnectToVirtualNetworkUsingConnectData(
   2833           static_cast<VirtualNetwork*>(network));
   2834     } else {
   2835       LOG(WARNING) << "Unable to create VPN Service: " << service_path;
   2836     }
   2837   }
   2838 
   2839   void ConnectToVirtualNetworkUsingConnectData(VirtualNetwork* vpn) {
   2840     ConnectData& data = connect_data_;
   2841     if (vpn->name() != data.service_name) {
   2842       LOG(WARNING) << "Virtual network name does not match ConnectData: "
   2843                    << vpn->name() << " != " << data.service_name;
   2844       return;
   2845     }
   2846 
   2847     vpn->set_added(true);
   2848     vpn->set_server_hostname(data.server_hostname);
   2849     vpn->SetCACert("");
   2850     vpn->SetUserCert("");
   2851     vpn->SetUserCertKey("");
   2852     vpn->SetPSKPassphrase(data.psk_key);
   2853     vpn->SetUsername(data.identity);
   2854     vpn->SetUserPassphrase(data.passphrase);
   2855 
   2856     CallConnectToNetwork(vpn);
   2857   }
   2858 
   2859   virtual void DisconnectFromNetwork(const Network* network) {
   2860     DCHECK(network);
   2861     if (!EnsureCrosLoaded() || !network)
   2862       return;
   2863     VLOG(1) << "Disconnect from network: " << network->service_path();
   2864     if (chromeos::DisconnectFromNetwork(network->service_path().c_str())) {
   2865       // Update local cache and notify listeners.
   2866       Network* found_network = FindNetworkByPath(network->service_path());
   2867       if (found_network) {
   2868         found_network->set_connected(false);
   2869         if (found_network == active_wifi_)
   2870           active_wifi_ = NULL;
   2871         else if (found_network == active_cellular_)
   2872           active_cellular_ = NULL;
   2873         else if (found_network == active_virtual_)
   2874           active_virtual_ = NULL;
   2875       }
   2876       NotifyNetworkManagerChanged(true);  // Forced update.
   2877     }
   2878   }
   2879 
   2880   virtual void ForgetWifiNetwork(const std::string& service_path) {
   2881     if (!EnsureCrosLoaded())
   2882       return;
   2883     DeleteRememberedService(service_path.c_str());
   2884     DeleteRememberedWifiNetwork(service_path);
   2885     NotifyNetworkManagerChanged(true);  // Forced update.
   2886   }
   2887 
   2888   virtual std::string GetCellularHomeCarrierId() const {
   2889     std::string carrier_id;
   2890     const NetworkDevice* cellular = FindCellularDevice();
   2891     if (cellular) {
   2892       return cellular->home_provider_id();
   2893 
   2894     }
   2895     return carrier_id;
   2896   }
   2897 
   2898   virtual bool ethernet_available() const {
   2899     return available_devices_ & (1 << TYPE_ETHERNET);
   2900   }
   2901   virtual bool wifi_available() const {
   2902     return available_devices_ & (1 << TYPE_WIFI);
   2903   }
   2904   virtual bool cellular_available() const {
   2905     return available_devices_ & (1 << TYPE_CELLULAR);
   2906   }
   2907 
   2908   virtual bool ethernet_enabled() const {
   2909     return enabled_devices_ & (1 << TYPE_ETHERNET);
   2910   }
   2911   virtual bool wifi_enabled() const {
   2912     return enabled_devices_ & (1 << TYPE_WIFI);
   2913   }
   2914   virtual bool cellular_enabled() const {
   2915     return enabled_devices_ & (1 << TYPE_CELLULAR);
   2916   }
   2917 
   2918   virtual bool wifi_scanning() const {
   2919     return wifi_scanning_;
   2920   }
   2921 
   2922   virtual bool offline_mode() const { return offline_mode_; }
   2923 
   2924   // Note: This does not include any virtual networks.
   2925   virtual const Network* active_network() const {
   2926     // Use flimflam's ordering of the services to determine what the active
   2927     // network is (i.e. don't assume priority of network types).
   2928     Network* result = NULL;
   2929     if (ethernet_ && ethernet_->is_active())
   2930       result = ethernet_;
   2931     if ((active_wifi_ && active_wifi_->is_active()) &&
   2932         (!result ||
   2933          active_wifi_->priority_order_ < result->priority_order_))
   2934       result = active_wifi_;
   2935     if ((active_cellular_ && active_cellular_->is_active()) &&
   2936         (!result ||
   2937          active_cellular_->priority_order_ < result->priority_order_))
   2938       result = active_cellular_;
   2939     return result;
   2940   }
   2941 
   2942   virtual const Network* connected_network() const {
   2943     // Use flimflam's ordering of the services to determine what the connected
   2944     // network is (i.e. don't assume priority of network types).
   2945     Network* result = NULL;
   2946     if (ethernet_ && ethernet_->connected())
   2947       result = ethernet_;
   2948     if ((active_wifi_ && active_wifi_->connected()) &&
   2949         (!result ||
   2950          active_wifi_->priority_order_ < result->priority_order_))
   2951       result = active_wifi_;
   2952     if ((active_cellular_ && active_cellular_->connected()) &&
   2953         (!result ||
   2954          active_cellular_->priority_order_ < result->priority_order_))
   2955       result = active_cellular_;
   2956     return result;
   2957   }
   2958 
   2959   virtual void EnableEthernetNetworkDevice(bool enable) {
   2960     if (is_locked_)
   2961       return;
   2962     EnableNetworkDeviceType(TYPE_ETHERNET, enable);
   2963   }
   2964 
   2965   virtual void EnableWifiNetworkDevice(bool enable) {
   2966     if (is_locked_)
   2967       return;
   2968     EnableNetworkDeviceType(TYPE_WIFI, enable);
   2969   }
   2970 
   2971   virtual void EnableCellularNetworkDevice(bool enable) {
   2972     if (is_locked_)
   2973       return;
   2974     EnableNetworkDeviceType(TYPE_CELLULAR, enable);
   2975   }
   2976 
   2977   virtual void EnableOfflineMode(bool enable) {
   2978     if (!EnsureCrosLoaded())
   2979       return;
   2980 
   2981     // If network device is already enabled/disabled, then don't do anything.
   2982     if (enable && offline_mode_) {
   2983       VLOG(1) << "Trying to enable offline mode when it's already enabled.";
   2984       return;
   2985     }
   2986     if (!enable && !offline_mode_) {
   2987       VLOG(1) << "Trying to disable offline mode when it's already disabled.";
   2988       return;
   2989     }
   2990 
   2991     if (SetOfflineMode(enable)) {
   2992       offline_mode_ = enable;
   2993     }
   2994   }
   2995 
   2996   virtual NetworkIPConfigVector GetIPConfigs(const std::string& device_path,
   2997                                              std::string* hardware_address,
   2998                                              HardwareAddressFormat format) {
   2999     DCHECK(hardware_address);
   3000     hardware_address->clear();
   3001     NetworkIPConfigVector ipconfig_vector;
   3002     if (EnsureCrosLoaded() && !device_path.empty()) {
   3003       IPConfigStatus* ipconfig_status = ListIPConfigs(device_path.c_str());
   3004       if (ipconfig_status) {
   3005         for (int i = 0; i < ipconfig_status->size; i++) {
   3006           IPConfig ipconfig = ipconfig_status->ips[i];
   3007           ipconfig_vector.push_back(
   3008               NetworkIPConfig(device_path, ipconfig.type, ipconfig.address,
   3009                               ipconfig.netmask, ipconfig.gateway,
   3010                               ipconfig.name_servers));
   3011         }
   3012         *hardware_address = ipconfig_status->hardware_address;
   3013         FreeIPConfigStatus(ipconfig_status);
   3014         // Sort the list of ip configs by type.
   3015         std::sort(ipconfig_vector.begin(), ipconfig_vector.end());
   3016       }
   3017     }
   3018 
   3019     for (size_t i = 0; i < hardware_address->size(); ++i)
   3020       (*hardware_address)[i] = toupper((*hardware_address)[i]);
   3021     if (format == FORMAT_COLON_SEPARATED_HEX) {
   3022       if (hardware_address->size() % 2 == 0) {
   3023         std::string output;
   3024         for (size_t i = 0; i < hardware_address->size(); ++i) {
   3025           if ((i != 0) && (i % 2 == 0))
   3026             output.push_back(':');
   3027           output.push_back((*hardware_address)[i]);
   3028         }
   3029         *hardware_address = output;
   3030       }
   3031     } else {
   3032       DCHECK(format == FORMAT_RAW_HEX);
   3033     }
   3034     return ipconfig_vector;
   3035   }
   3036 
   3037  private:
   3038 
   3039   typedef std::map<std::string, Network*> NetworkMap;
   3040   typedef std::map<std::string, int> PriorityMap;
   3041   typedef std::map<std::string, NetworkDevice*> NetworkDeviceMap;
   3042   typedef std::map<std::string, CellularDataPlanVector*> CellularDataPlanMap;
   3043 
   3044   class NetworkObserverList : public ObserverList<NetworkObserver> {
   3045    public:
   3046     NetworkObserverList(NetworkLibraryImpl* library,
   3047                         const std::string& service_path) {
   3048       network_monitor_ = MonitorNetworkService(&NetworkStatusChangedHandler,
   3049                                                service_path.c_str(),
   3050                                                library);
   3051     }
   3052 
   3053     virtual ~NetworkObserverList() {
   3054       if (network_monitor_)
   3055         DisconnectPropertyChangeMonitor(network_monitor_);
   3056     }
   3057 
   3058    private:
   3059     static void NetworkStatusChangedHandler(void* object,
   3060                                             const char* path,
   3061                                             const char* key,
   3062                                             const Value* value) {
   3063       NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3064       DCHECK(networklib);
   3065       networklib->UpdateNetworkStatus(path, key, value);
   3066     }
   3067     PropertyChangeMonitor network_monitor_;
   3068     DISALLOW_COPY_AND_ASSIGN(NetworkObserverList);
   3069   };
   3070 
   3071   typedef std::map<std::string, NetworkObserverList*> NetworkObserverMap;
   3072 
   3073   class NetworkDeviceObserverList : public ObserverList<NetworkDeviceObserver> {
   3074    public:
   3075     NetworkDeviceObserverList(NetworkLibraryImpl* library,
   3076                               const std::string& device_path) {
   3077       device_monitor_ = MonitorNetworkDevice(
   3078           &NetworkDevicePropertyChangedHandler,
   3079           device_path.c_str(),
   3080           library);
   3081     }
   3082 
   3083     virtual ~NetworkDeviceObserverList() {
   3084       if (device_monitor_)
   3085         DisconnectPropertyChangeMonitor(device_monitor_);
   3086     }
   3087 
   3088    private:
   3089     static void NetworkDevicePropertyChangedHandler(void* object,
   3090                                                     const char* path,
   3091                                                     const char* key,
   3092                                                     const Value* value) {
   3093       NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3094       DCHECK(networklib);
   3095       networklib->UpdateNetworkDeviceStatus(path, key, value);
   3096     }
   3097     PropertyChangeMonitor device_monitor_;
   3098     DISALLOW_COPY_AND_ASSIGN(NetworkDeviceObserverList);
   3099   };
   3100 
   3101   typedef std::map<std::string, NetworkDeviceObserverList*>
   3102       NetworkDeviceObserverMap;
   3103 
   3104   ////////////////////////////////////////////////////////////////////////////
   3105   // Callbacks.
   3106 
   3107   static void NetworkManagerStatusChangedHandler(void* object,
   3108                                                  const char* path,
   3109                                                  const char* key,
   3110                                                  const Value* value) {
   3111     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3112     DCHECK(networklib);
   3113     networklib->NetworkManagerStatusChanged(key, value);
   3114   }
   3115 
   3116   // This processes all Manager update messages.
   3117   void NetworkManagerStatusChanged(const char* key, const Value* value) {
   3118     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   3119     base::TimeTicks start = base::TimeTicks::Now();
   3120     VLOG(1) << "NetworkManagerStatusChanged: KEY=" << key;
   3121     if (!key)
   3122       return;
   3123     int index = property_index_parser().Get(std::string(key));
   3124     switch (index) {
   3125       case PROPERTY_INDEX_STATE:
   3126         // Currently we ignore the network manager state.
   3127         break;
   3128       case PROPERTY_INDEX_AVAILABLE_TECHNOLOGIES: {
   3129         DCHECK_EQ(value->GetType(), Value::TYPE_LIST);
   3130         const ListValue* vlist = static_cast<const ListValue*>(value);
   3131         UpdateAvailableTechnologies(vlist);
   3132         break;
   3133       }
   3134       case PROPERTY_INDEX_ENABLED_TECHNOLOGIES: {
   3135         DCHECK_EQ(value->GetType(), Value::TYPE_LIST);
   3136         const ListValue* vlist = static_cast<const ListValue*>(value);
   3137         UpdateEnabledTechnologies(vlist);
   3138         break;
   3139       }
   3140       case PROPERTY_INDEX_CONNECTED_TECHNOLOGIES: {
   3141         DCHECK_EQ(value->GetType(), Value::TYPE_LIST);
   3142         const ListValue* vlist = static_cast<const ListValue*>(value);
   3143         UpdateConnectedTechnologies(vlist);
   3144         break;
   3145       }
   3146       case PROPERTY_INDEX_DEFAULT_TECHNOLOGY:
   3147         // Currently we ignore DefaultTechnology.
   3148         break;
   3149       case PROPERTY_INDEX_OFFLINE_MODE: {
   3150         DCHECK_EQ(value->GetType(), Value::TYPE_BOOLEAN);
   3151         value->GetAsBoolean(&offline_mode_);
   3152         NotifyNetworkManagerChanged(false);  // Not forced.
   3153         break;
   3154       }
   3155       case PROPERTY_INDEX_ACTIVE_PROFILE: {
   3156         DCHECK_EQ(value->GetType(), Value::TYPE_STRING);
   3157         value->GetAsString(&active_profile_path_);
   3158         RequestRememberedNetworksUpdate();
   3159         break;
   3160       }
   3161       case PROPERTY_INDEX_PROFILES:
   3162         // Currently we ignore Profiles (list of all profiles).
   3163         break;
   3164       case PROPERTY_INDEX_SERVICES: {
   3165         DCHECK_EQ(value->GetType(), Value::TYPE_LIST);
   3166         const ListValue* vlist = static_cast<const ListValue*>(value);
   3167         UpdateNetworkServiceList(vlist);
   3168         break;
   3169       }
   3170       case PROPERTY_INDEX_SERVICE_WATCH_LIST: {
   3171         DCHECK_EQ(value->GetType(), Value::TYPE_LIST);
   3172         const ListValue* vlist = static_cast<const ListValue*>(value);
   3173         UpdateWatchedNetworkServiceList(vlist);
   3174         break;
   3175       }
   3176       case PROPERTY_INDEX_DEVICE:
   3177       case PROPERTY_INDEX_DEVICES: {
   3178         DCHECK_EQ(value->GetType(), Value::TYPE_LIST);
   3179         const ListValue* vlist = static_cast<const ListValue*>(value);
   3180         UpdateNetworkDeviceList(vlist);
   3181         break;
   3182       }
   3183       default:
   3184         LOG(WARNING) << "Unhandled key: " << key;
   3185         break;
   3186     }
   3187     base::TimeDelta delta = base::TimeTicks::Now() - start;
   3188     VLOG(1) << "  time: " << delta.InMilliseconds() << " ms.";
   3189     HISTOGRAM_TIMES("CROS_NETWORK_UPDATE", delta);
   3190   }
   3191 
   3192   static void NetworkManagerUpdate(void* object,
   3193                                    const char* manager_path,
   3194                                    const Value* info) {
   3195     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3196     DCHECK(networklib);
   3197     if (!info) {
   3198       LOG(ERROR) << "Error retrieving manager properties: " << manager_path;
   3199       return;
   3200     }
   3201     VLOG(1) << "Received NetworkManagerUpdate.";
   3202     DCHECK_EQ(info->GetType(), Value::TYPE_DICTIONARY);
   3203     const DictionaryValue* dict = static_cast<const DictionaryValue*>(info);
   3204     networklib->ParseNetworkManager(dict);
   3205   }
   3206 
   3207   void ParseNetworkManager(const DictionaryValue* dict) {
   3208     for (DictionaryValue::key_iterator iter = dict->begin_keys();
   3209          iter != dict->end_keys(); ++iter) {
   3210       const std::string& key = *iter;
   3211       Value* value;
   3212       bool res = dict->GetWithoutPathExpansion(key, &value);
   3213       CHECK(res);
   3214       NetworkManagerStatusChanged(key.c_str(), value);
   3215     }
   3216   }
   3217 
   3218   static void ProfileUpdate(void* object,
   3219                             const char* profile_path,
   3220                             const Value* info) {
   3221     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3222     DCHECK(networklib);
   3223     if (!info) {
   3224       LOG(ERROR) << "Error retrieving profile: " << profile_path;
   3225       return;
   3226     }
   3227     VLOG(1) << "Received ProfileUpdate for: " << profile_path;
   3228     DCHECK_EQ(info->GetType(), Value::TYPE_DICTIONARY);
   3229     const DictionaryValue* dict = static_cast<const DictionaryValue*>(info);
   3230     ListValue* entries(NULL);
   3231     dict->GetList(kEntriesProperty, &entries);
   3232     DCHECK(entries);
   3233     networklib->UpdateRememberedServiceList(profile_path, entries);
   3234   }
   3235 
   3236   static void NetworkServiceUpdate(void* object,
   3237                                    const char* service_path,
   3238                                    const Value* info) {
   3239     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3240     DCHECK(networklib);
   3241     if (service_path) {
   3242       if (!info) {
   3243         // Network no longer exists.
   3244         networklib->DeleteNetwork(std::string(service_path));
   3245       } else {
   3246         DCHECK_EQ(info->GetType(), Value::TYPE_DICTIONARY);
   3247         const DictionaryValue* dict = static_cast<const DictionaryValue*>(info);
   3248         networklib->ParseNetwork(std::string(service_path), dict);
   3249       }
   3250     }
   3251   }
   3252 
   3253   static void RememberedNetworkServiceUpdate(void* object,
   3254                                              const char* service_path,
   3255                                              const Value* info) {
   3256     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3257     DCHECK(networklib);
   3258     if (service_path) {
   3259       if (!info) {
   3260         // Remembered network no longer exists.
   3261         networklib->DeleteRememberedWifiNetwork(std::string(service_path));
   3262       } else {
   3263         DCHECK_EQ(info->GetType(), Value::TYPE_DICTIONARY);
   3264         const DictionaryValue* dict = static_cast<const DictionaryValue*>(info);
   3265         networklib->ParseRememberedNetwork(std::string(service_path), dict);
   3266       }
   3267     }
   3268   }
   3269 
   3270   static void NetworkDeviceUpdate(void* object,
   3271                                   const char* device_path,
   3272                                   const Value* info) {
   3273     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3274     DCHECK(networklib);
   3275     if (device_path) {
   3276       if (!info) {
   3277         // device no longer exists.
   3278         networklib->DeleteDevice(std::string(device_path));
   3279       } else {
   3280         DCHECK_EQ(info->GetType(), Value::TYPE_DICTIONARY);
   3281         const DictionaryValue* dict = static_cast<const DictionaryValue*>(info);
   3282         networklib->ParseNetworkDevice(std::string(device_path), dict);
   3283       }
   3284     }
   3285   }
   3286 
   3287   static void DataPlanUpdateHandler(void* object,
   3288                                     const char* modem_service_path,
   3289                                     const CellularDataPlanList* dataplan) {
   3290     NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
   3291     DCHECK(networklib);
   3292     if (modem_service_path && dataplan) {
   3293       networklib->UpdateCellularDataPlan(std::string(modem_service_path),
   3294                                          dataplan);
   3295     }
   3296   }
   3297 
   3298   ////////////////////////////////////////////////////////////////////////////
   3299   // Network technology functions.
   3300 
   3301   void UpdateTechnologies(const ListValue* technologies, int* bitfieldp) {
   3302     DCHECK(bitfieldp);
   3303     if (!technologies)
   3304       return;
   3305     int bitfield = 0;
   3306     for (ListValue::const_iterator iter = technologies->begin();
   3307          iter != technologies->end(); ++iter) {
   3308       std::string technology;
   3309       (*iter)->GetAsString(&technology);
   3310       if (!technology.empty()) {
   3311         ConnectionType type = ParseType(technology);
   3312         bitfield |= 1 << type;
   3313       }
   3314     }
   3315     *bitfieldp = bitfield;
   3316     NotifyNetworkManagerChanged(false);  // Not forced.
   3317   }
   3318 
   3319   void UpdateAvailableTechnologies(const ListValue* technologies) {
   3320     UpdateTechnologies(technologies, &available_devices_);
   3321   }
   3322 
   3323   void UpdateEnabledTechnologies(const ListValue* technologies) {
   3324     UpdateTechnologies(technologies, &enabled_devices_);
   3325     if (!ethernet_enabled())
   3326       ethernet_ = NULL;
   3327     if (!wifi_enabled()) {
   3328       active_wifi_ = NULL;
   3329       wifi_networks_.clear();
   3330     }
   3331     if (!cellular_enabled()) {
   3332       active_cellular_ = NULL;
   3333       cellular_networks_.clear();
   3334     }
   3335   }
   3336 
   3337   void UpdateConnectedTechnologies(const ListValue* technologies) {
   3338     UpdateTechnologies(technologies, &connected_devices_);
   3339   }
   3340 
   3341   ////////////////////////////////////////////////////////////////////////////
   3342   // Network list management functions.
   3343 
   3344   // Note: sometimes flimflam still returns networks when the device type is
   3345   // disabled. Always check the appropriate enabled() state before adding
   3346   // networks to a list or setting an active network so that we do not show them
   3347   // in the UI.
   3348 
   3349   // This relies on services being requested from flimflam in priority order,
   3350   // and the updates getting processed and received in order.
   3351   void UpdateActiveNetwork(Network* network) {
   3352     ConnectionType type(network->type());
   3353     if (type == TYPE_ETHERNET) {
   3354       if (ethernet_enabled()) {
   3355         // Set ethernet_ to the first connected ethernet service, or the first
   3356         // disconnected ethernet service if none are connected.
   3357         if (ethernet_ == NULL || !ethernet_->connected())
   3358           ethernet_ = static_cast<EthernetNetwork*>(network);
   3359       }
   3360     } else if (type == TYPE_WIFI) {
   3361       if (wifi_enabled()) {
   3362         // Set active_wifi_ to the first connected or connecting wifi service.
   3363         if (active_wifi_ == NULL && network->connecting_or_connected())
   3364           active_wifi_ = static_cast<WifiNetwork*>(network);
   3365       }
   3366     } else if (type == TYPE_CELLULAR) {
   3367       if (cellular_enabled()) {
   3368         // Set active_cellular_ to first connected/connecting celluar service.
   3369         if (active_cellular_ == NULL && network->connecting_or_connected())
   3370           active_cellular_ = static_cast<CellularNetwork*>(network);
   3371       }
   3372     } else if (type == TYPE_VPN) {
   3373       // Set active_virtual_ to the first connected or connecting vpn service.
   3374       if (active_virtual_ == NULL && network->connecting_or_connected())
   3375         active_virtual_ = static_cast<VirtualNetwork*>(network);
   3376     }
   3377   }
   3378 
   3379   void AddNetwork(Network* network) {
   3380     std::pair<NetworkMap::iterator,bool> result =
   3381         network_map_.insert(std::make_pair(network->service_path(), network));
   3382     DCHECK(result.second);  // Should only get called with new network.
   3383     VLOG(2) << "Adding Network: " << network->service_path()
   3384             << " (" << network->name() << ")";
   3385     ConnectionType type(network->type());
   3386     if (type == TYPE_WIFI) {
   3387       if (wifi_enabled())
   3388         wifi_networks_.push_back(static_cast<WifiNetwork*>(network));
   3389     } else if (type == TYPE_CELLULAR) {
   3390       if (cellular_enabled())
   3391         cellular_networks_.push_back(static_cast<CellularNetwork*>(network));
   3392     } else if (type == TYPE_VPN) {
   3393       virtual_networks_.push_back(static_cast<VirtualNetwork*>(network));
   3394     }
   3395     // Do not set the active network here. Wait until we parse the network.
   3396   }
   3397 
   3398   // This only gets called when NetworkServiceUpdate receives a NULL update
   3399   // for an existing network, e.g. an error occurred while fetching a network.
   3400   void DeleteNetwork(const std::string& service_path) {
   3401     NetworkMap::iterator found = network_map_.find(service_path);
   3402     if (found == network_map_.end()) {
   3403       // This occurs when we receive an update request followed by a disconnect
   3404       // which triggers another update. See UpdateNetworkServiceList.
   3405       return;
   3406     }
   3407     Network* network = found->second;
   3408     network_map_.erase(found);
   3409     if (!network->unique_id().empty())
   3410       network_unique_id_map_.erase(network->unique_id());
   3411     ConnectionType type(network->type());
   3412     if (type == TYPE_ETHERNET) {
   3413       if (network == ethernet_) {
   3414         // This should never happen.
   3415         LOG(ERROR) << "Deleting active ethernet network: " << service_path;
   3416         ethernet_ = NULL;
   3417       }
   3418     } else if (type == TYPE_WIFI) {
   3419       WifiNetworkVector::iterator iter = std::find(
   3420           wifi_networks_.begin(), wifi_networks_.end(), network);
   3421       if (iter != wifi_networks_.end())
   3422         wifi_networks_.erase(iter);
   3423       if (network == active_wifi_) {
   3424         // This should never happen.
   3425         LOG(ERROR) << "Deleting active wifi network: " << service_path;
   3426         active_wifi_ = NULL;
   3427       }
   3428     } else if (type == TYPE_CELLULAR) {
   3429       CellularNetworkVector::iterator iter = std::find(
   3430           cellular_networks_.begin(), cellular_networks_.end(), network);
   3431       if (iter != cellular_networks_.end())
   3432         cellular_networks_.erase(iter);
   3433       if (network == active_cellular_) {
   3434         // This should never happen.
   3435         LOG(ERROR) << "Deleting active cellular network: " << service_path;
   3436         active_cellular_ = NULL;
   3437       }
   3438       // Find and delete any existing data plans associated with |service_path|.
   3439       CellularDataPlanMap::iterator found =  data_plan_map_.find(service_path);
   3440       if (found != data_plan_map_.end()) {
   3441         CellularDataPlanVector* data_plans = found->second;
   3442         delete data_plans;
   3443         data_plan_map_.erase(found);
   3444       }
   3445     } else if (type == TYPE_VPN) {
   3446       VirtualNetworkVector::iterator iter = std::find(
   3447           virtual_networks_.begin(), virtual_networks_.end(), network);
   3448       if (iter != virtual_networks_.end())
   3449         virtual_networks_.erase(iter);
   3450       if (network == active_virtual_) {
   3451         // This should never happen.
   3452         LOG(ERROR) << "Deleting active virtual network: " << service_path;
   3453         active_virtual_ = NULL;
   3454       }
   3455     }
   3456     delete network;
   3457   }
   3458 
   3459   void AddRememberedWifiNetwork(WifiNetwork* wifi) {
   3460     std::pair<NetworkMap::iterator,bool> result =
   3461         remembered_network_map_.insert(
   3462             std::make_pair(wifi->service_path(), wifi));
   3463     DCHECK(result.second);  // Should only get called with new network.
   3464     remembered_wifi_networks_.push_back(wifi);
   3465   }
   3466 
   3467   void DeleteRememberedWifiNetwork(const std::string& service_path) {
   3468     NetworkMap::iterator found = remembered_network_map_.find(service_path);
   3469     if (found == remembered_network_map_.end()) {
   3470       LOG(WARNING) << "Attempt to delete non-existant remembered network: "
   3471                    << service_path;
   3472       return;
   3473     }
   3474     Network* remembered_network = found->second;
   3475     remembered_network_map_.erase(found);
   3476     WifiNetworkVector::iterator iter = std::find(
   3477         remembered_wifi_networks_.begin(), remembered_wifi_networks_.end(),
   3478         remembered_network);
   3479     if (iter != remembered_wifi_networks_.end())
   3480       remembered_wifi_networks_.erase(iter);
   3481     Network* network = FindNetworkFromRemembered(remembered_network);
   3482     if (network && network->type() == TYPE_WIFI) {
   3483       // Clear the stored credentials for any visible forgotten networks.
   3484       WifiNetwork* wifi = static_cast<WifiNetwork*>(network);
   3485       wifi->EraseCredentials();
   3486     } else {
   3487       // Network is not in visible list.
   3488       VLOG(2) << "Remembered Network not found: "
   3489               << remembered_network->unique_id();
   3490     }
   3491     delete remembered_network;
   3492   }
   3493 
   3494   // Update all network lists, and request associated service updates.
   3495   void UpdateNetworkServiceList(const ListValue* services) {
   3496     // TODO(stevenjb): Wait for wifi_scanning_ to be false.
   3497     // Copy the list of existing networks to "old" and clear the map and lists.
   3498     NetworkMap old_network_map = network_map_;
   3499     ClearNetworks(false /*don't delete*/);
   3500     // Clear the list of update requests.
   3501     int network_priority_order = 0;
   3502     network_update_requests_.clear();
   3503     // wifi_scanning_ will remain false unless we request a network update.
   3504     wifi_scanning_ = false;
   3505     // |services| represents a complete list of visible networks.
   3506     for (ListValue::const_iterator iter = services->begin();
   3507          iter != services->end(); ++iter) {
   3508       std::string service_path;
   3509       (*iter)->GetAsString(&service_path);
   3510       if (!service_path.empty()) {
   3511         // If we find the network in "old", add it immediately to the map
   3512         // and lists. Otherwise it will get added when NetworkServiceUpdate
   3513         // calls ParseNetwork.
   3514         NetworkMap::iterator found = old_network_map.find(service_path);
   3515         if (found != old_network_map.end()) {
   3516           AddNetwork(found->second);
   3517           old_network_map.erase(found);
   3518         }
   3519         // Always request network updates.
   3520         // TODO(stevenjb): Investigate why we are missing updates then
   3521         // rely on watched network updates and only request updates here for
   3522         // new networks.
   3523         // Use update_request map to store network priority.
   3524         network_update_requests_[service_path] = network_priority_order++;
   3525         wifi_scanning_ = true;
   3526         RequestNetworkServiceInfo(service_path.c_str(),
   3527                                   &NetworkServiceUpdate,
   3528                                   this);
   3529       }
   3530     }
   3531     // Delete any old networks that no longer exist.
   3532     for (NetworkMap::iterator iter = old_network_map.begin();
   3533          iter != old_network_map.end(); ++iter) {
   3534       delete iter->second;
   3535     }
   3536   }
   3537 
   3538   // Request updates for watched networks. Does not affect network lists.
   3539   // Existing networks will be updated. There should not be any new networks
   3540   // in this list, but if there are they will be added appropriately.
   3541   void UpdateWatchedNetworkServiceList(const ListValue* services) {
   3542     for (ListValue::const_iterator iter = services->begin();
   3543          iter != services->end(); ++iter) {
   3544       std::string service_path;
   3545       (*iter)->GetAsString(&service_path);
   3546       if (!service_path.empty()) {
   3547         VLOG(1) << "Watched Service: " << service_path;
   3548         RequestNetworkServiceInfo(
   3549             service_path.c_str(), &NetworkServiceUpdate, this);
   3550       }
   3551     }
   3552   }
   3553 
   3554   // Request the active profile which lists the remembered networks.
   3555   void RequestRememberedNetworksUpdate() {
   3556     if (!active_profile_path_.empty()) {
   3557       RequestNetworkProfile(
   3558           active_profile_path_.c_str(), &ProfileUpdate, this);
   3559     }
   3560   }
   3561 
   3562   // Update the list of remembered (profile) networks, and request associated
   3563   // service updates.
   3564   void UpdateRememberedServiceList(const char* profile_path,
   3565                                    const ListValue* profile_entries) {
   3566     // Copy the list of existing networks to "old" and clear the map and list.
   3567     NetworkMap old_network_map = remembered_network_map_;
   3568     ClearRememberedNetworks(false /*don't delete*/);
   3569     // |profile_entries| represents a complete list of remembered networks.
   3570     for (ListValue::const_iterator iter = profile_entries->begin();
   3571          iter != profile_entries->end(); ++iter) {
   3572       std::string service_path;
   3573       (*iter)->GetAsString(&service_path);
   3574       if (!service_path.empty()) {
   3575         // If we find the network in "old", add it immediately to the map
   3576         // and list. Otherwise it will get added when
   3577         // RememberedNetworkServiceUpdate calls ParseRememberedNetwork.
   3578         NetworkMap::iterator found = old_network_map.find(service_path);
   3579         if (found != old_network_map.end()) {
   3580           Network* network = found->second;
   3581           if (network->type() == TYPE_WIFI) {
   3582             WifiNetwork* wifi = static_cast<WifiNetwork*>(network);
   3583             AddRememberedWifiNetwork(wifi);
   3584             old_network_map.erase(found);
   3585           }
   3586         }
   3587         // Always request updates for remembered networks.
   3588         RequestNetworkProfileEntry(profile_path,
   3589                                    service_path.c_str(),
   3590                                    &RememberedNetworkServiceUpdate,
   3591                                    this);
   3592       }
   3593     }
   3594     // Delete any old networks that no longer exist.
   3595     for (NetworkMap::iterator iter = old_network_map.begin();
   3596          iter != old_network_map.end(); ++iter) {
   3597       delete iter->second;
   3598     }
   3599   }
   3600 
   3601   Network* CreateNewNetwork(ConnectionType type,
   3602                             const std::string& service_path) {
   3603     switch (type) {
   3604       case TYPE_ETHERNET: {
   3605         EthernetNetwork* ethernet = new EthernetNetwork(service_path);
   3606         return ethernet;
   3607       }
   3608       case TYPE_WIFI: {
   3609         WifiNetwork* wifi = new WifiNetwork(service_path);
   3610         return wifi;
   3611       }
   3612       case TYPE_CELLULAR: {
   3613         CellularNetwork* cellular = new CellularNetwork(service_path);
   3614         return cellular;
   3615       }
   3616       case TYPE_VPN: {
   3617         VirtualNetwork* vpn = new VirtualNetwork(service_path);
   3618         return vpn;
   3619       }
   3620       default: {
   3621         LOG(WARNING) << "Unknown service type: " << type;
   3622         return new Network(service_path, type);
   3623       }
   3624     }
   3625   }
   3626 
   3627   Network* ParseNetwork(const std::string& service_path,
   3628                         const DictionaryValue* info) {
   3629     Network* network = FindNetworkByPath(service_path);
   3630     if (!network) {
   3631       ConnectionType type = ParseTypeFromDictionary(info);
   3632       network = CreateNewNetwork(type, service_path);
   3633       AddNetwork(network);
   3634     }
   3635 
   3636     // Erase entry from network_unique_id_map_ in case unique id changes.
   3637     if (!network->unique_id().empty())
   3638       network_unique_id_map_.erase(network->unique_id());
   3639 
   3640     network->ParseInfo(info);  // virtual.
   3641 
   3642     if (!network->unique_id().empty())
   3643       network_unique_id_map_[network->unique_id()] = network;
   3644 
   3645     UpdateActiveNetwork(network);
   3646 
   3647     // Find and erase entry in update_requests, and set network priority.
   3648     PriorityMap::iterator found2 = network_update_requests_.find(service_path);
   3649     if (found2 != network_update_requests_.end()) {
   3650       network->priority_order_ = found2->second;
   3651       network_update_requests_.erase(found2);
   3652       if (network_update_requests_.empty()) {
   3653         // Clear wifi_scanning_ when we have no pending requests.
   3654         wifi_scanning_ = false;
   3655       }
   3656     } else {
   3657       // TODO(stevenjb): Enable warning once UpdateNetworkServiceList is fixed.
   3658       // LOG(WARNING) << "ParseNetwork called with no update request entry: "
   3659       //              << service_path;
   3660     }
   3661 
   3662     VLOG(1) << "ParseNetwork: " << network->name();
   3663     NotifyNetworkManagerChanged(false);  // Not forced.
   3664     return network;
   3665   }
   3666 
   3667   // Returns NULL if |service_path| refers to a network that is not a
   3668   // remembered type.
   3669   Network* ParseRememberedNetwork(const std::string& service_path,
   3670                                   const DictionaryValue* info) {
   3671     Network* network;
   3672     NetworkMap::iterator found = remembered_network_map_.find(service_path);
   3673     if (found != remembered_network_map_.end()) {
   3674       network = found->second;
   3675     } else {
   3676       ConnectionType type = ParseTypeFromDictionary(info);
   3677       if (type == TYPE_WIFI) {
   3678         network = CreateNewNetwork(type, service_path);
   3679         WifiNetwork* wifi = static_cast<WifiNetwork*>(network);
   3680         AddRememberedWifiNetwork(wifi);
   3681       } else {
   3682         VLOG(1) << "Ignoring remembered network: " << service_path
   3683                 << " Type: " << ConnectionTypeToString(type);
   3684         return NULL;
   3685       }
   3686     }
   3687     network->ParseInfo(info);  // virtual.
   3688     VLOG(1) << "ParseRememberedNetwork: " << network->name();
   3689     NotifyNetworkManagerChanged(false);  // Not forced.
   3690     return network;
   3691   }
   3692 
   3693   void ClearNetworks(bool delete_networks) {
   3694     if (delete_networks)
   3695       STLDeleteValues(&network_map_);
   3696     network_map_.clear();
   3697     network_unique_id_map_.clear();
   3698     ethernet_ = NULL;
   3699     active_wifi_ = NULL;
   3700     active_cellular_ = NULL;
   3701     active_virtual_ = NULL;
   3702     wifi_networks_.clear();
   3703     cellular_networks_.clear();
   3704     virtual_networks_.clear();
   3705   }
   3706 
   3707   void ClearRememberedNetworks(bool delete_networks) {
   3708     if (delete_networks)
   3709       STLDeleteValues(&remembered_network_map_);
   3710     remembered_network_map_.clear();
   3711     remembered_wifi_networks_.clear();
   3712   }
   3713 
   3714   ////////////////////////////////////////////////////////////////////////////
   3715   // NetworkDevice list management functions.
   3716 
   3717   // Returns pointer to device or NULL if device is not found by path.
   3718   // Use FindNetworkDeviceByPath when you're not intending to change device.
   3719   NetworkDevice* GetNetworkDeviceByPath(const std::string& path) {
   3720     NetworkDeviceMap::iterator iter = device_map_.find(path);
   3721     if (iter != device_map_.end())
   3722       return iter->second;
   3723     LOG(WARNING) << "Device path not found: " << path;
   3724     return NULL;
   3725   }
   3726 
   3727   // Update device list, and request associated device updates.
   3728   // |devices| represents a complete list of devices.
   3729   void UpdateNetworkDeviceList(const ListValue* devices) {
   3730     NetworkDeviceMap old_device_map = device_map_;
   3731     device_map_.clear();
   3732     VLOG(2) << "Updating Device List.";
   3733     for (ListValue::const_iterator iter = devices->begin();
   3734          iter != devices->end(); ++iter) {
   3735       std::string device_path;
   3736       (*iter)->GetAsString(&device_path);
   3737       if (!device_path.empty()) {
   3738         NetworkDeviceMap::iterator found = old_device_map.find(device_path);
   3739         if (found != old_device_map.end()) {
   3740           VLOG(2) << " Adding existing device: " << device_path;
   3741           device_map_[device_path] = found->second;
   3742           old_device_map.erase(found);
   3743         }
   3744         RequestNetworkDeviceInfo(
   3745             device_path.c_str(), &NetworkDeviceUpdate, this);
   3746       }
   3747     }
   3748     // Delete any old devices that no longer exist.
   3749     for (NetworkDeviceMap::iterator iter = old_device_map.begin();
   3750          iter != old_device_map.end(); ++iter) {
   3751       DeleteDeviceFromDeviceObserversMap(iter->first);
   3752       // Delete device.
   3753       delete iter->second;
   3754     }
   3755   }
   3756 
   3757   void DeleteDeviceFromDeviceObserversMap(const std::string& device_path) {
   3758     // Delete all device observers associated with this device.
   3759     NetworkDeviceObserverMap::iterator map_iter =
   3760         network_device_observers_.find(device_path);
   3761     if (map_iter != network_device_observers_.end()) {
   3762       delete map_iter->second;
   3763       network_device_observers_.erase(map_iter);
   3764     }
   3765   }
   3766 
   3767   void DeleteDevice(const std::string& device_path) {
   3768     NetworkDeviceMap::iterator found = device_map_.find(device_path);
   3769     if (found == device_map_.end()) {
   3770       LOG(WARNING) << "Attempt to delete non-existant device: "
   3771                    << device_path;
   3772       return;
   3773     }
   3774     VLOG(2) << " Deleting device: " << device_path;
   3775     NetworkDevice* device = found->second;
   3776     device_map_.erase(found);
   3777     DeleteDeviceFromDeviceObserversMap(device_path);
   3778     delete device;
   3779   }
   3780 
   3781   void ParseNetworkDevice(const std::string& device_path,
   3782                           const DictionaryValue* info) {
   3783     NetworkDeviceMap::iterator found = device_map_.find(device_path);
   3784     NetworkDevice* device;
   3785     if (found != device_map_.end()) {
   3786       device = found->second;
   3787     } else {
   3788       device = new NetworkDevice(device_path);
   3789       VLOG(2) << " Adding device: " << device_path;
   3790       device_map_[device_path] = device;
   3791       if (network_device_observers_.find(device_path) ==
   3792           network_device_observers_.end()) {
   3793         network_device_observers_[device_path] =
   3794             new NetworkDeviceObserverList(this, device_path);
   3795       }
   3796     }
   3797     device->ParseInfo(info);
   3798     VLOG(1) << "ParseNetworkDevice:" << device->name();
   3799     NotifyNetworkManagerChanged(false);  // Not forced.
   3800   }
   3801 
   3802   ////////////////////////////////////////////////////////////////////////////
   3803 
   3804   void EnableNetworkDeviceType(ConnectionType device, bool enable) {
   3805     if (!EnsureCrosLoaded())
   3806       return;
   3807 
   3808     // If network device is already enabled/disabled, then don't do anything.
   3809     if (enable && (enabled_devices_ & (1 << device))) {
   3810       LOG(WARNING) << "Trying to enable a device that's already enabled: "
   3811                    << device;
   3812       return;
   3813     }
   3814     if (!enable && !(enabled_devices_ & (1 << device))) {
   3815       LOG(WARNING) << "Trying to disable a device that's already disabled: "
   3816                    << device;
   3817       return;
   3818     }
   3819 
   3820     RequestNetworkDeviceEnable(ConnectionTypeToString(device), enable);
   3821   }
   3822 
   3823   ////////////////////////////////////////////////////////////////////////////
   3824   // Notifications.
   3825 
   3826   // We call this any time something in NetworkLibrary changes.
   3827   // TODO(stevenjb): We should consider breaking this into multiple
   3828   // notifications, e.g. connection state, devices, services, etc.
   3829   void NotifyNetworkManagerChanged(bool force_update) {
   3830     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   3831     // Cancel any pending signals.
   3832     if (notify_task_) {
   3833       notify_task_->Cancel();
   3834       notify_task_ = NULL;
   3835     }
   3836     if (force_update) {
   3837       // Signal observers now.
   3838       SignalNetworkManagerObservers();
   3839     } else {
   3840       // Schedule a deleayed signal to limit the frequency of notifications.
   3841       notify_task_ = NewRunnableMethod(
   3842           this, &NetworkLibraryImpl::SignalNetworkManagerObservers);
   3843       BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, notify_task_,
   3844                                      kNetworkNotifyDelayMs);
   3845     }
   3846   }
   3847 
   3848   void SignalNetworkManagerObservers() {
   3849     notify_task_ = NULL;
   3850     FOR_EACH_OBSERVER(NetworkManagerObserver,
   3851                       network_manager_observers_,
   3852                       OnNetworkManagerChanged(this));
   3853   }
   3854 
   3855   void NotifyNetworkChanged(Network* network) {
   3856     VLOG(2) << "Network changed: " << network->name();
   3857     DCHECK(network);
   3858     NetworkObserverMap::const_iterator iter = network_observers_.find(
   3859         network->service_path());
   3860     if (iter != network_observers_.end()) {
   3861       FOR_EACH_OBSERVER(NetworkObserver,
   3862                         *(iter->second),
   3863                         OnNetworkChanged(this, network));
   3864     } else {
   3865       NOTREACHED() <<
   3866           "There weren't supposed to be any property change observers of " <<
   3867            network->service_path();
   3868     }
   3869   }
   3870 
   3871   void NotifyNetworkDeviceChanged(NetworkDevice* device) {
   3872     DCHECK(device);
   3873     NetworkDeviceObserverMap::const_iterator iter =
   3874         network_device_observers_.find(device->device_path());
   3875     if (iter != network_device_observers_.end()) {
   3876       NetworkDeviceObserverList* device_observer_list = iter->second;
   3877       FOR_EACH_OBSERVER(NetworkDeviceObserver,
   3878                         *device_observer_list,
   3879                         OnNetworkDeviceChanged(this, device));
   3880     } else {
   3881       NOTREACHED() <<
   3882           "There weren't supposed to be any property change observers of " <<
   3883            device->device_path();
   3884     }
   3885   }
   3886 
   3887   void NotifyCellularDataPlanChanged() {
   3888     FOR_EACH_OBSERVER(CellularDataPlanObserver,
   3889                       data_plan_observers_,
   3890                       OnCellularDataPlanChanged(this));
   3891   }
   3892 
   3893   void NotifyPinOperationCompleted(PinOperationError error) {
   3894     FOR_EACH_OBSERVER(PinOperationObserver,
   3895                       pin_operation_observers_,
   3896                       OnPinOperationCompleted(this, error));
   3897     sim_operation_ = SIM_OPERATION_NONE;
   3898   }
   3899 
   3900   void NotifyUserConnectionInitiated(const Network* network) {
   3901     FOR_EACH_OBSERVER(UserActionObserver,
   3902                       user_action_observers_,
   3903                       OnConnectionInitiated(this, network));
   3904   }
   3905 
   3906   ////////////////////////////////////////////////////////////////////////////
   3907   // Device updates.
   3908 
   3909   void FlipSimPinRequiredStateIfNeeded() {
   3910     if (sim_operation_ != SIM_OPERATION_CHANGE_REQUIRE_PIN)
   3911       return;
   3912 
   3913     const NetworkDevice* cellular = FindCellularDevice();
   3914     if (cellular) {
   3915       NetworkDevice* device = GetNetworkDeviceByPath(cellular->device_path());
   3916       if (device->sim_pin_required() == SIM_PIN_NOT_REQUIRED)
   3917         device->sim_pin_required_ = SIM_PIN_REQUIRED;
   3918       else if (device->sim_pin_required() == SIM_PIN_REQUIRED)
   3919         device->sim_pin_required_ = SIM_PIN_NOT_REQUIRED;
   3920     }
   3921   }
   3922 
   3923   void UpdateNetworkDeviceStatus(const char* path,
   3924                                  const char* key,
   3925                                  const Value* value) {
   3926     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   3927     if (key == NULL || value == NULL)
   3928       return;
   3929     NetworkDevice* device = GetNetworkDeviceByPath(path);
   3930     if (device) {
   3931       VLOG(1) << "UpdateNetworkDeviceStatus: " << device->name() << "." << key;
   3932       int index = property_index_parser().Get(std::string(key));
   3933       if (!device->ParseValue(index, value)) {
   3934         LOG(WARNING) << "UpdateNetworkDeviceStatus: Error parsing: "
   3935                      << path << "." << key;
   3936       } else if (strcmp(key, kCellularAllowRoamingProperty) == 0) {
   3937         bool settings_value =
   3938             UserCrosSettingsProvider::cached_data_roaming_enabled();
   3939         if (device->data_roaming_allowed() != settings_value) {
   3940           // Switch back to signed settings value.
   3941           SetCellularDataRoamingAllowed(settings_value);
   3942           return;
   3943         }
   3944       }
   3945       // Notify only observers on device property change.
   3946       NotifyNetworkDeviceChanged(device);
   3947       // If a device's power state changes, new properties may become
   3948       // defined.
   3949       if (strcmp(key, kPoweredProperty) == 0) {
   3950         RequestNetworkDeviceInfo(path, &NetworkDeviceUpdate, this);
   3951       }
   3952     }
   3953   }
   3954 
   3955   ////////////////////////////////////////////////////////////////////////////
   3956   // Service updates.
   3957 
   3958   void UpdateNetworkStatus(const char* path,
   3959                            const char* key,
   3960                            const Value* value) {
   3961     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   3962     if (key == NULL || value == NULL)
   3963       return;
   3964     Network* network = FindNetworkByPath(path);
   3965     if (network) {
   3966       VLOG(2) << "UpdateNetworkStatus: " << network->name() << "." << key;
   3967       // Note: ParseValue is virtual.
   3968       int index = property_index_parser().Get(std::string(key));
   3969       if (!network->ParseValue(index, value)) {
   3970         LOG(WARNING) << "UpdateNetworkStatus: Error parsing: "
   3971                      << path << "." << key;
   3972       }
   3973       NotifyNetworkChanged(network);
   3974       // Anything observing the manager needs to know about any service change.
   3975       NotifyNetworkManagerChanged(false);  // Not forced.
   3976     }
   3977   }
   3978 
   3979   ////////////////////////////////////////////////////////////////////////////
   3980   // Data Plans.
   3981 
   3982   const CellularDataPlan* GetSignificantDataPlanFromVector(
   3983       const CellularDataPlanVector* plans) const {
   3984     const CellularDataPlan* significant = NULL;
   3985     for (CellularDataPlanVector::const_iterator iter = plans->begin();
   3986          iter != plans->end(); ++iter) {
   3987       // Set significant to the first plan or to first non metered base plan.
   3988       if (significant == NULL ||
   3989           significant->plan_type == CELLULAR_DATA_PLAN_METERED_BASE)
   3990         significant = *iter;
   3991     }
   3992     return significant;
   3993   }
   3994 
   3995   CellularNetwork::DataLeft GetDataLeft(
   3996       CellularDataPlanVector* data_plans) {
   3997     const CellularDataPlan* plan = GetSignificantDataPlanFromVector(data_plans);
   3998     if (!plan)
   3999       return CellularNetwork::DATA_UNKNOWN;
   4000     if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
   4001       base::TimeDelta remaining = plan->remaining_time();
   4002       if (remaining <= base::TimeDelta::FromSeconds(0))
   4003         return CellularNetwork::DATA_NONE;
   4004       if (remaining <= base::TimeDelta::FromSeconds(kCellularDataVeryLowSecs))
   4005         return CellularNetwork::DATA_VERY_LOW;
   4006       if (remaining <= base::TimeDelta::FromSeconds(kCellularDataLowSecs))
   4007         return CellularNetwork::DATA_LOW;
   4008       return CellularNetwork::DATA_NORMAL;
   4009     } else if (plan->plan_type == CELLULAR_DATA_PLAN_METERED_PAID ||
   4010                plan->plan_type == CELLULAR_DATA_PLAN_METERED_BASE) {
   4011       int64 remaining = plan->remaining_data();
   4012       if (remaining <= 0)
   4013         return CellularNetwork::DATA_NONE;
   4014       if (remaining <= kCellularDataVeryLowBytes)
   4015         return CellularNetwork::DATA_VERY_LOW;
   4016       // For base plans, we do not care about low data.
   4017       if (remaining <= kCellularDataLowBytes &&
   4018           plan->plan_type != CELLULAR_DATA_PLAN_METERED_BASE)
   4019         return CellularNetwork::DATA_LOW;
   4020       return CellularNetwork::DATA_NORMAL;
   4021     }
   4022     return CellularNetwork::DATA_UNKNOWN;
   4023   }
   4024 
   4025   void UpdateCellularDataPlan(const std::string& service_path,
   4026                               const CellularDataPlanList* data_plan_list) {
   4027     VLOG(1) << "Updating cellular data plans for: " << service_path;
   4028     CellularDataPlanVector* data_plans = NULL;
   4029     // Find and delete any existing data plans associated with |service_path|.
   4030     CellularDataPlanMap::iterator found = data_plan_map_.find(service_path);
   4031     if (found != data_plan_map_.end()) {
   4032       data_plans = found->second;
   4033       data_plans->reset();  // This will delete existing data plans.
   4034     } else {
   4035       data_plans = new CellularDataPlanVector;
   4036       data_plan_map_[service_path] = data_plans;
   4037     }
   4038     for (size_t i = 0; i < data_plan_list->plans_size; i++) {
   4039       const CellularDataPlanInfo* info(data_plan_list->GetCellularDataPlan(i));
   4040       CellularDataPlan* plan = new CellularDataPlan(*info);
   4041       data_plans->push_back(plan);
   4042       VLOG(2) << " Plan: " << plan->GetPlanDesciption()
   4043               << " : " << plan->GetDataRemainingDesciption();
   4044     }
   4045     // Now, update any matching cellular network's cached data
   4046     CellularNetwork* cellular = FindCellularNetworkByPath(service_path);
   4047     if (cellular) {
   4048       CellularNetwork::DataLeft data_left;
   4049       // If the network needs a new plan, then there's no data.
   4050       if (cellular->needs_new_plan())
   4051         data_left = CellularNetwork::DATA_NONE;
   4052       else
   4053         data_left = GetDataLeft(data_plans);
   4054       VLOG(2) << " Data left: " << data_left
   4055               << " Need plan: " << cellular->needs_new_plan();
   4056       cellular->set_data_left(data_left);
   4057     }
   4058     NotifyCellularDataPlanChanged();
   4059   }
   4060 
   4061   ////////////////////////////////////////////////////////////////////////////
   4062 
   4063   void Init() {
   4064     // First, get the currently available networks. This data is cached
   4065     // on the connman side, so the call should be quick.
   4066     if (EnsureCrosLoaded()) {
   4067       VLOG(1) << "Requesting initial network manager info from libcros.";
   4068       RequestNetworkManagerInfo(&NetworkManagerUpdate, this);
   4069     }
   4070   }
   4071 
   4072   void InitTestData() {
   4073     is_locked_ = false;
   4074 
   4075     // Devices
   4076     int devices =
   4077         (1 << TYPE_ETHERNET) | (1 << TYPE_WIFI) | (1 << TYPE_CELLULAR);
   4078     available_devices_ = devices;
   4079     enabled_devices_ = devices;