// 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.

#include "chrome/browser/ui/webui/signin/managed_user_profile_notice_handler.h"

#include <string>
#include <vector>

#include "base/containers/fixed_flat_map.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/utf_string_conversions.h"
#include "build/branding_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/enterprise/browser_management/management_identity.h"
#include "chrome/browser/enterprise/signin/profile_management_disclaimer_service.h"
#include "chrome/browser/enterprise/signin/profile_management_disclaimer_service_factory.h"
#include "chrome/browser/enterprise/util/managed_browser_utils.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/managed_ui.h"
#include "chrome/browser/ui/signin/signin_view_controller.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/webui/management/management_ui_handler.h"
#include "chrome/browser/ui/webui/signin/signin_utils.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/policy/core/browser/signin/profile_separation_policies.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/signin_constants.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_contents.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/native_theme/native_theme.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/webui/webui_util.h"

#if !BUILDFLAG(IS_CHROMEOS)
#include "base/feature_list.h"
#include "chrome/browser/enterprise/profile_management/profile_management_features.h"
#endif

#if BUILDFLAG(CHROME_FOR_TESTING)
#include "base/command_line.h"
#include "base/task/sequenced_task_runner.h"
#endif

namespace {
const int kAvatarSize = 100;
constexpr base::TimeDelta kLongProcessingThreshold = base::Seconds(5);

std::string GetManagedAccountTitle(ProfileAttributesEntry* entry,
                                   const std::string& account_domain_name) {
  DCHECK(entry);
  std::optional<std::string> hosted_domain = entry->GetHostedDomain();
  if (hosted_domain == std::string()) {
    return std::string();
  }
  return l10n_util::GetStringFUTF8(
      IDS_ENTERPRISE_PROFILE_WELCOME_ACCOUNT_MANAGED_BY,
      base::UTF8ToUTF16(hosted_domain.value_or(account_domain_name)));
}

std::string GetManagedDeviceTitle() {
  std::optional<std::string> device_manager = GetDeviceManagerIdentity();
  if (!device_manager) {
    return std::string();
  }
  if (device_manager->empty()) {
    return l10n_util::GetStringUTF8(
        IDS_ENTERPRISE_PROFILE_WELCOME_DEVICE_MANAGED);
  }
  return l10n_util::GetStringFUTF8(
      IDS_ENTERPRISE_PROFILE_WELCOME_DEVICE_MANAGED_BY,
      base::UTF8ToUTF16(*device_manager));
}

}  // namespace

ManagedUserProfileNoticeHandler::ManagedUserProfileNoticeHandler(
    BrowserWindowInterface* browser,
    ManagedUserProfileNoticeUI::ScreenType type,
    std::unique_ptr<signin::EnterpriseProfileCreationDialogParams> create_param)
    : browser_(browser),
      type_(type),
      profile_creation_required_by_policy_(
          create_param->profile_creation_required_by_policy),
      is_modal_dialog_(create_param->is_device_signals_disclaimer_modal),
#if !BUILDFLAG(IS_CHROMEOS)
      show_link_data_option_(create_param->show_link_data_option),
