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