| OLD | NEW |
| (Empty) |
| 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 // TODO(mattm): this isn't gtk specific, it shouldn't be under the gtk dir | |
| 6 | |
| 7 #include "chrome/browser/ui/gtk/certificate_dialogs.h" | |
| 8 | |
| 9 | |
| 10 #include <vector> | |
| 11 | |
| 12 #include "base/base64.h" | |
| 13 #include "base/file_util.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/memory/scoped_ptr.h" | |
| 16 #include "base/task.h" | |
| 17 #include "chrome/common/net/x509_certificate_model.h" | |
| 18 #include "content/public/browser/browser_thread.h" | |
| 19 #include "grit/generated_resources.h" | |
| 20 #include "ui/base/l10n/l10n_util.h" | |
| 21 | |
| 22 using content::BrowserThread; | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 //////////////////////////////////////////////////////////////////////////////// | |
| 27 // General utility functions. | |
| 28 | |
| 29 class Writer : public Task { | |
| 30 public: | |
| 31 Writer(const FilePath& path, const std::string& data) | |
| 32 : path_(path), data_(data) { | |
| 33 } | |
| 34 | |
| 35 virtual void Run() { | |
| 36 int bytes_written = file_util::WriteFile(path_, data_.data(), data_.size()); | |
| 37 if (bytes_written != static_cast<ssize_t>(data_.size())) { | |
| 38 LOG(ERROR) << "Writing " << path_.value() << " (" | |
| 39 << data_.size() << "B) returned " << bytes_written; | |
| 40 } | |
| 41 } | |
| 42 private: | |
| 43 FilePath path_; | |
| 44 std::string data_; | |
| 45 }; | |
| 46 | |
| 47 void WriteFileOnFileThread(const FilePath& path, const std::string& data) { | |
| 48 BrowserThread::PostTask( | |
| 49 BrowserThread::FILE, FROM_HERE, new Writer(path, data)); | |
| 50 } | |
| 51 | |
| 52 std::string WrapAt64(const std::string &str) { | |
| 53 std::string result; | |
| 54 for (size_t i = 0; i < str.size(); i += 64) { | |
| 55 result.append(str, i, 64); // Append clamps the len arg internally. | |
| 56 result.append("\r\n"); | |
| 57 } | |
| 58 return result; | |
| 59 } | |
| 60 | |
| 61 std::string GetBase64String(net::X509Certificate::OSCertHandle cert) { | |
| 62 std::string base64; | |
| 63 if (!base::Base64Encode( | |
| 64 x509_certificate_model::GetDerString(cert), &base64)) { | |
| 65 LOG(ERROR) << "base64 encoding error"; | |
| 66 return ""; | |
| 67 } | |
| 68 return "-----BEGIN CERTIFICATE-----\r\n" + | |
| 69 WrapAt64(base64) + | |
| 70 "-----END CERTIFICATE-----\r\n"; | |
| 71 } | |
| 72 | |
| 73 //////////////////////////////////////////////////////////////////////////////// | |
| 74 // General utility functions. | |
| 75 | |
| 76 class Exporter : public SelectFileDialog::Listener { | |
| 77 public: | |
| 78 Exporter(TabContents* tab_contents, gfx::NativeWindow parent, | |
| 79 net::X509Certificate::OSCertHandle cert); | |
| 80 ~Exporter(); | |
| 81 | |
| 82 // SelectFileDialog::Listener implemenation. | |
| 83 virtual void FileSelected(const FilePath& path, | |
| 84 int index, void* params); | |
| 85 virtual void FileSelectionCanceled(void* params); | |
| 86 private: | |
| 87 scoped_refptr<SelectFileDialog> select_file_dialog_; | |
| 88 | |
| 89 // The certificate hierarchy (leaf cert first). | |
| 90 net::X509Certificate::OSCertHandles cert_chain_list_; | |
| 91 }; | |
| 92 | |
| 93 Exporter::Exporter(TabContents* tab_contents, | |
| 94 gfx::NativeWindow parent, | |
| 95 net::X509Certificate::OSCertHandle cert) | |
| 96 : select_file_dialog_(SelectFileDialog::Create(this)) { | |
| 97 x509_certificate_model::GetCertChainFromCert(cert, &cert_chain_list_); | |
| 98 | |
| 99 // TODO(mattm): should this default to some directory? | |
| 100 // Maybe SavePackage::GetSaveDirPreference? (Except that it's private.) | |
| 101 FilePath suggested_path("certificate"); | |
| 102 std::string cert_title = x509_certificate_model::GetTitle(cert); | |
| 103 if (!cert_title.empty()) | |
| 104 suggested_path = FilePath(cert_title); | |
| 105 | |
| 106 ShowCertSelectFileDialog(select_file_dialog_.get(), | |
| 107 SelectFileDialog::SELECT_SAVEAS_FILE, | |
| 108 suggested_path, | |
| 109 tab_contents, | |
| 110 parent, | |
| 111 NULL); | |
| 112 } | |
| 113 | |
| 114 Exporter::~Exporter() { | |
| 115 // There may be pending file dialogs, we need to tell them that we've gone | |
| 116 // away so they don't try and call back to us. | |
| 117 if (select_file_dialog_.get()) | |
| 118 select_file_dialog_->ListenerDestroyed(); | |
| 119 | |
| 120 x509_certificate_model::DestroyCertChain(&cert_chain_list_); | |
| 121 } | |
| 122 | |
| 123 void Exporter::FileSelected(const FilePath& path, int index, void* params) { | |
| 124 std::string data; | |
| 125 switch (index) { | |
| 126 case 2: | |
| 127 for (size_t i = 0; i < cert_chain_list_.size(); ++i) | |
| 128 data += GetBase64String(cert_chain_list_[i]); | |
| 129 break; | |
| 130 case 3: | |
| 131 data = x509_certificate_model::GetDerString(cert_chain_list_[0]); | |
| 132 break; | |
| 133 case 4: | |
| 134 data = x509_certificate_model::GetCMSString(cert_chain_list_, 0, 1); | |
| 135 break; | |
| 136 case 5: | |
| 137 data = x509_certificate_model::GetCMSString( | |
| 138 cert_chain_list_, 0, cert_chain_list_.size()); | |
| 139 break; | |
| 140 case 1: | |
| 141 default: | |
| 142 data = GetBase64String(cert_chain_list_[0]); | |
| 143 break; | |
| 144 } | |
| 145 | |
| 146 if (!data.empty()) | |
| 147 WriteFileOnFileThread(path, data); | |
| 148 | |
| 149 delete this; | |
| 150 } | |
| 151 | |
| 152 void Exporter::FileSelectionCanceled(void* params) { | |
| 153 delete this; | |
| 154 } | |
| 155 | |
| 156 } // namespace | |
| 157 | |
| 158 void ShowCertSelectFileDialog(SelectFileDialog* select_file_dialog, | |
| 159 SelectFileDialog::Type type, | |
| 160 const FilePath& suggested_path, | |
| 161 TabContents* tab_contents, | |
| 162 gfx::NativeWindow parent, | |
| 163 void* params) { | |
| 164 SelectFileDialog::FileTypeInfo file_type_info; | |
| 165 file_type_info.extensions.resize(5); | |
| 166 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("pem")); | |
| 167 file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("crt")); | |
| 168 file_type_info.extension_description_overrides.push_back( | |
| 169 l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64)); | |
| 170 file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("pem")); | |
| 171 file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("crt")); | |
| 172 file_type_info.extension_description_overrides.push_back( | |
| 173 l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64_CHAIN)); | |
| 174 file_type_info.extensions[2].push_back(FILE_PATH_LITERAL("der")); | |
| 175 file_type_info.extension_description_overrides.push_back( | |
| 176 l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_DER)); | |
| 177 file_type_info.extensions[3].push_back(FILE_PATH_LITERAL("p7c")); | |
| 178 file_type_info.extension_description_overrides.push_back( | |
| 179 l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7)); | |
| 180 file_type_info.extensions[4].push_back(FILE_PATH_LITERAL("p7c")); | |
| 181 file_type_info.extension_description_overrides.push_back( | |
| 182 l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7_CHAIN)); | |
| 183 file_type_info.include_all_files = true; | |
| 184 select_file_dialog->SelectFile( | |
| 185 type, string16(), | |
| 186 suggested_path, &file_type_info, 1, | |
| 187 FILE_PATH_LITERAL("crt"), tab_contents, | |
| 188 parent, params); | |
| 189 } | |
| 190 | |
| 191 void ShowCertExportDialog(TabContents* tab_contents, | |
| 192 gfx::NativeWindow parent, | |
| 193 net::X509Certificate::OSCertHandle cert) { | |
| 194 new Exporter(tab_contents, parent, cert); | |
| 195 } | |
| OLD | NEW |