#endif
      email_((create_param->is_oidc_account ||
              create_param->is_device_signals_disclaimer)
                 ? std::u16string()
                 : base::UTF8ToUTF16(create_param->account_info.GetEmail())),
      domain_name_(
          (create_param->is_oidc_account ||
           create_param->is_device_signals_disclaimer)
              ? std::string()
              : gaia::ExtractDomainName(create_param->account_info.GetEmail())),
      account_id_(create_param->account_info.GetAccountId()),
      done_callback_(std::move(create_param->done_callback)),
      retry_callback_(std::move(create_param->retry_callback)) {
  if (std::holds_alternative<signin::SigninChoiceWithConfirmAndRetryCallback>(
          create_param->process_user_choice_callback)) {
    process_user_choice_with_confirmation_callback_ =
        std::move(std::get<signin::SigninChoiceWithConfirmAndRetryCallback>(
            create_param->process_user_choice_callback));
    CHECK(process_user_choice_with_confirmation_callback_);
  }
  if (std::holds_alternative<signin::SigninChoiceCallback>(
          create_param->process_user_choice_callback)) {
    CHECK(std::get<signin::SigninChoiceCallback>(
        create_param->process_user_choice_callback));
    process_user_choice_with_confirmation_callback_ = base::BindOnce(
        [](signin::SigninChoiceCallback callback, signin::SigninChoice choice,
           signin::SigninChoiceOperationDoneCallback done,
           signin::SigninChoiceOperationRetryCallback) {
          std::move(callback).Run(choice);
          std::move(done).Run(
              signin::SigninChoiceOperationResult::SIGNIN_SILENT_SUCCESS,
              signin::SigninChoiceErrorType::kNoError);
        },
        std::move(std::get<signin::SigninChoiceCallback>(
            create_param->process_user_choice_callback)));
  }
  if (std::holds_alternative<signin::DeviceSignalsDisclaimerCallback>(
          create_param->process_user_choice_callback)) {
    device_signals_disclaimer_callback_ =
        std::move(std::get<signin::DeviceSignalsDisclaimerCallback>(
            create_param->process_user_choice_callback));
  }
  CHECK(browser_ ||
        type_ !=
            ManagedUserProfileNoticeUI::ScreenType::kEnterpriseAccountCreation);
  if (browser_) {
    browser_did_close_subscription_ = browser_->RegisterBrowserDidClose(
        base::BindRepeating(&ManagedUserProfileNoticeHandler::OnBrowserDidClose,
                            base::Unretained(this)));
  }
}

ManagedUserProfileNoticeHandler::~ManagedUserProfileNoticeHandler() {
  if (device_signals_disclaimer_callback_) {
    std::move(device_signals_disclaimer_callback_)
        .Run(signin::DeviceSignalsDisclaimerResult::kDismissed);
  } else if (!canceling_) {
    HandleCancel(base::ListValue());
  }
}

void ManagedUserProfileNoticeHandler::RegisterMessages() {
  profile_path_ = Profile::FromWebUI(web_ui())->GetPath();
  web_ui()->RegisterMessageCallback(
      "initialized",
      base::BindRepeating(&ManagedUserProfileNoticeHandler::HandleInitialized,
                          base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "initializedWithSize",
      base::BindRepeating(
          &ManagedUserProfileNoticeHandler::HandleInitializedWithSize,
          base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "proceed",
      base::BindRepeating(&ManagedUserProfileNoticeHandler::HandleProceed,
                          base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "cancel",
      base::BindRepeating(&ManagedUserProfileNoticeHandler::HandleCancel,
                          base::Unretained(this)));
  web_ui()->RegisterMessageCallback(
      "learnMoreClicked",
      base::BindRepeating(
          &ManagedUserProfileNoticeHandler::HandleLearnMoreClicked,
          base::Unretained(this)));
}

void ManagedUserProfileNoticeHandler::OnProfileAvatarChanged(
    const base::FilePath& profile_path) {
  UpdateProfileInfo(profile_path);
}

void ManagedUserProfileNoticeHandler::OnProfileHighResAvatarLoaded(
    const base::FilePath& profile_path) {
  UpdateProfileInfo(profile_path);
}

void ManagedUserProfileNoticeHandler::OnProfileHostedDomainChanged(
    const base::FilePath& profile_path) {
  UpdateProfileInfo(profile_path);
}

void ManagedUserProfileNoticeHandler::OnProfileIsManagedChanged(
    const base::FilePath& profile_path) {
  UpdateProfileInfo(profile_path);
}

void ManagedUserProfileNoticeHandler::OnBrowserDidClose(
    BrowserWindowInterface* browser) {
  CHECK_EQ(browser_, browser);
  browser_ = nullptr;
}

void ManagedUserProfileNoticeHandler::OnExtendedAccountInfoUpdated(
    const AccountInfo& info) {
  if (info.GetAccountId() == account_id_ && info.GetAvatarImage().has_value()) {
    UpdateProfileInfo(profile_path_);
  }
}
void ManagedUserProfileNoticeHandler::OnExtendedAccountInfoRemoved(
    const AccountInfo& info) {
  // If the account has been removed, we should cancel the process.
  if (info.GetAccountId() == account_id_ && !canceling_) {
    HandleCancel(base::ListValue());
  }
}

void ManagedUserProfileNoticeHandler::OnIdentityManagerShutdown(
    signin::IdentityManager* identity_manager) {
  // If the identity manager has been shutdown, we should cancel the process.
  if (!canceling_) {
    HandleCancel(base::ListValue());
  }
}

void ManagedUserProfileNoticeHandler::OnJavascriptAllowed() {
  if (type_ !=
      ManagedUserProfileNoticeUI::ScreenType::kEnterpriseAccountCreation) {
    observed_profile_.Observe(
        &g_browser_process->profile_manager()->GetProfileAttributesStorage());
  } else {
    observed_account_.Observe(
        IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui())));
  }
  if (javascript_allowed_callback_) {
    std::move(javascript_allowed_callback_).Run();
  }
}

void ManagedUserProfileNoticeHandler::OnJavascriptDisallowed() {
  observed_profile_.Reset();
  observed_account_.Reset();
}

void ManagedUserProfileNoticeHandler::HandleInitialized(
    const base::ListValue& args) {
  CHECK_EQ(1u, args.size());
  AllowJavascript();
  const base::Value& callback_id = args[0];
  ResolveJavascriptCallback(callback_id, GetProfileInfoValue());

#if BUILDFLAG(CHROME_FOR_TESTING)
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE,
      base::BindOnce(&ManagedUserProfileNoticeHandler::ProcessAutoApprove,
                     weak_ptr_factory_.GetWeakPtr()));
#endif
}

