vpn_config_view.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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 "base/strings/string_util.h" 8#include "base/strings/stringprintf.h" 9#include "base/strings/utf_string_conversions.h" 10#include "chrome/browser/chromeos/cros/network_library.h" 11#include "chrome/browser/chromeos/enrollment_dialog_view.h" 12#include "chrome/browser/profiles/profile_manager.h" 13#include "chrome/common/net/x509_certificate_model.h" 14#include "chromeos/network/network_ui_data.h" 15#include "chromeos/network/onc/onc_constants.h" 16#include "grit/chromium_strings.h" 17#include "grit/generated_resources.h" 18#include "grit/locale_settings.h" 19#include "grit/theme_resources.h" 20#include "ui/base/events/event.h" 21#include "ui/base/l10n/l10n_util.h" 22#include "ui/base/models/combobox_model.h" 23#include "ui/base/resource/resource_bundle.h" 24#include "ui/views/controls/button/checkbox.h" 25#include "ui/views/controls/combobox/combobox.h" 26#include "ui/views/controls/label.h" 27#include "ui/views/controls/textfield/textfield.h" 28#include "ui/views/layout/grid_layout.h" 29#include "ui/views/layout/layout_constants.h" 30#include "ui/views/widget/widget.h" 31#include "ui/views/window/dialog_client_view.h" 32 33namespace { 34 35// Root CA certificates that are built into Chrome use this token name. 36const char* const kRootCertificateTokenName = "Builtin Object Token"; 37 38string16 ProviderTypeToString(chromeos::ProviderType type) { 39 switch (type) { 40 case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK: 41 return l10n_util::GetStringUTF16( 42 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK); 43 case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: 44 return l10n_util::GetStringUTF16( 45 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT); 46 case chromeos::PROVIDER_TYPE_OPEN_VPN: 47 return l10n_util::GetStringUTF16( 48 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN); 49 case chromeos::PROVIDER_TYPE_MAX: 50 break; 51 } 52 NOTREACHED(); 53 return string16(); 54} 55 56// Translates the provider type to the name of the respective ONC dictionary 57// containing configuration data for the type. 58std::string ProviderTypeToONCDictKey(chromeos::ProviderType type) { 59 switch (type) { 60 case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK: 61 case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: 62 return chromeos::onc::vpn::kIPsec; 63 case chromeos::PROVIDER_TYPE_OPEN_VPN: 64 return chromeos::onc::vpn::kOpenVPN; 65 case chromeos::PROVIDER_TYPE_MAX: 66 break; 67 } 68 69 NOTREACHED() << "Unhandled provider type " << type; 70 return std::string(); 71} 72 73} // namespace 74 75namespace chromeos { 76 77namespace internal { 78 79class ProviderTypeComboboxModel : public ui::ComboboxModel { 80 public: 81 ProviderTypeComboboxModel(); 82 virtual ~ProviderTypeComboboxModel(); 83 84 // Overridden from ui::ComboboxModel: 85 virtual int GetItemCount() const OVERRIDE; 86 virtual string16 GetItemAt(int index) OVERRIDE; 87 88 private: 89 DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel); 90}; 91 92class VpnServerCACertComboboxModel : public ui::ComboboxModel { 93 public: 94 VpnServerCACertComboboxModel(); 95 virtual ~VpnServerCACertComboboxModel(); 96 97 // Overridden from ui::ComboboxModel: 98 virtual int GetItemCount() const OVERRIDE; 99 virtual string16 GetItemAt(int index) OVERRIDE; 100 101 private: 102 DISALLOW_COPY_AND_ASSIGN(VpnServerCACertComboboxModel); 103}; 104 105class VpnUserCertComboboxModel : public ui::ComboboxModel { 106 public: 107 VpnUserCertComboboxModel(); 108 virtual ~VpnUserCertComboboxModel(); 109 110 // Overridden from ui::ComboboxModel: 111 virtual int GetItemCount() const OVERRIDE; 112 virtual string16 GetItemAt(int index) OVERRIDE; 113 114 private: 115 DISALLOW_COPY_AND_ASSIGN(VpnUserCertComboboxModel); 116}; 117 118// ProviderTypeComboboxModel --------------------------------------------------- 119 120ProviderTypeComboboxModel::ProviderTypeComboboxModel() { 121} 122 123ProviderTypeComboboxModel::~ProviderTypeComboboxModel() { 124} 125 126int ProviderTypeComboboxModel::GetItemCount() const { 127 return PROVIDER_TYPE_MAX; 128} 129 130string16 ProviderTypeComboboxModel::GetItemAt(int index) { 131 ProviderType type = static_cast<ProviderType>(index); 132 return ProviderTypeToString(type); 133} 134 135// VpnServerCACertComboboxModel ------------------------------------------------ 136 137VpnServerCACertComboboxModel::VpnServerCACertComboboxModel() { 138} 139 140VpnServerCACertComboboxModel::~VpnServerCACertComboboxModel() { 141} 142 143int VpnServerCACertComboboxModel::GetItemCount() const { 144 if (CertLibrary::Get()->CertificatesLoading()) 145 return 1; // "Loading" 146 // "Default" + certs. 147 return CertLibrary::Get()->NumCertificates( 148 CertLibrary::CERT_TYPE_SERVER_CA) + 1; 149} 150 151string16 VpnServerCACertComboboxModel::GetItemAt(int index) { 152 if (CertLibrary::Get()->CertificatesLoading()) 153 return l10n_util::GetStringUTF16( 154 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING); 155 if (index == 0) 156 return l10n_util::GetStringUTF16( 157 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT); 158 int cert_index = index - 1; 159 return CertLibrary::Get()->GetCertDisplayStringAt( 160 CertLibrary::CERT_TYPE_SERVER_CA, cert_index); 161} 162 163// VpnUserCertComboboxModel ---------------------------------------------------- 164 165VpnUserCertComboboxModel::VpnUserCertComboboxModel() { 166} 167 168VpnUserCertComboboxModel::~VpnUserCertComboboxModel() { 169} 170 171int VpnUserCertComboboxModel::GetItemCount() const { 172 if (CertLibrary::Get()->CertificatesLoading()) 173 return 1; // "Loading" 174 int num_certs = 175 CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER); 176 if (num_certs == 0) 177 return 1; // "None installed" 178 return num_certs; 179} 180 181string16 VpnUserCertComboboxModel::GetItemAt(int index) { 182 if (CertLibrary::Get()->CertificatesLoading()) { 183 return l10n_util::GetStringUTF16( 184 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING); 185 } 186 if (CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) == 0) { 187 return l10n_util::GetStringUTF16( 188 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USER_CERT_NONE_INSTALLED); 189 } 190 return CertLibrary::Get()->GetCertDisplayStringAt( 191 CertLibrary::CERT_TYPE_USER, index); 192} 193 194} // namespace internal 195 196VPNConfigView::VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn) 197 : ChildNetworkConfigView(parent, vpn), 198 title_(0) { 199 Init(vpn); 200} 201 202VPNConfigView::VPNConfigView(NetworkConfigView* parent) 203 : ChildNetworkConfigView(parent), 204 title_(0) { 205 Init(NULL); 206} 207 208VPNConfigView::~VPNConfigView() { 209 CertLibrary::Get()->RemoveObserver(this); 210} 211 212string16 VPNConfigView::GetTitle() const { 213 DCHECK_NE(title_, 0); 214 return l10n_util::GetStringUTF16(title_); 215} 216 217views::View* VPNConfigView::GetInitiallyFocusedView() { 218 // Put focus in the first editable field. 219 if (server_textfield_) 220 return server_textfield_; 221 else if (service_textfield_) 222 return service_textfield_; 223 else if (provider_type_combobox_) 224 return provider_type_combobox_; 225 else if (psk_passphrase_textfield_ && psk_passphrase_textfield_->enabled()) 226 return psk_passphrase_textfield_; 227 else if (user_cert_combobox_ && user_cert_combobox_->enabled()) 228 return user_cert_combobox_; 229 else if (server_ca_cert_combobox_ && server_ca_cert_combobox_->enabled()) 230 return server_ca_cert_combobox_; 231 else 232 return NULL; 233} 234 235bool VPNConfigView::CanLogin() { 236 // Username is always required. 237 if (GetUsername().empty()) 238 return false; 239 240 // TODO(stevenjb): min kMinPassphraseLen length? 241 if (service_path_.empty() && 242 (GetService().empty() || GetServer().empty())) 243 return false; 244 245 // Block login if certs are required but user has none. 246 if (UserCertRequired() && (!HaveUserCerts() || !IsUserCertValid())) 247 return false; 248 249 return true; 250} 251 252void VPNConfigView::ContentsChanged(views::Textfield* sender, 253 const string16& new_contents) { 254 if (sender == server_textfield_ && !service_text_modified_) { 255 // Set the service name to the server name up to '.', unless it has 256 // been explicitly set by the user. 257 string16 server = server_textfield_->text(); 258 string16::size_type n = server.find_first_of(L'.'); 259 service_name_from_server_ = server.substr(0, n); 260 service_textfield_->SetText(service_name_from_server_); 261 } 262 if (sender == service_textfield_) { 263 if (new_contents.empty()) 264 service_text_modified_ = false; 265 else if (new_contents != service_name_from_server_) 266 service_text_modified_ = true; 267 } 268 UpdateCanLogin(); 269} 270 271bool VPNConfigView::HandleKeyEvent(views::Textfield* sender, 272 const ui::KeyEvent& key_event) { 273 if ((sender == psk_passphrase_textfield_ || 274 sender == user_passphrase_textfield_) && 275 key_event.key_code() == ui::VKEY_RETURN) { 276 parent_->GetDialogClientView()->AcceptWindow(); 277 } 278 return false; 279} 280 281void VPNConfigView::ButtonPressed(views::Button* sender, 282 const ui::Event& event) { 283} 284 285void VPNConfigView::OnSelectedIndexChanged(views::Combobox* combobox) { 286 if (combobox == provider_type_combobox_) { 287 provider_type_ = static_cast<ProviderType>(combobox->selected_index()); 288 UpdateControls(); 289 } else if (combobox == user_cert_combobox_ || 290 combobox == server_ca_cert_combobox_) { 291 // Do nothing. 292 } else { 293 NOTREACHED(); 294 } 295 UpdateErrorLabel(); 296 UpdateCanLogin(); 297} 298 299void VPNConfigView::OnCertificatesLoaded(bool initial_load) { 300 Refresh(); 301} 302 303bool VPNConfigView::Login() { 304 NetworkLibrary* cros = NetworkLibrary::Get(); 305 if (service_path_.empty()) { 306 NetworkLibrary::VPNConfigData config_data; 307 switch (provider_type_) { 308 case PROVIDER_TYPE_L2TP_IPSEC_PSK: 309 config_data.psk = GetPSKPassphrase(); 310 config_data.username = GetUsername(); 311 config_data.user_passphrase = GetUserPassphrase(); 312 config_data.group_name = GetGroupName(); 313 break; 314 case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: { 315 config_data.server_ca_cert_pem = GetServerCACertPEM(); 316 config_data.client_cert_pkcs11_id = GetUserCertID(); 317 config_data.username = GetUsername(); 318 config_data.user_passphrase = GetUserPassphrase(); 319 config_data.group_name = GetGroupName(); 320 break; 321 } 322 case PROVIDER_TYPE_OPEN_VPN: 323 config_data.server_ca_cert_pem = GetServerCACertPEM(); 324 config_data.client_cert_pkcs11_id = GetUserCertID(); 325 config_data.username = GetUsername(); 326 config_data.user_passphrase = GetUserPassphrase(); 327 config_data.otp = GetOTP(); 328 break; 329 case PROVIDER_TYPE_MAX: 330 break; 331 } 332 config_data.save_credentials = GetSaveCredentials(); 333 cros->ConnectToUnconfiguredVirtualNetwork( 334 GetService(), GetServer(), provider_type_, config_data); 335 } else { 336 VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_); 337 if (!vpn) { 338 // TODO(stevenjb): Add notification for this. 339 LOG(WARNING) << "VPN no longer exists: " << service_path_; 340 return true; // Close dialog. 341 } 342 switch (provider_type_) { 343 case PROVIDER_TYPE_L2TP_IPSEC_PSK: 344 vpn->SetL2TPIPsecPSKCredentials(GetPSKPassphrase(), 345 GetUsername(), 346 GetUserPassphrase(), 347 GetGroupName()); 348 break; 349 case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: { 350 vpn->SetL2TPIPsecCertCredentials(GetUserCertID(), 351 GetUsername(), 352 GetUserPassphrase(), 353 GetGroupName()); 354 break; 355 } 356 case PROVIDER_TYPE_OPEN_VPN: { 357 vpn->SetOpenVPNCredentials(GetUserCertID(), 358 GetUsername(), 359 GetUserPassphrase(), 360 GetOTP()); 361 break; 362 } 363 case PROVIDER_TYPE_MAX: 364 break; 365 } 366 vpn->SetEnrollmentDelegate( 367 CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(), 368 vpn->name(), 369 ProfileManager::GetLastUsedProfile())); 370 vpn->SetSaveCredentials(GetSaveCredentials()); 371 cros->ConnectToVirtualNetwork(vpn); 372 } 373 // Connection failures are responsible for updating the UI, including 374 // reopening dialogs. 375 return true; // Close dialog. 376} 377 378void VPNConfigView::Cancel() { 379} 380 381void VPNConfigView::InitFocus() { 382 views::View* view_to_focus = GetInitiallyFocusedView(); 383 if (view_to_focus) 384 view_to_focus->RequestFocus(); 385} 386 387const std::string VPNConfigView::GetService() const { 388 if (service_textfield_ != NULL) 389 return GetTextFromField(service_textfield_, true); 390 return service_path_; 391} 392 393const std::string VPNConfigView::GetServer() const { 394 if (server_textfield_ != NULL) 395 return GetTextFromField(server_textfield_, true); 396 return server_hostname_; 397} 398 399const std::string VPNConfigView::GetPSKPassphrase() const { 400 if (psk_passphrase_textfield_ && 401 enable_psk_passphrase_ && 402 psk_passphrase_textfield_->visible()) 403 return GetPassphraseFromField(psk_passphrase_textfield_); 404 return std::string(); 405} 406 407const std::string VPNConfigView::GetUsername() const { 408 return GetTextFromField(username_textfield_, true); 409} 410 411const std::string VPNConfigView::GetUserPassphrase() const { 412 return GetPassphraseFromField(user_passphrase_textfield_); 413} 414 415const std::string VPNConfigView::GetGroupName() const { 416 return GetTextFromField(group_name_textfield_, false); 417} 418 419const std::string VPNConfigView::GetOTP() const { 420 return GetTextFromField(otp_textfield_, true); 421} 422 423const std::string VPNConfigView::GetServerCACertPEM() const { 424 int index = server_ca_cert_combobox_ ? 425 server_ca_cert_combobox_->selected_index() : 0; 426 if (index == 0) { 427 // First item is "Default". 428 return std::string(); 429 } else { 430 int cert_index = index - 1; 431 return CertLibrary::Get()->GetCertPEMAt( 432 CertLibrary::CERT_TYPE_SERVER_CA, cert_index); 433 } 434} 435 436const std::string VPNConfigView::GetUserCertID() const { 437 if (!HaveUserCerts()) { 438 return std::string(); // "None installed" 439 } else { 440 // Certificates are listed in the order they appear in the model. 441 int index = user_cert_combobox_ ? user_cert_combobox_->selected_index() : 0; 442 return CertLibrary::Get()->GetCertPkcs11IdAt( 443 CertLibrary::CERT_TYPE_USER, index); 444 } 445} 446 447bool VPNConfigView::GetSaveCredentials() const { 448 return save_credentials_checkbox_->checked(); 449} 450 451void VPNConfigView::Init(VirtualNetwork* vpn) { 452 if (vpn) { 453 ProviderType type = vpn->provider_type(); 454 std::string type_dict_name = ProviderTypeToONCDictKey(type); 455 456 if (type == PROVIDER_TYPE_L2TP_IPSEC_PSK) { 457 ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name, 458 onc::ipsec::kServerCARef); 459 ParseVPNUIProperty(&psk_passphrase_ui_data_, vpn, type_dict_name, 460 onc::ipsec::kPSK); 461 ParseVPNUIProperty(&group_name_ui_data_, vpn, type_dict_name, 462 onc::ipsec::kGroup); 463 } else { // OpenVPN 464 ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name, 465 onc::openvpn::kServerCARef); 466 } 467 ParseVPNUIProperty(&user_cert_ui_data_, vpn, type_dict_name, 468 onc::vpn::kClientCertRef); 469 470 const std::string credentials_dict_name( 471 type == PROVIDER_TYPE_L2TP_IPSEC_PSK ? 472 onc::vpn::kL2TP : type_dict_name); 473 ParseVPNUIProperty(&username_ui_data_, vpn, credentials_dict_name, 474 onc::vpn::kUsername); 475 ParseVPNUIProperty(&user_passphrase_ui_data_, vpn, credentials_dict_name, 476 onc::vpn::kPassword); 477 ParseVPNUIProperty(&save_credentials_ui_data_, vpn, credentials_dict_name, 478 onc::vpn::kSaveCredentials); 479 } 480 481 views::GridLayout* layout = views::GridLayout::CreatePanel(this); 482 SetLayoutManager(layout); 483 484 // Observer any changes to the certificate list. 485 CertLibrary::Get()->AddObserver(this); 486 487 const int column_view_set_id = 0; 488 views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id); 489 // Label. 490 column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1, 491 views::GridLayout::USE_PREF, 0, 0); 492 column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing); 493 // Textfield, combobox. 494 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, 495 views::GridLayout::USE_PREF, 0, 496 ChildNetworkConfigView::kInputFieldMinWidth); 497 column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing); 498 // Policy indicator. 499 column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0, 500 views::GridLayout::USE_PREF, 0, 0); 501 502 // Initialize members. 503 service_text_modified_ = false; 504 if (vpn) { 505 provider_type_ = vpn->provider_type(); 506 // Sets enable_* based on the provider type which we use to control 507 // which controls to make visible. 508 UpdateControlsToEnable(); 509 } else { 510 // Set the default provider type. 511 provider_type_ = PROVIDER_TYPE_L2TP_IPSEC_PSK; 512 // Provider Type is user selectable, so enable all controls during init. 513 enable_psk_passphrase_ = true; 514 enable_user_cert_ = true; 515 enable_server_ca_cert_ = true; 516 enable_otp_ = true; 517 enable_group_name_ = true; 518 } 519 520 // Initialize the title string ID used for the dialog. 521 title_ = vpn ? IDS_OPTIONS_SETTINGS_JOIN_VPN : IDS_OPTIONS_SETTINGS_ADD_VPN; 522 523 // Server label and input. 524 // Only provide Server name when configuring a new VPN. 525 if (!vpn) { 526 layout->StartRow(0, column_view_set_id); 527 layout->AddView(new views::Label(l10n_util::GetStringUTF16( 528 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME))); 529 server_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); 530 server_textfield_->SetController(this); 531 layout->AddView(server_textfield_); 532 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 533 } else { 534 server_textfield_ = NULL; 535 } 536 537 // Service label and name or input. 538 layout->StartRow(0, column_view_set_id); 539 layout->AddView(new views::Label(l10n_util::GetStringUTF16( 540 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME))); 541 if (!vpn) { 542 service_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); 543 service_textfield_->SetController(this); 544 layout->AddView(service_textfield_); 545 service_text_ = NULL; 546 } else { 547 service_text_ = new views::Label(ASCIIToUTF16(vpn->name())); 548 service_text_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 549 layout->AddView(service_text_); 550 service_textfield_ = NULL; 551 } 552 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 553 554 // Provider type label and select. 555 layout->StartRow(0, column_view_set_id); 556 layout->AddView(new views::Label(l10n_util::GetStringUTF16( 557 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE))); 558 if (!vpn) { 559 provider_type_combobox_model_.reset( 560 new internal::ProviderTypeComboboxModel); 561 provider_type_combobox_ = new views::Combobox( 562 provider_type_combobox_model_.get()); 563 provider_type_combobox_->set_listener(this); 564 layout->AddView(provider_type_combobox_); 565 provider_type_text_label_ = NULL; 566 } else { 567 provider_type_text_label_ = 568 new views::Label(ProviderTypeToString(provider_type_)); 569 provider_type_text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 570 layout->AddView(provider_type_text_label_); 571 provider_type_combobox_ = NULL; 572 } 573 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 574 575 // PSK passphrase label, input and visible button. 576 if (enable_psk_passphrase_) { 577 layout->StartRow(0, column_view_set_id); 578 psk_passphrase_label_ = new views::Label(l10n_util::GetStringUTF16( 579 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE)); 580 layout->AddView(psk_passphrase_label_); 581 bool has_psk_passphrase = vpn && !vpn->IsPSKPassphraseRequired(); 582 psk_passphrase_textfield_ = new PassphraseTextfield(has_psk_passphrase); 583 psk_passphrase_textfield_->SetController(this); 584 layout->AddView(psk_passphrase_textfield_); 585 layout->AddView( 586 new ControlledSettingIndicatorView(psk_passphrase_ui_data_)); 587 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 588 } else { 589 psk_passphrase_label_ = NULL; 590 psk_passphrase_textfield_ = NULL; 591 } 592 593 // Server CA certificate 594 // Only provide Server CA when configuring a new VPN. 595 if (!vpn) { 596 layout->StartRow(0, column_view_set_id); 597 server_ca_cert_label_ = 598 new views::Label(l10n_util::GetStringUTF16( 599 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA)); 600 layout->AddView(server_ca_cert_label_); 601 server_ca_cert_combobox_model_.reset( 602 new internal::VpnServerCACertComboboxModel()); 603 server_ca_cert_combobox_ = new views::Combobox( 604 server_ca_cert_combobox_model_.get()); 605 layout->AddView(server_ca_cert_combobox_); 606 layout->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_)); 607 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 608 } else { 609 server_ca_cert_label_ = NULL; 610 server_ca_cert_combobox_ = NULL; 611 } 612 613 // User certificate label and input. 614 if (enable_user_cert_) { 615 layout->StartRow(0, column_view_set_id); 616 user_cert_label_ = new views::Label(l10n_util::GetStringUTF16( 617 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT)); 618 layout->AddView(user_cert_label_); 619 user_cert_combobox_model_.reset( 620 new internal::VpnUserCertComboboxModel()); 621 user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get()); 622 user_cert_combobox_->set_listener(this); 623 layout->AddView(user_cert_combobox_); 624 layout->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_)); 625 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 626 } else { 627 user_cert_label_ = NULL; 628 user_cert_combobox_ = NULL; 629 } 630 631 // Username label and input. 632 layout->StartRow(0, column_view_set_id); 633 layout->AddView(new views::Label(l10n_util::GetStringUTF16( 634 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME))); 635 username_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); 636 username_textfield_->SetController(this); 637 username_textfield_->SetEnabled(username_ui_data_.IsEditable()); 638 if (vpn && !vpn->username().empty()) 639 username_textfield_->SetText(UTF8ToUTF16(vpn->username())); 640 layout->AddView(username_textfield_); 641 layout->AddView(new ControlledSettingIndicatorView(username_ui_data_)); 642 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 643 644 // User passphrase label, input and visble button. 645 layout->StartRow(0, column_view_set_id); 646 layout->AddView(new views::Label(l10n_util::GetStringUTF16( 647 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE))); 648 bool has_user_passphrase = vpn && !vpn->IsUserPassphraseRequired(); 649 user_passphrase_textfield_ = new PassphraseTextfield(has_user_passphrase); 650 user_passphrase_textfield_->SetController(this); 651 user_passphrase_textfield_->SetEnabled(user_passphrase_ui_data_.IsEditable()); 652 layout->AddView(user_passphrase_textfield_); 653 layout->AddView(new ControlledSettingIndicatorView(user_passphrase_ui_data_)); 654 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 655 656 // OTP label and input. 657 if (enable_otp_) { 658 layout->StartRow(0, column_view_set_id); 659 otp_label_ = new views::Label(l10n_util::GetStringUTF16( 660 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP)); 661 layout->AddView(otp_label_); 662 otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); 663 otp_textfield_->SetController(this); 664 layout->AddView(otp_textfield_); 665 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 666 } else { 667 otp_label_ = NULL; 668 otp_textfield_ = NULL; 669 } 670 671 // Group Name label and input. 672 if (enable_group_name_) { 673 layout->StartRow(0, column_view_set_id); 674 group_name_label_ = new views::Label(l10n_util::GetStringUTF16( 675 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME)); 676 layout->AddView(group_name_label_); 677 group_name_textfield_ = 678 new views::Textfield(views::Textfield::STYLE_DEFAULT); 679 group_name_textfield_->SetController(this); 680 if (vpn && !vpn->group_name().empty()) 681 group_name_textfield_->SetText(UTF8ToUTF16(vpn->group_name())); 682 layout->AddView(group_name_textfield_); 683 layout->AddView(new ControlledSettingIndicatorView(group_name_ui_data_)); 684 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 685 } else { 686 group_name_label_ = NULL; 687 group_name_textfield_ = NULL; 688 } 689 690 // Save credentials 691 layout->StartRow(0, column_view_set_id); 692 save_credentials_checkbox_ = new views::Checkbox( 693 l10n_util::GetStringUTF16( 694 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS)); 695 save_credentials_checkbox_->SetEnabled( 696 save_credentials_ui_data_.IsEditable()); 697 bool save_credentials = vpn ? vpn->save_credentials() : false; 698 save_credentials_checkbox_->SetChecked(save_credentials); 699 layout->SkipColumns(1); 700 layout->AddView(save_credentials_checkbox_); 701 layout->AddView( 702 new ControlledSettingIndicatorView(save_credentials_ui_data_)); 703 704 // Error label. 705 layout->StartRow(0, column_view_set_id); 706 layout->SkipColumns(1); 707 error_label_ = new views::Label(); 708 error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 709 error_label_->SetEnabledColor(SK_ColorRED); 710 layout->AddView(error_label_); 711 712 // Set or hide the UI, update comboboxes and error labels. 713 Refresh(); 714} 715 716void VPNConfigView::Refresh() { 717 NetworkLibrary* cros = NetworkLibrary::Get(); 718 719 UpdateControls(); 720 721 // Set certificate combo boxes. 722 VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_); 723 if (server_ca_cert_combobox_) { 724 server_ca_cert_combobox_->ModelChanged(); 725 if (enable_server_ca_cert_ && 726 (vpn && !vpn->ca_cert_pem().empty())) { 727 // Select the current server CA certificate in the combobox. 728 int cert_index = CertLibrary::Get()->GetCertIndexByPEM( 729 CertLibrary::CERT_TYPE_SERVER_CA, vpn->ca_cert_pem()); 730 if (cert_index >= 0) { 731 // Skip item for "Default" 732 server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index); 733 } else { 734 server_ca_cert_combobox_->SetSelectedIndex(0); 735 } 736 } else { 737 server_ca_cert_combobox_->SetSelectedIndex(0); 738 } 739 } 740 741 if (user_cert_combobox_) { 742 user_cert_combobox_->ModelChanged(); 743 if (enable_user_cert_ && 744 (vpn && !vpn->client_cert_id().empty())) { 745 int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id( 746 CertLibrary::CERT_TYPE_USER, vpn->client_cert_id()); 747 if (cert_index >= 0) 748 user_cert_combobox_->SetSelectedIndex(cert_index); 749 else 750 user_cert_combobox_->SetSelectedIndex(0); 751 } else { 752 user_cert_combobox_->SetSelectedIndex(0); 753 } 754 } 755 756 UpdateErrorLabel(); 757} 758 759void VPNConfigView::UpdateControlsToEnable() { 760 // Set which controls are enabled. 761 enable_psk_passphrase_ = false; 762 enable_user_cert_ = false; 763 enable_server_ca_cert_ = false; 764 enable_otp_ = false; 765 enable_group_name_ = false; 766 switch (provider_type_) { 767 case PROVIDER_TYPE_L2TP_IPSEC_PSK: 768 enable_psk_passphrase_ = true; 769 enable_group_name_ = true; 770 break; 771 case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: 772 enable_server_ca_cert_ = true; 773 enable_user_cert_ = HaveUserCerts(); 774 enable_group_name_ = true; 775 break; 776 case PROVIDER_TYPE_OPEN_VPN: 777 enable_server_ca_cert_ = true; 778 enable_user_cert_ = HaveUserCerts(); 779 enable_otp_ = true; 780 break; 781 default: 782 NOTREACHED(); 783 break; 784 } 785} 786 787void VPNConfigView::UpdateControls() { 788 UpdateControlsToEnable(); 789 790 if (psk_passphrase_label_) 791 psk_passphrase_label_->SetEnabled(enable_psk_passphrase_); 792 if (psk_passphrase_textfield_) 793 psk_passphrase_textfield_->SetEnabled(enable_psk_passphrase_ && 794 psk_passphrase_ui_data_.IsEditable()); 795 796 if (user_cert_label_) 797 user_cert_label_->SetEnabled(enable_user_cert_); 798 if (user_cert_combobox_) 799 user_cert_combobox_->SetEnabled(enable_user_cert_ && 800 user_cert_ui_data_.IsEditable()); 801 802 if (server_ca_cert_label_) 803 server_ca_cert_label_->SetEnabled(enable_server_ca_cert_); 804 if (server_ca_cert_combobox_) 805 server_ca_cert_combobox_->SetEnabled(enable_server_ca_cert_ && 806 ca_cert_ui_data_.IsEditable()); 807 808 if (otp_label_) 809 otp_label_->SetEnabled(enable_otp_); 810 if (otp_textfield_) 811 otp_textfield_->SetEnabled(enable_otp_); 812 813 if (group_name_label_) 814 group_name_label_->SetEnabled(enable_group_name_); 815 if (group_name_textfield_) 816 group_name_textfield_->SetEnabled(enable_group_name_ && 817 group_name_ui_data_.IsEditable()); 818} 819 820void VPNConfigView::UpdateErrorLabel() { 821 NetworkLibrary* cros = NetworkLibrary::Get(); 822 823 // Error message. 824 std::string error_msg; 825 if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) { 826 if (!HaveUserCerts()) { 827 error_msg = l10n_util::GetStringUTF8( 828 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT); 829 } else if (!IsUserCertValid()) { 830 error_msg = l10n_util::GetStringUTF8( 831 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED); 832 } 833 } 834 if (error_msg.empty() && !service_path_.empty()) { 835 // TODO(kuan): differentiate between bad psk and user passphrases. 836 VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_); 837 if (vpn && vpn->failed()) { 838 if (vpn->error() == ERROR_BAD_PASSPHRASE) { 839 error_msg = l10n_util::GetStringUTF8( 840 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE); 841 } else { 842 error_msg = vpn->GetErrorString(); 843 } 844 } 845 } 846 if (!error_msg.empty()) { 847 error_label_->SetText(UTF8ToUTF16(error_msg)); 848 error_label_->SetVisible(true); 849 } else { 850 error_label_->SetVisible(false); 851 } 852} 853 854void VPNConfigView::UpdateCanLogin() { 855 parent_->GetDialogClientView()->UpdateDialogButtons(); 856} 857 858bool VPNConfigView::UserCertRequired() const { 859 return provider_type_ == PROVIDER_TYPE_L2TP_IPSEC_USER_CERT; 860} 861 862bool VPNConfigView::HaveUserCerts() const { 863 return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) > 0; 864} 865 866bool VPNConfigView::IsUserCertValid() const { 867 if (!user_cert_combobox_ || !enable_user_cert_) 868 return false; 869 int index = user_cert_combobox_->selected_index(); 870 if (index < 0) 871 return false; 872 // Currently only hardware-backed user certificates are valid. 873 if (CertLibrary::Get()->IsHardwareBacked() && 874 !CertLibrary::Get()->IsCertHardwareBackedAt( 875 CertLibrary::CERT_TYPE_USER, index)) 876 return false; 877 return true; 878} 879 880const std::string VPNConfigView::GetTextFromField(views::Textfield* textfield, 881 bool trim_whitespace) const { 882 if (!textfield) 883 return std::string(); 884 std::string untrimmed = UTF16ToUTF8(textfield->text()); 885 if (!trim_whitespace) 886 return untrimmed; 887 std::string result; 888 TrimWhitespaceASCII(untrimmed, TRIM_ALL, &result); 889 return result; 890} 891 892const std::string VPNConfigView::GetPassphraseFromField( 893 PassphraseTextfield* textfield) const { 894 if (!textfield) 895 return std::string(); 896 return textfield->GetPassphrase(); 897} 898 899void VPNConfigView::ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data, 900 Network* network, 901 const std::string& dict_key, 902 const std::string& key) { 903 onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; 904 const base::DictionaryValue* onc = 905 NetworkConfigView::FindPolicyForActiveUser(network, &onc_source); 906 907 VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->unique_id(); 908 property_ui_data->ParseOncProperty( 909 onc_source, 910 onc, 911 base::StringPrintf("%s.%s.%s", 912 onc::network_config::kVPN, 913 dict_key.c_str(), 914 key.c_str())); 915} 916 917} // namespace chromeos 918