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