// Copyright 2012 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/extensions/api/identity/identity_api.h"

#include <stddef.h>

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/containers/contains.h"
#include "base/functional/callback_forward.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/account_consistency_mode_manager.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/common/extensions/api/identity.h"
#include "chrome/common/url_constants.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/primary_account_change_event.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_l10n_util.h"
#include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
#include "google_apis/gaia/gaia_id.h"
#include "google_apis/gaia/gaia_urls.h"
#include "url/gurl.h"

#if BUILDFLAG(ENABLE_DICE_SUPPORT)
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
#include "chrome/browser/ui/signin/signin_view_controller.h"  // nogncheck crbug.com/423799622
#endif

static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));

using signin::ConsentLevel;
using signin::PrimaryAccountChangeEvent;

namespace extensions {

namespace {
const char kIdentityGaiaIdPref[] = "identity_gaia_id";
}

IdentityAPI::IdentityAPI(content::BrowserContext* context)
    : IdentityAPI(Profile::FromBrowserContext(context),
                  IdentityManagerFactory::GetForProfile(
                      Profile::FromBrowserContext(context)),
                  ExtensionPrefs::Get(context),
                  EventRouter::Get(context)) {}

IdentityAPI::~IdentityAPI() = default;

IdentityMintRequestQueue* IdentityAPI::mint_queue() { return &mint_queue_; }

IdentityTokenCache* IdentityAPI::token_cache() {
  return &token_cache_;
}

void IdentityAPI::SetGaiaIdForExtension(const std::string& extension_id,
                                        const GaiaId& gaia_id) {
  DCHECK(!gaia_id.empty());
  extension_prefs_->UpdateExtensionPref(extension_id, kIdentityGaiaIdPref,
                                        base::Value(gaia_id.ToString()));
}

std::optional<GaiaId> IdentityAPI::GetGaiaIdForExtension(
    const std::string& extension_id) {
  std::string gaia_id;
  if (!extension_prefs_->ReadPrefAsString(extension_id, kIdentityGaiaIdPref,
                                          &gaia_id)) {
    return std::nullopt;
  }
  return GaiaId(gaia_id);
}

void IdentityAPI::EraseGaiaIdForExtension(const std::string& extension_id) {
  extension_prefs_->UpdateExtensionPref(extension_id, kIdentityGaiaIdPref,
                                        std::nullopt);
}

void IdentityAPI::EraseStaleGaiaIdsForAllExtensions() {
  // Refresh tokens haven't been loaded yet. Wait for OnRefreshTokensLoaded() to
  // fire.
  if (!identity_manager_->AreRefreshTokensLoaded())
    return;
  auto accounts = GetAccountsWithRefreshTokensForExtensions();
  for (const ExtensionId& extension_id : extension_prefs_->GetExtensions()) {
    std::optional<GaiaId> gaia_id = GetGaiaIdForExtension(extension_id);
    if (!gaia_id)
      continue;
    if (!base::Contains(accounts, *gaia_id, &CoreAccountInfo::gaia)) {
      EraseGaiaIdForExtension(extension_id);
    }
  }
}

void IdentityAPI::Shutdown() {
  on_shutdown_callback_list_.Notify();
  identity_manager_->RemoveObserver(this);
}

static base::LazyInstance<BrowserContextKeyedAPIFactory<IdentityAPI>>::
    DestructorAtExit g_identity_api_factory = LAZY_INSTANCE_INITIALIZER;

// static
BrowserContextKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
  return g_identity_api_factory.Pointer();
}

base::CallbackListSubscription IdentityAPI::RegisterOnShutdownCallback(
    base::OnceClosure cb) {
  return on_shutdown_callback_list_.Add(std::move(cb));
}

bool IdentityAPI::AreExtensionsRestrictedToPrimaryAccount() {
  return !AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_) &&
         !AccountConsistencyModeManager::IsMirrorEnabledForProfile(profile_);
}

bool IdentityAPI::HasAccessToChromeAccounts() const {
  return identity_manager_->HasPrimaryAccount(ConsentLevel::kSignin);
}

std::vector<CoreAccountInfo>
IdentityAPI::GetAccountsWithRefreshTokensForExtensions() {
  if (!HasAccessToChromeAccounts()) {
    return {};
  }
  return identity_manager_->GetAccountsWithRefreshTokens();
}

