Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: chrome/browser/ui/views/certificate_selector.cc

Issue 2898573002: Refactor client cert private key handling. (Closed)
Patch Set: review changes for comment 93 Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 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/certificate_selector.h" 5 #include "chrome/browser/ui/views/certificate_selector.h"
6 6
7 #include <stddef.h> // For size_t. 7 #include <stddef.h> // For size_t.
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 27 matching lines...) Expand all
38 #include "extensions/browser/extension_registry_factory.h" 38 #include "extensions/browser/extension_registry_factory.h"
39 #endif 39 #endif
40 40
41 namespace chrome { 41 namespace chrome {
42 42
43 const int CertificateSelector::kTableViewWidth = 500; 43 const int CertificateSelector::kTableViewWidth = 500;
44 const int CertificateSelector::kTableViewHeight = 150; 44 const int CertificateSelector::kTableViewHeight = 150;
45 45
46 class CertificateSelector::CertificateTableModel : public ui::TableModel { 46 class CertificateSelector::CertificateTableModel : public ui::TableModel {
47 public: 47 public:
48 // |certs| and |provider_names| must have the same size. 48 // |identities| and |provider_names| must have the same size.
49 CertificateTableModel(const net::CertificateList& certs, 49 CertificateTableModel(const net::ClientCertIdentityList& identities,
50 const std::vector<std::string>& provider_names); 50 const std::vector<std::string>& provider_names);
51 51
52 // ui::TableModel: 52 // ui::TableModel:
53 int RowCount() override; 53 int RowCount() override;
54 base::string16 GetText(int index, int column_id) override; 54 base::string16 GetText(int index, int column_id) override;
55 void SetObserver(ui::TableModelObserver* observer) override; 55 void SetObserver(ui::TableModelObserver* observer) override;
56 56
57 private: 57 private:
58 struct Row { 58 struct Row {
59 base::string16 subject; 59 base::string16 subject;
60 base::string16 issuer; 60 base::string16 issuer;
61 base::string16 provider; 61 base::string16 provider;
62 base::string16 serial; 62 base::string16 serial;
63 }; 63 };
64 std::vector<Row> rows_; 64 std::vector<Row> rows_;
65 65
66 DISALLOW_COPY_AND_ASSIGN(CertificateTableModel); 66 DISALLOW_COPY_AND_ASSIGN(CertificateTableModel);
67 }; 67 };
68 68
69 CertificateSelector::CertificateTableModel::CertificateTableModel( 69 CertificateSelector::CertificateTableModel::CertificateTableModel(
70 const net::CertificateList& certs, 70 const net::ClientCertIdentityList& identities,
71 const std::vector<std::string>& provider_names) { 71 const std::vector<std::string>& provider_names) {
72 DCHECK_EQ(certs.size(), provider_names.size()); 72 DCHECK_EQ(identities.size(), provider_names.size());
73 for (size_t i = 0; i < certs.size(); i++) { 73 for (size_t i = 0; i < identities.size(); i++) {
74 net::X509Certificate* cert = certs[i].get(); 74 net::X509Certificate* cert = identities[i]->certificate();
75 Row row; 75 Row row;
76 row.subject = base::UTF8ToUTF16(cert->subject().GetDisplayName()); 76 row.subject = base::UTF8ToUTF16(cert->subject().GetDisplayName());
77 row.issuer = base::UTF8ToUTF16(cert->issuer().GetDisplayName()); 77 row.issuer = base::UTF8ToUTF16(cert->issuer().GetDisplayName());
78 row.provider = base::UTF8ToUTF16(provider_names[i]); 78 row.provider = base::UTF8ToUTF16(provider_names[i]);
79 if (cert->serial_number().size() < std::numeric_limits<size_t>::max() / 2) { 79 if (cert->serial_number().size() < std::numeric_limits<size_t>::max() / 2) {
80 row.serial = base::UTF8ToUTF16(base::HexEncode( 80 row.serial = base::UTF8ToUTF16(base::HexEncode(
81 cert->serial_number().data(), cert->serial_number().size())); 81 cert->serial_number().data(), cert->serial_number().size()));
82 } 82 }
83 rows_.push_back(row); 83 rows_.push_back(row);
84 } 84 }
(...skipping 21 matching lines...) Expand all
106 return row.serial; 106 return row.serial;
107 default: 107 default:
108 NOTREACHED(); 108 NOTREACHED();
109 } 109 }
110 return base::string16(); 110 return base::string16();
111 } 111 }
112 112
113 void CertificateSelector::CertificateTableModel::SetObserver( 113 void CertificateSelector::CertificateTableModel::SetObserver(
114 ui::TableModelObserver* observer) {} 114 ui::TableModelObserver* observer) {}
115 115
116 CertificateSelector::CertificateSelector( 116 CertificateSelector::CertificateSelector(net::ClientCertIdentityList identities,
117 const net::CertificateList& certificates, 117 content::WebContents* web_contents)
118 content::WebContents* web_contents)
119 : web_contents_(web_contents), table_(nullptr), view_cert_button_(nullptr) { 118 : web_contents_(web_contents), table_(nullptr), view_cert_button_(nullptr) {
120 CHECK(web_contents_); 119 CHECK(web_contents_);
121 120
122 // |provider_names| and |certificates_| are parallel arrays. 121 // |provider_names| and |identities_| are parallel arrays.
123 // The entry at index |i| is the provider name for |certificates_[i]|. 122 // The entry at index |i| is the provider name for |identities_[i]|.
124 std::vector<std::string> provider_names; 123 std::vector<std::string> provider_names;
125 #if defined(OS_CHROMEOS) 124 #if defined(OS_CHROMEOS)
126 chromeos::CertificateProviderService* service = 125 chromeos::CertificateProviderService* service =
127 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( 126 chromeos::CertificateProviderServiceFactory::GetForBrowserContext(
128 web_contents->GetBrowserContext()); 127 web_contents->GetBrowserContext());
129 extensions::ExtensionRegistry* extension_registry = 128 extensions::ExtensionRegistry* extension_registry =
130 extensions::ExtensionRegistryFactory::GetForBrowserContext( 129 extensions::ExtensionRegistryFactory::GetForBrowserContext(
131 web_contents->GetBrowserContext()); 130 web_contents->GetBrowserContext());
132 131
133 for (const auto& cert : certificates) { 132 for (auto& identity : identities) {
134 std::string provider_name; 133 std::string provider_name;
135 bool has_extension = false; 134 bool has_extension = false;
136 std::string extension_id; 135 std::string extension_id;
137 if (service->LookUpCertificate(*cert, &has_extension, &extension_id)) { 136 if (service->LookUpCertificate(*identity->certificate(), &has_extension,
137 &extension_id)) {
138 if (!has_extension) { 138 if (!has_extension) {
139 // This certificate was provided by an extension but isn't provided by 139 // This certificate was provided by an extension but isn't provided by
140 // any extension currently. Don't expose it to the user. 140 // any extension currently. Don't expose it to the user.
141 continue; 141 continue;
142 } 142 }
143 const auto* extension = extension_registry->GetExtensionById( 143 const auto* extension = extension_registry->GetExtensionById(
144 extension_id, extensions::ExtensionRegistry::ENABLED); 144 extension_id, extensions::ExtensionRegistry::ENABLED);
145 if (!extension) { 145 if (!extension) {
146 // This extension was unloaded in the meantime. Don't show the 146 // This extension was unloaded in the meantime. Don't show the
147 // certificate. 147 // certificate.
148 continue; 148 continue;
149 } 149 }
150 provider_name = extension->short_name(); 150 provider_name = extension->short_name();
151 show_provider_column_ = true; 151 show_provider_column_ = true;
152 } // Otherwise the certificate is provided by the platform. 152 } // Otherwise the certificate is provided by the platform.
153 153
154 certificates_.push_back(cert); 154 identities_.push_back(std::move(identity));
155 provider_names.push_back(provider_name); 155 provider_names.push_back(provider_name);
156 } 156 }
157 #else 157 #else
158 provider_names.assign(certificates.size(), std::string()); 158 provider_names.assign(identities.size(), std::string());
159 certificates_ = certificates; 159 identities_ = std::move(identities);
160 #endif 160 #endif
161 161
162 model_.reset(new CertificateTableModel(certificates_, provider_names)); 162 model_.reset(new CertificateTableModel(identities_, provider_names));
163 } 163 }
164 164
165 CertificateSelector::~CertificateSelector() { 165 CertificateSelector::~CertificateSelector() {
166 table_->SetModel(nullptr); 166 table_->SetModel(nullptr);
167 } 167 }
168 168
169 // static 169 // static
170 bool CertificateSelector::CanShow(content::WebContents* web_contents) { 170 bool CertificateSelector::CanShow(content::WebContents* web_contents) {
171 // GetTopLevelWebContents returns |web_contents| if it is not a guest. 171 // GetTopLevelWebContents returns |web_contents| if it is not a guest.
172 content::WebContents* top_level_web_contents = 172 content::WebContents* top_level_web_contents =
173 guest_view::GuestViewBase::GetTopLevelWebContents(web_contents); 173 guest_view::GuestViewBase::GetTopLevelWebContents(web_contents);
174 return web_modal::WebContentsModalDialogManager::FromWebContents( 174 return web_modal::WebContentsModalDialogManager::FromWebContents(
175 top_level_web_contents) != nullptr; 175 top_level_web_contents) != nullptr;
176 } 176 }
177 177
178 void CertificateSelector::Show() { 178 void CertificateSelector::Show() {
179 constrained_window::ShowWebModalDialogViews(this, web_contents_); 179 constrained_window::ShowWebModalDialogViews(this, web_contents_);
180 180
181 // TODO(isandrk): A certificate that was previously provided by *both* the 181 // TODO(isandrk): A certificate that was previously provided by *both* the
182 // platform and an extension will get incorrectly filtered out if the 182 // platform and an extension will get incorrectly filtered out if the
183 // extension stops providing it (both instances will be filtered out), hence 183 // extension stops providing it (both instances will be filtered out), hence
184 // the |certificates_| array will be empty. Displaying a dialog with an empty 184 // the |identities_| array will be empty. Displaying a dialog with an empty
185 // list won't make much sense for the user, and also there are some CHECKs in 185 // list won't make much sense for the user, and also there are some CHECKs in
186 // the code that will fail when the list is empty and that's why an early exit 186 // the code that will fail when the list is empty and that's why an early exit
187 // is performed here. See crbug.com/641440 for more details. 187 // is performed here. See crbug.com/641440 for more details.
188 if (certificates_.empty()) { 188 if (identities_.empty()) {
189 GetWidget()->Close(); 189 GetWidget()->Close();
190 return; 190 return;
191 } 191 }
192 192
193 // Select the first row automatically. This must be done after the dialog has 193 // Select the first row automatically. This must be done after the dialog has
194 // been created. 194 // been created.
195 table_->Select(0); 195 table_->Select(0);
196 } 196 }
197 197
198 void CertificateSelector::InitWithText( 198 void CertificateSelector::InitWithText(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 views::GridLayout::FILL, views::GridLayout::FILL, 232 views::GridLayout::FILL, views::GridLayout::FILL,
233 kTableViewWidth, kTableViewHeight); 233 kTableViewWidth, kTableViewHeight);
234 234
235 layout->AddPaddingRow(0, vertical_spacing); 235 layout->AddPaddingRow(0, vertical_spacing);
236 } 236 }
237 237
238 ui::TableModel* CertificateSelector::table_model_for_testing() const { 238 ui::TableModel* CertificateSelector::table_model_for_testing() const {
239 return model_.get(); 239 return model_.get();
240 } 240 }
241 241
242 net::X509Certificate* CertificateSelector::GetSelectedCert() const { 242 net::ClientCertIdentity* CertificateSelector::GetSelectedCert() const {
243 DCHECK(!certificate_accepted_);
243 const int selected = table_->FirstSelectedRow(); 244 const int selected = table_->FirstSelectedRow();
244 if (selected < 0) // Nothing is selected in |table_|. 245 if (selected < 0) // Nothing is selected in |table_|.
245 return nullptr; 246 return nullptr;
246 CHECK_LT(static_cast<size_t>(selected), certificates_.size()); 247 CHECK_LT(static_cast<size_t>(selected), identities_.size());
Peter Kasting 2017/06/16 23:29:52 Nit: Seems like this should be DCHECK? (I think t
mattm 2017/06/17 03:20:07 Done.
247 return certificates_[selected].get(); 248 return identities_[selected].get();
249 }
250
251 bool CertificateSelector::Accept() {
252 DCHECK(!certificate_accepted_);
253 const int selected = table_->FirstSelectedRow();
254 if (selected < 0) // Nothing is selected in |table_|.
255 return false;
256
257 certificate_accepted_ = true;
258 table_->SetEnabled(false);
259 view_cert_button_->SetEnabled(false);
260 GetDialogClientView()->ok_button()->SetEnabled(false);
261 GetDialogClientView()->cancel_button()->SetEnabled(false);
262
263 CHECK_LT(static_cast<size_t>(selected), identities_.size());
Peter Kasting 2017/06/16 23:29:52 Nit: Seems like this should be DCHECK too?
mattm 2017/06/17 03:20:07 Done.
264 return AcceptCertificate(std::move(identities_[selected]));
Peter Kasting 2017/06/16 23:29:52 So, if AcceptCertificate() returns false, then we
mattm 2017/06/17 03:20:07 Done. (Though I just did it by returning true, I t
248 } 265 }
249 266
250 bool CertificateSelector::CanResize() const { 267 bool CertificateSelector::CanResize() const {
251 return true; 268 return true;
252 } 269 }
253 270
254 base::string16 CertificateSelector::GetWindowTitle() const { 271 base::string16 CertificateSelector::GetWindowTitle() const {
255 return l10n_util::GetStringUTF16(IDS_CLIENT_CERT_DIALOG_TITLE); 272 return l10n_util::GetStringUTF16(IDS_CLIENT_CERT_DIALOG_TITLE);
256 } 273 }
257 274
258 bool CertificateSelector::IsDialogButtonEnabled(ui::DialogButton button) const { 275 bool CertificateSelector::IsDialogButtonEnabled(ui::DialogButton button) const {
259 return button != ui::DIALOG_BUTTON_OK || GetSelectedCert() != nullptr; 276 return !certificate_accepted_ &&
277 (button != ui::DIALOG_BUTTON_OK || GetSelectedCert() != nullptr);
260 } 278 }
261 279
262 views::View* CertificateSelector::GetInitiallyFocusedView() { 280 views::View* CertificateSelector::GetInitiallyFocusedView() {
263 DCHECK(table_); 281 DCHECK(table_);
264 return table_; 282 return table_;
265 } 283 }
266 284
267 views::View* CertificateSelector::CreateExtraView() { 285 views::View* CertificateSelector::CreateExtraView() {
268 DCHECK(!view_cert_button_); 286 DCHECK(!view_cert_button_);
269 view_cert_button_ = views::MdTextButton::CreateSecondaryUiButton( 287 view_cert_button_ = views::MdTextButton::CreateSecondaryUiButton(
270 this, l10n_util::GetStringUTF16(IDS_PAGE_INFO_CERT_INFO_BUTTON)); 288 this, l10n_util::GetStringUTF16(IDS_PAGE_INFO_CERT_INFO_BUTTON));
271 return view_cert_button_; 289 return view_cert_button_;
272 } 290 }
273 291
274 ui::ModalType CertificateSelector::GetModalType() const { 292 ui::ModalType CertificateSelector::GetModalType() const {
275 return ui::MODAL_TYPE_CHILD; 293 return ui::MODAL_TYPE_CHILD;
276 } 294 }
277 295
278 void CertificateSelector::ButtonPressed(views::Button* sender, 296 void CertificateSelector::ButtonPressed(views::Button* sender,
279 const ui::Event& event) { 297 const ui::Event& event) {
298 DCHECK(!certificate_accepted_);
280 if (sender == view_cert_button_) { 299 if (sender == view_cert_button_) {
281 net::X509Certificate* const cert = GetSelectedCert(); 300 net::ClientCertIdentity* const cert = GetSelectedCert();
282 if (cert) 301 if (cert) {
283 ShowCertificateViewer(web_contents_, 302 ShowCertificateViewer(web_contents_,
284 web_contents_->GetTopLevelNativeWindow(), cert); 303 web_contents_->GetTopLevelNativeWindow(),
304 cert->certificate());
305 }
285 } 306 }
286 } 307 }
287 308
288 void CertificateSelector::OnSelectionChanged() { 309 void CertificateSelector::OnSelectionChanged() {
289 GetDialogClientView()->ok_button()->SetEnabled(GetSelectedCert() != nullptr); 310 GetDialogClientView()->ok_button()->SetEnabled(!certificate_accepted_ &&
311 GetSelectedCert() != nullptr);
290 } 312 }
291 313
292 void CertificateSelector::OnDoubleClick() { 314 void CertificateSelector::OnDoubleClick() {
315 DCHECK(!certificate_accepted_);
293 if (GetSelectedCert()) 316 if (GetSelectedCert())
294 GetDialogClientView()->AcceptWindow(); 317 GetDialogClientView()->AcceptWindow();
295 } 318 }
296 319
297 } // namespace chrome 320 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698