Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / certificate_manager_model.cc
blobe932883638c538e2f7b5fbd667894bb568b770e5
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.
5 #include "chrome/browser/certificate_manager_model.h"
7 #include "base/bind.h"
8 #include "base/i18n/time_formatting.h"
9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/net/nss_context.h"
12 #include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
13 #include "chrome/common/net/x509_certificate_model.h"
14 #include "chrome/grit/generated_resources.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/resource_context.h"
18 #include "crypto/nss_util.h"
19 #include "net/base/crypto_module.h"
20 #include "net/base/net_errors.h"
21 #include "net/cert/x509_certificate.h"
22 #include "ui/base/l10n/l10n_util.h"
24 using content::BrowserThread;
26 // CertificateManagerModel is created on the UI thread. It needs a
27 // NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
28 // needs to be done on the IO thread.
30 // The initialization flow is roughly:
32 // UI thread IO Thread
34 // CertificateManagerModel::Create
35 // \--------------------------------------v
36 // CertificateManagerModel::GetCertDBOnIOThread
37 // |
38 // GetNSSCertDatabaseForResourceContext
39 // |
40 // CertificateManagerModel::DidGetCertDBOnIOThread
41 // |
42 // crypto::IsTPMTokenEnabledForNSS
43 // v--------------------------------------/
44 // CertificateManagerModel::DidGetCertDBOnUIThread
45 // |
46 // new CertificateManagerModel
47 // |
48 // callback
50 // static
51 void CertificateManagerModel::Create(
52 content::BrowserContext* browser_context,
53 CertificateManagerModel::Observer* observer,
54 const CreationCallback& callback) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
56 BrowserThread::PostTask(
57 BrowserThread::IO,
58 FROM_HERE,
59 base::Bind(&CertificateManagerModel::GetCertDBOnIOThread,
60 browser_context->GetResourceContext(),
61 observer,
62 callback));
65 CertificateManagerModel::CertificateManagerModel(
66 net::NSSCertDatabase* nss_cert_database,
67 bool is_user_db_available,
68 bool is_tpm_available,
69 Observer* observer)
70 : cert_db_(nss_cert_database),
71 is_user_db_available_(is_user_db_available),
72 is_tpm_available_(is_tpm_available),
73 observer_(observer) {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
77 CertificateManagerModel::~CertificateManagerModel() {
80 void CertificateManagerModel::Refresh() {
81 DVLOG(1) << "refresh started";
82 net::CryptoModuleList modules;
83 cert_db_->ListModules(&modules, false);
84 DVLOG(1) << "refresh waiting for unlocking...";
85 chrome::UnlockSlotsIfNecessary(
86 modules,
87 chrome::kCryptoModulePasswordListCerts,
88 net::HostPortPair(), // unused.
89 NULL, // TODO(mattm): supply parent window.
90 base::Bind(&CertificateManagerModel::RefreshSlotsUnlocked,
91 base::Unretained(this)));
94 void CertificateManagerModel::RefreshSlotsUnlocked() {
95 DVLOG(1) << "refresh listing certs...";
96 // TODO(tbarzic): Use async |ListCerts|.
97 cert_db_->ListCertsSync(&cert_list_);
98 observer_->CertificatesRefreshed();
99 DVLOG(1) << "refresh finished";
102 void CertificateManagerModel::FilterAndBuildOrgGroupingMap(
103 net::CertType filter_type,
104 CertificateManagerModel::OrgGroupingMap* map) const {
105 for (net::CertificateList::const_iterator i = cert_list_.begin();
106 i != cert_list_.end(); ++i) {
107 net::X509Certificate* cert = i->get();
108 net::CertType type =
109 x509_certificate_model::GetType(cert->os_cert_handle());
110 if (type != filter_type)
111 continue;
113 std::string org;
114 if (!cert->subject().organization_names.empty())
115 org = cert->subject().organization_names[0];
116 if (org.empty())
117 org = cert->subject().GetDisplayName();
119 (*map)[org].push_back(cert);
123 base::string16 CertificateManagerModel::GetColumnText(
124 const net::X509Certificate& cert,
125 Column column) const {
126 base::string16 rv;
127 switch (column) {
128 case COL_SUBJECT_NAME:
129 rv = base::UTF8ToUTF16(
130 x509_certificate_model::GetCertNameOrNickname(cert.os_cert_handle()));
132 // TODO(xiyuan): Put this into a column when we have js tree-table.
133 if (IsHardwareBacked(&cert)) {
134 rv = l10n_util::GetStringFUTF16(
135 IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT,
137 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
139 break;
140 case COL_CERTIFICATE_STORE:
141 rv = base::UTF8ToUTF16(
142 x509_certificate_model::GetTokenName(cert.os_cert_handle()));
143 break;
144 case COL_SERIAL_NUMBER:
145 rv = base::ASCIIToUTF16(x509_certificate_model::GetSerialNumberHexified(
146 cert.os_cert_handle(), std::string()));
147 break;
148 case COL_EXPIRES_ON:
149 if (!cert.valid_expiry().is_null())
150 rv = base::TimeFormatShortDateNumeric(cert.valid_expiry());
151 break;
152 default:
153 NOTREACHED();
155 return rv;
158 int CertificateManagerModel::ImportFromPKCS12(net::CryptoModule* module,
159 const std::string& data,
160 const base::string16& password,
161 bool is_extractable) {
162 int result = cert_db_->ImportFromPKCS12(module, data, password,
163 is_extractable, NULL);
164 if (result == net::OK)
165 Refresh();
166 return result;
169 bool CertificateManagerModel::ImportCACerts(
170 const net::CertificateList& certificates,
171 net::NSSCertDatabase::TrustBits trust_bits,
172 net::NSSCertDatabase::ImportCertFailureList* not_imported) {
173 bool result = cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
174 if (result && not_imported->size() != certificates.size())
175 Refresh();
176 return result;
179 bool CertificateManagerModel::ImportServerCert(
180 const net::CertificateList& certificates,
181 net::NSSCertDatabase::TrustBits trust_bits,
182 net::NSSCertDatabase::ImportCertFailureList* not_imported) {
183 bool result = cert_db_->ImportServerCert(certificates, trust_bits,
184 not_imported);
185 if (result && not_imported->size() != certificates.size())
186 Refresh();
187 return result;
190 bool CertificateManagerModel::SetCertTrust(
191 const net::X509Certificate* cert,
192 net::CertType type,
193 net::NSSCertDatabase::TrustBits trust_bits) {
194 return cert_db_->SetCertTrust(cert, type, trust_bits);
197 bool CertificateManagerModel::Delete(net::X509Certificate* cert) {
198 bool result = cert_db_->DeleteCertAndKey(cert);
199 if (result)
200 Refresh();
201 return result;
204 bool CertificateManagerModel::IsHardwareBacked(
205 const net::X509Certificate* cert) const {
206 return cert_db_->IsHardwareBacked(cert);
209 // static
210 void CertificateManagerModel::DidGetCertDBOnUIThread(
211 net::NSSCertDatabase* cert_db,
212 bool is_user_db_available,
213 bool is_tpm_available,
214 CertificateManagerModel::Observer* observer,
215 const CreationCallback& callback) {
216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
218 scoped_ptr<CertificateManagerModel> model(new CertificateManagerModel(
219 cert_db, is_user_db_available, is_tpm_available, observer));
220 callback.Run(model.Pass());
223 // static
224 void CertificateManagerModel::DidGetCertDBOnIOThread(
225 CertificateManagerModel::Observer* observer,
226 const CreationCallback& callback,
227 net::NSSCertDatabase* cert_db) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
230 bool is_user_db_available = cert_db->GetPublicSlot();
231 bool is_tpm_available = false;
232 #if defined(OS_CHROMEOS)
233 is_tpm_available = crypto::IsTPMTokenEnabledForNSS();
234 #endif
235 BrowserThread::PostTask(
236 BrowserThread::UI,
237 FROM_HERE,
238 base::Bind(&CertificateManagerModel::DidGetCertDBOnUIThread,
239 cert_db,
240 is_user_db_available,
241 is_tpm_available,
242 observer,
243 callback));
246 // static
247 void CertificateManagerModel::GetCertDBOnIOThread(
248 content::ResourceContext* context,
249 CertificateManagerModel::Observer* observer,
250 const CreationCallback& callback) {
251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
252 net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
253 context,
254 base::Bind(&CertificateManagerModel::DidGetCertDBOnIOThread,
255 observer,
256 callback));
257 if (cert_db)
258 DidGetCertDBOnIOThread(observer, callback, cert_db);