chromium/chrome/browser/ash/policy/core/cached_policy_key_loader.h

// Copyright 2017 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_ASH_POLICY_CORE_CACHED_POLICY_KEY_LOADER_H_
#define CHROME_BROWSER_ASH_POLICY_CORE_CACHED_POLICY_KEY_LOADER_H_

#include <optional>
#include <string>
#include <vector>

#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chromeos/ash/components/dbus/cryptohome/UserDataAuth.pb.h"
#include "components/account_id/account_id.h"

namespace ash {
class CryptohomeMiscClient;
}

namespace base {
class SequencedTaskRunner;
}

namespace policy {

// Loads policy key cached by session_manager.
class CachedPolicyKeyLoader {
 public:
  CachedPolicyKeyLoader(ash::CryptohomeMiscClient* cryptohome_misc_client,
                        scoped_refptr<base::SequencedTaskRunner> task_runner,
                        const AccountId& account_id,
                        const base::FilePath& user_policy_key_dir);

  CachedPolicyKeyLoader(const CachedPolicyKeyLoader&) = delete;
  CachedPolicyKeyLoader& operator=(const CachedPolicyKeyLoader&) = delete;

  ~CachedPolicyKeyLoader();

  // Invokes |callback| after loading |policy_key_|, if it hasn't been loaded
  // yet; otherwise invokes |callback| immediately.
  // This method may not be called while a load is currently in progres.
  void EnsurePolicyKeyLoaded(base::OnceClosure callback);

  // Invokes |callback| after reloading |policy_key_|.
  void ReloadPolicyKey(base::OnceClosure callback);

  // Loads the policy key synchronously on the current thread.
  bool LoadPolicyKeyImmediately();

  const std::string& cached_policy_key() const { return cached_policy_key_; }

 private:
  // Reads and returns the contents of |path|. If the path does not exist or the
  // key is empty/not readable, returns an empty string. Also samples the
  // validation failure UMA stat.
  static std::string LoadPolicyKey(const base::FilePath& path);

  // Posts a task to load the policy key on |task_runner_|. OnPolicyKeyLoaded()
  // will be called on completition.
  void TriggerLoadPolicyKey();

  // Callback for the key reloading.
  void OnPolicyKeyLoaded(const std::string& key);

  // Callback for getting the sanitized username from |cryptohome_client_|.
  void OnGetSanitizedUsername(
      std::optional<user_data_auth::GetSanitizedUsernameReply> reply);

  void NotifyAndClearCallbacks();

  // Task runner for background file operations.
  scoped_refptr<base::SequencedTaskRunner> task_runner_;

  const raw_ptr<ash::CryptohomeMiscClient> cryptohome_misc_client_;
  const AccountId account_id_;
  const base::FilePath user_policy_key_dir_;
  base::FilePath cached_policy_key_path_;

  // The current key used to verify signatures of policy. This value is loaded
  // from the key cache file (which is owned and kept up to date by the Chrome
  // OS session manager).
  std::string cached_policy_key_;

  // This will be true when a previous key load succeeded. It signals that
  // EnsurePolicyKeyLoaded can call the passed callback immediately.
  bool key_loaded_ = false;

  // This will be true when an asynchronous key load (started by
  // EnsurePolicyKeyLoaded or ReloadPolicyKey) is in progress.
  bool key_load_in_progress_ = false;

  // All callbacks that should be called when the async key load finishes.
  std::vector<base::OnceClosure> key_loaded_callbacks_;

  SEQUENCE_CHECKER(sequence_checker_);

  // Must be the last memeber.
  base::WeakPtrFactory<CachedPolicyKeyLoader> weak_factory_{this};
};

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_CORE_CACHED_POLICY_KEY_LOADER_H_