#if BUILDFLAG(ENABLE_DICE_SUPPORT)
void IdentityAPI::MaybeShowChromeSigninDialog(
    const std::u16string& extension_name_for_display,
    base::OnceClosure on_complete) {
  if (HasAccessToChromeAccounts() ||
      identity_manager_->GetAccountsWithRefreshTokens().empty()) {
    DVLOG(1) << "The user is not signed in on the web!";
    std::move(on_complete).Run();
    return;
  }

  if (is_chrome_signin_dialog_open_) {
    DVLOG(1) << "Chrome sign in dialog is already open, extensions are not "
                "allowed to trigger more than one";
    on_chrome_signin_dialog_completed_.push_back(std::move(on_complete));
    return;
  }

  // Used in unittests to avoid creating a browser.
  if (skip_ui_for_testing_callback_) {
    HandleSkipUIForTesting(std::move(on_complete));  // IN-TEST
    return;
  }

  chrome::ScopedTabbedBrowserDisplayer displayer(profile_);
  Browser* browser = displayer.browser();
  if (!browser) {
    DVLOG(1) << "Could not create a browser to show Extensions Chrome Sign in "
                "dialog.";
    std::move(on_complete).Run();
    return;
  }
  on_chrome_signin_dialog_completed_.push_back(std::move(on_complete));
  is_chrome_signin_dialog_open_ = true;
  browser->GetFeatures()
      .signin_view_controller()
      ->MaybeShowChromeSigninDialogForExtensions(
          extension_name_for_display,
          base::BindOnce(&IdentityAPI::OnChromeSigninDialogDestroyed,
                         weak_ptr_factory_.GetWeakPtr()));
}

void IdentityAPI::OnChromeSigninDialogDestroyed() {
  is_chrome_signin_dialog_open_ = false;
  std::vector<base::OnceClosure> callbacks;
  std::swap(on_chrome_signin_dialog_completed_, callbacks);
  for (auto& callback : callbacks) {
    std::move(callback).Run();
  }
}

void IdentityAPI::HandleSkipUIForTesting(base::OnceClosure on_complete) {
  is_chrome_signin_dialog_open_ = true;
  on_chrome_signin_dialog_completed_.push_back(std::move(on_complete));
  // Allow tests to complete the flow.
  std::move(skip_ui_for_testing_callback_)
      .Run(base::BindOnce(&IdentityAPI::OnChromeSigninDialogDestroyed,
                          weak_ptr_factory_.GetWeakPtr()));
  return;
}
#endif

IdentityAPI::IdentityAPI(Profile* profile,
                         signin::IdentityManager* identity_manager,
                         ExtensionPrefs* extension_prefs,
                         EventRouter* event_router)
    : profile_(profile),
      identity_manager_(identity_manager),
      extension_prefs_(extension_prefs),
      event_router_(event_router) {
  identity_manager_->AddObserver(this);
  EraseStaleGaiaIdsForAllExtensions();
}

void IdentityAPI::OnPrimaryAccountChanged(
    const PrimaryAccountChangeEvent& event_details) {
  switch (event_details.GetEventTypeFor(ConsentLevel::kSignin)) {
    case signin::PrimaryAccountChangeEvent::Type::kNone:
      break;
    case signin::PrimaryAccountChangeEvent::Type::kSet:
      for (auto& account : GetAccountsWithRefreshTokensForExtensions()) {
        OnRefreshTokenUpdatedForAccount(account);
      }
      break;
    case signin::PrimaryAccountChangeEvent::Type::kCleared:
      EraseStaleGaiaIdsForAllExtensions();
      base::flat_set<GaiaId> tracked_accounts;
      std::swap(tracked_accounts, accounts_known_to_extensions_);
      for (auto& account_id : tracked_accounts) {
        FireOnAccountSignInChanged(account_id, /*is_signed_in=*/false);
      }
      break;
  }
}

void IdentityAPI::OnRefreshTokensLoaded() {
  EraseStaleGaiaIdsForAllExtensions();
}

void IdentityAPI::OnRefreshTokenUpdatedForAccount(
    const CoreAccountInfo& account_info) {
  // Refresh tokens are sometimes made available in contexts where
  // AccountTrackerService is not tracking the account in question. Bail out in
  // these cases.
  if (!HasAccessToChromeAccounts() || account_info.gaia.empty()) {
    return;
  }
  accounts_known_to_extensions_.insert(account_info.gaia);
  FireOnAccountSignInChanged(account_info.gaia, true);
}

void IdentityAPI::OnExtendedAccountInfoRemoved(
    const AccountInfo& account_info) {
  DCHECK(!account_info.gaia.empty());
  EraseStaleGaiaIdsForAllExtensions();

  auto it = accounts_known_to_extensions_.find(account_info.gaia);
  if (it == accounts_known_to_extensions_.end()) {
    // Account unknown to Extensions.
    return;
  }
  accounts_known_to_extensions_.erase(it);
  FireOnAccountSignInChanged(account_info.gaia, false);
}

void IdentityAPI::FireOnAccountSignInChanged(const GaiaId& gaia_id,
                                             bool is_signed_in) {
  CHECK(!gaia_id.empty());
  api::identity::AccountInfo api_account_info;
  api_account_info.id = gaia_id.ToString();

  auto args =
      api::identity::OnSignInChanged::Create(api_account_info, is_signed_in);
  std::unique_ptr<Event> event(new Event(
      events::IDENTITY_ON_SIGN_IN_CHANGED,
      api::identity::OnSignInChanged::kEventName, std::move(args), profile_));

  if (on_signin_changed_callback_for_testing_)
    on_signin_changed_callback_for_testing_.Run(event.get());

  event_router_->BroadcastEvent(std::move(event));
}

template <>
void BrowserContextKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
  DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());

  DependsOn(ChromeSigninClientFactory::GetInstance());
  DependsOn(IdentityManagerFactory::GetInstance());
}

}  // namespace extensions
