network_library.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1  // Copyright (c) 2010 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/time_formatting.h"
11#include "base/stl_util-inl.h"
12#include "base/string_number_conversions.h"
13#include "base/string_util.h"
14#include "base/utf_string_conversions.h"
15#include "base/values.h"
16#include "chrome/browser/browser_thread.h"
17#include "chrome/browser/chromeos/network_login_observer.h"
18#include "chrome/browser/chromeos/cros/cros_library.h"
19#include "chrome/browser/chromeos/login/user_manager.h"
20#include "chrome/common/time_format.h"
21#include "grit/generated_resources.h"
22#include "ui/base/l10n/l10n_util.h"
23
24namespace {
25
26// FlimFlam may send multiple notifications for single network change.
27// We wait small amount of time before retrieving the status to
28// avoid send multiple sync request to flim flam.
29const int kNetworkUpdateDelayMs = 50;
30
31}  // namespace
32
33namespace chromeos {
34
35namespace {
36// TODO(ers) These string constants and Parse functions are copied
37// straight out of libcros:chromeos_network.cc. Fix this by moving
38// all handling of properties into libcros.
39// Network service properties we are interested in monitoring
40static const char* kConnectableProperty = "Connectable";
41static const char* kIsActiveProperty = "IsActive";
42static const char* kStateProperty = "State";
43static const char* kConnectivityStateProperty = "ConnectivityState";
44static const char* kSignalStrengthProperty = "Strength";
45static const char* kActivationStateProperty = "Cellular.ActivationState";
46static const char* kNetworkTechnologyProperty = "Cellular.NetworkTechnology";
47static const char* kPaymentURLProperty = "Cellular.OlpUrl";
48  static const char* kRoamingStateProperty = "Cellular.RoamingState";
49
50// Connman state options.
51static const char* kStateIdle = "idle";
52static const char* kStateCarrier = "carrier";
53static const char* kStateAssociation = "association";
54static const char* kStateConfiguration = "configuration";
55static const char* kStateReady = "ready";
56  static const char* kStateDisconnect = "disconnect";
57static const char* kStateFailure = "failure";
58static const char* kStateActivationFailure = "activation-failure";
59
60// Connman activation state options
61static const char* kActivationStateActivated = "activated";
62static const char* kActivationStateActivating = "activating";
63static const char* kActivationStateNotActivated = "not-activated";
64static const char* kActivationStatePartiallyActivated = "partially-activated";
65static const char* kActivationStateUnknown = "unknown";
66
67// Connman connectivity state options
68static const char* kConnStateUnrestricted = "unrestricted";
69static const char* kConnStateRestricted = "restricted";
70static const char* kConnStateNone = "none";
71
72// Connman network technology options.
73static const char* kNetworkTechnology1Xrtt = "1xRTT";
74static const char* kNetworkTechnologyEvdo = "EVDO";
75static const char* kNetworkTechnologyGprs = "GPRS";
76static const char* kNetworkTechnologyEdge = "EDGE";
77static const char* kNetworkTechnologyUmts = "UMTS";
78static const char* kNetworkTechnologyHspa = "HSPA";
79static const char* kNetworkTechnologyHspaPlus = "HSPA+";
80static const char* kNetworkTechnologyLte = "LTE";
81static const char* kNetworkTechnologyLteAdvanced = "LTE Advanced";
82
83// Connman roaming state options
84static const char* kRoamingStateHome = "home";
85static const char* kRoamingStateRoaming = "roaming";
86static const char* kRoamingStateUnknown = "unknown";
87
88// How long we should remember that cellular plan payment was received.
89const int kRecentPlanPaymentHours = 6;
90
91static ConnectionState ParseState(const std::string& state) {
92  if (state == kStateIdle)
93    return STATE_IDLE;
94  if (state == kStateCarrier)
95    return STATE_CARRIER;
96  if (state == kStateAssociation)
97    return STATE_ASSOCIATION;
98  if (state == kStateConfiguration)
99    return STATE_CONFIGURATION;
100  if (state == kStateReady)
101    return STATE_READY;
102  if (state == kStateDisconnect)
103    return STATE_DISCONNECT;
104  if (state == kStateFailure)
105    return STATE_FAILURE;
106  if (state == kStateActivationFailure)
107    return STATE_ACTIVATION_FAILURE;
108  return STATE_UNKNOWN;
109}
110
111static ActivationState ParseActivationState(
112    const std::string& activation_state) {
113  if (activation_state == kActivationStateActivated)
114    return ACTIVATION_STATE_ACTIVATED;
115  if (activation_state == kActivationStateActivating)
116    return ACTIVATION_STATE_ACTIVATING;
117  if (activation_state == kActivationStateNotActivated)
118    return ACTIVATION_STATE_NOT_ACTIVATED;
119  if (activation_state == kActivationStateUnknown)
120    return ACTIVATION_STATE_UNKNOWN;
121  if (activation_state == kActivationStatePartiallyActivated)
122    return ACTIVATION_STATE_PARTIALLY_ACTIVATED;
123  return ACTIVATION_STATE_UNKNOWN;
124}
125
126static ConnectivityState ParseConnectivityState(const std::string& state) {
127  if (state == kConnStateUnrestricted)
128    return CONN_STATE_UNRESTRICTED;
129  if (state == kConnStateRestricted)
130    return CONN_STATE_RESTRICTED;
131  if (state == kConnStateNone)
132    return CONN_STATE_NONE;
133  return CONN_STATE_UNKNOWN;
134}
135
136static NetworkTechnology ParseNetworkTechnology(
137    const std::string& technology) {
138    if (technology == kNetworkTechnology1Xrtt)
139    return NETWORK_TECHNOLOGY_1XRTT;
140  if (technology == kNetworkTechnologyEvdo)
141    return NETWORK_TECHNOLOGY_EVDO;
142  if (technology == kNetworkTechnologyGprs)
143    return NETWORK_TECHNOLOGY_GPRS;
144  if (technology == kNetworkTechnologyEdge)
145    return NETWORK_TECHNOLOGY_EDGE;
146  if (technology == kNetworkTechnologyUmts)
147    return NETWORK_TECHNOLOGY_UMTS;
148  if (technology == kNetworkTechnologyHspa)
149    return NETWORK_TECHNOLOGY_HSPA;
150  if (technology == kNetworkTechnologyHspaPlus)
151    return NETWORK_TECHNOLOGY_HSPA_PLUS;
152  if (technology == kNetworkTechnologyLte)
153    return NETWORK_TECHNOLOGY_LTE;
154  if (technology == kNetworkTechnologyLteAdvanced)
155    return NETWORK_TECHNOLOGY_LTE_ADVANCED;
156  return NETWORK_TECHNOLOGY_UNKNOWN;
157}
158
159static NetworkRoamingState ParseRoamingState(
160    const std::string& roaming_state) {
161    if (roaming_state == kRoamingStateHome)
162      return ROAMING_STATE_HOME;
163  if (roaming_state == kRoamingStateRoaming)
164    return ROAMING_STATE_ROAMING;
165  if (roaming_state == kRoamingStateUnknown)
166    return ROAMING_STATE_UNKNOWN;
167  return ROAMING_STATE_UNKNOWN;
168}
169
170}  // namespace
171
172// Helper function to wrap Html with <th> tag.
173static std::string WrapWithTH(std::string text) {
174  return "<th>" + text + "</th>";
175}
176
177// Helper function to wrap Html with <td> tag.
178static std::string WrapWithTD(std::string text) {
179  return "<td>" + text + "</td>";
180}
181
182// Helper function to create an Html table header for a Network.
183static std::string ToHtmlTableHeader(Network* network) {
184  std::string str;
185  if (network->type() == TYPE_ETHERNET) {
186    str += WrapWithTH("Active");
187  } else if (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR) {
188    str += WrapWithTH("Name") + WrapWithTH("Active") +
189        WrapWithTH("Auto-Connect") + WrapWithTH("Strength");
190    if (network->type() == TYPE_WIFI)
191      str += WrapWithTH("Encryption") + WrapWithTH("Passphrase") +
192          WrapWithTH("Identity") + WrapWithTH("Certificate");
193  }
194  str += WrapWithTH("State") + WrapWithTH("Error") + WrapWithTH("IP Address");
195  return str;
196}
197
198// Helper function to create an Html table row for a Network.
199static std::string ToHtmlTableRow(Network* network) {
200  std::string str;
201  if (network->type() == TYPE_ETHERNET) {
202    str += WrapWithTD(base::IntToString(network->is_active()));
203  } else if (network->type() == TYPE_WIFI || network->type() == TYPE_CELLULAR) {
204    WirelessNetwork* wireless = static_cast<WirelessNetwork*>(network);
205    str += WrapWithTD(wireless->name()) +
206        WrapWithTD(base::IntToString(network->is_active())) +
207        WrapWithTD(base::IntToString(wireless->auto_connect())) +
208        WrapWithTD(base::IntToString(wireless->strength()));
209    if (network->type() == TYPE_WIFI) {
210      WifiNetwork* wifi = static_cast<WifiNetwork*>(network);
211      str += WrapWithTD(wifi->GetEncryptionString()) +
212          WrapWithTD(std::string(wifi->passphrase().length(), '*')) +
213          WrapWithTD(wifi->identity()) + WrapWithTD(wifi->cert_path());
214    }
215  }
216  str += WrapWithTD(network->GetStateString()) +
217      WrapWithTD(network->failed() ? network->GetErrorString() : "") +
218      WrapWithTD(network->ip_address());
219  return str;
220}
221
222// Safe string constructor since we can't rely on non NULL pointers
223// for string values from libcros.
224static std::string SafeString(const char* s) {
225  return s ? std::string(s) : std::string();
226}
227
228static bool EnsureCrosLoaded() {
229  if (!CrosLibrary::Get()->EnsureLoaded()) {
230    return false;
231  } else {
232    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
233      LOG(ERROR) << "chromeos_library calls made from non UI thread!";
234      NOTREACHED();
235    }
236    return true;
237  }
238}
239
240////////////////////////////////////////////////////////////////////////////////
241// Network
242
243Network::Network(const Network& network) {
244  service_path_ = network.service_path_;
245  device_path_ = network.device_path_;
246  ip_address_ = network.ip_address_;
247  type_ = network.type_;
248  state_ = network.state_;
249  error_ = network.error_;
250  connectable_ = network.connectable_;
251  is_active_ = network.is_active_;
252}
253
254void Network::Clear() {
255  service_path_.clear();
256  device_path_.clear();
257  ip_address_.clear();
258  type_ = TYPE_UNKNOWN;
259  state_ = STATE_UNKNOWN;
260  error_ = ERROR_UNKNOWN;
261  connectable_ = true;
262  is_active_ = false;
263}
264
265Network::Network(const ServiceInfo* service) {
266  type_ = service->type;
267  state_ = service->state;
268  error_ = service->error;
269  service_path_ = SafeString(service->service_path);
270  device_path_ = SafeString(service->device_path);
271  connectable_ = service->connectable;
272  is_active_ = service->is_active;
273  InitIPAddress();
274}
275
276// Used by GetHtmlInfo() which is called from the about:network handler.
277std::string Network::GetStateString() const {
278  switch (state_) {
279    case STATE_UNKNOWN:
280      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNKNOWN);
281    case STATE_IDLE:
282      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_IDLE);
283    case STATE_CARRIER:
284      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_CARRIER);
285    case STATE_ASSOCIATION:
286      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_ASSOCIATION);
287    case STATE_CONFIGURATION:
288      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_CONFIGURATION);
289    case STATE_READY:
290      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_READY);
291    case STATE_DISCONNECT:
292      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_DISCONNECT);
293    case STATE_FAILURE:
294      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_FAILURE);
295    case STATE_ACTIVATION_FAILURE:
296      return l10n_util::GetStringUTF8(
297          IDS_CHROMEOS_NETWORK_STATE_ACTIVATION_FAILURE);
298    default:
299      // Usually no default, but changes to libcros may add states.
300      break;
301  }
302  return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED);
303}
304
305std::string Network::GetErrorString() const {
306  switch (error_) {
307    case ERROR_UNKNOWN:
308      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
309    case ERROR_OUT_OF_RANGE:
310      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE);
311    case ERROR_PIN_MISSING:
312      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_PIN_MISSING);
313    case ERROR_DHCP_FAILED:
314      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_DHCP_FAILED);
315    case ERROR_CONNECT_FAILED:
316      return l10n_util::GetStringUTF8(
317          IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
318    case ERROR_BAD_PASSPHRASE:
319      return l10n_util::GetStringUTF8(
320          IDS_CHROMEOS_NETWORK_ERROR_BAD_PASSPHRASE);
321    case ERROR_BAD_WEPKEY:
322      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_BAD_WEPKEY);
323    case ERROR_ACTIVATION_FAILED:
324      return l10n_util::GetStringUTF8(
325          IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
326    case ERROR_NEED_EVDO:
327      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_NEED_EVDO);
328    case ERROR_NEED_HOME_NETWORK:
329      return l10n_util::GetStringUTF8(
330          IDS_CHROMEOS_NETWORK_ERROR_NEED_HOME_NETWORK);
331    case ERROR_OTASP_FAILED:
332      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_OTASP_FAILED);
333    case ERROR_AAA_FAILED:
334      return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_AAA_FAILED);
335    default:
336      // Usually no default, but changes to libcros may add errors.
337      break;
338  }
339  return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED);
340}
341
342void Network::InitIPAddress() {
343  ip_address_.clear();
344  // If connected, get ip config.
345  if (EnsureCrosLoaded() && connected() && !device_path_.empty()) {
346    IPConfigStatus* ipconfig_status = ListIPConfigs(device_path_.c_str());
347    if (ipconfig_status) {
348      for (int i = 0; i < ipconfig_status->size; i++) {
349        IPConfig ipconfig = ipconfig_status->ips[i];
350        if (strlen(ipconfig.address) > 0) {
351          ip_address_ = ipconfig.address;
352          break;
353        }
354      }
355      FreeIPConfigStatus(ipconfig_status);
356    }
357  }
358}
359
360////////////////////////////////////////////////////////////////////////////////
361// WirelessNetwork
362WirelessNetwork::WirelessNetwork(const WirelessNetwork& network)
363    : Network(network) {
364  name_ = network.name_;
365  strength_ = network.strength_;
366  auto_connect_ = network.auto_connect_;
367  favorite_ = network.favorite_;
368}
369
370WirelessNetwork::WirelessNetwork(const ServiceInfo* service)
371    : Network(service) {
372  name_ = SafeString(service->name);
373  strength_ = service->strength;
374  auto_connect_ = service->auto_connect;
375  favorite_ = service->favorite;
376}
377
378void WirelessNetwork::Clear() {
379  Network::Clear();
380  name_.clear();
381  strength_ = 0;
382  auto_connect_ = false;
383  favorite_ = false;
384}
385
386////////////////////////////////////////////////////////////////////////////////
387// CellularDataPlan
388
389string16 CellularDataPlan::GetPlanDesciption() const {
390  switch (plan_type) {
391    case chromeos::CELLULAR_DATA_PLAN_UNLIMITED: {
392      return l10n_util::GetStringFUTF16(
393          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_UNLIMITED_DATA,
394          base::TimeFormatFriendlyDate(plan_start_time));
395      break;
396    }
397    case chromeos::CELLULAR_DATA_PLAN_METERED_PAID: {
398      return l10n_util::GetStringFUTF16(
399                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PURCHASE_DATA,
400                FormatBytes(plan_data_bytes,
401                            GetByteDisplayUnits(plan_data_bytes),
402                            true),
403                base::TimeFormatFriendlyDate(plan_start_time));
404    }
405    case chromeos::CELLULAR_DATA_PLAN_METERED_BASE: {
406      return l10n_util::GetStringFUTF16(
407                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_RECEIVED_FREE_DATA,
408                FormatBytes(plan_data_bytes,
409                            GetByteDisplayUnits(plan_data_bytes),
410                            true),
411                base::TimeFormatFriendlyDate(plan_start_time));
412    default:
413      break;
414    }
415  }
416  return string16();
417}
418
419string16 CellularDataPlan::GetRemainingWarning() const {
420  if (plan_type == chromeos::CELLULAR_DATA_PLAN_UNLIMITED) {
421    // Time based plan. Show nearing expiration and data expiration.
422    if (remaining_time().InSeconds() <= chromeos::kCellularDataVeryLowSecs) {
423      return GetPlanExpiration();
424    }
425  } else if (plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_PAID ||
426             plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_BASE) {
427    // Metered plan. Show low data and out of data.
428    if (remaining_data() <= chromeos::kCellularDataVeryLowBytes) {
429      return l10n_util::GetStringFUTF16(
430          IDS_NETWORK_DATA_REMAINING_MESSAGE,
431          UTF8ToUTF16(base::Int64ToString(remaining_mbytes())));
432    }
433  }
434  return string16();
435}
436
437string16 CellularDataPlan::GetDataRemainingDesciption() const {
438  int64 remaining_bytes = remaining_data();
439  switch (plan_type) {
440    case chromeos::CELLULAR_DATA_PLAN_UNLIMITED: {
441      return l10n_util::GetStringUTF16(
442          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_UNLIMITED);
443    }
444    case chromeos::CELLULAR_DATA_PLAN_METERED_PAID: {
445      return FormatBytes(remaining_bytes,
446          GetByteDisplayUnits(remaining_bytes),
447          true);
448    }
449    case chromeos::CELLULAR_DATA_PLAN_METERED_BASE: {
450      return FormatBytes(remaining_bytes,
451          GetByteDisplayUnits(remaining_bytes),
452          true);
453    }
454    default:
455      break;
456  }
457  return string16();
458}
459
460string16 CellularDataPlan::GetUsageInfo() const {
461  if (plan_type == chromeos::CELLULAR_DATA_PLAN_UNLIMITED) {
462    // Time based plan. Show nearing expiration and data expiration.
463    return GetPlanExpiration();
464  } else if (plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_PAID ||
465             plan_type == chromeos::CELLULAR_DATA_PLAN_METERED_BASE) {
466    // Metered plan. Show low data and out of data.
467    return l10n_util::GetStringFUTF16(
468        IDS_NETWORK_DATA_AVAILABLE_MESSAGE,
469        UTF8ToUTF16(base::Int64ToString(remaining_mbytes())));
470  }
471  return string16();
472}
473
474std::string CellularDataPlan::GetUniqueIdentifier() const {
475  // A cellular plan is uniquely described by the union of name, type,
476  // start time, end time, and max bytes.
477  // So we just return a union of all these variables.
478  return plan_name + "|" +
479      base::Int64ToString(plan_type) + "|" +
480      base::Int64ToString(plan_start_time.ToInternalValue()) + "|" +
481      base::Int64ToString(plan_end_time.ToInternalValue()) + "|" +
482      base::Int64ToString(plan_data_bytes);
483}
484
485base::TimeDelta CellularDataPlan::remaining_time() const {
486  base::TimeDelta time = plan_end_time - base::Time::Now();
487  return time.InMicroseconds() < 0 ? base::TimeDelta() : time;
488}
489
490int64 CellularDataPlan::remaining_minutes() const {
491  return remaining_time().InMinutes();
492}
493
494int64 CellularDataPlan::remaining_data() const {
495  int64 data = plan_data_bytes - data_bytes_used;
496  return data < 0 ? 0 : data;
497}
498
499int64 CellularDataPlan::remaining_mbytes() const {
500  return remaining_data() / (1024 * 1024);
501}
502
503string16 CellularDataPlan::GetPlanExpiration() const {
504  return TimeFormat::TimeRemaining(remaining_time());
505}
506
507////////////////////////////////////////////////////////////////////////////////
508// CellularNetwork
509
510CellularNetwork::CellularNetwork()
511    : WirelessNetwork(),
512      activation_state_(ACTIVATION_STATE_UNKNOWN),
513      network_technology_(NETWORK_TECHNOLOGY_UNKNOWN),
514      roaming_state_(ROAMING_STATE_UNKNOWN),
515      connectivity_state_(CONN_STATE_UNKNOWN),
516      prl_version_(0) {
517  type_ = TYPE_CELLULAR;
518}
519
520CellularNetwork::CellularNetwork(const CellularNetwork& network)
521    : WirelessNetwork(network) {
522  activation_state_ = network.activation_state_;
523  network_technology_ = network.network_technology_;
524  roaming_state_ = network.roaming_state_;
525  connectivity_state_ = network.connectivity_state_;
526  service_name_ = network.service_name_;
527  operator_name_ = network.operator_name_;
528  operator_code_ = network.operator_code_;
529  payment_url_ = network.payment_url_;
530  meid_ = network.meid_;
531  imei_ = network.imei_;
532  imsi_ = network.imsi_;
533  esn_ = network.esn_;
534  mdn_ = network.mdn_;
535  min_ = network.min_;
536  model_id_ = network.model_id_;
537  manufacturer_ = network.manufacturer_;
538  firmware_revision_ = network.firmware_revision_;
539  hardware_revision_ = network.hardware_revision_;
540  last_update_ = network.last_update_;
541  prl_version_ = network.prl_version_;
542  type_ = TYPE_CELLULAR;
543}
544
545CellularNetwork::CellularNetwork(const ServiceInfo* service)
546    : WirelessNetwork(service) {
547  service_name_ = SafeString(service->name);
548  activation_state_ = service->activation_state;
549  network_technology_ = service->network_technology;
550  roaming_state_ = service->roaming_state;
551  connectivity_state_ = service->connectivity_state;
552  // Carrier Info
553  if (service->carrier_info) {
554    operator_name_ = SafeString(service->carrier_info->operator_name);
555    operator_code_ = SafeString(service->carrier_info->operator_code);
556    payment_url_ = SafeString(service->carrier_info->payment_url);
557  }
558  // Device Info
559  if (service->device_info) {
560    meid_ = SafeString(service->device_info->MEID);
561    imei_ = SafeString(service->device_info->IMEI);
562    imsi_ = SafeString(service->device_info->IMSI);
563    esn_ = SafeString(service->device_info->ESN);
564    mdn_ = SafeString(service->device_info->MDN);
565    min_ = SafeString(service->device_info->MIN);
566    model_id_ = SafeString(service->device_info->model_id);
567    manufacturer_ = SafeString(service->device_info->manufacturer);
568    firmware_revision_ = SafeString(service->device_info->firmware_revision);
569    hardware_revision_ = SafeString(service->device_info->hardware_revision);
570    last_update_ = SafeString(service->device_info->last_update);
571    prl_version_ = service->device_info->PRL_version;
572  }
573  type_ = TYPE_CELLULAR;
574}
575
576CellularNetwork::~CellularNetwork() {
577}
578
579bool CellularNetwork::StartActivation() const {
580  if (!EnsureCrosLoaded())
581    return false;
582  return ActivateCellularModem(service_path_.c_str(), NULL);
583}
584
585void CellularNetwork::Clear() {
586  WirelessNetwork::Clear();
587  activation_state_ = ACTIVATION_STATE_UNKNOWN;
588  roaming_state_ = ROAMING_STATE_UNKNOWN;
589  network_technology_ = NETWORK_TECHNOLOGY_UNKNOWN;
590  connectivity_state_ = CONN_STATE_UNKNOWN;
591  service_name_.clear();
592  operator_name_.clear();
593  operator_code_.clear();
594  payment_url_.clear();
595  meid_.clear();
596  imei_.clear();
597  imsi_.clear();
598  esn_.clear();
599  mdn_.clear();
600  min_.clear();
601  model_id_.clear();
602  manufacturer_.clear();
603  firmware_revision_.clear();
604  hardware_revision_.clear();
605  last_update_.clear();
606  prl_version_ = 0;
607}
608
609const CellularDataPlan* CellularNetwork::GetSignificantDataPlan() const {
610  const CellularDataPlan* significant = NULL;
611  const CellularDataPlanVector& plans = GetDataPlans();
612  for (CellularDataPlanVector::const_iterator iter = plans.begin();
613       iter != plans.end();
614       ++iter) {
615    // Set significant to the first plan or to first non metered base plan.
616    if (significant == NULL ||
617        significant->plan_type == CELLULAR_DATA_PLAN_METERED_BASE)
618      significant = *iter;
619  }
620  return significant;
621}
622
623CellularNetwork::DataLeft CellularNetwork::GetDataLeft() const {
624  // If we need a new plan, then there's no data.
625  if (needs_new_plan())
626    return DATA_NONE;
627  const CellularDataPlan* plan = GetSignificantDataPlan();
628  if (!plan)
629    return DATA_UNKNOWN;
630  if (plan->plan_type == CELLULAR_DATA_PLAN_UNLIMITED) {
631    base::TimeDelta remaining = plan->remaining_time();
632    if (remaining <= base::TimeDelta::FromSeconds(0))
633      return DATA_NONE;
634    if (remaining <= base::TimeDelta::FromSeconds(kCellularDataVeryLowSecs))
635      return DATA_VERY_LOW;
636    if (remaining <= base::TimeDelta::FromSeconds(kCellularDataLowSecs))
637      return DATA_LOW;
638    return DATA_NORMAL;
639  } else if (plan->plan_type == CELLULAR_DATA_PLAN_METERED_PAID ||
640             plan->plan_type == CELLULAR_DATA_PLAN_METERED_BASE) {
641    int64 remaining = plan->remaining_data();
642    if (remaining <= 0)
643      return DATA_NONE;
644    if (remaining <= kCellularDataVeryLowBytes)
645      return DATA_VERY_LOW;
646    // For base plans, we do not care about low data.
647    if (remaining <= kCellularDataLowBytes &&
648        plan->plan_type != CELLULAR_DATA_PLAN_METERED_BASE)
649      return DATA_LOW;
650    return DATA_NORMAL;
651  }
652  return DATA_UNKNOWN;
653}
654
655std::string CellularNetwork::GetNetworkTechnologyString() const {
656  // No need to localize these cellular technology abbreviations.
657  switch (network_technology_) {
658    case NETWORK_TECHNOLOGY_1XRTT:
659      return "1xRTT";
660      break;
661    case NETWORK_TECHNOLOGY_EVDO:
662      return "EVDO";
663      break;
664    case NETWORK_TECHNOLOGY_GPRS:
665      return "GPRS";
666      break;
667    case NETWORK_TECHNOLOGY_EDGE:
668      return "EDGE";
669      break;
670    case NETWORK_TECHNOLOGY_UMTS:
671      return "UMTS";
672      break;
673    case NETWORK_TECHNOLOGY_HSPA:
674      return "HSPA";
675      break;
676    case NETWORK_TECHNOLOGY_HSPA_PLUS:
677      return "HSPA Plus";
678      break;
679    case NETWORK_TECHNOLOGY_LTE:
680      return "LTE";
681      break;
682    case NETWORK_TECHNOLOGY_LTE_ADVANCED:
683      return "LTE Advanced";
684      break;
685    default:
686      return l10n_util::GetStringUTF8(
687          IDS_CHROMEOS_NETWORK_CELLULAR_TECHNOLOGY_UNKNOWN);
688      break;
689  }
690}
691
692std::string CellularNetwork::GetConnectivityStateString() const {
693  // These strings do not appear in the UI, so no need to localize them
694  switch (connectivity_state_) {
695    case CONN_STATE_UNRESTRICTED:
696      return "unrestricted";
697      break;
698    case CONN_STATE_RESTRICTED:
699      return "restricted";
700      break;
701    case CONN_STATE_NONE:
702      return "none";
703      break;
704    case CONN_STATE_UNKNOWN:
705    default:
706      return "unknown";
707  }
708}
709
710std::string CellularNetwork::ActivationStateToString(
711    ActivationState activation_state) {
712  switch (activation_state) {
713    case ACTIVATION_STATE_ACTIVATED:
714      return l10n_util::GetStringUTF8(
715          IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATED);
716      break;
717    case ACTIVATION_STATE_ACTIVATING:
718      return l10n_util::GetStringUTF8(
719          IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATING);
720      break;
721    case ACTIVATION_STATE_NOT_ACTIVATED:
722      return l10n_util::GetStringUTF8(
723          IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_NOT_ACTIVATED);
724      break;
725    case ACTIVATION_STATE_PARTIALLY_ACTIVATED:
726      return l10n_util::GetStringUTF8(
727          IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_PARTIALLY_ACTIVATED);
728      break;
729    default:
730      return l10n_util::GetStringUTF8(
731          IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_UNKNOWN);
732      break;
733  }
734}
735
736std::string CellularNetwork::GetActivationStateString() const {
737  return ActivationStateToString(this->activation_state_);
738}
739
740std::string CellularNetwork::GetRoamingStateString() const {
741  switch (this->roaming_state_) {
742    case ROAMING_STATE_HOME:
743      return l10n_util::GetStringUTF8(
744          IDS_CHROMEOS_NETWORK_ROAMING_STATE_HOME);
745      break;
746    case ROAMING_STATE_ROAMING:
747      return l10n_util::GetStringUTF8(
748          IDS_CHROMEOS_NETWORK_ROAMING_STATE_ROAMING);
749      break;
750    default:
751      return l10n_util::GetStringUTF8(
752          IDS_CHROMEOS_NETWORK_ROAMING_STATE_UNKNOWN);
753      break;
754  };
755}
756
757
758////////////////////////////////////////////////////////////////////////////////
759// WifiNetwork
760
761WifiNetwork::WifiNetwork()
762    : WirelessNetwork(),
763      encryption_(SECURITY_NONE) {
764  type_ = TYPE_WIFI;
765}
766
767WifiNetwork::WifiNetwork(const WifiNetwork& network)
768    : WirelessNetwork(network) {
769  encryption_ = network.encryption_;
770  passphrase_ = network.passphrase_;
771  passphrase_required_ = network.passphrase_required_;
772  identity_ = network.identity_;
773  cert_path_ = network.cert_path_;
774}
775
776WifiNetwork::WifiNetwork(const ServiceInfo* service)
777    : WirelessNetwork(service) {
778  encryption_ = service->security;
779  // TODO(stevenjb): Remove this if/when flimflam handles multiple profiles.
780  if (UserManager::Get()->current_user_is_owner())
781    passphrase_ = SafeString(service->passphrase);
782  else
783    passphrase_.clear();
784  passphrase_required_ = service->passphrase_required;
785  identity_ = SafeString(service->identity);
786  cert_path_ = SafeString(service->cert_path);
787  type_ = TYPE_WIFI;
788}
789
790void WifiNetwork::Clear() {
791  WirelessNetwork::Clear();
792  encryption_ = SECURITY_NONE;
793  passphrase_.clear();
794  identity_.clear();
795  cert_path_.clear();
796}
797
798std::string WifiNetwork::GetEncryptionString() {
799  switch (encryption_) {
800    case SECURITY_UNKNOWN:
801      break;
802    case SECURITY_NONE:
803      return "";
804    case SECURITY_WEP:
805      return "WEP";
806    case SECURITY_WPA:
807      return "WPA";
808    case SECURITY_RSN:
809      return "RSN";
810    case SECURITY_8021X:
811      return "8021X";
812  }
813  return "Unknown";
814}
815
816bool WifiNetwork::IsPassphraseRequired() const {
817  // TODO(stevenjb): Remove error_ tests when fixed in flimflam
818  // (http://crosbug.com/10135).
819  if (error_ == ERROR_BAD_PASSPHRASE || error_ == ERROR_BAD_WEPKEY)
820    return true;
821  return passphrase_required_;
822}
823
824// Parse 'path' to determine if the certificate is stored in a pkcs#11 device.
825// flimflam recognizes the string "SETTINGS:" to specify authentication
826// parameters. 'key_id=' indicates that the certificate is stored in a pkcs#11
827// device. See src/third_party/flimflam/files/doc/service-api.txt.
828bool WifiNetwork::IsCertificateLoaded() const {
829  static const std::string settings_string("SETTINGS:");
830  static const std::string pkcs11_key("key_id");
831  if (cert_path_.find(settings_string) == 0) {
832    std::string::size_type idx = cert_path_.find(pkcs11_key);
833    if (idx != std::string::npos)
834      idx = cert_path_.find_first_not_of(kWhitespaceASCII,
835                                         idx + pkcs11_key.length());
836    if (idx != std::string::npos && cert_path_[idx] == '=')
837      return true;
838  }
839  return false;
840}
841
842////////////////////////////////////////////////////////////////////////////////
843// NetworkLibrary
844
845class NetworkLibraryImpl : public NetworkLibrary  {
846 public:
847  NetworkLibraryImpl()
848      : network_manager_monitor_(NULL),
849        data_plan_monitor_(NULL),
850        ethernet_(NULL),
851        wifi_(NULL),
852        cellular_(NULL),
853        available_devices_(0),
854        enabled_devices_(0),
855        connected_devices_(0),
856        wifi_scanning_(false),
857        offline_mode_(false),
858        is_locked_(false),
859        update_task_(NULL) {
860    if (EnsureCrosLoaded()) {
861      Init();
862      network_manager_monitor_ =
863          MonitorNetworkManager(&NetworkManagerStatusChangedHandler,
864                                this);
865      data_plan_monitor_ = MonitorCellularDataPlan(&DataPlanUpdateHandler,
866                                                   this);
867      network_login_observer_.reset(new NetworkLoginObserver(this));
868    } else {
869      InitTestData();
870    }
871  }
872
873  ~NetworkLibraryImpl() {
874    network_manager_observers_.Clear();
875    if (network_manager_monitor_)
876      DisconnectPropertyChangeMonitor(network_manager_monitor_);
877    data_plan_observers_.Clear();
878    if (data_plan_monitor_)
879      DisconnectDataPlanUpdateMonitor(data_plan_monitor_);
880    STLDeleteValues(&network_observers_);
881    ClearNetworks();
882  }
883
884  virtual void AddNetworkManagerObserver(NetworkManagerObserver* observer) {
885    if (!network_manager_observers_.HasObserver(observer))
886      network_manager_observers_.AddObserver(observer);
887  }
888
889  void NetworkStatusChanged() {
890    DVLOG(1) << "Got NetworkStatusChanged";
891    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
892    if (update_task_) {
893      DVLOG(1) << "  found previous task";
894      update_task_->Cancel();
895    }
896    update_task_ =
897        NewRunnableMethod(this,
898                          &NetworkLibraryImpl::UpdateNetworkManagerStatus);
899    BrowserThread::PostDelayedTask(
900        BrowserThread::UI, FROM_HERE, update_task_,
901        kNetworkUpdateDelayMs);
902  }
903
904  virtual void RemoveNetworkManagerObserver(NetworkManagerObserver* observer) {
905    network_manager_observers_.RemoveObserver(observer);
906  }
907
908  virtual void AddNetworkObserver(const std::string& service_path,
909                                  NetworkObserver* observer) {
910    DCHECK(observer);
911    if (!EnsureCrosLoaded())
912      return;
913    // First, add the observer to the callback map.
914    NetworkObserverMap::iterator iter = network_observers_.find(service_path);
915    NetworkObserverList* oblist;
916    if (iter != network_observers_.end()) {
917      oblist = iter->second;
918    } else {
919      std::pair<NetworkObserverMap::iterator, bool> inserted =
920        network_observers_.insert(
921            std::make_pair<std::string, NetworkObserverList*>(
922                service_path,
923                new NetworkObserverList(this, service_path)));
924      oblist = inserted.first->second;
925    }
926    if (!oblist->HasObserver(observer))
927      oblist->AddObserver(observer);
928  }
929
930  virtual void RemoveNetworkObserver(const std::string& service_path,
931                                     NetworkObserver* observer) {
932    DCHECK(observer);
933    DCHECK(service_path.size());
934    NetworkObserverMap::iterator map_iter =
935        network_observers_.find(service_path);
936    if (map_iter != network_observers_.end()) {
937      map_iter->second->RemoveObserver(observer);
938      if (!map_iter->second->size()) {
939        delete map_iter->second;
940        network_observers_.erase(map_iter++);
941      }
942    }
943  }
944
945  virtual void RemoveObserverForAllNetworks(NetworkObserver* observer) {
946    DCHECK(observer);
947    NetworkObserverMap::iterator map_iter = network_observers_.begin();
948    while (map_iter != network_observers_.end()) {
949      map_iter->second->RemoveObserver(observer);
950      if (!map_iter->second->size()) {
951        delete map_iter->second;
952        network_observers_.erase(map_iter++);
953      } else {
954        ++map_iter;
955      }
956    }
957  }
958
959  virtual void Lock() {
960    if (is_locked_)
961      return;
962    is_locked_ = true;
963    NotifyNetworkManagerChanged();
964  }
965
966  virtual void Unlock() {
967    DCHECK(is_locked_);
968    if (!is_locked_)
969      return;
970    is_locked_ = false;
971    NotifyNetworkManagerChanged();
972  }
973
974  virtual bool IsLocked() {
975    return is_locked_;
976  }
977
978  virtual void AddCellularDataPlanObserver(CellularDataPlanObserver* observer) {
979    if (!data_plan_observers_.HasObserver(observer))
980      data_plan_observers_.AddObserver(observer);
981  }
982
983  virtual void RemoveCellularDataPlanObserver(
984      CellularDataPlanObserver* observer) {
985    data_plan_observers_.RemoveObserver(observer);
986  }
987
988  virtual const EthernetNetwork* ethernet_network() const { return ethernet_; }
989  virtual bool ethernet_connecting() const {
990    return ethernet_ ? ethernet_->connecting() : false;
991  }
992  virtual bool ethernet_connected() const {
993    return ethernet_ ? ethernet_->connected() : false;
994  }
995
996  virtual const WifiNetwork* wifi_network() const { return wifi_; }
997  virtual bool wifi_connecting() const {
998    return wifi_ ? wifi_->connecting() : false;
999  }
1000  virtual bool wifi_connected() const {
1001    return wifi_ ? wifi_->connected() : false;
1002  }
1003
1004  virtual const CellularNetwork* cellular_network() const { return cellular_; }
1005  virtual bool cellular_connecting() const {
1006    return cellular_ ? cellular_->connecting() : false;
1007  }
1008  virtual bool cellular_connected() const {
1009    return cellular_ ? cellular_->connected() : false;
1010  }
1011
1012  bool Connected() const {
1013    return ethernet_connected() || wifi_connected() || cellular_connected();
1014  }
1015
1016  bool Connecting() const {
1017    return ethernet_connecting() || wifi_connecting() || cellular_connecting();
1018  }
1019
1020  const std::string& IPAddress() const {
1021    // Returns IP address for the active network.
1022    const Network* active = active_network();
1023    if (active != NULL)
1024      return active->ip_address();
1025    if (ethernet_)
1026      return ethernet_->ip_address();
1027    static std::string null_address("0.0.0.0");
1028    return null_address;
1029  }
1030
1031  virtual const WifiNetworkVector& wifi_networks() const {
1032    return wifi_networks_;
1033  }
1034
1035  virtual const WifiNetworkVector& remembered_wifi_networks() const {
1036    return remembered_wifi_networks_;
1037  }
1038
1039  virtual const CellularNetworkVector& cellular_networks() const {
1040    return cellular_networks_;
1041  }
1042
1043  /////////////////////////////////////////////////////////////////////////////
1044
1045  virtual WifiNetwork* FindWifiNetworkByPath(
1046      const std::string& path) {
1047    return GetWirelessNetworkByPath(wifi_networks_, path);
1048  }
1049
1050  virtual CellularNetwork* FindCellularNetworkByPath(
1051      const std::string& path) {
1052    return GetWirelessNetworkByPath(cellular_networks_, path);
1053  }
1054
1055  virtual void RequestWifiScan() {
1056    if (EnsureCrosLoaded() && wifi_enabled()) {
1057      wifi_scanning_ = true;  // Cleared in UpdateNetworkManagerStatus.
1058      RequestScan(TYPE_WIFI);
1059    }
1060  }
1061
1062  virtual bool GetWifiAccessPoints(WifiAccessPointVector* result) {
1063    if (!EnsureCrosLoaded())
1064      return false;
1065    DeviceNetworkList* network_list = GetDeviceNetworkList();
1066    if (network_list == NULL)
1067      return false;
1068    result->clear();
1069    result->reserve(network_list->network_size);
1070    const base::Time now = base::Time::Now();
1071    for (size_t i = 0; i < network_list->network_size; ++i) {
1072      DCHECK(network_list->networks[i].address);
1073      DCHECK(network_list->networks[i].name);
1074      WifiAccessPoint ap;
1075      ap.mac_address = SafeString(network_list->networks[i].address);
1076      ap.name = SafeString(network_list->networks[i].name);
1077      ap.timestamp = now -
1078          base::TimeDelta::FromSeconds(network_list->networks[i].age_seconds);
1079      ap.signal_strength = network_list->networks[i].strength;
1080      ap.channel = network_list->networks[i].channel;
1081      result->push_back(ap);
1082    }
1083    FreeDeviceNetworkList(network_list);
1084    return true;
1085  }
1086
1087  virtual bool ConnectToWifiNetwork(WifiNetwork* network,
1088                                    const std::string& password,
1089                                    const std::string& identity,
1090                                    const std::string& certpath) {
1091    DCHECK(network);
1092    if (!EnsureCrosLoaded())
1093      return true;  // No library loaded, don't trigger a retry attempt.
1094    // TODO(ers) make wifi the highest priority service type
1095    if (ConnectToNetworkWithCertInfo(network->service_path().c_str(),
1096        password.empty() ? NULL : password.c_str(),
1097        identity.empty() ? NULL : identity.c_str(),
1098        certpath.empty() ? NULL : certpath.c_str())) {
1099      // Update local cache and notify listeners.
1100      WifiNetwork* wifi = GetWirelessNetworkByPath(
1101          wifi_networks_, network->service_path());
1102      if (wifi) {
1103        wifi->set_passphrase(password);
1104        wifi->set_identity(identity);
1105        wifi->set_cert_path(certpath);
1106        wifi->set_connecting(true);
1107        wifi_ = wifi;
1108      }
1109      NotifyNetworkManagerChanged();
1110      return true;
1111    } else {
1112      // The only likely cause for an immediate failure is a badly formatted
1113      // passphrase. TODO(stevenjb): get error information from libcros
1114      // and call set_error correctly. crosbug.com/9538.
1115      network->set_error(ERROR_BAD_PASSPHRASE);
1116      return false;  // Immediate failure.
1117    }
1118  }
1119
1120  virtual bool ConnectToWifiNetwork(ConnectionSecurity security,
1121                                    const std::string& ssid,
1122                                    const std::string& password,
1123                                    const std::string& identity,
1124                                    const std::string& certpath,
1125                                    bool auto_connect) {
1126    if (!EnsureCrosLoaded())
1127      return true;  // No library loaded, don't trigger a retry attempt.
1128    // First create a service from hidden network.
1129    ServiceInfo* service = GetWifiService(ssid.c_str(), security);
1130    if (service) {
1131      // Set auto-connect.
1132      SetAutoConnect(service->service_path, auto_connect);
1133      // Now connect to that service.
1134      // TODO(ers) make wifi the highest priority service type
1135      bool res = ConnectToNetworkWithCertInfo(
1136          service->service_path,
1137          password.empty() ? NULL : password.c_str(),
1138          identity.empty() ? NULL : identity.c_str(),
1139          certpath.empty() ? NULL : certpath.c_str());
1140
1141      // Clean up ServiceInfo object.
1142      FreeServiceInfo(service);
1143      return res;
1144    } else {
1145      LOG(WARNING) << "Cannot find hidden network: " << ssid;
1146      // TODO(chocobo): Show error message.
1147      return false;  // Immediate failure.
1148    }
1149  }
1150
1151  virtual bool ConnectToCellularNetwork(const CellularNetwork* network) {
1152    DCHECK(network);
1153    if (!EnsureCrosLoaded())
1154      return true;  // No library loaded, don't trigger a retry attempt.
1155    // TODO(ers) make cellular the highest priority service type
1156    if (network && ConnectToNetwork(network->service_path().c_str(), NULL)) {
1157      // Update local cache and notify listeners.
1158      CellularNetwork* cellular = GetWirelessNetworkByPath(
1159          cellular_networks_, network->service_path());
1160      if (cellular) {
1161        cellular->set_connecting(true);
1162        cellular_ = cellular;
1163      }
1164      NotifyNetworkManagerChanged();
1165      return true;
1166    } else {
1167      return false;  // Immediate failure.
1168    }
1169  }
1170
1171  virtual void RefreshCellularDataPlans(const CellularNetwork* network) {
1172    DCHECK(network);
1173    if (!EnsureCrosLoaded() || !network)
1174      return;
1175    RequestCellularDataPlanUpdate(network->service_path().c_str());
1176  }
1177
1178  // Records information that cellular play payment had happened.
1179  virtual void SignalCellularPlanPayment() {
1180    DCHECK(!HasRecentCellularPlanPayment());
1181    cellular_plan_payment_time_ = base::Time::Now();
1182  }
1183
1184  // Returns true if cellular plan payment had been recorded recently.
1185  virtual bool HasRecentCellularPlanPayment() {
1186    return (base::Time::Now() -
1187              cellular_plan_payment_time_).InHours() < kRecentPlanPaymentHours;
1188  }
1189
1190  virtual void DisconnectFromWirelessNetwork(const WirelessNetwork* network) {
1191    DCHECK(network);
1192    if (!EnsureCrosLoaded() || !network)
1193      return;
1194    // TODO(ers) restore default service type priority ordering?
1195    if (DisconnectFromNetwork(network->service_path().c_str())) {
1196      // Update local cache and notify listeners.
1197      if (network->type() == TYPE_WIFI) {
1198        WifiNetwork* wifi = GetWirelessNetworkByPath(
1199            wifi_networks_, network->service_path());
1200        if (wifi) {
1201          wifi->set_connected(false);
1202          wifi_ = NULL;
1203        }
1204      } else if (network->type() == TYPE_CELLULAR) {
1205        CellularNetwork* cellular = GetWirelessNetworkByPath(
1206            cellular_networks_, network->service_path());
1207        if (cellular) {
1208          cellular->set_connected(false);
1209          cellular_ = NULL;
1210        }
1211      }
1212      NotifyNetworkManagerChanged();
1213    }
1214  }
1215
1216  virtual void SaveCellularNetwork(const CellularNetwork* network) {
1217    DCHECK(network);
1218    // Update the cellular network with libcros.
1219    if (!EnsureCrosLoaded() || !network)
1220      return;
1221    CellularNetwork* cellular =
1222        GetWirelessNetworkByPath(cellular_networks_,
1223                                 network->service_path());
1224    if (!cellular) {
1225      LOG(WARNING) << "Save to unknown network: " << network->service_path();
1226      return;
1227    }
1228
1229    // Immediately update properties in the cached structure.
1230    cellular->set_auto_connect(network->auto_connect());
1231    // Update libcros.
1232    SetAutoConnect(network->service_path().c_str(), network->auto_connect());
1233  }
1234
1235  virtual void SaveWifiNetwork(const WifiNetwork* network) {
1236    DCHECK(network);
1237    // Update the wifi network with libcros.
1238    if (!EnsureCrosLoaded() || !network)
1239      return;
1240    WifiNetwork* wifi = GetWirelessNetworkByPath(wifi_networks_,
1241                                                 network->service_path());
1242    if (!wifi) {
1243      LOG(WARNING) << "Save to unknown network: " << network->service_path();
1244      return;
1245    }
1246    // Immediately update properties in the cached structure.
1247    wifi->set_passphrase(network->passphrase());
1248    wifi->set_identity(network->identity());
1249    wifi->set_cert_path(network->cert_path());
1250    wifi->set_auto_connect(network->auto_connect());
1251    // Update libcros.
1252    const char* service_path = network->service_path().c_str();
1253    SetPassphrase(service_path, network->passphrase().c_str());
1254    SetIdentity(service_path, network->identity().c_str());
1255    SetCertPath(service_path, network->cert_path().c_str());
1256    SetAutoConnect(service_path, network->auto_connect());
1257  }
1258
1259  virtual void ForgetWifiNetwork(const std::string& service_path) {
1260    if (!EnsureCrosLoaded())
1261      return;
1262    // NOTE: service paths for remembered wifi networks do not match the
1263    // service paths in wifi_networks_; calling a libcros funtion that
1264    // operates on the wifi_networks_ list with this service_path will
1265    // trigger a crash because the DBUS path does not exist.
1266    // TODO(stevenjb): modify libcros to warn and fail instead of crash.
1267    // https://crosbug.com/9295
1268    if (DeleteRememberedService(service_path.c_str())) {
1269      // Update local cache and notify listeners.
1270      for (WifiNetworkVector::iterator iter =
1271               remembered_wifi_networks_.begin();
1272          iter != remembered_wifi_networks_.end();
1273          ++iter) {
1274        if ((*iter)->service_path() == service_path) {
1275          delete (*iter);
1276          remembered_wifi_networks_.erase(iter);
1277          break;
1278        }
1279      }
1280      NotifyNetworkManagerChanged();
1281    }
1282  }
1283
1284  virtual bool ethernet_available() const {
1285    return available_devices_ & (1 << TYPE_ETHERNET);
1286  }
1287  virtual bool wifi_available() const {
1288    return available_devices_ & (1 << TYPE_WIFI);
1289  }
1290  virtual bool cellular_available() const {
1291    return available_devices_ & (1 << TYPE_CELLULAR);
1292  }
1293
1294  virtual bool ethernet_enabled() const {
1295    return enabled_devices_ & (1 << TYPE_ETHERNET);
1296  }
1297  virtual bool wifi_enabled() const {
1298    return enabled_devices_ & (1 << TYPE_WIFI);
1299  }
1300  virtual bool cellular_enabled() const {
1301    return enabled_devices_ & (1 << TYPE_CELLULAR);
1302  }
1303
1304  virtual bool wifi_scanning() const {
1305    return wifi_scanning_;
1306  }
1307
1308  virtual bool offline_mode() const { return offline_mode_; }
1309
1310  virtual const Network* active_network() const {
1311    if (ethernet_ && ethernet_->is_active())
1312      return ethernet_;
1313    if (wifi_ && wifi_->is_active())
1314      return wifi_;
1315    if (cellular_ && cellular_->is_active())
1316      return cellular_;
1317    // Due to bug chromium-os:9310, if no active network is found,
1318    // use the first connected.
1319    // TODO(chocobo): Remove when bug 9310 is fixed.
1320    // START BUG 9310 WORKAROUND
1321    if (ethernet_ && ethernet_->connected()) {
1322      ethernet_->set_active(true);
1323      return ethernet_;
1324    }
1325    if (wifi_ && wifi_->connected()) {
1326      wifi_->set_active(true);
1327      return wifi_;
1328    }
1329    if (cellular_ && cellular_->connected()) {
1330      cellular_->set_active(true);
1331      return cellular_;
1332    }
1333    // END BUG 9310 WORKAROUND
1334    return NULL;
1335  }
1336
1337  virtual void EnableEthernetNetworkDevice(bool enable) {
1338    if (is_locked_)
1339      return;
1340    EnableNetworkDeviceType(TYPE_ETHERNET, enable);
1341  }
1342
1343  virtual void EnableWifiNetworkDevice(bool enable) {
1344    if (is_locked_)
1345      return;
1346    EnableNetworkDeviceType(TYPE_WIFI, enable);
1347  }
1348
1349  virtual void EnableCellularNetworkDevice(bool enable) {
1350    if (is_locked_)
1351      return;
1352    EnableNetworkDeviceType(TYPE_CELLULAR, enable);
1353  }
1354
1355  virtual void EnableOfflineMode(bool enable) {
1356    if (!EnsureCrosLoaded())
1357      return;
1358
1359    // If network device is already enabled/disabled, then don't do anything.
1360    if (enable && offline_mode_) {
1361      VLOG(1) << "Trying to enable offline mode when it's already enabled.";
1362      return;
1363    }
1364    if (!enable && !offline_mode_) {
1365      VLOG(1) << "Trying to disable offline mode when it's already disabled.";
1366      return;
1367    }
1368
1369    if (SetOfflineMode(enable)) {
1370      offline_mode_ = enable;
1371    }
1372  }
1373
1374  virtual NetworkIPConfigVector GetIPConfigs(const std::string& device_path,
1375                                             std::string* hardware_address) {
1376    hardware_address->clear();
1377    NetworkIPConfigVector ipconfig_vector;
1378    if (EnsureCrosLoaded() && !device_path.empty()) {
1379      IPConfigStatus* ipconfig_status = ListIPConfigs(device_path.c_str());
1380      if (ipconfig_status) {
1381        for (int i = 0; i < ipconfig_status->size; i++) {
1382          IPConfig ipconfig = ipconfig_status->ips[i];
1383          ipconfig_vector.push_back(
1384              NetworkIPConfig(device_path, ipconfig.type, ipconfig.address,
1385                              ipconfig.netmask, ipconfig.gateway,
1386                              ipconfig.name_servers));
1387        }
1388        *hardware_address = ipconfig_status->hardware_address;
1389        FreeIPConfigStatus(ipconfig_status);
1390        // Sort the list of ip configs by type.
1391        std::sort(ipconfig_vector.begin(), ipconfig_vector.end());
1392      }
1393    }
1394    return ipconfig_vector;
1395  }
1396
1397  virtual std::string GetHtmlInfo(int refresh) {
1398    std::string output;
1399    output.append("<html><head><title>About Network</title>");
1400    if (refresh > 0)
1401      output.append("<meta http-equiv=\"refresh\" content=\"" +
1402          base::IntToString(refresh) + "\"/>");
1403    output.append("</head><body>");
1404    if (refresh > 0) {
1405      output.append("(Auto-refreshing page every " +
1406                    base::IntToString(refresh) + "s)");
1407    } else {
1408      output.append("(To auto-refresh this page: about:network/&lt;secs&gt;)");
1409    }
1410
1411    if (ethernet_enabled()) {
1412      output.append("<h3>Ethernet:</h3><table border=1>");
1413      if (ethernet_) {
1414        output.append("<tr>" + ToHtmlTableHeader(ethernet_) + "</tr>");
1415        output.append("<tr>" + ToHtmlTableRow(ethernet_) + "</tr>");
1416      }
1417    }
1418
1419    if (wifi_enabled()) {
1420      output.append("</table><h3>Wifi:</h3><table border=1>");
1421      for (size_t i = 0; i < wifi_networks_.size(); ++i) {
1422        if (i == 0)
1423          output.append("<tr>" + ToHtmlTableHeader(wifi_networks_[i]) +
1424                        "</tr>");
1425        output.append("<tr>" + ToHtmlTableRow(wifi_networks_[i]) + "</tr>");
1426      }
1427    }
1428
1429    if (cellular_enabled()) {
1430      output.append("</table><h3>Cellular:</h3><table border=1>");
1431      for (size_t i = 0; i < cellular_networks_.size(); ++i) {
1432        if (i == 0)
1433          output.append("<tr>" + ToHtmlTableHeader(cellular_networks_[i]) +
1434                        "</tr>");
1435        output.append("<tr>" + ToHtmlTableRow(cellular_networks_[i]) + "</tr>");
1436      }
1437    }
1438
1439    output.append("</table><h3>Remembered Wifi:</h3><table border=1>");
1440    for (size_t i = 0; i < remembered_wifi_networks_.size(); ++i) {
1441      if (i == 0)
1442        output.append(
1443            "<tr>" + ToHtmlTableHeader(remembered_wifi_networks_[i]) +
1444            "</tr>");
1445      output.append("<tr>" + ToHtmlTableRow(remembered_wifi_networks_[i]) +
1446          "</tr>");
1447    }
1448
1449    output.append("</table></body></html>");
1450    return output;
1451  }
1452
1453 private:
1454
1455  class NetworkObserverList : public ObserverList<NetworkObserver> {
1456   public:
1457    NetworkObserverList(NetworkLibraryImpl* library,
1458                        const std::string& service_path) {
1459      network_monitor_ = MonitorNetworkService(&NetworkStatusChangedHandler,
1460                                               service_path.c_str(),
1461                                               library);
1462    }
1463
1464    virtual ~NetworkObserverList() {
1465      if (network_monitor_)
1466        DisconnectPropertyChangeMonitor(network_monitor_);
1467    }
1468
1469   private:
1470    static void NetworkStatusChangedHandler(void* object,
1471                                            const char* path,
1472                                            const char* key,
1473                                            const Value* value) {
1474      NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
1475      DCHECK(networklib);
1476      networklib->UpdateNetworkStatus(path, key, value);
1477    }
1478    PropertyChangeMonitor network_monitor_;
1479  };
1480
1481  typedef std::map<std::string, NetworkObserverList*> NetworkObserverMap;
1482
1483  static void NetworkManagerStatusChangedHandler(void* object,
1484                                                 const char* path,
1485                                                 const char* key,
1486                                                 const Value* value) {
1487    NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
1488    DCHECK(networklib);
1489    networklib->NetworkStatusChanged();
1490  }
1491
1492  static void DataPlanUpdateHandler(void* object,
1493                                    const char* modem_service_path,
1494                                    const CellularDataPlanList* dataplan) {
1495    NetworkLibraryImpl* networklib = static_cast<NetworkLibraryImpl*>(object);
1496    if (!networklib || !networklib->cellular_network()) {
1497      // This might happen if an update is received as we are shutting down.
1498      return;
1499    }
1500    // Store data plan for currently connected cellular network.
1501    if (networklib->cellular_network()->service_path()
1502        .compare(modem_service_path) == 0) {
1503      if (dataplan != NULL) {
1504        networklib->UpdateCellularDataPlan(dataplan);
1505      }
1506    }
1507  }
1508
1509  void ParseSystem(SystemInfo* system) {
1510    std::string prev_cellular_service_path = cellular_ ?
1511        cellular_->service_path() : std::string();
1512    bool prev_cellular_connected = cellular_ ?
1513        cellular_->connected() : false;
1514    std::vector<CellularDataPlan> prev_cellular_data_plans;
1515    if (cellular_) {
1516      const CellularDataPlanVector& plans = cellular_->GetDataPlans();
1517      for (CellularDataPlanVector::const_iterator iter = plans.begin();
1518           iter != plans.end();
1519           ++iter) {
1520        prev_cellular_data_plans.push_back(**iter);
1521      }
1522    }
1523
1524    ClearNetworks();
1525    available_devices_ = system->available_technologies;
1526    enabled_devices_ = system->enabled_technologies;
1527    connected_devices_ = system->connected_technologies;
1528    offline_mode_ = system->offline_mode;
1529
1530    DVLOG(1) << "ParseSystem:";
1531    for (int i = 0; i < system->service_size; i++) {
1532      const ServiceInfo* service = system->GetServiceInfo(i);
1533      DVLOG(1) << "  (" << service->type << ") " << service->name
1534               << " mode=" << service->mode
1535               << " state=" << service->state
1536               << " sec=" << service->security
1537               << " req=" << service->passphrase_required
1538               << " pass=" << service->passphrase
1539               << " id=" << service->identity
1540               << " certpath=" << service->cert_path
1541               << " str=" << service->strength
1542               << " fav=" << service->favorite
1543               << " auto=" << service->auto_connect
1544               << " is_active=" << service->is_active
1545               << " error=" << service->error;
1546      // Once a connected ethernet service is found, disregard other ethernet
1547      // services that are also found
1548      if (service->type == TYPE_ETHERNET) {
1549        // There could be multiple ethernet services (eth0, dummy0, etc)
1550        // In this case, once you find a connected service, ignore the
1551        // other ones.  Otherwise, you may choose an ethernet service
1552        // that is not connected.
1553        if (ethernet_enabled() &&
1554            (ethernet_ == NULL || !(ethernet_->connected()))) {
1555          // If previous ethernet was previously created, free it first
1556          if (ethernet_ != NULL)
1557            delete ethernet_;
1558          ethernet_ = new EthernetNetwork(service);
1559        }
1560      } else if (service->type == TYPE_WIFI) {
1561        // Sometimes flimflam still returns wifi networks when disabled.
1562        // We don't want to show these in the UI.
1563        if (wifi_enabled())
1564          wifi_networks_.push_back(new WifiNetwork(service));
1565      } else if (service->type == TYPE_CELLULAR) {
1566        // Sometimes flimflam still returns cellular networks when disabled.
1567        // We don't want to show these in the UI.
1568        if (cellular_enabled())
1569          cellular_networks_.push_back(new CellularNetwork(service));
1570      }
1571    }
1572
1573    // Create placeholder network for ethernet even if the service is not
1574    // detected at this moment.
1575    if (!ethernet_)
1576      ethernet_ = new EthernetNetwork();
1577
1578    DVLOG(1) << "Remembered networks:";
1579    for (int i = 0; i < system->remembered_service_size; i++) {
1580      const ServiceInfo* service = system->GetRememberedServiceInfo(i);
1581      // All services in the remembered list are "favorites" even though
1582      // they do not explicitly set the "favorite" property.
1583      DVLOG(1) << "  (" << service->type << ") " << service->name
1584               << " mode=" << service->mode
1585               << " sec=" << service->security
1586               << " pass=" << service->passphrase
1587               << " id=" << service->identity
1588               << " certpath=" << service->cert_path
1589               << " auto=" << service->auto_connect;
1590      if (service->type == TYPE_WIFI) {
1591        remembered_wifi_networks_.push_back(new WifiNetwork(service));
1592      }
1593    }
1594
1595    // Find the active wifi network (if any).
1596    wifi_ = NULL;
1597    for (size_t i = 0; i < wifi_networks_.size(); i++) {
1598      if (wifi_networks_[i]->connecting_or_connected()) {
1599        wifi_ = wifi_networks_[i];
1600        break;  // There is only one connected or connecting wifi network.
1601      }
1602    }
1603
1604    // Find the active cellular network (if any).
1605    cellular_ = NULL;
1606    for (size_t i = 0; i < cellular_networks_.size(); i++) {
1607      if (cellular_networks_[i]->connecting_or_connected()) {
1608        cellular_ = cellular_networks_[i];
1609        // If refreshing previous cellular, then copy over prev data plans.
1610        if (cellular_->service_path() == prev_cellular_service_path) {
1611          for (std::vector<CellularDataPlan>::iterator iter =
1612                   prev_cellular_data_plans.begin();
1613               iter != prev_cellular_data_plans.end();
1614               ++iter) {
1615            cellular_->data_plans_.push_back(new CellularDataPlan(*iter));
1616          }
1617        } else if (!prev_cellular_connected && cellular_->connected()) {
1618          // If new cellular, then request update of the data plan list.
1619          RefreshCellularDataPlans(cellular_);
1620        }
1621        break;  // There is only one connected or connecting cellular network.
1622      }
1623    }
1624
1625    wifi_scanning_ = false;
1626    for (int i = 0; i < system->device_size; i++) {
1627      const DeviceInfo* device = system->GetDeviceInfo(i);
1628      if (device->type == TYPE_WIFI && device->scanning)
1629        wifi_scanning_ = true;
1630    }
1631  }
1632
1633  void Init() {
1634    // First, get the currently available networks. This data is cached
1635    // on the connman side, so the call should be quick.
1636    VLOG(1) << "Getting initial CrOS network info.";
1637    UpdateSystemInfo();
1638  }
1639
1640  void InitTestData() {
1641    is_locked_ = true;
1642    ethernet_ = new EthernetNetwork();
1643    ethernet_->set_connected(true);
1644    ethernet_->set_service_path("eth1");
1645
1646    STLDeleteElements(&wifi_networks_);
1647    wifi_networks_.clear();
1648    WifiNetwork* wifi1 = new WifiNetwork();
1649    wifi1->set_service_path("fw1");
1650    wifi1->set_name("Fake Wifi 1");
1651    wifi1->set_strength(90);
1652    wifi1->set_connected(false);
1653    wifi1->set_encryption(SECURITY_NONE);
1654    wifi_networks_.push_back(wifi1);
1655
1656    WifiNetwork* wifi2 = new WifiNetwork();
1657    wifi2->set_service_path("fw2");
1658    wifi2->set_name("Fake Wifi 2");
1659    wifi2->set_strength(70);
1660    wifi2->set_connected(true);
1661    wifi2->set_encryption(SECURITY_WEP);
1662    wifi_networks_.push_back(wifi2);
1663
1664    WifiNetwork* wifi3 = new WifiNetwork();
1665    wifi3->set_service_path("fw3");
1666    wifi3->set_name("Fake Wifi 3");
1667    wifi3->set_strength(50);
1668    wifi3->set_connected(false);
1669    wifi3->set_encryption(SECURITY_8021X);
1670    wifi3->set_identity("nobody@google.com");
1671    wifi3->set_cert_path("SETTINGS:key_id=3,cert_id=3,pin=111111");
1672    wifi_networks_.push_back(wifi3);
1673
1674    wifi_ = wifi2;
1675
1676    STLDeleteElements(&cellular_networks_);
1677    cellular_networks_.clear();
1678
1679    CellularNetwork* cellular1 = new CellularNetwork();
1680    cellular1->set_service_path("fc1");
1681    cellular1->set_name("Fake Cellular 1");
1682    cellular1->set_strength(70);
1683    cellular1->set_connected(false);
1684    cellular1->set_activation_state(ACTIVATION_STATE_ACTIVATED);
1685    cellular1->set_payment_url(std::string("http://www.google.com"));
1686    cellular1->set_network_technology(NETWORK_TECHNOLOGY_EVDO);
1687
1688    CellularDataPlan* base_plan = new CellularDataPlan();
1689    base_plan->plan_name = "Base plan";
1690    base_plan->plan_type = CELLULAR_DATA_PLAN_METERED_BASE;
1691    base_plan->plan_data_bytes = 100ll * 1024 * 1024;
1692    base_plan->data_bytes_used = 75ll * 1024 * 1024;
1693    cellular1->data_plans_.push_back(base_plan);
1694
1695    CellularDataPlan* paid_plan = new CellularDataPlan();
1696    paid_plan->plan_name = "Paid plan";
1697    paid_plan->plan_type = CELLULAR_DATA_PLAN_METERED_PAID;
1698    paid_plan->plan_data_bytes = 5ll * 1024 * 1024 * 1024;
1699    paid_plan->data_bytes_used = 3ll * 1024 * 1024 * 1024;
1700    cellular1->data_plans_.push_back(paid_plan);
1701
1702    cellular_networks_.push_back(cellular1);
1703    cellular_ = cellular1;
1704
1705    remembered_wifi_networks_.clear();
1706    remembered_wifi_networks_.push_back(new WifiNetwork(*wifi2));
1707
1708    int devices = (1 << TYPE_ETHERNET) | (1 << TYPE_WIFI) |
1709        (1 << TYPE_CELLULAR);
1710    available_devices_ = devices;
1711    enabled_devices_ = devices;
1712    connected_devices_ = devices;
1713    wifi_scanning_ = false;
1714    offline_mode_ = false;
1715  }
1716
1717  void UpdateSystemInfo() {
1718    if (EnsureCrosLoaded()) {
1719      UpdateNetworkManagerStatus();
1720    }
1721  }
1722
1723  WifiNetwork* GetWifiNetworkByName(const std::string& name) {
1724    for (size_t i = 0; i < wifi_networks_.size(); ++i) {
1725      if (wifi_networks_[i]->name().compare(name) == 0) {
1726        return wifi_networks_[i];
1727      }
1728    }
1729    return NULL;
1730  }
1731
1732  template<typename T> T GetWirelessNetworkByPath(
1733      std::vector<T>& networks, const std::string& path) {
1734    typedef typename std::vector<T>::iterator iter_t;
1735    iter_t iter = std::find_if(networks.begin(), networks.end(),
1736                               WirelessNetwork::ServicePathEq(path));
1737    return (iter != networks.end()) ? *iter : NULL;
1738  }
1739
1740  // const version
1741  template<typename T> const T GetWirelessNetworkByPath(
1742      const std::vector<T>& networks, const std::string& path) const {
1743    typedef typename std::vector<T>::const_iterator iter_t;
1744    iter_t iter = std::find_if(networks.begin(), networks.end(),
1745                               WirelessNetwork::ServicePathEq(path));
1746    return (iter != networks.end()) ? *iter : NULL;
1747  }
1748
1749  void EnableNetworkDeviceType(ConnectionType device, bool enable) {
1750    if (!EnsureCrosLoaded())
1751      return;
1752
1753    // If network device is already enabled/disabled, then don't do anything.
1754    if (enable && (enabled_devices_ & (1 << device))) {
1755      LOG(WARNING) << "Trying to enable a device that's already enabled: "
1756                   << device;
1757      return;
1758    }
1759    if (!enable && !(enabled_devices_ & (1 << device))) {
1760      LOG(WARNING) << "Trying to disable a device that's already disabled: "
1761                   << device;
1762      return;
1763    }
1764
1765    EnableNetworkDevice(device, enable);
1766  }
1767
1768  void NotifyNetworkManagerChanged() {
1769    FOR_EACH_OBSERVER(NetworkManagerObserver,
1770                      network_manager_observers_,
1771                      OnNetworkManagerChanged(this));
1772  }
1773
1774  void NotifyNetworkChanged(Network* network) {
1775    DCHECK(network);
1776    NetworkObserverMap::const_iterator iter = network_observers_.find(
1777        network->service_path());
1778    if (iter != network_observers_.end()) {
1779      FOR_EACH_OBSERVER(NetworkObserver,
1780                        *(iter->second),
1781                        OnNetworkChanged(this, network));
1782    } else {
1783      NOTREACHED() <<
1784          "There weren't supposed to be any property change observers of " <<
1785           network->service_path();
1786    }
1787  }
1788
1789  void NotifyCellularDataPlanChanged() {
1790    FOR_EACH_OBSERVER(CellularDataPlanObserver,
1791                      data_plan_observers_,
1792                      OnCellularDataPlanChanged(this));
1793  }
1794
1795  void UpdateNetworkManagerStatus() {
1796    // Make sure we run on UI thread.
1797    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1798
1799    update_task_ = NULL;
1800    VLOG(1) << "Updating Network Status";
1801
1802    SystemInfo* system = GetSystemInfo();
1803    if (!system)
1804      return;
1805
1806    ParseSystem(system);
1807
1808    NotifyNetworkManagerChanged();
1809    FreeSystemInfo(system);
1810  }
1811
1812  void UpdateNetworkStatus(const char* path,
1813                           const char* key,
1814                           const Value* value) {
1815    if (key == NULL || value == NULL)
1816      return;
1817    // Make sure we run on UI thread.
1818    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
1819      BrowserThread::PostTask(
1820          BrowserThread::UI, FROM_HERE,
1821          NewRunnableMethod(this,
1822                            &NetworkLibraryImpl::UpdateNetworkStatus,
1823                            path, key, value));
1824      return;
1825    }
1826
1827    bool boolval = false;
1828    int intval = 0;
1829    std::string stringval;
1830    Network* network = NULL;
1831    if (ethernet_->service_path() == path) {
1832      network = ethernet_;
1833    } else {
1834      CellularNetwork* cellular =
1835          GetWirelessNetworkByPath(cellular_networks_, path);
1836      WifiNetwork* wifi =
1837          GetWirelessNetworkByPath(wifi_networks_, path);
1838      if (cellular == NULL && wifi == NULL)
1839        return;
1840
1841      WirelessNetwork* wireless = NULL;
1842      if (wifi != NULL)
1843        wireless = static_cast<WirelessNetwork*>(wifi);
1844      else
1845        wireless = static_cast<WirelessNetwork*>(cellular);
1846
1847      if (strcmp(key, kSignalStrengthProperty) == 0) {
1848        if (value->GetAsInteger(&intval))
1849          wireless->set_strength(intval);
1850      } else if (cellular != NULL) {
1851        if (strcmp(key, kConnectivityStateProperty) == 0) {
1852          if (value->GetAsString(&stringval))
1853            cellular->set_connectivity_state(ParseConnectivityState(stringval));
1854        } else if (strcmp(key, kActivationStateProperty) == 0) {
1855          if (value->GetAsString(&stringval))
1856            cellular->set_activation_state(ParseActivationState(stringval));
1857        } else if (strcmp(key, kPaymentURLProperty) == 0) {
1858          if (value->GetAsString(&stringval))
1859            cellular->set_payment_url(stringval);
1860        } else if (strcmp(key, kNetworkTechnologyProperty) == 0) {
1861          if (value->GetAsString(&stringval))
1862            cellular->set_network_technology(
1863                ParseNetworkTechnology(stringval));
1864        } else if (strcmp(key, kRoamingStateProperty) == 0) {
1865          if (value->GetAsString(&stringval))
1866            cellular->set_roaming_state(ParseRoamingState(stringval));
1867        }
1868      }
1869      network = wireless;
1870    }
1871    if (strcmp(key, kConnectableProperty) == 0) {
1872      if (value->GetAsBoolean(&boolval))
1873        network->set_connectable(boolval);
1874    } else if (strcmp(key, kIsActiveProperty) == 0) {
1875      if (value->GetAsBoolean(&boolval))
1876        network->set_active(boolval);
1877    } else if (strcmp(key, kStateProperty) == 0) {
1878      if (value->GetAsString(&stringval)) {
1879        network->set_state(ParseState(stringval));
1880        // State changed, so refresh IP address.
1881        network->InitIPAddress();
1882      }
1883    }
1884    if (network)
1885      NotifyNetworkChanged(network);
1886  }
1887
1888  void UpdateCellularDataPlan(const CellularDataPlanList* data_plans) {
1889    DCHECK(cellular_);
1890    cellular_->SetDataPlans(data_plans);
1891    NotifyCellularDataPlanChanged();
1892  }
1893
1894  void ClearNetworks() {
1895    if (ethernet_)
1896      delete ethernet_;
1897    ethernet_ = NULL;
1898    wifi_ = NULL;
1899    cellular_ = NULL;
1900    STLDeleteElements(&wifi_networks_);
1901    wifi_networks_.clear();
1902    STLDeleteElements(&cellular_networks_);
1903    cellular_networks_.clear();
1904    STLDeleteElements(&remembered_wifi_networks_);
1905    remembered_wifi_networks_.clear();
1906  }
1907
1908  // Network manager observer list
1909  ObserverList<NetworkManagerObserver> network_manager_observers_;
1910
1911  // Cellular data plan observer list
1912  ObserverList<CellularDataPlanObserver> data_plan_observers_;
1913
1914  // Network observer map
1915  NetworkObserverMap network_observers_;
1916
1917  // For monitoring network manager status changes.
1918  PropertyChangeMonitor network_manager_monitor_;
1919
1920  // For monitoring data plan changes to the connected cellular network.
1921  DataPlanUpdateMonitor data_plan_monitor_;
1922
1923  // Network login observer.
1924  scoped_ptr<NetworkLoginObserver> network_login_observer_;
1925
1926  // The ethernet network.
1927  EthernetNetwork* ethernet_;
1928
1929  // The list of available wifi networks.
1930  WifiNetworkVector wifi_networks_;
1931
1932  // The current connected (or connecting) wifi network.
1933  WifiNetwork* wifi_;
1934
1935  // The remembered wifi networks.
1936  WifiNetworkVector remembered_wifi_networks_;
1937
1938  // The list of available cellular networks.
1939  CellularNetworkVector cellular_networks_;
1940
1941  // The current connected (or connecting) cellular network.
1942  CellularNetwork* cellular_;
1943
1944  // The current available network devices. Bitwise flag of ConnectionTypes.
1945  int available_devices_;
1946
1947  // The current enabled network devices. Bitwise flag of ConnectionTypes.
1948  int enabled_devices_;
1949
1950  // The current connected network devices. Bitwise flag of ConnectionTypes.
1951  int connected_devices_;
1952
1953  // True if we are currently scanning for wifi networks.
1954  bool wifi_scanning_;
1955
1956  // Currently not implemented. TODO: implement or eliminate.
1957  bool offline_mode_;
1958
1959  // True if access network library is locked.
1960  bool is_locked_;
1961
1962  // Delayed task to retrieve the network information.
1963  CancelableTask* update_task_;
1964
1965  // Cellular plan payment time.
1966  base::Time cellular_plan_payment_time_;
1967
1968  DISALLOW_COPY_AND_ASSIGN(NetworkLibraryImpl);
1969};
1970
1971class NetworkLibraryStubImpl : public NetworkLibrary {
1972 public:
1973  NetworkLibraryStubImpl()
1974      : ip_address_("1.1.1.1"),
1975        ethernet_(new EthernetNetwork()),
1976        wifi_(NULL),
1977        cellular_(NULL) {
1978  }
1979  ~NetworkLibraryStubImpl() { if (ethernet_) delete ethernet_; }
1980  virtual void AddNetworkManagerObserver(NetworkManagerObserver* observer) {}
1981  virtual void RemoveNetworkManagerObserver(NetworkManagerObserver* observer) {}
1982  virtual void AddNetworkObserver(const std::string& service_path,
1983                                  NetworkObserver* observer) {}
1984  virtual void RemoveNetworkObserver(const std::string& service_path,
1985                                     NetworkObserver* observer) {}
1986  virtual void RemoveObserverForAllNetworks(NetworkObserver* observer) {}
1987  virtual void Lock() {}
1988  virtual void Unlock() {}
1989  virtual bool IsLocked() { return true; }
1990  virtual void AddCellularDataPlanObserver(
1991      CellularDataPlanObserver* observer) {}
1992  virtual void RemoveCellularDataPlanObserver(
1993      CellularDataPlanObserver* observer) {}
1994  virtual const EthernetNetwork* ethernet_network() const {
1995    return ethernet_;
1996  }
1997  virtual bool ethernet_connecting() const { return false; }
1998  virtual bool ethernet_connected() const { return true; }
1999  virtual const WifiNetwork* wifi_network() const {
2000    return wifi_;
2001  }
2002  virtual bool wifi_connecting() const { return false; }
2003  virtual bool wifi_connected() const { return false; }
2004  virtual const CellularNetwork* cellular_network() const {
2005    return cellular_;
2006  }
2007  virtual bool cellular_connecting() const { return false; }
2008  virtual bool cellular_connected() const { return false; }
2009
2010  bool Connected() const { return true; }
2011  bool Connecting() const { return false; }
2012  const std::string& IPAddress() const { return ip_address_; }
2013  virtual const WifiNetworkVector& wifi_networks() const {
2014    return wifi_networks_;
2015  }
2016  virtual const WifiNetworkVector& remembered_wifi_networks() const {
2017    return wifi_networks_;
2018  }
2019  virtual const CellularNetworkVector& cellular_networks() const {
2020    return cellular_networks_;
2021  }
2022  virtual bool has_cellular_networks() const {
2023    return cellular_networks_.begin() != cellular_networks_.end();
2024  }
2025  /////////////////////////////////////////////////////////////////////////////
2026
2027  virtual WifiNetwork* FindWifiNetworkByPath(
2028      const std::string& path) { return NULL; }
2029  virtual CellularNetwork* FindCellularNetworkByPath(
2030      const std::string& path) { return NULL; }
2031  virtual void RequestWifiScan() {}
2032  virtual bool GetWifiAccessPoints(WifiAccessPointVector* result) {
2033    return false;
2034  }
2035
2036  virtual bool ConnectToWifiNetwork(WifiNetwork* network,
2037                                    const std::string& password,
2038                                    const std::string& identity,
2039                                    const std::string& certpath) {
2040    return true;
2041  }
2042  virtual bool ConnectToWifiNetwork(ConnectionSecurity security,
2043                                    const std::string& ssid,
2044                                    const std::string& password,
2045                                    const std::string& identity,
2046                                    const std::string& certpath,
2047                                    bool auto_connect) {
2048    return true;
2049  }
2050  virtual bool ConnectToCellularNetwork(const CellularNetwork* network) {
2051    return true;
2052  }
2053  virtual void RefreshCellularDataPlans(const CellularNetwork* network) {}
2054  virtual void SignalCellularPlanPayment() {}
2055  virtual bool HasRecentCellularPlanPayment() { return false; }
2056  virtual void DisconnectFromWirelessNetwork(const WirelessNetwork* network) {}
2057  virtual void SaveCellularNetwork(const CellularNetwork* network) {}
2058  virtual void SaveWifiNetwork(const WifiNetwork* network) {}
2059  virtual void ForgetWifiNetwork(const std::string& service_path) {}
2060  virtual bool ethernet_available() const { return true; }
2061  virtual bool wifi_available() const { return false; }
2062  virtual bool cellular_available() const { return false; }
2063  virtual bool ethernet_enabled() const { return true; }
2064  virtual bool wifi_enabled() const { return false; }
2065  virtual bool cellular_enabled() const { return false; }
2066  virtual bool wifi_scanning() const { return false; }
2067  virtual const Network* active_network() const { return NULL; }
2068  virtual bool offline_mode() const { return false; }
2069  virtual void EnableEthernetNetworkDevice(bool enable) {}
2070  virtual void EnableWifiNetworkDevice(bool enable) {}
2071  virtual void EnableCellularNetworkDevice(bool enable) {}
2072  virtual void EnableOfflineMode(bool enable) {}
2073  virtual NetworkIPConfigVector GetIPConfigs(const std::string& device_path,
2074                                             std::string* hardware_address) {
2075    hardware_address->clear();
2076    return NetworkIPConfigVector();
2077  }
2078  virtual std::string GetHtmlInfo(int refresh) { return std::string(); }
2079
2080 private:
2081  std::string ip_address_;
2082  EthernetNetwork* ethernet_;
2083  WifiNetwork* wifi_;
2084  CellularNetwork* cellular_;
2085  WifiNetworkVector wifi_networks_;
2086  CellularNetworkVector cellular_networks_;
2087};
2088
2089// static
2090NetworkLibrary* NetworkLibrary::GetImpl(bool stub) {
2091  if (stub)
2092    return new NetworkLibraryStubImpl();
2093  else
2094    return new NetworkLibraryImpl();
2095}
2096
2097}  // namespace chromeos
2098
2099// Allows InvokeLater without adding refcounting. This class is a Singleton and
2100// won't be deleted until it's last InvokeLater is run.
2101DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::NetworkLibraryImpl);
2102