Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2011 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 "base/file_util.h"  // for FileAccessProvider
      8 #include "base/memory/scoped_vector.h"
      9 #include "base/safe_strerror_posix.h"
     10 #include "base/string_number_conversions.h"
     11 #include "base/values.h"
     12 #include "chrome/browser/browser_process.h"
     13 #include "chrome/browser/ui/crypto_module_password_dialog.h"
     14 #include "chrome/browser/ui/gtk/certificate_dialogs.h"
     15 #include "content/browser/browser_thread.h"  // for FileAccessProvider
     16 #include "content/browser/certificate_viewer.h"
     17 #include "content/browser/tab_contents/tab_contents.h"
     18 #include "content/browser/tab_contents/tab_contents_view.h"
     19 #include "grit/generated_resources.h"
     20 #include "net/base/crypto_module.h"
     21 #include "net/base/x509_certificate.h"
     22 #include "ui/base/l10n/l10n_util.h"
     23 #include "ui/base/l10n/l10n_util_collator.h"
     24 
     25 #if defined(OS_CHROMEOS)
     26 #include "chrome/browser/chromeos/cros/cros_library.h"
     27 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
     28 #endif
     29 
     30 namespace {
     31 
     32 static const char kKeyId[] = "id";
     33 static const char kSubNodesId[] = "subnodes";
     34 static const char kNameId[] = "name";
     35 static const char kReadOnlyId[] = "readonly";
     36 static const char kIconId[] = "icon";
     37 static const char kSecurityDeviceId[] = "device";
     38 static const char kErrorId[] = "error";
     39 
     40 // Enumeration of different callers of SelectFile.  (Start counting at 1 so
     41 // if SelectFile is accidentally called with params=NULL it won't match any.)
     42 enum {
     43   EXPORT_PERSONAL_FILE_SELECTED = 1,
     44   IMPORT_PERSONAL_FILE_SELECTED,
     45   IMPORT_SERVER_FILE_SELECTED,
     46   IMPORT_CA_FILE_SELECTED,
     47 };
     48 
     49 // TODO(mattm): These are duplicated from cookies_view_handler.cc
     50 // Encodes a pointer value into a hex string.
     51 std::string PointerToHexString(const void* pointer) {
     52   return base::HexEncode(&pointer, sizeof(pointer));
     53 }
     54 
     55 // Decodes a pointer from a hex string.
     56 void* HexStringToPointer(const std::string& str) {
     57   std::vector<uint8> buffer;
     58   if (!base::HexStringToBytes(str, &buffer) ||
     59       buffer.size() != sizeof(void*)) {
     60     return NULL;
     61   }
     62 
     63   return *reinterpret_cast<void**>(&buffer[0]);
     64 }
     65 
     66 std::string OrgNameToId(const std::string& org) {
     67   return "org-" + org;
     68 }
     69 
     70 std::string CertToId(const net::X509Certificate& cert) {
     71   return "cert-" + PointerToHexString(&cert);
     72 }
     73 
     74 net::X509Certificate* IdToCert(const std::string& id) {
     75   if (!StartsWithASCII(id, "cert-", true))
     76     return NULL;
     77   return reinterpret_cast<net::X509Certificate*>(
     78       HexStringToPointer(id.substr(5)));
     79 }
     80 
     81 net::X509Certificate* CallbackArgsToCert(const ListValue* args) {
     82   std::string node_id;
     83   if (!args->GetString(0, &node_id)){
     84     return NULL;
     85   }
     86   net::X509Certificate* cert = IdToCert(node_id);
     87   if (!cert) {
     88     NOTREACHED();
     89     return NULL;
     90   }
     91   return cert;
     92 }
     93 
     94 bool CallbackArgsToBool(const ListValue* args, int index, bool* result) {
     95   std::string string_value;
     96   if (!args->GetString(index, &string_value))
     97     return false;
     98 
     99   *result = string_value[0] == 't';
    100   return true;
    101 }
    102 
    103 struct DictionaryIdComparator {
    104   explicit DictionaryIdComparator(icu::Collator* collator)
    105       : collator_(collator) {
    106   }
    107 
    108   bool operator()(const Value* a,
    109                   const Value* b) const {
    110     DCHECK(a->GetType() == Value::TYPE_DICTIONARY);
    111     DCHECK(b->GetType() == Value::TYPE_DICTIONARY);
    112     const DictionaryValue* a_dict = reinterpret_cast<const DictionaryValue*>(a);
    113     const DictionaryValue* b_dict = reinterpret_cast<const DictionaryValue*>(b);
    114     string16 a_str;
    115     string16 b_str;
    116     a_dict->GetString(kNameId, &a_str);
    117     b_dict->GetString(kNameId, &b_str);
    118     if (collator_ == NULL)
    119       return a_str < b_str;
    120     return l10n_util::CompareString16WithCollator(
    121         collator_, a_str, b_str) == UCOL_LESS;
    122   }
    123 
    124   icu::Collator* collator_;
    125 };
    126 
    127 std::string NetErrorToString(int net_error) {
    128   switch (net_error) {
    129     // TODO(mattm): handle more cases.
    130     case net::ERR_IMPORT_CA_CERT_NOT_CA:
    131       return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_ERROR_NOT_CA);
    132     default:
    133       return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR);
    134   }
    135 }
    136 
    137 }  // namespace
    138 
    139 ///////////////////////////////////////////////////////////////////////////////
    140 //  FileAccessProvider
    141 
    142 // TODO(mattm): Move to some shared location?
    143 class FileAccessProvider
    144     : public base::RefCountedThreadSafe<FileAccessProvider>,
    145       public CancelableRequestProvider {
    146  public:
    147   // Reports 0 on success or errno on failure, and the data of the file upon
    148   // success.
    149   // TODO(mattm): don't pass std::string by value.. could use RefCountedBytes
    150   // but it's a vector.  Maybe do the derive from CancelableRequest thing
    151   // described in cancelable_request.h?
    152   typedef Callback2<int, std::string>::Type ReadCallback;
    153 
    154   // Reports 0 on success or errno on failure, and the number of bytes written,
    155   // on success.
    156   typedef Callback2<int, int>::Type WriteCallback;
    157 
    158   Handle StartRead(const FilePath& path,
    159                    CancelableRequestConsumerBase* consumer,
    160                    ReadCallback* callback);
    161   Handle StartWrite(const FilePath& path,
    162                     const std::string& data,
    163                     CancelableRequestConsumerBase* consumer,
    164                     WriteCallback* callback);
    165 
    166  private:
    167   void DoRead(scoped_refptr<CancelableRequest<ReadCallback> > request,
    168               FilePath path);
    169   void DoWrite(scoped_refptr<CancelableRequest<WriteCallback> > request,
    170               FilePath path,
    171               std::string data);
    172 };
    173 
    174 CancelableRequestProvider::Handle FileAccessProvider::StartRead(
    175     const FilePath& path,
    176     CancelableRequestConsumerBase* consumer,
    177     FileAccessProvider::ReadCallback* callback) {
    178   scoped_refptr<CancelableRequest<ReadCallback> > request(
    179       new CancelableRequest<ReadCallback>(callback));
    180   AddRequest(request, consumer);
    181 
    182   // Send the parameters and the request to the file thread.
    183   BrowserThread::PostTask(
    184       BrowserThread::FILE, FROM_HERE,
    185       NewRunnableMethod(this, &FileAccessProvider::DoRead, request, path));
    186 
    187   // The handle will have been set by AddRequest.
    188   return request->handle();
    189 }
    190 
    191 CancelableRequestProvider::Handle FileAccessProvider::StartWrite(
    192     const FilePath& path,
    193     const std::string& data,
    194     CancelableRequestConsumerBase* consumer,
    195     WriteCallback* callback) {
    196   scoped_refptr<CancelableRequest<WriteCallback> > request(
    197       new CancelableRequest<WriteCallback>(callback));
    198   AddRequest(request, consumer);
    199 
    200   // Send the parameters and the request to the file thWrite.
    201   BrowserThread::PostTask(
    202       BrowserThread::FILE, FROM_HERE,
    203       NewRunnableMethod(
    204           this, &FileAccessProvider::DoWrite, request, path, data));
    205 
    206   // The handle will have been set by AddRequest.
    207   return request->handle();
    208 }
    209 
    210 void FileAccessProvider::DoRead(
    211     scoped_refptr<CancelableRequest<ReadCallback> > request,
    212     FilePath path) {
    213   if (request->canceled())
    214     return;
    215 
    216   std::string data;
    217   VLOG(1) << "DoRead starting read";
    218   bool success = file_util::ReadFileToString(path, &data);
    219   int saved_errno = success ? 0 : errno;
    220   VLOG(1) << "DoRead done read: " << success << " " << data.size();
    221   request->ForwardResult(ReadCallback::TupleType(saved_errno, data));
    222 }
    223 
    224 void FileAccessProvider::DoWrite(
    225     scoped_refptr<CancelableRequest<WriteCallback> > request,
    226     FilePath path,
    227     std::string data) {
    228   VLOG(1) << "DoWrite starting write";
    229   int bytes_written = file_util::WriteFile(path, data.data(), data.size());
    230   int saved_errno = bytes_written >= 0 ? 0 : errno;
    231   VLOG(1) << "DoWrite done write " << bytes_written;
    232 
    233   if (request->canceled())
    234     return;
    235 
    236   request->ForwardResult(WriteCallback::TupleType(saved_errno, bytes_written));
    237 }
    238 
    239 ///////////////////////////////////////////////////////////////////////////////
    240 //  CertificateManagerHandler
    241 
    242 CertificateManagerHandler::CertificateManagerHandler()
    243     : file_access_provider_(new FileAccessProvider) {
    244   certificate_manager_model_.reset(new CertificateManagerModel(this));
    245 }
    246 
    247 CertificateManagerHandler::~CertificateManagerHandler() {
    248 }
    249 
    250 void CertificateManagerHandler::GetLocalizedValues(
    251     DictionaryValue* localized_strings) {
    252   DCHECK(localized_strings);
    253 
    254   RegisterTitle(localized_strings, "certificateManagerPage",
    255                 IDS_CERTIFICATE_MANAGER_TITLE);
    256 
    257   // Tabs.
    258   localized_strings->SetString("personalCertsTabTitle",
    259       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PERSONAL_CERTS_TAB_LABEL));
    260   localized_strings->SetString("serverCertsTabTitle",
    261       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_CERTS_TAB_LABEL));
    262   localized_strings->SetString("caCertsTabTitle",
    263       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CERT_AUTHORITIES_TAB_LABEL));
    264   localized_strings->SetString("unknownCertsTabTitle",
    265       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TAB_LABEL));
    266 
    267   // Tab descriptions.
    268   localized_strings->SetString("personalCertsTabDescription",
    269       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_USER_TREE_DESCRIPTION));
    270   localized_strings->SetString("serverCertsTabDescription",
    271       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_TREE_DESCRIPTION));
    272   localized_strings->SetString("caCertsTabDescription",
    273       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_AUTHORITIES_TREE_DESCRIPTION));
    274   localized_strings->SetString("unknownCertsTabDescription",
    275       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TREE_DESCRIPTION));
    276 
    277   // Tree columns.
    278   localized_strings->SetString("certNameColumn",
    279       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_NAME_COLUMN_LABEL));
    280   localized_strings->SetString("certDeviceColumn",
    281       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DEVICE_COLUMN_LABEL));
    282   localized_strings->SetString("certSerialColumn",
    283       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERIAL_NUMBER_COLUMN_LABEL));
    284   localized_strings->SetString("certExpiresColumn",
    285       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPIRES_COLUMN_LABEL));
    286 
    287   // Buttons.
    288   localized_strings->SetString("view_certificate",
    289       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_VIEW_CERT_BUTTON));
    290   localized_strings->SetString("import_certificate",
    291       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_BUTTON));
    292   localized_strings->SetString("export_certificate",
    293       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_BUTTON));
    294   localized_strings->SetString("export_all_certificates",
    295       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_ALL_BUTTON));
    296   localized_strings->SetString("edit_certificate",
    297       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_BUTTON));
    298   localized_strings->SetString("delete_certificate",
    299       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_BUTTON));
    300 
    301   // Certificate Delete overlay strings.
    302   localized_strings->SetString("personalCertsTabDeleteConfirm",
    303       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_FORMAT));
    304   localized_strings->SetString("personalCertsTabDeleteImpact",
    305       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_DESCRIPTION));
    306   localized_strings->SetString("serverCertsTabDeleteConfirm",
    307       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_FORMAT));
    308   localized_strings->SetString("serverCertsTabDeleteImpact",
    309       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_DESCRIPTION));
    310   localized_strings->SetString("caCertsTabDeleteConfirm",
    311       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_FORMAT));
    312   localized_strings->SetString("caCertsTabDeleteImpact",
    313       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_DESCRIPTION));
    314   localized_strings->SetString("unknownCertsTabDeleteConfirm",
    315       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_UNKNOWN_FORMAT));
    316   localized_strings->SetString("unknownCertsTabDeleteImpact", "");
    317 
    318   // Certificate Restore overlay strings.
    319   localized_strings->SetString("certificateRestorePasswordDescription",
    320       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_RESTORE_PASSWORD_DESC));
    321   localized_strings->SetString("certificatePasswordLabel",
    322       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PASSWORD_LABEL));
    323 
    324   // Personal Certificate Export overlay strings.
    325   localized_strings->SetString("certificateExportPasswordDescription",
    326       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_DESC));
    327   localized_strings->SetString("certificateExportPasswordHelp",
    328       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_HELP));
    329   localized_strings->SetString("certificateConfirmPasswordLabel",
    330       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CONFIRM_PASSWORD_LABEL));
    331 
    332   // Edit CA Trust & Import CA overlay strings.
    333   localized_strings->SetString("certificateEditTrustLabel",
    334       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_TRUST_LABEL));
    335   localized_strings->SetString("certificateEditCaTrustDescriptionFormat",
    336       l10n_util::GetStringUTF16(
    337           IDS_CERT_MANAGER_EDIT_CA_TRUST_DESCRIPTION_FORMAT));
    338   localized_strings->SetString("certificateImportCaDescriptionFormat",
    339       l10n_util::GetStringUTF16(
    340           IDS_CERT_MANAGER_IMPORT_CA_DESCRIPTION_FORMAT));
    341   localized_strings->SetString("certificateCaTrustSSLLabel",
    342       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_SSL_LABEL));
    343   localized_strings->SetString("certificateCaTrustEmailLabel",
    344       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_EMAIL_LABEL));
    345   localized_strings->SetString("certificateCaTrustObjSignLabel",
    346       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_OBJSIGN_LABEL));
    347   localized_strings->SetString("certificateImportErrorFormat",
    348       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_ERROR_FORMAT));
    349 
    350 #if defined(OS_CHROMEOS)
    351   localized_strings->SetString("importAndBindCertificate",
    352       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_AND_BIND_BUTTON));
    353   localized_strings->SetString("hardwareBackedKeyFormat",
    354       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT));
    355   localized_strings->SetString("chromeOSDeviceName",
    356       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
    357 #endif  // defined(OS_CHROMEOS)
    358 }
    359 
    360 void CertificateManagerHandler::RegisterMessages() {
    361   web_ui_->RegisterMessageCallback("viewCertificate",
    362       NewCallback(this, &CertificateManagerHandler::View));
    363 
    364   web_ui_->RegisterMessageCallback("getCaCertificateTrust",
    365       NewCallback(this, &CertificateManagerHandler::GetCATrust));
    366   web_ui_->RegisterMessageCallback("editCaCertificateTrust",
    367       NewCallback(this, &CertificateManagerHandler::EditCATrust));
    368 
    369   web_ui_->RegisterMessageCallback("editServerCertificate",
    370       NewCallback(this, &CertificateManagerHandler::EditServer));
    371 
    372   web_ui_->RegisterMessageCallback("cancelImportExportCertificate",
    373       NewCallback(this, &CertificateManagerHandler::CancelImportExportProcess));
    374 
    375   web_ui_->RegisterMessageCallback("exportPersonalCertificate",
    376       NewCallback(this, &CertificateManagerHandler::ExportPersonal));
    377   web_ui_->RegisterMessageCallback("exportAllPersonalCertificates",
    378       NewCallback(this, &CertificateManagerHandler::ExportAllPersonal));
    379   web_ui_->RegisterMessageCallback("exportPersonalCertificatePasswordSelected",
    380       NewCallback(this,
    381                   &CertificateManagerHandler::ExportPersonalPasswordSelected));
    382 
    383   web_ui_->RegisterMessageCallback("importPersonalCertificate",
    384       NewCallback(this, &CertificateManagerHandler::StartImportPersonal));
    385   web_ui_->RegisterMessageCallback("importPersonalCertificatePasswordSelected",
    386       NewCallback(this,
    387                   &CertificateManagerHandler::ImportPersonalPasswordSelected));
    388 
    389   web_ui_->RegisterMessageCallback("importCaCertificate",
    390       NewCallback(this, &CertificateManagerHandler::ImportCA));
    391   web_ui_->RegisterMessageCallback("importCaCertificateTrustSelected",
    392       NewCallback(this, &CertificateManagerHandler::ImportCATrustSelected));
    393 
    394   web_ui_->RegisterMessageCallback("importServerCertificate",
    395       NewCallback(this, &CertificateManagerHandler::ImportServer));
    396 
    397   web_ui_->RegisterMessageCallback("exportCertificate",
    398       NewCallback(this, &CertificateManagerHandler::Export));
    399 
    400   web_ui_->RegisterMessageCallback("deleteCertificate",
    401       NewCallback(this, &CertificateManagerHandler::Delete));
    402 
    403   web_ui_->RegisterMessageCallback("populateCertificateManager",
    404       NewCallback(this, &CertificateManagerHandler::Populate));
    405 
    406 #if defined(OS_CHROMEOS)
    407   web_ui_->RegisterMessageCallback("checkTpmTokenReady",
    408       NewCallback(this, &CertificateManagerHandler::CheckTpmTokenReady));
    409 #endif
    410 }
    411 
    412 void CertificateManagerHandler::CertificatesRefreshed() {
    413   PopulateTree("personalCertsTab", net::USER_CERT);
    414   PopulateTree("serverCertsTab", net::SERVER_CERT);
    415   PopulateTree("caCertsTab", net::CA_CERT);
    416   PopulateTree("otherCertsTab", net::UNKNOWN_CERT);
    417   VLOG(1) << "populating finished";
    418 }
    419 
    420 void CertificateManagerHandler::FileSelected(const FilePath& path, int index,
    421                                              void* params) {
    422   switch (reinterpret_cast<intptr_t>(params)) {
    423     case EXPORT_PERSONAL_FILE_SELECTED:
    424       ExportPersonalFileSelected(path);
    425       break;
    426     case IMPORT_PERSONAL_FILE_SELECTED:
    427       ImportPersonalFileSelected(path);
    428       break;
    429     case IMPORT_SERVER_FILE_SELECTED:
    430       ImportServerFileSelected(path);
    431       break;
    432     case IMPORT_CA_FILE_SELECTED:
    433       ImportCAFileSelected(path);
    434       break;
    435     default:
    436       NOTREACHED();
    437   }
    438 }
    439 
    440 void CertificateManagerHandler::FileSelectionCanceled(void* params) {
    441   switch (reinterpret_cast<intptr_t>(params)) {
    442     case EXPORT_PERSONAL_FILE_SELECTED:
    443     case IMPORT_PERSONAL_FILE_SELECTED:
    444     case IMPORT_SERVER_FILE_SELECTED:
    445     case IMPORT_CA_FILE_SELECTED:
    446       ImportExportCleanup();
    447       break;
    448     default:
    449       NOTREACHED();
    450   }
    451 }
    452 
    453 void CertificateManagerHandler::View(const ListValue* args) {
    454   net::X509Certificate* cert = CallbackArgsToCert(args);
    455   if (!cert)
    456     return;
    457   ShowCertificateViewer(GetParentWindow(), cert);
    458 }
    459 
    460 void CertificateManagerHandler::GetCATrust(const ListValue* args) {
    461   net::X509Certificate* cert = CallbackArgsToCert(args);
    462   if (!cert) {
    463     web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
    464     return;
    465   }
    466 
    467   int trust = certificate_manager_model_->cert_db().GetCertTrust(
    468       cert, net::CA_CERT);
    469   FundamentalValue ssl_value(bool(trust & net::CertDatabase::TRUSTED_SSL));
    470   FundamentalValue email_value(bool(trust & net::CertDatabase::TRUSTED_EMAIL));
    471   FundamentalValue obj_sign_value(
    472       bool(trust & net::CertDatabase::TRUSTED_OBJ_SIGN));
    473   web_ui_->CallJavascriptFunction(
    474       "CertificateEditCaTrustOverlay.populateTrust",
    475       ssl_value, email_value, obj_sign_value);
    476 }
    477 
    478 void CertificateManagerHandler::EditCATrust(const ListValue* args) {
    479   net::X509Certificate* cert = CallbackArgsToCert(args);
    480   bool fail = !cert;
    481   bool trust_ssl = false;
    482   bool trust_email = false;
    483   bool trust_obj_sign = false;
    484   fail |= !CallbackArgsToBool(args, 1, &trust_ssl);
    485   fail |= !CallbackArgsToBool(args, 2, &trust_email);
    486   fail |= !CallbackArgsToBool(args, 3, &trust_obj_sign);
    487   if (fail) {
    488     LOG(ERROR) << "EditCATrust args fail";
    489     web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
    490     return;
    491   }
    492 
    493   bool result = certificate_manager_model_->SetCertTrust(
    494       cert,
    495       net::CA_CERT,
    496       trust_ssl * net::CertDatabase::TRUSTED_SSL +
    497           trust_email * net::CertDatabase::TRUSTED_EMAIL +
    498           trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN);
    499   web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
    500   if (!result) {
    501     // TODO(mattm): better error messages?
    502     ShowError(
    503         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SET_TRUST_ERROR_TITLE),
    504         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
    505   }
    506 }
    507 
    508 void CertificateManagerHandler::EditServer(const ListValue* args) {
    509   NOTIMPLEMENTED();
    510 }
    511 
    512 void CertificateManagerHandler::ExportPersonal(const ListValue* args) {
    513   net::X509Certificate* cert = CallbackArgsToCert(args);
    514   if (!cert)
    515     return;
    516 
    517   selected_cert_list_.push_back(cert);
    518 
    519   SelectFileDialog::FileTypeInfo file_type_info;
    520   file_type_info.extensions.resize(1);
    521   file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
    522   file_type_info.extension_description_overrides.push_back(
    523       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
    524   file_type_info.include_all_files = true;
    525   select_file_dialog_ = SelectFileDialog::Create(this);
    526   select_file_dialog_->SelectFile(
    527       SelectFileDialog::SELECT_SAVEAS_FILE, string16(),
    528       FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
    529       web_ui_->tab_contents(), GetParentWindow(),
    530       reinterpret_cast<void*>(EXPORT_PERSONAL_FILE_SELECTED));
    531 }
    532 
    533 void CertificateManagerHandler::ExportAllPersonal(const ListValue* args) {
    534   NOTIMPLEMENTED();
    535 }
    536 
    537 void CertificateManagerHandler::ExportPersonalFileSelected(
    538     const FilePath& path) {
    539   file_path_ = path;
    540   web_ui_->CallJavascriptFunction(
    541       "CertificateManager.exportPersonalAskPassword");
    542 }
    543 
    544 void CertificateManagerHandler::ExportPersonalPasswordSelected(
    545     const ListValue* args) {
    546   if (!args->GetString(0, &password_)){
    547     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
    548     ImportExportCleanup();
    549     return;
    550   }
    551 
    552   // Currently, we don't support exporting more than one at a time.  If we do,
    553   // this would need to either change this to use UnlockSlotsIfNecessary or
    554   // change UnlockCertSlotIfNecessary to take a CertificateList.
    555   DCHECK_EQ(selected_cert_list_.size(), 1U);
    556 
    557   // TODO(mattm): do something smarter about non-extractable keys
    558   browser::UnlockCertSlotIfNecessary(
    559       selected_cert_list_[0].get(),
    560       browser::kCryptoModulePasswordCertExport,
    561       "",  // unused.
    562       NewCallback(this,
    563                   &CertificateManagerHandler::ExportPersonalSlotsUnlocked));
    564 }
    565 
    566 void CertificateManagerHandler::ExportPersonalSlotsUnlocked() {
    567   std::string output;
    568   int num_exported = certificate_manager_model_->cert_db().ExportToPKCS12(
    569       selected_cert_list_,
    570       password_,
    571       &output);
    572   if (!num_exported) {
    573     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
    574     ShowError(
    575         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
    576         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
    577     ImportExportCleanup();
    578     return;
    579   }
    580   file_access_provider_->StartWrite(
    581       file_path_,
    582       output,
    583       &consumer_,
    584       NewCallback(this, &CertificateManagerHandler::ExportPersonalFileWritten));
    585 }
    586 
    587 void CertificateManagerHandler::ExportPersonalFileWritten(int write_errno,
    588                                                           int bytes_written) {
    589   web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
    590   ImportExportCleanup();
    591   if (write_errno) {
    592     ShowError(
    593         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
    594         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_WRITE_ERROR_FORMAT,
    595                                   UTF8ToUTF16(safe_strerror(write_errno))));
    596   }
    597 }
    598 
    599 void CertificateManagerHandler::StartImportPersonal(const ListValue* args) {
    600   SelectFileDialog::FileTypeInfo file_type_info;
    601   if (!args->GetBoolean(0, &use_hardware_backed_)){
    602     // Unable to retrieve the hardware backed attribute from the args,
    603     // so bail.
    604     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
    605     ImportExportCleanup();
    606     return;
    607   }
    608   file_type_info.extensions.resize(1);
    609   file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
    610   file_type_info.extension_description_overrides.push_back(
    611       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
    612   file_type_info.include_all_files = true;
    613   select_file_dialog_ = SelectFileDialog::Create(this);
    614   select_file_dialog_->SelectFile(
    615       SelectFileDialog::SELECT_OPEN_FILE, string16(),
    616       FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
    617       web_ui_->tab_contents(), GetParentWindow(),
    618       reinterpret_cast<void*>(IMPORT_PERSONAL_FILE_SELECTED));
    619 }
    620 
    621 void CertificateManagerHandler::ImportPersonalFileSelected(
    622     const FilePath& path) {
    623   file_path_ = path;
    624   web_ui_->CallJavascriptFunction(
    625       "CertificateManager.importPersonalAskPassword");
    626 }
    627 
    628 void CertificateManagerHandler::ImportPersonalPasswordSelected(
    629     const ListValue* args) {
    630   if (!args->GetString(0, &password_)){
    631     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
    632     ImportExportCleanup();
    633     return;
    634   }
    635   file_access_provider_->StartRead(
    636       file_path_,
    637       &consumer_,
    638       NewCallback(this, &CertificateManagerHandler::ImportPersonalFileRead));
    639 }
    640 
    641 void CertificateManagerHandler::ImportPersonalFileRead(
    642     int read_errno, std::string data) {
    643   if (read_errno) {
    644     ImportExportCleanup();
    645     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
    646     ShowError(
    647         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
    648         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
    649                                   UTF8ToUTF16(safe_strerror(read_errno))));
    650     return;
    651   }
    652 
    653   file_data_ = data;
    654 
    655   if (use_hardware_backed_) {
    656     module_ = certificate_manager_model_->cert_db().GetPrivateModule();
    657   } else {
    658     module_ = certificate_manager_model_->cert_db().GetPublicModule();
    659   }
    660 
    661   net::CryptoModuleList modules;
    662   modules.push_back(module_);
    663   browser::UnlockSlotsIfNecessary(
    664       modules,
    665       browser::kCryptoModulePasswordCertImport,
    666       "",  // unused.
    667       NewCallback(this,
    668                   &CertificateManagerHandler::ImportPersonalSlotUnlocked));
    669 }
    670 
    671 void CertificateManagerHandler::ImportPersonalSlotUnlocked() {
    672   int result = certificate_manager_model_->ImportFromPKCS12(
    673       module_, file_data_, password_);
    674   ImportExportCleanup();
    675   web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
    676   switch (result) {
    677     case net::OK:
    678       break;
    679     case net::ERR_PKCS12_IMPORT_BAD_PASSWORD:
    680       ShowError(
    681           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
    682           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_BAD_PASSWORD));
    683       // TODO(mattm): if the error was a bad password, we should reshow the
    684       // password dialog after the user dismisses the error dialog.
    685       break;
    686     default:
    687       ShowError(
    688           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
    689           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
    690       break;
    691   }
    692 }
    693 
    694 void CertificateManagerHandler::CancelImportExportProcess(
    695     const ListValue* args) {
    696   ImportExportCleanup();
    697 }
    698 
    699 void CertificateManagerHandler::ImportExportCleanup() {
    700   file_path_.clear();
    701   password_.clear();
    702   file_data_.clear();
    703   use_hardware_backed_ = false;
    704   selected_cert_list_.clear();
    705   module_ = NULL;
    706 
    707   // There may be pending file dialogs, we need to tell them that we've gone
    708   // away so they don't try and call back to us.
    709   if (select_file_dialog_.get())
    710     select_file_dialog_->ListenerDestroyed();
    711   select_file_dialog_ = NULL;
    712 }
    713 
    714 void CertificateManagerHandler::ImportServer(const ListValue* args) {
    715   select_file_dialog_ = SelectFileDialog::Create(this);
    716   ShowCertSelectFileDialog(
    717       select_file_dialog_.get(),
    718       SelectFileDialog::SELECT_OPEN_FILE,
    719       FilePath(),
    720       web_ui_->tab_contents(),
    721       GetParentWindow(),
    722       reinterpret_cast<void*>(IMPORT_SERVER_FILE_SELECTED));
    723 }
    724 
    725 void CertificateManagerHandler::ImportServerFileSelected(const FilePath& path) {
    726   file_path_ = path;
    727   file_access_provider_->StartRead(
    728       file_path_,
    729       &consumer_,
    730       NewCallback(this, &CertificateManagerHandler::ImportServerFileRead));
    731 }
    732 
    733 void CertificateManagerHandler::ImportServerFileRead(int read_errno,
    734                                                      std::string data) {
    735   if (read_errno) {
    736     ImportExportCleanup();
    737     ShowError(
    738         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
    739         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
    740                                   UTF8ToUTF16(safe_strerror(read_errno))));
    741     return;
    742   }
    743 
    744   selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
    745           data.data(), data.size(), net::X509Certificate::FORMAT_AUTO);
    746   if (selected_cert_list_.empty()) {
    747     ImportExportCleanup();
    748     ShowError(
    749         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
    750         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
    751     return;
    752   }
    753 
    754   net::CertDatabase::ImportCertFailureList not_imported;
    755   bool result = certificate_manager_model_->ImportServerCert(
    756       selected_cert_list_,
    757       &not_imported);
    758   if (!result) {
    759     ShowError(
    760         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
    761         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
    762   } else if (!not_imported.empty()) {
    763     ShowImportErrors(
    764         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
    765         not_imported);
    766   }
    767   ImportExportCleanup();
    768 }
    769 
    770 void CertificateManagerHandler::ImportCA(const ListValue* args) {
    771   select_file_dialog_ = SelectFileDialog::Create(this);
    772   ShowCertSelectFileDialog(select_file_dialog_.get(),
    773                            SelectFileDialog::SELECT_OPEN_FILE,
    774                            FilePath(),
    775                            web_ui_->tab_contents(),
    776                            GetParentWindow(),
    777                            reinterpret_cast<void*>(IMPORT_CA_FILE_SELECTED));
    778 }
    779 
    780 void CertificateManagerHandler::ImportCAFileSelected(const FilePath& path) {
    781   file_path_ = path;
    782   file_access_provider_->StartRead(
    783       file_path_,
    784       &consumer_,
    785       NewCallback(this, &CertificateManagerHandler::ImportCAFileRead));
    786 }
    787 
    788 void CertificateManagerHandler::ImportCAFileRead(int read_errno,
    789                                                  std::string data) {
    790   if (read_errno) {
    791     ImportExportCleanup();
    792     ShowError(
    793         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
    794         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
    795                                   UTF8ToUTF16(safe_strerror(read_errno))));
    796     return;
    797   }
    798 
    799   selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
    800           data.data(), data.size(), net::X509Certificate::FORMAT_AUTO);
    801   if (selected_cert_list_.empty()) {
    802     ImportExportCleanup();
    803     ShowError(
    804         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
    805         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
    806     return;
    807   }
    808 
    809   scoped_refptr<net::X509Certificate> root_cert =
    810       certificate_manager_model_->cert_db().FindRootInList(selected_cert_list_);
    811 
    812   // TODO(mattm): check here if root_cert is not a CA cert and show error.
    813 
    814   StringValue cert_name(root_cert->subject().GetDisplayName());
    815   web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.showImport",
    816                                   cert_name);
    817 }
    818 
    819 void CertificateManagerHandler::ImportCATrustSelected(const ListValue* args) {
    820   bool fail = false;
    821   bool trust_ssl = false;
    822   bool trust_email = false;
    823   bool trust_obj_sign = false;
    824   fail |= !CallbackArgsToBool(args, 0, &trust_ssl);
    825   fail |= !CallbackArgsToBool(args, 1, &trust_email);
    826   fail |= !CallbackArgsToBool(args, 2, &trust_obj_sign);
    827   if (fail) {
    828     LOG(ERROR) << "ImportCATrustSelected args fail";
    829     ImportExportCleanup();
    830     web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
    831     return;
    832   }
    833 
    834   net::CertDatabase::ImportCertFailureList not_imported;
    835   bool result = certificate_manager_model_->ImportCACerts(
    836       selected_cert_list_,
    837       trust_ssl * net::CertDatabase::TRUSTED_SSL +
    838           trust_email * net::CertDatabase::TRUSTED_EMAIL +
    839           trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN,
    840       &not_imported);
    841   web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
    842   if (!result) {
    843     ShowError(
    844         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
    845         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
    846   } else if (!not_imported.empty()) {
    847     ShowImportErrors(
    848         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
    849         not_imported);
    850   }
    851   ImportExportCleanup();
    852 }
    853 
    854 void CertificateManagerHandler::Export(const ListValue* args) {
    855   net::X509Certificate* cert = CallbackArgsToCert(args);
    856   if (!cert)
    857     return;
    858   ShowCertExportDialog(web_ui_->tab_contents(), GetParentWindow(),
    859                        cert->os_cert_handle());
    860 }
    861 
    862 void CertificateManagerHandler::Delete(const ListValue* args) {
    863   net::X509Certificate* cert = CallbackArgsToCert(args);
    864   if (!cert)
    865     return;
    866   bool result = certificate_manager_model_->Delete(cert);
    867   if (!result) {
    868     // TODO(mattm): better error messages?
    869     ShowError(
    870         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_DELETE_CERT_ERROR_TITLE),
    871         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
    872   }
    873 }
    874 
    875 void CertificateManagerHandler::Populate(const ListValue* args) {
    876   certificate_manager_model_->Refresh();
    877 }
    878 
    879 void CertificateManagerHandler::PopulateTree(const std::string& tab_name,
    880                                              net::CertType type) {
    881   const std::string tree_name = tab_name + "-tree";
    882 
    883   scoped_ptr<icu::Collator> collator;
    884   UErrorCode error = U_ZERO_ERROR;
    885   collator.reset(
    886       icu::Collator::createInstance(
    887           icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
    888           error));
    889   if (U_FAILURE(error))
    890     collator.reset(NULL);
    891   DictionaryIdComparator comparator(collator.get());
    892   CertificateManagerModel::OrgGroupingMap map;
    893 
    894   certificate_manager_model_->FilterAndBuildOrgGroupingMap(type, &map);
    895 
    896   {
    897     ListValue* nodes = new ListValue;
    898     for (CertificateManagerModel::OrgGroupingMap::iterator i = map.begin();
    899          i != map.end(); ++i) {
    900       // Populate first level (org name).
    901       DictionaryValue* dict = new DictionaryValue;
    902       dict->SetString(kKeyId, OrgNameToId(i->first));
    903       dict->SetString(kNameId, i->first);
    904 
    905       // Populate second level (certs).
    906       ListValue* subnodes = new ListValue;
    907       for (net::CertificateList::const_iterator org_cert_it = i->second.begin();
    908            org_cert_it != i->second.end(); ++org_cert_it) {
    909         DictionaryValue* cert_dict = new DictionaryValue;
    910         net::X509Certificate* cert = org_cert_it->get();
    911         cert_dict->SetString(kKeyId, CertToId(*cert));
    912         cert_dict->SetString(kNameId, certificate_manager_model_->GetColumnText(
    913             *cert, CertificateManagerModel::COL_SUBJECT_NAME));
    914         cert_dict->SetBoolean(
    915             kReadOnlyId,
    916             certificate_manager_model_->cert_db().IsReadOnly(cert));
    917         // TODO(mattm): Other columns.
    918         cert_dict->SetString(kIconId, "none");
    919         subnodes->Append(cert_dict);
    920       }
    921       std::sort(subnodes->begin(), subnodes->end(), comparator);
    922 
    923       dict->Set(kSubNodesId, subnodes);
    924       nodes->Append(dict);
    925     }
    926     std::sort(nodes->begin(), nodes->end(), comparator);
    927 
    928     ListValue args;
    929     args.Append(Value::CreateStringValue(tree_name));
    930     args.Append(nodes);
    931     web_ui_->CallJavascriptFunction("CertificateManager.onPopulateTree", args);
    932   }
    933 }
    934 
    935 void CertificateManagerHandler::ShowError(const std::string& title,
    936                                           const std::string& error) const {
    937   ScopedVector<const Value> args;
    938   args.push_back(Value::CreateStringValue(title));
    939   args.push_back(Value::CreateStringValue(error));
    940   args.push_back(Value::CreateStringValue(l10n_util::GetStringUTF8(IDS_OK)));
    941   args.push_back(Value::CreateNullValue());  // cancelTitle
    942   args.push_back(Value::CreateNullValue());  // okCallback
    943   args.push_back(Value::CreateNullValue());  // cancelCallback
    944   web_ui_->CallJavascriptFunction("AlertOverlay.show", args.get());
    945 }
    946 
    947 void CertificateManagerHandler::ShowImportErrors(
    948     const std::string& title,
    949     const net::CertDatabase::ImportCertFailureList& not_imported) const {
    950   std::string error;
    951   if (selected_cert_list_.size() == 1)
    952     error = l10n_util::GetStringUTF8(
    953         IDS_CERT_MANAGER_IMPORT_SINGLE_NOT_IMPORTED);
    954   else if (not_imported.size() == selected_cert_list_.size())
    955     error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_ALL_NOT_IMPORTED);
    956   else
    957     error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_SOME_NOT_IMPORTED);
    958 
    959   ListValue cert_error_list;
    960   for (size_t i = 0; i < not_imported.size(); ++i) {
    961     const net::CertDatabase::ImportCertFailure& failure = not_imported[i];
    962     DictionaryValue* dict = new DictionaryValue;
    963     dict->SetString(kNameId, failure.certificate->subject().GetDisplayName());
    964     dict->SetString(kErrorId, NetErrorToString(failure.net_error));
    965     cert_error_list.Append(dict);
    966   }
    967 
    968   StringValue title_value(title);
    969   StringValue error_value(error);
    970   web_ui_->CallJavascriptFunction("CertificateImportErrorOverlay.show",
    971                                   title_value,
    972                                   error_value,
    973                                   cert_error_list);
    974 }
    975 
    976 #if defined(OS_CHROMEOS)
    977 void CertificateManagerHandler::CheckTpmTokenReady(const ListValue* args) {
    978   chromeos::CryptohomeLibrary* cryptohome =
    979       chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
    980 
    981   // TODO(xiyuan): Use async way when underlying supports it.
    982   FundamentalValue ready(cryptohome->Pkcs11IsTpmTokenReady());
    983   web_ui_->CallJavascriptFunction("CertificateManager.onCheckTpmTokenReady",
    984                                   ready);
    985 }
    986 #endif
    987 
    988 gfx::NativeWindow CertificateManagerHandler::GetParentWindow() const {
    989   return web_ui_->tab_contents()->view()->GetTopLevelNativeWindow();
    990 }
    991