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