Home | History | Annotate | Download | only in options
      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 "chrome/browser/ui/webui/certificate_viewer_webui.h"
     27 #include "content/public/browser/browser_thread.h"
     28 #include "content/public/browser/web_contents.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 #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(),
    987                        cert->os_cert_handle());
    988 }
    989 
    990 void CertificateManagerHandler::Delete(const base::ListValue* args) {
    991   net::X509Certificate* cert = cert_id_map_->CallbackArgsToCert(args);
    992   if (!cert)
    993     return;
    994   bool result = certificate_manager_model_->Delete(cert);
    995   if (!result) {
    996     // TODO(mattm): better error messages?
    997     ShowError(
    998         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_DELETE_CERT_ERROR_TITLE),
    999         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
   1000   }
   1001 }
   1002 
   1003 void CertificateManagerHandler::OnCertificateManagerModelCreated(
   1004     scoped_ptr<CertificateManagerModel> model) {
   1005   certificate_manager_model_ = model.Pass();
   1006   CertificateManagerModelReady();
   1007 }
   1008 
   1009 void CertificateManagerHandler::CertificateManagerModelReady() {
   1010   base::FundamentalValue user_db_available_value(
   1011       certificate_manager_model_->is_user_db_available());
   1012   base::FundamentalValue tpm_available_value(
   1013       certificate_manager_model_->is_tpm_available());
   1014   web_ui()->CallJavascriptFunction("CertificateManager.onModelReady",
   1015                                    user_db_available_value,
   1016                                    tpm_available_value);
   1017   certificate_manager_model_->Refresh();
   1018 }
   1019 
   1020 void CertificateManagerHandler::Populate(const base::ListValue* args) {
   1021   if (certificate_manager_model_) {
   1022     // Already have a model, the webui must be re-loading.  Just re-run the
   1023     // webui initialization.
   1024     CertificateManagerModelReady();
   1025     return;
   1026   }
   1027 
   1028   if (!requested_certificate_manager_model_) {
   1029     // Request that a model be created.
   1030     CertificateManagerModel::Create(
   1031         Profile::FromWebUI(web_ui()),
   1032         this,
   1033         base::Bind(&CertificateManagerHandler::OnCertificateManagerModelCreated,
   1034                    weak_ptr_factory_.GetWeakPtr()));
   1035     requested_certificate_manager_model_ = true;
   1036     return;
   1037   }
   1038 
   1039   // We are already waiting for a CertificateManagerModel to be created, no need
   1040   // to do anything.
   1041 }
   1042 
   1043 void CertificateManagerHandler::PopulateTree(
   1044     const std::string& tab_name,
   1045     net::CertType type,
   1046     const net::CertificateList& web_trust_certs) {
   1047   const std::string tree_name = tab_name + "-tree";
   1048 
   1049   scoped_ptr<icu::Collator> collator;
   1050   UErrorCode error = U_ZERO_ERROR;
   1051   collator.reset(
   1052       icu::Collator::createInstance(
   1053           icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
   1054           error));
   1055   if (U_FAILURE(error))
   1056     collator.reset(NULL);
   1057   DictionaryIdComparator comparator(collator.get());
   1058   CertificateManagerModel::OrgGroupingMap map;
   1059 
   1060   certificate_manager_model_->FilterAndBuildOrgGroupingMap(type, &map);
   1061 
   1062   {
   1063     base::ListValue* nodes = new base::ListValue;
   1064     for (CertificateManagerModel::OrgGroupingMap::iterator i = map.begin();
   1065          i != map.end(); ++i) {
   1066       // Populate first level (org name).
   1067       base::DictionaryValue* dict = new base::DictionaryValue;
   1068       dict->SetString(kKeyId, OrgNameToId(i->first));
   1069       dict->SetString(kNameId, i->first);
   1070 
   1071       // Populate second level (certs).
   1072       base::ListValue* subnodes = new base::ListValue;
   1073       for (net::CertificateList::const_iterator org_cert_it = i->second.begin();
   1074            org_cert_it != i->second.end(); ++org_cert_it) {
   1075         base::DictionaryValue* cert_dict = new base::DictionaryValue;
   1076         net::X509Certificate* cert = org_cert_it->get();
   1077         cert_dict->SetString(kKeyId, cert_id_map_->CertToId(cert));
   1078         cert_dict->SetString(kNameId, certificate_manager_model_->GetColumnText(
   1079             *cert, CertificateManagerModel::COL_SUBJECT_NAME));
   1080         cert_dict->SetBoolean(
   1081             kReadOnlyId,
   1082             certificate_manager_model_->cert_db()->IsReadOnly(cert));
   1083         // Policy-installed certificates with web trust are trusted.
   1084         bool policy_trusted =
   1085             IsPolicyInstalledWithWebTrust(web_trust_certs, cert);
   1086         cert_dict->SetBoolean(
   1087             kUntrustedId,
   1088             !policy_trusted &&
   1089                 certificate_manager_model_->cert_db()->IsUntrusted(cert));
   1090         cert_dict->SetBoolean(kPolicyTrustedId, policy_trusted);
   1091         // TODO(hshi): This should be determined by testing for PKCS #11
   1092         // CKA_EXTRACTABLE attribute. We may need to use the NSS function
   1093         // PK11_ReadRawAttribute to do that.
   1094         cert_dict->SetBoolean(
   1095             kExtractableId,
   1096             !certificate_manager_model_->IsHardwareBacked(cert));
   1097         // TODO(mattm): Other columns.
   1098         subnodes->Append(cert_dict);
   1099       }
   1100       std::sort(subnodes->begin(), subnodes->end(), comparator);
   1101 
   1102       dict->Set(kSubNodesId, subnodes);
   1103       nodes->Append(dict);
   1104     }
   1105     std::sort(nodes->begin(), nodes->end(), comparator);
   1106 
   1107     base::ListValue args;
   1108     args.Append(new base::StringValue(tree_name));
   1109     args.Append(nodes);
   1110     web_ui()->CallJavascriptFunction("CertificateManager.onPopulateTree", args);
   1111   }
   1112 }
   1113 
   1114 void CertificateManagerHandler::ShowError(const std::string& title,
   1115                                           const std::string& error) const {
   1116   ScopedVector<const base::Value> args;
   1117   args.push_back(new base::StringValue(title));
   1118   args.push_back(new base::StringValue(error));
   1119   args.push_back(new base::StringValue(l10n_util::GetStringUTF8(IDS_OK)));
   1120   args.push_back(base::Value::CreateNullValue());  // cancelTitle
   1121   args.push_back(base::Value::CreateNullValue());  // okCallback
   1122   args.push_back(base::Value::CreateNullValue());  // cancelCallback
   1123   web_ui()->CallJavascriptFunction("AlertOverlay.show", args.get());
   1124 }
   1125 
   1126 void CertificateManagerHandler::ShowImportErrors(
   1127     const std::string& title,
   1128     const net::NSSCertDatabase::ImportCertFailureList& not_imported) const {
   1129   std::string error;
   1130   if (selected_cert_list_.size() == 1)
   1131     error = l10n_util::GetStringUTF8(
   1132         IDS_CERT_MANAGER_IMPORT_SINGLE_NOT_IMPORTED);
   1133   else if (not_imported.size() == selected_cert_list_.size())
   1134     error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_ALL_NOT_IMPORTED);
   1135   else
   1136     error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_SOME_NOT_IMPORTED);
   1137 
   1138   base::ListValue cert_error_list;
   1139   for (size_t i = 0; i < not_imported.size(); ++i) {
   1140     const net::NSSCertDatabase::ImportCertFailure& failure = not_imported[i];
   1141     base::DictionaryValue* dict = new base::DictionaryValue;
   1142     dict->SetString(kNameId, failure.certificate->subject().GetDisplayName());
   1143     dict->SetString(kErrorId, NetErrorToString(failure.net_error));
   1144     cert_error_list.Append(dict);
   1145   }
   1146 
   1147   base::StringValue title_value(title);
   1148   base::StringValue error_value(error);
   1149   web_ui()->CallJavascriptFunction("CertificateImportErrorOverlay.show",
   1150                                    title_value,
   1151                                    error_value,
   1152                                    cert_error_list);
   1153 }
   1154 
   1155 gfx::NativeWindow CertificateManagerHandler::GetParentWindow() const {
   1156   return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
   1157 }
   1158 
   1159 }  // namespace options
   1160