Home | History | Annotate | Download | only in options
      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/vpn_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/profiles/profile_manager.h"
     14 #include "chrome/common/net/x509_certificate_model.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_state.h"
     19 #include "chromeos/network/network_state_handler.h"
     20 #include "chromeos/network/network_ui_data.h"
     21 #include "components/onc/onc_constants.h"
     22 #include "grit/chromium_strings.h"
     23 #include "grit/generated_resources.h"
     24 #include "grit/locale_settings.h"
     25 #include "grit/theme_resources.h"
     26 #include "third_party/cros_system_api/dbus/service_constants.h"
     27 #include "ui/base/l10n/l10n_util.h"
     28 #include "ui/base/models/combobox_model.h"
     29 #include "ui/base/resource/resource_bundle.h"
     30 #include "ui/events/event.h"
     31 #include "ui/views/controls/button/checkbox.h"
     32 #include "ui/views/controls/combobox/combobox.h"
     33 #include "ui/views/controls/label.h"
     34 #include "ui/views/controls/textfield/textfield.h"
     35 #include "ui/views/layout/grid_layout.h"
     36 #include "ui/views/layout/layout_constants.h"
     37 #include "ui/views/widget/widget.h"
     38 #include "ui/views/window/dialog_client_view.h"
     39 
     40 namespace {
     41 
     42 enum ProviderTypeIndex {
     43   PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK = 0,
     44   PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT = 1,
     45   PROVIDER_TYPE_INDEX_OPEN_VPN = 2,
     46   PROVIDER_TYPE_INDEX_MAX = 3,
     47 };
     48 
     49 base::string16 ProviderTypeIndexToString(int index) {
     50   switch (index) {
     51     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
     52       return l10n_util::GetStringUTF16(
     53           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK);
     54     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
     55       return l10n_util::GetStringUTF16(
     56           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT);
     57     case PROVIDER_TYPE_INDEX_OPEN_VPN:
     58       return l10n_util::GetStringUTF16(
     59           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN);
     60   }
     61   NOTREACHED();
     62   return base::string16();
     63 }
     64 
     65 int ProviderTypeToIndex(const std::string& provider_type,
     66                         const std::string& client_cert_id) {
     67   if (provider_type == shill::kProviderL2tpIpsec) {
     68     if (!client_cert_id.empty())
     69       return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
     70     else
     71       return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK;
     72   } else {
     73     DCHECK(provider_type == shill::kProviderOpenVpn);
     74     return PROVIDER_TYPE_INDEX_OPEN_VPN;
     75   }
     76 }
     77 
     78 // Translates the provider type to the name of the respective ONC dictionary
     79 // containing configuration data for the type.
     80 std::string ProviderTypeIndexToONCDictKey(int provider_type_index) {
     81   switch (provider_type_index) {
     82     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
     83     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
     84       return onc::vpn::kIPsec;
     85     case PROVIDER_TYPE_INDEX_OPEN_VPN:
     86       return onc::vpn::kOpenVPN;
     87   }
     88   NOTREACHED() << "Unhandled provider type index " << provider_type_index;
     89   return std::string();
     90 }
     91 
     92 std::string GetPemFromDictionary(
     93     const base::DictionaryValue* provider_properties,
     94     const std::string& key) {
     95   const base::ListValue* pems = NULL;
     96   if (!provider_properties->GetListWithoutPathExpansion(key, &pems))
     97     return std::string();
     98   std::string pem;
     99   pems->GetString(0, &pem);
    100   return pem;
    101 }
    102 
    103 }  // namespace
    104 
    105 namespace chromeos {
    106 
    107 namespace internal {
    108 
    109 class ProviderTypeComboboxModel : public ui::ComboboxModel {
    110  public:
    111   ProviderTypeComboboxModel();
    112   virtual ~ProviderTypeComboboxModel();
    113 
    114   // Overridden from ui::ComboboxModel:
    115   virtual int GetItemCount() const OVERRIDE;
    116   virtual base::string16 GetItemAt(int index) OVERRIDE;
    117 
    118  private:
    119   DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel);
    120 };
    121 
    122 class VpnServerCACertComboboxModel : public ui::ComboboxModel {
    123  public:
    124   VpnServerCACertComboboxModel();
    125   virtual ~VpnServerCACertComboboxModel();
    126 
    127   // Overridden from ui::ComboboxModel:
    128   virtual int GetItemCount() const OVERRIDE;
    129   virtual base::string16 GetItemAt(int index) OVERRIDE;
    130 
    131  private:
    132   DISALLOW_COPY_AND_ASSIGN(VpnServerCACertComboboxModel);
    133 };
    134 
    135 class VpnUserCertComboboxModel : public ui::ComboboxModel {
    136  public:
    137   VpnUserCertComboboxModel();
    138   virtual ~VpnUserCertComboboxModel();
    139 
    140   // Overridden from ui::ComboboxModel:
    141   virtual int GetItemCount() const OVERRIDE;
    142   virtual base::string16 GetItemAt(int index) OVERRIDE;
    143 
    144  private:
    145   DISALLOW_COPY_AND_ASSIGN(VpnUserCertComboboxModel);
    146 };
    147 
    148 // ProviderTypeComboboxModel ---------------------------------------------------
    149 
    150 ProviderTypeComboboxModel::ProviderTypeComboboxModel() {
    151 }
    152 
    153 ProviderTypeComboboxModel::~ProviderTypeComboboxModel() {
    154 }
    155 
    156 int ProviderTypeComboboxModel::GetItemCount() const {
    157   return PROVIDER_TYPE_INDEX_MAX;
    158 }
    159 
    160 base::string16 ProviderTypeComboboxModel::GetItemAt(int index) {
    161   return ProviderTypeIndexToString(index);
    162 }
    163 
    164 // VpnServerCACertComboboxModel ------------------------------------------------
    165 
    166 VpnServerCACertComboboxModel::VpnServerCACertComboboxModel() {
    167 }
    168 
    169 VpnServerCACertComboboxModel::~VpnServerCACertComboboxModel() {
    170 }
    171 
    172 int VpnServerCACertComboboxModel::GetItemCount() const {
    173   if (CertLibrary::Get()->CertificatesLoading())
    174     return 1;  // "Loading"
    175   // "Default" + certs.
    176   return CertLibrary::Get()->NumCertificates(
    177       CertLibrary::CERT_TYPE_SERVER_CA) + 1;
    178 }
    179 
    180 base::string16 VpnServerCACertComboboxModel::GetItemAt(int index) {
    181   if (CertLibrary::Get()->CertificatesLoading())
    182     return l10n_util::GetStringUTF16(
    183         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING);
    184   if (index == 0)
    185     return l10n_util::GetStringUTF16(
    186         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT);
    187   int cert_index = index - 1;
    188   return CertLibrary::Get()->GetCertDisplayStringAt(
    189       CertLibrary::CERT_TYPE_SERVER_CA, cert_index);
    190 }
    191 
    192 // VpnUserCertComboboxModel ----------------------------------------------------
    193 
    194 VpnUserCertComboboxModel::VpnUserCertComboboxModel() {
    195 }
    196 
    197 VpnUserCertComboboxModel::~VpnUserCertComboboxModel() {
    198 }
    199 
    200 int VpnUserCertComboboxModel::GetItemCount() const {
    201   if (CertLibrary::Get()->CertificatesLoading())
    202     return 1;  // "Loading"
    203   int num_certs =
    204       CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER);
    205   if (num_certs == 0)
    206     return 1;  // "None installed"
    207   return num_certs;
    208 }
    209 
    210 base::string16 VpnUserCertComboboxModel::GetItemAt(int index) {
    211   if (CertLibrary::Get()->CertificatesLoading()) {
    212     return l10n_util::GetStringUTF16(
    213         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING);
    214   }
    215   if (CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) == 0) {
    216     return l10n_util::GetStringUTF16(
    217         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USER_CERT_NONE_INSTALLED);
    218   }
    219   return CertLibrary::Get()->GetCertDisplayStringAt(
    220       CertLibrary::CERT_TYPE_USER, index);
    221 }
    222 
    223 }  // namespace internal
    224 
    225 VPNConfigView::VPNConfigView(NetworkConfigView* parent,
    226                              const std::string& service_path)
    227     : ChildNetworkConfigView(parent, service_path),
    228       service_text_modified_(false),
    229       enable_psk_passphrase_(false),
    230       enable_user_cert_(false),
    231       enable_server_ca_cert_(false),
    232       enable_otp_(false),
    233       enable_group_name_(false),
    234       title_(0),
    235       layout_(NULL),
    236       server_textfield_(NULL),
    237       service_text_(NULL),
    238       service_textfield_(NULL),
    239       provider_type_combobox_(NULL),
    240       provider_type_text_label_(NULL),
    241       psk_passphrase_label_(NULL),
    242       psk_passphrase_textfield_(NULL),
    243       user_cert_label_(NULL),
    244       user_cert_combobox_(NULL),
    245       server_ca_cert_label_(NULL),
    246       server_ca_cert_combobox_(NULL),
    247       username_textfield_(NULL),
    248       user_passphrase_textfield_(NULL),
    249       otp_label_(NULL),
    250       otp_textfield_(NULL),
    251       group_name_label_(NULL),
    252       group_name_textfield_(NULL),
    253       save_credentials_checkbox_(NULL),
    254       error_label_(NULL),
    255       provider_type_index_(PROVIDER_TYPE_INDEX_MAX),
    256       weak_ptr_factory_(this) {
    257   Init();
    258 }
    259 
    260 VPNConfigView::~VPNConfigView() {
    261   RemoveAllChildViews(true);  // Destroy children before models
    262   CertLibrary::Get()->RemoveObserver(this);
    263 }
    264 
    265 base::string16 VPNConfigView::GetTitle() const {
    266   DCHECK_NE(title_, 0);
    267   return l10n_util::GetStringUTF16(title_);
    268 }
    269 
    270 views::View* VPNConfigView::GetInitiallyFocusedView() {
    271   if (service_path_.empty()) {
    272     // Put focus in the first editable field.
    273     if (server_textfield_)
    274       return server_textfield_;
    275     else if (service_textfield_)
    276       return service_textfield_;
    277     else if (provider_type_combobox_)
    278       return provider_type_combobox_;
    279     else if (psk_passphrase_textfield_ && psk_passphrase_textfield_->enabled())
    280       return psk_passphrase_textfield_;
    281     else if (user_cert_combobox_ && user_cert_combobox_->enabled())
    282       return user_cert_combobox_;
    283     else if (server_ca_cert_combobox_ && server_ca_cert_combobox_->enabled())
    284       return server_ca_cert_combobox_;
    285   }
    286   if (user_passphrase_textfield_)
    287     return user_passphrase_textfield_;
    288   else if (otp_textfield_)
    289     return otp_textfield_;
    290   return NULL;
    291 }
    292 
    293 bool VPNConfigView::CanLogin() {
    294   // Username is always required.
    295   if (GetUsername().empty())
    296     return false;
    297 
    298   // TODO(stevenjb): min kMinPassphraseLen length?
    299   if (service_path_.empty() &&
    300       (GetService().empty() || GetServer().empty()))
    301     return false;
    302 
    303   // Block login if certs are required but user has none.
    304   bool cert_required =
    305       GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
    306   if (cert_required && (!HaveUserCerts() || !IsUserCertValid()))
    307     return false;
    308 
    309   return true;
    310 }
    311 
    312 void VPNConfigView::ContentsChanged(views::Textfield* sender,
    313                                     const base::string16& new_contents) {
    314   if (sender == server_textfield_ && !service_text_modified_) {
    315     // Set the service name to the server name up to '.', unless it has
    316     // been explicitly set by the user.
    317     base::string16 server = server_textfield_->text();
    318     base::string16::size_type n = server.find_first_of(L'.');
    319     service_name_from_server_ = server.substr(0, n);
    320     service_textfield_->SetText(service_name_from_server_);
    321   }
    322   if (sender == service_textfield_) {
    323     if (new_contents.empty())
    324       service_text_modified_ = false;
    325     else if (new_contents != service_name_from_server_)
    326       service_text_modified_ = true;
    327   }
    328   UpdateCanLogin();
    329 }
    330 
    331 bool VPNConfigView::HandleKeyEvent(views::Textfield* sender,
    332                                    const ui::KeyEvent& key_event) {
    333   if ((sender == psk_passphrase_textfield_ ||
    334        sender == user_passphrase_textfield_) &&
    335       key_event.key_code() == ui::VKEY_RETURN) {
    336     parent_->GetDialogClientView()->AcceptWindow();
    337   }
    338   return false;
    339 }
    340 
    341 void VPNConfigView::ButtonPressed(views::Button* sender,
    342                                   const ui::Event& event) {
    343 }
    344 
    345 void VPNConfigView::OnSelectedIndexChanged(views::Combobox* combobox) {
    346   UpdateControls();
    347   UpdateErrorLabel();
    348   UpdateCanLogin();
    349 }
    350 
    351 void VPNConfigView::OnCertificatesLoaded(bool initial_load) {
    352   Refresh();
    353 }
    354 
    355 bool VPNConfigView::Login() {
    356   if (service_path_.empty()) {
    357     base::DictionaryValue properties;
    358     // Identifying properties
    359     properties.SetStringWithoutPathExpansion(
    360         shill::kTypeProperty, shill::kTypeVPN);
    361     properties.SetStringWithoutPathExpansion(
    362         shill::kNameProperty, GetService());
    363     properties.SetStringWithoutPathExpansion(
    364         shill::kProviderHostProperty, GetServer());
    365     properties.SetStringWithoutPathExpansion(
    366         shill::kProviderTypeProperty, GetProviderTypeString());
    367 
    368     SetConfigProperties(&properties);
    369     bool shared = !LoginState::Get()->IsUserAuthenticated();
    370 
    371     bool only_policy_autoconnect =
    372         onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!shared);
    373     if (only_policy_autoconnect) {
    374       properties.SetBooleanWithoutPathExpansion(shill::kAutoConnectProperty,
    375                                                 false);
    376     }
    377 
    378     ash::network_connect::CreateConfigurationAndConnect(&properties, shared);
    379   } else {
    380     const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
    381         GetNetworkState(service_path_);
    382     if (!vpn) {
    383       // Shill no longer knows about this network (edge case).
    384       // TODO(stevenjb): Add notification for this.
    385       NET_LOG_ERROR("Network not found", service_path_);
    386       return true;  // Close dialog
    387     }
    388     base::DictionaryValue properties;
    389     SetConfigProperties(&properties);
    390     ash::network_connect::ConfigureNetworkAndConnect(
    391         service_path_, properties, false /* not shared */);
    392   }
    393   return true;  // Close dialog.
    394 }
    395 
    396 void VPNConfigView::Cancel() {
    397 }
    398 
    399 void VPNConfigView::InitFocus() {
    400   views::View* view_to_focus = GetInitiallyFocusedView();
    401   if (view_to_focus)
    402     view_to_focus->RequestFocus();
    403 }
    404 
    405 const std::string VPNConfigView::GetService() const {
    406   if (service_textfield_ != NULL)
    407     return GetTextFromField(service_textfield_, true);
    408   return service_path_;
    409 }
    410 
    411 const std::string VPNConfigView::GetServer() const {
    412   if (server_textfield_ != NULL)
    413     return GetTextFromField(server_textfield_, true);
    414   return std::string();
    415 }
    416 
    417 const std::string VPNConfigView::GetPSKPassphrase() const {
    418   if (psk_passphrase_textfield_ &&
    419       enable_psk_passphrase_ &&
    420       psk_passphrase_textfield_->visible())
    421     return GetPassphraseFromField(psk_passphrase_textfield_);
    422   return std::string();
    423 }
    424 
    425 const std::string VPNConfigView::GetUsername() const {
    426   return GetTextFromField(username_textfield_, true);
    427 }
    428 
    429 const std::string VPNConfigView::GetUserPassphrase() const {
    430   return GetPassphraseFromField(user_passphrase_textfield_);
    431 }
    432 
    433 const std::string VPNConfigView::GetGroupName() const {
    434   return GetTextFromField(group_name_textfield_, false);
    435 }
    436 
    437 const std::string VPNConfigView::GetOTP() const {
    438   return GetTextFromField(otp_textfield_, true);
    439 }
    440 
    441 const std::string VPNConfigView::GetServerCACertPEM() const {
    442   int index = server_ca_cert_combobox_ ?
    443       server_ca_cert_combobox_->selected_index() : 0;
    444   if (index == 0) {
    445     // First item is "Default".
    446     return std::string();
    447   } else {
    448     int cert_index = index - 1;
    449     return CertLibrary::Get()->GetCertPEMAt(
    450         CertLibrary::CERT_TYPE_SERVER_CA, cert_index);
    451   }
    452 }
    453 
    454 const std::string VPNConfigView::GetUserCertID() const {
    455   if (!HaveUserCerts()) {
    456     return std::string();  // "None installed"
    457   } else {
    458     // Certificates are listed in the order they appear in the model.
    459     int index = user_cert_combobox_ ? user_cert_combobox_->selected_index() : 0;
    460     return CertLibrary::Get()->GetCertPkcs11IdAt(
    461         CertLibrary::CERT_TYPE_USER, index);
    462   }
    463 }
    464 
    465 bool VPNConfigView::GetSaveCredentials() const {
    466   return save_credentials_checkbox_->checked();
    467 }
    468 
    469 int VPNConfigView::GetProviderTypeIndex() const {
    470   if (provider_type_combobox_)
    471     return provider_type_combobox_->selected_index();
    472   return provider_type_index_;
    473 }
    474 
    475 std::string VPNConfigView::GetProviderTypeString() const {
    476   int index = GetProviderTypeIndex();
    477   switch (index) {
    478     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
    479     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
    480       return shill::kProviderL2tpIpsec;
    481     case PROVIDER_TYPE_INDEX_OPEN_VPN:
    482       return shill::kProviderOpenVpn;
    483   }
    484   NOTREACHED();
    485   return std::string();
    486 }
    487 
    488 void VPNConfigView::Init() {
    489   const NetworkState* vpn = NULL;
    490   if (!service_path_.empty()) {
    491     vpn = NetworkHandler::Get()->network_state_handler()->
    492         GetNetworkState(service_path_);
    493     DCHECK(vpn && vpn->type() == shill::kTypeVPN);
    494   }
    495   layout_ = views::GridLayout::CreatePanel(this);
    496   SetLayoutManager(layout_);
    497 
    498   // Observer any changes to the certificate list.
    499   CertLibrary::Get()->AddObserver(this);
    500 
    501   views::ColumnSet* column_set = layout_->AddColumnSet(0);
    502   // Label.
    503   column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
    504                         views::GridLayout::USE_PREF, 0, 0);
    505   column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
    506   // Textfield, combobox.
    507   column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
    508                         views::GridLayout::USE_PREF, 0,
    509                         ChildNetworkConfigView::kInputFieldMinWidth);
    510   column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
    511   // Policy indicator.
    512   column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
    513                         views::GridLayout::USE_PREF, 0, 0);
    514 
    515   // Initialize members.
    516   service_text_modified_ = false;
    517   title_ = vpn ? IDS_OPTIONS_SETTINGS_JOIN_VPN : IDS_OPTIONS_SETTINGS_ADD_VPN;
    518 
    519   // By default enable all controls.
    520   enable_psk_passphrase_ = true;
    521   enable_user_cert_ = true;
    522   enable_server_ca_cert_ = true;
    523   enable_otp_ = true;
    524   enable_group_name_ = true;
    525 
    526   // Server label and input.
    527   layout_->StartRow(0, 0);
    528   views::View* server_label =
    529       new views::Label(l10n_util::GetStringUTF16(
    530           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME));
    531   layout_->AddView(server_label);
    532   server_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
    533   server_textfield_->SetController(this);
    534   layout_->AddView(server_textfield_);
    535   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    536   if (!service_path_.empty()) {
    537     server_label->SetEnabled(false);
    538     server_textfield_->SetEnabled(false);
    539   }
    540 
    541   // Service label and name or input.
    542   layout_->StartRow(0, 0);
    543   layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
    544       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME)));
    545   if (service_path_.empty()) {
    546     service_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
    547     service_textfield_->SetController(this);
    548     layout_->AddView(service_textfield_);
    549     service_text_ = NULL;
    550   } else {
    551     service_text_ = new views::Label();
    552     service_text_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    553     layout_->AddView(service_text_);
    554     service_textfield_ = NULL;
    555   }
    556   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    557 
    558   // Provider type label and select.
    559   layout_->StartRow(0, 0);
    560   layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
    561       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE)));
    562   if (service_path_.empty()) {
    563     provider_type_combobox_model_.reset(
    564         new internal::ProviderTypeComboboxModel);
    565     provider_type_combobox_ = new views::Combobox(
    566         provider_type_combobox_model_.get());
    567     provider_type_combobox_->set_listener(this);
    568     layout_->AddView(provider_type_combobox_);
    569     provider_type_text_label_ = NULL;
    570   } else {
    571     provider_type_text_label_ = new views::Label();
    572     provider_type_text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    573     layout_->AddView(provider_type_text_label_);
    574     provider_type_combobox_ = NULL;
    575   }
    576   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    577 
    578   // PSK passphrase label, input and visible button.
    579   layout_->StartRow(0, 0);
    580   psk_passphrase_label_ =  new views::Label(l10n_util::GetStringUTF16(
    581       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE));
    582   layout_->AddView(psk_passphrase_label_);
    583   psk_passphrase_textfield_ = new PassphraseTextfield();
    584   psk_passphrase_textfield_->SetController(this);
    585   layout_->AddView(psk_passphrase_textfield_);
    586   layout_->AddView(
    587       new ControlledSettingIndicatorView(psk_passphrase_ui_data_));
    588   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    589 
    590   // Server CA certificate
    591   if (service_path_.empty()) {
    592     layout_->StartRow(0, 0);
    593     server_ca_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
    594         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA));
    595     layout_->AddView(server_ca_cert_label_);
    596     server_ca_cert_combobox_model_.reset(
    597         new internal::VpnServerCACertComboboxModel());
    598     server_ca_cert_combobox_ = new views::Combobox(
    599         server_ca_cert_combobox_model_.get());
    600     layout_->AddView(server_ca_cert_combobox_);
    601     layout_->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_));
    602     layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    603   } else {
    604     server_ca_cert_label_ = NULL;
    605     server_ca_cert_combobox_ = NULL;
    606   }
    607 
    608   // User certificate label and input.
    609   layout_->StartRow(0, 0);
    610   user_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
    611       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT));
    612   layout_->AddView(user_cert_label_);
    613   user_cert_combobox_model_.reset(
    614       new internal::VpnUserCertComboboxModel());
    615   user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get());
    616   user_cert_combobox_->set_listener(this);
    617   layout_->AddView(user_cert_combobox_);
    618   layout_->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_));
    619   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    620 
    621   // Username label and input.
    622   layout_->StartRow(0, 0);
    623   layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
    624       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME)));
    625   username_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
    626   username_textfield_->SetController(this);
    627   username_textfield_->SetEnabled(username_ui_data_.IsEditable());
    628   layout_->AddView(username_textfield_);
    629   layout_->AddView(new ControlledSettingIndicatorView(username_ui_data_));
    630   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    631 
    632   // User passphrase label, input and visble button.
    633   layout_->StartRow(0, 0);
    634   layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
    635       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE)));
    636   user_passphrase_textfield_ = new PassphraseTextfield();
    637   user_passphrase_textfield_->SetController(this);
    638   user_passphrase_textfield_->SetEnabled(user_passphrase_ui_data_.IsEditable());
    639   layout_->AddView(user_passphrase_textfield_);
    640   layout_->AddView(
    641       new ControlledSettingIndicatorView(user_passphrase_ui_data_));
    642   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    643 
    644   // OTP label and input.
    645   layout_->StartRow(0, 0);
    646   otp_label_ = new views::Label(l10n_util::GetStringUTF16(
    647       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP));
    648   layout_->AddView(otp_label_);
    649   otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
    650   otp_textfield_->SetController(this);
    651   layout_->AddView(otp_textfield_);
    652   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    653 
    654   // Group Name label and input.
    655   layout_->StartRow(0, 0);
    656   group_name_label_ = new views::Label(l10n_util::GetStringUTF16(
    657       IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME));
    658   layout_->AddView(group_name_label_);
    659   group_name_textfield_ =
    660       new views::Textfield(views::Textfield::STYLE_DEFAULT);
    661   group_name_textfield_->SetController(this);
    662   layout_->AddView(group_name_textfield_);
    663   layout_->AddView(new ControlledSettingIndicatorView(group_name_ui_data_));
    664   layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    665 
    666   // Save credentials
    667   layout_->StartRow(0, 0);
    668   save_credentials_checkbox_ = new views::Checkbox(
    669       l10n_util::GetStringUTF16(
    670           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS));
    671   save_credentials_checkbox_->SetEnabled(
    672       save_credentials_ui_data_.IsEditable());
    673   layout_->SkipColumns(1);
    674   layout_->AddView(save_credentials_checkbox_);
    675   layout_->AddView(
    676       new ControlledSettingIndicatorView(save_credentials_ui_data_));
    677 
    678   // Error label.
    679   layout_->StartRow(0, 0);
    680   layout_->SkipColumns(1);
    681   error_label_ = new views::Label();
    682   error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    683   error_label_->SetEnabledColor(SK_ColorRED);
    684   layout_->AddView(error_label_);
    685 
    686   // Set or hide the UI, update comboboxes and error labels.
    687   Refresh();
    688 
    689   if (vpn) {
    690     NetworkHandler::Get()->network_configuration_handler()->GetProperties(
    691         service_path_,
    692         base::Bind(&VPNConfigView::InitFromProperties,
    693                    weak_ptr_factory_.GetWeakPtr()),
    694         base::Bind(&VPNConfigView::GetPropertiesError,
    695                    weak_ptr_factory_.GetWeakPtr()));
    696   }
    697 }
    698 
    699 void VPNConfigView::InitFromProperties(
    700     const std::string& service_path,
    701     const base::DictionaryValue& service_properties) {
    702   const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
    703       GetNetworkState(service_path);
    704   if (!vpn) {
    705     NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path);
    706     return;
    707   }
    708 
    709   std::string provider_type, server_hostname, username, group_name;
    710   bool psk_passphrase_required = false;
    711   const base::DictionaryValue* provider_properties;
    712   if (service_properties.GetDictionaryWithoutPathExpansion(
    713           shill::kProviderProperty, &provider_properties)) {
    714     provider_properties->GetStringWithoutPathExpansion(
    715         shill::kTypeProperty, &provider_type);
    716     provider_properties->GetStringWithoutPathExpansion(
    717         shill::kHostProperty, &server_hostname);
    718   }
    719   if (provider_type == shill::kProviderL2tpIpsec) {
    720     provider_properties->GetStringWithoutPathExpansion(
    721         shill::kL2tpIpsecClientCertIdProperty, &client_cert_id_);
    722     ca_cert_pem_ = GetPemFromDictionary(
    723         provider_properties, shill::kL2tpIpsecCaCertPemProperty);
    724     provider_properties->GetBooleanWithoutPathExpansion(
    725         shill::kL2tpIpsecPskRequiredProperty, &psk_passphrase_required);
    726     provider_properties->GetStringWithoutPathExpansion(
    727         shill::kL2tpIpsecUserProperty, &username);
    728     provider_properties->GetStringWithoutPathExpansion(
    729         shill::kL2tpIpsecTunnelGroupProperty, &group_name);
    730   } else if (provider_type == shill::kProviderOpenVpn) {
    731     provider_properties->GetStringWithoutPathExpansion(
    732         shill::kOpenVPNClientCertIdProperty, &client_cert_id_);
    733     ca_cert_pem_ = GetPemFromDictionary(
    734         provider_properties, shill::kOpenVPNCaCertPemProperty);
    735     provider_properties->GetStringWithoutPathExpansion(
    736         shill::kOpenVPNUserProperty, &username);
    737   }
    738   bool save_credentials = false;
    739   service_properties.GetBooleanWithoutPathExpansion(
    740       shill::kSaveCredentialsProperty, &save_credentials);
    741 
    742   provider_type_index_ = ProviderTypeToIndex(provider_type, client_cert_id_);
    743 
    744   if (service_text_)
    745     service_text_->SetText(ASCIIToUTF16(vpn->name()));
    746   if (provider_type_text_label_)
    747     provider_type_text_label_->SetText(
    748         ProviderTypeIndexToString(provider_type_index_));
    749 
    750   if (server_textfield_ && !server_hostname.empty())
    751     server_textfield_->SetText(UTF8ToUTF16(server_hostname));
    752   if (username_textfield_ && !username.empty())
    753     username_textfield_->SetText(UTF8ToUTF16(username));
    754   if (group_name_textfield_ && !group_name.empty())
    755     group_name_textfield_->SetText(UTF8ToUTF16(group_name));
    756   if (psk_passphrase_textfield_)
    757     psk_passphrase_textfield_->SetShowFake(!psk_passphrase_required);
    758   if (save_credentials_checkbox_)
    759     save_credentials_checkbox_->SetChecked(save_credentials);
    760 
    761   Refresh();
    762 }
    763 
    764 void VPNConfigView::ParseUIProperties(const NetworkState* vpn) {
    765   std::string type_dict_name =
    766       ProviderTypeIndexToONCDictKey(provider_type_index_);
    767   if (provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) {
    768     ParseVPNUIProperty(vpn, type_dict_name, ::onc::ipsec::kServerCARef,
    769                        &ca_cert_ui_data_);
    770     ParseVPNUIProperty(vpn, type_dict_name, ::onc::ipsec::kPSK,
    771                        &psk_passphrase_ui_data_);
    772     ParseVPNUIProperty(vpn, type_dict_name, ::onc::ipsec::kGroup,
    773                        &group_name_ui_data_);
    774   } else if (provider_type_index_ == PROVIDER_TYPE_INDEX_OPEN_VPN) {
    775     ParseVPNUIProperty(vpn, type_dict_name, ::onc::openvpn::kServerCARef,
    776                        &ca_cert_ui_data_);
    777   }
    778   ParseVPNUIProperty(vpn, type_dict_name, ::onc::vpn::kClientCertRef,
    779                      &user_cert_ui_data_);
    780 
    781   const std::string credentials_dict_name(
    782       provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK ?
    783       ::onc::vpn::kL2TP : type_dict_name);
    784   ParseVPNUIProperty(vpn, credentials_dict_name, ::onc::vpn::kUsername,
    785                      &username_ui_data_);
    786   ParseVPNUIProperty(vpn, credentials_dict_name, ::onc::vpn::kPassword,
    787                      &user_passphrase_ui_data_);
    788   ParseVPNUIProperty(vpn, credentials_dict_name, ::onc::vpn::kSaveCredentials,
    789                      &save_credentials_ui_data_);
    790 }
    791 
    792 void VPNConfigView::GetPropertiesError(
    793     const std::string& error_name,
    794     scoped_ptr<base::DictionaryValue> error_data) {
    795   NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, "");
    796 }
    797 
    798 void VPNConfigView::SetConfigProperties(
    799     base::DictionaryValue* properties) {
    800   int provider_type_index = GetProviderTypeIndex();
    801   std::string user_passphrase = GetUserPassphrase();
    802   std::string user_name = GetUsername();
    803   std::string group_name = GetGroupName();
    804   switch (provider_type_index) {
    805     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: {
    806       std::string psk_passphrase = GetPSKPassphrase();
    807       if (!psk_passphrase.empty()) {
    808         properties->SetStringWithoutPathExpansion(
    809             shill::kL2tpIpsecPskProperty, GetPSKPassphrase());
    810       }
    811       if (!group_name.empty()) {
    812         properties->SetStringWithoutPathExpansion(
    813             shill::kL2tpIpsecTunnelGroupProperty, group_name);
    814       }
    815       if (!user_name.empty()) {
    816         properties->SetStringWithoutPathExpansion(
    817             shill::kL2tpIpsecUserProperty, user_name);
    818       }
    819       if (!user_passphrase.empty()) {
    820         properties->SetStringWithoutPathExpansion(
    821             shill::kL2tpIpsecPasswordProperty, user_passphrase);
    822       }
    823       break;
    824     }
    825     case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: {
    826       std::string ca_cert_pem = GetServerCACertPEM();
    827       if (!ca_cert_pem.empty()) {
    828         base::ListValue* pem_list = new base::ListValue;
    829         pem_list->AppendString(ca_cert_pem);
    830         properties->SetWithoutPathExpansion(
    831             shill::kL2tpIpsecCaCertPemProperty, pem_list);
    832       }
    833       properties->SetStringWithoutPathExpansion(
    834           shill::kL2tpIpsecClientCertIdProperty, GetUserCertID());
    835       if (!group_name.empty()) {
    836         properties->SetStringWithoutPathExpansion(
    837             shill::kL2tpIpsecTunnelGroupProperty, GetGroupName());
    838       }
    839       if (!user_name.empty()) {
    840         properties->SetStringWithoutPathExpansion(
    841             shill::kL2tpIpsecUserProperty, user_name);
    842       }
    843       if (!user_passphrase.empty()) {
    844         properties->SetStringWithoutPathExpansion(
    845             shill::kL2tpIpsecPasswordProperty, user_passphrase);
    846       }
    847       break;
    848     }
    849     case PROVIDER_TYPE_INDEX_OPEN_VPN: {
    850       std::string ca_cert_pem = GetServerCACertPEM();
    851       if (!ca_cert_pem.empty()) {
    852         base::ListValue* pem_list = new base::ListValue;
    853         pem_list->AppendString(ca_cert_pem);
    854         properties->SetWithoutPathExpansion(
    855             shill::kOpenVPNCaCertPemProperty, pem_list);
    856       }
    857       properties->SetStringWithoutPathExpansion(
    858           shill::kOpenVPNClientCertIdProperty, GetUserCertID());
    859       properties->SetStringWithoutPathExpansion(
    860           shill::kOpenVPNUserProperty, GetUsername());
    861       if (!user_passphrase.empty()) {
    862         properties->SetStringWithoutPathExpansion(
    863             shill::kOpenVPNPasswordProperty, user_passphrase);
    864       }
    865       std::string otp = GetOTP();
    866       if (!otp.empty()) {
    867         properties->SetStringWithoutPathExpansion(
    868             shill::kOpenVPNOTPProperty, otp);
    869       }
    870       break;
    871     }
    872     case PROVIDER_TYPE_INDEX_MAX:
    873       NOTREACHED();
    874       break;
    875   }
    876   properties->SetBooleanWithoutPathExpansion(
    877       shill::kSaveCredentialsProperty, GetSaveCredentials());
    878 }
    879 
    880 void VPNConfigView::Refresh() {
    881   UpdateControls();
    882 
    883   // Set certificate combo boxes.
    884   if (server_ca_cert_combobox_) {
    885     server_ca_cert_combobox_->ModelChanged();
    886     if (enable_server_ca_cert_ && !ca_cert_pem_.empty()) {
    887       // Select the current server CA certificate in the combobox.
    888       int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
    889           CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem_);
    890       if (cert_index >= 0) {
    891         // Skip item for "Default"
    892         server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
    893       } else {
    894         server_ca_cert_combobox_->SetSelectedIndex(0);
    895       }
    896     } else {
    897       server_ca_cert_combobox_->SetSelectedIndex(0);
    898     }
    899   }
    900 
    901   if (user_cert_combobox_) {
    902     user_cert_combobox_->ModelChanged();
    903     if (enable_user_cert_ && !client_cert_id_.empty()) {
    904       int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
    905           CertLibrary::CERT_TYPE_USER, client_cert_id_);
    906       if (cert_index >= 0)
    907         user_cert_combobox_->SetSelectedIndex(cert_index);
    908       else
    909         user_cert_combobox_->SetSelectedIndex(0);
    910     } else {
    911       user_cert_combobox_->SetSelectedIndex(0);
    912     }
    913   }
    914 
    915   UpdateErrorLabel();
    916 }
    917 
    918 void VPNConfigView::UpdateControlsToEnable() {
    919   enable_psk_passphrase_ = false;
    920   enable_user_cert_ = false;
    921   enable_server_ca_cert_ = false;
    922   enable_otp_ = false;
    923   enable_group_name_ = false;
    924   int provider_type_index = GetProviderTypeIndex();
    925   if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) {
    926     enable_psk_passphrase_ = true;
    927     enable_group_name_ = true;
    928   } else if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT) {
    929     enable_server_ca_cert_ = true;
    930     enable_user_cert_ = HaveUserCerts();
    931     enable_group_name_ = true;
    932   } else {  // PROVIDER_TYPE_INDEX_OPEN_VPN (default)
    933     enable_server_ca_cert_ = true;
    934     enable_user_cert_ = HaveUserCerts();
    935     enable_otp_ = true;
    936   }
    937 }
    938 
    939 void VPNConfigView::UpdateControls() {
    940   UpdateControlsToEnable();
    941 
    942   if (psk_passphrase_label_)
    943     psk_passphrase_label_->SetEnabled(enable_psk_passphrase_);
    944   if (psk_passphrase_textfield_)
    945     psk_passphrase_textfield_->SetEnabled(enable_psk_passphrase_ &&
    946                                           psk_passphrase_ui_data_.IsEditable());
    947 
    948   if (user_cert_label_)
    949     user_cert_label_->SetEnabled(enable_user_cert_);
    950   if (user_cert_combobox_)
    951     user_cert_combobox_->SetEnabled(enable_user_cert_ &&
    952                                     user_cert_ui_data_.IsEditable());
    953 
    954   if (server_ca_cert_label_)
    955     server_ca_cert_label_->SetEnabled(enable_server_ca_cert_);
    956   if (server_ca_cert_combobox_)
    957     server_ca_cert_combobox_->SetEnabled(enable_server_ca_cert_ &&
    958                                          ca_cert_ui_data_.IsEditable());
    959 
    960   if (otp_label_)
    961     otp_label_->SetEnabled(enable_otp_);
    962   if (otp_textfield_)
    963     otp_textfield_->SetEnabled(enable_otp_);
    964 
    965   if (group_name_label_)
    966     group_name_label_->SetEnabled(enable_group_name_);
    967   if (group_name_textfield_)
    968     group_name_textfield_->SetEnabled(enable_group_name_ &&
    969                                       group_name_ui_data_.IsEditable());
    970 }
    971 
    972 void VPNConfigView::UpdateErrorLabel() {
    973   // Error message.
    974   base::string16 error_msg;
    975   bool cert_required =
    976       GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
    977   if (cert_required && CertLibrary::Get()->CertificatesLoaded()) {
    978     if (!HaveUserCerts()) {
    979       error_msg = l10n_util::GetStringUTF16(
    980           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT);
    981     } else if (!IsUserCertValid()) {
    982       error_msg = l10n_util::GetStringUTF16(
    983           IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED);
    984     }
    985   }
    986   if (error_msg.empty() && !service_path_.empty()) {
    987     // TODO(kuan): differentiate between bad psk and user passphrases.
    988     const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
    989         GetNetworkState(service_path_);
    990     if (vpn && vpn->connection_state() == shill::kStateFailure)
    991       error_msg = ash::network_connect::ErrorString(vpn->error(), vpn->path());
    992   }
    993   if (!error_msg.empty()) {
    994     error_label_->SetText(error_msg);
    995     error_label_->SetVisible(true);
    996   } else {
    997     error_label_->SetVisible(false);
    998   }
    999 }
   1000 
   1001 void VPNConfigView::UpdateCanLogin() {
   1002   parent_->GetDialogClientView()->UpdateDialogButtons();
   1003 }
   1004 
   1005 bool VPNConfigView::HaveUserCerts() const {
   1006   return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) > 0;
   1007 }
   1008 
   1009 bool VPNConfigView::IsUserCertValid() const {
   1010   if (!user_cert_combobox_ || !enable_user_cert_)
   1011     return false;
   1012   int index = user_cert_combobox_->selected_index();
   1013   if (index < 0)
   1014     return false;
   1015   // Currently only hardware-backed user certificates are valid.
   1016   if (CertLibrary::Get()->IsHardwareBacked() &&
   1017       !CertLibrary::Get()->IsCertHardwareBackedAt(
   1018           CertLibrary::CERT_TYPE_USER, index))
   1019     return false;
   1020   return true;
   1021 }
   1022 
   1023 const std::string VPNConfigView::GetTextFromField(views::Textfield* textfield,
   1024                                                   bool trim_whitespace) const {
   1025   if (!textfield)
   1026     return std::string();
   1027   std::string untrimmed = UTF16ToUTF8(textfield->text());
   1028   if (!trim_whitespace)
   1029     return untrimmed;
   1030   std::string result;
   1031   TrimWhitespaceASCII(untrimmed, TRIM_ALL, &result);
   1032   return result;
   1033 }
   1034 
   1035 const std::string VPNConfigView::GetPassphraseFromField(
   1036     PassphraseTextfield* textfield) const {
   1037   if (!textfield)
   1038     return std::string();
   1039   return textfield->GetPassphrase();
   1040 }
   1041 
   1042 void VPNConfigView::ParseVPNUIProperty(
   1043     const NetworkState* network,
   1044     const std::string& dict_key,
   1045     const std::string& key,
   1046     NetworkPropertyUIData* property_ui_data) {
   1047   ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
   1048   const base::DictionaryValue* onc =
   1049       onc::FindPolicyForActiveUser(network->guid(), &onc_source);
   1050 
   1051   VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->guid();
   1052   property_ui_data->ParseOncProperty(
   1053       onc_source,
   1054       onc,
   1055       base::StringPrintf("%s.%s.%s",
   1056                          ::onc::network_config::kVPN,
   1057                          dict_key.c_str(),
   1058                          key.c_str()));
   1059 }
   1060 
   1061 }  // namespace chromeos
   1062