1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/options/wifi_config_view.h"
6
7#include "base/command_line.h"  // TODO(jamescook): Remove.
8#include "base/string_util.h"
9#include "base/utf_string_conversions.h"
10#include "chrome/browser/chromeos/cros/cros_library.h"
11#include "chrome/browser/chromeos/login/user_manager.h"
12#include "chrome/browser/chromeos/options/wifi_config_model.h"
13#include "chrome/common/chrome_switches.h"  // TODO(jamescook): Remove.
14#include "grit/chromium_strings.h"
15#include "grit/generated_resources.h"
16#include "grit/locale_settings.h"
17#include "grit/theme_resources.h"
18#include "ui/base/l10n/l10n_util.h"
19#include "ui/base/resource/resource_bundle.h"
20#include "views/controls/button/checkbox.h"
21#include "views/controls/button/image_button.h"
22#include "views/controls/button/native_button.h"
23#include "views/controls/label.h"
24#include "views/controls/textfield/textfield.h"
25#include "views/layout/grid_layout.h"
26#include "views/layout/layout_constants.h"
27#include "views/window/window.h"
28
29namespace chromeos {
30
31namespace {
32
33enum SecurityComboboxIndex {
34  SECURITY_INDEX_NONE  = 0,
35  SECURITY_INDEX_WEP   = 1,
36  SECURITY_INDEX_WPA   = 2,
37  SECURITY_INDEX_RSN   = 3,
38  SECURITY_INDEX_COUNT = 4
39};
40
41class SecurityComboboxModel : public ui::ComboboxModel {
42 public:
43  SecurityComboboxModel() {}
44  virtual ~SecurityComboboxModel() {}
45  virtual int GetItemCount() {
46    return SECURITY_INDEX_COUNT;
47  }
48  virtual string16 GetItemAt(int index) {
49    if (index == SECURITY_INDEX_NONE)
50      return l10n_util::GetStringUTF16(
51          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY_NONE);
52    else if (index == SECURITY_INDEX_WEP)
53      return l10n_util::GetStringUTF16(
54          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY_WEP);
55    else if (index == SECURITY_INDEX_WPA)
56      return l10n_util::GetStringUTF16(
57          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY_WPA);
58    else if (index == SECURITY_INDEX_RSN)
59      return l10n_util::GetStringUTF16(
60          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY_RSN);
61    NOTREACHED();
62    return string16();
63  }
64 private:
65  DISALLOW_COPY_AND_ASSIGN(SecurityComboboxModel);
66};
67
68// TODO(jamescook):  For M12 we only expose PEAP and EAP-TTLS.  Later, when
69// when we support all methods by default, order this list to be alphabetical.
70enum EAPMethodComboboxIndex {
71  EAP_METHOD_INDEX_NONE  = 0,
72  EAP_METHOD_INDEX_PEAP  = 1,
73  EAP_METHOD_INDEX_TTLS  = 2,  // By default we support up to here.
74  EAP_METHOD_INDEX_TLS   = 3,
75  EAP_METHOD_INDEX_LEAP  = 4,  // Flag "--enable-all-eap" allows up to here.
76  EAP_METHOD_INDEX_COUNT = 5
77};
78
79class EAPMethodComboboxModel : public ui::ComboboxModel {
80 public:
81  EAPMethodComboboxModel() {}
82  virtual ~EAPMethodComboboxModel() {}
83  virtual int GetItemCount() {
84    // TODO(jamescook):  For M12 we only expose PEAP and EAP-TTLS by default.
85    // Remove this switch when all methods are supported.
86    if (!CommandLine::ForCurrentProcess()->HasSwitch(
87        switches::kEnableExperimentalEap))
88      return EAP_METHOD_INDEX_TTLS + 1;
89    return EAP_METHOD_INDEX_COUNT;
90  }
91  virtual string16 GetItemAt(int index) {
92    if (index == EAP_METHOD_INDEX_NONE)
93      return l10n_util::GetStringUTF16(
94          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_NONE);
95    else if (index == EAP_METHOD_INDEX_PEAP)
96      return l10n_util::GetStringUTF16(
97          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_PEAP);
98    else if (index == EAP_METHOD_INDEX_TLS)
99      return l10n_util::GetStringUTF16(
100          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_TLS);
101    else if (index == EAP_METHOD_INDEX_TTLS)
102      return l10n_util::GetStringUTF16(
103          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_TTLS);
104    else if (index == EAP_METHOD_INDEX_LEAP)
105      return l10n_util::GetStringUTF16(
106          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD_LEAP);
107    NOTREACHED();
108    return string16();
109  }
110 private:
111  DISALLOW_COPY_AND_ASSIGN(EAPMethodComboboxModel);
112};
113
114enum Phase2AuthComboboxIndex {
115  PHASE_2_AUTH_INDEX_AUTO     = 0, // LEAP, EAP-TLS have only this auth.
116  PHASE_2_AUTH_INDEX_MD5      = 1,
117  PHASE_2_AUTH_INDEX_MSCHAPV2 = 2, // PEAP has up to this auth.
118  PHASE_2_AUTH_INDEX_MSCHAP   = 3,
119  PHASE_2_AUTH_INDEX_PAP      = 4,
120  PHASE_2_AUTH_INDEX_CHAP     = 5, // EAP-TTLS has up to this auth.
121  PHASE_2_AUTH_INDEX_COUNT    = 6
122};
123
124class Phase2AuthComboboxModel : public ui::ComboboxModel {
125 public:
126  explicit Phase2AuthComboboxModel(views::Combobox* eap_method_combobox)
127      : eap_method_combobox_(eap_method_combobox) {}
128  virtual ~Phase2AuthComboboxModel() {}
129  virtual int GetItemCount() {
130    switch (eap_method_combobox_->selected_item()) {
131      case EAP_METHOD_INDEX_NONE:
132      case EAP_METHOD_INDEX_TLS:
133      case EAP_METHOD_INDEX_LEAP:
134        return PHASE_2_AUTH_INDEX_AUTO + 1;
135      case EAP_METHOD_INDEX_PEAP:
136        return PHASE_2_AUTH_INDEX_MSCHAPV2 + 1;
137      case EAP_METHOD_INDEX_TTLS:
138        return PHASE_2_AUTH_INDEX_CHAP + 1;
139    }
140    NOTREACHED();
141    return 0;
142  }
143  virtual string16 GetItemAt(int index) {
144    if (index == PHASE_2_AUTH_INDEX_AUTO)
145      return l10n_util::GetStringUTF16(
146          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_AUTO);
147    else if (index == PHASE_2_AUTH_INDEX_MD5)
148      return l10n_util::GetStringUTF16(
149          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_MD5);
150    else if (index == PHASE_2_AUTH_INDEX_MSCHAPV2)
151      return l10n_util::GetStringUTF16(
152          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_MSCHAPV2);
153    else if (index == PHASE_2_AUTH_INDEX_MSCHAP)
154      return l10n_util::GetStringUTF16(
155          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_MSCHAP);
156    else if (index == PHASE_2_AUTH_INDEX_PAP)
157      return l10n_util::GetStringUTF16(
158          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_PAP);
159    else if (index == PHASE_2_AUTH_INDEX_CHAP)
160      return l10n_util::GetStringUTF16(
161          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH_CHAP);
162    NOTREACHED();
163    return string16();
164  }
165 private:
166  views::Combobox* eap_method_combobox_;
167  DISALLOW_COPY_AND_ASSIGN(Phase2AuthComboboxModel);
168};
169
170// Combobox that supports a preferred width.  Used by Server CA combobox
171// because the strings inside it are too wide.
172class ComboboxWithWidth : public views::Combobox {
173 public:
174  ComboboxWithWidth(ui::ComboboxModel* model, int width)
175      : Combobox(model),
176        width_(width) {
177  }
178  virtual ~ComboboxWithWidth() {}
179  virtual gfx::Size GetPreferredSize() OVERRIDE {
180    gfx::Size size = Combobox::GetPreferredSize();
181    size.set_width(width_);
182    return size;
183  }
184 private:
185  int width_;
186  DISALLOW_COPY_AND_ASSIGN(ComboboxWithWidth);
187};
188
189class ServerCACertComboboxModel : public ui::ComboboxModel {
190 public:
191  explicit ServerCACertComboboxModel(WifiConfigModel* wifi_config_model)
192      : wifi_config_model_(wifi_config_model) {
193  }
194  virtual ~ServerCACertComboboxModel() {}
195  virtual int GetItemCount() {
196    // First "Default", then the certs, then "Do not check".
197    return wifi_config_model_->GetServerCaCertCount() + 2;
198  }
199  virtual string16 GetItemAt(int combo_index) {
200    if (combo_index == 0)
201      return l10n_util::GetStringUTF16(
202          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT);
203    if (combo_index == GetItemCount() - 1)
204      return l10n_util::GetStringUTF16(
205          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DO_NOT_CHECK);
206    int cert_index = combo_index - 1;
207    return wifi_config_model_->GetServerCaCertName(cert_index);
208  }
209 private:
210  WifiConfigModel* wifi_config_model_;
211  DISALLOW_COPY_AND_ASSIGN(ServerCACertComboboxModel);
212};
213
214class ClientCertComboboxModel : public ui::ComboboxModel {
215 public:
216  explicit ClientCertComboboxModel(WifiConfigModel* wifi_config_model)
217      : wifi_config_model_(wifi_config_model) {
218  }
219  virtual ~ClientCertComboboxModel() {}
220  virtual int GetItemCount() {
221    // One initial item "None", then the certs.
222    return 1 + wifi_config_model_->GetUserCertCount();
223  }
224  virtual string16 GetItemAt(int combo_index) {
225    if (combo_index == 0)
226      return l10n_util::GetStringUTF16(
227          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_NONE);
228    int cert_index = combo_index - 1;
229    return wifi_config_model_->GetUserCertName(cert_index);
230  }
231 private:
232  WifiConfigModel* wifi_config_model_;
233  DISALLOW_COPY_AND_ASSIGN(ClientCertComboboxModel);
234};
235
236}  // namespace
237
238WifiConfigView::WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi)
239    : ChildNetworkConfigView(parent, wifi),
240      wifi_config_model_(new WifiConfigModel()),
241      is_8021x_(false),
242      ssid_textfield_(NULL),
243      eap_method_combobox_(NULL),
244      phase_2_auth_label_(NULL),
245      phase_2_auth_combobox_(NULL),
246      client_cert_label_(NULL),
247      client_cert_combobox_(NULL),
248      server_ca_cert_label_(NULL),
249      server_ca_cert_combobox_(NULL),
250      identity_label_(NULL),
251      identity_textfield_(NULL),
252      identity_anonymous_label_(NULL),
253      identity_anonymous_textfield_(NULL),
254      save_credentials_checkbox_(NULL),
255      security_combobox_(NULL),
256      passphrase_label_(NULL),
257      passphrase_textfield_(NULL),
258      passphrase_visible_button_(NULL),
259      error_label_(NULL) {
260  Init(wifi);
261}
262
263WifiConfigView::WifiConfigView(NetworkConfigView* parent)
264    : ChildNetworkConfigView(parent),
265      wifi_config_model_(new WifiConfigModel()),
266      is_8021x_(false),
267      ssid_textfield_(NULL),
268      eap_method_combobox_(NULL),
269      phase_2_auth_label_(NULL),
270      phase_2_auth_combobox_(NULL),
271      client_cert_label_(NULL),
272      client_cert_combobox_(NULL),
273      server_ca_cert_label_(NULL),
274      server_ca_cert_combobox_(NULL),
275      identity_label_(NULL),
276      identity_textfield_(NULL),
277      identity_anonymous_label_(NULL),
278      identity_anonymous_textfield_(NULL),
279      save_credentials_checkbox_(NULL),
280      security_combobox_(NULL),
281      passphrase_label_(NULL),
282      passphrase_textfield_(NULL),
283      passphrase_visible_button_(NULL),
284      error_label_(NULL) {
285  Init(NULL);
286}
287
288WifiConfigView::~WifiConfigView() {
289}
290
291string16 WifiConfigView::GetTitle() {
292  return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_JOIN_WIFI_NETWORKS);
293}
294
295bool WifiConfigView::CanLogin() {
296  static const size_t kMinWirelessPasswordLen = 5;
297
298  if (service_path_.empty()) {
299    // Enforce ssid is non empty.
300    if (GetSSID().empty())
301      return false;
302
303    // If security is not none, also enforce passphrase is non empty.
304    if (security_combobox_->selected_item() != SECURITY_INDEX_NONE &&
305        passphrase_textfield_->text().length() < kMinWirelessPasswordLen)
306      return false;
307  } else {
308    if (is_8021x_) {
309      // Make sure the EAP method is set
310      if (eap_method_combobox_->selected_item() == EAP_METHOD_INDEX_NONE)
311        return false;
312    } else {
313      // if the network requires a passphrase, make sure it is the right length.
314      if (passphrase_textfield_ != NULL &&
315          passphrase_textfield_->text().length() < kMinWirelessPasswordLen)
316        return false;
317    }
318  }
319  return true;
320}
321
322void WifiConfigView::UpdateDialogButtons() {
323  parent_->GetDialogClientView()->UpdateDialogButtons();
324}
325
326void WifiConfigView::RefreshEAPFields() {
327  int selected = eap_method_combobox_->selected_item();
328
329  // If EAP method changes, the phase 2 auth choices may have changed also.
330  phase_2_auth_combobox_->ModelChanged();
331  phase_2_auth_combobox_->SetSelectedItem(0);
332  phase_2_auth_combobox_->SetEnabled(
333      phase_2_auth_combobox_->model()->GetItemCount() > 1);
334  phase_2_auth_label_->SetEnabled(phase_2_auth_combobox_->IsEnabled());
335
336  // No password for EAP-TLS
337  passphrase_textfield_->SetEnabled(selected != EAP_METHOD_INDEX_NONE &&
338                                    selected != EAP_METHOD_INDEX_TLS);
339  passphrase_label_->SetEnabled(passphrase_textfield_->IsEnabled());
340  if (!passphrase_textfield_->IsEnabled())
341    passphrase_textfield_->SetText(string16());
342
343  // Client certs only for EAP-TLS
344  if (client_cert_combobox_) {
345    client_cert_combobox_->SetEnabled(selected == EAP_METHOD_INDEX_TLS);
346    client_cert_label_->SetEnabled(client_cert_combobox_->IsEnabled());
347  }
348
349  // No server CA certs for LEAP
350  server_ca_cert_combobox_->SetEnabled(selected != EAP_METHOD_INDEX_NONE &&
351                                       selected != EAP_METHOD_INDEX_LEAP);
352  server_ca_cert_label_->SetEnabled(server_ca_cert_combobox_->IsEnabled());
353
354  // No anonymous identity if no phase 2 auth.
355  identity_anonymous_textfield_->SetEnabled(
356      phase_2_auth_combobox_->IsEnabled());
357  identity_anonymous_label_->SetEnabled(
358      identity_anonymous_textfield_->IsEnabled());
359  if (!identity_anonymous_textfield_->IsEnabled())
360    identity_anonymous_textfield_->SetText(string16());
361}
362
363void WifiConfigView::UpdateErrorLabel() {
364  std::string error_msg;
365  if (!service_path_.empty()) {
366    NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
367    const WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_);
368    if (wifi && wifi->failed()) {
369      bool passphrase_empty = wifi->GetPassphrase().empty();
370      switch (wifi->error()) {
371        case ERROR_BAD_PASSPHRASE:
372          if (!passphrase_empty) {
373            error_msg = l10n_util::GetStringUTF8(
374                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
375          }
376          break;
377        case ERROR_BAD_WEPKEY:
378          if (!passphrase_empty) {
379            error_msg = l10n_util::GetStringUTF8(
380                IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY);
381          }
382          break;
383        default:
384          error_msg = wifi->GetErrorString();
385          break;
386      }
387    }
388  }
389  if (!error_msg.empty()) {
390    error_label_->SetText(UTF8ToWide(error_msg));
391    error_label_->SetVisible(true);
392  } else {
393    error_label_->SetVisible(false);
394  }
395}
396
397void WifiConfigView::ContentsChanged(views::Textfield* sender,
398                                     const string16& new_contents) {
399  UpdateDialogButtons();
400}
401
402bool WifiConfigView::HandleKeyEvent(views::Textfield* sender,
403                                    const views::KeyEvent& key_event) {
404  if (sender == passphrase_textfield_ &&
405      key_event.key_code() == ui::VKEY_RETURN) {
406    parent_->GetDialogClientView()->AcceptWindow();
407  }
408  return false;
409}
410
411void WifiConfigView::ButtonPressed(views::Button* sender,
412                                   const views::Event& event) {
413  if (sender == passphrase_visible_button_) {
414    if (passphrase_textfield_)
415      passphrase_textfield_->SetPassword(!passphrase_textfield_->IsPassword());
416  } else {
417    NOTREACHED();
418  }
419}
420
421void WifiConfigView::ItemChanged(views::Combobox* combo_box,
422                                 int prev_index, int new_index) {
423  if (new_index == prev_index)
424    return;
425  if (combo_box == security_combobox_) {
426    // If changed to no security, then disable combobox and clear it.
427    // Otherwise, enable it. Also, update can login.
428    if (new_index == SECURITY_INDEX_NONE) {
429      passphrase_label_->SetEnabled(false);
430      passphrase_textfield_->SetEnabled(false);
431      passphrase_textfield_->SetText(string16());
432    } else {
433      passphrase_label_->SetEnabled(true);
434      passphrase_textfield_->SetEnabled(true);
435    }
436  } else if (combo_box == eap_method_combobox_) {
437    RefreshEAPFields();
438  }
439  UpdateDialogButtons();
440}
441
442bool WifiConfigView::Login() {
443  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
444  if (service_path_.empty()) {
445    ConnectionSecurity sec = SECURITY_UNKNOWN;
446    switch (security_combobox_->selected_item()) {
447      case SECURITY_INDEX_NONE:
448        sec = SECURITY_NONE;
449        break;
450      case SECURITY_INDEX_WEP:
451        sec = SECURITY_WEP;
452        break;
453      case SECURITY_INDEX_WPA:
454        sec = SECURITY_WPA;
455        break;
456      case SECURITY_INDEX_RSN:
457        sec = SECURITY_RSN;
458        break;
459    }
460    cros->ConnectToWifiNetwork(
461        sec, GetSSID(), GetPassphrase(), std::string(), std::string());
462  } else {
463    WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_);
464    if (!wifi) {
465      // Flimflam no longer knows about this wifi network (edge case).
466      // TODO(stevenjb): Add a notification (chromium-os13225).
467      LOG(WARNING) << "Wifi network: " << service_path_ << " no longer exists.";
468      return true;
469    }
470    if (is_8021x_) {
471      // EAP method
472      EAPMethod method = EAP_METHOD_UNKNOWN;
473      switch (eap_method_combobox_->selected_item()) {
474        case EAP_METHOD_INDEX_PEAP:
475          method = EAP_METHOD_PEAP;
476          break;
477        case EAP_METHOD_INDEX_TLS:
478          method = EAP_METHOD_TLS;
479          break;
480        case EAP_METHOD_INDEX_TTLS:
481          method = EAP_METHOD_TTLS;
482          break;
483        case EAP_METHOD_INDEX_LEAP:
484          method = EAP_METHOD_LEAP;
485          break;
486      }
487      DCHECK(method != EAP_METHOD_UNKNOWN);
488      wifi->SetEAPMethod(method);
489
490      // Phase 2 authentication
491      if (phase_2_auth_combobox_->IsEnabled()) {
492        EAPPhase2Auth auth = EAP_PHASE_2_AUTH_AUTO;
493        switch (phase_2_auth_combobox_->selected_item()) {
494          case PHASE_2_AUTH_INDEX_MD5:
495            auth = EAP_PHASE_2_AUTH_MD5;
496            break;
497          case PHASE_2_AUTH_INDEX_MSCHAPV2:
498            auth = EAP_PHASE_2_AUTH_MSCHAPV2;
499            break;
500          case PHASE_2_AUTH_INDEX_MSCHAP:
501            auth = EAP_PHASE_2_AUTH_MSCHAP;
502            break;
503          case PHASE_2_AUTH_INDEX_PAP:
504            auth = EAP_PHASE_2_AUTH_PAP;
505            break;
506          case PHASE_2_AUTH_INDEX_CHAP:
507            auth = EAP_PHASE_2_AUTH_CHAP;
508            break;
509        }
510        wifi->SetEAPPhase2Auth(auth);
511      }
512
513      // Server CA certificate
514      if (server_ca_cert_combobox_->IsEnabled()) {
515        int selected = server_ca_cert_combobox_->selected_item();
516        if (selected == 0) {
517          // First item is "Default".
518          wifi->SetEAPServerCaCertNssNickname(std::string());
519          wifi->SetEAPUseSystemCAs(true);
520        } else if (selected ==
521            server_ca_cert_combobox_->model()->GetItemCount() - 1) {
522          // Last item is "Do not check".
523          wifi->SetEAPServerCaCertNssNickname(std::string());
524          wifi->SetEAPUseSystemCAs(false);
525        } else {
526          int cert_index = selected - 1;
527          std::string nss_nickname =
528              wifi_config_model_->GetServerCaCertNssNickname(cert_index);
529          wifi->SetEAPServerCaCertNssNickname(nss_nickname);
530        }
531      }
532
533      // Client certificate
534      if (client_cert_combobox_ && client_cert_combobox_->IsEnabled()) {
535        int selected = client_cert_combobox_->selected_item();
536        if (selected == 0) {
537          // First item is "None".
538          wifi->SetEAPClientCertPkcs11Id(std::string());
539        } else {
540          // Send cert ID to flimflam.
541          int cert_index = selected - 1;
542          std::string cert_pkcs11_id =
543              wifi_config_model_->GetUserCertPkcs11Id(cert_index);
544          wifi->SetEAPClientCertPkcs11Id(cert_pkcs11_id);
545        }
546      }
547
548      // Identity
549      if (identity_textfield_->IsEnabled()) {
550        wifi->SetEAPIdentity(UTF16ToUTF8(identity_textfield_->text()));
551      }
552
553      // Anonymous identity
554      if (identity_anonymous_textfield_->IsEnabled()) {
555        wifi->SetEAPAnonymousIdentity(
556            UTF16ToUTF8(identity_anonymous_textfield_->text()));
557      }
558
559      // Passphrase
560      if (passphrase_textfield_->IsEnabled()) {
561        wifi->SetEAPPassphrase(UTF16ToUTF8(passphrase_textfield_->text()));
562      }
563
564      // Save credentials
565      wifi->SetSaveCredentials(save_credentials_checkbox_->checked());
566    } else {
567      const std::string passphrase = GetPassphrase();
568      if (passphrase != wifi->passphrase())
569        wifi->SetPassphrase(passphrase);
570    }
571
572    cros->ConnectToWifiNetwork(wifi);
573    // Connection failures are responsible for updating the UI, including
574    // reopening dialogs.
575  }
576  return true;  // dialog will be closed
577}
578
579void WifiConfigView::Cancel() {
580}
581
582std::string WifiConfigView::GetSSID() const {
583  std::string result;
584  if (ssid_textfield_ != NULL) {
585    std::string untrimmed = UTF16ToUTF8(ssid_textfield_->text());
586    TrimWhitespaceASCII(untrimmed, TRIM_ALL, &result);
587  }
588  return result;
589}
590
591std::string WifiConfigView::GetPassphrase() const {
592  std::string result;
593  if (passphrase_textfield_ != NULL)
594    result = UTF16ToUTF8(passphrase_textfield_->text());
595  return result;
596}
597
598// This will initialize the view depending on if we have a wifi network or not.
599// And if we are doing simple password encyption or the more complicated
600// 802.1x encryption.
601// If we are creating the "Join other network..." dialog, we will allow user
602// to enter the data. And if they select the 802.1x encryption, we will show
603// the 802.1x fields.
604void WifiConfigView::Init(WifiNetwork* wifi) {
605  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
606  SetLayoutManager(layout);
607
608  int column_view_set_id = 0;
609  views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
610  // Label
611  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
612                        views::GridLayout::USE_PREF, 0, 0);
613  // Textfield
614  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
615                        views::GridLayout::USE_PREF, 0,
616                        ChildNetworkConfigView::kPassphraseWidth);
617  // Password visible button
618  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL, 1,
619                        views::GridLayout::USE_PREF, 0, 0);
620
621  // SSID input
622  layout->StartRow(0, column_view_set_id);
623  layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
624      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID))));
625  if (!wifi) {
626    ssid_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
627    ssid_textfield_->SetController(this);
628    ssid_textfield_->SetAccessibleName(l10n_util::GetStringUTF16(
629        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID));
630    layout->AddView(ssid_textfield_);
631  } else {
632    views::Label* label = new views::Label(UTF8ToWide(wifi->name()));
633    label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
634    layout->AddView(label);
635  }
636  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
637
638  // Security select
639  if (!wifi) {
640    layout->StartRow(0, column_view_set_id);
641    layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
642          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY))));
643    security_combobox_ = new views::Combobox(new SecurityComboboxModel());
644    security_combobox_->set_listener(this);
645    layout->AddView(security_combobox_);
646    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
647  }
648
649  is_8021x_ = wifi && wifi->encrypted() &&
650      wifi->encryption() == SECURITY_8021X;
651  if (is_8021x_) {
652    // Only enumerate certificates in the data model for 802.1X networks.
653    wifi_config_model_->UpdateCertificates();
654
655    // EAP method
656    layout->StartRow(0, column_view_set_id);
657    layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
658        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_EAP_METHOD))));
659    eap_method_combobox_ = new views::Combobox(new EAPMethodComboboxModel());
660    eap_method_combobox_->set_listener(this);
661    layout->AddView(eap_method_combobox_);
662    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
663
664    // Phase 2 authentication
665    layout->StartRow(0, column_view_set_id);
666    phase_2_auth_label_ =
667        new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
668            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PHASE_2_AUTH)));
669    layout->AddView(phase_2_auth_label_);
670    phase_2_auth_combobox_ = new views::Combobox(
671        new Phase2AuthComboboxModel(eap_method_combobox_));
672    phase_2_auth_label_->SetEnabled(false);
673    phase_2_auth_combobox_->SetEnabled(false);
674    phase_2_auth_combobox_->set_listener(this);
675    layout->AddView(phase_2_auth_combobox_);
676    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
677
678    // Server CA certificate
679    layout->StartRow(0, column_view_set_id);
680    server_ca_cert_label_ =
681        new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
682            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA)));
683    layout->AddView(server_ca_cert_label_);
684    server_ca_cert_combobox_ = new ComboboxWithWidth(
685        new ServerCACertComboboxModel(wifi_config_model_.get()),
686        ChildNetworkConfigView::kPassphraseWidth);
687    server_ca_cert_label_->SetEnabled(false);
688    server_ca_cert_combobox_->SetEnabled(false);
689    server_ca_cert_combobox_->set_listener(this);
690    layout->AddView(server_ca_cert_combobox_);
691    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
692
693    // TODO(jamescook): Add back client certificate combobox when we support
694    // EAP-TLS by default.
695    if (CommandLine::ForCurrentProcess()->HasSwitch(
696        switches::kEnableExperimentalEap)) {
697      // Client certificate
698      layout->StartRow(0, column_view_set_id);
699      client_cert_label_ = new views::Label(
700          UTF16ToWide(l10n_util::GetStringUTF16(
701              IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT)));
702      layout->AddView(client_cert_label_);
703      client_cert_combobox_ = new views::Combobox(
704          new ClientCertComboboxModel(wifi_config_model_.get()));
705      client_cert_label_->SetEnabled(false);
706      client_cert_combobox_->SetEnabled(false);
707      client_cert_combobox_->set_listener(this);
708      layout->AddView(client_cert_combobox_);
709      layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
710    }
711
712    // Identity
713    layout->StartRow(0, column_view_set_id);
714    identity_label_ = new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
715        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_IDENTITY)));
716    layout->AddView(identity_label_);
717    identity_textfield_ = new views::Textfield(
718        views::Textfield::STYLE_DEFAULT);
719    identity_textfield_->SetController(this);
720    if (!wifi->identity().empty())
721      identity_textfield_->SetText(UTF8ToUTF16(wifi->identity()));
722    layout->AddView(identity_textfield_);
723    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
724  }
725
726  // Passphrase input
727  layout->StartRow(0, column_view_set_id);
728  int label_text_id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE;
729  passphrase_label_ = new views::Label(
730      UTF16ToWide(l10n_util::GetStringUTF16(label_text_id)));
731  layout->AddView(passphrase_label_);
732  passphrase_textfield_ = new views::Textfield(
733      views::Textfield::STYLE_PASSWORD);
734  passphrase_textfield_->SetController(this);
735  if (wifi && !wifi->GetPassphrase().empty())
736    passphrase_textfield_->SetText(UTF8ToUTF16(wifi->GetPassphrase()));
737  // Disable passphrase input initially for other network.
738  if (!wifi) {
739    passphrase_label_->SetEnabled(false);
740    passphrase_textfield_->SetEnabled(false);
741  }
742  passphrase_textfield_->SetAccessibleName(l10n_util::GetStringUTF16(
743      label_text_id));
744  layout->AddView(passphrase_textfield_);
745  // Password visible button.
746  passphrase_visible_button_ = new views::ImageButton(this);
747  passphrase_visible_button_->SetImage(
748      views::ImageButton::BS_NORMAL,
749      ResourceBundle::GetSharedInstance().
750      GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
751  passphrase_visible_button_->SetImageAlignment(
752      views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE);
753  layout->AddView(passphrase_visible_button_);
754  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
755
756  if (is_8021x_) {
757    // Anonymous identity
758    layout->StartRow(0, column_view_set_id);
759    identity_anonymous_label_ =
760        new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
761            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_IDENTITY_ANONYMOUS)));
762    layout->AddView(identity_anonymous_label_);
763    identity_anonymous_textfield_ = new views::Textfield(
764        views::Textfield::STYLE_DEFAULT);
765    identity_anonymous_label_->SetEnabled(false);
766    identity_anonymous_textfield_->SetEnabled(false);
767    identity_anonymous_textfield_->SetController(this);
768    layout->AddView(identity_anonymous_textfield_);
769    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
770
771    // Save credentials
772    layout->StartRow(0, column_view_set_id);
773    save_credentials_checkbox_ = new views::Checkbox(
774        UTF16ToWide(l10n_util::GetStringUTF16(
775            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS)));
776    layout->SkipColumns(1);
777    layout->AddView(save_credentials_checkbox_);
778    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
779  }
780
781  // After creating the fields, we set the values. Fields need to be created
782  // first because RefreshEAPFields() will enable/disable them as appropriate.
783  if (is_8021x_) {
784    // EAP Method
785    switch (wifi->eap_method()) {
786      case EAP_METHOD_PEAP:
787        eap_method_combobox_->SetSelectedItem(EAP_METHOD_INDEX_PEAP);
788        break;
789      case EAP_METHOD_TTLS:
790        eap_method_combobox_->SetSelectedItem(EAP_METHOD_INDEX_TTLS);
791        break;
792      case EAP_METHOD_TLS:
793        if (CommandLine::ForCurrentProcess()->HasSwitch(
794                switches::kEnableExperimentalEap))
795          eap_method_combobox_->SetSelectedItem(EAP_METHOD_INDEX_TLS);
796        else // Clean up from previous run with the switch set.
797          eap_method_combobox_->SetSelectedItem(EAP_METHOD_INDEX_NONE);
798        break;
799      case EAP_METHOD_LEAP:
800        if (CommandLine::ForCurrentProcess()->HasSwitch(
801                switches::kEnableExperimentalEap))
802          eap_method_combobox_->SetSelectedItem(EAP_METHOD_INDEX_LEAP);
803        else // Clean up from previous run with the switch set.
804          eap_method_combobox_->SetSelectedItem(EAP_METHOD_INDEX_NONE);
805        break;
806      default:
807        break;
808    }
809    RefreshEAPFields();
810
811    // Phase 2 authentication
812    if (phase_2_auth_combobox_->IsEnabled()) {
813      switch (wifi->eap_phase_2_auth()) {
814        case EAP_PHASE_2_AUTH_MD5:
815          phase_2_auth_combobox_->SetSelectedItem(PHASE_2_AUTH_INDEX_MD5);
816          break;
817        case EAP_PHASE_2_AUTH_MSCHAPV2:
818          phase_2_auth_combobox_->SetSelectedItem(PHASE_2_AUTH_INDEX_MSCHAPV2);
819          break;
820        case EAP_PHASE_2_AUTH_MSCHAP:
821          phase_2_auth_combobox_->SetSelectedItem(PHASE_2_AUTH_INDEX_MSCHAP);
822          break;
823        case EAP_PHASE_2_AUTH_PAP:
824          phase_2_auth_combobox_->SetSelectedItem(PHASE_2_AUTH_INDEX_PAP);
825          break;
826        case EAP_PHASE_2_AUTH_CHAP:
827          phase_2_auth_combobox_->SetSelectedItem(PHASE_2_AUTH_INDEX_CHAP);
828          break;
829        default:
830          break;
831      }
832    }
833
834    // Server CA certificate
835    if (server_ca_cert_combobox_->IsEnabled()) {
836      const std::string& nss_nickname = wifi->eap_server_ca_cert_nss_nickname();
837      if (nss_nickname.empty()) {
838        if (wifi->eap_use_system_cas()) {
839          // "Default"
840          server_ca_cert_combobox_->SetSelectedItem(0);
841        } else {
842          // "Do not check"
843          server_ca_cert_combobox_->SetSelectedItem(
844              server_ca_cert_combobox_->model()->GetItemCount() - 1);
845        }
846      } else {
847        // select the certificate if available
848        int cert_index = wifi_config_model_->GetServerCaCertIndex(nss_nickname);
849        if (cert_index >= 0) {
850          // Skip item for "Default"
851          server_ca_cert_combobox_->SetSelectedItem(1 + cert_index);
852        }
853      }
854    }
855
856    // Client certificate
857    if (client_cert_combobox_ && client_cert_combobox_->IsEnabled()) {
858      const std::string& pkcs11_id = wifi->eap_client_cert_pkcs11_id();
859      if (pkcs11_id.empty()) {
860        // First item is "None".
861        client_cert_combobox_->SetSelectedItem(0);
862      } else {
863        int cert_index = wifi_config_model_->GetUserCertIndex(pkcs11_id);
864        if (cert_index >= 0) {
865          // Skip item for "None"
866          client_cert_combobox_->SetSelectedItem(1 + cert_index);
867        }
868      }
869    }
870
871    // Identity
872    if (identity_textfield_->IsEnabled())
873      identity_textfield_->SetText(UTF8ToUTF16(wifi->eap_identity()));
874
875    // Anonymous identity
876    if (identity_anonymous_textfield_->IsEnabled())
877      identity_anonymous_textfield_->SetText(
878          UTF8ToUTF16(wifi->eap_anonymous_identity()));
879
880    // Passphrase
881    if (passphrase_textfield_->IsEnabled())
882      passphrase_textfield_->SetText(UTF8ToUTF16(wifi->eap_passphrase()));
883
884    // Save credentials
885    bool save_credentials = (wifi ? wifi->save_credentials() : false);
886    save_credentials_checkbox_->SetChecked(save_credentials);
887  }
888
889  // Create an error label.
890  layout->StartRow(0, column_view_set_id);
891  layout->SkipColumns(1);
892  error_label_ = new views::Label();
893  error_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
894  error_label_->SetColor(SK_ColorRED);
895  layout->AddView(error_label_);
896
897  // Set or hide the error text.
898  UpdateErrorLabel();
899}
900
901void WifiConfigView::InitFocus() {
902  // Set focus to a reasonable widget, depending on what we're showing.
903  if (ssid_textfield_)
904    ssid_textfield_->RequestFocus();
905  else if (eap_method_combobox_)
906    eap_method_combobox_->RequestFocus();
907  else if (passphrase_textfield_ && passphrase_textfield_->IsEnabled())
908    passphrase_textfield_->RequestFocus();
909}
910
911}  // namespace chromeos
912