void ManagedUserProfileNoticeHandler::HandleInitializedWithSize(
    const base::ListValue& args) {
  AllowJavascript();

  if (browser_) {
    signin::SetInitializedModalHeight(browser_, web_ui(), args);
  }
}

#if BUILDFLAG(CHROME_FOR_TESTING)
void ManagedUserProfileNoticeHandler::ProcessAutoApprove() {
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (!command_line->HasSwitch(
          switches::kEnterpriseSigninDialogBehaviorForTesting)) {
    return;
  }
  std::string behavior = command_line->GetSwitchValueASCII(
      switches::kEnterpriseSigninDialogBehaviorForTesting);

  if (behavior == "accept-new-profile") {
    CallProceedCallbackForTesting(signin::SIGNIN_CHOICE_NEW_PROFILE);
  } else if (behavior == "accept-link-data" ||
             behavior == "accept-current-profile") {
    CallProceedCallbackForTesting(signin::SIGNIN_CHOICE_CONTINUE);
  } else if (behavior == "cancel") {
    HandleCancel(base::ListValue());
  }
}
#endif

void ManagedUserProfileNoticeHandler::HandleProceed(
    const base::ListValue& args) {
  CHECK_EQ(2u, args.size());
  AllowJavascript();
  if (device_signals_disclaimer_callback_) {
    DisallowJavascript();
    std::move(device_signals_disclaimer_callback_)
        .Run(signin::DeviceSignalsDisclaimerResult::kAccepted);
    return;
  }
  bool use_existing_profile = args[1].GetIfBool().value_or(false);
  auto result = use_existing_profile ? signin::SIGNIN_CHOICE_CONTINUE
                                     : signin::SIGNIN_CHOICE_NEW_PROFILE;

  int state = args[0].GetIfInt().value_or(0);
  CHECK_NE(state, ManagedUserProfileNoticeHandler::State::kProcessing)
      << "User should not be able to click the proceed button while processing";

  bool is_consumer_domain =
      enterprise_util::IsKnownConsumerDomain(domain_name_);

  if (!is_consumer_domain &&
      state == ManagedUserProfileNoticeHandler::State::kValueProposition &&
      IsJavascriptAllowed()) {
    FireWebUIListener("on-state-changed",
                      ManagedUserProfileNoticeHandler::State::kDisclosure);
    return;
  }

#if !BUILDFLAG(IS_CHROMEOS)
  if (show_link_data_option_ && IsJavascriptAllowed()) {
    if ((is_consumer_domain &&
         state == ManagedUserProfileNoticeHandler::State::kValueProposition) ||
        (!is_consumer_domain &&
         state == ManagedUserProfileNoticeHandler::State::kDisclosure)) {
      FireWebUIListener(
          "on-state-changed",
          ManagedUserProfileNoticeHandler::State::kUserDataHandling);
      return;
    }
  }
#endif
  if (process_user_choice_with_confirmation_callback_ &&
      (state == ManagedUserProfileNoticeHandler::State::kDisclosure ||
       state == ManagedUserProfileNoticeHandler::State::kTimeout) &&
      IsJavascriptAllowed()) {
    if (type_ == ManagedUserProfileNoticeUI::ScreenType::kEnterpriseOIDC) {
      processing_timer_.Start(
          FROM_HERE, kLongProcessingThreshold,
          base::BindOnce(&ManagedUserProfileNoticeHandler::OnLongProcessingTime,
                         base::Unretained(this)));
    }

    FireWebUIListener("on-state-changed",
                      ManagedUserProfileNoticeHandler::State::kProcessing);
  }

  if (process_user_choice_with_confirmation_callback_) {
    std::move(process_user_choice_with_confirmation_callback_)
        .Run(result,
             base::BindOnce(
                 &ManagedUserProfileNoticeHandler::OnUserChoiceHandled,
                 weak_ptr_factory_.GetWeakPtr()),
             base::BindRepeating(
                 &ManagedUserProfileNoticeHandler::OnUserChoiceHandled,
                 weak_ptr_factory_.GetWeakPtr()));
    return;
  }

  if (retry_callback_ &&
      state == ManagedUserProfileNoticeHandler::State::kTimeout &&
      IsJavascriptAllowed()) {
    FireWebUIListener("on-state-changed",
                      ManagedUserProfileNoticeHandler::State::kProcessing);
    retry_callback_.Run();
    return;
  }

  if (done_callback_) {
    DisallowJavascript();
    std::move(done_callback_).Run();
  }
}

