chromium/chrome/browser/lacros/account_manager/add_account_helper.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_ACCOUNT_MANAGER_ADD_ACCOUNT_HELPER_H_
#define CHROME_BROWSER_LACROS_ACCOUNT_MANAGER_ADD_ACCOUNT_HELPER_H_

#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/lacros/account_manager/account_profile_mapper.h"
#include "chrome/browser/profiles/profile.h"
#include "components/account_manager_core/account_manager_facade.h"
#include "third_party/abseil-cpp/absl/types/variant.h"

namespace account_manager {
struct Account;
class AccountUpsertionResult;
class AccountManagerFacade;
}  // namespace account_manager

namespace base {
class FilePath;
}

class ProfileAttributesStorage;

// Helper class encapsulating creation of accounts and profiles for
// `AccountProfileMapper`.
class AddAccountHelper {
 public:
  using IsAccountInCacheCallback =
      base::RepeatingCallback<bool(const account_manager::Account&)>;

  AddAccountHelper(IsAccountInCacheCallback is_account_in_cache_callback,
                   account_manager::AccountManagerFacade* facade,
                   ProfileAttributesStorage* storage);
  ~AddAccountHelper();

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

  // Starts the account addition flow. `callback` must not be null.
  // If `profile_path` is empty, created a new profile that is ephemeral and
  // omitted. The account in `source_or_account` is used if present, otherwise a
  // new account is added with the source.
  // Note: it is important that `AddAccountHelper` completes quickly, as account
  // updates are blocked in the meantime. In particular, this should not block
  // on any user input beside the OS account addition flow.
  void Start(const base::FilePath& profile_path,
             const absl::variant<
                 account_manager::AccountManagerFacade::AccountAdditionSource,
                 account_manager::Account>& source_or_account,
             AccountProfileMapper::AddAccountCallback callback);

  // Adds or updates an account programmatically without user interaction.
  // Should only be used in tests.
  void UpsertAccountForTesting(
      const base::FilePath& profile_path,
      const account_manager::Account& account,
      const std::string& token_value,
      AccountProfileMapper::AddAccountCallback callback);

  // Notifies an `AddAccountHelper` that the account cache has been updated.
  void OnAccountCacheUpdated();

 private:
  // Called once the user added an account, and before the account is added to
  // the profile.
  void OnShowAddAccountDialogCompleted(
      const base::FilePath& profile_path,
      const account_manager::AccountUpsertionResult& result);

  // Called as part of the account addition flow, if the profile does not
  // already exist.
  void OnNewProfileInitialized(Profile* new_profile);

  // Called after the user added and account and the profile exists.
  // `profile_path` must not be empty.
  void OnShowAddAccountDialogCompletedWithProfilePath(
      const base::FilePath& profile_path);

  // Attempts to finish the account addition. Proceeds only if all of the
  // following is true:
  // - an account has been chosen by the user
  // - an account has been added to cache
  // - a profile path has been determined
  void MaybeCompleteAddAccount();

  IsAccountInCacheCallback is_account_in_cache_callback_;
  const raw_ptr<account_manager::AccountManagerFacade> account_manager_facade_;
  const raw_ptr<ProfileAttributesStorage> profile_attributes_storage_;
  AccountProfileMapper::AddAccountCallback callback_;

  std::optional<account_manager::Account> account_;
  // std::nullopt means that the path hasn't been determined yet.
  // An empty path means that the account should be unassigned.
  std::optional<base::FilePath> profile_path_;

  bool is_account_in_cache_ = false;

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

#endif  // CHROME_BROWSER_LACROS_ACCOUNT_MANAGER_ADD_ACCOUNT_HELPER_H_