diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-29 17:49:58 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-29 17:49:58 +0000 |
commit | eeb49a365c8bb421b237c125c36f8aaa02d77646 (patch) | |
tree | f0318aed9dddb7cbeb3bbae249d9de11c15da3b4 | |
parent | 4a3f36c05d9e4c9b355844c7efc377c50b12cc88 (diff) | |
download | chromium_src-eeb49a365c8bb421b237c125c36f8aaa02d77646.zip chromium_src-eeb49a365c8bb421b237c125c36f8aaa02d77646.tar.gz chromium_src-eeb49a365c8bb421b237c125c36f8aaa02d77646.tar.bz2 |
CrOS - List user certificates in VPN connect dialog UI.
User certificates are still not supported fully by the underlying network code, but this lists them in the VPN UI.
BUG=chromium-os:13974
TEST=Ensure you have no user certificates installed. Delete them with Manage certificates if necessary. Under about:flags enable the VPN experiment. Under network menu create a new VPN network. Verify that the user certificate combobox says "none installed" and is disabled. Add a user certificate (use Settings > Under the hood > Manage certificates, import a .p12 file containing an X509 certificate with a public/private key pair). Create a new VPN network again. Verify that your user certificate is listed in the certificates combobox.
Review URL: http://codereview.chromium.org/6880215
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83541 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 6 | ||||
-rw-r--r-- | chrome/browser/chromeos/options/vpn_config_view.cc | 145 | ||||
-rw-r--r-- | chrome/browser/chromeos/options/vpn_config_view.h | 31 |
3 files changed, 126 insertions, 56 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 624032c..f33174f 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -10415,6 +10415,12 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE" desc="In settings Internet options, a string specifying VPN user passphrase."> Password: </message> + <message name="IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT_NONE_INSTALLED" desc="In settings Internet options, when creating a VPN connection, combobox item to display when no user certificates are installed."> + None installed + </message> + <message name="IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PLEASE_INSTALL_USER_CERT" desc="In settings Internet options, when creating a VPN connection, error message to display when no user certificates are installed."> + Please install a user certificate. + </message> <message name="IDS_NETWORK_RECONNECT_TITLE" desc="In network menu, title of the reconnect button that allows user to retry connection on error."> Reconnect </message> diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc index 9e9d846..fadbbe0 100644 --- a/chrome/browser/chromeos/options/vpn_config_view.cc +++ b/chrome/browser/chromeos/options/vpn_config_view.cc @@ -8,14 +8,16 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/login/user_manager.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 "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" @@ -46,31 +48,79 @@ string16 ProviderTypeToString(chromeos::VirtualNetwork::ProviderType type) { 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; -} +class ProviderTypeComboboxModel : public ui::ComboboxModel { + public: + ProviderTypeComboboxModel() {} + virtual ~ProviderTypeComboboxModel() {} + virtual int GetItemCount() { + // TODO(stevenjb): Include OpenVPN option once enabled. + return VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT + 1; + // return VirtualNetwork::PROVIDER_TYPE_MAX; + } + virtual string16 GetItemAt(int index) { + VirtualNetwork::ProviderType type = + static_cast<VirtualNetwork::ProviderType>(index); + return ProviderTypeToString(type); + } + private: + DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel); +}; + +class UserCertComboboxModel : public ui::ComboboxModel { + public: + UserCertComboboxModel() { + net::CertDatabase cert_db; + net::CertificateList cert_list; + cert_db.ListCerts(&cert_list); + // Find all the user certificates. There shouldn't be many. + for (net::CertificateList::const_iterator it = cert_list.begin(); + it != cert_list.end(); ++it) { + net::X509Certificate* cert = it->get(); + net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); + net::CertType type = x509_certificate_model::GetType(cert_handle); + if (type == net::USER_CERT) + user_certs_.push_back(*it); + } + } + virtual ~UserCertComboboxModel() {} -string16 VPNConfigView::ProviderTypeComboboxModel::GetItemAt(int index) { - VirtualNetwork::ProviderType type = - static_cast<VirtualNetwork::ProviderType>(index); - return ProviderTypeToString(type); -} + virtual int GetItemCount() { + if (user_certs_.empty()) + return 1; // "None installed" item + return static_cast<int>(user_certs_.size()); + } -VPNConfigView::UserCertComboboxModel::UserCertComboboxModel() { - // TODO(jamescook): populate user_certs_. chromium-os:14111 -} + virtual string16 GetItemAt(int index) { + if (user_certs_.empty()) { + // "None installed" item. + return l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT_NONE_INSTALLED); + } + if (index >= 0 && index < static_cast<int>(user_certs_.size())) { + net::X509Certificate* cert = user_certs_[index].get(); + std::string name = + x509_certificate_model::GetCertNameOrNickname(cert->os_cert_handle()); + return UTF8ToUTF16(name); + } + return string16(); + } -int VPNConfigView::UserCertComboboxModel::GetItemCount() { - return static_cast<int>(user_certs_.size()); -} + bool HaveCerts() { + return !user_certs_.empty(); + } -string16 VPNConfigView::UserCertComboboxModel::GetItemAt(int index) { - if (index >= 0 && index < static_cast<int>(user_certs_.size())) - return ASCIIToUTF16(user_certs_[index]); - return string16(); -} + std::string GetCertID(int index) { + if (0 <= index && index < static_cast<int>(user_certs_.size())) { + // TODO(jamescook): Return the proper ID for flimflam, perhaps PKCS#11? + return "/tmp/ca.pem"; + } + return std::string(); + } + + private: + net::CertificateList user_certs_; + DISALLOW_COPY_AND_ASSIGN(UserCertComboboxModel); +}; VPNConfigView::VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn) : ChildNetworkConfigView(parent, vpn) { @@ -101,6 +151,8 @@ bool VPNConfigView::CanLogin() { if (provider_type_ == VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_PSK && psk_passphrase_textfield_->text().length() < kMinPassphraseLen) return false; + if (UserCertRequired() && GetUserCertID().empty()) + return false; if (GetUsername().empty()) return false; if (user_passphrase_textfield_->text().length() < kMinPassphraseLen) @@ -110,6 +162,9 @@ bool VPNConfigView::CanLogin() { void VPNConfigView::UpdateErrorLabel() { std::string error_msg; + if (UserCertRequired() && GetUserCertID().empty()) + error_msg = l10n_util::GetStringUTF8( + IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PLEASE_INSTALL_USER_CERT); if (!service_path_.empty()) { // TODO(kuan): differentiate between bad psk and user passphrases. NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); @@ -131,11 +186,16 @@ void VPNConfigView::UpdateErrorLabel() { } } +bool VPNConfigView::UserCertRequired() const { + return provider_type_ == VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT + || provider_type_ == VirtualNetwork::PROVIDER_TYPE_OPEN_VPN; +} + 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. + // 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); @@ -171,6 +231,7 @@ void VPNConfigView::ItemChanged(views::Combobox* combo_box, if (combo_box == provider_type_combobox_) { provider_type_ = static_cast<VirtualNetwork::ProviderType>(new_index); EnableControls(); + UpdateErrorLabel(); } else if (combo_box == user_cert_combobox_) { // Nothing to do for now. } else { @@ -211,10 +272,10 @@ bool VPNConfigView::Login() { 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); + // TODO(jamescook): Figure out if flimflam consumes a cert path, + // PKCS#11 ID or other identifier. Then do something like: + // vpn->SetUserCertID(GetUserCertID()); + LOG(WARNING) << "VPN user certs not yet supported."; break; } case VirtualNetwork::PROVIDER_TYPE_MAX: @@ -234,7 +295,17 @@ void VPNConfigView::Cancel() { } void VPNConfigView::InitFocus() { - // TODO(jamescook): Put focus in a more reasonable widget. + // Put focus in the first editable field. + if (server_textfield_) + server_textfield_->RequestFocus(); + else if (service_textfield_) + service_textfield_->RequestFocus(); + else if (provider_type_combobox_) + provider_type_combobox_->RequestFocus(); + else if (psk_passphrase_textfield_ && psk_passphrase_textfield_->IsEnabled()) + psk_passphrase_textfield_->RequestFocus(); + else if (user_cert_combobox_ && user_cert_combobox_->IsEnabled()) + user_cert_combobox_->RequestFocus(); } const std::string VPNConfigView::GetTextFromField( @@ -274,6 +345,13 @@ const std::string VPNConfigView::GetUserPassphrase() const { return GetTextFromField(user_passphrase_textfield_, false); } +const std::string VPNConfigView::GetUserCertID() const { + int selected = user_cert_combobox_->selected_item(); + UserCertComboboxModel* model = static_cast<UserCertComboboxModel*>( + user_cert_combobox_->model()); + return model->GetCertID(selected); +} + void VPNConfigView::Init(VirtualNetwork* vpn) { views::GridLayout* layout = views::GridLayout::CreatePanel(this); SetLayoutManager(layout); @@ -376,6 +454,8 @@ void VPNConfigView::Init(VirtualNetwork* vpn) { if (vpn && !vpn->user_cert().empty()) { string16 user_cert = UTF8ToUTF16(vpn->user_cert()); for (int i = 0; i < user_cert_combobox_->model()->GetItemCount(); ++i) { + // TODO(jamescook): Select the proper certificate based on the + // appropriate property from flimflam, perhaps PKCS#11 ID. if (user_cert_combobox_->model()->GetItemAt(i) == user_cert) { user_cert_combobox_->SetSelectedItem(i); break; @@ -433,12 +513,15 @@ void VPNConfigView::EnableControls() { user_cert_combobox_->SetEnabled(false); break; case VirtualNetwork::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: - case VirtualNetwork::PROVIDER_TYPE_OPEN_VPN: + 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); + // Only enable the combobox if the user actually has a cert to select. + bool have_cert = !GetUserCertID().empty(); + user_cert_combobox_->SetEnabled(have_cert); break; + } default: NOTREACHED(); } diff --git a/chrome/browser/chromeos/options/vpn_config_view.h b/chrome/browser/chromeos/options/vpn_config_view.h index 01bbc89..7670d07 100644 --- a/chrome/browser/chromeos/options/vpn_config_view.h +++ b/chrome/browser/chromeos/options/vpn_config_view.h @@ -12,9 +12,7 @@ #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/options/network_config_view.h" #include "chrome/browser/ui/shell_dialogs.h" -#include "ui/base/models/combobox_model.h" #include "views/controls/button/button.h" -#include "views/controls/button/native_button.h" #include "views/controls/combobox/combobox.h" #include "views/controls/textfield/textfield_controller.h" #include "views/view.h" @@ -56,27 +54,6 @@ class VPNConfigView : public ChildNetworkConfigView, virtual void InitFocus() OVERRIDE; private: - class ProviderTypeComboboxModel : public ui::ComboboxModel { - public: - ProviderTypeComboboxModel() {} - virtual ~ProviderTypeComboboxModel() {} - virtual int GetItemCount(); - virtual string16 GetItemAt(int index); - private: - DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel); - }; - - class UserCertComboboxModel : public ui::ComboboxModel { - public: - UserCertComboboxModel(); - virtual ~UserCertComboboxModel() {} - virtual int GetItemCount(); - virtual string16 GetItemAt(int index); - private: - std::vector<std::string> user_certs_; - DISALLOW_COPY_AND_ASSIGN(UserCertComboboxModel); - }; - // Initializes data members and create UI controls. void Init(VirtualNetwork* vpn); @@ -88,6 +65,9 @@ class VPNConfigView : public ChildNetworkConfigView, // Update the error text label. void UpdateErrorLabel(); + // Returns true if the provider type requires a user certificate. + bool UserCertRequired() const; + // Get text from input field. const std::string GetTextFromField(views::Textfield* textfield, bool trim_whitespace) const; @@ -98,16 +78,17 @@ class VPNConfigView : public ChildNetworkConfigView, const std::string GetPSKPassphrase() const; const std::string GetUsername() const; const std::string GetUserPassphrase() const; + const std::string GetUserCertID() const; std::string server_hostname_; string16 service_name_from_server_; bool service_text_modified_; VirtualNetwork::ProviderType provider_type_; - views::Label* service_text_; - views::Textfield* service_textfield_; views::Label* server_text_; views::Textfield* server_textfield_; + views::Label* service_text_; + views::Textfield* service_textfield_; views::Combobox* provider_type_combobox_; views::Label* provider_type_text_label_; views::Label* psk_passphrase_label_; |