void ManagedUserProfileNoticeHandler::HandleCancel(
    const base::ListValue& args) {
  canceling_ = true;
  if (IsJavascriptAllowed()) {
    DisallowJavascript();
  }
  // Move the `done_callback_` here to avoid it being potentially destroyed
  // by `process_user_choice_with_confirmation_callback_` since it may destroy
  // `this`.
  auto done_callback = std::move(done_callback_);
  if (device_signals_disclaimer_callback_) {
    std::move(device_signals_disclaimer_callback_)
        .Run(signin::DeviceSignalsDisclaimerResult::kCanceled);
  } else if (process_user_choice_with_confirmation_callback_) {
    std::move(process_user_choice_with_confirmation_callback_)
        .Run(signin::SIGNIN_CHOICE_CANCEL, base::DoNothing(),
             base::DoNothing());
  }
  if (done_callback) {
    std::move(done_callback).Run();
  }
}

void ManagedUserProfileNoticeHandler::HandleLearnMoreClicked(
    const base::ListValue& args) {
  auto* service = ProfileManagementDisclaimerServiceFactory::GetForProfile(
      Profile::FromWebUI(web_ui()));
  if (service) {
    service->OpenPrivacyPolicyArticlePopUp(is_modal_dialog_);
  }
}

void ManagedUserProfileNoticeHandler::OnLongProcessingTime() {
  FireWebUIListener("on-long-processing");
}

void ManagedUserProfileNoticeHandler::UpdateProfileInfo(
    const base::FilePath& profile_path) {
  DCHECK(IsJavascriptAllowed());
  if (profile_path != profile_path_) {
    return;
  }

  // If the user has canceled the process, we should not update the profile info.
  if (canceling_) {
    return;
  }

  // If the account has been removed, we should not update the profile info.
  if (auto account_info =
          IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()))
              ->FindExtendedAccountInfoByAccountId(account_id_);
      account_info.IsEmpty()) {
    return;
  }
  FireWebUIListener("on-profile-info-changed", GetProfileInfoValue());
}

