chromium/chrome/browser/permissions/permission_infobar_delegate_android.cc

// Copyright 2022 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/permissions/permission_infobar_delegate_android.h"

#include "base/memory/ptr_util.h"
#include "chrome/browser/android/android_theme_resources.h"
#include "chrome/browser/permissions/quiet_notification_permission_ui_config.h"
#include "chrome/browser/permissions/quiet_notification_permission_ui_state.h"
#include "chrome/browser/ui/android/infobars/permission_infobar.h"
#include "chrome/grit/generated_resources.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/infobars/core/infobar.h"
#include "components/permissions/android/permission_prompt/permission_prompt_android.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_request_manager.h"
#include "components/permissions/permission_uma_util.h"
#include "components/permissions/permission_util.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/elide_url.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/strings/grit/ui_strings.h"

namespace {

using PrimaryButtonBehavior =
    QuietPermissionPromptModelAndroid::PrimaryButtonBehavior;
using SecondaryButtonBehavior =
    QuietPermissionPromptModelAndroid::SecondaryButtonBehavior;

}  // namespace

PermissionInfoBarDelegate::~PermissionInfoBarDelegate() {
  permissions::PermissionUmaUtil::RecordInfobarDetailsExpanded(
      details_expanded_);
}

// static
infobars::InfoBar* PermissionInfoBarDelegate::Create(
    const base::WeakPtr<permissions::PermissionPromptAndroid>&
        permission_prompt,
    infobars::ContentInfoBarManager* infobar_manager) {
  // WrapUnique needs to be used because the constructor is private.
  return infobar_manager->AddInfoBar(
      std::make_unique<PermissionInfoBar>(base::WrapUnique(
          new PermissionInfoBarDelegate(permission_prompt, infobar_manager))));
}

size_t PermissionInfoBarDelegate::PermissionCount() const {
  return permission_prompt_->PermissionCount();
}

ContentSettingsType PermissionInfoBarDelegate::GetContentSettingType(
    size_t position) const {
  return permission_prompt_->GetContentSettingType(position);
}

std::u16string PermissionInfoBarDelegate::GetCompactMessageText() const {
  return l10n_util::GetStringUTF16(
      IDS_NOTIFICATION_QUIET_PERMISSION_MINI_INFOBAR_MESSAGE);
}

std::u16string PermissionInfoBarDelegate::GetCompactLinkText() const {
  switch (QuietNotificationPermissionUiConfig::GetMiniInfobarExpandLinkText()) {
    case QuietNotificationPermissionUiConfig::InfobarLinkTextVariation::kManage:
      return l10n_util::GetStringUTF16(IDS_NOTIFICATION_BUTTON_MANAGE);
    case QuietNotificationPermissionUiConfig::InfobarLinkTextVariation::
        kDetails:
      return l10n_util::GetStringUTF16(
          IDS_NOTIFICATION_QUIET_PERMISSION_MINI_INFOBAR_DETAILS_LINK);
  }

  NOTREACHED_IN_MIGRATION();
  return std::u16string();
}

// TODO(crbug.com/40131069): Many methods of this class switches on the quiet UI
// reason. Refactor this into separate subclasses instead.
std::u16string PermissionInfoBarDelegate::GetDescriptionText() const {
  return prompt_model_.description;
}

bool PermissionInfoBarDelegate::ShouldSecondaryButtonOpenSettings() const {
  return prompt_model_.secondary_button_behavior ==
         SecondaryButtonBehavior::kShowSettings;
}

int PermissionInfoBarDelegate::GetIconId() const {
  return IDR_ANDROID_INFOBAR_NOTIFICATIONS_OFF;
}

std::u16string PermissionInfoBarDelegate::GetLinkText() const {
  // This will be used as the text of the link in the expanded state.
  return prompt_model_.learn_more_text;
}

GURL PermissionInfoBarDelegate::GetLinkURL() const {
  return GetNotificationBlockedLearnMoreUrl();
}

bool PermissionInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
  // The link shown in the compact state should expand the infobar, and do
  // nothing more. This is handled entirely in PermissionInfoBar.java.
  if (!details_expanded_) {
    details_expanded_ = true;
    return false;
  }

  permission_prompt_->SetLearnMoreClicked();
  // The link shown in the expanded state is a `Learn more` link. Let the base
  // class handle opening the URL returned by GetLinkURL().
  return ConfirmInfoBarDelegate::LinkClicked(disposition);
}

void PermissionInfoBarDelegate::InfoBarDismissed() {
  if (permission_prompt_)
    permission_prompt_->Closing();
}

std::u16string PermissionInfoBarDelegate::GetMessageText() const {
  return prompt_model_.title;
}

bool PermissionInfoBarDelegate::Accept() {
  if (!permission_prompt_)
    return true;

  switch (prompt_model_.primary_button_behavior) {
    case PrimaryButtonBehavior::kAllowForThisSite:
      permission_prompt_->Accept();
      break;
    case PrimaryButtonBehavior::kContinueBlocking:
      permission_prompt_->Deny();
      break;
  }
  return true;
}

bool PermissionInfoBarDelegate::Cancel() {
  if (!permission_prompt_)
    return true;
  switch (prompt_model_.secondary_button_behavior) {
    case SecondaryButtonBehavior::kShowSettings:
      // The infobar needs to be kept open after the "Manage" button is clicked.
      permission_prompt_->SetManageClicked();
      return false;
    case SecondaryButtonBehavior::kAllowForThisSite:
      permission_prompt_->Accept();
      return true;
  }
  NOTREACHED_IN_MIGRATION();
  return true;
}

PermissionInfoBarDelegate::PermissionInfoBarDelegate(
    const base::WeakPtr<permissions::PermissionPromptAndroid>&
        permission_prompt,
    infobars::ContentInfoBarManager* infobar_manager)
    : permission_prompt_(permission_prompt),
      infobar_manager_(infobar_manager),
      details_expanded_(false) {
  DCHECK(permission_prompt_);
  DCHECK(infobar_manager_);

  // Infobars are only used for NOTIFICATIONS right now, therefore strings can
  // be hardcoded for that type.
  DCHECK_EQ(permission_prompt_->GetContentSettingType(0u),
            ContentSettingsType::NOTIFICATIONS);

  auto* manager = permissions::PermissionRequestManager::FromWebContents(
      permission_prompt_->web_contents());

  auto quiet_ui_reason = manager->ReasonForUsingQuietUi();
  DCHECK(quiet_ui_reason);
  prompt_model_ = GetQuietPermissionPromptModel(
      *quiet_ui_reason, ContentSettingsType::NOTIFICATIONS);
}

infobars::InfoBarDelegate::InfoBarIdentifier
PermissionInfoBarDelegate::GetIdentifier() const {
  return PERMISSION_INFOBAR_DELEGATE_ANDROID;
}

int PermissionInfoBarDelegate::GetButtons() const {
  return BUTTON_OK | BUTTON_CANCEL;
}

std::u16string PermissionInfoBarDelegate::GetButtonLabel(
    InfoBarButton button) const {
  return (button == BUTTON_OK) ? prompt_model_.primary_button_label
                               : prompt_model_.secondary_button_label;
}

bool PermissionInfoBarDelegate::EqualsDelegate(
    infobars::InfoBarDelegate* delegate) const {
  // The PermissionRequestManager doesn't create duplicate infobars so a pointer
  // equality check is sufficient.
  return this == delegate;
}