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