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