Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / views / ssl_client_certificate_selector.cc
blob2e105e199f4c55d5df3a016b333de8b580f2d076
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.
5 #include "chrome/browser/ui/views/ssl_client_certificate_selector.h"
7 #include "base/compiler_specific.h"
8 #include "base/i18n/time_formatting.h"
9 #include "base/logging.h"
10 #include "base/strings/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_host.h"
14 #include "components/web_modal/web_contents_modal_dialog_manager.h"
15 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_contents_view.h"
19 #include "grit/generated_resources.h"
20 #include "net/cert/x509_certificate.h"
21 #include "net/ssl/ssl_cert_request_info.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/models/table_model.h"
24 #include "ui/base/models/table_model_observer.h"
25 #include "ui/gfx/native_widget_types.h"
26 #include "ui/views/controls/button/label_button.h"
27 #include "ui/views/controls/label.h"
28 #include "ui/views/controls/table/table_view.h"
29 #include "ui/views/layout/grid_layout.h"
30 #include "ui/views/layout/layout_constants.h"
31 #include "ui/views/widget/widget.h"
32 #include "ui/views/window/dialog_client_view.h"
34 #if defined(USE_NSS)
35 #include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
36 #endif
38 using content::BrowserThread;
39 using content::WebContents;
40 using web_modal::WebContentsModalDialogManager;
41 using web_modal::WebContentsModalDialogManagerDelegate;
43 namespace {
45 // The dimensions of the certificate selector table view, in pixels.
46 static const int kTableViewWidth = 400;
47 static const int kTableViewHeight = 100;
49 } // namespace
51 ///////////////////////////////////////////////////////////////////////////////
52 // CertificateSelectorTableModel:
54 class CertificateSelectorTableModel : public ui::TableModel {
55 public:
56 explicit CertificateSelectorTableModel(
57 net::SSLCertRequestInfo* cert_request_info);
59 // ui::TableModel implementation:
60 virtual int RowCount() OVERRIDE;
61 virtual base::string16 GetText(int index, int column_id) OVERRIDE;
62 virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
64 private:
65 std::vector<base::string16> items_;
67 DISALLOW_COPY_AND_ASSIGN(CertificateSelectorTableModel);
70 CertificateSelectorTableModel::CertificateSelectorTableModel(
71 net::SSLCertRequestInfo* cert_request_info) {
72 for (size_t i = 0; i < cert_request_info->client_certs.size(); ++i) {
73 net::X509Certificate* cert = cert_request_info->client_certs[i].get();
74 base::string16 text = l10n_util::GetStringFUTF16(
75 IDS_CERT_SELECTOR_TABLE_CERT_FORMAT,
76 base::UTF8ToUTF16(cert->subject().GetDisplayName()),
77 base::UTF8ToUTF16(cert->issuer().GetDisplayName()));
78 items_.push_back(text);
82 int CertificateSelectorTableModel::RowCount() {
83 return items_.size();
86 base::string16 CertificateSelectorTableModel::GetText(int index,
87 int column_id) {
88 DCHECK_EQ(column_id, 0);
89 DCHECK_GE(index, 0);
90 DCHECK_LT(index, static_cast<int>(items_.size()));
92 return items_[index];
95 void CertificateSelectorTableModel::SetObserver(
96 ui::TableModelObserver* observer) {
99 ///////////////////////////////////////////////////////////////////////////////
100 // SSLClientCertificateSelector:
102 SSLClientCertificateSelector::SSLClientCertificateSelector(
103 WebContents* web_contents,
104 const net::HttpNetworkSession* network_session,
105 net::SSLCertRequestInfo* cert_request_info,
106 const chrome::SelectCertificateCallback& callback)
107 : SSLClientAuthObserver(network_session, cert_request_info, callback),
108 model_(new CertificateSelectorTableModel(cert_request_info)),
109 web_contents_(web_contents),
110 window_(NULL),
111 table_(NULL),
112 view_cert_button_(NULL) {
113 DVLOG(1) << __FUNCTION__;
116 SSLClientCertificateSelector::~SSLClientCertificateSelector() {
117 table_->SetModel(NULL);
120 void SSLClientCertificateSelector::Init() {
121 views::GridLayout* layout = views::GridLayout::CreatePanel(this);
122 SetLayoutManager(layout);
124 const int column_set_id = 0;
125 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
126 column_set->AddColumn(
127 views::GridLayout::FILL, views::GridLayout::FILL,
128 1, views::GridLayout::USE_PREF, 0, 0);
130 layout->StartRow(0, column_set_id);
131 base::string16 text = l10n_util::GetStringFUTF16(
132 IDS_CLIENT_CERT_DIALOG_TEXT,
133 base::ASCIIToUTF16(cert_request_info()->host_and_port.ToString()));
134 views::Label* label = new views::Label(text);
135 label->SetMultiLine(true);
136 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
137 label->SetAllowCharacterBreak(true);
138 layout->AddView(label);
140 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
142 CreateCertTable();
143 layout->StartRow(1, column_set_id);
144 layout->AddView(table_->CreateParentIfNecessary(), 1, 1,
145 views::GridLayout::FILL,
146 views::GridLayout::FILL, kTableViewWidth, kTableViewHeight);
148 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
150 StartObserving();
152 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
153 WebContentsModalDialogManager::FromWebContents(web_contents_);
154 WebContentsModalDialogManagerDelegate* modal_delegate =
155 web_contents_modal_dialog_manager->delegate();
156 DCHECK(modal_delegate);
157 window_ = views::Widget::CreateWindowAsFramelessChild(
158 this, modal_delegate->GetWebContentsModalDialogHost()->GetHostView());
159 web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView());
161 // Select the first row automatically. This must be done after the dialog has
162 // been created.
163 table_->Select(0);
166 net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() const {
167 int selected = table_->FirstSelectedRow();
168 if (selected >= 0 &&
169 selected < static_cast<int>(
170 cert_request_info()->client_certs.size()))
171 return cert_request_info()->client_certs[selected].get();
172 return NULL;
175 ///////////////////////////////////////////////////////////////////////////////
176 // SSLClientAuthObserver implementation:
178 void SSLClientCertificateSelector::OnCertSelectedByNotification() {
179 DVLOG(1) << __FUNCTION__;
180 DCHECK(window_);
181 window_->Close();
184 ///////////////////////////////////////////////////////////////////////////////
185 // DialogDelegateView implementation:
187 bool SSLClientCertificateSelector::CanResize() const {
188 return true;
191 base::string16 SSLClientCertificateSelector::GetWindowTitle() const {
192 return l10n_util::GetStringUTF16(IDS_CLIENT_CERT_DIALOG_TITLE);
195 void SSLClientCertificateSelector::DeleteDelegate() {
196 DVLOG(1) << __FUNCTION__;
197 delete this;
200 bool SSLClientCertificateSelector::IsDialogButtonEnabled(
201 ui::DialogButton button) const {
202 if (button == ui::DIALOG_BUTTON_OK)
203 return !!GetSelectedCert();
204 return true;
207 bool SSLClientCertificateSelector::Cancel() {
208 DVLOG(1) << __FUNCTION__;
209 StopObserving();
210 CertificateSelected(NULL);
212 return true;
215 bool SSLClientCertificateSelector::Accept() {
216 DVLOG(1) << __FUNCTION__;
217 scoped_refptr<net::X509Certificate> cert = GetSelectedCert();
218 if (cert) {
219 // Remove the observer before we try unlocking, otherwise we might act on a
220 // notification while waiting for the unlock dialog, causing us to delete
221 // ourself before the Unlocked callback gets called.
222 StopObserving();
223 #if defined(USE_NSS)
224 chrome::UnlockCertSlotIfNecessary(
225 cert,
226 chrome::kCryptoModulePasswordClientAuth,
227 cert_request_info()->host_and_port,
228 window_->GetNativeView(),
229 base::Bind(&SSLClientCertificateSelector::Unlocked,
230 base::Unretained(this),
231 cert));
232 #else
233 Unlocked(cert);
234 #endif
235 return false; // Unlocked() will close the dialog.
238 return false;
241 // TODO(wittman): Remove this override once we move to the new style frame view
242 // on all dialogs.
243 views::NonClientFrameView*
244 SSLClientCertificateSelector::CreateNonClientFrameView(
245 views::Widget* widget) {
246 return CreateConstrainedStyleNonClientFrameView(
247 widget,
248 web_contents_->GetBrowserContext());
251 views::View* SSLClientCertificateSelector::GetInitiallyFocusedView() {
252 return table_;
255 views::View* SSLClientCertificateSelector::CreateExtraView() {
256 DCHECK(!view_cert_button_);
257 view_cert_button_ = new views::LabelButton(this,
258 l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
259 view_cert_button_->SetStyle(views::Button::STYLE_BUTTON);
260 return view_cert_button_;
263 ui::ModalType SSLClientCertificateSelector::GetModalType() const {
264 #if defined(USE_ASH)
265 return ui::MODAL_TYPE_CHILD;
266 #else
267 return views::WidgetDelegate::GetModalType();
268 #endif
271 ///////////////////////////////////////////////////////////////////////////////
272 // views::ButtonListener implementation:
274 void SSLClientCertificateSelector::ButtonPressed(
275 views::Button* sender, const ui::Event& event) {
276 if (sender == view_cert_button_) {
277 net::X509Certificate* cert = GetSelectedCert();
278 if (cert)
279 ShowCertificateViewer(web_contents_,
280 web_contents_->GetView()->GetTopLevelNativeWindow(),
281 cert);
285 ///////////////////////////////////////////////////////////////////////////////
286 // views::TableViewObserver implementation:
287 void SSLClientCertificateSelector::OnSelectionChanged() {
288 GetDialogClientView()->ok_button()->SetEnabled(!!GetSelectedCert());
291 void SSLClientCertificateSelector::OnDoubleClick() {
292 if (Accept())
293 window_->Close();
296 ///////////////////////////////////////////////////////////////////////////////
297 // SSLClientCertificateSelector private methods:
299 void SSLClientCertificateSelector::CreateCertTable() {
300 std::vector<ui::TableColumn> columns;
301 columns.push_back(ui::TableColumn());
302 table_ = new views::TableView(model_.get(),
303 columns,
304 views::TEXT_ONLY,
305 true /* single_selection */);
306 table_->SetObserver(this);
309 void SSLClientCertificateSelector::Unlocked(net::X509Certificate* cert) {
310 DVLOG(1) << __FUNCTION__;
311 CertificateSelected(cert);
312 window_->Close();
315 namespace chrome {
317 void ShowSSLClientCertificateSelector(
318 content::WebContents* contents,
319 const net::HttpNetworkSession* network_session,
320 net::SSLCertRequestInfo* cert_request_info,
321 const chrome::SelectCertificateCallback& callback) {
322 DVLOG(1) << __FUNCTION__ << " " << contents;
323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
324 (new SSLClientCertificateSelector(
325 contents, network_session, cert_request_info, callback))->Init();
328 } // namespace chrome