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