| // Copyright (c) 2011 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/utf_string_conversions.h" |
| #include "chrome/browser/chromeos/cros/cros_library.h" |
| #include "chrome/browser/chromeos/login/user_manager.h" |
| #include "grit/chromium_strings.h" |
| #include "grit/generated_resources.h" |
| #include "grit/locale_settings.h" |
| #include "grit/theme_resources.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "views/controls/button/image_button.h" |
| #include "views/controls/button/native_button.h" |
| #include "views/controls/label.h" |
| #include "views/controls/textfield/textfield.h" |
| #include "views/layout/grid_layout.h" |
| #include "views/layout/layout_constants.h" |
| #include "views/window/window.h" |
| |
| namespace { |
| |
| string16 ProviderTypeToString(chromeos::VirtualNetwork::ProviderType type) { |
| switch (type) { |
| case chromeos::VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK: |
| return l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK); |
| case chromeos::VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: |
| return l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT); |
| case chromeos::VirtualNetwork::PROVIDER_TYPE_OPEN_VPN: |
| return l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN); |
| case chromeos::VirtualNetwork::PROVIDER_TYPE_MAX: |
| break; |
| } |
| NOTREACHED(); |
| return string16(); |
| } |
| |
| } // namespace |
| |
| namespace chromeos { |
| |
| int VPNConfigView::ProviderTypeComboboxModel::GetItemCount() { |
| // TODO(stevenjb): Include OpenVPN option once enabled. |
| return VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT + 1; |
| // return VirtualNetwork::PROVIDER_TYPE_MAX; |
| } |
| |
| string16 VPNConfigView::ProviderTypeComboboxModel::GetItemAt(int index) { |
| VirtualNetwork::ProviderType type = |
| static_cast<VirtualNetwork::ProviderType>(index); |
| return ProviderTypeToString(type); |
| } |
| |
| VPNConfigView::UserCertComboboxModel::UserCertComboboxModel() { |
| // TODO(jamescook): populate user_certs_. chromium-os:14111 |
| } |
| |
| int VPNConfigView::UserCertComboboxModel::GetItemCount() { |
| return static_cast<int>(user_certs_.size()); |
| } |
| |
| string16 VPNConfigView::UserCertComboboxModel::GetItemAt(int index) { |
| if (index >= 0 && index < static_cast<int>(user_certs_.size())) |
| return ASCIIToUTF16(user_certs_[index]); |
| return string16(); |
| } |
| |
| VPNConfigView::VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn) |
| : ChildNetworkConfigView(parent, vpn) { |
| Init(vpn); |
| } |
| |
| VPNConfigView::VPNConfigView(NetworkConfigView* parent) |
| : ChildNetworkConfigView(parent) { |
| Init(NULL); |
| } |
| |
| VPNConfigView::~VPNConfigView() { |
| } |
| |
| void VPNConfigView::UpdateCanLogin() { |
| parent_->GetDialogClientView()->UpdateDialogButtons(); |
| } |
| |
| string16 VPNConfigView::GetTitle() { |
| return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_ADD_VPN); |
| } |
| |
| bool VPNConfigView::CanLogin() { |
| static const size_t kMinPassphraseLen = 0; // TODO(stevenjb): min length? |
| if (service_path_.empty() && |
| (GetService().empty() || GetServer().empty())) |
| return false; |
| if (provider_type_ == VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK && |
| psk_passphrase_textfield_->text().length() < kMinPassphraseLen) |
| return false; |
| if (GetUsername().empty()) |
| return false; |
| if (user_passphrase_textfield_->text().length() < kMinPassphraseLen) |
| return false; |
| return true; |
| } |
| |
| void VPNConfigView::UpdateErrorLabel() { |
| std::string error_msg; |
| if (!service_path_.empty()) { |
| // TODO(kuan): differentiate between bad psk and user passphrases. |
| NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); |
| 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(UTF8ToWide(error_msg)); |
| error_label_->SetVisible(true); |
| } else { |
| error_label_->SetVisible(false); |
| } |
| } |
| |
| 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 explicityly 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::ItemChanged(views::Combobox* combo_box, |
| int prev_index, int new_index) { |
| if (prev_index == new_index) |
| return; |
| if (combo_box == provider_type_combobox_) { |
| provider_type_ = static_cast<VirtualNetwork::ProviderType>(new_index); |
| EnableControls(); |
| } else if (combo_box == user_cert_combobox_) { |
| // Nothing to do for now. |
| } else { |
| NOTREACHED(); |
| } |
| UpdateCanLogin(); |
| } |
| |
| bool VPNConfigView::Login() { |
| NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); |
| if (service_path_.empty()) { |
| switch (provider_type_) { |
| case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK: |
| cros->ConnectToVirtualNetworkPSK(GetService(), |
| GetServer(), |
| GetPSKPassphrase(), |
| GetUsername(), |
| GetUserPassphrase()); |
| break; |
| case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: |
| case VirtualNetwork::PROVIDER_TYPE_OPEN_VPN: |
| // TODO(stevenjb): Add support for OpenVPN and user certs. |
| LOG(WARNING) << "Unsupported provider type: " << provider_type_; |
| break; |
| case VirtualNetwork::PROVIDER_TYPE_MAX: |
| break; |
| } |
| } 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 VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK: |
| vpn->SetPSKPassphrase(GetPSKPassphrase()); |
| break; |
| case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: |
| case VirtualNetwork::PROVIDER_TYPE_OPEN_VPN: { |
| const std::string user_cert = UTF16ToUTF8( |
| user_cert_combobox_->model()->GetItemAt( |
| user_cert_combobox_->selected_item())); |
| vpn->SetUserCert(user_cert); |
| break; |
| } |
| case VirtualNetwork::PROVIDER_TYPE_MAX: |
| break; |
| } |
| vpn->SetUsername(GetUsername()); |
| vpn->SetUserPassphrase(GetUserPassphrase()); |
| |
| cros->ConnectToVirtualNetwork(vpn); |
| } |
| // Connection failures are responsible for updating the UI, including |
| // reopening dialogs. |
| return true; // Close dialog. |
| } |
| |
| void VPNConfigView::Cancel() { |
| } |
| |
| void VPNConfigView::InitFocus() { |
| // TODO(jamescook): Put focus in a more reasonable widget. |
| } |
| |
| const std::string VPNConfigView::GetTextFromField( |
| views::Textfield* textfield, bool trim_whitespace) const { |
| 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::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_->IsEnabled() && |
| psk_passphrase_textfield_->IsVisible()) |
| return GetTextFromField(psk_passphrase_textfield_, false); |
| return std::string(); |
| } |
| |
| const std::string VPNConfigView::GetUsername() const { |
| return GetTextFromField(username_textfield_, true); |
| } |
| |
| const std::string VPNConfigView::GetUserPassphrase() const { |
| return GetTextFromField(user_passphrase_textfield_, false); |
| } |
| |
| void VPNConfigView::Init(VirtualNetwork* vpn) { |
| views::GridLayout* layout = views::GridLayout::CreatePanel(this); |
| SetLayoutManager(layout); |
| |
| 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::kPassphraseWidth); |
| column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing); |
| // Passphrase visible button. |
| column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL, 1, |
| views::GridLayout::USE_PREF, 0, 0); |
| |
| // Initialize members. |
| service_text_modified_ = false; |
| provider_type_ = vpn ? |
| vpn->provider_type() : |
| chromeos::VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK; |
| |
| // Server label and input. |
| layout->StartRow(0, column_view_set_id); |
| layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME)))); |
| if (!vpn) { |
| server_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); |
| server_textfield_->SetController(this); |
| layout->AddView(server_textfield_); |
| server_text_ = NULL; |
| } else { |
| server_hostname_ = vpn->server_hostname(); |
| server_text_ = new views::Label(UTF8ToWide(server_hostname_)); |
| server_text_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| layout->AddView(server_text_); |
| server_textfield_ = NULL; |
| } |
| layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| |
| // Service label and name or input. |
| layout->StartRow(0, column_view_set_id); |
| layout->AddView(new views::Label(UTF16ToWide(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(ASCIIToWide(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(UTF16ToWide(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(UTF16ToWide(ProviderTypeToString(provider_type_))); |
| layout->AddView(provider_type_text_label_); |
| provider_type_combobox_ = NULL; |
| } |
| layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| |
| // PSK passphrase label, input and visible button. |
| layout->StartRow(0, column_view_set_id); |
| psk_passphrase_label_ = new views::Label(UTF16ToWide( |
| l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE))); |
| layout->AddView(psk_passphrase_label_); |
| psk_passphrase_textfield_ = new views::Textfield( |
| views::Textfield::STYLE_PASSWORD); |
| psk_passphrase_textfield_->SetController(this); |
| if (vpn && !vpn->psk_passphrase().empty()) |
| psk_passphrase_textfield_->SetText(UTF8ToUTF16(vpn->psk_passphrase())); |
| layout->AddView(psk_passphrase_textfield_); |
| layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| |
| // User certificate label and input. |
| layout->StartRow(0, column_view_set_id); |
| user_cert_label_ = new views::Label(UTF16ToWide(l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT))); |
| layout->AddView(user_cert_label_); |
| user_cert_combobox_ = new views::Combobox(new UserCertComboboxModel()); |
| user_cert_combobox_->set_listener(this); |
| if (vpn && !vpn->user_cert().empty()) { |
| string16 user_cert = UTF8ToUTF16(vpn->user_cert()); |
| for (int i = 0; i < user_cert_combobox_->model()->GetItemCount(); ++i) { |
| if (user_cert_combobox_->model()->GetItemAt(i) == user_cert) { |
| user_cert_combobox_->SetSelectedItem(i); |
| break; |
| } |
| } |
| } |
| layout->AddView(user_cert_combobox_); |
| layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| |
| // Username label and input. |
| layout->StartRow(0, column_view_set_id); |
| layout->AddView(new views::Label(UTF16ToWide(l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME)))); |
| username_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT); |
| username_textfield_->SetController(this); |
| if (vpn && !vpn->username().empty()) |
| username_textfield_->SetText(UTF8ToUTF16(vpn->username())); |
| layout->AddView(username_textfield_); |
| layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| |
| // User passphrase label, input and visble button. |
| layout->StartRow(0, column_view_set_id); |
| layout->AddView(new views::Label(UTF16ToWide( |
| l10n_util::GetStringUTF16( |
| IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE)))); |
| user_passphrase_textfield_ = new views::Textfield( |
| views::Textfield::STYLE_PASSWORD); |
| user_passphrase_textfield_->SetController(this); |
| if (vpn && !vpn->user_passphrase().empty()) |
| user_passphrase_textfield_->SetText(UTF8ToUTF16(vpn->user_passphrase())); |
| layout->AddView(user_passphrase_textfield_); |
| layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| |
| // 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_->SetColor(SK_ColorRED); |
| layout->AddView(error_label_); |
| |
| // Enable controls based on provider type combo. |
| EnableControls(); |
| |
| // Set or hide the error text. |
| UpdateErrorLabel(); |
| } |
| |
| void VPNConfigView::EnableControls() { |
| switch (provider_type_) { |
| case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK: |
| psk_passphrase_label_->SetEnabled(true); |
| psk_passphrase_textfield_->SetEnabled(true); |
| user_cert_label_->SetEnabled(false); |
| user_cert_combobox_->SetEnabled(false); |
| break; |
| case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: |
| case VirtualNetwork::PROVIDER_TYPE_OPEN_VPN: |
| psk_passphrase_label_->SetEnabled(false); |
| psk_passphrase_textfield_->SetEnabled(false); |
| user_cert_label_->SetEnabled(true); |
| user_cert_combobox_->SetEnabled(true); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| } // namespace chromeos |