chromium/chrome/browser/lacros/cert/cert_db_initializer_io_impl.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_LACROS_CERT_CERT_DB_INITIALIZER_IO_IMPL_H_
#define CHROME_BROWSER_LACROS_CERT_CERT_DB_INITIALIZER_IO_IMPL_H_

#include <memory>

#include "base/callback_list.h"
#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "chromeos/crosapi/mojom/cert_database.mojom.h"
#include "crypto/scoped_nss_types.h"
#include "net/cert/nss_cert_database_chromeos.h"

// This class is a part of CertDbInitializerImpl that lives on the IO thread.
// All the methods (except for the constructor) must be called on the IO thread.
// The main purpose of the class is to create NSSCertDatabase and provide
// access to it.
class CertDbInitializerIOImpl : public net::NSSCertDatabase::Observer {
 public:
  using GetNSSCertDatabaseCallback =
      base::OnceCallback<void(net::NSSCertDatabase*)>;

  CertDbInitializerIOImpl();
  ~CertDbInitializerIOImpl() override;

  // If `nss_cert_database_` is already created, returns a pointer to it and
  // never calls the `callback`. Otherwise, returns nullptr and will call the
  // `callback` when it is created.
  net::NSSCertDatabase* GetNssCertDatabase(GetNSSCertDatabaseCallback callback);

  // Similar to LoadSoftwareNssDb(), but will use the internal slot as the
  // public slot instead of loading the software NSS database from disk.
  void InitReadOnlyPublicSlot(base::OnceClosure done_callback);

  // Loads the software NSS certificate database (a.k.a. public slot). This step
  // should be executed as soon as possbile because the database may contain
  // user defined CA trust settings that are required for loading web pages.
  // `load_callback` will be called when the load is done.
  void LoadSoftwareNssDb(const base::FilePath& user_nss_database_path,
                         base::OnceClosure load_callback);

  // Creates an NSSCertDatabase based upon the initialization data from
  // `cert_db_info`. This database will then be used for all waiting and
  // future calls to `GetNssCertDatabase`. If `cert_db_info` is nullptr, a
  // read-only database will be created, without any user certificates.
  // `init_callback` will be called when the initialization is done.
  //
  // Summary of what slots are used and when:
  // Public slot:
  // * It is expected to reference the software NSS database in the user
  // directory.
  // * If the path to the directory was not provided by Ash, it will reference
  // the internal slot.
  // * In case of errors it will be empty which will cause a crash if Chrome
  // tries to read it.
  //
  // Private slot:
  // * It is expected to reference a per-user cert storage in Chaps (i.e. in
  // TPM).
  // * If Chaps should not be loaded for the current session (e.g. for guest
  // sessions) or if it failed to load, the private slot will reference the
  // internal slot.
  //
  // System slot:
  // * If it should be used it is expected to reference the device-wide cert
  // storage in Chaps. The decision is made in Ash-Chrome.
  // * Otherwise or if fails to load, system slot will be empty. This will limit
  // access to some certs, but otherwise won't break Chrome.
  void InitializeNssCertDatabase(
      crosapi::mojom::GetCertDatabaseInfoResultPtr cert_db_info,
      base::OnceClosure init_callback);

  // Initializes a read-only database without any user certificates.
  // `init_callback` will be called when the initialization is done.
  void InitializeReadOnlyNssCertDatabase(base::OnceClosure init_callback);

  // net::NSSCertDatabase::Observer
  void OnTrustStoreChanged() override;
  void OnClientCertStoreChanged() override;

 private:
  void DidLoadSoftwareNssDb(base::OnceClosure load_callback,
                            crypto::ScopedPK11Slot public_slot);

  void DidLoadSlots(base::OnceClosure init_callback,
                    crypto::ScopedPK11Slot private_slot,
                    crypto::ScopedPK11Slot system_slot);

  crypto::ScopedPK11Slot pending_public_slot_;
  std::unique_ptr<net::NSSCertDatabaseChromeOS> nss_cert_database_;
  base::OnceCallbackList<GetNSSCertDatabaseCallback::RunType>
      ready_callback_list_;

  base::WeakPtrFactory<CertDbInitializerIOImpl> weak_factory_{this};
};

#endif  // CHROME_BROWSER_LACROS_CERT_CERT_DB_INITIALIZER_IO_IMPL_H_