// static
std::string ManagedUserProfileNoticeHandler::GetManagedAccountTitleWithEmail(
    Profile* profile,
    ProfileAttributesEntry* entry,
    const std::string& account_domain_name,
    const std::u16string& email) {
  DCHECK(profile);
  DCHECK(entry);
  DCHECK(!email.empty());

#if !BUILDFLAG(IS_CHROMEOS)
  std::optional<std::string> account_manager =
      GetAccountManagerIdentity(profile);
  std::optional<std::string> device_manager = GetDeviceManagerIdentity();

  if (!signin_util::IsProfileSeparationEnforcedByProfile(
          profile, base::UTF16ToUTF8(email))) {
    // The profile is managed but does not enforce profile separation. The
    // intercepted account requires it.
    if (account_manager && !account_manager->empty()) {
      return l10n_util::GetStringFUTF8(
          IDS_ENTERPRISE_PROFILE_WELCOME_PROFILE_MANAGED_SEPARATION,
          base::UTF8ToUTF16(*account_manager), email,
          base::UTF8ToUTF16(account_domain_name));
    }
    // The profile is not managed. The intercepted account requires profile
    // separation.
    return l10n_util::GetStringFUTF8(
        IDS_ENTERPRISE_PROFILE_WELCOME_ACCOUNT_EMAIL_MANAGED_BY, email,
        base::UTF8ToUTF16(account_domain_name));
  }
  if (!profile->GetPrefs()->GetBoolean(
          prefs::kManagedAccountsSigninRestrictionScopeMachine) &&
      account_manager && !account_manager->empty()) {
    return l10n_util::GetStringFUTF8(
        IDS_ENTERPRISE_PROFILE_WELCOME_PROFILE_MANAGED_STRICT_SEPARATION,
        base::UTF8ToUTF16(*account_manager), email);
  }
  if (device_manager && !device_manager->empty()) {
    // The device is managed and requires profile separation.
    return l10n_util::GetStringFUTF8(
        IDS_ENTERPRISE_PROFILE_WELCOME_PROFILE_SEPARATION_DEVICE_MANAGED_BY,
        base::UTF8ToUTF16(*device_manager), email);
  }
  return l10n_util::GetStringFUTF8(
      IDS_ENTERPRISE_PROFILE_WELCOME_PROFILE_SEPARATION_DEVICE_MANAGED, email);
#else
  std::optional<std::string> hosted_domain = entry->GetHostedDomain();
  if (hosted_domain == std::string()) {
    return std::string();
  }
  return l10n_util::GetStringFUTF8(
      IDS_ENTERPRISE_PROFILE_WELCOME_ACCOUNT_EMAIL_MANAGED_BY, email,
      base::UTF8ToUTF16(hosted_domain.value_or(account_domain_name)));
#endif  //  !BUILDFLAG(IS_CHROMEOS)
}

