certificate_manager_handler.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/chromeos/policy/user_network_configuration_updater.h"
37#include "chrome/browser/chromeos/policy/user_network_configuration_updater_factory.h"
38#include "chromeos/dbus/cryptohome_client.h"
39#include "chromeos/dbus/dbus_thread_manager.h"
40#endif
41
42using content::BrowserThread;
43
44namespace {
45
46static const char kKeyId[] = "id";
47static const char kSubNodesId[] = "subnodes";
48static const char kNameId[] = "name";
49static const char kReadOnlyId[] = "readonly";
50static const char kUntrustedId[] = "untrusted";
51static const char kExtractableId[] = "extractable";
52static const char kErrorId[] = "error";
53static 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.)
57enum {
58  EXPORT_PERSONAL_FILE_SELECTED = 1,
59  IMPORT_PERSONAL_FILE_SELECTED,
60  IMPORT_SERVER_FILE_SELECTED,
61  IMPORT_CA_FILE_SELECTED,
62};
63
64std::string OrgNameToId(const std::string& org) {
65  return "org-" + org;
66}
67
68bool 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
77struct 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    base::string16 a_str;
89    base::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
101std::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.
115struct 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.
124bool 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
133namespace options {
134
135///////////////////////////////////////////////////////////////////////////////
136//  CertIdMap
137
138class 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
159std::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
169net::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
177net::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?
196class 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
232CancelableTaskTracker::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
248CancelableTaskTracker::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
271void 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
278void 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
289CertificateManagerHandler::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
297CertificateManagerHandler::~CertificateManagerHandler() {
298}
299
300void 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#endif  // defined(OS_CHROMEOS)
400}
401
402void CertificateManagerHandler::RegisterMessages() {
403  web_ui()->RegisterMessageCallback(
404      "viewCertificate",
405      base::Bind(&CertificateManagerHandler::View, base::Unretained(this)));
406
407  web_ui()->RegisterMessageCallback(
408      "getCaCertificateTrust",
409      base::Bind(&CertificateManagerHandler::GetCATrust,
410                 base::Unretained(this)));
411  web_ui()->RegisterMessageCallback(
412      "editCaCertificateTrust",
413      base::Bind(&CertificateManagerHandler::EditCATrust,
414                 base::Unretained(this)));
415
416  web_ui()->RegisterMessageCallback(
417      "editServerCertificate",
418      base::Bind(&CertificateManagerHandler::EditServer,
419                 base::Unretained(this)));
420
421  web_ui()->RegisterMessageCallback(
422      "cancelImportExportCertificate",
423      base::Bind(&CertificateManagerHandler::CancelImportExportProcess,
424                 base::Unretained(this)));
425
426  web_ui()->RegisterMessageCallback(
427      "exportPersonalCertificate",
428      base::Bind(&CertificateManagerHandler::ExportPersonal,
429                 base::Unretained(this)));
430  web_ui()->RegisterMessageCallback(
431      "exportAllPersonalCertificates",
432      base::Bind(&CertificateManagerHandler::ExportAllPersonal,
433                 base::Unretained(this)));
434  web_ui()->RegisterMessageCallback(
435      "exportPersonalCertificatePasswordSelected",
436      base::Bind(&CertificateManagerHandler::ExportPersonalPasswordSelected,
437                 base::Unretained(this)));
438
439  web_ui()->RegisterMessageCallback(
440      "importPersonalCertificate",
441      base::Bind(&CertificateManagerHandler::StartImportPersonal,
442                 base::Unretained(this)));
443  web_ui()->RegisterMessageCallback(
444      "importPersonalCertificatePasswordSelected",
445      base::Bind(&CertificateManagerHandler::ImportPersonalPasswordSelected,
446                 base::Unretained(this)));
447
448  web_ui()->RegisterMessageCallback(
449      "importCaCertificate",
450      base::Bind(&CertificateManagerHandler::ImportCA,
451                 base::Unretained(this)));
452  web_ui()->RegisterMessageCallback(
453      "importCaCertificateTrustSelected",
454      base::Bind(&CertificateManagerHandler::ImportCATrustSelected,
455                 base::Unretained(this)));
456
457  web_ui()->RegisterMessageCallback(
458      "importServerCertificate",
459      base::Bind(&CertificateManagerHandler::ImportServer,
460                 base::Unretained(this)));
461
462  web_ui()->RegisterMessageCallback(
463      "exportCertificate",
464      base::Bind(&CertificateManagerHandler::Export,
465                 base::Unretained(this)));
466
467  web_ui()->RegisterMessageCallback(
468      "deleteCertificate",
469      base::Bind(&CertificateManagerHandler::Delete,
470                 base::Unretained(this)));
471
472  web_ui()->RegisterMessageCallback(
473      "populateCertificateManager",
474      base::Bind(&CertificateManagerHandler::Populate,
475                 base::Unretained(this)));
476
477#if defined(OS_CHROMEOS)
478  web_ui()->RegisterMessageCallback(
479      "checkTpmTokenReady",
480      base::Bind(&CertificateManagerHandler::CheckTpmTokenReady,
481                 base::Unretained(this)));
482#endif
483}
484
485void CertificateManagerHandler::CertificatesRefreshed() {
486  net::CertificateList web_trusted_certs;
487#if defined(OS_CHROMEOS)
488  policy::UserNetworkConfigurationUpdater* service =
489      policy::UserNetworkConfigurationUpdaterFactory::GetForProfile(
490          Profile::FromWebUI(web_ui()));
491  if (service)
492    service->GetWebTrustedCertificates(&web_trusted_certs);
493#endif
494  PopulateTree("personalCertsTab", net::USER_CERT, web_trusted_certs);
495  PopulateTree("serverCertsTab", net::SERVER_CERT, web_trusted_certs);
496  PopulateTree("caCertsTab", net::CA_CERT, web_trusted_certs);
497  PopulateTree("otherCertsTab", net::OTHER_CERT, web_trusted_certs);
498}
499
500void CertificateManagerHandler::FileSelected(const base::FilePath& path,
501                                             int index,
502                                             void* params) {
503  switch (reinterpret_cast<intptr_t>(params)) {
504    case EXPORT_PERSONAL_FILE_SELECTED:
505      ExportPersonalFileSelected(path);
506      break;
507    case IMPORT_PERSONAL_FILE_SELECTED:
508      ImportPersonalFileSelected(path);
509      break;
510    case IMPORT_SERVER_FILE_SELECTED:
511      ImportServerFileSelected(path);
512      break;
513    case IMPORT_CA_FILE_SELECTED:
514      ImportCAFileSelected(path);
515      break;
516    default:
517      NOTREACHED();
518  }
519}
520
521void CertificateManagerHandler::FileSelectionCanceled(void* params) {
522  switch (reinterpret_cast<intptr_t>(params)) {
523    case EXPORT_PERSONAL_FILE_SELECTED:
524    case IMPORT_PERSONAL_FILE_SELECTED:
525    case IMPORT_SERVER_FILE_SELECTED:
526    case IMPORT_CA_FILE_SELECTED:
527      ImportExportCleanup();
528      break;
529    default:
530      NOTREACHED();
531  }
532}
533
534void CertificateManagerHandler::View(const ListValue* args) {
535  net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
536  if (!cert)
537    return;
538  ShowCertificateViewer(web_ui()->GetWebContents(), GetParentWindow(), cert);
539}
540
541void CertificateManagerHandler::GetCATrust(const ListValue* args) {
542  net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
543  if (!cert) {
544    web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
545    return;
546  }
547
548  net::NSSCertDatabase::TrustBits trust_bits =
549      certificate_manager_model_->cert_db()->GetCertTrust(cert, net::CA_CERT);
550  base::FundamentalValue ssl_value(
551      static_cast<bool>(trust_bits & net::NSSCertDatabase::TRUSTED_SSL));
552  base::FundamentalValue email_value(
553      static_cast<bool>(trust_bits & net::NSSCertDatabase::TRUSTED_EMAIL));
554  base::FundamentalValue obj_sign_value(
555      static_cast<bool>(trust_bits & net::NSSCertDatabase::TRUSTED_OBJ_SIGN));
556  web_ui()->CallJavascriptFunction(
557      "CertificateEditCaTrustOverlay.populateTrust",
558      ssl_value, email_value, obj_sign_value);
559}
560
561void CertificateManagerHandler::EditCATrust(const ListValue* args) {
562  net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
563  bool fail = !cert;
564  bool trust_ssl = false;
565  bool trust_email = false;
566  bool trust_obj_sign = false;
567  fail |= !CallbackArgsToBool(args, 1, &trust_ssl);
568  fail |= !CallbackArgsToBool(args, 2, &trust_email);
569  fail |= !CallbackArgsToBool(args, 3, &trust_obj_sign);
570  if (fail) {
571    LOG(ERROR) << "EditCATrust args fail";
572    web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
573    return;
574  }
575
576  bool result = certificate_manager_model_->SetCertTrust(
577      cert,
578      net::CA_CERT,
579      trust_ssl * net::NSSCertDatabase::TRUSTED_SSL +
580          trust_email * net::NSSCertDatabase::TRUSTED_EMAIL +
581          trust_obj_sign * net::NSSCertDatabase::TRUSTED_OBJ_SIGN);
582  web_ui()->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
583  if (!result) {
584    // TODO(mattm): better error messages?
585    ShowError(
586        l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SET_TRUST_ERROR_TITLE),
587        l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
588  }
589}
590
591void CertificateManagerHandler::EditServer(const ListValue* args) {
592  NOTIMPLEMENTED();
593}
594
595void CertificateManagerHandler::ExportPersonal(const ListValue* args) {
596  net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
597  if (!cert)
598    return;
599
600  selected_cert_list_.push_back(cert);
601
602  ui::SelectFileDialog::FileTypeInfo file_type_info;
603  file_type_info.extensions.resize(1);
604  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
605  file_type_info.extension_description_overrides.push_back(
606      l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
607  file_type_info.include_all_files = true;
608  select_file_dialog_ = ui::SelectFileDialog::Create(
609      this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
610  select_file_dialog_->SelectFile(
611      ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(),
612      base::FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
613      GetParentWindow(),
614      reinterpret_cast<void*>(EXPORT_PERSONAL_FILE_SELECTED));
615}
616
617void CertificateManagerHandler::ExportAllPersonal(const ListValue* args) {
618  NOTIMPLEMENTED();
619}
620
621void CertificateManagerHandler::ExportPersonalFileSelected(
622    const base::FilePath& path) {
623  file_path_ = path;
624  web_ui()->CallJavascriptFunction(
625      "CertificateManager.exportPersonalAskPassword");
626}
627
628void CertificateManagerHandler::ExportPersonalPasswordSelected(
629    const ListValue* args) {
630  if (!args->GetString(0, &password_)) {
631    web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
632    ImportExportCleanup();
633    return;
634  }
635
636  // Currently, we don't support exporting more than one at a time.  If we do,
637  // this would need to either change this to use UnlockSlotsIfNecessary or
638  // change UnlockCertSlotIfNecessary to take a CertificateList.
639  DCHECK_EQ(selected_cert_list_.size(), 1U);
640
641  // TODO(mattm): do something smarter about non-extractable keys
642  chrome::UnlockCertSlotIfNecessary(
643      selected_cert_list_[0].get(),
644      chrome::kCryptoModulePasswordCertExport,
645      std::string(),  // unused.
646      GetParentWindow(),
647      base::Bind(&CertificateManagerHandler::ExportPersonalSlotsUnlocked,
648                 base::Unretained(this)));
649}
650
651void CertificateManagerHandler::ExportPersonalSlotsUnlocked() {
652  std::string output;
653  int num_exported = certificate_manager_model_->cert_db()->ExportToPKCS12(
654      selected_cert_list_,
655      password_,
656      &output);
657  if (!num_exported) {
658    web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
659    ShowError(
660        l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
661        l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
662    ImportExportCleanup();
663    return;
664  }
665  file_access_provider_->StartWrite(
666      file_path_,
667      output,
668      base::Bind(&CertificateManagerHandler::ExportPersonalFileWritten,
669                 base::Unretained(this)),
670      &tracker_);
671}
672
673void CertificateManagerHandler::ExportPersonalFileWritten(
674    const int* write_errno, const int* bytes_written) {
675  web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
676  ImportExportCleanup();
677  if (*write_errno) {
678    ShowError(
679        l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
680        l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_WRITE_ERROR_FORMAT,
681                                  UTF8ToUTF16(safe_strerror(*write_errno))));
682  }
683}
684
685void CertificateManagerHandler::StartImportPersonal(const ListValue* args) {
686  ui::SelectFileDialog::FileTypeInfo file_type_info;
687  if (!args->GetBoolean(0, &use_hardware_backed_)) {
688    // Unable to retrieve the hardware backed attribute from the args,
689    // so bail.
690    web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
691    ImportExportCleanup();
692    return;
693  }
694  file_type_info.extensions.resize(1);
695  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
696  file_type_info.extension_description_overrides.push_back(
697      l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
698  file_type_info.include_all_files = true;
699  select_file_dialog_ = ui::SelectFileDialog::Create(
700      this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
701  select_file_dialog_->SelectFile(
702      ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(),
703      base::FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
704      GetParentWindow(),
705      reinterpret_cast<void*>(IMPORT_PERSONAL_FILE_SELECTED));
706}
707
708void CertificateManagerHandler::ImportPersonalFileSelected(
709    const base::FilePath& path) {
710  file_path_ = path;
711  web_ui()->CallJavascriptFunction(
712      "CertificateManager.importPersonalAskPassword");
713}
714
715void CertificateManagerHandler::ImportPersonalPasswordSelected(
716    const ListValue* args) {
717  if (!args->GetString(0, &password_)) {
718    web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
719    ImportExportCleanup();
720    return;
721  }
722  file_access_provider_->StartRead(
723      file_path_,
724      base::Bind(&CertificateManagerHandler::ImportPersonalFileRead,
725                 base::Unretained(this)),
726      &tracker_);
727}
728
729void CertificateManagerHandler::ImportPersonalFileRead(
730    const int* read_errno, const std::string* data) {
731  if (*read_errno) {
732    ImportExportCleanup();
733    web_ui()->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
734    ShowError(
735        l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
736        l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
737                                  UTF8ToUTF16(safe_strerror(*read_errno))));
738    return;
739  }
740
741  file_data_ = *data;
742
743  if (use_hardware_backed_) {
744    module_ = certificate_manager_model_->cert_db()->GetPrivateModule();
745  } else {
746    module_ = certificate_manager_model_->cert_db()->GetPublicModule();
747  }
748
749  net::CryptoModuleList modules;
750  modules.push_back(module_);
751  chrome::UnlockSlotsIfNecessary(
752      modules,
753      chrome::kCryptoModulePasswordCertImport,
754      std::string(),  // unused.
755      GetParentWindow(),
756      base::Bind(&CertificateManagerHandler::ImportPersonalSlotUnlocked,
757                 base::Unretained(this)));
758}
759
760void 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
797void CertificateManagerHandler::CancelImportExportProcess(
798    const ListValue* args) {
799  ImportExportCleanup();
800}
801
802void 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
817void 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
828void 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
838void 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
877void 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
887void 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
897void 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
929void 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
966void 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
974void 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
987void CertificateManagerHandler::Populate(const ListValue* args) {
988  certificate_manager_model_->Refresh();
989}
990
991void 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
1062void 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
1074void 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)
1104void 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
1112void 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
1122gfx::NativeWindow CertificateManagerHandler::GetParentWindow() const {
1123  return web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow();
1124}
1125
1126}  // namespace options
1127