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