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
85namespace chromeos {
86
87// Local constants.
88namespace {
89
90// Only send network change notifications to observers once every 50ms.
91const int kNetworkNotifyDelayMs = 50;
92
93// How long we should remember that cellular plan payment was received.
94const 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.
99const int kDefaultSimUnlockRetriesCount = 999;
100
101// Format of the Carrier ID: <carrier name> (<carrier country>).
102const char* kCarrierIdFormat = "%s (%s)";
103
104// Type of a pending SIM operation.
105enum 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.
116const char* kSecurityProperty = "Security";
117const char* kPassphraseProperty = "Passphrase";
118const char* kIdentityProperty = "Identity";
119const char* kCertPathProperty = "CertPath";
120const char* kPassphraseRequiredProperty = "PassphraseRequired";
121const char* kSaveCredentialsProperty = "SaveCredentials";
122const char* kProfilesProperty = "Profiles";
123const char* kServicesProperty = "Services";
124const char* kServiceWatchListProperty = "ServiceWatchList";
125const char* kAvailableTechnologiesProperty = "AvailableTechnologies";
126const char* kEnabledTechnologiesProperty = "EnabledTechnologies";
127const char* kConnectedTechnologiesProperty = "ConnectedTechnologies";
128const char* kDefaultTechnologyProperty = "DefaultTechnology";
129const char* kOfflineModeProperty = "OfflineMode";
130const char* kSignalStrengthProperty = "Strength";
131const char* kNameProperty = "Name";
132const char* kStateProperty = "State";
133const char* kConnectivityStateProperty = "ConnectivityState";
134const char* kTypeProperty = "Type";
135const char* kDeviceProperty = "Device";
136const char* kActivationStateProperty = "Cellular.ActivationState";
137const char* kNetworkTechnologyProperty = "Cellular.NetworkTechnology";
138const char* kRoamingStateProperty = "Cellular.RoamingState";
139const char* kOperatorNameProperty = "Cellular.OperatorName";
140const char* kOperatorCodeProperty = "Cellular.OperatorCode";
141const char* kServingOperatorProperty = "Cellular.ServingOperator";
142const char* kPaymentURLProperty = "Cellular.OlpUrl";
143const char* kUsageURLProperty = "Cellular.UsageUrl";
144const char* kCellularApnProperty = "Cellular.APN";
145const char* kCellularLastGoodApnProperty = "Cellular.LastGoodAPN";
146const char* kWifiHexSsid = "WiFi.HexSSID";
147const char* kWifiFrequency = "WiFi.Frequency";
148const char* kWifiHiddenSsid = "WiFi.HiddenSSID";
149const char* kWifiPhyMode = "WiFi.PhyMode";
150const char* kFavoriteProperty = "Favorite";
151const char* kConnectableProperty = "Connectable";
152const char* kAutoConnectProperty = "AutoConnect";
153const char* kIsActiveProperty = "IsActive";
154const char* kModeProperty = "Mode";
155const char* kErrorProperty = "Error";
156const char* kActiveProfileProperty = "ActiveProfile";
157const char* kEntriesProperty = "Entries";
158const char* kDevicesProperty = "Devices";
159const char* kProviderProperty = "Provider";
160const char* kHostProperty = "Host";
161
162// Flimflam property names for SIMLock status.
163const char* kSIMLockStatusProperty = "Cellular.SIMLockStatus";
164const char* kSIMLockTypeProperty = "LockType";
165const char* kSIMLockRetriesLeftProperty = "RetriesLeft";
166
167// Flimflam property names for Cellular.FoundNetworks.
168const char* kLongNameProperty = "long_name";
169const char* kStatusProperty = "status";
170const char* kShortNameProperty = "short_name";
171const char* kTechnologyProperty = "technology";
172
173// Flimflam SIMLock status types.
174const char* kSIMLockPin = "sim-pin";
175const char* kSIMLockPuk = "sim-puk";
176
177// APN info property names.
178const char* kApnProperty = "apn";
179const char* kNetworkIdProperty = "network_id";
180const char* kUsernameProperty = "username";
181const char* kPasswordProperty = "password";
182
183// Operator info property names.
184const char* kOperatorNameKey = "name";
185const char* kOperatorCodeKey = "code";
186const char* kOperatorCountryKey = "country";
187
188// Flimflam device info property names.
189const char* kScanningProperty = "Scanning";
190const char* kCarrierProperty = "Cellular.Carrier";
191const char* kCellularAllowRoamingProperty = "Cellular.AllowRoaming";
192const char* kHomeProviderProperty = "Cellular.HomeProvider";
193const char* kMeidProperty = "Cellular.MEID";
194const char* kImeiProperty = "Cellular.IMEI";
195const char* kImsiProperty = "Cellular.IMSI";
196const char* kEsnProperty = "Cellular.ESN";
197const char* kMdnProperty = "Cellular.MDN";
198const char* kMinProperty = "Cellular.MIN";
199const char* kModelIDProperty = "Cellular.ModelID";
200const char* kManufacturerProperty = "Cellular.Manufacturer";
201const char* kFirmwareRevisionProperty = "Cellular.FirmwareRevision";
202const char* kHardwareRevisionProperty = "Cellular.HardwareRevision";
203const char* kPoweredProperty = "Powered";
204const char* kPRLVersionProperty = "Cellular.PRLVersion"; // (INT16)
205const char* kSelectedNetworkProperty = "Cellular.SelectedNetwork";
206const char* kSupportNetworkScanProperty = "Cellular.SupportNetworkScan";
207const char* kFoundNetworksProperty = "Cellular.FoundNetworks";
208
209// Flimflam type options.
210const char* kTypeEthernet = "ethernet";
211const char* kTypeWifi = "wifi";
212const char* kTypeWimax = "wimax";
213const char* kTypeBluetooth = "bluetooth";
214const char* kTypeCellular = "cellular";
215const char* kTypeVPN = "vpn";
216
217// Flimflam mode options.
218const char* kModeManaged = "managed";
219const char* kModeAdhoc = "adhoc";
220
221// Flimflam security options.
222const char* kSecurityWpa = "wpa";
223const char* kSecurityWep = "wep";
224const char* kSecurityRsn = "rsn";
225const char* kSecurity8021x = "802_1x";
226const char* kSecurityPsk = "psk";
227const char* kSecurityNone = "none";
228
229// Flimflam L2TPIPsec property names.
230const char* kL2TPIPSecCACertProperty = "L2TPIPsec.CACert";
231const char* kL2TPIPSecCertProperty = "L2TPIPsec.Cert";
232const char* kL2TPIPSecKeyProperty = "L2TPIPsec.Key";
233const char* kL2TPIPSecPSKProperty = "L2TPIPsec.PSK";
234const char* kL2TPIPSecUserProperty = "L2TPIPsec.User";
235const char* kL2TPIPSecPasswordProperty = "L2TPIPsec.Password";
236
237// Flimflam EAP property names.
238// See src/third_party/flimflam/doc/service-api.txt.
239const char* kEapIdentityProperty = "EAP.Identity";
240const char* kEapMethodProperty = "EAP.EAP";
241const char* kEapPhase2AuthProperty = "EAP.InnerEAP";
242const char* kEapAnonymousIdentityProperty = "EAP.AnonymousIdentity";
243const char* kEapClientCertProperty = "EAP.ClientCert";  // path
244const char* kEapCertIDProperty = "EAP.CertID";  // PKCS#11 ID
245const char* kEapClientCertNssProperty = "EAP.ClientCertNSS";  // NSS nickname
246const char* kEapPrivateKeyProperty = "EAP.PrivateKey";
247const char* kEapPrivateKeyPasswordProperty = "EAP.PrivateKeyPassword";
248const char* kEapKeyIDProperty = "EAP.KeyID";
249const char* kEapCaCertProperty = "EAP.CACert";  // server CA cert path
250const char* kEapCaCertIDProperty = "EAP.CACertID";  // server CA PKCS#11 ID
251const char* kEapCaCertNssProperty = "EAP.CACertNSS";  // server CA NSS nickname
252const char* kEapUseSystemCAsProperty = "EAP.UseSystemCAs";
253const char* kEapPinProperty = "EAP.PIN";
254const char* kEapPasswordProperty = "EAP.Password";
255const char* kEapKeyMgmtProperty = "EAP.KeyMgmt";
256
257// Flimflam EAP method options.
258const std::string& kEapMethodPEAP = "PEAP";
259const std::string& kEapMethodTLS = "TLS";
260const std::string& kEapMethodTTLS = "TTLS";
261const std::string& kEapMethodLEAP = "LEAP";
262
263// Flimflam EAP phase 2 auth options.
264const std::string& kEapPhase2AuthPEAPMD5 = "auth=MD5";
265const std::string& kEapPhase2AuthPEAPMSCHAPV2 = "auth=MSCHAPV2";
266const std::string& kEapPhase2AuthTTLSMD5 = "autheap=MD5";
267const std::string& kEapPhase2AuthTTLSMSCHAPV2 = "autheap=MSCHAPV2";
268const std::string& kEapPhase2AuthTTLSMSCHAP = "autheap=MSCHAP";
269const std::string& kEapPhase2AuthTTLSPAP = "autheap=PAP";
270const std::string& kEapPhase2AuthTTLSCHAP = "autheap=CHAP";
271
272// Flimflam VPN provider types.
273const char* kProviderL2tpIpsec = "l2tpipsec";
274const char* kProviderOpenVpn = "openvpn";
275
276
277// Flimflam state options.
278const char* kStateIdle = "idle";
279const char* kStateCarrier = "carrier";
280const char* kStateAssociation = "association";
281const char* kStateConfiguration = "configuration";
282const char* kStateReady = "ready";
283const char* kStateDisconnect = "disconnect";
284const char* kStateFailure = "failure";
285const char* kStateActivationFailure = "activation-failure";
286
287// Flimflam connectivity state options.
288const char* kConnStateUnrestricted = "unrestricted";
289const char* kConnStateRestricted = "restricted";
290const char* kConnStateNone = "none";
291
292// Flimflam network technology options.
293const char* kNetworkTechnology1Xrtt = "1xRTT";
294const char* kNetworkTechnologyEvdo = "EVDO";
295const char* kNetworkTechnologyGprs = "GPRS";
296const char* kNetworkTechnologyEdge = "EDGE";
297const char* kNetworkTechnologyUmts = "UMTS";
298const char* kNetworkTechnologyHspa = "HSPA";
299const char* kNetworkTechnologyHspaPlus = "HSPA+";
300const char* kNetworkTechnologyLte = "LTE";
301const char* kNetworkTechnologyLteAdvanced = "LTE Advanced";
302
303// Flimflam roaming state options
304const char* kRoamingStateHome = "home";
305const char* kRoamingStateRoaming = "roaming";
306const char* kRoamingStateUnknown = "unknown";
307
308// Flimflam activation state options
309const char* kActivationStateActivated = "activated";
310const char* kActivationStateActivating = "activating";
311const char* kActivationStateNotActivated = "not-activated";
312const char* kActivationStatePartiallyActivated = "partially-activated";
313const char* kActivationStateUnknown = "unknown";
314
315// Flimflam error options.
316const char* kErrorOutOfRange = "out-of-range";
317const char* kErrorPinMissing = "pin-missing";
318const char* kErrorDhcpFailed = "dhcp-failed";
319const char* kErrorConnectFailed = "connect-failed";
320const char* kErrorBadPassphrase = "bad-passphrase";
321const char* kErrorBadWEPKey = "bad-wepkey";
322const char* kErrorActivationFailed = "activation-failed";
323const char* kErrorNeedEvdo = "need-evdo";
324const char* kErrorNeedHomeNetwork = "need-home-network";
325const char* kErrorOtaspFailed = "otasp-failed";
326const char* kErrorAaaFailed = "aaa-failed";
327
328// Flimflam error messages.
329const char* kErrorPassphraseRequiredMsg = "Passphrase required";
330const char* kErrorIncorrectPinMsg = "org.chromium.flimflam.Error.IncorrectPin";
331const char* kErrorPinBlockedMsg = "org.chromium.flimflam.Error.PinBlocked";
332const char* kErrorPinRequiredMsg = "org.chromium.flimflam.Error.PinRequired";
333
334const char* kUnknownString = "UNKNOWN";
335
336////////////////////////////////////////////////////////////////////////////
337
338static 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.
360static 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
381static 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.
398template <typename Type>
399class 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
429enum 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
520StringToEnum<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
610StringToEnum<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.
621static 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
635ConnectionType ParseTypeFromDictionary(const DictionaryValue* info) {
636  std::string type_string;
637  info->GetString(kTypeProperty, &type_string);
638  return ParseType(type_string);
639}
640
641static 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
651static 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
667static 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
687static 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.
698static 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
711static 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
722static 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
739static 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
752static 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
765static 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
790static 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
802static 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
816static 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
828static 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.
848static 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.
853static void WipeString(std::string* str) {
854  str->assign(str->size(), '\0');
855  str->clear();
856}
857
858static 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
870static 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
890NetworkDevice::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
902bool 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
1008void 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
1026void Network::SetName(const std::string& name) {
1027  std::string name_utf8;
1028  ValidateUTF8(name, &name_utf8);
1029  set_name(name_utf8);
1030}
1031
1032bool 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
1107void 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
1124void 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
1132void Network::ClearProperty(const char* prop) {
1133  DCHECK(prop);
1134  if (!EnsureCrosLoaded())
1135    return;
1136  ClearNetworkServiceProperty(service_path_.c_str(), prop);
1137}
1138
1139void 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
1147void 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
1159void 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
1166void 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
1173void Network::SetAutoConnect(bool auto_connect) {
1174  SetBooleanProperty(kAutoConnectProperty, auto_connect, &auto_connect_);
1175}
1176
1177std::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
1202std::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
1237void 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
1258bool 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
1279bool 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
1318void 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
1328bool 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
1347void VirtualNetwork::SetCACert(const std::string& ca_cert) {
1348  SetStringProperty(kL2TPIPSecCACertProperty, ca_cert, &ca_cert_);
1349}
1350
1351void VirtualNetwork::SetPSKPassphrase(const std::string& psk_passphrase) {
1352  SetStringProperty(kL2TPIPSecPSKProperty, psk_passphrase,
1353                           &psk_passphrase_);
1354}
1355
1356void VirtualNetwork::SetUserCert(const std::string& user_cert) {
1357  SetStringProperty(kL2TPIPSecCertProperty, user_cert, &user_cert_);
1358}
1359
1360void VirtualNetwork::SetUserCertKey(const std::string& key) {
1361  SetStringProperty(kL2TPIPSecKeyProperty, key, &user_cert_key_);
1362}
1363
1364void VirtualNetwork::SetUsername(const std::string& username) {
1365  SetStringProperty(kL2TPIPSecUserProperty, username, &username_);
1366}
1367
1368void VirtualNetwork::SetUserPassphrase(const std::string& user_passphrase) {
1369  SetStringProperty(kL2TPIPSecPasswordProperty, user_passphrase,
1370                    &user_passphrase_);
1371}
1372
1373std::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
1397bool 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
1411string16 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
1441string16 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
1460string16 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
1483string16 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
1507std::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
1518base::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
1523int64 CellularDataPlan::remaining_minutes() const {
1524  return remaining_time().InMinutes();
1525}
1526
1527int64 CellularDataPlan::remaining_data() const {
1528  int64 data = plan_data_bytes - data_bytes_used;
1529  return data < 0 ? 0 : data;
1530}
1531
1532string16 CellularDataPlan::GetPlanExpiration() const {
1533  return TimeFormat::TimeRemaining(remaining_time());
1534}
1535
1536////////////////////////////////////////////////////////////////////////////////
1537// CellularNetwork::Apn
1538
1539void 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
1553CellularNetwork::~CellularNetwork() {
1554}
1555
1556bool 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
1650bool CellularNetwork::StartActivation() const {
1651  if (!EnsureCrosLoaded())
1652    return false;
1653  return ActivateCellularModem(service_path().c_str(), NULL);
1654}
1655
1656void CellularNetwork::RefreshDataPlansIfNeeded() const {
1657  if (!EnsureCrosLoaded())
1658    return;
1659  if (connected() && activated())
1660    RequestCellularDataPlanUpdate(service_path().c_str());
1661}
1662
1663void 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
1679bool 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
1684std::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
1721std::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
1739std::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
1765std::string CellularNetwork::GetActivationStateString() const {
1766  return ActivationStateToString(this->activation_state_);
1767}
1768
1769std::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.
1790void 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
1800bool 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
1820bool 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
1832bool 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
1921void WifiNetwork::ParseInfo(const DictionaryValue* info) {
1922  Network::ParseInfo(info);
1923  CalculateUniqueId();
1924}
1925
1926const std::string& WifiNetwork::GetPassphrase() const {
1927  if (!user_passphrase_.empty())
1928    return user_passphrase_;
1929  return passphrase_;
1930}
1931
1932void 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
1947void 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.
1954void 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
1963void WifiNetwork::SetIdentity(const std::string& identity) {
1964  SetStringProperty(kIdentityProperty, identity, &identity_);
1965}
1966
1967void WifiNetwork::SetCertPath(const std::string& cert_path) {
1968  SetStringProperty(kCertPathProperty, cert_path, &cert_path_);
1969}
1970
1971void 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
1992void 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
2023void 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
2030void 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
2036void WifiNetwork::SetEAPUseSystemCAs(bool use_system_cas) {
2037  SetBooleanProperty(kEapUseSystemCAsProperty, use_system_cas,
2038                     &eap_use_system_cas_);
2039}
2040
2041void WifiNetwork::SetEAPIdentity(const std::string& identity) {
2042  SetOrClearStringProperty(kEapIdentityProperty, identity, &eap_identity_);
2043}
2044
2045void WifiNetwork::SetEAPAnonymousIdentity(const std::string& identity) {
2046  SetOrClearStringProperty(kEapAnonymousIdentityProperty, identity,
2047                           &eap_anonymous_identity_);
2048}
2049
2050void WifiNetwork::SetEAPPassphrase(const std::string& passphrase) {
2051  SetOrClearStringProperty(kEapPasswordProperty, passphrase, &eap_passphrase_);
2052}
2053
2054std::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
2074bool 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.
2089bool 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
2106class 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;
4080    connected_devices_ = devices;
4081
4082    NetworkDevice* cellular = new NetworkDevice("cellular");
4083    scoped_ptr<Value> cellular_type(Value::CreateStringValue(kTypeCellular));
4084    cellular->ParseValue(PROPERTY_INDEX_TYPE, cellular_type.get());
4085    cellular->IMSI_ = "123456789012345";
4086    device_map_["cellular"] = cellular;
4087
4088    // Networks
4089    ClearNetworks(true /*delete networks*/);
4090
4091    ethernet_ = new EthernetNetwork("eth1");
4092    ethernet_->set_connected(true);
4093    AddNetwork(ethernet_);
4094
4095    WifiNetwork* wifi1 = new WifiNetwork("fw1");
4096    wifi1->set_name("Fake Wifi Connected");
4097    wifi1->set_strength(90);
4098    wifi1->set_connected(true);
4099    wifi1->set_active(true);
4100    wifi1->set_encryption(SECURITY_NONE);
4101    AddNetwork(wifi1);
4102
4103    WifiNetwork* wifi2 = new WifiNetwork("fw2");
4104    wifi2->set_name("Fake Wifi");
4105    wifi2->set_strength(70);
4106    wifi2->set_connected(false);
4107    wifi2->set_encryption(SECURITY_NONE);
4108    AddNetwork(wifi2);
4109
4110    WifiNetwork* wifi3 = new WifiNetwork("fw3");
4111    wifi3->set_name("Fake Wifi Encrypted");
4112    wifi3->set_strength(60);
4113    wifi3->set_connected(false);
4114    wifi3->set_encryption(SECURITY_WEP);
4115    wifi3->set_passphrase_required(true);
4116    AddNetwork(wifi3);
4117
4118    WifiNetwork* wifi4 = new WifiNetwork("fw4");
4119    wifi4->set_name("Fake Wifi 802.1x");
4120    wifi4->set_strength(50);
4121    wifi4->set_connected(false);
4122    wifi4->set_connectable(false);
4123    wifi4->set_encryption(SECURITY_8021X);
4124    wifi4->set_identity("nobody@google.com");
4125    wifi4->set_cert_path("SETTINGS:key_id=3,cert_id=3,pin=111111");
4126    AddNetwork(wifi4);
4127
4128    WifiNetwork* wifi5 = new WifiNetwork("fw5");
4129    wifi5->set_name("Fake Wifi UTF-8 SSID ");
4130    wifi5->SetSsid("Fake Wifi UTF-8 SSID \u3042\u3044\u3046");
4131    wifi5->set_strength(25);
4132    wifi5->set_connected(false);
4133    AddNetwork(wifi5);
4134
4135    WifiNetwork* wifi6 = new WifiNetwork("fw6");
4136    wifi6->set_name("Fake Wifi latin-1 SSID ");
4137    wifi6->SetSsid("Fake Wifi latin-1 SSID \xc0\xcb\xcc\xd6\xfb");
4138    wifi6->set_strength(20);
4139    wifi6->set_connected(false);
4140    AddNetwork(wifi6);
4141
4142    active_wifi_ = wifi1;
4143
4144    CellularNetwork* cellular1 = new CellularNetwork("fc1");
4145    cellular1->set_name("Fake Cellular");
4146    cellular1->set_strength(70);
4147    cellular1->set_connected(true);
4148    cellular1->set_active(true);
4149    cellular1->set_activation_state(ACTIVATION_STATE_ACTIVATED);
4150    cellular1->set_payment_url(std::string("http://www.google.com"));
4151    cellular1->set_usage_url(std::string("http://www.google.com"));
4152    cellular1->set_network_technology(NETWORK_TECHNOLOGY_EVDO);
4153    cellular1->set_roaming_state(ROAMING_STATE_ROAMING);
4154
4155    CellularDataPlan* base_plan = new CellularDataPlan();
4156    base_plan->plan_name = "Base plan";
4157    base_plan->plan_type = CELLULAR_DATA_PLAN_METERED_BASE;
4158    base_plan->plan_data_bytes = 100ll * 1024 * 1024;
4159    base_plan->data_bytes_used = 75ll * 1024 * 1024;
4160    CellularDataPlanVector* data_plans = new CellularDataPlanVector();
4161    data_plan_map_[cellular1->service_path()] = data_plans;
4162    data_plans->push_back(base_plan);
4163
4164    CellularDataPlan* paid_plan = new CellularDataPlan();
4165    paid_plan->plan_name = "Paid plan";
4166    paid_plan->plan_type = CELLULAR_DATA_PLAN_METERED_PAID;
4167    paid_plan->plan_data_bytes = 5ll * 1024 * 1024 * 1024;
4168    paid_plan->data_bytes_used = 3ll * 1024 * 1024 * 1024;
4169    data_plans->push_back(paid_plan);
4170
4171    AddNetwork(cellular1);
4172    active_cellular_ = cellular1;
4173
4174    CellularNetwork* cellular2 = new CellularNetwork("fc2");
4175    cellular2->set_name("Fake Cellular 2");
4176    cellular2->set_strength(70);
4177    cellular2->set_connected(true);
4178    cellular2->set_activation_state(ACTIVATION_STATE_ACTIVATED);
4179    cellular2->set_network_technology(NETWORK_TECHNOLOGY_UMTS);
4180    AddNetwork(cellular2);
4181
4182    // Remembered Networks
4183    ClearRememberedNetworks(true /*delete networks*/);
4184    WifiNetwork* remembered_wifi2 = new WifiNetwork("fw2");
4185    remembered_wifi2->set_name("Fake Wifi 2");
4186    remembered_wifi2->set_strength(70);
4187    remembered_wifi2->set_connected(true);
4188    remembered_wifi2->set_encryption(SECURITY_WEP);
4189    AddRememberedWifiNetwork(remembered_wifi2);
4190
4191    // VPNs.
4192    VirtualNetwork* vpn1 = new VirtualNetwork("fv1");
4193    vpn1->set_name("Fake VPN Provider 1");
4194    vpn1->set_server_hostname("vpn1server.fake.com");
4195    vpn1->set_provider_type(VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK);
4196    vpn1->set_username("VPN User 1");
4197    vpn1->set_connected(false);
4198    AddNetwork(vpn1);
4199
4200    VirtualNetwork* vpn2 = new VirtualNetwork("fv2");
4201    vpn2->set_name("Fake VPN Provider 2");
4202    vpn2->set_server_hostname("vpn2server.fake.com");
4203    vpn2->set_provider_type(VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT);
4204    vpn2->set_username("VPN User 2");
4205    vpn2->set_connected(true);
4206    AddNetwork(vpn2);
4207
4208    VirtualNetwork* vpn3 = new VirtualNetwork("fv3");
4209    vpn3->set_name("Fake VPN Provider 3");
4210    vpn3->set_server_hostname("vpn3server.fake.com");
4211    vpn3->set_provider_type(VirtualNetwork::PROVIDER_TYPE_OPEN_VPN);
4212    vpn3->set_connected(false);
4213    AddNetwork(vpn3);
4214
4215    active_virtual_ = vpn2;
4216
4217    wifi_scanning_ = false;
4218    offline_mode_ = false;
4219  }
4220
4221  // Network manager observer list
4222  ObserverList<NetworkManagerObserver> network_manager_observers_;
4223
4224  // Cellular data plan observer list
4225  ObserverList<CellularDataPlanObserver> data_plan_observers_;
4226
4227  // PIN operation observer list.
4228  ObserverList<PinOperationObserver> pin_operation_observers_;
4229
4230  // User action observer list
4231  ObserverList<UserActionObserver> user_action_observers_;
4232
4233  // Network observer map
4234  NetworkObserverMap network_observers_;
4235
4236  // Network device observer map.
4237  NetworkDeviceObserverMap network_device_observers_;
4238
4239  // For monitoring network manager status changes.
4240  PropertyChangeMonitor network_manager_monitor_;
4241
4242  // For monitoring data plan changes to the connected cellular network.
4243  DataPlanUpdateMonitor data_plan_monitor_;
4244
4245  // Network login observer.
4246  scoped_ptr<NetworkLoginObserver> network_login_observer_;
4247
4248  // A service path based map of all Networks.
4249  NetworkMap network_map_;
4250
4251  // A unique_id_ based map of Networks.
4252  NetworkMap network_unique_id_map_;
4253
4254  // A service path based map of all remembered Networks.
4255  NetworkMap remembered_network_map_;
4256
4257  // A list of services that we are awaiting updates for.
4258  PriorityMap network_update_requests_;
4259
4260  // A device path based map of all NetworkDevices.
4261  NetworkDeviceMap device_map_;
4262
4263  // A network service path based map of all CellularDataPlanVectors.
4264  CellularDataPlanMap data_plan_map_;
4265
4266  // The ethernet network.
4267  EthernetNetwork* ethernet_;
4268
4269  // The list of available wifi networks.
4270  WifiNetworkVector wifi_networks_;
4271
4272  // The current connected (or connecting) wifi network.
4273  WifiNetwork* active_wifi_;
4274
4275  // The remembered wifi networks.
4276  WifiNetworkVector remembered_wifi_networks_;
4277
4278  // The list of available cellular networks.
4279  CellularNetworkVector cellular_networks_;
4280
4281  // The current connected (or connecting) cellular network.
4282  CellularNetwork* active_cellular_;
4283
4284  // The list of available virtual networks.
4285  VirtualNetworkVector virtual_networks_;
4286
4287  // The current connected (or connecting) virtual network.
4288  VirtualNetwork* active_virtual_;
4289
4290  // The path of the active profile (for retrieving remembered services).
4291  std::string active_profile_path_;
4292
4293  // The current available network devices. Bitwise flag of ConnectionTypes.
4294  int available_devices_;
4295
4296  // The current enabled network devices. Bitwise flag of ConnectionTypes.
4297  int enabled_devices_;
4298
4299  // The current connected network devices. Bitwise flag of ConnectionTypes.
4300  int connected_devices_;
4301
4302  // True if we are currently scanning for wifi networks.
4303  bool wifi_scanning_;
4304
4305  // Currently not implemented. TODO: implement or eliminate.
4306  bool offline_mode_;
4307
4308  // True if access network library is locked.
4309  bool is_locked_;
4310
4311  // Type of pending SIM operation, SIM_OPERATION_NONE otherwise.
4312  SimOperationType sim_operation_;
4313
4314  // Delayed task to notify a network change.
4315  CancelableTask* notify_task_;
4316
4317  // Cellular plan payment time.
4318  base::Time cellular_plan_payment_time_;
4319
4320  // Temporary connection data for async connect calls.
4321  struct ConnectData {
4322    std::string service_name;
4323    std::string passphrase;
4324    std::string identity;
4325    std::string cert_path;
4326    std::string psk_key;
4327    std::string server_hostname;
4328  };
4329  ConnectData connect_data_;
4330
4331  DISALLOW_COPY_AND_ASSIGN(NetworkLibraryImpl);
4332};
4333
4334class NetworkLibraryStubImpl : public NetworkLibrary {
4335 public:
4336  NetworkLibraryStubImpl()
4337      : ip_address_("1.1.1.1"),
4338        ethernet_(new EthernetNetwork("eth0")),
4339        active_wifi_(NULL),
4340        active_cellular_(NULL) {
4341  }
4342  ~NetworkLibraryStubImpl() { if (ethernet_) delete ethernet_; }
4343  virtual void AddNetworkManagerObserver(NetworkManagerObserver* observer) {}
4344  virtual void RemoveNetworkManagerObserver(NetworkManagerObserver* observer) {}
4345  virtual void AddNetworkObserver(const std::string& service_path,
4346                                  NetworkObserver* observer) {}
4347  virtual void RemoveNetworkObserver(const std::string& service_path,
4348                                     NetworkObserver* observer) {}
4349  virtual void RemoveObserverForAllNetworks(NetworkObserver* observer) {}
4350  virtual void AddNetworkDeviceObserver(const std::string& device_path,
4351                                        NetworkDeviceObserver* observer) {}
4352  virtual void RemoveNetworkDeviceObserver(const std::string& device_path,
4353                                           NetworkDeviceObserver* observer) {}
4354  virtual void Lock() {}
4355  virtual void Unlock() {}
4356  virtual bool IsLocked() { return false; }
4357  virtual void AddCellularDataPlanObserver(
4358      CellularDataPlanObserver* observer) {}
4359  virtual void RemoveCellularDataPlanObserver(
4360      CellularDataPlanObserver* observer) {}
4361  virtual void AddPinOperationObserver(PinOperationObserver* observer) {}
4362  virtual void RemovePinOperationObserver(PinOperationObserver* observer) {}
4363  virtual void AddUserActionObserver(UserActionObserver* observer) {}
4364  virtual void RemoveUserActionObserver(UserActionObserver* observer) {}
4365
4366  virtual const EthernetNetwork* ethernet_network() const {
4367    return ethernet_;
4368  }
4369  virtual bool ethernet_connecting() const { return false; }
4370  virtual bool ethernet_connected() const { return true; }
4371
4372  virtual const WifiNetwork* wifi_network() const {
4373    return active_wifi_;
4374  }
4375  virtual bool wifi_connecting() const { return false; }
4376  virtual bool wifi_connected() const { return false; }
4377
4378  virtual const CellularNetwork* cellular_network() const {
4379    return active_cellular_;
4380  }
4381  virtual bool cellular_connecting() const { return false; }
4382  virtual bool cellular_connected() const { return false; }
4383
4384  virtual const VirtualNetwork* virtual_network() const {
4385    return active_virtual_;
4386  }
4387  virtual bool virtual_network_connecting() const { return false; }
4388  virtual bool virtual_network_connected() const { return false; }
4389
4390  bool Connected() const { return true; }
4391  bool Connecting() const { return false; }
4392  const std::string& IPAddress() const { return ip_address_; }
4393  virtual const WifiNetworkVector& wifi_networks() const {
4394    return wifi_networks_;
4395  }
4396  virtual const WifiNetworkVector& remembered_wifi_networks() const {
4397    return wifi_networks_;
4398  }
4399  virtual const CellularNetworkVector& cellular_networks() const {
4400    return cellular_networks_;
4401  }
4402  virtual const VirtualNetworkVector& virtual_networks() const {
4403    return virtual_networks_;
4404  }
4405  virtual bool has_cellular_networks() const {
4406    return cellular_networks_.begin() != cellular_networks_.end();
4407  }
4408  /////////////////////////////////////////////////////////////////////////////
4409
4410  virtual const NetworkDevice* FindNetworkDeviceByPath(
4411      const std::string& path) const { return NULL; }
4412  virtual const NetworkDevice* FindCellularDevice() const {
4413    return NULL;
4414  }
4415  virtual const NetworkDevice* FindEthernetDevice() const {
4416    return NULL;
4417  }
4418  virtual const NetworkDevice* FindWifiDevice() const {
4419    return NULL;
4420  }
4421  virtual Network* FindNetworkByPath(
4422      const std::string& path) const { return NULL; }
4423  virtual WifiNetwork* FindWifiNetworkByPath(
4424      const std::string& path) const { return NULL; }
4425  virtual CellularNetwork* FindCellularNetworkByPath(
4426      const std::string& path) const { return NULL; }
4427  virtual VirtualNetwork* FindVirtualNetworkByPath(
4428      const std::string& path) const { return NULL; }
4429  virtual Network* FindNetworkFromRemembered(
4430      const Network* remembered) const { return NULL; }
4431  virtual const CellularDataPlanVector* GetDataPlans(
4432      const std::string& path) const { return NULL; }
4433  virtual const CellularDataPlan* GetSignificantDataPlan(
4434      const std::string& path) const { return NULL; }
4435
4436  virtual void ChangePin(const std::string& old_pin,
4437                         const std::string& new_pin) {}
4438  virtual void ChangeRequirePin(bool require_pin, const std::string& pin) {}
4439  virtual void EnterPin(const std::string& pin) {}
4440  virtual void UnblockPin(const std::string& puk, const std::string& new_pin) {}
4441  virtual void RequestCellularScan() {}
4442  virtual void RequestCellularRegister(const std::string& network_id) {}
4443  virtual void SetCellularDataRoamingAllowed(bool new_value) {}
4444
4445  virtual void RequestNetworkScan() {}
4446  virtual bool GetWifiAccessPoints(WifiAccessPointVector* result) {
4447    return false;
4448  }
4449
4450  virtual void ConnectToWifiNetwork(WifiNetwork* network) {}
4451  virtual void ConnectToWifiNetwork(const std::string& service_path) {}
4452  virtual void ConnectToWifiNetwork(ConnectionSecurity security,
4453                                    const std::string& ssid,
4454                                    const std::string& passphrase,
4455                                    const std::string& identity,
4456                                    const std::string& certpath) {}
4457  virtual void ConnectToCellularNetwork(CellularNetwork* network) {}
4458  virtual void ConnectToVirtualNetwork(VirtualNetwork* network) {}
4459  virtual void ConnectToVirtualNetworkPSK(
4460      const std::string& service_name,
4461      const std::string& server,
4462      const std::string& psk,
4463      const std::string& username,
4464      const std::string& user_passphrase) {}
4465  virtual void SignalCellularPlanPayment() {}
4466  virtual bool HasRecentCellularPlanPayment() { return false; }
4467  virtual void DisconnectFromNetwork(const Network* network) {}
4468  virtual void ForgetWifiNetwork(const std::string& service_path) {}
4469  virtual std::string GetCellularHomeCarrierId() const { return std::string(); }
4470  virtual bool ethernet_available() const { return true; }
4471  virtual bool wifi_available() const { return false; }
4472  virtual bool cellular_available() const { return false; }
4473  virtual bool ethernet_enabled() const { return true; }
4474  virtual bool wifi_enabled() const { return false; }
4475  virtual bool cellular_enabled() const { return false; }
4476  virtual bool wifi_scanning() const { return false; }
4477  virtual const Network* active_network() const { return NULL; }
4478  virtual const Network* connected_network() const { return NULL; }
4479  virtual bool offline_mode() const { return false; }
4480  virtual void EnableEthernetNetworkDevice(bool enable) {}
4481  virtual void EnableWifiNetworkDevice(bool enable) {}
4482  virtual void EnableCellularNetworkDevice(bool enable) {}
4483  virtual void EnableOfflineMode(bool enable) {}
4484  virtual NetworkIPConfigVector GetIPConfigs(const std::string& device_path,
4485                                             std::string* hardware_address,
4486                                             HardwareAddressFormat) {
4487    hardware_address->clear();
4488    return NetworkIPConfigVector();
4489  }
4490
4491 private:
4492  std::string ip_address_;
4493  EthernetNetwork* ethernet_;
4494  WifiNetwork* active_wifi_;
4495  CellularNetwork* active_cellular_;
4496  VirtualNetwork* active_virtual_;
4497  WifiNetworkVector wifi_networks_;
4498  CellularNetworkVector cellular_networks_;
4499  VirtualNetworkVector virtual_networks_;
4500};
4501
4502// static
4503NetworkLibrary* NetworkLibrary::GetImpl(bool stub) {
4504  if (stub)
4505    return new NetworkLibraryStubImpl();
4506  else
4507    return new NetworkLibraryImpl();
4508}
4509
4510}  // namespace chromeos
4511
4512// Allows InvokeLater without adding refcounting. This class is a Singleton and
4513// won't be deleted until it's last InvokeLater is run.
4514DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::NetworkLibraryImpl);
4515