base::DictValue ManagedUserProfileNoticeHandler::GetProfileInfoValue() {
  base::DictValue dict;
  dict.Set("pictureUrl", GetPictureUrl());

  std::string title =
      l10n_util::GetStringUTF8(IDS_ENTERPRISE_PROFILE_WELCOME_TITLE);
  std::string subtitle;
  std::string email;
  std::string account_name;
  ProfileAttributesEntry* entry = GetProfileEntry();

  switch (type_) {
    case ManagedUserProfileNoticeUI::ScreenType::kEntepriseAccountSyncEnabled:
      dict.Set("showEnterpriseBadge", true);
      subtitle = GetManagedAccountTitle(entry, domain_name_);
      dict.Set("proceedLabel", l10n_util::GetStringUTF8(
                                   IDS_PROFILE_PICKER_IPH_NEXT_BUTTON_LABEL));
      break;
    case ManagedUserProfileNoticeUI::ScreenType::kEntepriseAccountSyncDisabled:
      dict.Set("showEnterpriseBadge", true);
      subtitle = GetManagedAccountTitle(entry, domain_name_);
      dict.Set("proceedLabel", l10n_util::GetStringUTF8(IDS_DONE));
      break;
    case ManagedUserProfileNoticeUI::ScreenType::kConsumerAccountSyncDisabled:
      dict.Set("showEnterpriseBadge", false);
      subtitle = GetManagedDeviceTitle();
      dict.Set("proceedLabel", l10n_util::GetStringUTF8(IDS_DONE));
      break;
    case ManagedUserProfileNoticeUI::ScreenType::kEnterpriseOIDC:
      title =
          l10n_util::GetStringUTF8(IDS_ENTERPRISE_WELCOME_PROFILE_SETUP_TITLE);
      dict.Set("showEnterpriseBadge", true);
      subtitle = l10n_util::GetStringUTF8(
          IDS_ENTERPRISE_PROFILE_WELCOME_PROFILE_SEPARATION_ACCOUNT_MANAGED);
      dict.Set("proceedLabel",
               l10n_util::GetStringUTF8(
                   profile_creation_required_by_policy_
                       ? IDS_ENTERPRISE_PROFILE_WELCOME_CREATE_PROFILE_BUTTON
                       : IDS_APP_CONTINUE));
      break;
    case ManagedUserProfileNoticeUI::ScreenType::kDeviceSignalsDisclaimer:
      dict.Set("showEnterpriseBadge", true);
      break;
    case ManagedUserProfileNoticeUI::ScreenType::kFirstRun:
      // TODO(crbug.com/483637730): Specify the exact UI for the First Run case
    case ManagedUserProfileNoticeUI::ScreenType::kProfilePicker:
    case ManagedUserProfileNoticeUI::ScreenType::kEnterpriseAccountCreation:
      title = l10n_util::GetStringUTF8(
          profile_creation_required_by_policy_
              ? IDS_ENTERPRISE_WELCOME_PROFILE_REQUIRED_TITLE
              : IDS_ENTERPRISE_WELCOME_PROFILE_WILL_BE_MANAGED_TITLE);
      dict.Set("showEnterpriseBadge",
               !enterprise_util::IsKnownConsumerDomain(domain_name_));
      subtitle = GetManagedAccountTitleWithEmail(Profile::FromWebUI(web_ui()),
                                                 entry, domain_name_, email_);
      dict.Set("proceedLabel",
               l10n_util::GetStringUTF8(
                   profile_creation_required_by_policy_
                       ? IDS_ENTERPRISE_PROFILE_WELCOME_CREATE_PROFILE_BUTTON
                       : IDS_APP_CONTINUE));

      AccountInfo account_info =
          IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()))
              ->FindExtendedAccountInfoByAccountId(account_id_);
      CHECK(!account_info.IsEmpty());
      dict.Set(
          "continueAs",
          l10n_util::GetStringFUTF8(
              IDS_PROFILES_DICE_WEB_ONLY_SIGNIN_BUTTON,
              base::UTF8ToUTF16(account_info.GetGivenName().value_or(""))));
      dict.Set("email", base::UTF16ToUTF8(email_));
      dict.Set("accountName", account_info.GetFullName().value_or(""));

#if !BUILDFLAG(IS_CHROMEOS)
      // We apply the checkLinkDataCheckboxByDefault to true value only if the
      // link data checkbox is visible and the policy
      // ProfileSeparationDataMigrationSettings is set to its OPTOUT value (2)
      // or the legacy policy EnterpriseProfileCreationKeepBrowsingData is set
      // to True.
      bool profile_separation_data_migration_settings_optout =
          Profile::FromWebUI(web_ui())->GetPrefs()->GetInteger(
              prefs::kProfileSeparationDataMigrationSettings) == 2;
      bool check_link_Data_checkbox_by_default_from_legacy_policy =
          g_browser_process->local_state()->GetBoolean(
              prefs::kEnterpriseProfileCreationKeepBrowsingData);
      dict.Set("checkLinkDataCheckboxByDefault",
               show_link_data_option_ &&
                   (profile_separation_data_migration_settings_optout ||
                    check_link_Data_checkbox_by_default_from_legacy_policy));
#endif
      break;
  }

  dict.Set("title", title);
  dict.Set("subtitle", subtitle);

  return dict;
}

ProfileAttributesEntry* ManagedUserProfileNoticeHandler::GetProfileEntry()
    const {
  ProfileAttributesEntry* entry =
      g_browser_process->profile_manager()
          ->GetProfileAttributesStorage()
          .GetProfileAttributesWithPath(profile_path_);
  DCHECK(entry);
  return entry;
}

