// 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/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::AdaptCallbackForRepeating(
            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::AdaptCallbackForRepeating(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());
      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));
    }

    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 */));
    }

    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 */));
    }

    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)
    : 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) {}

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());
}

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);
}
