blob: 15ce9af6973f41baf1e985900ddd1fe49d06d9df [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/certificate_manager_model.h"
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/net/nss_context.h"
#include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
#include "chrome/common/net/x509_certificate_model_nss.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "crypto/nss_util.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util_nss.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/certificate_provider/certificate_provider.h"
#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h"
#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h"
#include "chrome/browser/chromeos/policy/user_network_configuration_updater.h"
#include "chrome/browser/chromeos/policy/user_network_configuration_updater_factory.h"
#include "chromeos/network/policy_certificate_provider.h"
#endif
using content::BrowserThread;
// CertificateManagerModel is created on the UI thread. It needs a
// NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
// needs to be done on the IO thread.
//
// The initialization flow is roughly:
//
// UI thread IO Thread
//
// CertificateManagerModel::Create
// \--------------------------------------v
// CertificateManagerModel::GetCertDBOnIOThread
// |
// GetNSSCertDatabaseForResourceContext
// |
// CertificateManagerModel::DidGetCertDBOnIOThread
// |
// crypto::IsTPMTokenEnabledForNSS
// v--------------------------------------/
// CertificateManagerModel::DidGetCertDBOnUIThread
// |
// new CertificateManagerModel
// |
// callback
namespace {
std::string GetCertificateOrg(CERTCertificate* cert) {
std::string org =
x509_certificate_model::GetSubjectOrgName(cert, std::string());
if (org.empty())
org = x509_certificate_model::GetSubjectDisplayName(cert);
return org;
}
#if defined(OS_CHROMEOS)
// Log message for an operation that can not be performed on a certificate of a
// given source.
constexpr char kOperationNotPermitted[] =
"Operation not permitted on a certificate. Source: ";
#endif // OS_CHROMEOS
} // namespace
// A source of certificates that should be displayed on the certificate manager
// UI. Currently, a CertsSource yields CertInfo objects. Each CertInfo contains
// a NSS ScopedCERTCertificate.
class CertificateManagerModel::CertsSource {
public:
// |certs_source_updated_callback| will be invoked when the list of
// certificates provided by this CertsSource changes.
explicit CertsSource(base::RepeatingClosure certs_source_updated_callback)
: certs_source_updated_callback_(certs_source_updated_callback) {}
virtual ~CertsSource() = default;
// Returns the CertInfos provided by this CertsSource.
const std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>>&
cert_infos() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return cert_infos_;
}
// Returns true if |cert| is in this CertsSource's certificate list.
bool HasCert(CERTCertificate* cert) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (const auto& cert_info : cert_infos_) {
if (cert_info->cert() == cert)
return true;
}
return false;
}
// Triggers a refresh of this CertsSource. When done, the
// |certs_source_updated_callback| passed to the constructor will be invoked.
virtual void Refresh() = 0;
// If any CertsSource's |IsHoldBackUpdates| is returning true, the
// CertificateManagerModel will not notify its Observer about updates.
bool IsHoldBackUpdates() const { return hold_back_updates_; }
// Set trust values for certificate.
// |trust_bits| should be a bit field of TRUST* values from NSSCertDatabase.
// Returns true on success or false on failure.
virtual bool SetCertTrust(CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) = 0;
// Delete the cert. Returns true on success. |cert| is still valid when this
// function returns.
virtual bool Delete(CERTCertificate* cert) = 0;
protected:
// To be called by subclasses to set the CertInfo list provided by this
// CertsSource. If this CertsSource is signalling that updates should be held
// back (|SetHoldBackUpdates(true)|, this will be set to false. The
// |certs_source_updated_callback| passed to the constructor will be invoked.
void SetCertInfos(
std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>>
cert_infos) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
cert_infos_.swap(cert_infos);
SetHoldBackUpdates(false);
certs_source_updated_callback_.Run();
}
// Signal to |CertificateManagerModel| that updates to its Observer should be
// held back. This will be automatically taken back on |SetCertInfos|.
// This should only be used by |CertsSource|s that provide their list of
// certificates asynchronously but expect their certificate listing to be
// fast.
void SetHoldBackUpdates(bool hold_back_updates) {
hold_back_updates_ = hold_back_updates;
}
// Used to verify that the constructor, and accessing |cert_infos_| are
// performed on the same sequence. Offered to subclasses so they can also
// check that they're being called on a valid sequence.
SEQUENCE_CHECKER(sequence_checker_);
private:
// Cached CertInfos provided by this CertsSource.
std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos_;
// Invoked when the list of certificates provided by this CertsSource has
// changed.
base::RepeatingClosure certs_source_updated_callback_;
// If true, the CertificateManagerModel should be holding back update
// notifications.
bool hold_back_updates_ = false;
DISALLOW_COPY_AND_ASSIGN(CertsSource);
};
namespace {
// Provides certificates enumerable from a NSSCertDatabase.
class CertsSourcePlatformNSS : public CertificateManagerModel::CertsSource {
public:
CertsSourcePlatformNSS(base::RepeatingClosure certs_source_updated_callback,
net::NSSCertDatabase* nss_cert_database)
: CertsSource(certs_source_updated_callback),
cert_db_(nss_cert_database),
weak_ptr_factory_(this) {}
~CertsSourcePlatformNSS() override = default;
void Refresh() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
SetHoldBackUpdates(true);
DVLOG(1) << "refresh started";
std::vector<crypto::ScopedPK11Slot> modules;
cert_db_->ListModules(&modules, false);
DVLOG(1) << "refresh waiting for unlocking...";
chrome::UnlockSlotsIfNecessary(
std::move(modules), kCryptoModulePasswordListCerts,
net::HostPortPair(), // unused.
nullptr, // TODO(mattm): supply parent window.
base::BindOnce(&CertsSourcePlatformNSS::RefreshSlotsUnlocked,
weak_ptr_factory_.GetWeakPtr()));
}
bool SetCertTrust(CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return cert_db_->SetCertTrust(cert, type, trust_bits);
}
bool Delete(CERTCertificate* cert) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool result = cert_db_->DeleteCertAndKey(cert);
if (result)
Refresh();
return result;
}
private:
void RefreshSlotsUnlocked() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOG(1) << "refresh listing certs...";
cert_db_->ListCerts(base::BindOnce(&CertsSourcePlatformNSS::DidGetCerts,
weak_ptr_factory_.GetWeakPtr()));
}
void DidGetCerts(net::ScopedCERTCertificateList certs) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOG(1) << "refresh finished for platform provided certificates";
std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
cert_infos.reserve(certs.size());
for (auto& cert : certs) {
net::CertType type = x509_certificate_model::GetType(cert.get());
bool read_only = cert_db_->IsReadOnly(cert.get());
bool untrusted = cert_db_->IsUntrusted(cert.get());
bool hardware_backed = cert_db_->IsHardwareBacked(cert.get());
bool web_trust_anchor = cert_db_->IsWebTrustAnchor(cert.get());
bool device_wide = false;
#if defined(OS_CHROMEOS)
device_wide = cert_db_->IsCertificateOnSystemSlot(cert.get());
#endif
base::string16 name = GetName(cert.get(), hardware_backed);
cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
std::move(cert), type, name, read_only, untrusted,
CertificateManagerModel::CertInfo::Source::kPlatform,
web_trust_anchor, hardware_backed, device_wide));
}
SetCertInfos(std::move(cert_infos));
}
static base::string16 GetName(CERTCertificate* cert,
bool is_hardware_backed) {
base::string16 name =
base::UTF8ToUTF16(x509_certificate_model::GetCertNameOrNickname(cert));
if (is_hardware_backed) {
name = l10n_util::GetStringFUTF16(
IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT, name,
l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
}
return name;
}
// The source NSSCertDatabase used for listing certificates.
net::NSSCertDatabase* cert_db_;
base::WeakPtrFactory<CertsSourcePlatformNSS> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CertsSourcePlatformNSS);
};
#if defined(OS_CHROMEOS)
// Provides certificates installed through enterprise policy.
class CertsSourcePolicy : public CertificateManagerModel::CertsSource,
chromeos::PolicyCertificateProvider::Observer {
public:
// Defines which policy-provided certificates this CertsSourcePolicy instance
// should yield.
enum class Mode {
// Only certificates which are installed by enterprise policy, but not Web
// trusted.
kPolicyCertsWithoutWebTrust,
// Only certificates which are installed by enterprise policy and Web
// trusted.
kPolicyCertsWithWebTrust
};
CertsSourcePolicy(base::RepeatingClosure certs_source_updated_callback,
chromeos::PolicyCertificateProvider* policy_certs_provider,
Mode mode)
: CertsSource(certs_source_updated_callback),
policy_certs_provider_(policy_certs_provider),
mode_(mode) {
policy_certs_provider_->AddPolicyProvidedCertsObserver(this);
}
~CertsSourcePolicy() override {
policy_certs_provider_->RemovePolicyProvidedCertsObserver(this);
}
// chromeos::PolicyCertificateProvider::Observer
void OnPolicyProvidedCertsChanged(
const net::CertificateList& all_server_and_authority_certs,
const net::CertificateList& web_trusted_certs) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Refresh();
}
void Refresh() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
switch (mode_) {
case Mode::kPolicyCertsWithoutWebTrust:
RefreshImpl(policy_certs_provider_->GetCertificatesWithoutWebTrust(),
false /* policy_web_trusted */);
break;
case Mode::kPolicyCertsWithWebTrust:
RefreshImpl(policy_certs_provider_->GetWebTrustedCertificates(),
true /* policy_web_trusted */);
break;
default:
NOTREACHED();
}
}
bool SetCertTrust(CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) override {
// Trust of policy-provided certificates can not be changed.
LOG(WARNING) << kOperationNotPermitted << "Policy";
return false;
}
bool Delete(CERTCertificate* cert) override {
// Policy-provided certificates can not be deleted.
LOG(WARNING) << kOperationNotPermitted << "Policy";
return false;
}
private:
void RefreshImpl(const net::CertificateList& certificates,
bool policy_web_trusted) {
std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
cert_infos.reserve(certificates.size());
for (const auto& policy_cert : certificates) {
net::ScopedCERTCertificate nss_cert(
net::x509_util::CreateCERTCertificateFromX509Certificate(
policy_cert.get()));
if (!nss_cert)
continue;
net::CertType type = x509_certificate_model::GetType(nss_cert.get());
base::string16 cert_name = base::UTF8ToUTF16(
x509_certificate_model::GetCertNameOrNickname(nss_cert.get()));
cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
std::move(nss_cert), type, std::move(cert_name), true /* read_only */,
false /* untrusted */,
CertificateManagerModel::CertInfo::Source::kPolicy,
policy_web_trusted /* web_trust_anchor */,
false /* hardware_backed */, false /* device_wide */));
}
SetCertInfos(std::move(cert_infos));
}
chromeos::PolicyCertificateProvider* policy_certs_provider_;
Mode mode_;
DISALLOW_COPY_AND_ASSIGN(CertsSourcePolicy);
};
// Provides certificates made available by extensions through the
// chrome.certificateProvider API.
class CertsSourceExtensions : public CertificateManagerModel::CertsSource {
public:
CertsSourceExtensions(base::RepeatingClosure certs_source_updated_callback,
std::unique_ptr<chromeos::CertificateProvider>
certificate_provider_service)
: CertsSource(certs_source_updated_callback),
certificate_provider_service_(std::move(certificate_provider_service)),
weak_ptr_factory_(this) {}
void Refresh() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
certificate_provider_service_->GetCertificates(
base::AdaptCallbackForRepeating(
base::BindOnce(&CertsSourceExtensions::DidGetCerts,
weak_ptr_factory_.GetWeakPtr())));
}
bool SetCertTrust(CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) override {
// Extension-provided certificates are user certificates; changing trust
// does not make sense here.
LOG(WARNING) << kOperationNotPermitted << "Extension";
return false;
}
bool Delete(CERTCertificate* cert) override {
// Extension-provided certificates can not be deleted.
LOG(WARNING) << kOperationNotPermitted << "Extension";
return false;
}
private:
void DidGetCerts(net::ClientCertIdentityList cert_identities) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<std::unique_ptr<CertificateManagerModel::CertInfo>> cert_infos;
cert_infos.reserve(cert_identities.size());
for (const auto& identity : cert_identities) {
net::ScopedCERTCertificate nss_cert(
net::x509_util::CreateCERTCertificateFromX509Certificate(
identity->certificate()));
if (!nss_cert)
continue;
base::string16 cert_name = base::UTF8ToUTF16(
x509_certificate_model::GetCertNameOrNickname(nss_cert.get()));
base::string16 display_name = l10n_util::GetStringFUTF16(
IDS_CERT_MANAGER_EXTENSION_PROVIDED_FORMAT, std::move(cert_name));
cert_infos.push_back(std::make_unique<CertificateManagerModel::CertInfo>(
std::move(nss_cert), net::CertType::USER_CERT /* type */,
display_name, true /* read_only */, false /* untrusted */,
CertificateManagerModel::CertInfo::Source::kExtension,
false /* web_trust_anchor */, false /* hardware_backed */,
false /* device_wide */));
}
SetCertInfos(std::move(cert_infos));
}
std::unique_ptr<chromeos::CertificateProvider> certificate_provider_service_;
base::WeakPtrFactory<CertsSourceExtensions> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CertsSourceExtensions);
};
#endif // OS_CHROMEOS
} // namespace
CertificateManagerModel::CertInfo::CertInfo(net::ScopedCERTCertificate cert,
net::CertType type,
base::string16 name,
bool read_only,
bool untrusted,
Source source,
bool web_trust_anchor,
bool hardware_backed,
bool device_wide)
: cert_(std::move(cert)),
type_(type),
name_(std::move(name)),
read_only_(read_only),
untrusted_(untrusted),
source_(source),
web_trust_anchor_(web_trust_anchor),
hardware_backed_(hardware_backed),
device_wide_(device_wide) {}
CertificateManagerModel::CertInfo::~CertInfo() {}
// static
std::unique_ptr<CertificateManagerModel::CertInfo>
CertificateManagerModel::CertInfo::Clone(const CertInfo* cert_info) {
return std::make_unique<CertInfo>(
net::x509_util::DupCERTCertificate(cert_info->cert()), cert_info->type(),
cert_info->name(), cert_info->read_only(), cert_info->untrusted(),
cert_info->source(), cert_info->web_trust_anchor(),
cert_info->hardware_backed(), cert_info->device_wide());
}
CertificateManagerModel::Params::Params() = default;
CertificateManagerModel::Params::~Params() = default;
CertificateManagerModel::Params::Params(Params&& other) = default;
// static
void CertificateManagerModel::Create(
content::BrowserContext* browser_context,
CertificateManagerModel::Observer* observer,
const CreationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::unique_ptr<Params> params = std::make_unique<Params>();
#if defined(OS_CHROMEOS)
policy::UserNetworkConfigurationUpdater* user_network_configuration_updater =
policy::UserNetworkConfigurationUpdaterFactory::GetForBrowserContext(
browser_context);
params->policy_certs_provider = user_network_configuration_updater;
chromeos::CertificateProviderService* certificate_provider_service =
chromeos::CertificateProviderServiceFactory::GetForBrowserContext(
browser_context);
params->extension_certificate_provider =
certificate_provider_service->CreateCertificateProvider();
#endif
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CertificateManagerModel::GetCertDBOnIOThread,
std::move(params), browser_context->GetResourceContext(),
observer, callback));
}
CertificateManagerModel::CertificateManagerModel(
std::unique_ptr<Params> params,
Observer* observer,
net::NSSCertDatabase* nss_cert_database,
bool is_user_db_available,
bool is_tpm_available)
: cert_db_(nss_cert_database),
is_user_db_available_(is_user_db_available),
is_tpm_available_(is_tpm_available),
observer_(observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Fill |certs_sources_|. Note that the order matters. Higher priority
// CertsSources must come first.
base::RepeatingClosure certs_source_updated_callback = base::BindRepeating(
&CertificateManagerModel::OnCertsSourceUpdated, base::Unretained(this));
#if defined(OS_CHROMEOS)
// Certificates installed and web trusted by enterprise policy is the highest
// priority CertsSource.
// UserNetworkConfigurationUpdater is only available for the primary user's
// profile.
if (params->policy_certs_provider) {
certs_sources_.push_back(std::make_unique<CertsSourcePolicy>(
certs_source_updated_callback, params->policy_certs_provider,
CertsSourcePolicy::Mode::kPolicyCertsWithWebTrust));
}
#endif
// Add the main NSS DB based CertsSource.
certs_sources_.push_back(std::make_unique<CertsSourcePlatformNSS>(
certs_source_updated_callback, nss_cert_database));
#if defined(OS_CHROMEOS)
// Certificates installed by enterprise policy without web trust are lower
// priority than the main NSS DB based CertsSource.
// Rationale: The user should be able to add trust to policy-provided
// certificates by re-importing them and modifying their trust settings.
if (params->policy_certs_provider) {
certs_sources_.push_back(std::make_unique<CertsSourcePolicy>(
certs_source_updated_callback, params->policy_certs_provider,
CertsSourcePolicy::Mode::kPolicyCertsWithoutWebTrust));
}
// Extensions is the lowest priority CertsSource.
if (params->extension_certificate_provider) {
certs_sources_.push_back(std::make_unique<CertsSourceExtensions>(
certs_source_updated_callback,
std::move(params->extension_certificate_provider)));
}
#endif
}
CertificateManagerModel::~CertificateManagerModel() {}
void CertificateManagerModel::OnCertsSourceUpdated() {
if (hold_back_updates_)
return;
for (const auto& certs_source : certs_sources_) {
if (certs_source->IsHoldBackUpdates()) {
return;
}
}
observer_->CertificatesRefreshed();
}
CertificateManagerModel::CertsSource*
CertificateManagerModel::FindCertsSourceForCert(CERTCertificate* cert) {
for (auto& certs_source : certs_sources_) {
if (certs_source->HasCert(cert))
return certs_source.get();
}
return nullptr;
}
void CertificateManagerModel::Refresh() {
hold_back_updates_ = true;
for (auto& certs_source : certs_sources_)
certs_source->Refresh();
hold_back_updates_ = false;
OnCertsSourceUpdated();
}
void CertificateManagerModel::FilterAndBuildOrgGroupingMap(
net::CertType filter_type,
CertificateManagerModel::OrgGroupingMap* out_org_grouping_map) const {
std::map<CERTCertificate*, std::unique_ptr<CertInfo>> cert_info_map;
for (const auto& certs_source : certs_sources_) {
for (const auto& cert_info : certs_source->cert_infos()) {
if (cert_info->type() != filter_type)
continue;
if (cert_info_map.find(cert_info->cert()) == cert_info_map.end())
cert_info_map[cert_info->cert()] = CertInfo::Clone(cert_info.get());
}
}
for (auto& cert_info_kv : cert_info_map) {
std::string org = GetCertificateOrg(cert_info_kv.second->cert());
(*out_org_grouping_map)[org].push_back(std::move(cert_info_kv.second));
}
}
int CertificateManagerModel::ImportFromPKCS12(PK11SlotInfo* slot_info,
const std::string& data,
const base::string16& password,
bool is_extractable) {
int result = cert_db_->ImportFromPKCS12(slot_info, data, password,
is_extractable, nullptr);
if (result == net::OK)
Refresh();
return result;
}
int CertificateManagerModel::ImportUserCert(const std::string& data) {
int result = cert_db_->ImportUserCert(data);
if (result == net::OK)
Refresh();
return result;
}
bool CertificateManagerModel::ImportCACerts(
const net::ScopedCERTCertificateList& certificates,
net::NSSCertDatabase::TrustBits trust_bits,
net::NSSCertDatabase::ImportCertFailureList* not_imported) {
const size_t num_certs = certificates.size();
bool result = cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
if (result && not_imported->size() != num_certs)
Refresh();
return result;
}
bool CertificateManagerModel::ImportServerCert(
const net::ScopedCERTCertificateList& certificates,
net::NSSCertDatabase::TrustBits trust_bits,
net::NSSCertDatabase::ImportCertFailureList* not_imported) {
const size_t num_certs = certificates.size();
bool result =
cert_db_->ImportServerCert(certificates, trust_bits, not_imported);
if (result && not_imported->size() != num_certs)
Refresh();
return result;
}
bool CertificateManagerModel::SetCertTrust(
CERTCertificate* cert,
net::CertType type,
net::NSSCertDatabase::TrustBits trust_bits) {
CertsSource* certs_source = FindCertsSourceForCert(cert);
if (!certs_source)
return false;
return certs_source->SetCertTrust(cert, type, trust_bits);
}
bool CertificateManagerModel::Delete(CERTCertificate* cert) {
CertsSource* certs_source = FindCertsSourceForCert(cert);
if (!certs_source)
return false;
return certs_source->Delete(cert);
}
// static
void CertificateManagerModel::DidGetCertDBOnUIThread(
std::unique_ptr<Params> params,
CertificateManagerModel::Observer* observer,
const CreationCallback& callback,
net::NSSCertDatabase* cert_db,
bool is_user_db_available,
bool is_tpm_available) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::unique_ptr<CertificateManagerModel> model =
std::make_unique<CertificateManagerModel>(std::move(params), observer,
cert_db, is_user_db_available,
is_tpm_available);
callback.Run(std::move(model));
}
// static
void CertificateManagerModel::DidGetCertDBOnIOThread(
std::unique_ptr<Params> params,
CertificateManagerModel::Observer* observer,
const CreationCallback& callback,
net::NSSCertDatabase* cert_db) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
bool is_user_db_available = !!cert_db->GetPublicSlot();
bool is_tpm_available = false;
#if defined(OS_CHROMEOS)
is_tpm_available = crypto::IsTPMTokenEnabledForNSS();
#endif
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&CertificateManagerModel::DidGetCertDBOnUIThread,
std::move(params), observer, callback, cert_db,
is_user_db_available, is_tpm_available));
}
// static
void CertificateManagerModel::GetCertDBOnIOThread(
std::unique_ptr<Params> params,
content::ResourceContext* resource_context,
CertificateManagerModel::Observer* observer,
const CreationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
auto did_get_cert_db_callback = base::AdaptCallbackForRepeating(
base::BindOnce(&CertificateManagerModel::DidGetCertDBOnIOThread,
std::move(params), observer, callback));
net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
resource_context, did_get_cert_db_callback);
// If the NSS database was already available, |cert_db| is non-null and
// |did_get_cert_db_callback| has not been called. Call it explicitly.
if (cert_db)
did_get_cert_db_callback.Run(cert_db);
}