summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-10 00:15:35 +0000
committerdavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-10 00:15:35 +0000
commit95a8885c7470e8a4572fa672728ba948535f2da1 (patch)
treeaf36bdfef2dd30550b077258c36ebf45fd599aa1
parentdbec3790ae6053744920c3c85eab1bccd32b8016 (diff)
downloadchromium_src-95a8885c7470e8a4572fa672728ba948535f2da1.zip
chromium_src-95a8885c7470e8a4572fa672728ba948535f2da1.tar.gz
chromium_src-95a8885c7470e8a4572fa672728ba948535f2da1.tar.bz2
Make GTK certificate selection dialog a constrained window
This makes the dialog tab-modal. Implementation on OS X is forthcoming. Windows will be messier; we'll need to implement our own dialog, but we want that anyway because of the annoying blocking call. R=wtc,mattm TEST=none BUG=50710 Review URL: http://codereview.chromium.org/3077008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55509 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/cocoa/ssl_client_certificate_selector.mm6
-rw-r--r--chrome/browser/gtk/ssl_client_certificate_selector.cc190
-rw-r--r--chrome/browser/ssl_client_certificate_selector.h18
-rw-r--r--chrome/browser/tab_contents/tab_contents_ssl_helper.cc4
-rw-r--r--chrome/browser/views/ssl_client_certificate_selector_win.cc9
5 files changed, 139 insertions, 88 deletions
diff --git a/chrome/browser/cocoa/ssl_client_certificate_selector.mm b/chrome/browser/cocoa/ssl_client_certificate_selector.mm
index 4475bb9..82d9822 100644
--- a/chrome/browser/cocoa/ssl_client_certificate_selector.mm
+++ b/chrome/browser/cocoa/ssl_client_certificate_selector.mm
@@ -17,6 +17,7 @@
#include "base/sys_string_conversions.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/ssl/ssl_client_auth_handler.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
#include "grit/generated_resources.h"
#include "net/base/x509_certificate.h"
@@ -40,15 +41,16 @@
namespace browser {
void ShowSSLClientCertificateSelector(
- gfx::NativeWindow parent,
+ TabContents* parent,
net::SSLCertRequestInfo* cert_request_info,
SSLClientAuthHandler* delegate) {
+ // TODO(davidben): Implement a tab-modal dialog.
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
SSLClientCertificateSelectorCocoa* selector =
[[[SSLClientCertificateSelectorCocoa alloc]
initWithHandler:delegate
certRequestInfo:cert_request_info] autorelease];
- [selector displayDialog:parent];
+ [selector displayDialog:parent->GetMessageBoxRootWindow()];
}
} // namespace browser
diff --git a/chrome/browser/gtk/ssl_client_certificate_selector.cc b/chrome/browser/gtk/ssl_client_certificate_selector.cc
index b7c3f5f..987e51a 100644
--- a/chrome/browser/gtk/ssl_client_certificate_selector.cc
+++ b/chrome/browser/gtk/ssl_client_certificate_selector.cc
@@ -10,14 +10,18 @@
#include <string>
#include <vector>
+#include "app/gtk_signal.h"
#include "app/l10n_util.h"
#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/nss_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/certificate_viewer.h"
+#include "chrome/browser/gtk/constrained_window_gtk.h"
#include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/gtk/owned_widget_gtk.h"
#include "chrome/browser/ssl/ssl_client_auth_handler.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
#include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h"
#include "chrome/third_party/mozilla_security_manager/nsUsageArrayHelper.h"
@@ -34,68 +38,70 @@ enum {
RESPONSE_SHOW_CERT_INFO = 1,
};
-
///////////////////////////////////////////////////////////////////////////////
// SSLClientCertificateSelector
-class SSLClientCertificateSelector {
+class SSLClientCertificateSelector : public ConstrainedDialogDelegate {
public:
- SSLClientCertificateSelector(gfx::NativeWindow parent,
- net::SSLCertRequestInfo* cert_request_info,
- SSLClientAuthHandler* delegate);
+ explicit SSLClientCertificateSelector(
+ TabContents* parent,
+ net::SSLCertRequestInfo* cert_request_info,
+ SSLClientAuthHandler* delegate);
+ ~SSLClientCertificateSelector();
void Show();
+ // ConstrainedDialogDelegate implementation:
+ virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); }
+ virtual void DeleteDelegate() { delete this; }
+
private:
void PopulateCerts();
+ net::X509Certificate* GetSelectedCert();
+
static std::string FormatComboBoxText(CERTCertificate* cert,
const char* nickname);
static std::string FormatDetailsText(CERTCertificate* cert);
- static void OnComboBoxChanged(GtkComboBox* combo_box,
- SSLClientCertificateSelector* cert_selector);
- static void OnResponse(GtkDialog* dialog, gint response_id,
- SSLClientCertificateSelector* cert_selector);
- static void OnDestroy(GtkDialog* dialog,
- SSLClientCertificateSelector* cert_selector);
+ CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged);
+ CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked);
+ CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked);
+ CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked);
+ CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown,
+ GtkWidget*);
- scoped_refptr<SSLClientAuthHandler> delegate_;
scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
std::vector<std::string> details_strings_;
- GtkWidget* dialog_;
GtkWidget* cert_combo_box_;
GtkTextBuffer* cert_details_buffer_;
+
+ scoped_refptr<SSLClientAuthHandler> delegate_;
+
+ OwnedWidgetGtk root_widget_;
+ // Hold on to the select button to focus it.
+ GtkWidget* select_button_;
+
+ TabContents* parent_;
+ ConstrainedWindow* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLClientCertificateSelector);
};
SSLClientCertificateSelector::SSLClientCertificateSelector(
- gfx::NativeWindow parent,
+ TabContents* parent,
net::SSLCertRequestInfo* cert_request_info,
SSLClientAuthHandler* delegate)
- : delegate_(delegate),
- cert_request_info_(cert_request_info) {
- dialog_ = gtk_dialog_new_with_buttons(
- l10n_util::GetStringFUTF8(
- IDS_CERT_SELECTOR_DIALOG_TITLE,
- UTF8ToUTF16(cert_request_info->host_and_port)).c_str(),
- parent,
- // Non-modal.
- GTK_DIALOG_NO_SEPARATOR,
- l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str(),
- RESPONSE_SHOW_CERT_INFO,
- GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK,
- GTK_RESPONSE_OK,
- NULL);
- gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
- gtk_util::kContentAreaSpacing);
- gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
+ : cert_request_info_(cert_request_info),
+ delegate_(delegate),
+ parent_(parent),
+ window_(NULL) {
+ root_widget_.Own(gtk_vbox_new(FALSE, gtk_util::kControlSpacing));
GtkWidget* site_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), site_vbox,
+ gtk_box_pack_start(GTK_BOX(root_widget_.get()), site_vbox,
FALSE, FALSE, 0);
GtkWidget* site_description_label = gtk_util::CreateBoldLabel(
@@ -109,7 +115,7 @@ SSLClientCertificateSelector::SSLClientCertificateSelector(
gtk_box_pack_start(GTK_BOX(site_vbox), site_label, FALSE, FALSE, 0);
GtkWidget* selector_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), selector_vbox,
+ gtk_box_pack_start(GTK_BOX(root_widget_.get()), selector_vbox,
TRUE, TRUE, 0);
GtkWidget* choose_description_label = gtk_util::CreateBoldLabel(
@@ -119,8 +125,8 @@ SSLClientCertificateSelector::SSLClientCertificateSelector(
cert_combo_box_ = gtk_combo_box_new_text();
- g_signal_connect(cert_combo_box_, "changed", G_CALLBACK(OnComboBoxChanged),
- this);
+ g_signal_connect(cert_combo_box_, "changed",
+ G_CALLBACK(OnComboBoxChangedThunk), this);
gtk_box_pack_start(GTK_BOX(selector_vbox), cert_combo_box_,
FALSE, FALSE, 0);
@@ -144,14 +150,44 @@ SSLClientCertificateSelector::SSLClientCertificateSelector(
gtk_container_add(GTK_CONTAINER(details_frame), cert_details_view);
gtk_box_pack_start(GTK_BOX(selector_vbox), details_frame, TRUE, TRUE, 0);
+ // And then create a set of buttons like a GtkDialog would.
+ GtkWidget* button_box = gtk_hbutton_box_new();
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
+ gtk_box_pack_end(GTK_BOX(root_widget_.get()), button_box, FALSE, FALSE, 0);
+
+ GtkWidget* view_button = gtk_button_new_with_mnemonic(
+ l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
+ gtk_box_pack_start(GTK_BOX(button_box), view_button, FALSE, FALSE, 0);
+ g_signal_connect(view_button, "clicked",
+ G_CALLBACK(OnViewClickedThunk), this);
+
+ GtkWidget* cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_box_pack_end(GTK_BOX(button_box), cancel_button, FALSE, FALSE, 0);
+ g_signal_connect(cancel_button, "clicked",
+ G_CALLBACK(OnCancelClickedThunk), this);
+
+ GtkWidget* select_button = gtk_button_new_from_stock(GTK_STOCK_OK);
+ gtk_box_pack_end(GTK_BOX(button_box), select_button, FALSE, FALSE, 0);
+ g_signal_connect(select_button, "clicked",
+ G_CALLBACK(OnOkClickedThunk), this);
+
+ // When we are attached to a window, focus the select button.
+ select_button_ = select_button;
+ g_signal_connect(root_widget_.get(), "hierarchy-changed",
+ G_CALLBACK(OnPromptShownThunk), this);
PopulateCerts();
- g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
- g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroy), this);
+ gtk_widget_show_all(root_widget_.get());
+}
+
+SSLClientCertificateSelector::~SSLClientCertificateSelector() {
+ root_widget_.Destroy();
}
void SSLClientCertificateSelector::Show() {
- gtk_widget_show_all(dialog_);
+ DCHECK(!window_);
+ window_ = parent_->CreateConstrainedDialog(this);
}
void SSLClientCertificateSelector::PopulateCerts() {
@@ -192,6 +228,15 @@ void SSLClientCertificateSelector::PopulateCerts() {
gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0);
}
+net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() {
+ int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_));
+ if (selected >= 0 &&
+ selected < static_cast<int>(
+ cert_request_info_->client_certs.size()))
+ return cert_request_info_->client_certs[selected];
+ return NULL;
+}
+
// static
std::string SSLClientCertificateSelector::FormatComboBoxText(
CERTCertificate* cert, const char* nickname) {
@@ -278,46 +323,45 @@ std::string SSLClientCertificateSelector::FormatDetailsText(
return rv;
}
-// static
-void SSLClientCertificateSelector::OnComboBoxChanged(
- GtkComboBox* combo_box, SSLClientCertificateSelector* cert_selector) {
+void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) {
int selected = gtk_combo_box_get_active(
- GTK_COMBO_BOX(cert_selector->cert_combo_box_));
+ GTK_COMBO_BOX(cert_combo_box_));
if (selected < 0)
return;
- gtk_text_buffer_set_text(cert_selector->cert_details_buffer_,
- cert_selector->details_strings_[selected].c_str(),
- cert_selector->details_strings_[selected].size());
+ gtk_text_buffer_set_text(cert_details_buffer_,
+ details_strings_[selected].c_str(),
+ details_strings_[selected].size());
}
-// static
-void SSLClientCertificateSelector::OnResponse(
- GtkDialog* dialog, gint response_id,
- SSLClientCertificateSelector* cert_selector) {
- net::X509Certificate* cert = NULL;
- if (response_id == GTK_RESPONSE_OK ||
- response_id == RESPONSE_SHOW_CERT_INFO) {
- int selected = gtk_combo_box_get_active(
- GTK_COMBO_BOX(cert_selector->cert_combo_box_));
- if (selected >= 0 &&
- selected < static_cast<int>(
- cert_selector->cert_request_info_->client_certs.size()))
- cert = cert_selector->cert_request_info_->client_certs[selected];
+void SSLClientCertificateSelector::OnViewClicked(GtkWidget* button) {
+ net::X509Certificate* cert = GetSelectedCert();
+ if (cert) {
+ GtkWidget* toplevel = gtk_widget_get_toplevel(root_widget_.get());
+ ShowCertificateViewer(GTK_WINDOW(toplevel), cert);
}
- if (response_id == RESPONSE_SHOW_CERT_INFO) {
- if (cert)
- ShowCertificateViewer(GTK_WINDOW(cert_selector->dialog_), cert);
- return;
- }
- cert_selector->delegate_->CertificateSelected(cert);
- gtk_widget_destroy(GTK_WIDGET(dialog));
}
-// static
-void SSLClientCertificateSelector::OnDestroy(
- GtkDialog* dialog,
- SSLClientCertificateSelector* cert_selector) {
- delete cert_selector;
+void SSLClientCertificateSelector::OnCancelClicked(GtkWidget* button) {
+ delegate_->CertificateSelected(NULL);
+ DCHECK(window_);
+ window_->CloseConstrainedWindow();
+}
+
+void SSLClientCertificateSelector::OnOkClicked(GtkWidget* button) {
+ net::X509Certificate* cert = GetSelectedCert();
+ delegate_->CertificateSelected(cert);
+ DCHECK(window_);
+ window_->CloseConstrainedWindow();
+}
+
+void SSLClientCertificateSelector::OnPromptShown(GtkWidget* widget,
+ GtkWidget* previous_toplevel) {
+ if (!root_widget_.get() ||
+ !GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(root_widget_.get())))
+ return;
+ GTK_WIDGET_SET_FLAGS(select_button_, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(select_button_);
+ gtk_widget_grab_focus(select_button_);
}
} // namespace
@@ -328,7 +372,7 @@ void SSLClientCertificateSelector::OnDestroy(
namespace browser {
void ShowSSLClientCertificateSelector(
- gfx::NativeWindow parent,
+ TabContents* parent,
net::SSLCertRequestInfo* cert_request_info,
SSLClientAuthHandler* delegate) {
(new SSLClientCertificateSelector(parent,
diff --git a/chrome/browser/ssl_client_certificate_selector.h b/chrome/browser/ssl_client_certificate_selector.h
index 24b953e..3b5c6e9 100644
--- a/chrome/browser/ssl_client_certificate_selector.h
+++ b/chrome/browser/ssl_client_certificate_selector.h
@@ -6,9 +6,8 @@
#define CHROME_BROWSER_SSL_CLIENT_CERTIFICATE_SELECTOR_H_
#pragma once
-#include "gfx/native_widget_types.h"
-
class SSLClientAuthHandler;
+class TabContents;
namespace net {
class SSLCertRequestInfo;
@@ -16,13 +15,16 @@ class SSLCertRequestInfo;
namespace browser {
-// Opens an SSL client certificate selection dialog under |parent|, offering
-// certificates from |cert_request_info|. When the user has made a selection,
-// the dialog will report back to |delegate|. |delegate| is notified when the
-// dialog closes in call cases; if the user cancels the dialog, we call with a
-// NULL certificate.
+// Opens a constrained SSL client certificate selection dialog under |parent|,
+// offering certificates from |cert_request_info|. When the user has made a
+// selection, the dialog will report back to |delegate|. |delegate| is notified
+// when the dialog closes in call cases; if the user cancels the dialog, we call
+// with a NULL certificate.
+//
+// Note: constrained dialog currently only implemented on Linux. On other
+// platforms, a window-modal dialog will be used.
void ShowSSLClientCertificateSelector(
- gfx::NativeWindow parent,
+ TabContents* parent,
net::SSLCertRequestInfo* cert_request_info,
SSLClientAuthHandler* delegate);
diff --git a/chrome/browser/tab_contents/tab_contents_ssl_helper.cc b/chrome/browser/tab_contents/tab_contents_ssl_helper.cc
index 90041d9..db6d960 100644
--- a/chrome/browser/tab_contents/tab_contents_ssl_helper.cc
+++ b/chrome/browser/tab_contents/tab_contents_ssl_helper.cc
@@ -163,10 +163,8 @@ TabContentsSSLHelper::~TabContentsSSLHelper() {
void TabContentsSSLHelper::ShowClientCertificateRequestDialog(
scoped_refptr<SSLClientAuthHandler> handler) {
- // Display the native certificate request dialog for each platform.
browser::ShowSSLClientCertificateSelector(
- tab_contents_->GetMessageBoxRootWindow(),
- handler->cert_request_info(), handler);
+ tab_contents_, handler->cert_request_info(), handler);
}
void TabContentsSSLHelper::OnVerifyClientCertificateError(
diff --git a/chrome/browser/views/ssl_client_certificate_selector_win.cc b/chrome/browser/views/ssl_client_certificate_selector_win.cc
index 1ea9d8c..e3bc8e1 100644
--- a/chrome/browser/views/ssl_client_certificate_selector_win.cc
+++ b/chrome/browser/views/ssl_client_certificate_selector_win.cc
@@ -15,19 +15,23 @@
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/ssl/ssl_client_auth_handler.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
#include "grit/generated_resources.h"
#include "net/url_request/url_request.h"
namespace browser {
void ShowSSLClientCertificateSelector(
- gfx::NativeWindow parent,
+ TabContents* parent,
net::SSLCertRequestInfo* cert_request_info,
SSLClientAuthHandler* delegate) {
net::X509Certificate* cert = NULL;
// TODO(jcampan): replace this with our own cert selection dialog.
// CryptUIDlgSelectCertificateFromStore is blocking (but still processes
// Windows messages), which is scary.
+ //
+ // TODO(davidben): Make this dialog tab-modal to the
+ // TabContents. This depends on the above TODO.
HCERTSTORE client_certs = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL,
0, NULL);
BOOL ok;
@@ -43,7 +47,8 @@ void ShowSSLClientCertificateSelector(
IDS_CLIENT_CERT_DIALOG_TEXT,
ASCIIToWide(cert_request_info->host_and_port));
PCCERT_CONTEXT cert_context = CryptUIDlgSelectCertificateFromStore(
- client_certs, parent, title.c_str(), text.c_str(), 0, 0, NULL);
+ client_certs, parent->GetMessageBoxRootWindow(),
+ title.c_str(), text.c_str(), 0, 0, NULL);
if (cert_context) {
cert = net::X509Certificate::CreateFromHandle(