ssl_client_certificate_selector.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/ui/views/ssl_client_certificate_selector.h" 6 7#include "base/compiler_specific.h" 8#include "base/i18n/time_formatting.h" 9#include "base/logging.h" 10#include "base/utf_string_conversions.h" 11#include "chrome/browser/certificate_viewer.h" 12#include "chrome/browser/ui/views/constrained_window_views.h" 13#include "components/web_modal/web_contents_modal_dialog_manager.h" 14#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" 15#include "content/public/browser/browser_thread.h" 16#include "content/public/browser/web_contents.h" 17#include "content/public/browser/web_contents_view.h" 18#include "grit/generated_resources.h" 19#include "net/cert/x509_certificate.h" 20#include "net/ssl/ssl_cert_request_info.h" 21#include "ui/base/l10n/l10n_util.h" 22#include "ui/base/models/table_model.h" 23#include "ui/base/models/table_model_observer.h" 24#include "ui/gfx/native_widget_types.h" 25#include "ui/views/controls/button/label_button.h" 26#include "ui/views/controls/label.h" 27#include "ui/views/controls/table/table_view.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 33using content::BrowserThread; 34using content::WebContents; 35using web_modal::WebContentsModalDialogManager; 36 37namespace { 38 39// The dimensions of the certificate selector table view, in pixels. 40static const int kTableViewWidth = 400; 41static const int kTableViewHeight = 100; 42 43} // namespace 44 45/////////////////////////////////////////////////////////////////////////////// 46// CertificateSelectorTableModel: 47 48class CertificateSelectorTableModel : public ui::TableModel { 49 public: 50 explicit CertificateSelectorTableModel( 51 net::SSLCertRequestInfo* cert_request_info); 52 53 // ui::TableModel implementation: 54 virtual int RowCount() OVERRIDE; 55 virtual string16 GetText(int index, int column_id) OVERRIDE; 56 virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE; 57 58 private: 59 std::vector<string16> items_; 60 61 DISALLOW_COPY_AND_ASSIGN(CertificateSelectorTableModel); 62}; 63 64CertificateSelectorTableModel::CertificateSelectorTableModel( 65 net::SSLCertRequestInfo* cert_request_info) { 66 for (size_t i = 0; i < cert_request_info->client_certs.size(); ++i) { 67 net::X509Certificate* cert = cert_request_info->client_certs[i]; 68 string16 text = l10n_util::GetStringFUTF16( 69 IDS_CERT_SELECTOR_TABLE_CERT_FORMAT, 70 UTF8ToUTF16(cert->subject().GetDisplayName()), 71 UTF8ToUTF16(cert->issuer().GetDisplayName())); 72 items_.push_back(text); 73 } 74} 75 76int CertificateSelectorTableModel::RowCount() { 77 return items_.size(); 78} 79 80string16 CertificateSelectorTableModel::GetText(int index, int column_id) { 81 DCHECK_EQ(column_id, 0); 82 DCHECK_GE(index, 0); 83 DCHECK_LT(index, static_cast<int>(items_.size())); 84 85 return items_[index]; 86} 87 88void CertificateSelectorTableModel::SetObserver( 89 ui::TableModelObserver* observer) { 90} 91 92/////////////////////////////////////////////////////////////////////////////// 93// SSLClientCertificateSelector: 94 95SSLClientCertificateSelector::SSLClientCertificateSelector( 96 WebContents* web_contents, 97 const net::HttpNetworkSession* network_session, 98 net::SSLCertRequestInfo* cert_request_info, 99 const chrome::SelectCertificateCallback& callback) 100 : SSLClientAuthObserver(network_session, cert_request_info, callback), 101 model_(new CertificateSelectorTableModel(cert_request_info)), 102 web_contents_(web_contents), 103 window_(NULL), 104 table_(NULL), 105 view_cert_button_(NULL) { 106 DVLOG(1) << __FUNCTION__; 107} 108 109SSLClientCertificateSelector::~SSLClientCertificateSelector() { 110 table_->SetModel(NULL); 111} 112 113void SSLClientCertificateSelector::Init() { 114 views::GridLayout* layout = views::GridLayout::CreatePanel(this); 115 SetLayoutManager(layout); 116 117 const int column_set_id = 0; 118 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); 119 column_set->AddColumn( 120 views::GridLayout::FILL, views::GridLayout::FILL, 121 1, views::GridLayout::USE_PREF, 0, 0); 122 123 layout->StartRow(0, column_set_id); 124 string16 text = l10n_util::GetStringFUTF16( 125 IDS_CLIENT_CERT_DIALOG_TEXT, 126 ASCIIToUTF16(cert_request_info()->host_and_port)); 127 views::Label* label = new views::Label(text); 128 label->SetMultiLine(true); 129 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 130 label->SetAllowCharacterBreak(true); 131 layout->AddView(label); 132 133 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 134 135 CreateCertTable(); 136 layout->StartRow(1, column_set_id); 137 layout->AddView(table_->CreateParentIfNecessary(), 1, 1, 138 views::GridLayout::FILL, 139 views::GridLayout::FILL, kTableViewWidth, kTableViewHeight); 140 141 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 142 143 StartObserving(); 144 145 WebContentsModalDialogManager* web_contents_modal_dialog_manager = 146 WebContentsModalDialogManager::FromWebContents(web_contents_); 147 window_ = CreateWebContentsModalDialogViews( 148 this, 149 web_contents_->GetView()->GetNativeView(), 150 web_contents_modal_dialog_manager->delegate()-> 151 GetWebContentsModalDialogHost()); 152 web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView()); 153 154 // Select the first row automatically. This must be done after the dialog has 155 // been created. 156 table_->Select(0); 157} 158 159net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() const { 160 int selected = table_->FirstSelectedRow(); 161 if (selected >= 0 && 162 selected < static_cast<int>( 163 cert_request_info()->client_certs.size())) 164 return cert_request_info()->client_certs[selected]; 165 return NULL; 166} 167 168/////////////////////////////////////////////////////////////////////////////// 169// SSLClientAuthObserver implementation: 170 171void SSLClientCertificateSelector::OnCertSelectedByNotification() { 172 DVLOG(1) << __FUNCTION__; 173 DCHECK(window_); 174 window_->Close(); 175} 176 177/////////////////////////////////////////////////////////////////////////////// 178// DialogDelegateView implementation: 179 180bool SSLClientCertificateSelector::CanResize() const { 181 return true; 182} 183 184string16 SSLClientCertificateSelector::GetWindowTitle() const { 185 return l10n_util::GetStringUTF16(IDS_CLIENT_CERT_DIALOG_TITLE); 186} 187 188void SSLClientCertificateSelector::DeleteDelegate() { 189 DVLOG(1) << __FUNCTION__; 190 delete this; 191} 192 193bool SSLClientCertificateSelector::IsDialogButtonEnabled( 194 ui::DialogButton button) const { 195 if (button == ui::DIALOG_BUTTON_OK) 196 return !!GetSelectedCert(); 197 return true; 198} 199 200bool SSLClientCertificateSelector::Cancel() { 201 DVLOG(1) << __FUNCTION__; 202 StopObserving(); 203 CertificateSelected(NULL); 204 205 return true; 206} 207 208bool SSLClientCertificateSelector::Accept() { 209 DVLOG(1) << __FUNCTION__; 210 net::X509Certificate* cert = GetSelectedCert(); 211 if (cert) { 212 StopObserving(); 213 CertificateSelected(cert); 214 return true; 215 } 216 217 return false; 218} 219 220// TODO(wittman): Remove this override once we move to the new style frame view 221// on all dialogs. 222views::NonClientFrameView* 223 SSLClientCertificateSelector::CreateNonClientFrameView( 224 views::Widget* widget) { 225 return CreateConstrainedStyleNonClientFrameView( 226 widget, 227 web_contents_->GetBrowserContext()); 228} 229 230views::View* SSLClientCertificateSelector::GetInitiallyFocusedView() { 231 return table_; 232} 233 234views::View* SSLClientCertificateSelector::CreateExtraView() { 235 DCHECK(!view_cert_button_); 236 view_cert_button_ = new views::LabelButton(this, 237 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON)); 238 view_cert_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 239 return view_cert_button_; 240} 241 242ui::ModalType SSLClientCertificateSelector::GetModalType() const { 243#if defined(USE_ASH) 244 return ui::MODAL_TYPE_CHILD; 245#else 246 return views::WidgetDelegate::GetModalType(); 247#endif 248} 249 250/////////////////////////////////////////////////////////////////////////////// 251// views::ButtonListener implementation: 252 253void SSLClientCertificateSelector::ButtonPressed( 254 views::Button* sender, const ui::Event& event) { 255 if (sender == view_cert_button_) { 256 net::X509Certificate* cert = GetSelectedCert(); 257 if (cert) 258 ShowCertificateViewer(web_contents_, 259 web_contents_->GetView()->GetTopLevelNativeWindow(), 260 cert); 261 } 262} 263 264/////////////////////////////////////////////////////////////////////////////// 265// views::TableViewObserver implementation: 266void SSLClientCertificateSelector::OnSelectionChanged() { 267 GetDialogClientView()->ok_button()->SetEnabled(!!GetSelectedCert()); 268} 269 270void SSLClientCertificateSelector::OnDoubleClick() { 271 if (Accept()) 272 window_->Close(); 273} 274 275/////////////////////////////////////////////////////////////////////////////// 276// SSLClientCertificateSelector private methods: 277 278void SSLClientCertificateSelector::CreateCertTable() { 279 std::vector<ui::TableColumn> columns; 280 columns.push_back(ui::TableColumn()); 281 table_ = new views::TableView(model_.get(), 282 columns, 283 views::TEXT_ONLY, 284 true /* single_selection */); 285 table_->SetObserver(this); 286} 287 288namespace chrome { 289 290void ShowSSLClientCertificateSelector( 291 content::WebContents* contents, 292 const net::HttpNetworkSession* network_session, 293 net::SSLCertRequestInfo* cert_request_info, 294 const chrome::SelectCertificateCallback& callback) { 295 DVLOG(1) << __FUNCTION__ << " " << contents; 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 297 (new SSLClientCertificateSelector( 298 contents, network_session, cert_request_info, callback))->Init(); 299} 300 301} // namespace chrome 302