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

#include "content/browser/devtools/protocol/fedcm_handler.h"

#include <optional>

#include "base/strings/string_number_conversions.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/webid/request_page_data.h"
#include "content/browser/webid/request_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/webid/federated_identity_api_permission_context_delegate.h"
#include "content/public/browser/webid/identity_request_dialog_controller.h"

namespace content {
namespace {
namespace FedCm = protocol::FedCm;

using DialogType = webid::RequestService::DialogType;

FedCm::DialogType ConvertDialogType(DialogType type) {
  switch (type) {
    case DialogType::kNone:
      NOTREACHED() << "This should only be called if there is a dialog";
    case DialogType::kLoginToIdpPopup:
    case DialogType::kContinueOnPopup:
    case DialogType::kErrorUrlPopup:
      NOTREACHED()
          << "These dialog types are not currently exposed to automation";
    case DialogType::kSelectAccount:
      return FedCm::DialogTypeEnum::AccountChooser;
    case DialogType::kAutoReauth:
      return FedCm::DialogTypeEnum::AutoReauthn;
    case DialogType::kConfirmIdpLogin:
      return FedCm::DialogTypeEnum::ConfirmIdpLogin;
    case DialogType::kError:
      return FedCm::DialogTypeEnum::Error;
  }
}

}  // namespace

namespace protocol {

FedCmHandler::FedCmHandler()
    : DevToolsDomainHandler(FedCm::Metainfo::domainName) {}

FedCmHandler::~FedCmHandler() = default;

// static
std::vector<FedCmHandler*> FedCmHandler::ForAgentHost(
    DevToolsAgentHostImpl* host) {
  return host->HandlersByName<FedCmHandler>(FedCm::Metainfo::domainName);
}

void FedCmHandler::SetRenderer(int process_host_id,
                               RenderFrameHostImpl* frame_host) {
  frame_host_ = frame_host;
}

void FedCmHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ = std::make_unique<FedCm::Frontend>(dispatcher->channel());
  FedCm::Dispatcher::wire(dispatcher, this);
}

DispatchResponse FedCmHandler::Enable(
    std::optional<bool> in_disableRejectionDelay) {
  auto* auth_request = GetFederatedAuthRequest();
  bool was_enabled = enabled_;
  enabled_ = true;
  disable_delay_ = in_disableRejectionDelay.value_or(false);

  // OnDialogShown should have been called previously if was_enabled is true.
  // This could happen if FedCmHandler::Enable was called to enable/disable the
  // rejection delay.
  if (!was_enabled && auth_request &&
      auth_request->GetDialogType() != DialogType::kNone) {
    DidShowDialog();
  }

  return DispatchResponse::Success();
}

DispatchResponse FedCmHandler::Disable() {
  enabled_ = false;
  return DispatchResponse::Success();
}

void FedCmHandler::DidShowDialog() {
  DCHECK(frontend_);
  if (!enabled_) {
    return;
  }

  static int next_dialog_id_ = 0;
  dialog_id_ = base::NumberToString(next_dialog_id_++);

  auto* auth_request = GetFederatedAuthRequest();
  const auto* accounts = GetAccounts(auth_request);
  // `accounts` can be empty if this is an IDP Signin Confirmation dialog.
  auto accounts_array = std::make_unique<Array<FedCm::Account>>();
  if (accounts) {
    for (const auto& account : *accounts) {
      FedCm::LoginState login_state;
      std::optional<std::string> tos_url;
      std::optional<std::string> pp_url;
      switch (account->idp_claimed_login_state.value_or(
          account->browser_trusted_login_state)) {
        case IdentityRequestAccount::LoginState::kSignUp:
          login_state = FedCm::LoginStateEnum::SignUp;
          // Because TOS and PP URLs are only used when the login state is
          // sign up, we only populate them in that case.
          pp_url = account->identity_provider->client_metadata
                       .privacy_policy_url.spec();
          tos_url = account->identity_provider->client_metadata
                        .terms_of_service_url.spec();
          break;
        case IdentityRequestAccount::LoginState::kSignIn:
          login_state = FedCm::LoginStateEnum::SignIn;
          break;
      }
      std::unique_ptr<FedCm::Account> entry =
          FedCm::Account::Create()
              .SetAccountId(account->id)
              .SetEmail(account->display_identifier)
              .SetName(account->display_name)
              .SetGivenName(account->given_name)
              .SetPictureUrl(account->picture.spec())
              .SetIdpConfigUrl(
                  account->identity_provider->idp_metadata.config_url.spec())
              .SetIdpLoginUrl(
                  account->identity_provider->idp_metadata.idp_login_url.spec())
              .SetLoginState(login_state)
              .Build();
      if (pp_url) {
        entry->SetPrivacyPolicyUrl(*pp_url);
      }
      if (tos_url) {
        entry->SetTermsOfServiceUrl(*tos_url);
      }
      accounts_array->push_back(std::move(entry));
    }
  }
  IdentityRequestDialogController* dialog = auth_request->GetDialogController();
  CHECK(dialog);

  FedCm::DialogType dialog_type =
      ConvertDialogType(auth_request->GetDialogType());
  std::optional<String> maybe_subtitle;
  std::optional<std::string> subtitle = dialog->GetSubtitle();
  if (subtitle) {
    maybe_subtitle = *subtitle;
  }
  frontend_->DialogShown(dialog_id_, dialog_type, std::move(accounts_array),
                         dialog->GetTitle(), std::move(maybe_subtitle));
}

void FedCmHandler::DidCloseDialog() {
  CHECK(frontend_);
  if (!enabled_) {
    return;
  }
  frontend_->DialogClosed(dialog_id_);
}

DispatchResponse FedCmHandler::SelectAccount(const String& in_dialogId,
                                             int in_accountIndex) {
  if (in_dialogId != dialog_id_) {
    return DispatchResponse::InvalidParams(
        "Dialog ID does not match current dialog");
  }

  auto* auth_request = GetFederatedAuthRequest();
  if (!GetIdentityProviderData(auth_request)) {
    return DispatchResponse::ServerError(
        "selectAccount called while no FedCm dialog is shown");
  }
  const auto* accounts = GetAccounts(auth_request);
  if (!accounts || in_accountIndex < 0 ||
      static_cast<size_t>(in_accountIndex) >= accounts->size()) {
    return DispatchResponse::InvalidParams("Invalid account index");
  }

  const auto& account = accounts->at(in_accountIndex);
  auth_request->AcceptAccountsDialogForDevtools(
      account->identity_provider->idp_metadata.config_url, *account);
  return DispatchResponse::Success();
}

DispatchResponse FedCmHandler::OpenUrl(
    const String& in_dialogId,
    int in_accountIndex,
    const FedCm::AccountUrlType& in_accountUrlType) {
  if (in_dialogId != dialog_id_) {
    return DispatchResponse::InvalidParams(
        "Dialog ID does not match current dialog");
  }

  auto* auth_request = GetFederatedAuthRequest();
  if (!GetIdentityProviderData(auth_request)) {
    return DispatchResponse::ServerError(
        "openUrl called while no FedCm dialog is shown");
  }

  const auto* accounts = GetAccounts(auth_request);
  if (!accounts || in_accountIndex < 0 ||
      static_cast<size_t>(in_accountIndex) >= accounts->size()) {
    return DispatchResponse::InvalidParams("Invalid account index");
  }

  const auto& account = accounts->at(in_accountIndex);
  IdentityRequestDialogController::LinkType type;
  GURL url;
  if (in_accountUrlType == FedCm::AccountUrlTypeEnum::TermsOfService) {
    type = IdentityRequestDialogController::LinkType::TERMS_OF_SERVICE;
    url = account->identity_provider->client_metadata.terms_of_service_url;
  } else if (in_accountUrlType == FedCm::AccountUrlTypeEnum::PrivacyPolicy) {
    type = IdentityRequestDialogController::LinkType::PRIVACY_POLICY;
    url = account->identity_provider->client_metadata.privacy_policy_url;
  } else {
    return DispatchResponse::InvalidParams("Invalid account URL type");
  }
  if (!url.is_valid() || account->fields.empty()) {
    return DispatchResponse::InvalidParams(
        "Account does not have requested URL");
  }
  auth_request->GetDialogController()->ShowUrl(type, url);
  return DispatchResponse::Success();
}

DispatchResponse FedCmHandler::ClickDialogButton(
    const String& in_dialogId,
    const FedCm::DialogButton& in_dialogButton) {
  if (in_dialogId != dialog_id_) {
    return DispatchResponse::InvalidParams(
        "Dialog ID does not match current dialog");
  }

  auto* auth_request = GetFederatedAuthRequest();
  if (!auth_request) {
    return DispatchResponse::ServerError(
        "clickDialogButton called while no FedCm dialog is shown");
  }

  DialogType type = auth_request->GetDialogType();
  if (in_dialogButton == FedCm::DialogButtonEnum::ConfirmIdpLoginContinue) {
    switch (type) {
      case DialogType::kConfirmIdpLogin:
        auth_request->AcceptConfirmIdpLoginDialogForDevtools();
        return DispatchResponse::Success();
      case DialogType::kSelectAccount: {
        const auto* idp_data = GetIdentityProviderData(auth_request);
        CHECK(idp_data) << "kSelectAccount should always have IDP data";
        CHECK(!idp_data->empty());
        if (idp_data->size() > 1) {
          return DispatchResponse::ServerError(
              "Multi-IDP not supported for ConfirmIdpLogin yet "
              "(crbug.com/328115461)");
        }
        if (!auth_request->UseAnotherAccountForDevtools(*idp_data->at(0))) {
          return DispatchResponse::ServerError(
              "'Use another account' not supported for this IDP");
        }
        return DispatchResponse::Success();
      }
      default:
        return DispatchResponse::ServerError(
            "clickDialogButton called with ConfirmIdpLoginContinue while no "
            "confirm IDP login dialog is shown");
    }
  } else if (in_dialogButton == FedCm::DialogButtonEnum::ErrorGotIt) {
    if (type != DialogType::kError) {
      return DispatchResponse::ServerError(
          "clickDialogButton called with ErrorGotIt while no error dialog is "
          "shown");
    }
    auth_request->ClickErrorDialogGotItForDevtools();
    return DispatchResponse::Success();
  } else if (in_dialogButton == FedCm::DialogButtonEnum::ErrorMoreDetails) {
    if (type != DialogType::kError) {
      return DispatchResponse::ServerError(
          "clickDialogButton called with ErrorMoreDetails while no error "
          "dialog is shown");
    } else if (!auth_request->HasMoreDetailsButtonForDevtools()) {
      return DispatchResponse::ServerError(
          "clickDialogButton called with ErrorMoreDetails but more details "
          "button is not shown");
    }
    auth_request->ClickErrorDialogMoreDetailsForDevtools();
    return DispatchResponse::Success();
  }
  return DispatchResponse::InvalidParams("Invalid dialog button");
}

DispatchResponse FedCmHandler::DismissDialog(
    const String& in_dialogId,
    std::optional<bool> in_triggerCooldown) {
  if (in_dialogId != dialog_id_) {
    return DispatchResponse::InvalidParams(
        "Dialog ID does not match current dialog");
  }

  auto* auth_request = GetFederatedAuthRequest();
  if (!auth_request){
    return DispatchResponse::ServerError(
        "dismissDialog called while no FedCm dialog is shown");
  }

  DialogType type = auth_request->GetDialogType();
  if (type == DialogType::kConfirmIdpLogin) {
    auth_request->DismissConfirmIdpLoginDialogForDevtools();
    return DispatchResponse::Success();
  }
  if (type == DialogType::kError) {
    auth_request->DismissErrorDialogForDevtools();
    return DispatchResponse::Success();
  }
  const auto* idp_data = GetIdentityProviderData(auth_request);
  if (!idp_data) {
    return DispatchResponse::ServerError(
        "cancelDialog called while no FedCm dialog is shown");
  }

  auth_request->DismissAccountsDialogForDevtools(
      in_triggerCooldown.value_or(false));
  return DispatchResponse::Success();
}

DispatchResponse FedCmHandler::ResetCooldown() {
  auto* context = GetApiPermissionContext();
  if (!context) {
    return DispatchResponse::ServerError("no frame host");
  }
  context->RemoveEmbargoAndResetCounts(GetEmbeddingOrigin());
  return DispatchResponse::Success();
}

url::Origin FedCmHandler::GetEmbeddingOrigin() {
  CHECK(frame_host_);
  CHECK(frame_host_->GetMainFrame());
  return frame_host_->GetMainFrame()->GetLastCommittedOrigin();
}

webid::RequestPageData* FedCmHandler::GetPageData() {
  if (!frame_host_) {
    return nullptr;
  }
  Page& page = frame_host_->GetPage();
  return PageUserData<webid::RequestPageData>::GetOrCreateForPage(page);
}

webid::RequestService* FedCmHandler::GetFederatedAuthRequest() {
  webid::RequestPageData* page_data = GetPageData();
  if (!page_data) {
    return nullptr;
  }
  return page_data->PendingWebIdentityRequest();
}

const std::vector<IdentityProviderDataPtr>*
FedCmHandler::GetIdentityProviderData(webid::RequestService* auth_request) {
  if (!auth_request) {
    return nullptr;
  }
  const auto& idp_data = auth_request->GetSortedIdpData();
  // idp_data is empty iff no dialog is shown.
  if (idp_data.empty()) {
    return nullptr;
  }
  return &idp_data;
}

const std::vector<IdentityRequestAccountPtr>* FedCmHandler::GetAccounts(
    webid::RequestService* auth_request) {
  if (!auth_request) {
    return nullptr;
  }
  const auto& accounts = auth_request->GetAccounts();
  if (accounts.empty()) {
    return nullptr;
  }
  return &accounts;
}

FederatedIdentityApiPermissionContextDelegate*
FedCmHandler::GetApiPermissionContext() {
  if (!frame_host_) {
    return nullptr;
  }
  return frame_host_->GetBrowserContext()
      ->GetFederatedIdentityApiPermissionContext();
}

}  // namespace protocol
}  // namespace content
