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