wifi_config_view.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright (c) 2012 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/options/wifi_config_view.h"
6
7#include "ash/system/chromeos/network/network_connect.h"
8#include "base/bind.h"
9#include "base/strings/string_util.h"
10#include "base/strings/stringprintf.h"
11#include "base/strings/utf_string_conversions.h"
12#include "chrome/browser/chromeos/enrollment_dialog_view.h"
13#include "chrome/browser/chromeos/net/onc_utils.h"
14#include "chrome/browser/chromeos/options/passphrase_textfield.h"
15#include "chrome/browser/profiles/profile_manager.h"
16#include "chromeos/login/login_state.h"
17#include "chromeos/network/network_configuration_handler.h"
18#include "chromeos/network/network_event_log.h"
19#include "chromeos/network/network_handler.h"
20#include "chromeos/network/network_state.h"
21#include "chromeos/network/network_state_handler.h"
22#include "chromeos/network/network_ui_data.h"
23#include "chromeos/network/shill_property_util.h"
24#include "components/onc/onc_constants.h"
25#include "grit/chromium_strings.h"
26#include "grit/generated_resources.h"
27#include "grit/locale_settings.h"
28#include "grit/theme_resources.h"
29#include "third_party/cros_system_api/dbus/service_constants.h"
30#include "ui/base/l10n/l10n_util.h"
31#include "ui/base/resource/resource_bundle.h"
32#include "ui/events/event.h"
33#include "ui/views/controls/button/checkbox.h"
34#include "ui/views/controls/button/image_button.h"
35#include "ui/views/controls/combobox/combobox.h"
36#include "ui/views/controls/label.h"
37#include "ui/views/controls/textfield/textfield.h"
38#include "ui/views/layout/grid_layout.h"
39#include "ui/views/layout/layout_constants.h"
40#include "ui/views/widget/widget.h"
41#include "ui/views/window/dialog_client_view.h"
42
43namespace chromeos {
44
45namespace {
46
47// Combobox that supports a preferred width.  Used by Server CA combobox
48// because the strings inside it are too wide.
49class ComboboxWithWidth : public views::Combobox {
50 public:
51  ComboboxWithWidth(ui::ComboboxModel* model, int width)
52      : Combobox(model),
53        width_(width) {
54  }
55  virtual ~ComboboxWithWidth() {}
56  virtual gfx::Size GetPreferredSize() OVERRIDE {
57    gfx::Size size = Combobox::GetPreferredSize();
58    size.set_width(width_);
59    return size;
60  }
61 private:
62  int width_;
63  DISALLOW_COPY_AND_ASSIGN(ComboboxWithWidth);
64};
65
66enum SecurityComboboxIndex {
67  SECURITY_INDEX_NONE  = 0,
68  SECURITY_INDEX_WEP   = 1,
69  SECURITY_INDEX_PSK   = 2,
70  SECURITY_INDEX_COUNT = 3
71};
72
73// Methods in alphabetical order.
74enum EAPMethodComboboxIndex {
75  EAP_METHOD_INDEX_NONE  = 0,
76  EAP_METHOD_INDEX_LEAP  = 1,
77  EAP_METHOD_INDEX_PEAP  = 2,
78  EAP_METHOD_INDEX_TLS   = 3,
79  EAP_METHOD_INDEX_TTLS  = 4,
80  EAP_METHOD_INDEX_COUNT = 5
81};
82
83enum Phase2AuthComboboxIndex {
84  PHASE_2_AUTH_INDEX_AUTO     = 0,  // LEAP, EAP-TLS have only this auth.
85  PHASE_2_AUTH_INDEX_MD5      = 1,
86  PHASE_2_AUTH_INDEX_MSCHAPV2 = 2,  // PEAP has up to this auth.
87  PHASE_2_AUTH_INDEX_MSCHAP   = 3,
88  PHASE_2_AUTH_INDEX_PAP      = 4,
89  PHASE_2_AUTH_INDEX_CHAP     = 5,  // EAP-TTLS has up to this auth.
90  PHASE_2_AUTH_INDEX_COUNT    = 6
91};
92
93void ShillError(const std::string& function,
94                const std::string& error_name,
95                scoped_ptr<base::DictionaryValue> error_data) {
96  NET_LOG_ERROR("Shill Error from WifiConfigView: " + error_name, function);
97}
98
99}  // namespace
100
101namespace internal {
102
103class SecurityComboboxModel : public ui::ComboboxModel {
104 public:
105  SecurityComboboxModel();
106  virtual ~SecurityComboboxModel();
107
108  // Overridden from ui::ComboboxModel:
109  virtual int GetItemCount() const OVERRIDE;
110  virtual base::string16 GetItemAt(int index) OVERRIDE;
111
112 private:
113  DISALLOW_COPY_AND_ASSIGN(SecurityComboboxModel);
114};
115
116class EAPMethodComboboxModel : public ui::ComboboxModel {
117 public:
118  EAPMethodComboboxModel();
119  virtual ~EAPMethodComboboxModel();
120
121  // Overridden from ui::ComboboxModel:
122  virtual int GetItemCount() const OVERRIDE;
123  virtual base::string16 GetItemAt(int index) OVERRIDE;
124
125 private:
126  DISALLOW_COPY_AND_ASSIGN(EAPMethodComboboxModel);
127};
128
129class Phase2AuthComboboxModel : public ui::ComboboxModel {
130 public:
131  explicit Phase2AuthComboboxModel(views::Combobox* eap_method_combobox);
132  virtual ~Phase2AuthComboboxModel();
133
134  // Overridden from ui::ComboboxModel:
135  virtual int GetItemCount() const OVERRIDE;
136  virtual base::string16 GetItemAt(int index) OVERRIDE;
137
138 private:
139  views::Combobox* eap_method_combobox_;
140
141  DISALLOW_COPY_AND_ASSIGN(Phase2AuthComboboxModel);
142};
143
144class ServerCACertComboboxModel : public ui::ComboboxModel {
145 public:
146  ServerCACertComboboxModel();
147  virtual ~ServerCACertComboboxModel();
148
149  // Overridden from ui::ComboboxModel:
150  virtual int GetItemCount() const OVERRIDE;
151  virtual base::string16 GetItemAt(int index) OVERRIDE;
152
153 private:
154  DISALLOW_COPY_AND_ASSIGN(ServerCACertComboboxModel);
155};
156
157class UserCertComboboxModel : public ui::ComboboxModel {
158 public:
159  explicit UserCertComboboxModel(WifiConfigView* owner);
160  virtual ~UserCertComboboxModel();
161
162  // Overridden from ui::ComboboxModel:
163  virtual int GetItemCount() const OVERRIDE;
164  virtual base::string16 GetItemAt(int index) OVERRIDE;
165
166 private:
167  WifiConfigView* owner_;
168
169  DISALLOW_COPY_AND_ASSIGN(UserCertComboboxModel);
170};
171
172// SecurityComboboxModel -------------------------------------------------------
173
174SecurityComboboxModel::SecurityComboboxModel() {
175}
176
177SecurityComboboxModel::~SecurityComboboxModel() {
178}
179
180int SecurityComboboxModel::GetItemCount() const {
181    return SECURITY_INDEX_COUNT;
182  }
183base::string16 SecurityComboboxModel::GetItemAt(int index) {
184  if (index == SECURITY_INDEX_NONE)
185    return l10n_util::GetStringUTF16(
186        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY_NONE);
187  else if (index == SECURITY_INDEX_WEP)
188    return l10n_util::GetStringUTF16(
189        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY_WEP);
190  else if (index == SECURITY_INDEX_PSK)
191    return l10n_util::GetStringUTF16(
192        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY_PSK);
193  NOTREACHED();
194  return base::string16();
195}
196
197// EAPMethodComboboxModel ------------------------------------------------------
198
199EAPMethodComboboxModel::EAPMethodComboboxModel() {
200}
201
202EAPMethodComboboxModel::~EAPMethodComboboxModel() {
203}
204
205int EAPMethodComboboxModel::GetItemCount() const {
206  return EAP_METHOD_INDEX_COUNT;
207}
208base::string16 EAPMethodComboboxModel::GetItemAt(int index) {
209  if (index == EAP_METHOD_INDEX_NONE)
210    return l10n_util::GetStringUTF16(
211        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_NONE);
212  else if (index == EAP_METHOD_INDEX_LEAP)
213    return l10n_util::GetStringUTF16(
214        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_LEAP);
215  else if (index == EAP_METHOD_INDEX_PEAP)
216    return l10n_util::GetStringUTF16(
217        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_PEAP);
218  else if (index == EAP_METHOD_INDEX_TLS)
219    return l10n_util::GetStringUTF16(
220        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_TLS);
221  else if (index == EAP_METHOD_INDEX_TTLS)
222    return l10n_util::GetStringUTF16(
223        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_TTLS);
224  NOTREACHED();
225  return base::string16();
226}
227
228// Phase2AuthComboboxModel -----------------------------------------------------
229
230Phase2AuthComboboxModel::Phase2AuthComboboxModel(
231    views::Combobox* eap_method_combobox)
232    : eap_method_combobox_(eap_method_combobox) {
233}
234
235Phase2AuthComboboxModel::~Phase2AuthComboboxModel() {
236}
237
238int Phase2AuthComboboxModel::GetItemCount() const {
239  switch (eap_method_combobox_->selected_index()) {
240    case EAP_METHOD_INDEX_NONE:
241    case EAP_METHOD_INDEX_TLS:
242    case EAP_METHOD_INDEX_LEAP:
243      return PHASE_2_AUTH_INDEX_AUTO + 1;
244    case EAP_METHOD_INDEX_PEAP:
245      return PHASE_2_AUTH_INDEX_MSCHAPV2 + 1;
246    case EAP_METHOD_INDEX_TTLS:
247      return PHASE_2_AUTH_INDEX_CHAP + 1;
248  }
249  NOTREACHED();
250  return 0;
251}
252
253base::string16 Phase2AuthComboboxModel::GetItemAt(int index) {
254  if (index == PHASE_2_AUTH_INDEX_AUTO)
255    return l10n_util::GetStringUTF16(
256        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_AUTO);
257  else if (index == PHASE_2_AUTH_INDEX_MD5)
258    return l10n_util::GetStringUTF16(
259        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_MD5);
260  else if (index == PHASE_2_AUTH_INDEX_MSCHAPV2)
261    return l10n_util::GetStringUTF16(
262        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_MSCHAPV2);
263  else if (index == PHASE_2_AUTH_INDEX_MSCHAP)
264    return l10n_util::GetStringUTF16(
265        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_MSCHAP);
266  else if (index == PHASE_2_AUTH_INDEX_PAP)
267    return l10n_util::GetStringUTF16(
268        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_PAP);
269  else if (index == PHASE_2_AUTH_INDEX_CHAP)
270    return l10n_util::GetStringUTF16(
271        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_CHAP);
272  NOTREACHED();
273  return base::string16();
274}
275
276// ServerCACertComboboxModel ---------------------------------------------------
277
278ServerCACertComboboxModel::ServerCACertComboboxModel() {
279}
280
281ServerCACertComboboxModel::~ServerCACertComboboxModel() {
282}
283
284int ServerCACertComboboxModel::GetItemCount() const {
285  if (CertLibrary::Get()->CertificatesLoading())
286    return 1;  // "Loading"
287  // First "Default", then the certs, then "Do not check".
288  return CertLibrary::Get()->NumCertificates(
289      CertLibrary::CERT_TYPE_SERVER_CA) + 2;
290}
291
292base::string16 ServerCACertComboboxModel::GetItemAt(int index) {
293  if (CertLibrary::Get()->CertificatesLoading())
294    return l10n_util::GetStringUTF16(
295        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING);
296  if (index == 0)
297    return l10n_util::GetStringUTF16(
298        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT);
299  if (index == GetItemCount() - 1)
300    return l10n_util::GetStringUTF16(
301        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DO_NOT_CHECK);
302  int cert_index = index - 1;
303  return CertLibrary::Get()->GetCertDisplayStringAt(
304      CertLibrary::CERT_TYPE_SERVER_CA, cert_index);
305}
306
307// UserCertComboboxModel -------------------------------------------------------
308
309UserCertComboboxModel::UserCertComboboxModel(WifiConfigView* owner)
310    : owner_(owner) {
311}
312
313UserCertComboboxModel::~UserCertComboboxModel() {
314}
315
316int UserCertComboboxModel::GetItemCount() const {
317  if (!owner_->UserCertActive())
318    return 0;
319  if (CertLibrary::Get()->CertificatesLoading())
320    return 1;  // "Loading"
321  int num_certs =
322      CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER);
323  if (num_certs == 0)
324    return 1;  // "None installed"
325  return num_certs;
326}
327
328base::string16 UserCertComboboxModel::GetItemAt(int index) {
329  if (!owner_->UserCertActive())
330    return base::string16();
331  if (CertLibrary::Get()->CertificatesLoading())
332    return l10n_util::GetStringUTF16(
333        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING);
334  if (CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) == 0)
335    return l10n_util::GetStringUTF16(
336        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USER_CERT_NONE_INSTALLED);
337  return CertLibrary::Get()->GetCertDisplayStringAt(
338      CertLibrary::CERT_TYPE_USER, index);
339}
340
341}  // namespace internal
342
343WifiConfigView::WifiConfigView(NetworkConfigView* parent,
344                               const std::string& service_path,
345                               bool show_8021x)
346    : ChildNetworkConfigView(parent, service_path),
347      ssid_textfield_(NULL),
348      eap_method_combobox_(NULL),
349      phase_2_auth_label_(NULL),
350      phase_2_auth_combobox_(NULL),
351      user_cert_label_(NULL),
352      user_cert_combobox_(NULL),
353      server_ca_cert_label_(NULL),
354      server_ca_cert_combobox_(NULL),
355      subject_match_label_(NULL),
356      subject_match_textfield_(NULL),
357      identity_label_(NULL),
358      identity_textfield_(NULL),
359      identity_anonymous_label_(NULL),
360      identity_anonymous_textfield_(NULL),
361      save_credentials_checkbox_(NULL),
362      share_network_checkbox_(NULL),
363      shared_network_label_(NULL),
364      security_combobox_(NULL),
365      passphrase_label_(NULL),
366      passphrase_textfield_(NULL),
367      passphrase_visible_button_(NULL),
368      error_label_(NULL),
369      weak_ptr_factory_(this) {
370  Init(show_8021x);
371  NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
372}
373
374WifiConfigView::~WifiConfigView() {
375  RemoveAllChildViews(true);  // Destroy children before models
376  if (NetworkHandler::IsInitialized()) {
377    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
378        this, FROM_HERE);
379  }
380  CertLibrary::Get()->RemoveObserver(this);
381}
382
383base::string16 WifiConfigView::GetTitle() const {
384  return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_JOIN_WIFI_NETWORKS);
385}
386
387views::View* WifiConfigView::GetInitiallyFocusedView() {
388  // Return a reasonable widget for initial focus,
389  // depending on what we're showing.
390  if (ssid_textfield_)
391    return ssid_textfield_;
392  else if (eap_method_combobox_)
393    return eap_method_combobox_;
394  else if (passphrase_textfield_ && passphrase_textfield_->enabled())
395    return passphrase_textfield_;
396  else
397    return NULL;
398}
399
400bool WifiConfigView::CanLogin() {
401  static const size_t kMinWirelessPasswordLen = 5;
402
403  // We either have an existing wifi network or the user entered an SSID.
404  if (service_path_.empty() && GetSsid().empty())
405    return false;
406
407  // If the network requires a passphrase, make sure it is the right length.
408  if (passphrase_textfield_ != NULL &&
409      passphrase_textfield_->enabled() &&
410      !passphrase_textfield_->show_fake() &&
411      passphrase_textfield_->text().length() < kMinWirelessPasswordLen)
412    return false;
413
414  // If we're using EAP, we must have a method.
415  if (eap_method_combobox_ &&
416      eap_method_combobox_->selected_index() == EAP_METHOD_INDEX_NONE)
417    return false;
418
419  // Block login if certs are required but user has none.
420  if (UserCertRequired() && (!HaveUserCerts() || !IsUserCertValid()))
421      return false;
422
423  return true;
424}
425
426bool WifiConfigView::UserCertRequired() const {
427  return UserCertActive();
428}
429
430bool WifiConfigView::HaveUserCerts() const {
431  return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) > 0;
432}
433
434bool WifiConfigView::IsUserCertValid() const {
435  if (!UserCertActive())
436    return false;
437  int index = user_cert_combobox_->selected_index();
438  if (index < 0)
439    return false;
440  // Currently only hardware-backed user certificates are valid.
441  if (CertLibrary::Get()->IsHardwareBacked() &&
442      !CertLibrary::Get()->IsCertHardwareBackedAt(
443          CertLibrary::CERT_TYPE_USER, index))
444    return false;
445  return true;
446}
447
448bool WifiConfigView::Phase2AuthActive() const {
449  if (phase_2_auth_combobox_)
450    return phase_2_auth_combobox_->model()->GetItemCount() > 1;
451  return false;
452}
453
454bool WifiConfigView::PassphraseActive() const {
455  if (eap_method_combobox_) {
456    // No password for EAP-TLS.
457    int index = eap_method_combobox_->selected_index();
458    return index != EAP_METHOD_INDEX_NONE && index != EAP_METHOD_INDEX_TLS;
459  } else if (security_combobox_) {
460    return security_combobox_->selected_index() != SECURITY_INDEX_NONE;
461  }
462  return false;
463}
464
465bool WifiConfigView::UserCertActive() const {
466  // User certs only for EAP-TLS.
467  if (eap_method_combobox_)
468    return eap_method_combobox_->selected_index() == EAP_METHOD_INDEX_TLS;
469
470  return false;
471}
472
473bool WifiConfigView::CaCertActive() const {
474  // No server CA certs for LEAP.
475  if (eap_method_combobox_) {
476    int index = eap_method_combobox_->selected_index();
477    return index != EAP_METHOD_INDEX_NONE && index != EAP_METHOD_INDEX_LEAP;
478  }
479  return false;
480}
481
482void WifiConfigView::UpdateDialogButtons() {
483  parent_->GetDialogClientView()->UpdateDialogButtons();
484}
485
486void WifiConfigView::RefreshEapFields() {
487  // If EAP method changes, the phase 2 auth choices may have changed also.
488  phase_2_auth_combobox_->ModelChanged();
489  phase_2_auth_combobox_->SetSelectedIndex(0);
490  bool phase_2_auth_enabled = Phase2AuthActive();
491  phase_2_auth_combobox_->SetEnabled(phase_2_auth_enabled &&
492                                     phase_2_auth_ui_data_.IsEditable());
493  phase_2_auth_label_->SetEnabled(phase_2_auth_enabled);
494
495  // Passphrase.
496  bool passphrase_enabled = PassphraseActive();
497  passphrase_textfield_->SetEnabled(passphrase_enabled &&
498                                    passphrase_ui_data_.IsEditable());
499  passphrase_label_->SetEnabled(passphrase_enabled);
500  if (!passphrase_enabled)
501    passphrase_textfield_->SetText(base::string16());
502
503  // User cert.
504  bool certs_loading = CertLibrary::Get()->CertificatesLoading();
505  bool user_cert_enabled = UserCertActive();
506  user_cert_label_->SetEnabled(user_cert_enabled);
507  bool have_user_certs = !certs_loading && HaveUserCerts();
508  user_cert_combobox_->SetEnabled(user_cert_enabled &&
509                                  have_user_certs &&
510                                  user_cert_ui_data_.IsEditable());
511  user_cert_combobox_->ModelChanged();
512  user_cert_combobox_->SetSelectedIndex(0);
513
514  // Server CA.
515  bool ca_cert_enabled = CaCertActive();
516  server_ca_cert_label_->SetEnabled(ca_cert_enabled);
517  server_ca_cert_combobox_->SetEnabled(ca_cert_enabled &&
518                                       !certs_loading &&
519                                       server_ca_cert_ui_data_.IsEditable());
520  server_ca_cert_combobox_->ModelChanged();
521  server_ca_cert_combobox_->SetSelectedIndex(0);
522
523  // Subject Match
524  bool subject_match_enabled =
525      ca_cert_enabled && eap_method_combobox_ &&
526      eap_method_combobox_->selected_index() == EAP_METHOD_INDEX_TLS;
527  subject_match_label_->SetEnabled(subject_match_enabled);
528  subject_match_textfield_->SetEnabled(subject_match_enabled);
529  if (!subject_match_enabled)
530    subject_match_textfield_->SetText(base::string16());
531
532  // No anonymous identity if no phase 2 auth.
533  bool identity_anonymous_enabled = phase_2_auth_enabled;
534  identity_anonymous_textfield_->SetEnabled(
535      identity_anonymous_enabled && identity_anonymous_ui_data_.IsEditable());
536  identity_anonymous_label_->SetEnabled(identity_anonymous_enabled);
537  if (!identity_anonymous_enabled)
538    identity_anonymous_textfield_->SetText(base::string16());
539
540  RefreshShareCheckbox();
541}
542
543void WifiConfigView::RefreshShareCheckbox() {
544  if (!share_network_checkbox_)
545    return;
546
547  if (security_combobox_ &&
548      security_combobox_->selected_index() == SECURITY_INDEX_NONE) {
549    share_network_checkbox_->SetEnabled(false);
550    share_network_checkbox_->SetChecked(true);
551  } else if (eap_method_combobox_ &&
552             (eap_method_combobox_->selected_index() == EAP_METHOD_INDEX_TLS ||
553              user_cert_combobox_->selected_index() != 0)) {
554    // Can not share TLS network (requires certificate), or any network where
555    // user certificates are enabled.
556    share_network_checkbox_->SetEnabled(false);
557    share_network_checkbox_->SetChecked(false);
558  } else if (!LoginState::Get()->IsUserAuthenticated()) {
559    // If not logged in as an authenticated user, networks must be shared.
560    share_network_checkbox_->SetEnabled(false);
561    share_network_checkbox_->SetChecked(true);
562  } else {
563    share_network_checkbox_->SetEnabled(true);
564    share_network_checkbox_->SetChecked(false);  // Default to unshared.
565  }
566}
567
568void WifiConfigView::UpdateErrorLabel() {
569  base::string16 error_msg;
570  if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) {
571    if (!HaveUserCerts()) {
572      if (!LoginState::Get()->IsUserAuthenticated()) {
573        error_msg = l10n_util::GetStringUTF16(
574            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_LOGIN_FOR_USER_CERT);
575      } else {
576        error_msg = l10n_util::GetStringUTF16(
577            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT);
578      }
579    } else if (!IsUserCertValid()) {
580      error_msg = l10n_util::GetStringUTF16(
581          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED);
582    }
583  }
584  if (error_msg.empty() && !service_path_.empty()) {
585    const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
586        GetNetworkState(service_path_);
587    if (wifi && wifi->connection_state() == shill::kStateFailure)
588      error_msg = ash::network_connect::ErrorString(
589          wifi->last_error(), wifi->path());
590  }
591  if (!error_msg.empty()) {
592    error_label_->SetText(error_msg);
593    error_label_->SetVisible(true);
594  } else {
595    error_label_->SetVisible(false);
596  }
597}
598
599void WifiConfigView::ContentsChanged(views::Textfield* sender,
600                                     const base::string16& new_contents) {
601  UpdateDialogButtons();
602}
603
604bool WifiConfigView::HandleKeyEvent(views::Textfield* sender,
605                                    const ui::KeyEvent& key_event) {
606  if (sender == passphrase_textfield_ &&
607      key_event.key_code() == ui::VKEY_RETURN) {
608    parent_->GetDialogClientView()->AcceptWindow();
609  }
610  return false;
611}
612
613void WifiConfigView::ButtonPressed(views::Button* sender,
614                                   const ui::Event& event) {
615  if (sender == passphrase_visible_button_ && passphrase_textfield_) {
616    if (passphrase_textfield_->GetTextInputType() == ui::TEXT_INPUT_TYPE_TEXT) {
617      passphrase_textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
618      passphrase_visible_button_->SetToggled(false);
619    } else {
620      passphrase_textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
621      passphrase_visible_button_->SetToggled(true);
622    }
623  } else {
624    NOTREACHED();
625  }
626}
627
628void WifiConfigView::OnPerformAction(views::Combobox* combobox) {
629  if (combobox == security_combobox_) {
630    bool passphrase_enabled = PassphraseActive();
631    passphrase_label_->SetEnabled(passphrase_enabled);
632    passphrase_textfield_->SetEnabled(passphrase_enabled &&
633                                      passphrase_ui_data_.IsEditable());
634    if (!passphrase_enabled)
635      passphrase_textfield_->SetText(base::string16());
636    RefreshShareCheckbox();
637  } else if (combobox == user_cert_combobox_) {
638    RefreshShareCheckbox();
639  } else if (combobox == eap_method_combobox_) {
640    RefreshEapFields();
641  }
642  UpdateDialogButtons();
643  UpdateErrorLabel();
644}
645
646void WifiConfigView::OnCertificatesLoaded(bool initial_load) {
647  RefreshEapFields();
648  UpdateDialogButtons();
649  UpdateErrorLabel();
650}
651
652bool WifiConfigView::Login() {
653  const NetworkState* wifi = !service_path_.empty() ?
654      NetworkHandler::Get()->network_state_handler()->
655          GetNetworkState(service_path_) :
656      NULL;
657
658  // Set configuration properties.
659  base::DictionaryValue properties;
660
661  // Default shared state for non-private networks is true.
662  const bool share_default = !wifi || !wifi->IsPrivate();
663  bool share_network = GetShareNetwork(share_default);
664  bool only_policy_autoconnect =
665      onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!share_network);
666  if (only_policy_autoconnect) {
667    properties.SetBooleanWithoutPathExpansion(shill::kAutoConnectProperty,
668                                              false);
669  }
670
671  if (service_path_.empty()) {
672    properties.SetStringWithoutPathExpansion(
673        shill::kTypeProperty, shill::kTypeWifi);
674    shill_property_util::SetSSID(GetSsid(), &properties);
675    properties.SetStringWithoutPathExpansion(
676        shill::kModeProperty, shill::kModeManaged);
677    properties.SetBooleanWithoutPathExpansion(
678        shill::kSaveCredentialsProperty, GetSaveCredentials());
679    std::string security = shill::kSecurityNone;
680    if (!eap_method_combobox_) {
681      // Hidden ordinary Wi-Fi connection.
682      switch (security_combobox_->selected_index()) {
683        case SECURITY_INDEX_NONE:
684          security = shill::kSecurityNone;
685          break;
686        case SECURITY_INDEX_WEP:
687          security = shill::kSecurityWep;
688          break;
689        case SECURITY_INDEX_PSK:
690          security = shill::kSecurityPsk;
691          break;
692      }
693      std::string passphrase = GetPassphrase();
694      if (!passphrase.empty()) {
695        properties.SetStringWithoutPathExpansion(
696            shill::kPassphraseProperty, GetPassphrase());
697      }
698    } else {
699      // Hidden 802.1X EAP Wi-Fi connection.
700      security = shill::kSecurity8021x;
701      SetEapProperties(&properties);
702    }
703    properties.SetStringWithoutPathExpansion(
704        shill::kSecurityProperty, security);
705
706    // Configure and connect to network.
707    ash::network_connect::CreateConfigurationAndConnect(&properties,
708                                                        share_network);
709  } else {
710    if (!wifi) {
711      // Shill no longer knows about this wifi network (edge case).
712      // TODO(stevenjb): Add notification for this.
713      NET_LOG_ERROR("Network not found", service_path_);
714      return true;  // Close dialog
715    }
716    if (eap_method_combobox_) {
717      // Visible 802.1X EAP Wi-Fi connection.
718      SetEapProperties(&properties);
719      properties.SetBooleanWithoutPathExpansion(
720          shill::kSaveCredentialsProperty, GetSaveCredentials());
721    } else {
722      // Visible ordinary Wi-Fi connection.
723      const std::string passphrase = GetPassphrase();
724      if (!passphrase.empty()) {
725        properties.SetStringWithoutPathExpansion(
726            shill::kPassphraseProperty, passphrase);
727      }
728    }
729    ash::network_connect::ConfigureNetworkAndConnect(
730        service_path_, properties, share_network);
731  }
732  return true;  // dialog will be closed
733}
734
735std::string WifiConfigView::GetSsid() const {
736  std::string result;
737  if (ssid_textfield_ != NULL) {
738    std::string untrimmed = base::UTF16ToUTF8(ssid_textfield_->text());
739    base::TrimWhitespaceASCII(untrimmed, base::TRIM_ALL, &result);
740  }
741  return result;
742}
743
744std::string WifiConfigView::GetPassphrase() const {
745  std::string result;
746  if (passphrase_textfield_ != NULL)
747    result = base::UTF16ToUTF8(passphrase_textfield_->text());
748  return result;
749}
750
751bool WifiConfigView::GetSaveCredentials() const {
752  if (!save_credentials_checkbox_)
753    return true;  // share networks by default (e.g. non 8021x).
754  return save_credentials_checkbox_->checked();
755}
756
757bool WifiConfigView::GetShareNetwork(bool share_default) const {
758  if (!share_network_checkbox_)
759    return share_default;
760  return share_network_checkbox_->checked();
761}
762
763std::string WifiConfigView::GetEapMethod() const {
764  DCHECK(eap_method_combobox_);
765  switch (eap_method_combobox_->selected_index()) {
766    case EAP_METHOD_INDEX_PEAP:
767      return shill::kEapMethodPEAP;
768    case EAP_METHOD_INDEX_TLS:
769      return shill::kEapMethodTLS;
770    case EAP_METHOD_INDEX_TTLS:
771      return shill::kEapMethodTTLS;
772    case EAP_METHOD_INDEX_LEAP:
773      return shill::kEapMethodLEAP;
774    case EAP_METHOD_INDEX_NONE:
775    default:
776      return "";
777  }
778}
779
780std::string WifiConfigView::GetEapPhase2Auth() const {
781  DCHECK(phase_2_auth_combobox_);
782  bool is_peap = (GetEapMethod() == shill::kEapMethodPEAP);
783  switch (phase_2_auth_combobox_->selected_index()) {
784    case PHASE_2_AUTH_INDEX_MD5:
785      return is_peap ? shill::kEapPhase2AuthPEAPMD5
786          : shill::kEapPhase2AuthTTLSMD5;
787    case PHASE_2_AUTH_INDEX_MSCHAPV2:
788      return is_peap ? shill::kEapPhase2AuthPEAPMSCHAPV2
789          : shill::kEapPhase2AuthTTLSMSCHAPV2;
790    case PHASE_2_AUTH_INDEX_MSCHAP:
791      return shill::kEapPhase2AuthTTLSMSCHAP;
792    case PHASE_2_AUTH_INDEX_PAP:
793      return shill::kEapPhase2AuthTTLSPAP;
794    case PHASE_2_AUTH_INDEX_CHAP:
795      return shill::kEapPhase2AuthTTLSCHAP;
796    case PHASE_2_AUTH_INDEX_AUTO:
797    default:
798      return "";
799  }
800}
801
802std::string WifiConfigView::GetEapServerCaCertPEM() const {
803  DCHECK(server_ca_cert_combobox_);
804  int index = server_ca_cert_combobox_->selected_index();
805  if (index == 0) {
806    // First item is "Default".
807    return std::string();
808  } else if (index == server_ca_cert_combobox_->model()->GetItemCount() - 1) {
809    // Last item is "Do not check".
810    return std::string();
811  } else {
812    int cert_index = index - 1;
813    return CertLibrary::Get()->GetCertPEMAt(
814        CertLibrary::CERT_TYPE_SERVER_CA, cert_index);
815  }
816}
817
818bool WifiConfigView::GetEapUseSystemCas() const {
819  DCHECK(server_ca_cert_combobox_);
820  // Only use system CAs if the first item ("Default") is selected.
821  return server_ca_cert_combobox_->selected_index() == 0;
822}
823
824std::string WifiConfigView::GetEapSubjectMatch() const {
825  DCHECK(subject_match_textfield_);
826  return base::UTF16ToUTF8(subject_match_textfield_->text());
827}
828
829std::string WifiConfigView::GetEapClientCertPkcs11Id() const {
830  DCHECK(user_cert_combobox_);
831  if (!HaveUserCerts() || !UserCertActive()) {
832    return std::string();  // No certificate selected or not required.
833  } else {
834    // Certificates are listed in the order they appear in the model.
835    int index = user_cert_combobox_->selected_index();
836    return CertLibrary::Get()->GetCertPkcs11IdAt(
837        CertLibrary::CERT_TYPE_USER, index);
838  }
839}
840
841std::string WifiConfigView::GetEapIdentity() const {
842  DCHECK(identity_textfield_);
843  return base::UTF16ToUTF8(identity_textfield_->text());
844}
845
846std::string WifiConfigView::GetEapAnonymousIdentity() const {
847  DCHECK(identity_anonymous_textfield_);
848  return base::UTF16ToUTF8(identity_anonymous_textfield_->text());
849}
850
851void WifiConfigView::SetEapProperties(base::DictionaryValue* properties) {
852  properties->SetStringWithoutPathExpansion(
853      shill::kEapIdentityProperty, GetEapIdentity());
854  properties->SetStringWithoutPathExpansion(
855      shill::kEapMethodProperty, GetEapMethod());
856  properties->SetStringWithoutPathExpansion(
857      shill::kEapPhase2AuthProperty, GetEapPhase2Auth());
858  properties->SetStringWithoutPathExpansion(
859      shill::kEapAnonymousIdentityProperty, GetEapAnonymousIdentity());
860  properties->SetStringWithoutPathExpansion(
861      shill::kEapSubjectMatchProperty, GetEapSubjectMatch());
862
863  // shill requires both CertID and KeyID for TLS connections, despite
864  // the fact that by convention they are the same ID.
865  properties->SetStringWithoutPathExpansion(
866      shill::kEapCertIdProperty, GetEapClientCertPkcs11Id());
867  properties->SetStringWithoutPathExpansion(
868      shill::kEapKeyIdProperty, GetEapClientCertPkcs11Id());
869
870  properties->SetBooleanWithoutPathExpansion(
871      shill::kEapUseSystemCasProperty, GetEapUseSystemCas());
872  properties->SetStringWithoutPathExpansion(
873      shill::kEapPasswordProperty, GetPassphrase());
874
875  base::ListValue* pem_list = new base::ListValue;
876  pem_list->AppendString(GetEapServerCaCertPEM());
877  properties->SetWithoutPathExpansion(
878      shill::kEapCaCertPemProperty, pem_list);
879}
880
881void WifiConfigView::Cancel() {
882}
883
884// This will initialize the view depending on if we have a wifi network or not.
885// And if we are doing simple password encryption or the more complicated
886// 802.1x encryption.
887// If we are creating the "Join other network..." dialog, we will allow user
888// to enter the data. And if they select the 802.1x encryption, we will show
889// the 802.1x fields.
890void WifiConfigView::Init(bool show_8021x) {
891  const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
892      GetNetworkState(service_path_);
893  if (wifi) {
894    DCHECK(wifi->type() == shill::kTypeWifi);
895    if (wifi->security() == shill::kSecurity8021x)
896      show_8021x = true;
897    ParseWiFiEAPUIProperty(&eap_method_ui_data_, wifi, ::onc::eap::kOuter);
898    ParseWiFiEAPUIProperty(&phase_2_auth_ui_data_, wifi, ::onc::eap::kInner);
899    ParseWiFiEAPUIProperty(&user_cert_ui_data_, wifi,
900                           ::onc::eap::kClientCertRef);
901    ParseWiFiEAPUIProperty(&server_ca_cert_ui_data_, wifi,
902                           ::onc::eap::kServerCARef);
903    if (server_ca_cert_ui_data_.IsManaged()) {
904      ParseWiFiEAPUIProperty(&server_ca_cert_ui_data_, wifi,
905                             ::onc::eap::kUseSystemCAs);
906    }
907    ParseWiFiEAPUIProperty(&identity_ui_data_, wifi, ::onc::eap::kIdentity);
908    ParseWiFiEAPUIProperty(&identity_anonymous_ui_data_, wifi,
909                           ::onc::eap::kAnonymousIdentity);
910    ParseWiFiEAPUIProperty(&save_credentials_ui_data_, wifi,
911                           ::onc::eap::kSaveCredentials);
912    if (show_8021x)
913      ParseWiFiEAPUIProperty(&passphrase_ui_data_, wifi, ::onc::eap::kPassword);
914    else
915      ParseWiFiUIProperty(&passphrase_ui_data_, wifi, ::onc::wifi::kPassphrase);
916  }
917
918  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
919  SetLayoutManager(layout);
920
921  const int column_view_set_id = 0;
922  views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
923  const int kPasswordVisibleWidth = 20;
924  // Label
925  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
926                        views::GridLayout::USE_PREF, 0, 0);
927  column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
928  // Textfield, combobox.
929  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
930                        views::GridLayout::USE_PREF, 0,
931                        ChildNetworkConfigView::kInputFieldMinWidth);
932  column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
933  // Password visible button / policy indicator.
934  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL, 1,
935                        views::GridLayout::USE_PREF, 0, kPasswordVisibleWidth);
936
937  // SSID input
938  layout->StartRow(0, column_view_set_id);
939  layout->AddView(new views::Label(l10n_util::GetStringUTF16(
940      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID)));
941  if (!wifi) {
942    ssid_textfield_ = new views::Textfield();
943    ssid_textfield_->set_controller(this);
944    ssid_textfield_->SetAccessibleName(l10n_util::GetStringUTF16(
945        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID));
946    layout->AddView(ssid_textfield_);
947  } else {
948    views::Label* label = new views::Label(base::UTF8ToUTF16(wifi->name()));
949    label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
950    layout->AddView(label);
951  }
952  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
953
954  // Security select
955  if (!wifi && !show_8021x) {
956    layout->StartRow(0, column_view_set_id);
957    base::string16 label_text = l10n_util::GetStringUTF16(
958        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY);
959    layout->AddView(new views::Label(label_text));
960    security_combobox_model_.reset(new internal::SecurityComboboxModel);
961    security_combobox_ = new views::Combobox(security_combobox_model_.get());
962    security_combobox_->SetAccessibleName(label_text);
963    security_combobox_->set_listener(this);
964    layout->AddView(security_combobox_);
965    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
966  }
967
968  // Only enumerate certificates in the data model for 802.1X networks.
969  if (show_8021x) {
970    // Observer any changes to the certificate list.
971    CertLibrary::Get()->AddObserver(this);
972
973    // EAP method
974    layout->StartRow(0, column_view_set_id);
975    base::string16 eap_label_text = l10n_util::GetStringUTF16(
976        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD);
977    layout->AddView(new views::Label(eap_label_text));
978    eap_method_combobox_model_.reset(new internal::EAPMethodComboboxModel);
979    eap_method_combobox_ = new views::Combobox(
980        eap_method_combobox_model_.get());
981    eap_method_combobox_->SetAccessibleName(eap_label_text);
982    eap_method_combobox_->set_listener(this);
983    eap_method_combobox_->SetEnabled(eap_method_ui_data_.IsEditable());
984    layout->AddView(eap_method_combobox_);
985    layout->AddView(new ControlledSettingIndicatorView(eap_method_ui_data_));
986    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
987
988    // Phase 2 authentication
989    layout->StartRow(0, column_view_set_id);
990    base::string16 phase_2_label_text = l10n_util::GetStringUTF16(
991        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH);
992    phase_2_auth_label_ = new views::Label(phase_2_label_text);
993    layout->AddView(phase_2_auth_label_);
994    phase_2_auth_combobox_model_.reset(
995        new internal::Phase2AuthComboboxModel(eap_method_combobox_));
996    phase_2_auth_combobox_ = new views::Combobox(
997        phase_2_auth_combobox_model_.get());
998    phase_2_auth_combobox_->SetAccessibleName(phase_2_label_text);
999    phase_2_auth_label_->SetEnabled(false);
1000    phase_2_auth_combobox_->SetEnabled(false);
1001    phase_2_auth_combobox_->set_listener(this);
1002    layout->AddView(phase_2_auth_combobox_);
1003    layout->AddView(new ControlledSettingIndicatorView(phase_2_auth_ui_data_));
1004    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1005
1006    // Server CA certificate
1007    layout->StartRow(0, column_view_set_id);
1008    base::string16 server_ca_cert_label_text = l10n_util::GetStringUTF16(
1009        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA);
1010    server_ca_cert_label_ = new views::Label(server_ca_cert_label_text);
1011    layout->AddView(server_ca_cert_label_);
1012    server_ca_cert_combobox_model_.reset(
1013        new internal::ServerCACertComboboxModel());
1014    server_ca_cert_combobox_ = new ComboboxWithWidth(
1015        server_ca_cert_combobox_model_.get(),
1016        ChildNetworkConfigView::kInputFieldMinWidth);
1017    server_ca_cert_combobox_->SetAccessibleName(server_ca_cert_label_text);
1018    server_ca_cert_label_->SetEnabled(false);
1019    server_ca_cert_combobox_->SetEnabled(false);
1020    server_ca_cert_combobox_->set_listener(this);
1021    layout->AddView(server_ca_cert_combobox_);
1022    layout->AddView(
1023        new ControlledSettingIndicatorView(server_ca_cert_ui_data_));
1024    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1025
1026    // Subject Match
1027    layout->StartRow(0, column_view_set_id);
1028    base::string16 subject_match_label_text = l10n_util::GetStringUTF16(
1029        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_SUBJECT_MATCH);
1030    subject_match_label_ = new views::Label(subject_match_label_text);
1031    layout->AddView(subject_match_label_);
1032    subject_match_textfield_ = new views::Textfield();
1033    subject_match_textfield_->SetAccessibleName(subject_match_label_text);
1034    subject_match_textfield_->set_controller(this);
1035    layout->AddView(subject_match_textfield_);
1036    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1037
1038    // User certificate
1039    layout->StartRow(0, column_view_set_id);
1040    base::string16 user_cert_label_text = l10n_util::GetStringUTF16(
1041        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT);
1042    user_cert_label_ = new views::Label(user_cert_label_text);
1043    layout->AddView(user_cert_label_);
1044    user_cert_combobox_model_.reset(new internal::UserCertComboboxModel(this));
1045    user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get());
1046    user_cert_combobox_->SetAccessibleName(user_cert_label_text);
1047    user_cert_label_->SetEnabled(false);
1048    user_cert_combobox_->SetEnabled(false);
1049    user_cert_combobox_->set_listener(this);
1050    layout->AddView(user_cert_combobox_);
1051    layout->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_));
1052    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1053
1054    // Identity
1055    layout->StartRow(0, column_view_set_id);
1056    base::string16 identity_label_text = l10n_util::GetStringUTF16(
1057        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_IDENTITY);
1058    identity_label_ = new views::Label(identity_label_text);
1059    layout->AddView(identity_label_);
1060    identity_textfield_ = new views::Textfield();
1061    identity_textfield_->SetAccessibleName(identity_label_text);
1062    identity_textfield_->set_controller(this);
1063    identity_textfield_->SetEnabled(identity_ui_data_.IsEditable());
1064    layout->AddView(identity_textfield_);
1065    layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_));
1066    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1067  }
1068
1069  // Passphrase input
1070  layout->StartRow(0, column_view_set_id);
1071  int label_text_id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE;
1072  base::string16 passphrase_label_text =
1073      l10n_util::GetStringUTF16(label_text_id);
1074  passphrase_label_ = new views::Label(passphrase_label_text);
1075  layout->AddView(passphrase_label_);
1076  passphrase_textfield_ = new PassphraseTextfield();
1077  passphrase_textfield_->set_controller(this);
1078  // Disable passphrase input initially for other network.
1079  passphrase_label_->SetEnabled(wifi);
1080  passphrase_textfield_->SetEnabled(wifi && passphrase_ui_data_.IsEditable());
1081  passphrase_textfield_->SetAccessibleName(passphrase_label_text);
1082  layout->AddView(passphrase_textfield_);
1083
1084  if (passphrase_ui_data_.IsManaged()) {
1085    layout->AddView(new ControlledSettingIndicatorView(passphrase_ui_data_));
1086  } else {
1087    // Password visible button.
1088    passphrase_visible_button_ = new views::ToggleImageButton(this);
1089    passphrase_visible_button_->SetFocusable(true);
1090    passphrase_visible_button_->SetTooltipText(
1091        l10n_util::GetStringUTF16(
1092            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_SHOW));
1093    passphrase_visible_button_->SetToggledTooltipText(
1094        l10n_util::GetStringUTF16(
1095            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE));
1096    passphrase_visible_button_->SetImage(
1097        views::ImageButton::STATE_NORMAL,
1098        ResourceBundle::GetSharedInstance().
1099        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD));
1100    passphrase_visible_button_->SetImage(
1101        views::ImageButton::STATE_HOVERED,
1102        ResourceBundle::GetSharedInstance().
1103        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER));
1104    passphrase_visible_button_->SetToggledImage(
1105        views::ImageButton::STATE_NORMAL,
1106        ResourceBundle::GetSharedInstance().
1107        GetImageSkiaNamed(IDR_NETWORK_HIDE_PASSWORD));
1108    passphrase_visible_button_->SetToggledImage(
1109        views::ImageButton::STATE_HOVERED,
1110        ResourceBundle::GetSharedInstance().
1111        GetImageSkiaNamed(IDR_NETWORK_HIDE_PASSWORD_HOVER));
1112    passphrase_visible_button_->SetImageAlignment(
1113        views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE);
1114    layout->AddView(passphrase_visible_button_);
1115  }
1116
1117  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1118
1119  if (show_8021x) {
1120    // Anonymous identity
1121    layout->StartRow(0, column_view_set_id);
1122    identity_anonymous_label_ =
1123        new views::Label(l10n_util::GetStringUTF16(
1124            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_IDENTITY_ANONYMOUS));
1125    layout->AddView(identity_anonymous_label_);
1126    identity_anonymous_textfield_ = new views::Textfield();
1127    identity_anonymous_label_->SetEnabled(false);
1128    identity_anonymous_textfield_->SetEnabled(false);
1129    identity_anonymous_textfield_->set_controller(this);
1130    layout->AddView(identity_anonymous_textfield_);
1131    layout->AddView(
1132        new ControlledSettingIndicatorView(identity_anonymous_ui_data_));
1133    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1134  }
1135
1136  // Checkboxes.
1137
1138  // Save credentials
1139  if (show_8021x) {
1140    layout->StartRow(0, column_view_set_id);
1141    save_credentials_checkbox_ = new views::Checkbox(
1142        l10n_util::GetStringUTF16(
1143            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS));
1144    save_credentials_checkbox_->SetEnabled(
1145        save_credentials_ui_data_.IsEditable());
1146    layout->SkipColumns(1);
1147    layout->AddView(save_credentials_checkbox_);
1148    layout->AddView(
1149        new ControlledSettingIndicatorView(save_credentials_ui_data_));
1150  }
1151
1152  // Share network
1153  if (!wifi || wifi->profile_path().empty()) {
1154    layout->StartRow(0, column_view_set_id);
1155    share_network_checkbox_ = new views::Checkbox(
1156        l10n_util::GetStringUTF16(
1157            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK));
1158    layout->SkipColumns(1);
1159    layout->AddView(share_network_checkbox_);
1160  }
1161  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1162
1163  // Create an error label.
1164  layout->StartRow(0, column_view_set_id);
1165  layout->SkipColumns(1);
1166  error_label_ = new views::Label();
1167  error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
1168  error_label_->SetEnabledColor(SK_ColorRED);
1169  layout->AddView(error_label_);
1170
1171  // Initialize the field and checkbox values.
1172
1173  if (!wifi && show_8021x)
1174    RefreshEapFields();
1175
1176  RefreshShareCheckbox();
1177  UpdateErrorLabel();
1178
1179  if (wifi) {
1180    NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1181        service_path_,
1182        base::Bind(&WifiConfigView::InitFromProperties,
1183                   weak_ptr_factory_.GetWeakPtr(), show_8021x),
1184        base::Bind(&ShillError, "GetProperties"));
1185  }
1186}
1187
1188void WifiConfigView::InitFromProperties(
1189    bool show_8021x,
1190    const std::string& service_path,
1191    const base::DictionaryValue& properties) {
1192  if (!show_8021x) {
1193    std::string passphrase;
1194    properties.GetStringWithoutPathExpansion(
1195        shill::kPassphraseProperty, &passphrase);
1196    passphrase_textfield_->SetText(base::UTF8ToUTF16(passphrase));
1197    return;
1198  }
1199
1200  // EAP Method
1201  std::string eap_method;
1202  properties.GetStringWithoutPathExpansion(
1203      shill::kEapMethodProperty, &eap_method);
1204  if (eap_method == shill::kEapMethodPEAP)
1205    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP);
1206  else if (eap_method == shill::kEapMethodTTLS)
1207    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS);
1208  else if (eap_method == shill::kEapMethodTLS)
1209    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS);
1210  else if (eap_method == shill::kEapMethodLEAP)
1211    eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP);
1212  RefreshEapFields();
1213
1214  // Phase 2 authentication and anonymous identity.
1215  if (Phase2AuthActive()) {
1216    std::string eap_phase_2_auth;
1217    properties.GetStringWithoutPathExpansion(
1218        shill::kEapPhase2AuthProperty, &eap_phase_2_auth);
1219    if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSMD5)
1220      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5);
1221    else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSMSCHAPV2)
1222      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2);
1223    else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSMSCHAP)
1224      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP);
1225    else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSPAP)
1226      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP);
1227    else if (eap_phase_2_auth == shill::kEapPhase2AuthTTLSCHAP)
1228      phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP);
1229
1230    std::string eap_anonymous_identity;
1231    properties.GetStringWithoutPathExpansion(
1232        shill::kEapAnonymousIdentityProperty, &eap_anonymous_identity);
1233    identity_anonymous_textfield_->SetText(
1234        base::UTF8ToUTF16(eap_anonymous_identity));
1235  }
1236
1237  // Subject match
1238  std::string subject_match;
1239  properties.GetStringWithoutPathExpansion(
1240      shill::kEapSubjectMatchProperty, &subject_match);
1241  subject_match_textfield_->SetText(base::UTF8ToUTF16(subject_match));
1242
1243  // Server CA certificate.
1244  if (CaCertActive()) {
1245    std::string eap_ca_cert_pem;
1246    const base::ListValue* pems = NULL;
1247    if (properties.GetListWithoutPathExpansion(
1248            shill::kEapCaCertPemProperty, &pems))
1249      pems->GetString(0, &eap_ca_cert_pem);
1250    if (eap_ca_cert_pem.empty()) {
1251      bool eap_use_system_cas = false;
1252      properties.GetBooleanWithoutPathExpansion(
1253          shill::kEapUseSystemCasProperty, &eap_use_system_cas);
1254      if (eap_use_system_cas) {
1255        // "Default"
1256        server_ca_cert_combobox_->SetSelectedIndex(0);
1257      } else {
1258        // "Do not check".
1259        server_ca_cert_combobox_->SetSelectedIndex(
1260            server_ca_cert_combobox_->model()->GetItemCount() - 1);
1261      }
1262    } else {
1263      // Select the certificate if available.
1264      int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
1265          CertLibrary::CERT_TYPE_SERVER_CA, eap_ca_cert_pem);
1266      if (cert_index >= 0) {
1267        // Skip item for "Default".
1268        server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
1269      } else {
1270        // "Default"
1271        server_ca_cert_combobox_->SetSelectedIndex(0);
1272      }
1273    }
1274  }
1275
1276  // User certificate.
1277  if (UserCertActive()) {
1278    std::string eap_cert_id;
1279    properties.GetStringWithoutPathExpansion(
1280        shill::kEapCertIdProperty, &eap_cert_id);
1281    if (!eap_cert_id.empty()) {
1282      int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
1283          CertLibrary::CERT_TYPE_USER, eap_cert_id);
1284      if (cert_index >= 0)
1285        user_cert_combobox_->SetSelectedIndex(cert_index);
1286    }
1287  }
1288
1289  // Identity is always active.
1290  std::string eap_identity;
1291  properties.GetStringWithoutPathExpansion(
1292      shill::kEapIdentityProperty, &eap_identity);
1293  identity_textfield_->SetText(base::UTF8ToUTF16(eap_identity));
1294
1295  // Passphrase
1296  if (PassphraseActive()) {
1297    std::string eap_password;
1298    properties.GetStringWithoutPathExpansion(
1299        shill::kEapPasswordProperty, &eap_password);
1300    passphrase_textfield_->SetText(base::UTF8ToUTF16(eap_password));
1301    // If 'Connectable' is True, show a fake passphrase to indicate that it
1302    // has already been set.
1303    bool connectable = false;
1304    properties.GetBooleanWithoutPathExpansion(
1305        shill::kConnectableProperty, &connectable);
1306    passphrase_textfield_->SetShowFake(connectable);
1307  }
1308
1309  // Save credentials
1310  bool save_credentials = false;
1311  properties.GetBooleanWithoutPathExpansion(
1312      shill::kSaveCredentialsProperty, &save_credentials);
1313  save_credentials_checkbox_->SetChecked(save_credentials);
1314
1315  UpdateDialogButtons();
1316  RefreshShareCheckbox();
1317  UpdateErrorLabel();
1318}
1319
1320void WifiConfigView::InitFocus() {
1321  views::View* view_to_focus = GetInitiallyFocusedView();
1322  if (view_to_focus)
1323    view_to_focus->RequestFocus();
1324}
1325
1326void WifiConfigView::NetworkPropertiesUpdated(const NetworkState* network) {
1327  if (network->path() != service_path_)
1328    return;
1329  UpdateErrorLabel();
1330}
1331
1332// static
1333void WifiConfigView::ParseWiFiUIProperty(
1334    NetworkPropertyUIData* property_ui_data,
1335    const NetworkState* network,
1336    const std::string& key) {
1337  ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
1338  const base::DictionaryValue* onc =
1339      onc::FindPolicyForActiveUser(network->guid(), &onc_source);
1340
1341  property_ui_data->ParseOncProperty(
1342      onc_source,
1343      onc,
1344      base::StringPrintf("%s.%s", ::onc::network_config::kWiFi, key.c_str()));
1345}
1346
1347// static
1348void WifiConfigView::ParseWiFiEAPUIProperty(
1349    NetworkPropertyUIData* property_ui_data,
1350    const NetworkState* network,
1351    const std::string& key) {
1352  ParseWiFiUIProperty(
1353      property_ui_data, network,
1354      base::StringPrintf("%s.%s", ::onc::wifi::kEAP, key.c_str()));
1355}
1356
1357}  // namespace chromeos
1358