Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / certificate_manager_handler.cc
blob12b76ef2c779708396d2739dd8af8707de004d99
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/webui/options/certificate_manager_handler.h"
7 #include <algorithm>
8 #include <map>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/files/file_util.h" // for FileAccessProvider
13 #include "base/i18n/string_compare.h"
14 #include "base/id_map.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/safe_strerror_posix.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/values.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/certificate_viewer.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/certificate_dialogs.h"
24 #include "chrome/browser/ui/chrome_select_file_policy.h"
25 #include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
26 #include "chrome/browser/ui/webui/certificate_viewer_webui.h"
27 #include "chrome/grit/generated_resources.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/web_contents.h"
30 #include "net/base/crypto_module.h"
31 #include "net/base/net_errors.h"
32 #include "net/cert/x509_certificate.h"
33 #include "ui/base/l10n/l10n_util.h"
35 #if defined(OS_CHROMEOS)
36 #include "chrome/browser/chromeos/policy/user_network_configuration_updater.h"
37 #include "chrome/browser/chromeos/policy/user_network_configuration_updater_factory.h"
38 #endif
40 using base::UTF8ToUTF16;
41 using content::BrowserThread;
43 namespace {
45 static const char kKeyId[] = "id";
46 static const char kSubNodesId[] = "subnodes";
47 static const char kNameId[] = "name";
48 static const char kReadOnlyId[] = "readonly";
49 static const char kUntrustedId[] = "untrusted";
50 static const char kExtractableId[] = "extractable";
51 static const char kErrorId[] = "error";
52 static const char kPolicyTrustedId[] = "policy";
54 // Enumeration of different callers of SelectFile. (Start counting at 1 so
55 // if SelectFile is accidentally called with params=NULL it won't match any.)
56 enum {
57 EXPORT_PERSONAL_FILE_SELECTED = 1,
58 IMPORT_PERSONAL_FILE_SELECTED,
59 IMPORT_SERVER_FILE_SELECTED,
60 IMPORT_CA_FILE_SELECTED,
63 std::string OrgNameToId(const std::string& org) {
64 return "org-" + org;
67 bool CallbackArgsToBool(const base::ListValue* args, int index, bool* result) {
68 std::string string_value;
69 if (!args->GetString(index, &string_value))
70 return false;
72 *result = string_value[0] == 't';
73 return true;
76 struct DictionaryIdComparator {
77 explicit DictionaryIdComparator(icu::Collator* collator)
78 : collator_(collator) {
81 bool operator()(const base::Value* a,
82 const base::Value* b) const {
83 DCHECK(a->GetType() == base::Value::TYPE_DICTIONARY);
84 DCHECK(b->GetType() == base::Value::TYPE_DICTIONARY);
85 const base::DictionaryValue* a_dict =
86 reinterpret_cast<const base::DictionaryValue*>(a);
87 const base::DictionaryValue* b_dict =
88 reinterpret_cast<const base::DictionaryValue*>(b);
89 base::string16 a_str;
90 base::string16 b_str;
91 a_dict->GetString(kNameId, &a_str);
92 b_dict->GetString(kNameId, &b_str);
93 if (collator_ == NULL)
94 return a_str < b_str;
95 return base::i18n::CompareString16WithCollator(*collator_, a_str, b_str) ==
96 UCOL_LESS;
99 icu::Collator* collator_;
102 std::string NetErrorToString(int net_error) {
103 switch (net_error) {
104 // TODO(mattm): handle more cases.
105 case net::ERR_IMPORT_CA_CERT_NOT_CA:
106 return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_ERROR_NOT_CA);
107 case net::ERR_IMPORT_CERT_ALREADY_EXISTS:
108 return l10n_util::GetStringUTF8(
109 IDS_CERT_MANAGER_ERROR_CERT_ALREADY_EXISTS);
110 default:
111 return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR);
115 // Struct to bind the Equals member function to an object for use in find_if.
116 struct CertEquals {
117 explicit CertEquals(const net::X509Certificate* cert) : cert_(cert) {}
118 bool operator()(const scoped_refptr<net::X509Certificate> cert) const {
119 return cert_->Equals(cert.get());
121 const net::X509Certificate* cert_;
124 // Determine whether a certificate was stored with web trust by a policy.
125 bool IsPolicyInstalledWithWebTrust(
126 const net::CertificateList& web_trust_certs,
127 net::X509Certificate* cert) {
128 return std::find_if(web_trust_certs.begin(), web_trust_certs.end(),
129 CertEquals(cert)) != web_trust_certs.end();
132 #if defined(OS_CHROMEOS)
133 void ShowCertificateViewerModalDialog(content::WebContents* web_contents,
134 gfx::NativeWindow parent,
135 net::X509Certificate* cert) {
136 CertificateViewerModalDialog* dialog = new CertificateViewerModalDialog(cert);
137 dialog->Show(web_contents, parent);
139 #endif
141 } // namespace
143 namespace options {
145 ///////////////////////////////////////////////////////////////////////////////
146 // CertIdMap
148 class CertIdMap {
149 public:
150 CertIdMap() {}
151 ~CertIdMap() {}
153 std::string CertToId(net::X509Certificate* cert);
154 net::X509Certificate* IdToCert(const std::string& id);
155 net::X509Certificate* CallbackArgsToCert(const base::ListValue* args);
157 private:
158 typedef std::map<net::X509Certificate*, int32> CertMap;
160 // Creates an ID for cert and looks up the cert for an ID.
161 IDMap<net::X509Certificate>id_map_;
163 // Finds the ID for a cert.
164 CertMap cert_map_;
166 DISALLOW_COPY_AND_ASSIGN(CertIdMap);
169 std::string CertIdMap::CertToId(net::X509Certificate* cert) {
170 CertMap::const_iterator iter = cert_map_.find(cert);
171 if (iter != cert_map_.end())
172 return base::IntToString(iter->second);
174 int32 new_id = id_map_.Add(cert);
175 cert_map_[cert] = new_id;
176 return base::IntToString(new_id);
179 net::X509Certificate* CertIdMap::IdToCert(const std::string& id) {
180 int32 cert_id = 0;
181 if (!base::StringToInt(id, &cert_id))
182 return NULL;
184 return id_map_.Lookup(cert_id);
187 net::X509Certificate* CertIdMap::CallbackArgsToCert(
188 const base::ListValue* args) {
189 std::string node_id;
190 if (!args->GetString(0, &node_id))
191 return NULL;
193 net::X509Certificate* cert = IdToCert(node_id);
194 if (!cert) {
195 NOTREACHED();
196 return NULL;
199 return cert;
202 ///////////////////////////////////////////////////////////////////////////////
203 // FileAccessProvider
205 // TODO(mattm): Move to some shared location?
206 class FileAccessProvider
207 : public base::RefCountedThreadSafe<FileAccessProvider> {
208 public:
209 // The first parameter is 0 on success or errno on failure. The second
210 // parameter is read result.
211 typedef base::Callback<void(const int*, const std::string*)> ReadCallback;
213 // The first parameter is 0 on success or errno on failure. The second
214 // parameter is the number of bytes written on success.
215 typedef base::Callback<void(const int*, const int*)> WriteCallback;
217 base::CancelableTaskTracker::TaskId StartRead(
218 const base::FilePath& path,
219 const ReadCallback& callback,
220 base::CancelableTaskTracker* tracker);
221 base::CancelableTaskTracker::TaskId StartWrite(
222 const base::FilePath& path,
223 const std::string& data,
224 const WriteCallback& callback,
225 base::CancelableTaskTracker* tracker);
227 private:
228 friend class base::RefCountedThreadSafe<FileAccessProvider>;
229 virtual ~FileAccessProvider() {}
231 // Reads file at |path|. |saved_errno| is 0 on success or errno on failure.
232 // When success, |data| has file content.
233 void DoRead(const base::FilePath& path,
234 int* saved_errno,
235 std::string* data);
236 // Writes data to file at |path|. |saved_errno| is 0 on success or errno on
237 // failure. When success, |bytes_written| has number of bytes written.
238 void DoWrite(const base::FilePath& path,
239 const std::string& data,
240 int* saved_errno,
241 int* bytes_written);
244 base::CancelableTaskTracker::TaskId FileAccessProvider::StartRead(
245 const base::FilePath& path,
246 const ReadCallback& callback,
247 base::CancelableTaskTracker* tracker) {
248 // Owned by reply callback posted below.
249 int* saved_errno = new int(0);
250 std::string* data = new std::string();
252 // Post task to file thread to read file.
253 return tracker->PostTaskAndReply(
254 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(),
255 FROM_HERE,
256 base::Bind(&FileAccessProvider::DoRead, this, path, saved_errno, data),
257 base::Bind(callback, base::Owned(saved_errno), base::Owned(data)));
260 base::CancelableTaskTracker::TaskId FileAccessProvider::StartWrite(
261 const base::FilePath& path,
262 const std::string& data,
263 const WriteCallback& callback,
264 base::CancelableTaskTracker* tracker) {
265 // Owned by reply callback posted below.
266 int* saved_errno = new int(0);
267 int* bytes_written = new int(0);
269 // Post task to file thread to write file.
270 return tracker->PostTaskAndReply(
271 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(),
272 FROM_HERE,
273 base::Bind(&FileAccessProvider::DoWrite,
274 this,
275 path,
276 data,
277 saved_errno,
278 bytes_written),
279 base::Bind(
280 callback, base::Owned(saved_errno), base::Owned(bytes_written)));
283 void FileAccessProvider::DoRead(const base::FilePath& path,
284 int* saved_errno,
285 std::string* data) {
286 bool success = base::ReadFileToString(path, data);
287 *saved_errno = success ? 0 : errno;
290 void FileAccessProvider::DoWrite(const base::FilePath& path,
291 const std::string& data,
292 int* saved_errno,
293 int* bytes_written) {
294 *bytes_written = base::WriteFile(path, data.data(), data.size());
295 *saved_errno = *bytes_written >= 0 ? 0 : errno;
298 ///////////////////////////////////////////////////////////////////////////////
299 // CertificateManagerHandler
301 CertificateManagerHandler::CertificateManagerHandler(
302 bool show_certs_in_modal_dialog)
303 : show_certs_in_modal_dialog_(show_certs_in_modal_dialog),
304 requested_certificate_manager_model_(false),
305 use_hardware_backed_(false),
306 file_access_provider_(new FileAccessProvider()),
307 cert_id_map_(new CertIdMap),
308 weak_ptr_factory_(this) {}
310 CertificateManagerHandler::~CertificateManagerHandler() {
313 void CertificateManagerHandler::GetLocalizedValues(
314 base::DictionaryValue* localized_strings) {
315 DCHECK(localized_strings);
317 RegisterTitle(localized_strings, "certificateManagerPage",
318 IDS_CERTIFICATE_MANAGER_TITLE);
320 // Tabs.
321 localized_strings->SetString("personalCertsTabTitle",
322 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PERSONAL_CERTS_TAB_LABEL));
323 localized_strings->SetString("serverCertsTabTitle",
324 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_CERTS_TAB_LABEL));
325 localized_strings->SetString("caCertsTabTitle",
326 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CERT_AUTHORITIES_TAB_LABEL));
327 localized_strings->SetString("otherCertsTabTitle",
328 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_OTHER_TAB_LABEL));
330 // Tab descriptions.
331 localized_strings->SetString("personalCertsTabDescription",
332 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_USER_TREE_DESCRIPTION));
333 localized_strings->SetString("serverCertsTabDescription",
334 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_TREE_DESCRIPTION));
335 localized_strings->SetString("caCertsTabDescription",
336 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_AUTHORITIES_TREE_DESCRIPTION));
337 localized_strings->SetString("otherCertsTabDescription",
338 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_OTHER_TREE_DESCRIPTION));
340 // Buttons.
341 localized_strings->SetString("view_certificate",
342 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_VIEW_CERT_BUTTON));
343 localized_strings->SetString("import_certificate",
344 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_BUTTON));
345 localized_strings->SetString("export_certificate",
346 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_BUTTON));
347 localized_strings->SetString("edit_certificate",
348 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_BUTTON));
349 localized_strings->SetString("delete_certificate",
350 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_BUTTON));
352 // Certificate Delete overlay strings.
353 localized_strings->SetString("personalCertsTabDeleteConfirm",
354 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_FORMAT));
355 localized_strings->SetString("personalCertsTabDeleteImpact",
356 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_DESCRIPTION));
357 localized_strings->SetString("serverCertsTabDeleteConfirm",
358 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_FORMAT));
359 localized_strings->SetString("serverCertsTabDeleteImpact",
360 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_DESCRIPTION));
361 localized_strings->SetString("caCertsTabDeleteConfirm",
362 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_FORMAT));
363 localized_strings->SetString("caCertsTabDeleteImpact",
364 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_DESCRIPTION));
365 localized_strings->SetString("otherCertsTabDeleteConfirm",
366 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_OTHER_FORMAT));
367 localized_strings->SetString("otherCertsTabDeleteImpact", std::string());
369 // Certificate Restore overlay strings.
370 localized_strings->SetString("certificateRestorePasswordDescription",
371 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_RESTORE_PASSWORD_DESC));
372 localized_strings->SetString("certificatePasswordLabel",
373 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PASSWORD_LABEL));
375 // Personal Certificate Export overlay strings.
376 localized_strings->SetString("certificateExportPasswordDescription",
377 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_DESC));
378 localized_strings->SetString("certificateExportPasswordHelp",
379 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_HELP));
380 localized_strings->SetString("certificateConfirmPasswordLabel",
381 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CONFIRM_PASSWORD_LABEL));
383 // Edit CA Trust & Import CA overlay strings.
384 localized_strings->SetString("certificateEditCaTitle",
385 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TITLE));
386 localized_strings->SetString("certificateEditTrustLabel",
387 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_TRUST_LABEL));
388 localized_strings->SetString("certificateEditCaTrustDescriptionFormat",
389 l10n_util::GetStringUTF16(
390 IDS_CERT_MANAGER_EDIT_CA_TRUST_DESCRIPTION_FORMAT));
391 localized_strings->SetString("certificateImportCaDescriptionFormat",
392 l10n_util::GetStringUTF16(
393 IDS_CERT_MANAGER_IMPORT_CA_DESCRIPTION_FORMAT));
394 localized_strings->SetString("certificateCaTrustSSLLabel",
395 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_SSL_LABEL));
396 localized_strings->SetString("certificateCaTrustEmailLabel",
397 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_EMAIL_LABEL));
398 localized_strings->SetString("certificateCaTrustObjSignLabel",
399 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_OBJSIGN_LABEL));
400 localized_strings->SetString("certificateImportErrorFormat",
401 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_ERROR_FORMAT));
403 // Badges next to certificates
404 localized_strings->SetString("badgeCertUntrusted",
405 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNTRUSTED));
406 localized_strings->SetString("certPolicyInstalled",
407 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_POLICY_INSTALLED));
409 #if defined(OS_CHROMEOS)
410 localized_strings->SetString("importAndBindCertificate",
411 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_AND_BIND_BUTTON));
412 #endif // defined(OS_CHROMEOS)
415 void CertificateManagerHandler::RegisterMessages() {
416 web_ui()->RegisterMessageCallback(
417 "viewCertificate",
418 base::Bind(&CertificateManagerHandler::View, base::Unretained(this)));
420 web_ui()->RegisterMessageCallback(
421 "getCaCertificateTrust",
422 base::Bind(&CertificateManagerHandler::GetCATrust,
423 base::Unretained(this)));
424 web_ui()->RegisterMessageCallback(
425 "editCaCertificateTrust",
426 base::Bind(&CertificateManagerHandler::EditCATrust,
427 base::Unretained(this)));
429 web_ui()->RegisterMessageCallback(
430 "editServerCertificate",
431 base::Bind(&CertificateManagerHandler::EditServer,
432 base::Unretained(this)));
434 web_ui()->RegisterMessageCallback(
435 "cancelImportExportCertificate",
436 base::Bind(&CertificateManagerHandler::CancelImportExportProcess,
437 base::Unretained(this)));
439 web_ui()->RegisterMessageCallback(
440 "exportPersonalCertificate",
441 base::Bind(&CertificateManagerHandler::ExportPersonal,
442 base::Unretained(this)));
443 web_ui()->RegisterMessageCallback(
444 "exportAllPersonalCertificates",
445 base::Bind(&CertificateManagerHandler::ExportAllPersonal,
446 base::Unretained(this)));
447 web_ui()->RegisterMessageCallback(
448 "exportPersonalCertificatePasswordSelected",
449 base::Bind(&CertificateManagerHandler::ExportPersonalPasswordSelected,
450 base::Unretained(this)));
452 web_ui()->RegisterMessageCallback(
453 "importPersonalCertificate",
454 base::Bind(&CertificateManagerHandler::StartImportPersonal,
455 base::Unretained(this)));
456 web_ui()->RegisterMessageCallback(
457 "importPersonalCertificatePasswordSelected",
458 base::Bind(&CertificateManagerHandler::ImportPersonalPasswordSelected,
459 base::Unretained(this)));
461 web_ui()->RegisterMessageCallback(
462 "importCaCertificate",
463 base::Bind(&CertificateManagerHandler::ImportCA,
464 base::Unretained(this)));
465 web_ui()->RegisterMessageCallback(
466 "importCaCertificateTrustSelected",
467 base::Bind(&CertificateManagerHandler::ImportCATrustSelected,
468 base::Unretained(this)));
470 web_ui()->RegisterMessageCallback(
471 "importServerCertificate",
472 base::Bind(&CertificateManagerHandler::ImportServer,
473 base::Unretained(this)));
475 web_ui()->RegisterMessageCallback(
476 "exportCertificate",
477 base::Bind(&CertificateManagerHandler::Export,
478 base::Unretained(this)));
480 web_ui()->RegisterMessageCallback(
481 "deleteCertificate",
482 base::Bind(&CertificateManagerHandler::Delete,
483 base::Unretained(this)));
485 web_ui()->RegisterMessageCallback(
486 "populateCertificateManager",
487 base::Bind(&CertificateManagerHandler::Populate,
488 base::Unretained(this)));
491 void CertificateManagerHandler::CertificatesRefreshed() {
492 net::CertificateList web_trusted_certs;
493 #if defined(OS_CHROMEOS)
494 policy::UserNetworkConfigurationUpdater* service =
495 policy::UserNetworkConfigurationUpdaterFactory::GetForProfile(
496 Profile::FromWebUI(web_ui()));
497 if (service)
498 service->GetWebTrustedCertificates(&web_trusted_certs);
499 #endif
500 PopulateTree("personalCertsTab", net::USER_CERT, web_trusted_certs);
501 PopulateTree("serverCertsTab", net::SERVER_CERT, web_trusted_certs);
502 PopulateTree("caCertsTab", net::CA_CERT, web_trusted_certs);
503 PopulateTree("otherCertsTab", net::OTHER_CERT, web_trusted_certs);
506 void CertificateManagerHandler::FileSelected(const base::FilePath& path,
507 int index,
508 void* params) {
509 switch (reinterpret_cast<intptr_t>(params)) {
510 case EXPORT_PERSONAL_FILE_SELECTED:
511 ExportPersonalFileSelected(path);
512 break;
513 case IMPORT_PERSONAL_FILE_SELECTED:
514 ImportPersonalFileSelected(path);
515 break;
516 case IMPORT_SERVER_FILE_SELECTED:
517 ImportServerFileSelected(path);
518 break;
519 case IMPORT_CA_FILE_SELECTED:
520 ImportCAFileSelected(path);
521 break;
522 default:
523 NOTREACHED();
527 void CertificateManagerHandler::FileSelectionCanceled(void* params) {
528 switch (reinterpret_cast<intptr_t>(params)) {
529 case EXPORT_PERSONAL_FILE_SELECTED:
530 case IMPORT_PERSONAL_FILE_SELECTED:
531 case IMPORT_SERVER_FILE_SELECTED:
532 case IMPORT_CA_FILE_SELECTED:
533 ImportExportCleanup();
534 break;
535 default:
536 NOTREACHED();
540 void CertificateManagerHandler::View(const base::ListValue* args) {
541 net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
542 if (!cert)
543 return;
544 #if defined(OS_CHROMEOS)
545 if (show_certs_in_modal_dialog_) {
546 ShowCertificateViewerModalDialog(web_ui()->GetWebContents(),
547 GetParentWindow(),
548 cert);
549 return;
551 #endif
552 ShowCertificateViewer(web_ui()->GetWebContents(), GetParentWindow(), cert);
555 void CertificateManagerHandler::GetCATrust(const base::ListValue* args) {
556 net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
557 if (!cert) {
558 web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
559 return;
562 net::NSSCertDatabase::TrustBits trust_bits =
563 certificate_manager_model_->cert_db()->GetCertTrust(cert, net::CA_CERT);
564 base::FundamentalValue ssl_value(
565 static_cast<bool>(trust_bits & net::NSSCertDatabase::TRUSTED_SSL));
566 base::FundamentalValue email_value(
567 static_cast<bool>(trust_bits & net::NSSCertDatabase::TRUSTED_EMAIL));
568 base::FundamentalValue obj_sign_value(
569 static_cast<bool>(trust_bits & net::NSSCertDatabase::TRUSTED_OBJ_SIGN));
570 web_ui()->CallJavascriptFunction(
571 "CertificateEditCaTrustOverlay.populateTrust",
572 ssl_value, email_value, obj_sign_value);
575 void CertificateManagerHandler::EditCATrust(const base::ListValue* args) {
576 net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
577 bool fail = !cert;
578 bool trust_ssl = false;
579 bool trust_email = false;
580 bool trust_obj_sign = false;
581 fail |= !CallbackArgsToBool(args, 1, &trust_ssl);
582 fail |= !CallbackArgsToBool(args, 2, &trust_email);
583 fail |= !CallbackArgsToBool(args, 3, &trust_obj_sign);
584 if (fail) {
585 LOG(ERROR) << "EditCATrust args fail";
586 web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
587 return;
590 bool result = certificate_manager_model_->SetCertTrust(
591 cert,
592 net::CA_CERT,
593 trust_ssl * net::NSSCertDatabase::TRUSTED_SSL +
594 trust_email * net::NSSCertDatabase::TRUSTED_EMAIL +
595 trust_obj_sign * net::NSSCertDatabase::TRUSTED_OBJ_SIGN);
596 web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
597 if (!result) {
598 // TODO(mattm): better error messages?
599 ShowError(
600 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SET_TRUST_ERROR_TITLE),
601 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
605 void CertificateManagerHandler::EditServer(const base::ListValue* args) {
606 NOTIMPLEMENTED();
609 void CertificateManagerHandler::ExportPersonal(const base::ListValue* args) {
610 net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
611 if (!cert)
612 return;
614 selected_cert_list_.push_back(cert);
616 ui::SelectFileDialog::FileTypeInfo file_type_info;
617 file_type_info.extensions.resize(1);
618 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
619 file_type_info.extension_description_overrides.push_back(
620 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
621 file_type_info.include_all_files = true;
622 select_file_dialog_ = ui::SelectFileDialog::Create(
623 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
624 select_file_dialog_->SelectFile(
625 ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(),
626 base::FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
627 GetParentWindow(),
628 reinterpret_cast<void*>(EXPORT_PERSONAL_FILE_SELECTED));
631 void CertificateManagerHandler::ExportAllPersonal(const base::ListValue* args) {
632 NOTIMPLEMENTED();
635 void CertificateManagerHandler::ExportPersonalFileSelected(
636 const base::FilePath& path) {
637 file_path_ = path;
638 web_ui()->CallJavascriptFunction(
639 "CertificateManager.exportPersonalAskPassword");
642 void CertificateManagerHandler::ExportPersonalPasswordSelected(
643 const base::ListValue* args) {
644 if (!args->GetString(0, &password_)) {
645 web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
646 ImportExportCleanup();
647 return;
650 // Currently, we don't support exporting more than one at a time. If we do,
651 // this would need to either change this to use UnlockSlotsIfNecessary or
652 // change UnlockCertSlotIfNecessary to take a CertificateList.
653 DCHECK_EQ(selected_cert_list_.size(), 1U);
655 // TODO(mattm): do something smarter about non-extractable keys
656 chrome::UnlockCertSlotIfNecessary(
657 selected_cert_list_[0].get(),
658 chrome::kCryptoModulePasswordCertExport,
659 net::HostPortPair(), // unused.
660 GetParentWindow(),
661 base::Bind(&CertificateManagerHandler::ExportPersonalSlotsUnlocked,
662 base::Unretained(this)));
665 void CertificateManagerHandler::ExportPersonalSlotsUnlocked() {
666 std::string output;
667 int num_exported = certificate_manager_model_->cert_db()->ExportToPKCS12(
668 selected_cert_list_,
669 password_,
670 &output);
671 if (!num_exported) {
672 web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
673 ShowError(
674 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
675 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
676 ImportExportCleanup();
677 return;
679 file_access_provider_->StartWrite(
680 file_path_,
681 output,
682 base::Bind(&CertificateManagerHandler::ExportPersonalFileWritten,
683 base::Unretained(this)),
684 &tracker_);
687 void CertificateManagerHandler::ExportPersonalFileWritten(
688 const int* write_errno, const int* bytes_written) {
689 web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
690 ImportExportCleanup();
691 if (*write_errno) {
692 ShowError(
693 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
694 l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_WRITE_ERROR_FORMAT,
695 UTF8ToUTF16(safe_strerror(*write_errno))));
699 void CertificateManagerHandler::StartImportPersonal(
700 const base::ListValue* args) {
701 ui::SelectFileDialog::FileTypeInfo file_type_info;
702 if (!args->GetBoolean(0, &use_hardware_backed_)) {
703 // Unable to retrieve the hardware backed attribute from the args,
704 // so bail.
705 web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
706 ImportExportCleanup();
707 return;
709 file_type_info.extensions.resize(1);
710 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
711 file_type_info.extension_description_overrides.push_back(
712 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
713 file_type_info.include_all_files = true;
714 select_file_dialog_ = ui::SelectFileDialog::Create(
715 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
716 select_file_dialog_->SelectFile(
717 ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(),
718 base::FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
719 GetParentWindow(),
720 reinterpret_cast<void*>(IMPORT_PERSONAL_FILE_SELECTED));
723 void CertificateManagerHandler::ImportPersonalFileSelected(
724 const base::FilePath& path) {
725 file_path_ = path;
726 web_ui()->CallJavascriptFunction(
727 "CertificateManager.importPersonalAskPassword");
730 void CertificateManagerHandler::ImportPersonalPasswordSelected(
731 const base::ListValue* args) {
732 if (!args->GetString(0, &password_)) {
733 web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
734 ImportExportCleanup();
735 return;
737 file_access_provider_->StartRead(
738 file_path_,
739 base::Bind(&CertificateManagerHandler::ImportPersonalFileRead,
740 base::Unretained(this)),
741 &tracker_);
744 void CertificateManagerHandler::ImportPersonalFileRead(
745 const int* read_errno, const std::string* data) {
746 if (*read_errno) {
747 ImportExportCleanup();
748 web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
749 ShowError(
750 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
751 l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
752 UTF8ToUTF16(safe_strerror(*read_errno))));
753 return;
756 file_data_ = *data;
758 if (use_hardware_backed_) {
759 module_ = certificate_manager_model_->cert_db()->GetPrivateModule();
760 } else {
761 module_ = certificate_manager_model_->cert_db()->GetPublicModule();
764 net::CryptoModuleList modules;
765 modules.push_back(module_);
766 chrome::UnlockSlotsIfNecessary(
767 modules,
768 chrome::kCryptoModulePasswordCertImport,
769 net::HostPortPair(), // unused.
770 GetParentWindow(),
771 base::Bind(&CertificateManagerHandler::ImportPersonalSlotUnlocked,
772 base::Unretained(this)));
775 void CertificateManagerHandler::ImportPersonalSlotUnlocked() {
776 // Determine if the private key should be unextractable after the import.
777 // We do this by checking the value of |use_hardware_backed_| which is set
778 // to true if importing into a hardware module. Currently, this only happens
779 // for Chrome OS when the "Import and Bind" option is chosen.
780 bool is_extractable = !use_hardware_backed_;
781 int result = certificate_manager_model_->ImportFromPKCS12(
782 module_.get(), file_data_, password_, is_extractable);
783 ImportExportCleanup();
784 web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
785 int string_id;
786 switch (result) {
787 case net::OK:
788 return;
789 case net::ERR_PKCS12_IMPORT_BAD_PASSWORD:
790 // TODO(mattm): if the error was a bad password, we should reshow the
791 // password dialog after the user dismisses the error dialog.
792 string_id = IDS_CERT_MANAGER_BAD_PASSWORD;
793 break;
794 case net::ERR_PKCS12_IMPORT_INVALID_MAC:
795 string_id = IDS_CERT_MANAGER_PKCS12_IMPORT_INVALID_MAC;
796 break;
797 case net::ERR_PKCS12_IMPORT_INVALID_FILE:
798 string_id = IDS_CERT_MANAGER_PKCS12_IMPORT_INVALID_FILE;
799 break;
800 case net::ERR_PKCS12_IMPORT_UNSUPPORTED:
801 string_id = IDS_CERT_MANAGER_PKCS12_IMPORT_UNSUPPORTED;
802 break;
803 default:
804 string_id = IDS_CERT_MANAGER_UNKNOWN_ERROR;
805 break;
807 ShowError(
808 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
809 l10n_util::GetStringUTF8(string_id));
812 void CertificateManagerHandler::CancelImportExportProcess(
813 const base::ListValue* args) {
814 ImportExportCleanup();
817 void CertificateManagerHandler::ImportExportCleanup() {
818 file_path_.clear();
819 password_.clear();
820 file_data_.clear();
821 use_hardware_backed_ = false;
822 selected_cert_list_.clear();
823 module_ = NULL;
825 // There may be pending file dialogs, we need to tell them that we've gone
826 // away so they don't try and call back to us.
827 if (select_file_dialog_.get())
828 select_file_dialog_->ListenerDestroyed();
829 select_file_dialog_ = NULL;
832 void CertificateManagerHandler::ImportServer(const base::ListValue* args) {
833 select_file_dialog_ = ui::SelectFileDialog::Create(
834 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
835 ShowCertSelectFileDialog(
836 select_file_dialog_.get(),
837 ui::SelectFileDialog::SELECT_OPEN_FILE,
838 base::FilePath(),
839 GetParentWindow(),
840 reinterpret_cast<void*>(IMPORT_SERVER_FILE_SELECTED));
843 void CertificateManagerHandler::ImportServerFileSelected(
844 const base::FilePath& path) {
845 file_path_ = path;
846 file_access_provider_->StartRead(
847 file_path_,
848 base::Bind(&CertificateManagerHandler::ImportServerFileRead,
849 base::Unretained(this)),
850 &tracker_);
853 void CertificateManagerHandler::ImportServerFileRead(const int* read_errno,
854 const std::string* data) {
855 if (*read_errno) {
856 ImportExportCleanup();
857 ShowError(
858 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
859 l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
860 UTF8ToUTF16(safe_strerror(*read_errno))));
861 return;
864 selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
865 data->data(), data->size(), net::X509Certificate::FORMAT_AUTO);
866 if (selected_cert_list_.empty()) {
867 ImportExportCleanup();
868 ShowError(
869 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
870 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
871 return;
874 net::NSSCertDatabase::ImportCertFailureList not_imported;
875 // TODO(mattm): Add UI for trust. http://crbug.com/76274
876 bool result = certificate_manager_model_->ImportServerCert(
877 selected_cert_list_,
878 net::NSSCertDatabase::TRUST_DEFAULT,
879 &not_imported);
880 if (!result) {
881 ShowError(
882 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
883 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
884 } else if (!not_imported.empty()) {
885 ShowImportErrors(
886 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
887 not_imported);
889 ImportExportCleanup();
892 void CertificateManagerHandler::ImportCA(const base::ListValue* args) {
893 select_file_dialog_ = ui::SelectFileDialog::Create(
894 this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
895 ShowCertSelectFileDialog(select_file_dialog_.get(),
896 ui::SelectFileDialog::SELECT_OPEN_FILE,
897 base::FilePath(),
898 GetParentWindow(),
899 reinterpret_cast<void*>(IMPORT_CA_FILE_SELECTED));
902 void CertificateManagerHandler::ImportCAFileSelected(
903 const base::FilePath& path) {
904 file_path_ = path;
905 file_access_provider_->StartRead(
906 file_path_,
907 base::Bind(&CertificateManagerHandler::ImportCAFileRead,
908 base::Unretained(this)),
909 &tracker_);
912 void CertificateManagerHandler::ImportCAFileRead(const int* read_errno,
913 const std::string* data) {
914 if (*read_errno) {
915 ImportExportCleanup();
916 ShowError(
917 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
918 l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
919 UTF8ToUTF16(safe_strerror(*read_errno))));
920 return;
923 selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
924 data->data(), data->size(), net::X509Certificate::FORMAT_AUTO);
925 if (selected_cert_list_.empty()) {
926 ImportExportCleanup();
927 ShowError(
928 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
929 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
930 return;
933 scoped_refptr<net::X509Certificate> root_cert =
934 certificate_manager_model_->cert_db()->FindRootInList(
935 selected_cert_list_);
937 // TODO(mattm): check here if root_cert is not a CA cert and show error.
939 base::StringValue cert_name(root_cert->subject().GetDisplayName());
940 web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.showImport",
941 cert_name);
944 void CertificateManagerHandler::ImportCATrustSelected(
945 const base::ListValue* args) {
946 bool fail = false;
947 bool trust_ssl = false;
948 bool trust_email = false;
949 bool trust_obj_sign = false;
950 fail |= !CallbackArgsToBool(args, 0, &trust_ssl);
951 fail |= !CallbackArgsToBool(args, 1, &trust_email);
952 fail |= !CallbackArgsToBool(args, 2, &trust_obj_sign);
953 if (fail) {
954 LOG(ERROR) << "ImportCATrustSelected args fail";
955 ImportExportCleanup();
956 web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
957 return;
960 // TODO(mattm): add UI for setting explicit distrust, too.
961 // http://crbug.com/128411
962 net::NSSCertDatabase::ImportCertFailureList not_imported;
963 bool result = certificate_manager_model_->ImportCACerts(
964 selected_cert_list_,
965 trust_ssl * net::NSSCertDatabase::TRUSTED_SSL +
966 trust_email * net::NSSCertDatabase::TRUSTED_EMAIL +
967 trust_obj_sign * net::NSSCertDatabase::TRUSTED_OBJ_SIGN,
968 &not_imported);
969 web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
970 if (!result) {
971 ShowError(
972 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
973 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
974 } else if (!not_imported.empty()) {
975 ShowImportErrors(
976 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
977 not_imported);
979 ImportExportCleanup();
982 void CertificateManagerHandler::Export(const base::ListValue* args) {
983 net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
984 if (!cert)
985 return;
986 ShowCertExportDialog(web_ui()->GetWebContents(), GetParentWindow(), cert);
989 void CertificateManagerHandler::Delete(const base::ListValue* args) {
990 net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
991 if (!cert)
992 return;
993 bool result = certificate_manager_model_->Delete(cert);
994 if (!result) {
995 // TODO(mattm): better error messages?
996 ShowError(
997 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_DELETE_CERT_ERROR_TITLE),
998 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
1002 void CertificateManagerHandler::OnCertificateManagerModelCreated(
1003 scoped_ptr<CertificateManagerModel> model) {
1004 certificate_manager_model_ = model.Pass();
1005 CertificateManagerModelReady();
1008 void CertificateManagerHandler::CertificateManagerModelReady() {
1009 base::FundamentalValue user_db_available_value(
1010 certificate_manager_model_->is_user_db_available());
1011 base::FundamentalValue tpm_available_value(
1012 certificate_manager_model_->is_tpm_available());
1013 web_ui()->CallJavascriptFunction("CertificateManager.onModelReady",
1014 user_db_available_value,
1015 tpm_available_value);
1016 certificate_manager_model_->Refresh();
1019 void CertificateManagerHandler::Populate(const base::ListValue* args) {
1020 if (certificate_manager_model_) {
1021 // Already have a model, the webui must be re-loading. Just re-run the
1022 // webui initialization.
1023 CertificateManagerModelReady();
1024 return;
1027 if (!requested_certificate_manager_model_) {
1028 // Request that a model be created.
1029 CertificateManagerModel::Create(
1030 Profile::FromWebUI(web_ui()),
1031 this,
1032 base::Bind(&CertificateManagerHandler::OnCertificateManagerModelCreated,
1033 weak_ptr_factory_.GetWeakPtr()));
1034 requested_certificate_manager_model_ = true;
1035 return;
1038 // We are already waiting for a CertificateManagerModel to be created, no need
1039 // to do anything.
1042 void CertificateManagerHandler::PopulateTree(
1043 const std::string& tab_name,
1044 net::CertType type,
1045 const net::CertificateList& web_trust_certs) {
1046 const std::string tree_name = tab_name + "-tree";
1048 scoped_ptr<icu::Collator> collator;
1049 UErrorCode error = U_ZERO_ERROR;
1050 collator.reset(
1051 icu::Collator::createInstance(
1052 icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
1053 error));
1054 if (U_FAILURE(error))
1055 collator.reset(NULL);
1056 DictionaryIdComparator comparator(collator.get());
1057 CertificateManagerModel::OrgGroupingMap map;
1059 certificate_manager_model_->FilterAndBuildOrgGroupingMap(type, &map);
1062 base::ListValue* nodes = new base::ListValue;
1063 for (CertificateManagerModel::OrgGroupingMap::iterator i = map.begin();
1064 i != map.end(); ++i) {
1065 // Populate first level (org name).
1066 base::DictionaryValue* dict = new base::DictionaryValue;
1067 dict->SetString(kKeyId, OrgNameToId(i->first));
1068 dict->SetString(kNameId, i->first);
1070 // Populate second level (certs).
1071 base::ListValue* subnodes = new base::ListValue;
1072 for (net::CertificateList::const_iterator org_cert_it = i->second.begin();
1073 org_cert_it != i->second.end(); ++org_cert_it) {
1074 base::DictionaryValue* cert_dict = new base::DictionaryValue;
1075 net::X509Certificate* cert = org_cert_it->get();
1076 cert_dict->SetString(kKeyId, cert_id_map_->CertToId(cert));
1077 cert_dict->SetString(kNameId, certificate_manager_model_->GetColumnText(
1078 *cert, CertificateManagerModel::COL_SUBJECT_NAME));
1079 cert_dict->SetBoolean(
1080 kReadOnlyId,
1081 certificate_manager_model_->cert_db()->IsReadOnly(cert));
1082 // Policy-installed certificates with web trust are trusted.
1083 bool policy_trusted =
1084 IsPolicyInstalledWithWebTrust(web_trust_certs, cert);
1085 cert_dict->SetBoolean(
1086 kUntrustedId,
1087 !policy_trusted &&
1088 certificate_manager_model_->cert_db()->IsUntrusted(cert));
1089 cert_dict->SetBoolean(kPolicyTrustedId, policy_trusted);
1090 // TODO(hshi): This should be determined by testing for PKCS #11
1091 // CKA_EXTRACTABLE attribute. We may need to use the NSS function
1092 // PK11_ReadRawAttribute to do that.
1093 cert_dict->SetBoolean(
1094 kExtractableId,
1095 !certificate_manager_model_->IsHardwareBacked(cert));
1096 // TODO(mattm): Other columns.
1097 subnodes->Append(cert_dict);
1099 std::sort(subnodes->begin(), subnodes->end(), comparator);
1101 dict->Set(kSubNodesId, subnodes);
1102 nodes->Append(dict);
1104 std::sort(nodes->begin(), nodes->end(), comparator);
1106 base::ListValue args;
1107 args.Append(new base::StringValue(tree_name));
1108 args.Append(nodes);
1109 web_ui()->CallJavascriptFunction("CertificateManager.onPopulateTree", args);
1113 void CertificateManagerHandler::ShowError(const std::string& title,
1114 const std::string& error) const {
1115 ScopedVector<const base::Value> args;
1116 args.push_back(new base::StringValue(title));
1117 args.push_back(new base::StringValue(error));
1118 args.push_back(new base::StringValue(l10n_util::GetStringUTF8(IDS_OK)));
1119 args.push_back(base::Value::CreateNullValue().release()); // cancelTitle
1120 args.push_back(base::Value::CreateNullValue().release()); // okCallback
1121 args.push_back(base::Value::CreateNullValue().release()); // cancelCallback
1122 web_ui()->CallJavascriptFunction("AlertOverlay.show", args.get());
1125 void CertificateManagerHandler::ShowImportErrors(
1126 const std::string& title,
1127 const net::NSSCertDatabase::ImportCertFailureList& not_imported) const {
1128 std::string error;
1129 if (selected_cert_list_.size() == 1)
1130 error = l10n_util::GetStringUTF8(
1131 IDS_CERT_MANAGER_IMPORT_SINGLE_NOT_IMPORTED);
1132 else if (not_imported.size() == selected_cert_list_.size())
1133 error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_ALL_NOT_IMPORTED);
1134 else
1135 error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_SOME_NOT_IMPORTED);
1137 base::ListValue cert_error_list;
1138 for (size_t i = 0; i < not_imported.size(); ++i) {
1139 const net::NSSCertDatabase::ImportCertFailure& failure = not_imported[i];
1140 base::DictionaryValue* dict = new base::DictionaryValue;
1141 dict->SetString(kNameId, failure.certificate->subject().GetDisplayName());
1142 dict->SetString(kErrorId, NetErrorToString(failure.net_error));
1143 cert_error_list.Append(dict);
1146 base::StringValue title_value(title);
1147 base::StringValue error_value(error);
1148 web_ui()->CallJavascriptFunction("CertificateImportErrorOverlay.show",
1149 title_value,
1150 error_value,
1151 cert_error_list);
1154 gfx::NativeWindow CertificateManagerHandler::GetParentWindow() const {
1155 return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
1158 } // namespace options