blob: af149baa43784237e072042c0d81dbbe83f9376a [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/options/vpn_config_view.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/onc_constants.h"
#include "chrome/browser/chromeos/enrollment_dialog_view.h"
#include "chrome/common/net/x509_certificate_model.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
#include "net/base/cert_database.h"
#include "net/base/x509_certificate.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/combobox_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"
namespace {
// Root CA certificates that are built into Chrome use this token name.
const char* const kRootCertificateTokenName = "Builtin Object Token";
string16 ProviderTypeToString(chromeos::ProviderType type) {
switch (type) {
case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK:
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK);
case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT);
case chromeos::PROVIDER_TYPE_OPEN_VPN:
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN);
case chromeos::PROVIDER_TYPE_MAX:
break;
}
NOTREACHED();
return string16();
}
} // namespace
namespace chromeos {
class ProviderTypeComboboxModel : public ui::ComboboxModel {
public:
ProviderTypeComboboxModel() {}
virtual ~ProviderTypeComboboxModel() {}
// Overridden from ui::ComboboxModel:
virtual int GetItemCount() const OVERRIDE {
return chromeos::PROVIDER_TYPE_MAX;
}
virtual string16 GetItemAt(int index) OVERRIDE {
ProviderType type = static_cast<ProviderType>(index);
return ProviderTypeToString(type);
}
private:
DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel);
};
class ServerCACertComboboxModel : public ui::ComboboxModel {
public:
explicit ServerCACertComboboxModel(CertLibrary* cert_library)
: cert_library_(cert_library) {
}
virtual ~ServerCACertComboboxModel() {}
// Overridden from ui::ComboboxModel:
virtual int GetItemCount() const OVERRIDE {
if (cert_library_->CertificatesLoading())
return 1; // "Loading"
// "Default" + certs.
return cert_library_->GetCACertificates().Size() + 1;
}
virtual string16 GetItemAt(int index) OVERRIDE {
if (cert_library_->CertificatesLoading())
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING);
if (index == 0)
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT);
int cert_index = index - 1;
return cert_library_->GetCACertificates().GetDisplayStringAt(cert_index);
}
private:
CertLibrary* cert_library_;
DISALLOW_COPY_AND_ASSIGN(ServerCACertComboboxModel);
};
class UserCertComboboxModel : public ui::ComboboxModel {
public:
explicit UserCertComboboxModel(CertLibrary* cert_library)
: cert_library_(cert_library) {
}
virtual ~UserCertComboboxModel() {}
// Overridden from ui::ComboboxModel:
virtual int GetItemCount() const OVERRIDE {
if (cert_library_->CertificatesLoading())
return 1; // "Loading"
int num_certs = cert_library_->GetUserCertificates().Size();
if (num_certs == 0)
return 1; // "None installed"
return num_certs;
}
virtual string16 GetItemAt(int index) OVERRIDE {
if (cert_library_->CertificatesLoading()) {
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING);
}
if (cert_library_->GetUserCertificates().Size() == 0) {
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USER_CERT_NONE_INSTALLED);
}
return cert_library_->GetUserCertificates().GetDisplayStringAt(index);
}
private:
CertLibrary* cert_library_;
DISALLOW_COPY_AND_ASSIGN(UserCertComboboxModel);
};
VPNConfigView::VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn)
: ChildNetworkConfigView(parent, vpn),
cert_library_(NULL) {
Init(vpn);
}
VPNConfigView::VPNConfigView(NetworkConfigView* parent)
: ChildNetworkConfigView(parent),
cert_library_(NULL) {
Init(NULL);
}
VPNConfigView::~VPNConfigView() {
if (cert_library_)
cert_library_->RemoveObserver(this);
}
string16 VPNConfigView::GetTitle() {
if (service_path_.empty())
return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_ADD_VPN);
else
return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_JOIN_VPN);
}
views::View* VPNConfigView::GetInitiallyFocusedView() {
// Put focus in the first editable field.
if (server_textfield_)
return server_textfield_;
else if (service_textfield_)
return service_textfield_;
else if (provider_type_combobox_)
return provider_type_combobox_;
else if (psk_passphrase_textfield_ && psk_passphrase_textfield_->enabled())
return psk_passphrase_textfield_;
else if (user_cert_combobox_ && user_cert_combobox_->enabled())
return user_cert_combobox_;
else if (server_ca_cert_combobox_ && server_ca_cert_combobox_->enabled())
return server_ca_cert_combobox_;
else
return NULL;
}
bool VPNConfigView::CanLogin() {
// Username is always required.
if (GetUsername().empty())
return false;
// TODO(stevenjb): min kMinPassphraseLen length?
if (service_path_.empty() &&
(GetService().empty() || GetServer().empty()))
return false;
// Block login if certs are required but user has none.
if (UserCertRequired() && (!HaveUserCerts() || !IsUserCertValid()))
return false;
return true;
}
void VPNConfigView::ContentsChanged(views::Textfield* sender,
const string16& new_contents) {
if (sender == server_textfield_ && !service_text_modified_) {
// Set the service name to the server name up to '.', unless it has
// been explicitly set by the user.
string16 server = server_textfield_->text();
string16::size_type n = server.find_first_of(L'.');
service_name_from_server_ = server.substr(0, n);
service_textfield_->SetText(service_name_from_server_);
}
if (sender == service_textfield_) {
if (new_contents.empty())
service_text_modified_ = false;
else if (new_contents != service_name_from_server_)
service_text_modified_ = true;
}
UpdateCanLogin();
}
bool VPNConfigView::HandleKeyEvent(views::Textfield* sender,
const views::KeyEvent& key_event) {
if ((sender == psk_passphrase_textfield_ ||
sender == user_passphrase_textfield_) &&
key_event.key_code() == ui::VKEY_RETURN) {
parent_->GetDialogClientView()->AcceptWindow();
}
return false;
}
void VPNConfigView::ButtonPressed(views::Button* sender,
const views::Event& event) {
}
void VPNConfigView::OnSelectedIndexChanged(views::Combobox* combobox) {
if (combobox == provider_type_combobox_) {
provider_type_ = static_cast<ProviderType>(combobox->selected_index());
UpdateControls();
} else if (combobox == user_cert_combobox_ ||
combobox == server_ca_cert_combobox_) {
// Do nothing.
} else {
NOTREACHED();
}
UpdateErrorLabel();
UpdateCanLogin();
}
void VPNConfigView::OnCertificatesLoaded(bool initial_load) {
Refresh();
}
bool VPNConfigView::Login() {
NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
if (service_path_.empty()) {
NetworkLibrary::VPNConfigData config_data;
switch (provider_type_) {
case PROVIDER_TYPE_L2TP_IPSEC_PSK:
config_data.psk = GetPSKPassphrase();
config_data.username = GetUsername();
config_data.user_passphrase = GetUserPassphrase();
config_data.group_name = GetGroupName();
break;
case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: {
config_data.server_ca_cert_nss_nickname = GetServerCACertNssNickname();
config_data.client_cert_pkcs11_id = GetUserCertID();
config_data.username = GetUsername();
config_data.user_passphrase = GetUserPassphrase();
config_data.group_name = GetGroupName();
break;
}
case PROVIDER_TYPE_OPEN_VPN:
config_data.server_ca_cert_nss_nickname = GetServerCACertNssNickname();
config_data.client_cert_pkcs11_id = GetUserCertID();
config_data.username = GetUsername();
config_data.user_passphrase = GetUserPassphrase();
config_data.otp = GetOTP();
break;
case PROVIDER_TYPE_MAX:
break;
}
cros->ConnectToUnconfiguredVirtualNetwork(
GetService(), GetServer(), provider_type_, config_data);
} else {
VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
if (!vpn) {
// TODO(stevenjb): Add notification for this.
LOG(WARNING) << "VPN no longer exists: " << service_path_;
return true; // Close dialog.
}
switch (provider_type_) {
case PROVIDER_TYPE_L2TP_IPSEC_PSK:
vpn->SetL2TPIPsecPSKCredentials(GetPSKPassphrase(),
GetUsername(),
GetUserPassphrase(),
GetGroupName());
break;
case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: {
vpn->SetL2TPIPsecCertCredentials(GetUserCertID(),
GetUsername(),
GetUserPassphrase(),
GetGroupName());
break;
}
case PROVIDER_TYPE_OPEN_VPN: {
vpn->SetOpenVPNCredentials(GetUserCertID(),
GetUsername(),
GetUserPassphrase(),
GetOTP());
break;
}
case PROVIDER_TYPE_MAX:
break;
}
vpn->SetEnrollmentDelegate(
EnrollmentDialogView::CreateEnrollmentDelegate(
GetWidget()->GetNativeWindow()));
cros->ConnectToVirtualNetwork(vpn);
}
// Connection failures are responsible for updating the UI, including
// reopening dialogs.
return true; // Close dialog.
}
void VPNConfigView::Cancel() {
}
void VPNConfigView::InitFocus() {
views::View* view_to_focus = GetInitiallyFocusedView();
if (view_to_focus)
view_to_focus->RequestFocus();
}
const std::string VPNConfigView::GetService() const {
if (service_textfield_ != NULL)
return GetTextFromField(service_textfield_, true);
return service_path_;
}
const std::string VPNConfigView::GetServer() const {
if (server_textfield_ != NULL)
return GetTextFromField(server_textfield_, true);
return server_hostname_;
}
const std::string VPNConfigView::GetPSKPassphrase() const {
if (psk_passphrase_textfield_ &&
enable_psk_passphrase_ &&
psk_passphrase_textfield_->visible())
return GetPassphraseFromField(psk_passphrase_textfield_);
return std::string();
}
const std::string VPNConfigView::GetUsername() const {
return GetTextFromField(username_textfield_, true);
}
const std::string VPNConfigView::GetUserPassphrase() const {
return GetPassphraseFromField(user_passphrase_textfield_);
}
const std::string VPNConfigView::GetGroupName() const {
return GetTextFromField(group_name_textfield_, false);
}
const std::string VPNConfigView::GetOTP() const {
return GetTextFromField(otp_textfield_, true);
}
const std::string VPNConfigView::GetServerCACertNssNickname() const {
DCHECK(cert_library_);
int index = server_ca_cert_combobox_ ?
server_ca_cert_combobox_->selected_index() : 0;
if (index == 0) {
// First item is "Default".
return std::string();
} else {
DCHECK(cert_library_);
DCHECK_GT(cert_library_->GetCACertificates().Size(), 0);
int cert_index = index - 1;
return cert_library_->GetCACertificates().GetNicknameAt(cert_index);
}
}
const std::string VPNConfigView::GetUserCertID() const {
DCHECK(cert_library_);
if (!HaveUserCerts()) {
return std::string(); // "None installed"
} else {
// Certificates are listed in the order they appear in the model.
int index = user_cert_combobox_ ? user_cert_combobox_->selected_index() : 0;
return cert_library_->GetUserCertificates().GetPkcs11IdAt(index);
}
}
void VPNConfigView::Init(VirtualNetwork* vpn) {
if (vpn) {
ParseVPNUIProperty(&ca_cert_ui_data_, vpn, onc::vpn::kServerCARef);
ParseVPNUIProperty(&psk_passphrase_ui_data_, vpn, onc::vpn::kPSK);
ParseVPNUIProperty(&user_cert_ui_data_, vpn, onc::vpn::kClientCertRef);
ParseVPNUIProperty(&username_ui_data_, vpn, onc::vpn::kUsername);
ParseVPNUIProperty(&user_passphrase_ui_data_, vpn, onc::vpn::kPassword);
ParseVPNUIProperty(&group_name_ui_data_, vpn, onc::vpn::kGroup);
}
views::GridLayout* layout = views::GridLayout::CreatePanel(this);
SetLayoutManager(layout);
// VPN may require certificates, so always set the library and observe.
cert_library_ = chromeos::CrosLibrary::Get()->GetCertLibrary();
// Setup a callback if certificates are yet to be loaded.
if (!cert_library_->CertificatesLoaded())
cert_library_->AddObserver(this);
int column_view_set_id = 0;
views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
// Label.
column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
views::GridLayout::USE_PREF, 0, 0);
column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
// Textfield, combobox.
column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
views::GridLayout::USE_PREF, 0,
ChildNetworkConfigView::kInputFieldMinWidth);
column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
// Policy indicator.
column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
views::GridLayout::USE_PREF, 0, 0);
// Initialize members.
service_text_modified_ = false;
if (vpn) {
provider_type_ = vpn->provider_type();
// Sets enable_* based on the provider type which we use to control
// which controls to make visible.
UpdateControlsToEnable();
} else {
// Set the default provider type.
provider_type_ = chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK;
// Provider Type is user selectable, so enable all controls during init.
enable_psk_passphrase_ = true;
enable_user_cert_ = true;
enable_server_ca_cert_ = true;
enable_otp_ = true;
enable_group_name_ = true;
}
// Server label and input.
// Only provide Server name when configuring a new VPN.
if (!vpn) {
layout->StartRow(0, column_view_set_id);
layout->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME)));
server_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
server_textfield_->SetController(this);
layout->AddView(server_textfield_);
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
server_textfield_ = NULL;
}
// Service label and name or input.
layout->StartRow(0, column_view_set_id);
layout->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME)));
if (!vpn) {
service_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
service_textfield_->SetController(this);
layout->AddView(service_textfield_);
service_text_ = NULL;
} else {
service_text_ = new views::Label(ASCIIToUTF16(vpn->name()));
service_text_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
layout->AddView(service_text_);
service_textfield_ = NULL;
}
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// Provider type label and select.
layout->StartRow(0, column_view_set_id);
layout->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE)));
if (!vpn) {
provider_type_combobox_ =
new views::Combobox(new ProviderTypeComboboxModel());
provider_type_combobox_->set_listener(this);
layout->AddView(provider_type_combobox_);
provider_type_text_label_ = NULL;
} else {
provider_type_text_label_ =
new views::Label(ProviderTypeToString(provider_type_));
provider_type_text_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
layout->AddView(provider_type_text_label_);
provider_type_combobox_ = NULL;
}
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// PSK passphrase label, input and visible button.
if (enable_psk_passphrase_) {
layout->StartRow(0, column_view_set_id);
psk_passphrase_label_ = new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE));
layout->AddView(psk_passphrase_label_);
bool has_psk_passphrase = vpn && !vpn->IsPSKPassphraseRequired();
psk_passphrase_textfield_ = new PassphraseTextfield(has_psk_passphrase);
psk_passphrase_textfield_->SetController(this);
layout->AddView(psk_passphrase_textfield_);
layout->AddView(
new ControlledSettingIndicatorView(psk_passphrase_ui_data_));
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
psk_passphrase_label_ = NULL;
psk_passphrase_textfield_ = NULL;
}
// Server CA certificate
// Only provide Server CA when configuring a new VPN.
if (!vpn) {
layout->StartRow(0, column_view_set_id);
server_ca_cert_label_ =
new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA));
layout->AddView(server_ca_cert_label_);
ServerCACertComboboxModel* server_ca_cert_model =
new ServerCACertComboboxModel(cert_library_);
server_ca_cert_combobox_ = new views::Combobox(server_ca_cert_model);
layout->AddView(server_ca_cert_combobox_);
layout->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_));
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
server_ca_cert_label_ = NULL;
server_ca_cert_combobox_ = NULL;
}
// User certificate label and input.
if (enable_user_cert_) {
layout->StartRow(0, column_view_set_id);
user_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT));
layout->AddView(user_cert_label_);
UserCertComboboxModel* user_cert_model =
new UserCertComboboxModel(cert_library_);
user_cert_combobox_ = new views::Combobox(user_cert_model);
user_cert_combobox_->set_listener(this);
layout->AddView(user_cert_combobox_);
layout->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_));
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
user_cert_label_ = NULL;
user_cert_combobox_ = NULL;
}
// Username label and input.
layout->StartRow(0, column_view_set_id);
layout->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME)));
username_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
username_textfield_->SetController(this);
username_textfield_->SetEnabled(username_ui_data_.editable());
if (vpn && !vpn->username().empty())
username_textfield_->SetText(UTF8ToUTF16(vpn->username()));
layout->AddView(username_textfield_);
layout->AddView(new ControlledSettingIndicatorView(username_ui_data_));
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// User passphrase label, input and visble button.
layout->StartRow(0, column_view_set_id);
layout->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE)));
bool has_user_passphrase = vpn && !vpn->IsUserPassphraseRequired();
user_passphrase_textfield_ = new PassphraseTextfield(has_user_passphrase);
user_passphrase_textfield_->SetController(this);
user_passphrase_textfield_->SetEnabled(user_passphrase_ui_data_.editable());
layout->AddView(user_passphrase_textfield_);
layout->AddView(new ControlledSettingIndicatorView(user_passphrase_ui_data_));
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// OTP label and input.
if (enable_otp_) {
layout->StartRow(0, column_view_set_id);
otp_label_ = new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP));
layout->AddView(otp_label_);
otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
otp_textfield_->SetController(this);
layout->AddView(otp_textfield_);
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
otp_label_ = NULL;
otp_textfield_ = NULL;
}
// This is not currently implemented with no immediate plans to do so.
// TODO(stevenjb,kmixter): Remove 'false &&' below if we implement this.
// See http://crosbug.com/19252.
const bool show_group_name = false && enable_group_name_;
// Group Name label and input.
if (show_group_name) {
layout->StartRow(0, column_view_set_id);
group_name_label_ = new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME));
layout->AddView(group_name_label_);
group_name_textfield_ =
new views::Textfield(views::Textfield::STYLE_DEFAULT);
group_name_textfield_->SetController(this);
if (vpn && !vpn->group_name().empty())
group_name_textfield_->SetText(UTF8ToUTF16(vpn->group_name()));
layout->AddView(group_name_textfield_);
layout->AddView(new ControlledSettingIndicatorView(group_name_ui_data_));
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
group_name_label_ = NULL;
group_name_textfield_ = NULL;
}
// Error label.
layout->StartRow(0, column_view_set_id);
layout->SkipColumns(1);
error_label_ = new views::Label();
error_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
error_label_->SetEnabledColor(SK_ColorRED);
layout->AddView(error_label_);
// Set or hide the UI, update comboboxes and error labels.
Refresh();
}
void VPNConfigView::Refresh() {
NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
UpdateControls();
// Set certificate combo boxes.
VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
if (server_ca_cert_combobox_) {
server_ca_cert_combobox_->ModelChanged();
if (enable_server_ca_cert_ &&
(vpn && !vpn->ca_cert_nss().empty())) {
// Select the current server CA certificate in the combobox.
int cert_index = cert_library_->GetCACertificates().FindCertByNickname(
vpn->ca_cert_nss());
if (cert_index >= 0) {
// Skip item for "Default"
server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
} else {
server_ca_cert_combobox_->SetSelectedIndex(0);
}
} else {
server_ca_cert_combobox_->SetSelectedIndex(0);
}
}
if (user_cert_combobox_) {
user_cert_combobox_->ModelChanged();
if (enable_user_cert_ &&
(vpn && !vpn->client_cert_id().empty())) {
int cert_index = cert_library_->GetUserCertificates().FindCertByPkcs11Id(
vpn->client_cert_id());
if (cert_index >= 0)
user_cert_combobox_->SetSelectedIndex(cert_index);
else
user_cert_combobox_->SetSelectedIndex(0);
} else {
user_cert_combobox_->SetSelectedIndex(0);
}
}
UpdateErrorLabel();
}
void VPNConfigView::UpdateControlsToEnable() {
// Set which controls are enabled.
enable_psk_passphrase_ = false;
enable_user_cert_ = false;
enable_server_ca_cert_ = false;
enable_otp_ = false;
enable_group_name_ = false;
switch (provider_type_) {
case PROVIDER_TYPE_L2TP_IPSEC_PSK:
enable_psk_passphrase_ = true;
enable_group_name_ = true;
break;
case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
enable_server_ca_cert_ = true;
enable_user_cert_ = HaveUserCerts();
enable_group_name_ = true;
break;
case PROVIDER_TYPE_OPEN_VPN:
enable_server_ca_cert_ = true;
enable_user_cert_ = HaveUserCerts();
enable_otp_ = true;
break;
default:
NOTREACHED();
break;
}
}
void VPNConfigView::UpdateControls() {
UpdateControlsToEnable();
if (psk_passphrase_label_)
psk_passphrase_label_->SetEnabled(enable_psk_passphrase_);
if (psk_passphrase_textfield_)
psk_passphrase_textfield_->SetEnabled(enable_psk_passphrase_ &&
psk_passphrase_ui_data_.editable());
if (user_cert_label_)
user_cert_label_->SetEnabled(enable_user_cert_);
if (user_cert_combobox_)
user_cert_combobox_->SetEnabled(enable_user_cert_ &&
user_cert_ui_data_.editable());
if (server_ca_cert_label_)
server_ca_cert_label_->SetEnabled(enable_server_ca_cert_);
if (server_ca_cert_combobox_)
server_ca_cert_combobox_->SetEnabled(enable_server_ca_cert_ &&
ca_cert_ui_data_.editable());
if (otp_label_)
otp_label_->SetEnabled(enable_otp_);
if (otp_textfield_)
otp_textfield_->SetEnabled(enable_otp_);
if (group_name_label_)
group_name_label_->SetEnabled(enable_group_name_);
if (group_name_textfield_)
group_name_textfield_->SetEnabled(enable_group_name_ &&
group_name_ui_data_.editable());
}
void VPNConfigView::UpdateErrorLabel() {
NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
// Error message.
std::string error_msg;
if (UserCertRequired() && cert_library_->CertificatesLoaded()) {
if (!HaveUserCerts()) {
error_msg = l10n_util::GetStringUTF8(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT);
} else if (!IsUserCertValid()) {
error_msg = l10n_util::GetStringUTF8(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED);
}
}
if (error_msg.empty() && !service_path_.empty()) {
// TODO(kuan): differentiate between bad psk and user passphrases.
VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
if (vpn && vpn->failed()) {
if (vpn->error() == ERROR_BAD_PASSPHRASE) {
error_msg = l10n_util::GetStringUTF8(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
} else {
error_msg = vpn->GetErrorString();
}
}
}
if (!error_msg.empty()) {
error_label_->SetText(UTF8ToUTF16(error_msg));
error_label_->SetVisible(true);
} else {
error_label_->SetVisible(false);
}
}
void VPNConfigView::UpdateCanLogin() {
parent_->GetDialogClientView()->UpdateDialogButtons();
}
bool VPNConfigView::UserCertRequired() const {
return provider_type_ == PROVIDER_TYPE_L2TP_IPSEC_USER_CERT;
}
bool VPNConfigView::HaveUserCerts() const {
return cert_library_->GetUserCertificates().Size() > 0;
}
bool VPNConfigView::IsUserCertValid() const {
if (!user_cert_combobox_ || !enable_user_cert_)
return false;
int index = user_cert_combobox_->selected_index();
if (index < 0)
return false;
// Currently only hardware-backed user certificates are valid.
if (cert_library_->IsHardwareBacked() &&
!cert_library_->GetUserCertificates().IsHardwareBackedAt(index))
return false;
return true;
}
const std::string VPNConfigView::GetTextFromField(views::Textfield* textfield,
bool trim_whitespace) const {
if (!textfield)
return std::string();
std::string untrimmed = UTF16ToUTF8(textfield->text());
if (!trim_whitespace)
return untrimmed;
std::string result;
TrimWhitespaceASCII(untrimmed, TRIM_ALL, &result);
return result;
}
const std::string VPNConfigView::GetPassphraseFromField(
PassphraseTextfield* textfield) const {
if (!textfield)
return std::string();
return textfield->GetPassphrase();
}
void VPNConfigView::ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data,
Network* network,
const std::string& key) {
NetworkLibrary* network_library = CrosLibrary::Get()->GetNetworkLibrary();
const base::DictionaryValue* onc =
network_library->FindOncForNetwork(network->unique_id());
base::DictionaryValue* vpn_dict = NULL;
if (!onc || !onc->GetDictionary(onc::kVPN, &vpn_dict))
return;
std::string vpn_type;
if (!vpn_dict || !vpn_dict->GetString(onc::kType, &vpn_type))
return;
property_ui_data->ParseOncProperty(
network->ui_data(), onc,
base::StringPrintf("%s.%s.%s", onc::kVPN, vpn_type.c_str(), key.c_str()));
}
} // namespace chromeos