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 |