| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ssl_client_certificate_selector.h" | 5 #include "chrome/browser/ssl_client_certificate_selector.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/i18n/time_formatting.h" | 13 #include "base/i18n/time_formatting.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
| 16 #include "chrome/browser/certificate_viewer.h" | 16 #include "chrome/browser/certificate_viewer.h" |
| 17 #include "chrome/browser/ssl/ssl_client_auth_observer.h" |
| 17 #include "chrome/browser/ui/crypto_module_password_dialog.h" | 18 #include "chrome/browser/ui/crypto_module_password_dialog.h" |
| 18 #include "chrome/browser/ui/gtk/constrained_window_gtk.h" | 19 #include "chrome/browser/ui/gtk/constrained_window_gtk.h" |
| 19 #include "chrome/browser/ui/gtk/gtk_util.h" | 20 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 20 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 21 #include "chrome/common/net/x509_certificate_model.h" | 22 #include "chrome/common/net/x509_certificate_model.h" |
| 22 #include "content/browser/ssl/ssl_client_auth_handler.h" | |
| 23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
| 25 #include "net/base/ssl_cert_request_info.h" |
| 25 #include "net/base/x509_certificate.h" | 26 #include "net/base/x509_certificate.h" |
| 26 #include "ui/base/gtk/gtk_compat.h" | 27 #include "ui/base/gtk/gtk_compat.h" |
| 27 #include "ui/base/gtk/gtk_hig_constants.h" | 28 #include "ui/base/gtk/gtk_hig_constants.h" |
| 28 #include "ui/base/gtk/gtk_signal.h" | 29 #include "ui/base/gtk/gtk_signal.h" |
| 29 #include "ui/base/gtk/owned_widget_gtk.h" | 30 #include "ui/base/gtk/owned_widget_gtk.h" |
| 30 #include "ui/base/l10n/l10n_util.h" | 31 #include "ui/base/l10n/l10n_util.h" |
| 31 #include "ui/gfx/native_widget_types.h" | 32 #include "ui/gfx/native_widget_types.h" |
| 32 | 33 |
| 33 using content::BrowserThread; | 34 using content::BrowserThread; |
| 34 | 35 |
| 35 namespace { | 36 namespace { |
| 36 | 37 |
| 37 enum { | 38 enum { |
| 38 RESPONSE_SHOW_CERT_INFO = 1, | 39 RESPONSE_SHOW_CERT_INFO = 1, |
| 39 }; | 40 }; |
| 40 | 41 |
| 41 /////////////////////////////////////////////////////////////////////////////// | 42 /////////////////////////////////////////////////////////////////////////////// |
| 42 // SSLClientCertificateSelector | 43 // SSLClientCertificateSelector |
| 43 | 44 |
| 44 class SSLClientCertificateSelector : public SSLClientAuthObserver, | 45 class SSLClientCertificateSelector : public SSLClientAuthObserver, |
| 45 public ConstrainedWindowGtkDelegate { | 46 public ConstrainedWindowGtkDelegate { |
| 46 public: | 47 public: |
| 47 explicit SSLClientCertificateSelector( | 48 explicit SSLClientCertificateSelector( |
| 48 TabContentsWrapper* parent, | 49 TabContentsWrapper* parent, |
| 50 const net::HttpNetworkSession* network_session, |
| 49 net::SSLCertRequestInfo* cert_request_info, | 51 net::SSLCertRequestInfo* cert_request_info, |
| 50 SSLClientAuthHandler* delegate); | 52 const base::Callback<void(net::X509Certificate*)>& callback); |
| 51 ~SSLClientCertificateSelector(); | 53 ~SSLClientCertificateSelector(); |
| 52 | 54 |
| 53 void Show(); | 55 void Show(); |
| 54 | 56 |
| 55 // SSLClientAuthObserver implementation: | 57 // SSLClientAuthObserver implementation: |
| 56 virtual void OnCertSelectedByNotification(); | 58 virtual void OnCertSelectedByNotification(); |
| 57 | 59 |
| 58 // ConstrainedWindowGtkDelegate implementation: | 60 // ConstrainedWindowGtkDelegate implementation: |
| 59 virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); } | 61 virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); } |
| 60 virtual GtkWidget* GetFocusWidget(); | 62 virtual GtkWidget* GetFocusWidget(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 74 // Callback after unlocking certificate slot. | 76 // Callback after unlocking certificate slot. |
| 75 void Unlocked(); | 77 void Unlocked(); |
| 76 | 78 |
| 77 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged); | 79 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged); |
| 78 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked); | 80 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked); |
| 79 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked); | 81 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked); |
| 80 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked); | 82 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked); |
| 81 CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown, | 83 CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown, |
| 82 GtkWidget*); | 84 GtkWidget*); |
| 83 | 85 |
| 84 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_; | |
| 85 | |
| 86 std::vector<std::string> details_strings_; | 86 std::vector<std::string> details_strings_; |
| 87 | 87 |
| 88 GtkWidget* cert_combo_box_; | 88 GtkWidget* cert_combo_box_; |
| 89 GtkTextBuffer* cert_details_buffer_; | 89 GtkTextBuffer* cert_details_buffer_; |
| 90 | 90 |
| 91 scoped_refptr<SSLClientAuthHandler> delegate_; | |
| 92 | |
| 93 ui::OwnedWidgetGtk root_widget_; | 91 ui::OwnedWidgetGtk root_widget_; |
| 94 // Hold on to the select button to focus it. | 92 // Hold on to the select button to focus it. |
| 95 GtkWidget* select_button_; | 93 GtkWidget* select_button_; |
| 96 | 94 |
| 97 TabContentsWrapper* wrapper_; | 95 TabContentsWrapper* wrapper_; |
| 98 ConstrainedWindow* window_; | 96 ConstrainedWindow* window_; |
| 99 | 97 |
| 100 DISALLOW_COPY_AND_ASSIGN(SSLClientCertificateSelector); | 98 DISALLOW_COPY_AND_ASSIGN(SSLClientCertificateSelector); |
| 101 }; | 99 }; |
| 102 | 100 |
| 103 SSLClientCertificateSelector::SSLClientCertificateSelector( | 101 SSLClientCertificateSelector::SSLClientCertificateSelector( |
| 104 TabContentsWrapper* wrapper, | 102 TabContentsWrapper* wrapper, |
| 103 const net::HttpNetworkSession* network_session, |
| 105 net::SSLCertRequestInfo* cert_request_info, | 104 net::SSLCertRequestInfo* cert_request_info, |
| 106 SSLClientAuthHandler* delegate) | 105 const base::Callback<void(net::X509Certificate*)>& callback) |
| 107 : SSLClientAuthObserver(cert_request_info, delegate), | 106 : SSLClientAuthObserver(network_session, cert_request_info, callback), |
| 108 cert_request_info_(cert_request_info), | |
| 109 delegate_(delegate), | |
| 110 wrapper_(wrapper), | 107 wrapper_(wrapper), |
| 111 window_(NULL) { | 108 window_(NULL) { |
| 112 root_widget_.Own(gtk_vbox_new(FALSE, ui::kControlSpacing)); | 109 root_widget_.Own(gtk_vbox_new(FALSE, ui::kControlSpacing)); |
| 113 | 110 |
| 114 GtkWidget* site_vbox = gtk_vbox_new(FALSE, ui::kControlSpacing); | 111 GtkWidget* site_vbox = gtk_vbox_new(FALSE, ui::kControlSpacing); |
| 115 gtk_box_pack_start(GTK_BOX(root_widget_.get()), site_vbox, | 112 gtk_box_pack_start(GTK_BOX(root_widget_.get()), site_vbox, |
| 116 FALSE, FALSE, 0); | 113 FALSE, FALSE, 0); |
| 117 | 114 |
| 118 GtkWidget* site_description_label = gtk_util::CreateBoldLabel( | 115 GtkWidget* site_description_label = gtk_util::CreateBoldLabel( |
| 119 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_SITE_DESCRIPTION_LABEL)); | 116 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_SITE_DESCRIPTION_LABEL)); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 SSLClientCertificateSelector::~SSLClientCertificateSelector() { | 194 SSLClientCertificateSelector::~SSLClientCertificateSelector() { |
| 198 root_widget_.Destroy(); | 195 root_widget_.Destroy(); |
| 199 } | 196 } |
| 200 | 197 |
| 201 void SSLClientCertificateSelector::Show() { | 198 void SSLClientCertificateSelector::Show() { |
| 202 DCHECK(!window_); | 199 DCHECK(!window_); |
| 203 window_ = new ConstrainedWindowGtk(wrapper_, this); | 200 window_ = new ConstrainedWindowGtk(wrapper_, this); |
| 204 } | 201 } |
| 205 | 202 |
| 206 void SSLClientCertificateSelector::OnCertSelectedByNotification() { | 203 void SSLClientCertificateSelector::OnCertSelectedByNotification() { |
| 207 delegate_ = NULL; | |
| 208 DCHECK(window_); | 204 DCHECK(window_); |
| 209 window_->CloseConstrainedWindow(); | 205 window_->CloseConstrainedWindow(); |
| 210 } | 206 } |
| 211 | 207 |
| 212 GtkWidget* SSLClientCertificateSelector::GetFocusWidget() { | 208 GtkWidget* SSLClientCertificateSelector::GetFocusWidget() { |
| 213 return select_button_; | 209 return select_button_; |
| 214 } | 210 } |
| 215 | 211 |
| 216 void SSLClientCertificateSelector::DeleteDelegate() { | 212 void SSLClientCertificateSelector::DeleteDelegate() { |
| 217 if (delegate_) { | 213 // The dialog was closed by escape key. |
| 218 // The dialog was closed by escape key. | 214 StopObserving(); |
| 219 StopObserving(); | 215 CertificateSelected(NULL); |
| 220 delegate_->CertificateSelected(NULL); | |
| 221 } | |
| 222 delete this; | 216 delete this; |
| 223 } | 217 } |
| 224 | 218 |
| 225 void SSLClientCertificateSelector::PopulateCerts() { | 219 void SSLClientCertificateSelector::PopulateCerts() { |
| 226 std::vector<std::string> nicknames; | 220 std::vector<std::string> nicknames; |
| 227 x509_certificate_model::GetNicknameStringsFromCertList( | 221 x509_certificate_model::GetNicknameStringsFromCertList( |
| 228 cert_request_info_->client_certs, | 222 cert_request_info()->client_certs, |
| 229 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_EXPIRED), | 223 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_EXPIRED), |
| 230 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_NOT_YET_VALID), | 224 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_NOT_YET_VALID), |
| 231 &nicknames); | 225 &nicknames); |
| 232 | 226 |
| 233 DCHECK_EQ(nicknames.size(), | 227 DCHECK_EQ(nicknames.size(), |
| 234 cert_request_info_->client_certs.size()); | 228 cert_request_info()->client_certs.size()); |
| 235 | 229 |
| 236 for (size_t i = 0; i < cert_request_info_->client_certs.size(); ++i) { | 230 for (size_t i = 0; i < cert_request_info()->client_certs.size(); ++i) { |
| 237 net::X509Certificate::OSCertHandle cert = | 231 net::X509Certificate::OSCertHandle cert = |
| 238 cert_request_info_->client_certs[i]->os_cert_handle(); | 232 cert_request_info()->client_certs[i]->os_cert_handle(); |
| 239 | 233 |
| 240 details_strings_.push_back(FormatDetailsText(cert)); | 234 details_strings_.push_back(FormatDetailsText(cert)); |
| 241 | 235 |
| 242 gtk_combo_box_append_text( | 236 gtk_combo_box_append_text( |
| 243 GTK_COMBO_BOX(cert_combo_box_), | 237 GTK_COMBO_BOX(cert_combo_box_), |
| 244 FormatComboBoxText(cert, nicknames[i]).c_str()); | 238 FormatComboBoxText(cert, nicknames[i]).c_str()); |
| 245 } | 239 } |
| 246 | 240 |
| 247 // Auto-select the first cert. | 241 // Auto-select the first cert. |
| 248 gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0); | 242 gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0); |
| 249 } | 243 } |
| 250 | 244 |
| 251 net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() { | 245 net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() { |
| 252 int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_)); | 246 int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_)); |
| 253 if (selected >= 0 && | 247 if (selected >= 0 && |
| 254 selected < static_cast<int>( | 248 selected < static_cast<int>( |
| 255 cert_request_info_->client_certs.size())) | 249 cert_request_info()->client_certs.size())) |
| 256 return cert_request_info_->client_certs[selected]; | 250 return cert_request_info()->client_certs[selected]; |
| 257 return NULL; | 251 return NULL; |
| 258 } | 252 } |
| 259 | 253 |
| 260 // static | 254 // static |
| 261 std::string SSLClientCertificateSelector::FormatComboBoxText( | 255 std::string SSLClientCertificateSelector::FormatComboBoxText( |
| 262 net::X509Certificate::OSCertHandle cert, const std::string& nickname) { | 256 net::X509Certificate::OSCertHandle cert, const std::string& nickname) { |
| 263 std::string rv(nickname); | 257 std::string rv(nickname); |
| 264 rv += " ["; | 258 rv += " ["; |
| 265 rv += x509_certificate_model::GetSerialNumberHexified(cert, ""); | 259 rv += x509_certificate_model::GetSerialNumberHexified(cert, ""); |
| 266 rv += ']'; | 260 rv += ']'; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 rv += '\n'; | 319 rv += '\n'; |
| 326 rv += l10n_util::GetStringFUTF8(IDS_CERT_TOKEN_FORMAT, token); | 320 rv += l10n_util::GetStringFUTF8(IDS_CERT_TOKEN_FORMAT, token); |
| 327 } | 321 } |
| 328 | 322 |
| 329 return rv; | 323 return rv; |
| 330 } | 324 } |
| 331 | 325 |
| 332 void SSLClientCertificateSelector::Unlocked() { | 326 void SSLClientCertificateSelector::Unlocked() { |
| 333 // TODO(mattm): refactor so we don't need to call GetSelectedCert again. | 327 // TODO(mattm): refactor so we don't need to call GetSelectedCert again. |
| 334 net::X509Certificate* cert = GetSelectedCert(); | 328 net::X509Certificate* cert = GetSelectedCert(); |
| 335 delegate_->CertificateSelected(cert); | 329 CertificateSelected(cert); |
| 336 delegate_ = NULL; | |
| 337 DCHECK(window_); | 330 DCHECK(window_); |
| 338 window_->CloseConstrainedWindow(); | 331 window_->CloseConstrainedWindow(); |
| 339 } | 332 } |
| 340 | 333 |
| 341 void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) { | 334 void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) { |
| 342 int selected = gtk_combo_box_get_active( | 335 int selected = gtk_combo_box_get_active( |
| 343 GTK_COMBO_BOX(cert_combo_box_)); | 336 GTK_COMBO_BOX(cert_combo_box_)); |
| 344 if (selected < 0) | 337 if (selected < 0) |
| 345 return; | 338 return; |
| 346 gtk_text_buffer_set_text(cert_details_buffer_, | 339 gtk_text_buffer_set_text(cert_details_buffer_, |
| 347 details_strings_[selected].c_str(), | 340 details_strings_[selected].c_str(), |
| 348 details_strings_[selected].size()); | 341 details_strings_[selected].size()); |
| 349 } | 342 } |
| 350 | 343 |
| 351 void SSLClientCertificateSelector::OnViewClicked(GtkWidget* button) { | 344 void SSLClientCertificateSelector::OnViewClicked(GtkWidget* button) { |
| 352 net::X509Certificate* cert = GetSelectedCert(); | 345 net::X509Certificate* cert = GetSelectedCert(); |
| 353 if (cert) { | 346 if (cert) { |
| 354 GtkWidget* toplevel = gtk_widget_get_toplevel(root_widget_.get()); | 347 GtkWidget* toplevel = gtk_widget_get_toplevel(root_widget_.get()); |
| 355 ShowCertificateViewer(GTK_WINDOW(toplevel), cert); | 348 ShowCertificateViewer(GTK_WINDOW(toplevel), cert); |
| 356 } | 349 } |
| 357 } | 350 } |
| 358 | 351 |
| 359 void SSLClientCertificateSelector::OnCancelClicked(GtkWidget* button) { | 352 void SSLClientCertificateSelector::OnCancelClicked(GtkWidget* button) { |
| 360 StopObserving(); | 353 CertificateSelected(NULL); |
| 361 delegate_->CertificateSelected(NULL); | |
| 362 delegate_ = NULL; | |
| 363 DCHECK(window_); | 354 DCHECK(window_); |
| 364 window_->CloseConstrainedWindow(); | 355 window_->CloseConstrainedWindow(); |
| 365 } | 356 } |
| 366 | 357 |
| 367 void SSLClientCertificateSelector::OnOkClicked(GtkWidget* button) { | 358 void SSLClientCertificateSelector::OnOkClicked(GtkWidget* button) { |
| 368 net::X509Certificate* cert = GetSelectedCert(); | 359 net::X509Certificate* cert = GetSelectedCert(); |
| 369 | 360 |
| 370 // Remove the observer before we try unlocking, otherwise we might act on a | 361 // Remove the observer before we try unlocking, otherwise we might act on a |
| 371 // notification while waiting for the unlock dialog, causing us to delete | 362 // notification while waiting for the unlock dialog, causing us to delete |
| 372 // ourself before the Unlocked callback gets called. | 363 // ourself before the Unlocked callback gets called. |
| 373 StopObserving(); | 364 StopObserving(); |
| 374 | 365 |
| 375 browser::UnlockCertSlotIfNecessary( | 366 browser::UnlockCertSlotIfNecessary( |
| 376 cert, | 367 cert, |
| 377 browser::kCryptoModulePasswordClientAuth, | 368 browser::kCryptoModulePasswordClientAuth, |
| 378 cert_request_info_->host_and_port, | 369 cert_request_info()->host_and_port, |
| 379 base::Bind(&SSLClientCertificateSelector::Unlocked, | 370 base::Bind(&SSLClientCertificateSelector::Unlocked, |
| 380 base::Unretained(this))); | 371 base::Unretained(this))); |
| 381 } | 372 } |
| 382 | 373 |
| 383 void SSLClientCertificateSelector::OnPromptShown(GtkWidget* widget, | 374 void SSLClientCertificateSelector::OnPromptShown(GtkWidget* widget, |
| 384 GtkWidget* previous_toplevel) { | 375 GtkWidget* previous_toplevel) { |
| 385 if (!root_widget_.get() || | 376 if (!root_widget_.get() || |
| 386 !gtk_widget_is_toplevel(gtk_widget_get_toplevel(root_widget_.get()))) | 377 !gtk_widget_is_toplevel(gtk_widget_get_toplevel(root_widget_.get()))) |
| 387 return; | 378 return; |
| 388 gtk_widget_set_can_default(select_button_, TRUE); | 379 gtk_widget_set_can_default(select_button_, TRUE); |
| 389 gtk_widget_grab_default(select_button_); | 380 gtk_widget_grab_default(select_button_); |
| 390 } | 381 } |
| 391 | 382 |
| 392 } // namespace | 383 } // namespace |
| 393 | 384 |
| 394 /////////////////////////////////////////////////////////////////////////////// | 385 /////////////////////////////////////////////////////////////////////////////// |
| 395 // SSLClientAuthHandler platform specific implementation: | 386 // SSLClientAuthHandler platform specific implementation: |
| 396 | 387 |
| 397 namespace browser { | 388 namespace browser { |
| 398 | 389 |
| 399 void ShowNativeSSLClientCertificateSelector( | 390 void ShowNativeSSLClientCertificateSelector( |
| 400 TabContentsWrapper* wrapper, | 391 TabContentsWrapper* wrapper, |
| 392 const net::HttpNetworkSession* network_session, |
| 401 net::SSLCertRequestInfo* cert_request_info, | 393 net::SSLCertRequestInfo* cert_request_info, |
| 402 SSLClientAuthHandler* delegate) { | 394 const base::Callback<void(net::X509Certificate*)>& callback) { |
| 403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 404 (new SSLClientCertificateSelector(wrapper, | 396 (new SSLClientCertificateSelector( |
| 405 cert_request_info, | 397 wrapper, network_session, cert_request_info, callback))->Show(); |
| 406 delegate))->Show(); | |
| 407 } | 398 } |
| 408 | 399 |
| 409 } // namespace browser | 400 } // namespace browser |
| OLD | NEW |