std::string ManagedUserProfileNoticeHandler::GetPictureUrl() {
  std::optional<gfx::Image> icon;
  if (type_ ==
      ManagedUserProfileNoticeUI::ScreenType::kEnterpriseAccountCreation) {
    AccountInfo account_info =
        IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()))
            ->FindExtendedAccountInfoByAccountId(account_id_);
    DCHECK(!account_info.IsEmpty());
    icon = account_info.GetAvatarImage().value_or(
        ui::ResourceBundle::GetSharedInstance().GetImageNamed(
            profiles::GetPlaceholderAvatarIconResourceID()));
  } else if (type_ == ManagedUserProfileNoticeUI::ScreenType::kEnterpriseOIDC) {
    icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
        profiles::GetPlaceholderAvatarIconResourceID());
  }

  const int avatar_icon_size = kAvatarSize * web_ui()->GetDeviceScaleFactor();
  return webui::GetBitmapDataUrl(
      profiles::GetSizedAvatarIcon(
          icon.value_or(GetProfileEntry()->GetAvatarIcon(avatar_icon_size)),
          avatar_icon_size, avatar_icon_size)
          .AsBitmap());
}

ManagedUserProfileNoticeUI::ScreenType
ManagedUserProfileNoticeHandler::GetTypeForTesting() {
  return type_;
}

void ManagedUserProfileNoticeHandler::CallProceedCallbackForTesting(
    signin::SigninChoice choice) {
  if (process_user_choice_with_confirmation_callback_) {
    std::move(process_user_choice_with_confirmation_callback_)
        .Run(choice,
             base::BindOnce(
                 &ManagedUserProfileNoticeHandler::OnUserChoiceHandled,
                 weak_ptr_factory_.GetWeakPtr()),
             base::BindRepeating(
                 &ManagedUserProfileNoticeHandler::OnUserChoiceHandled,
                 weak_ptr_factory_.GetWeakPtr()));
  }
}

void ManagedUserProfileNoticeHandler::OnUserChoiceHandled(
    signin::SigninChoiceOperationResult result,
    signin::SigninChoiceErrorType error_type) {
  if (type_ == ManagedUserProfileNoticeUI::ScreenType::kEnterpriseOIDC) {
    processing_timer_.Stop();
  }

  switch (result) {
    case signin::SigninChoiceOperationResult::SIGNIN_TIMEOUT:
      FireWebUIListener("on-state-changed",
                        ManagedUserProfileNoticeHandler::State::kTimeout);
      break;

    case signin::SigninChoiceOperationResult::SIGNIN_SILENT_SUCCESS:
      if (done_callback_) {
        DisallowJavascript();
        std::move(done_callback_).Run();
      }
      break;

    case signin::SigninChoiceOperationResult::SIGNIN_ERROR:
      FireErrorEvent(error_type);
      break;

    case signin::SigninChoiceOperationResult::SIGNIN_CONFIRM_SUCCESS:
      FireWebUIListener("on-state-changed",
                        ManagedUserProfileNoticeHandler::State::kSuccess);
      break;
  }
}

void ManagedUserProfileNoticeHandler::FireErrorEvent(
    signin::SigninChoiceErrorType error) {
  std::string dialog_title, dialog_subtitle;
  std::optional<std::string> device_manager = GetDeviceManagerIdentity();

  switch (error) {
    case signin::SigninChoiceErrorType::kSigninDisabled:
      dialog_title = l10n_util::GetStringUTF8(
          IDS_ENTERPRISE_OIDC_WELCOME_ERROR_NO_SIGNIN_TITLE);
      dialog_subtitle = l10n_util::GetStringUTF8(
          IDS_ENTERPRISE_OIDC_WELCOME_ERROR_NO_SIGNIN_SUBTITLE);
      break;
    case signin::SigninChoiceErrorType::kNoError:
    case signin::SigninChoiceErrorType::kUnknown:
      dialog_title =
          l10n_util::GetStringUTF8(IDS_ENTERPRISE_OIDC_WELCOME_ERROR_TITLE);
      dialog_subtitle =
          l10n_util::GetStringUTF8(IDS_ENTERPRISE_OIDC_WELCOME_ERROR_SUBTITLE);
      break;
  }

  FireWebUIListener("on-state-changed-to-error", dialog_title, dialog_subtitle);
}
