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

#include "components/permissions/permission_uma_util.h"

#include <cstdint>
#include <utility>

#include "base/command_line.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/content_settings/core/browser/content_settings_uma_util.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/features.h"
#include "components/permissions/constants.h"
#include "components/permissions/permission_actions_history.h"
#include "components/permissions/permission_decision_auto_blocker.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_util.h"
#include "components/permissions/permissions_client.h"
#include "components/permissions/prediction_service/prediction_common.h"
#include "components/permissions/prediction_service/prediction_request_features.h"
#include "components/permissions/request_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "printing/buildflags/buildflags.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_string.h"
#endif

namespace {
bool scoped_revocation_reporter_in_scope = false;
}  // namespace

namespace permissions {

#define PERMISSION_BUBBLE_TYPE_UMA(metric_name, request_type_for_uma) \
  base::UmaHistogramEnumeration(metric_name, request_type_for_uma,    \
                                RequestTypeForUma::NUM)

#define PERMISSION_BUBBLE_GESTURE_TYPE_UMA(                                  \
    gesture_metric_name, no_gesture_metric_name, gesture_type,               \
    permission_bubble_type)                                                  \
  if (gesture_type == PermissionRequestGestureType::GESTURE) {               \
    PERMISSION_BUBBLE_TYPE_UMA(gesture_metric_name, permission_bubble_type); \
  } else if (gesture_type == PermissionRequestGestureType::NO_GESTURE) {     \
    PERMISSION_BUBBLE_TYPE_UMA(no_gesture_metric_name,                       \
                               permission_bubble_type);                      \
  }

using blink::PermissionType;

namespace {

RequestTypeForUma GetUmaValueForRequestType(RequestType request_type) {
  switch (request_type) {
    case RequestType::kAccessibilityEvents:
      return RequestTypeForUma::PERMISSION_ACCESSIBILITY_EVENTS;
    case RequestType::kArSession:
      return RequestTypeForUma::PERMISSION_AR;
#if !BUILDFLAG(IS_ANDROID)
    case RequestType::kCameraPanTiltZoom:
      return RequestTypeForUma::PERMISSION_CAMERA_PAN_TILT_ZOOM;
#endif
    case RequestType::kCameraStream:
      return RequestTypeForUma::PERMISSION_MEDIASTREAM_CAMERA;
    case RequestType::kClipboard:
      return RequestTypeForUma::PERMISSION_CLIPBOARD_READ_WRITE;
    case RequestType::kDiskQuota:
      return RequestTypeForUma::QUOTA;
#if !BUILDFLAG(IS_ANDROID)
    // TODO(crbug.com/40214907): Enable on Android
    case RequestType::kLocalFonts:
      return RequestTypeForUma::PERMISSION_LOCAL_FONTS;
#endif
    case RequestType::kGeolocation:
      return RequestTypeForUma::PERMISSION_GEOLOCATION;
    case RequestType::kIdleDetection:
      return RequestTypeForUma::PERMISSION_IDLE_DETECTION;
    case RequestType::kMicStream:
      return RequestTypeForUma::PERMISSION_MEDIASTREAM_MIC;
    case RequestType::kMidiSysex:
      return RequestTypeForUma::PERMISSION_MIDI_SYSEX;
    case RequestType::kMultipleDownloads:
      return RequestTypeForUma::DOWNLOAD;
#if BUILDFLAG(IS_ANDROID)
    case RequestType::kNfcDevice:
      return RequestTypeForUma::PERMISSION_NFC;
#endif
    case RequestType::kNotifications:
      return RequestTypeForUma::PERMISSION_NOTIFICATIONS;
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
    case RequestType::kProtectedMediaIdentifier:
      return RequestTypeForUma::PERMISSION_PROTECTED_MEDIA_IDENTIFIER;
#endif
#if !BUILDFLAG(IS_ANDROID)
    case RequestType::kRegisterProtocolHandler:
      return RequestTypeForUma::REGISTER_PROTOCOL_HANDLER;
#endif
#if BUILDFLAG(IS_CHROMEOS)
    case RequestType::kSmartCard:
      return RequestTypeForUma::PERMISSION_SMART_CARD;
#endif
    case RequestType::kStorageAccess:
      return RequestTypeForUma::PERMISSION_STORAGE_ACCESS;
    case RequestType::kVrSession:
      return RequestTypeForUma::PERMISSION_VR;
#if BUILDFLAG(IS_CHROMEOS) && BUILDFLAG(USE_CUPS)
    case RequestType::kWebPrinting:
      return RequestTypeForUma::PERMISSION_WEB_PRINTING;
#endif
#if !BUILDFLAG(IS_ANDROID)
    case RequestType::kWindowManagement:
      return RequestTypeForUma::PERMISSION_WINDOW_MANAGEMENT;
#endif
    case RequestType::kTopLevelStorageAccess:
      return RequestTypeForUma::PERMISSION_TOP_LEVEL_STORAGE_ACCESS;
#if !BUILDFLAG(IS_ANDROID)
    case RequestType::kFileSystemAccess:
      return RequestTypeForUma::PERMISSION_FILE_SYSTEM_ACCESS;
    case RequestType::kCapturedSurfaceControl:
      return RequestTypeForUma::CAPTURED_SURFACE_CONTROL;
#endif
    case RequestType::kIdentityProvider:
      return RequestTypeForUma::PERMISSION_IDENTITY_PROVIDER;
  }
}

const int kPriorCountCap = 10;

std::string GetPermissionRequestString(RequestTypeForUma type) {
  switch (type) {
    case RequestTypeForUma::MULTIPLE:
      return "AudioAndVideoCapture";
    case RequestTypeForUma::QUOTA:
      return "Quota";
    case RequestTypeForUma::DOWNLOAD:
      return "MultipleDownload";
    case RequestTypeForUma::REGISTER_PROTOCOL_HANDLER:
      return "RegisterProtocolHandler";
    case RequestTypeForUma::PERMISSION_GEOLOCATION:
      return "Geolocation";
    case RequestTypeForUma::PERMISSION_MIDI_SYSEX:
      return "MidiSysEx";
    case RequestTypeForUma::PERMISSION_NOTIFICATIONS:
      return "Notifications";
    case RequestTypeForUma::PERMISSION_PROTECTED_MEDIA_IDENTIFIER:
      return "ProtectedMedia";
    case RequestTypeForUma::PERMISSION_MEDIASTREAM_MIC:
      return "AudioCapture";
    case RequestTypeForUma::PERMISSION_MEDIASTREAM_CAMERA:
      return "VideoCapture";
    case RequestTypeForUma::PERMISSION_PAYMENT_HANDLER:
      return "PaymentHandler";
    case RequestTypeForUma::PERMISSION_NFC:
      return "Nfc";
    case RequestTypeForUma::PERMISSION_CLIPBOARD_READ_WRITE:
      return "ClipboardReadWrite";
    case RequestTypeForUma::PERMISSION_VR:
      return "VR";
    case RequestTypeForUma::PERMISSION_AR:
      return "AR";
    case RequestTypeForUma::PERMISSION_STORAGE_ACCESS:
      return "StorageAccess";
    case RequestTypeForUma::PERMISSION_TOP_LEVEL_STORAGE_ACCESS:
      return "TopLevelStorageAccess";
    case RequestTypeForUma::PERMISSION_CAMERA_PAN_TILT_ZOOM:
      return "CameraPanTiltZoom";
    case RequestTypeForUma::PERMISSION_WINDOW_MANAGEMENT:
      return "WindowManagement";
    case RequestTypeForUma::PERMISSION_LOCAL_FONTS:
      return "LocalFonts";
    case RequestTypeForUma::PERMISSION_IDLE_DETECTION:
      return "IdleDetection";
    case RequestTypeForUma::PERMISSION_ACCESSIBILITY_EVENTS:
      return "AccessibilityEvents";
    case RequestTypeForUma::PERMISSION_FILE_SYSTEM_ACCESS:
      return "FileSystemAccess";
    case RequestTypeForUma::CAPTURED_SURFACE_CONTROL:
      return "CapturedSurfaceControl";
    case RequestTypeForUma::PERMISSION_SMART_CARD:
      return "SmartCard";
    case RequestTypeForUma::PERMISSION_WEB_PRINTING:
      return "WebPrinting";
    case RequestTypeForUma::PERMISSION_IDENTITY_PROVIDER:
      return "IdentityProvider";

    case RequestTypeForUma::UNKNOWN:
    case RequestTypeForUma::PERMISSION_FLASH:
    case RequestTypeForUma::PERMISSION_FILE_HANDLING:
    case RequestTypeForUma::NUM:
      NOTREACHED();
      return "";
  }
}

// Helper to check if the current render frame host is cross-origin with top
// level frame. Note: in case of nested frames like A(B(A)), the bottom frame A
// will get |IsCrossOriginSubframe| returns false.
bool IsCrossOriginSubframe(content::RenderFrameHost* render_frame_host) {
  DCHECK(render_frame_host);

  // Permissions are denied for fenced frames and other inner pages.
  // |GetMainFrame| should be enough to get top level frame.
  auto current_origin = render_frame_host->GetLastCommittedOrigin();
  return !render_frame_host->GetMainFrame()
              ->GetLastCommittedOrigin()
              .IsSameOriginWith(current_origin);
}

// Helper to check if the current render frame host is cross-origin with any of
// its parents.
bool IsCrossOriginWithAnyParent(content::RenderFrameHost* render_frame_host) {
  const url::Origin& current_origin =
      render_frame_host->GetLastCommittedOrigin();
  content::RenderFrameHost* parent = render_frame_host->GetParent();
  while (parent) {
    const url::Origin& parent_origin = parent->GetLastCommittedOrigin();
    if (!parent_origin.IsSameOriginWith(current_origin)) {
      return true;
    }
    parent = parent->GetParent();
  }
  return false;
}

// Helper to get permission policy header policy for the top-level frame.
// render_frame_host could be the top-level frame or a descendant of top-level
// frame.
PermissionHeaderPolicyForUMA GetTopLevelPermissionHeaderPolicyForUMA(
    content::RenderFrameHost* render_frame_host,
    blink::mojom::PermissionsPolicyFeature feature) {
  const auto& parsed_permission_policy_header =
      render_frame_host->GetMainFrame()->GetPermissionsPolicyHeader();
  if (parsed_permission_policy_header.empty()) {
    return PermissionHeaderPolicyForUMA::HEADER_NOT_PRESENT_OR_INVALID;
  }

  const auto* permissions_policy =
      render_frame_host->GetMainFrame()->GetPermissionsPolicy();
  const auto& allowlists = permissions_policy->allowlists();
  auto allowlist = allowlists.find(feature);
  if (allowlist == allowlists.end()) {
    return PermissionHeaderPolicyForUMA::FEATURE_NOT_PRESENT;
  }

  if (allowlist->second.MatchesAll()) {
    return PermissionHeaderPolicyForUMA::FEATURE_ALLOWLIST_IS_WILDCARD;
  }

  const auto& origin = render_frame_host->GetLastCommittedOrigin();
  return allowlist->second.Contains(origin)
             ? PermissionHeaderPolicyForUMA::
                   FEATURE_ALLOWLIST_EXPLICITLY_MATCHES_ORIGIN
             : PermissionHeaderPolicyForUMA::
                   FEATURE_ALLOWLIST_DOES_NOT_MATCH_ORIGIN;
}

void RecordEngagementMetric(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    content::WebContents* web_contents,
    const std::string& action) {
  CHECK(!requests.empty());

  RequestTypeForUma type =
      GetUmaValueForRequestType(requests[0]->request_type());
  if (requests.size() > 1)
    type = RequestTypeForUma::MULTIPLE;

  DCHECK(action == "Accepted" || action == "Denied" || action == "Dismissed" ||
         action == "Ignored" || action == "AcceptedOnce");
  std::string name = "Permissions.Engagement." + action + '.' +
                     GetPermissionRequestString(type);

  double engagement_score = PermissionsClient::Get()->GetSiteEngagementScore(
      web_contents->GetBrowserContext(), requests[0]->requesting_origin());
  base::UmaHistogramPercentageObsoleteDoNotUse(name, engagement_score);
}

// Records in a UMA histogram whether we should expect to see an event in UKM,
// to allow for evaluating if the current constraints on UKM recording work well
// in practice.
void RecordUmaForWhetherRevocationUkmWasRecorded(
    ContentSettingsType permission_type,
    bool has_source_id) {
  if (permission_type == ContentSettingsType::NOTIFICATIONS) {
    base::UmaHistogramBoolean(
        "Permissions.Revocation.Notifications.DidRecordUkm", has_source_id);
  }
}

// Records in a UMA histogram whether we should expect to see an event in UKM,
// to allow for evaluating if the current constraints on UKM recording work well
// in practice.
void RecordUmaForWhetherUsageUkmWasRecorded(ContentSettingsType permission_type,
                                            bool has_source_id) {
  if (permission_type == ContentSettingsType::NOTIFICATIONS) {
    base::UmaHistogramBoolean("Permissions.Usage.Notifications.DidRecordUkm",
                              has_source_id);
  }
}

void RecordUmaForRevocationSourceUI(ContentSettingsType permission_type,
                                    PermissionSourceUI source_ui) {
  if (permission_type == ContentSettingsType::NOTIFICATIONS) {
    base::UmaHistogramEnumeration(
        "Permissions.Revocation.Notifications.SourceUI", source_ui);
  }
}

void RecordPermissionUsageUkm(ContentSettingsType permission_type,
                              std::optional<ukm::SourceId> source_id) {
  RecordUmaForWhetherUsageUkmWasRecorded(permission_type,
                                         source_id.has_value());
  if (!source_id.has_value())
    return;

  ukm::builders::PermissionUsage builder(source_id.value());
  builder.SetPermissionType(static_cast<int64_t>(
      content_settings_uma_util::ContentSettingTypeToHistogramValue(
          permission_type)));
  builder.Record(ukm::UkmRecorder::Get());
}

void RecordPermissionActionUkm(
    PermissionAction action,
    PermissionRequestGestureType gesture_type,
    ContentSettingsType permission,
    int dismiss_count,
    int ignore_count,
    PermissionSourceUI source_ui,
    base::TimeDelta time_to_decision,
    PermissionPromptDisposition ui_disposition,
    std::optional<PermissionPromptDispositionReason> ui_reason,
    std::optional<std::vector<ElementAnchoredBubbleVariant>> variants,
    std::optional<bool> has_three_consecutive_denies,
    std::optional<bool> has_previously_revoked_permission,
    std::optional<PermissionUmaUtil::PredictionGrantLikelihood>
        predicted_grant_likelihood,
    PredictionRequestFeatures::ActionCounts
        loud_ui_actions_counts_for_request_type,
    PredictionRequestFeatures::ActionCounts loud_ui_actions_counts,
    PredictionRequestFeatures::ActionCounts actions_counts_for_request_type,
    PredictionRequestFeatures::ActionCounts actions_counts,
    std::optional<bool> prediction_decision_held_back,
    std::optional<ukm::SourceId> source_id) {
  if (action == PermissionAction::REVOKED) {
    RecordUmaForWhetherRevocationUkmWasRecorded(permission,
                                                source_id.has_value());
  }

  // Only record the permission change if the origin is in the history.
  if (!source_id.has_value())
    return;

  const int loud_ui_prompts_count_for_request_type =
      loud_ui_actions_counts_for_request_type.total();
  const int loud_ui_prompts_count = loud_ui_actions_counts.total();
  const int prompts_count_for_request_type =
      actions_counts_for_request_type.total();
  const int prompts_count = actions_counts.total();
  ukm::builders::Permission builder(source_id.value());
  builder.SetAction(static_cast<int64_t>(action))
      .SetGesture(static_cast<int64_t>(gesture_type))
      .SetPermissionType(static_cast<int64_t>(
          content_settings_uma_util::ContentSettingTypeToHistogramValue(
              permission)))
      .SetPriorDismissals(std::min(kPriorCountCap, dismiss_count))
      .SetPriorIgnores(std::min(kPriorCountCap, ignore_count))
      .SetSource(static_cast<int64_t>(source_ui))
      .SetPromptDisposition(static_cast<int64_t>(ui_disposition));

  builder
      .SetStats_LoudPromptsOfType_DenyRate(
          GetRoundedRatioForUkm(loud_ui_actions_counts_for_request_type.denies,
                                loud_ui_prompts_count_for_request_type))
      .SetStats_LoudPromptsOfType_DismissRate(GetRoundedRatioForUkm(
          loud_ui_actions_counts_for_request_type.dismissals,
          loud_ui_prompts_count_for_request_type))
      .SetStats_LoudPromptsOfType_GrantRate(
          GetRoundedRatioForUkm(loud_ui_actions_counts_for_request_type.grants,
                                loud_ui_prompts_count_for_request_type))
      .SetStats_LoudPromptsOfType_IgnoreRate(
          GetRoundedRatioForUkm(loud_ui_actions_counts_for_request_type.ignores,
                                loud_ui_prompts_count_for_request_type))
      .SetStats_LoudPromptsOfType_Count(
          BucketizeValue(loud_ui_prompts_count_for_request_type));

  builder
      .SetStats_LoudPrompts_DenyRate(GetRoundedRatioForUkm(
          loud_ui_actions_counts.denies, loud_ui_prompts_count))
      .SetStats_LoudPrompts_DismissRate(GetRoundedRatioForUkm(
          loud_ui_actions_counts.dismissals, loud_ui_prompts_count))
      .SetStats_LoudPrompts_GrantRate(GetRoundedRatioForUkm(
          loud_ui_actions_counts.grants, loud_ui_prompts_count))
      .SetStats_LoudPrompts_IgnoreRate(GetRoundedRatioForUkm(
          loud_ui_actions_counts.ignores, loud_ui_prompts_count))
      .SetStats_LoudPrompts_Count(BucketizeValue(loud_ui_prompts_count));

  builder
      .SetStats_AllPromptsOfType_DenyRate(
          GetRoundedRatioForUkm(actions_counts_for_request_type.denies,
                                prompts_count_for_request_type))
      .SetStats_AllPromptsOfType_DismissRate(
          GetRoundedRatioForUkm(actions_counts_for_request_type.dismissals,
                                prompts_count_for_request_type))
      .SetStats_AllPromptsOfType_GrantRate(
          GetRoundedRatioForUkm(actions_counts_for_request_type.grants,
                                prompts_count_for_request_type))
      .SetStats_AllPromptsOfType_IgnoreRate(
          GetRoundedRatioForUkm(actions_counts_for_request_type.ignores,
                                prompts_count_for_request_type))
      .SetStats_AllPromptsOfType_Count(
          BucketizeValue(prompts_count_for_request_type));

  builder
      .SetStats_AllPrompts_DenyRate(
          GetRoundedRatioForUkm(actions_counts.denies, prompts_count))
      .SetStats_AllPrompts_DismissRate(
          GetRoundedRatioForUkm(actions_counts.dismissals, prompts_count))
      .SetStats_AllPrompts_GrantRate(
          GetRoundedRatioForUkm(actions_counts.grants, prompts_count))
      .SetStats_AllPrompts_IgnoreRate(
          GetRoundedRatioForUkm(actions_counts.ignores, prompts_count))
      .SetStats_AllPrompts_Count(BucketizeValue(prompts_count));

  if (ui_reason.has_value())
    builder.SetPromptDispositionReason(static_cast<int64_t>(ui_reason.value()));

  if (predicted_grant_likelihood.has_value()) {
    builder.SetPredictionsApiResponse_GrantLikelihood(
        static_cast<int64_t>(predicted_grant_likelihood.value()));
  }

  if (prediction_decision_held_back.has_value()) {
    builder.SetPredictionsApiResponse_Heldback(
        prediction_decision_held_back.value());
  }

  if (has_three_consecutive_denies.has_value()) {
    int64_t satisfied_adaptive_triggers = 0;
    if (has_three_consecutive_denies.value())
      satisfied_adaptive_triggers |=
          static_cast<int64_t>(AdaptiveTriggers::THREE_CONSECUTIVE_DENIES);
    builder.SetSatisfiedAdaptiveTriggers(satisfied_adaptive_triggers);
  }

  if (has_previously_revoked_permission.has_value()) {
    int64_t previously_revoked_permission = 0;
    if (has_previously_revoked_permission.value()) {
      previously_revoked_permission = static_cast<int64_t>(
          PermissionAutoRevocationHistory::PREVIOUSLY_AUTO_REVOKED);
    }
    builder.SetPermissionAutoRevocationHistory(previously_revoked_permission);
  }

  if (ui_disposition == PermissionPromptDisposition::ELEMENT_ANCHORED_BUBBLE &&
      variants.has_value()) {
    // Variant can have a maximum of 3 values, one per site level and 2 for OS
    // level.
    CHECK_LE(variants->size(), 3U);

    const std::vector<ElementAnchoredBubbleVariant>& variant_array =
        variants.value();

    for (ElementAnchoredBubbleVariant variant : variant_array) {
      switch (variant) {
        case ElementAnchoredBubbleVariant::ADMINISTRATOR_GRANTED:
        case ElementAnchoredBubbleVariant::PREVIOUSLY_GRANTED:
        case ElementAnchoredBubbleVariant::ASK:
        case ElementAnchoredBubbleVariant::PREVIOUSLY_DENIED:
        case ElementAnchoredBubbleVariant::ADMINISTRATOR_DENIED:
          builder.SetSiteLevelScreen(static_cast<int64_t>(variant));
          break;
        case ElementAnchoredBubbleVariant::OS_PROMPT:
          builder.SetOsPromptScreen(static_cast<int64_t>(variant));
          break;

        case ElementAnchoredBubbleVariant::OS_SYSTEM_SETTINGS:
          builder.SetOsSystemSettingsScreen(static_cast<int64_t>(variant));
          break;
        case ElementAnchoredBubbleVariant::UNINITIALIZED:
          break;
      }
    }
  }
  if (!time_to_decision.is_zero()) {
    builder.SetTimeToDecision(ukm::GetExponentialBucketMinForUserTiming(
        time_to_decision.InMilliseconds()));
  }

  builder.Record(ukm::UkmRecorder::Get());
}

// |full_version| represented in the format `YYYY.M.D.m`, where m is the
// minute-of-day. Return int represented in the format `YYYYMMDD`.
// CrowdDeny versions published before 2020 will be reported as 1.
// Returns 0 if no version available.
// Returns 1 if a version has invalid format.
int ConvertCrowdDenyVersionToInt(const std::optional<base::Version>& version) {
  if (!version.has_value() || !version.value().IsValid())
    return 0;

  const std::vector<uint32_t>& full_version = version.value().components();
  if (full_version.size() != 4)
    return 1;

  const int kCrowdDenyMinYearLimit = 2020;
  const int year = base::checked_cast<int>(full_version.at(0));
  if (year < kCrowdDenyMinYearLimit)
    return 1;

  const int month = base::checked_cast<int>(full_version.at(1));
  const int day = base::checked_cast<int>(full_version.at(2));

  int short_version = year;

  short_version *= 100;
  short_version += month;
  short_version *= 100;
  short_version += day;

  return short_version;
}

AutoDSEPermissionRevertTransition GetAutoDSEPermissionRevertedTransition(
    ContentSetting backed_up_setting,
    ContentSetting effective_setting,
    ContentSetting end_state_setting) {
  if (backed_up_setting == CONTENT_SETTING_ASK &&
      effective_setting == CONTENT_SETTING_ALLOW &&
      end_state_setting == CONTENT_SETTING_ASK) {
    return AutoDSEPermissionRevertTransition::NO_DECISION_ASK;
  } else if (backed_up_setting == CONTENT_SETTING_ALLOW &&
             effective_setting == CONTENT_SETTING_ALLOW &&
             end_state_setting == CONTENT_SETTING_ALLOW) {
    return AutoDSEPermissionRevertTransition::PRESERVE_ALLOW;
  } else if (backed_up_setting == CONTENT_SETTING_BLOCK &&
             effective_setting == CONTENT_SETTING_ALLOW &&
             end_state_setting == CONTENT_SETTING_ASK) {
    return AutoDSEPermissionRevertTransition::CONFLICT_ASK;
  } else if (backed_up_setting == CONTENT_SETTING_ASK &&
             effective_setting == CONTENT_SETTING_BLOCK &&
             end_state_setting == CONTENT_SETTING_BLOCK) {
    return AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_ASK;
  } else if (backed_up_setting == CONTENT_SETTING_ALLOW &&
             effective_setting == CONTENT_SETTING_BLOCK &&
             end_state_setting == CONTENT_SETTING_BLOCK) {
    return AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_ALLOW;
  } else if (backed_up_setting == CONTENT_SETTING_BLOCK &&
             effective_setting == CONTENT_SETTING_BLOCK &&
             end_state_setting == CONTENT_SETTING_BLOCK) {
    return AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_BLOCK;
  } else {
    return AutoDSEPermissionRevertTransition::INVALID_END_STATE;
  }
}

void RecordTopLevelPermissionsHeaderPolicy(
    ContentSettingsType content_settings_type,
    const std::string& histogram,
    content::RenderFrameHost* render_frame_host) {
  DCHECK(IsCrossOriginSubframe(render_frame_host));

  // We only care about about permission types that have a corresponding
  // permission policy
  const auto feature =
      PermissionUtil::GetPermissionsPolicyFeature(content_settings_type);
  if (!feature.has_value()) {
    return;
  }

  // This function will only be called when we use/prompt a permission requested
  // from a cross-origin subframe. Being allowed by permission policy is a
  // necessary condition to use a permission in sub-frame.
  DCHECK(render_frame_host->IsFeatureEnabled(feature.value()));
  base::UmaHistogramEnumeration(histogram,
                                GetTopLevelPermissionHeaderPolicyForUMA(
                                    render_frame_host, feature.value()),
                                PermissionHeaderPolicyForUMA::NUM);
}

PermissionChangeInfo GetChangeInfo(bool is_used,
                                   bool show_infobar,
                                   bool page_reload) {
  if (show_infobar) {
    if (page_reload) {
      if (is_used) {
        return PermissionChangeInfo::kInfobarShownPageReloadPermissionUsed;
      } else {
        return PermissionChangeInfo::kInfobarShownPageReloadPermissionNotUsed;
      }

    } else {
      if (is_used) {
        return PermissionChangeInfo::kInfobarShownNoPageReloadPermissionUsed;
      } else {
        return PermissionChangeInfo::kInfobarShownNoPageReloadPermissionNotUsed;
      }
    }
  } else {
    if (page_reload) {
      if (is_used) {
        return PermissionChangeInfo::kInfobarNotShownPageReloadPermissionUsed;
      } else {
        return PermissionChangeInfo::
            kInfobarNotShownPageReloadPermissionNotUsed;
      }

    } else {
      if (is_used) {
        return PermissionChangeInfo::kInfobarNotShownNoPageReloadPermissionUsed;
      } else {
        return PermissionChangeInfo::
            kInfobarNotShownNoPageReloadPermissionNotUsed;
      }
    }
  }
}

}  // anonymous namespace

// PermissionUmaUtil ----------------------------------------------------------

const char PermissionUmaUtil::kPermissionsPromptShown[] =
    "Permissions.Prompt.Shown";
const char PermissionUmaUtil::kPermissionsPromptShownGesture[] =
    "Permissions.Prompt.Shown.Gesture";
const char PermissionUmaUtil::kPermissionsPromptShownNoGesture[] =
    "Permissions.Prompt.Shown.NoGesture";
const char PermissionUmaUtil::kPermissionsPromptAccepted[] =
    "Permissions.Prompt.Accepted";
const char PermissionUmaUtil::kPermissionsPromptAcceptedGesture[] =
    "Permissions.Prompt.Accepted.Gesture";
const char PermissionUmaUtil::kPermissionsPromptAcceptedNoGesture[] =
    "Permissions.Prompt.Accepted.NoGesture";
const char PermissionUmaUtil::kPermissionsPromptAcceptedOnce[] =
    "Permissions.Prompt.AcceptedOnce";
const char PermissionUmaUtil::kPermissionsPromptAcceptedOnceGesture[] =
    "Permissions.Prompt.AcceptedOnce.Gesture";
const char PermissionUmaUtil::kPermissionsPromptAcceptedOnceNoGesture[] =
    "Permissions.Prompt.AcceptedOnce.NoGesture";
const char PermissionUmaUtil::kPermissionsPromptDenied[] =
    "Permissions.Prompt.Denied";
const char PermissionUmaUtil::kPermissionsPromptDeniedGesture[] =
    "Permissions.Prompt.Denied.Gesture";
const char PermissionUmaUtil::kPermissionsPromptDeniedNoGesture[] =
    "Permissions.Prompt.Denied.NoGesture";
const char PermissionUmaUtil::kPermissionsExperimentalUsagePrefix[] =
    "Permissions.Experimental.Usage.";
const char PermissionUmaUtil::kPermissionsActionPrefix[] =
    "Permissions.Action.";

// Make sure you update histograms.xml permission histogram_suffix if you
// add new permission
void PermissionUmaUtil::PermissionRequested(ContentSettingsType content_type) {
  PermissionType permission;
  bool success = PermissionUtil::GetPermissionType(content_type, &permission);
  DCHECK(success);

  base::UmaHistogramEnumeration("ContentSettings.PermissionRequested",
                                permission, PermissionType::NUM);
}

void PermissionUmaUtil::RecordActivityIndicator(
    std::set<ContentSettingsType> permissions,
    bool blocked,
    bool blocked_system_level,
    bool clicked) {
  DCHECK(!permissions.empty());
  DCHECK(permissions.contains(ContentSettingsType::MEDIASTREAM_CAMERA) ||
         permissions.contains(ContentSettingsType::MEDIASTREAM_MIC));

  ActivityIndicatorState state;
  if (blocked) {
    if (blocked_system_level) {
      state = ActivityIndicatorState::kBlockedOnSystemLevel;
    } else {
      state = ActivityIndicatorState::kBlockedOnSiteLevel;
    }
  } else {
    state = ActivityIndicatorState::kInUse;
  }

  std::string indicators_type;

  if (permissions.size() > 1) {
    indicators_type = "AudioAndVideoCapture";
  } else if (permissions.contains(ContentSettingsType::MEDIASTREAM_CAMERA)) {
    indicators_type = "VideoCapture";
  } else {
    indicators_type = "AudioCapture";
  }

  std::string action;
  if (clicked) {
    action = "Click";
  } else {
    action = "Show";
  }

  base::UmaHistogramEnumeration(
      "Permissions.ActivityIndicator.LHS." + indicators_type + "." + action,
      state);
}

void PermissionUmaUtil::RecordDismissalType(
    const std::vector<ContentSettingsType>& content_settings_types,
    PermissionPromptDisposition ui_disposition,
    DismissalType dismissalType) {
  RequestTypeForUma type = GetUmaValueForRequestType(
      ContentSettingsTypeToRequestType(content_settings_types[0]));

  if (content_settings_types.size() > 1) {
    type = RequestTypeForUma::MULTIPLE;
  }

  std::string permission_type = GetPermissionRequestString(type);
  std::string permission_disposition =
      GetPromptDispositionString(ui_disposition);
  base::UmaHistogramEnumeration("Permissions.Prompt." + permission_type + "." +
                                    permission_disposition +
                                    ".Dismissed.Method",
                                dismissalType);
}

void PermissionUmaUtil::RecordPermissionRequestedFromFrame(
    ContentSettingsType content_settings_type,
    content::RenderFrameHost* rfh) {
  PermissionType permission;
  bool success =
      PermissionUtil::GetPermissionType(content_settings_type, &permission);
  DCHECK(success);

  if (IsCrossOriginWithAnyParent(rfh)) {
    base::UmaHistogramEnumeration("Permissions.Request.CrossOrigin", permission,
                                  PermissionType::NUM);
  } else {
    std::string frame_level =
        rfh->IsInPrimaryMainFrame() ? "MainFrame" : "SubFrame";

    base::UmaHistogramEnumeration(
        "Permissions.Request.SameOrigin." + frame_level, permission,
        PermissionType::NUM);
  }
}

void PermissionUmaUtil::PermissionRequestPreignored(PermissionType permission) {
  base::UmaHistogramEnumeration("Permissions.QuietPrompt.Preignore", permission,
                                PermissionType::NUM);
}

void PermissionUmaUtil::PermissionRevoked(
    ContentSettingsType permission,
    PermissionSourceUI source_ui,
    const GURL& revoked_origin,
    content::BrowserContext* browser_context) {
  DCHECK(PermissionUtil::IsPermission(permission));
  // An unknown gesture type is passed in since gesture type is only
  // applicable in prompt UIs where revocations are not possible.
  RecordPermissionAction(permission, PermissionAction::REVOKED, source_ui,
                         PermissionRequestGestureType::UNKNOWN,
                         /*time_to_decision=*/base::TimeDelta(),
                         PermissionPromptDisposition::NOT_APPLICABLE,
                         /*ui_reason=*/std::nullopt, /*variants=*/std::nullopt,
                         revoked_origin,
                         /*web_contents=*/nullptr, browser_context,
                         /*render_frame_host*/ nullptr,
                         /*predicted_grant_likelihood=*/std::nullopt,
                         /*prediction_decision_held_back=*/std::nullopt);
}

void PermissionUmaUtil::RecordEmbargoPromptSuppression(
    PermissionEmbargoStatus embargo_status) {
  base::UmaHistogramEnumeration(
      "Permissions.AutoBlocker.EmbargoPromptSuppression", embargo_status,
      PermissionEmbargoStatus::NUM);
}

void PermissionUmaUtil::RecordEmbargoPromptSuppressionFromSource(
    content::PermissionStatusSource source) {
  // Explicitly switch to ensure that any new
  // PermissionStatusSource values are dealt with appropriately.
  switch (source) {
    case content::PermissionStatusSource::MULTIPLE_DISMISSALS:
      PermissionUmaUtil::RecordEmbargoPromptSuppression(
          PermissionEmbargoStatus::REPEATED_DISMISSALS);
      break;
    case content::PermissionStatusSource::MULTIPLE_IGNORES:
      PermissionUmaUtil::RecordEmbargoPromptSuppression(
          PermissionEmbargoStatus::REPEATED_IGNORES);
      break;
    case content::PermissionStatusSource::RECENT_DISPLAY:
      PermissionUmaUtil::RecordEmbargoPromptSuppression(
          PermissionEmbargoStatus::RECENT_DISPLAY);
      break;
    case content::PermissionStatusSource::UNSPECIFIED:
    case content::PermissionStatusSource::KILL_SWITCH:
    case content::PermissionStatusSource::INSECURE_ORIGIN:
    case content::PermissionStatusSource::FEATURE_POLICY:
    case content::PermissionStatusSource::VIRTUAL_URL_DIFFERENT_ORIGIN:
    case content::PermissionStatusSource::FENCED_FRAME:
      // The permission wasn't under embargo, so don't record anything. We may
      // embargo it later.
      break;
  }
}

void PermissionUmaUtil::RecordEmbargoStatus(
    PermissionEmbargoStatus embargo_status) {
  base::UmaHistogramEnumeration("Permissions.AutoBlocker.EmbargoStatus",
                                embargo_status, PermissionEmbargoStatus::NUM);
}

void PermissionUmaUtil::RecordPermissionRecoverySuccessRate(
    ContentSettingsType permission,
    bool is_used,
    bool show_infobar,
    bool page_reload) {
  PermissionChangeInfo change_info =
      GetChangeInfo(is_used, show_infobar, page_reload);

  std::string permission_string = GetPermissionRequestString(
      GetUmaValueForRequestType(ContentSettingsTypeToRequestType(permission)));

  base::UmaHistogramEnumeration("Permissions.PageInfo.Changed." +
                                    permission_string + ".Reallowed.Outcome",
                                change_info);
}

void PermissionUmaUtil::RecordPermissionPromptAttempt(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    bool IsLocationBarEditingOrEmpty) {
  DCHECK(!requests.empty());

  RequestTypeForUma request_type = RequestTypeForUma::MULTIPLE;
  PermissionRequestGestureType gesture_type =
      PermissionRequestGestureType::UNKNOWN;
  if (requests.size() == 1) {
    request_type = GetUmaValueForRequestType(requests[0]->request_type());
    gesture_type = requests[0]->GetGestureType();
  }

  std::string permission_type = GetPermissionRequestString(request_type);

  std::string gesture;

  switch (gesture_type) {
    case PermissionRequestGestureType::UNKNOWN: {
      gesture = "Unknown";
      break;
    }
    case PermissionRequestGestureType::GESTURE: {
      gesture = "Gesture";
      break;
    }
    case PermissionRequestGestureType::NO_GESTURE: {
      gesture = "NoGesture";
      break;
    }
    default:
      NOTREACHED();
  }

  std::string histogram_name =
      "Permissions.Prompt." + permission_type + "." + gesture + ".Attempt";

  base::UmaHistogramBoolean(histogram_name, IsLocationBarEditingOrEmpty);
}

void PermissionUmaUtil::PermissionPromptShown(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>&
        requests) {
  DCHECK(!requests.empty());

  RequestTypeForUma request_type = RequestTypeForUma::MULTIPLE;
  PermissionRequestGestureType gesture_type =
      PermissionRequestGestureType::UNKNOWN;
  if (requests.size() == 1) {
    request_type = GetUmaValueForRequestType(requests[0]->request_type());
    gesture_type = requests[0]->GetGestureType();
  }

  PERMISSION_BUBBLE_TYPE_UMA(kPermissionsPromptShown, request_type);
  PERMISSION_BUBBLE_GESTURE_TYPE_UMA(kPermissionsPromptShownGesture,
                                     kPermissionsPromptShownNoGesture,
                                     gesture_type, request_type);
}

void PermissionUmaUtil::PermissionPromptResolved(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    content::WebContents* web_contents,
    PermissionAction permission_action,
    base::TimeDelta time_to_decision,
    PermissionPromptDisposition ui_disposition,
    std::optional<PermissionPromptDispositionReason> ui_reason,
    std::optional<std::vector<ElementAnchoredBubbleVariant>> variants,
    std::optional<PredictionGrantLikelihood> predicted_grant_likelihood,
    std::optional<bool> prediction_decision_held_back,
    std::optional<permissions::PermissionIgnoredReason> ignored_reason,
    bool did_show_prompt,
    bool did_click_managed,
    bool did_click_learn_more) {
  switch (permission_action) {
    case PermissionAction::GRANTED:
      RecordPromptDecided(requests, /*accepted=*/true, /*is_one_time=*/false);
      break;
    case PermissionAction::DENIED:
      RecordPromptDecided(requests, /*accepted=*/false, /*is_one_time*/ false);
      break;
    case PermissionAction::DISMISSED:
    case PermissionAction::IGNORED:
      RecordIgnoreReason(requests, ui_disposition,
                         ignored_reason.value_or(
                             permissions::PermissionIgnoredReason::UNKNOWN));
      break;
    case PermissionAction::GRANTED_ONCE:
      RecordPromptDecided(requests, /*accepted=*/true, /*is_one_time*/ true);
      break;
    default:
      NOTREACHED();
      break;
  }
  std::string action_string = GetPermissionActionString(permission_action);
  RecordEngagementMetric(requests, web_contents, action_string);

  PermissionDecisionAutoBlocker* autoblocker =
      PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
          web_contents->GetBrowserContext());

  for (PermissionRequest* request : requests) {
    ContentSettingsType permission = request->GetContentSettingsType();
    // TODO(timloh): We only record these metrics for permissions which have a
    // ContentSettingsType, as otherwise they don't support GetGestureType.
    if (permission == ContentSettingsType::DEFAULT)
      continue;

    PermissionRequestGestureType gesture_type = request->GetGestureType();
    const GURL& requesting_origin = request->requesting_origin();

    RecordPermissionAction(
        permission, permission_action, PermissionSourceUI::PROMPT, gesture_type,
        time_to_decision, ui_disposition, ui_reason, variants,
        requesting_origin, web_contents, web_contents->GetBrowserContext(),
        content::RenderFrameHost::FromID(request->get_requesting_frame_id()),
        predicted_grant_likelihood, prediction_decision_held_back);

    std::string priorDismissPrefix =
        "Permissions.Prompt." + action_string + ".PriorDismissCount2.";
    std::string priorIgnorePrefix =
        "Permissions.Prompt." + action_string + ".PriorIgnoreCount2.";
    RecordPermissionPromptPriorCount(
        permission, priorDismissPrefix,
        autoblocker->GetDismissCount(requesting_origin, permission));
    RecordPermissionPromptPriorCount(
        permission, priorIgnorePrefix,
        autoblocker->GetIgnoreCount(requesting_origin, permission));
  }

  base::UmaHistogramEnumeration("Permissions.Action.WithDisposition." +
                                    GetPromptDispositionString(ui_disposition),
                                permission_action, PermissionAction::NUM);

  RequestTypeForUma type =
      GetUmaValueForRequestType(requests[0]->request_type());
  if (requests.size() > 1)
    type = RequestTypeForUma::MULTIPLE;

  std::string permission_type = GetPermissionRequestString(type);
  std::string permission_disposition =
      GetPromptDispositionString(ui_disposition);

  base::UmaHistogramEnumeration("Permissions.Prompt." + permission_type + "." +
                                    permission_disposition + ".Action",
                                permission_action, PermissionAction::NUM);

  if (!time_to_decision.is_zero()) {
    base::UmaHistogramLongTimes("Permissions.Prompt." + permission_type + "." +
                                    permission_disposition + "." +
                                    action_string + ".TimeToAction",
                                time_to_decision);
  }

  if (permission_action == PermissionAction::IGNORED &&
      ui_disposition !=
          PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP_AUTO_BUBBLE &&
      ui_disposition != PermissionPromptDisposition::ANCHORED_BUBBLE) {
    base::UmaHistogramBoolean("Permissions.Prompt." + permission_type + "." +
                                  permission_disposition +
                                  ".Ignored.DidShowBubble",
                              did_show_prompt);
  }

  if (requests[0]->request_type() == RequestType::kGeolocation ||
      requests[0]->request_type() == RequestType::kNotifications) {
    if (ui_disposition ==
            PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_CHIP ||
        ui_disposition == PermissionPromptDisposition::MESSAGE_UI ||
        ui_disposition == PermissionPromptDisposition::MINI_INFOBAR) {
      base::UmaHistogramBoolean("Permissions.Prompt." + permission_type + "." +
                                    permission_disposition + "." +
                                    action_string + ".DidClickManage",
                                did_click_managed);
    } else if (ui_disposition == PermissionPromptDisposition::
                                     LOCATION_BAR_LEFT_QUIET_ABUSIVE_CHIP ||
               ui_disposition == PermissionPromptDisposition::MESSAGE_UI ||
               ui_disposition == PermissionPromptDisposition::MINI_INFOBAR) {
      base::UmaHistogramBoolean("Permissions.Prompt." + permission_type + "." +
                                    permission_disposition + "." +
                                    action_string + ".DidClickLearnMore",
                                did_click_learn_more);
    }
  }
}  // namespace permissions

void PermissionUmaUtil::RecordPermissionPromptPriorCount(
    ContentSettingsType permission,
    const std::string& prefix,
    int count) {
  // The user is not prompted for this permissions, thus there is no prompt
  // event to record a prior count for.
  DCHECK_NE(ContentSettingsType::BACKGROUND_SYNC, permission);

  // Expand UMA_HISTOGRAM_COUNTS_100 so that we can use a dynamically suffixed
  // histogram name.
  base::Histogram::FactoryGet(
      prefix + PermissionUtil::GetPermissionString(permission), 1, 100, 50,
      base::HistogramBase::kUmaTargetedHistogramFlag)
      ->Add(count);
}

void PermissionUmaUtil::RecordInfobarDetailsExpanded(bool expanded) {
  base::UmaHistogramBoolean("Permissions.Prompt.Infobar.DetailsExpanded",
                            expanded);
}

void PermissionUmaUtil::RecordCrowdDenyDelayedPushNotification(
    base::TimeDelta delay) {
  base::UmaHistogramTimes(
      "Permissions.CrowdDeny.PreloadData.DelayedPushNotification", delay);
}

void PermissionUmaUtil::RecordCrowdDenyVersionAtAbuseCheckTime(
    const std::optional<base::Version>& version) {
  base::UmaHistogramSparse(
      "Permissions.CrowdDeny.PreloadData.VersionAtAbuseCheckTime",
      ConvertCrowdDenyVersionToInt(version));
}

void PermissionUmaUtil::RecordMissingPermissionInfobarShouldShow(
    bool should_show,
    const std::vector<ContentSettingsType>& content_settings_types) {
  for (const auto& content_settings_type : content_settings_types) {
    base::UmaHistogramBoolean(
        "Permissions.MissingOSLevelPermission.ShouldShow." +
            PermissionUtil::GetPermissionString(content_settings_type),
        should_show);
  }
}

void PermissionUmaUtil::RecordMissingPermissionInfobarAction(
    PermissionAction action,
    const std::vector<ContentSettingsType>& content_settings_types) {
  for (const auto& content_settings_type : content_settings_types) {
    base::UmaHistogramEnumeration(
        "Permissions.MissingOSLevelPermission.Action." +
            PermissionUtil::GetPermissionString(content_settings_type),
        action, PermissionAction::NUM);
  }
}

PermissionUmaUtil::ScopedRevocationReporter::ScopedRevocationReporter(
    content::BrowserContext* browser_context,
    const GURL& primary_url,
    const GURL& secondary_url,
    ContentSettingsType content_type,
    PermissionSourceUI source_ui)
    : browser_context_(browser_context),
      primary_url_(primary_url),
      secondary_url_(secondary_url),
      content_type_(content_type),
      source_ui_(source_ui) {
  if (!primary_url_.is_valid() ||
      (!secondary_url_.is_valid() && !secondary_url_.is_empty()) ||
      !IsRequestablePermissionType(content_type_) ||
      !PermissionUtil::IsPermission(content_type_)) {
    is_initially_allowed_ = false;
    return;
  }
  HostContentSettingsMap* settings_map =
      PermissionsClient::Get()->GetSettingsMap(browser_context_);
  ContentSetting initial_content_setting = settings_map->GetContentSetting(
      primary_url_, secondary_url_, content_type_);
  is_initially_allowed_ = initial_content_setting == CONTENT_SETTING_ALLOW;
  content_settings::SettingInfo setting_info;
  settings_map->GetWebsiteSetting(primary_url, secondary_url, content_type_,
                                  &setting_info);
  last_modified_date_ = setting_info.metadata.last_modified();
  scoped_revocation_reporter_in_scope = true;
}

PermissionUmaUtil::ScopedRevocationReporter::ScopedRevocationReporter(
    content::BrowserContext* browser_context,
    const ContentSettingsPattern& primary_pattern,
    const ContentSettingsPattern& secondary_pattern,
    ContentSettingsType content_type,
    PermissionSourceUI source_ui)
    : ScopedRevocationReporter(
          browser_context,
          GURL(primary_pattern.ToString()),
          GURL((secondary_pattern == ContentSettingsPattern::Wildcard())
                   ? primary_pattern.ToString()
                   : secondary_pattern.ToString()),
          content_type,
          source_ui) {}

PermissionUmaUtil::ScopedRevocationReporter::~ScopedRevocationReporter() {
  scoped_revocation_reporter_in_scope = false;
  if (!is_initially_allowed_)
    return;
  if (!IsRequestablePermissionType(content_type_) ||
      !PermissionUtil::IsPermission(content_type_)) {
    return;
  }
  HostContentSettingsMap* settings_map =
      PermissionsClient::Get()->GetSettingsMap(browser_context_);
  ContentSetting final_content_setting = settings_map->GetContentSetting(
      primary_url_, secondary_url_, content_type_);
  if (final_content_setting != CONTENT_SETTING_ALLOW) {
    // PermissionUmaUtil takes origins, even though they're typed as GURL.
    GURL requesting_origin = primary_url_.DeprecatedGetOriginAsURL();
    PermissionRevoked(content_type_, source_ui_, requesting_origin,
                      browser_context_);
    if ((content_type_ == ContentSettingsType::GEOLOCATION ||
         content_type_ == ContentSettingsType::MEDIASTREAM_CAMERA ||
         content_type_ == ContentSettingsType::MEDIASTREAM_MIC) &&
        !last_modified_date_.is_null()) {
      RecordTimeElapsedBetweenGrantAndRevoke(
          content_type_, base::Time::Now() - last_modified_date_);
    }
  }
}

bool PermissionUmaUtil::ScopedRevocationReporter::IsInstanceInScope() {
  return scoped_revocation_reporter_in_scope;
}

void PermissionUmaUtil::RecordPermissionUsage(
    ContentSettingsType permission_type,
    content::BrowserContext* browser_context,
    content::WebContents* web_contents,
    const GURL& requesting_origin) {
  PermissionsClient::Get()->GetUkmSourceId(
      permission_type, browser_context, web_contents, requesting_origin,
      base::BindOnce(&RecordPermissionUsageUkm, permission_type));
}

void PermissionUmaUtil::RecordPermissionAction(
    ContentSettingsType permission,
    PermissionAction action,
    PermissionSourceUI source_ui,
    PermissionRequestGestureType gesture_type,
    base::TimeDelta time_to_decision,
    PermissionPromptDisposition ui_disposition,
    std::optional<PermissionPromptDispositionReason> ui_reason,
    std::optional<std::vector<ElementAnchoredBubbleVariant>> variants,
    const GURL& requesting_origin,
    content::WebContents* web_contents,
    content::BrowserContext* browser_context,
    content::RenderFrameHost* render_frame_host,
    std::optional<PredictionGrantLikelihood> predicted_grant_likelihood,
    std::optional<bool> prediction_decision_held_back) {
  DCHECK(PermissionUtil::IsPermission(permission));
  PermissionDecisionAutoBlocker* autoblocker =
      PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
          browser_context);
  int dismiss_count =
      autoblocker->GetDismissCount(requesting_origin, permission);
  int ignore_count = autoblocker->GetIgnoreCount(requesting_origin, permission);

  const base::Time cutoff = base::Time::Now() - base::Days(28);
  PermissionActionsHistory* permission_actions_history =
      PermissionsClient::Get()->GetPermissionActionsHistory(browser_context);

  PredictionRequestFeatures::ActionCounts
      loud_ui_actions_counts_per_request_type;
  PredictionRequestFeatures::ActionCounts loud_ui_actions_counts;
  PredictionRequestFeatures::ActionCounts actions_counts_per_request_type;
  PredictionRequestFeatures::ActionCounts actions_counts;

  if (permission_actions_history != nullptr) {
    DCHECK(IsRequestablePermissionType(permission));
    auto loud_ui_actions_per_request_type =
        permission_actions_history->GetHistory(
            cutoff, ContentSettingsTypeToRequestType(permission),
            PermissionActionsHistory::EntryFilter::WANT_LOUD_PROMPTS_ONLY);
    PermissionActionsHistory::FillInActionCounts(
        &loud_ui_actions_counts_per_request_type,
        loud_ui_actions_per_request_type);

    auto loud_ui_actions = permission_actions_history->GetHistory(
        cutoff, PermissionActionsHistory::EntryFilter::WANT_LOUD_PROMPTS_ONLY);
    PermissionActionsHistory::FillInActionCounts(&loud_ui_actions_counts,
                                                 loud_ui_actions);

    auto actions_per_request_type = permission_actions_history->GetHistory(
        cutoff, ContentSettingsTypeToRequestType(permission),
        PermissionActionsHistory::EntryFilter::WANT_ALL_PROMPTS);
    PermissionActionsHistory::FillInActionCounts(
        &actions_counts_per_request_type, actions_per_request_type);

    auto actions = permission_actions_history->GetHistory(
        cutoff, PermissionActionsHistory::EntryFilter::WANT_ALL_PROMPTS);
    PermissionActionsHistory::FillInActionCounts(&actions_counts, actions);
  }

  if (action == PermissionAction::REVOKED) {
    RecordUmaForRevocationSourceUI(permission, source_ui);
  }

  PermissionsClient::Get()->GetUkmSourceId(
      permission, browser_context, web_contents, requesting_origin,
      base::BindOnce(
          &RecordPermissionActionUkm, action, gesture_type, permission,
          dismiss_count, ignore_count, source_ui, time_to_decision,
          ui_disposition, ui_reason, variants,
          permission == ContentSettingsType::NOTIFICATIONS
              ? PermissionsClient::Get()
                    ->HadThreeConsecutiveNotificationPermissionDenies(
                        browser_context)
              : std::nullopt,
          PermissionsClient::Get()->HasPreviouslyAutoRevokedPermission(
              browser_context, requesting_origin, permission),
          predicted_grant_likelihood, loud_ui_actions_counts_per_request_type,
          loud_ui_actions_counts, actions_counts_per_request_type,
          actions_counts, prediction_decision_held_back));

  if (render_frame_host && IsCrossOriginSubframe(render_frame_host)) {
    RecordCrossOriginFrameActionAndPolicyConfiguration(permission, action,
                                                       render_frame_host);
  }

  switch (permission) {
    case ContentSettingsType::GEOLOCATION:
      base::UmaHistogramEnumeration("Permissions.Action.Geolocation", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::NOTIFICATIONS:
      base::UmaHistogramEnumeration("Permissions.Action.Notifications", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::MIDI_SYSEX:
      base::UmaHistogramEnumeration("Permissions.Action.MidiSysEx", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
      base::UmaHistogramEnumeration("Permissions.Action.ProtectedMedia", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::MEDIASTREAM_MIC:
      base::UmaHistogramEnumeration("Permissions.Action.AudioCapture", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::MEDIASTREAM_CAMERA:
      base::UmaHistogramEnumeration("Permissions.Action.VideoCapture", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::CLIPBOARD_READ_WRITE:
      base::UmaHistogramEnumeration("Permissions.Action.ClipboardReadWrite",
                                    action, PermissionAction::NUM);
      break;
    case ContentSettingsType::PAYMENT_HANDLER:
      base::UmaHistogramEnumeration("Permissions.Action.PaymentHandler", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::NFC:
      base::UmaHistogramEnumeration("Permissions.Action.Nfc", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::VR:
      base::UmaHistogramEnumeration("Permissions.Action.VR", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::AR:
      base::UmaHistogramEnumeration("Permissions.Action.AR", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::STORAGE_ACCESS:
      base::UmaHistogramEnumeration("Permissions.Action.StorageAccess", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS:
      base::UmaHistogramEnumeration("Permissions.Action.TopLevelStorageAccess",
                                    action, PermissionAction::NUM);
      break;
    case ContentSettingsType::CAMERA_PAN_TILT_ZOOM:
      base::UmaHistogramEnumeration("Permissions.Action.CameraPanTiltZoom",
                                    action, PermissionAction::NUM);
      break;
    case ContentSettingsType::WINDOW_MANAGEMENT:
      base::UmaHistogramEnumeration("Permissions.Action.WindowPlacement",
                                    action, PermissionAction::NUM);
      break;
    case ContentSettingsType::LOCAL_FONTS:
      base::UmaHistogramEnumeration("Permissions.Action.LocalFonts", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::IDLE_DETECTION:
      base::UmaHistogramEnumeration("Permissions.Action.IdleDetection", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::ACCESSIBILITY_EVENTS:
      base::UmaHistogramEnumeration("Permissions.Action.AccessibilityEvents",
                                    action, PermissionAction::NUM);
      break;
    case ContentSettingsType::CAPTURED_SURFACE_CONTROL:
      base::UmaHistogramEnumeration("Permissions.Action.CapturedSurfaceControl",
                                    action, PermissionAction::NUM);
      break;
    case ContentSettingsType::SMART_CARD_DATA:
      base::UmaHistogramEnumeration("Permissions.Action.SmartCard", action,
                                    PermissionAction::NUM);
      break;
    case ContentSettingsType::WEB_PRINTING:
      base::UmaHistogramEnumeration("Permissions.Action.WebPrinting", action,
                                    PermissionAction::NUM);
      break;
    // The user is not prompted for these permissions, thus there is no
    // permission action recorded for them.
    default:
      NOTREACHED() << "PERMISSION "
                   << PermissionUtil::GetPermissionString(permission)
                   << " not accounted for";
  }
}

// static
void PermissionUmaUtil::RecordPromptDecided(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    bool accepted,
    bool is_one_time) {
  DCHECK(!requests.empty());

  RequestTypeForUma request_type = RequestTypeForUma::MULTIPLE;
  PermissionRequestGestureType gesture_type =
      PermissionRequestGestureType::UNKNOWN;
  if (requests.size() == 1) {
    request_type = GetUmaValueForRequestType(requests[0]->request_type());
    gesture_type = requests[0]->GetGestureType();
  }

  if (accepted) {
    if (is_one_time) {
      PERMISSION_BUBBLE_TYPE_UMA(kPermissionsPromptAcceptedOnce, request_type);
      PERMISSION_BUBBLE_GESTURE_TYPE_UMA(
          kPermissionsPromptAcceptedOnceGesture,
          kPermissionsPromptAcceptedOnceNoGesture, gesture_type, request_type);
    } else {
      PERMISSION_BUBBLE_TYPE_UMA(kPermissionsPromptAccepted, request_type);
      PERMISSION_BUBBLE_GESTURE_TYPE_UMA(kPermissionsPromptAcceptedGesture,
                                         kPermissionsPromptAcceptedNoGesture,
                                         gesture_type, request_type);
    }
  } else {
    PERMISSION_BUBBLE_TYPE_UMA(kPermissionsPromptDenied, request_type);
    PERMISSION_BUBBLE_GESTURE_TYPE_UMA(kPermissionsPromptDeniedGesture,
                                       kPermissionsPromptDeniedNoGesture,
                                       gesture_type, request_type);
  }
}

void PermissionUmaUtil::RecordTimeElapsedBetweenGrantAndUse(
    ContentSettingsType type,
    base::TimeDelta delta,
    content_settings::SettingSource source) {
  std::string base_histogram = "Permissions.Usage.ElapsedTimeSinceGrant." +
                               PermissionUtil::GetPermissionString(type);
  std::string source_suffix;
  switch (source) {
    case content_settings::SETTING_SOURCE_NONE:
      source_suffix = "FromNone";
      break;
    case content_settings::SETTING_SOURCE_POLICY:
      source_suffix = "FromPolicy";
      break;
    case content_settings::SETTING_SOURCE_EXTENSION:
      source_suffix = "FromExtension";
      break;
    case content_settings::SETTING_SOURCE_USER:
      source_suffix = "FromUser";
      break;
    case content_settings::SETTING_SOURCE_ALLOWLIST:
      source_suffix = "FromAllowlist";
      break;
    case content_settings::SETTING_SOURCE_SUPERVISED:
      source_suffix = "FromSupervised";
      break;
    case content_settings::SETTING_SOURCE_INSTALLED_WEBAPP:
      source_suffix = "FromInstalledWebApp";
      break;
    case content_settings::SETTING_SOURCE_TPCD_GRANT:
      source_suffix = "FromSourceTpcdGrant";
      break;
  }
  base::UmaHistogramCustomCounts(base_histogram, delta.InSeconds(), 1,
                                 base::Days(365).InSeconds(), 100);
  if (!source_suffix.empty()) {
    base::UmaHistogramCustomCounts(base_histogram + "." + source_suffix,
                                   delta.InSeconds(), 1,
                                   base::Days(365).InSeconds(), 100);
  }
}

void PermissionUmaUtil::RecordTimeElapsedBetweenGrantAndRevoke(
    ContentSettingsType type,
    base::TimeDelta delta) {
  base::UmaHistogramCustomCounts(
      "Permissions.Revocation.ElapsedTimeSinceGrant." +
          PermissionUtil::GetPermissionString(type),
      delta.InSeconds(), 1, base::Days(365).InSeconds(), 100);
}

// static
void PermissionUmaUtil::RecordAutoDSEPermissionReverted(
    ContentSettingsType permission_type,
    ContentSetting backed_up_setting,
    ContentSetting effective_setting,
    ContentSetting end_state_setting) {
  std::string permission_string =
      GetPermissionRequestString(GetUmaValueForRequestType(
          ContentSettingsTypeToRequestType(permission_type)));
  auto transition = GetAutoDSEPermissionRevertedTransition(
      backed_up_setting, effective_setting, end_state_setting);
  base::UmaHistogramEnumeration(
      "Permissions.DSE.AutoPermissionRevertTransition." + permission_string,
      transition);
}

// static
void PermissionUmaUtil::RecordDSEEffectiveSetting(
    ContentSettingsType permission_type,
    ContentSetting setting) {
  std::string permission_string =
      GetPermissionRequestString(GetUmaValueForRequestType(
          ContentSettingsTypeToRequestType(permission_type)));
  base::UmaHistogramEnumeration(
      "Permissions.DSE.EffectiveSetting." + permission_string, setting,
      CONTENT_SETTING_NUM_SETTINGS);
}

// static
void PermissionUmaUtil::RecordPermissionPredictionSource(
    PermissionPredictionSource prediction_source) {
  base::UmaHistogramEnumeration(
      "Permissions.PredictionService.PredictionSource", prediction_source);
}

// static
void PermissionUmaUtil::RecordPermissionPredictionServiceHoldback(
    RequestType request_type,
    bool is_on_device,
    bool is_heldback) {
  if (is_on_device) {
    base::UmaHistogramBoolean(
        "Permissions.OnDevicePredictionService.Response." +
            GetPermissionRequestString(GetUmaValueForRequestType(request_type)),
        is_heldback);
  } else {
    base::UmaHistogramBoolean(
        "Permissions.PredictionService.Response." +
            GetPermissionRequestString(GetUmaValueForRequestType(request_type)),
        is_heldback);
  }
}

// static
void PermissionUmaUtil::RecordPageInfoDialogAccessType(
    PageInfoDialogAccessType access_type) {
  base::UmaHistogramEnumeration(
      "Permissions.ConfirmationChip.PageInfoDialogAccessType", access_type);
}

// static
std::string PermissionUmaUtil::GetOneTimePermissionEventHistogram(
    ContentSettingsType type) {
  // `FILE_SYSTEM_WRITE_GUARD` is not part of `OneTimePermission`,
  // (i.e. `CanPermissionBeAllowedOnce()`), but it uses its background expiry
  // flow. As a result, allow logging for this event.
  DCHECK(permissions::PermissionUtil::CanPermissionBeAllowedOnce(type) ||
         type == ContentSettingsType::FILE_SYSTEM_WRITE_GUARD);

  std::string permission_type = GetPermissionRequestString(
      GetUmaValueForRequestType(ContentSettingsTypeToRequestType(type)));
  return "Permissions.OneTimePermission." + permission_type + ".Event";
}

// static
void PermissionUmaUtil::RecordOneTimePermissionEvent(
    ContentSettingsType type,
    OneTimePermissionEvent event) {
  base::UmaHistogramEnumeration(GetOneTimePermissionEventHistogram(type),
                                event);
}

// static
void PermissionUmaUtil::RecordPageInfoPermissionChangeWithin1m(
    ContentSettingsType type,
    PermissionAction previous_action,
    ContentSetting setting_after) {
  DCHECK(IsRequestablePermissionType(type));
  std::string permission_type = GetPermissionRequestString(
      GetUmaValueForRequestType(ContentSettingsTypeToRequestType(type)));
  std::string histogram_name =
      "Permissions.PageInfo.ChangedWithin1m." + permission_type;
  switch (previous_action) {
    case PermissionAction::GRANTED:
    case PermissionAction::GRANTED_ONCE:
      if (setting_after == ContentSetting::CONTENT_SETTING_BLOCK) {
        base::UmaHistogramEnumeration(histogram_name,
                                      PermissionChangeAction::REVOKED);
      } else if (setting_after == ContentSetting::CONTENT_SETTING_DEFAULT) {
        base::UmaHistogramEnumeration(
            histogram_name, PermissionChangeAction::RESET_FROM_ALLOWED);
      }
      break;
    case PermissionAction::DENIED:
      if (setting_after == ContentSetting::CONTENT_SETTING_ALLOW) {
        base::UmaHistogramEnumeration(histogram_name,
                                      PermissionChangeAction::REALLOWED);
      } else if (setting_after == ContentSetting::CONTENT_SETTING_DEFAULT) {
        base::UmaHistogramEnumeration(
            histogram_name, PermissionChangeAction::RESET_FROM_DENIED);
      }
      break;
    case PermissionAction::DISMISSED:  // dismissing had no effect on content
                                       // setting
    case PermissionAction::IGNORED:    // ignoring has no effect on content
                                       // settings
    case PermissionAction::REVOKED:  // not a relevant use case for this metric
    case PermissionAction::NUM:      // placeholder
      break;                         // NOP
  }
}

// static
void PermissionUmaUtil::RecordPageInfoPermissionChange(
    ContentSettingsType type,
    ContentSetting setting_before,
    ContentSetting setting_after,
    bool suppress_reload_page_bar) {
  DCHECK(IsRequestablePermissionType(type));
  // Currently only Camera and Mic are supported.
  DCHECK(type == ContentSettingsType::MEDIASTREAM_MIC ||
         type == ContentSettingsType::MEDIASTREAM_CAMERA);
  std::string permission_type = GetPermissionRequestString(
      GetUmaValueForRequestType(ContentSettingsTypeToRequestType(type)));
  std::string histogram_name =
      "Permissions.PageInfo.Changed." + permission_type;

  if (suppress_reload_page_bar) {
    histogram_name = histogram_name + ".ReloadInfobarNotShown";
  } else {
    histogram_name = histogram_name + ".ReloadInfobarShown";
  }

  if (setting_before == ContentSetting::CONTENT_SETTING_BLOCK) {
    if (setting_after == ContentSetting::CONTENT_SETTING_ALLOW) {
      base::UmaHistogramEnumeration(histogram_name,
                                    PermissionChangeAction::REALLOWED);
    } else if (setting_after == ContentSetting::CONTENT_SETTING_ASK ||
               setting_after == ContentSetting::CONTENT_SETTING_DEFAULT) {
      base::UmaHistogramEnumeration(histogram_name,
                                    PermissionChangeAction::RESET_FROM_DENIED);
    } else {
      NOTREACHED();
    }
  } else if (setting_before == ContentSetting::CONTENT_SETTING_ALLOW) {
    if (setting_after == ContentSetting::CONTENT_SETTING_BLOCK) {
      base::UmaHistogramEnumeration(histogram_name,
                                    PermissionChangeAction::REVOKED);
    } else if (setting_after == ContentSetting::CONTENT_SETTING_ASK ||
               setting_after == ContentSetting::CONTENT_SETTING_DEFAULT) {
      base::UmaHistogramEnumeration(histogram_name,
                                    PermissionChangeAction::RESET_FROM_ALLOWED);
    } else if (setting_after == ContentSetting::CONTENT_SETTING_ALLOW) {
      base::UmaHistogramEnumeration(
          histogram_name, PermissionChangeAction::REMEMBER_CHECKBOX_TOGGLED);
    } else {
      NOTREACHED();
    }
  }
}

// static
std::string PermissionUmaUtil::GetPermissionActionString(
    PermissionAction permission_action) {
  switch (permission_action) {
    case PermissionAction::GRANTED:
      return "Accepted";
    case PermissionAction::DENIED:
      return "Denied";
    case PermissionAction::DISMISSED:
      return "Dismissed";
    case PermissionAction::IGNORED:
      return "Ignored";
    case PermissionAction::GRANTED_ONCE:
      return "AcceptedOnce";
    default:
      NOTREACHED();
  }
  NOTREACHED();
  return std::string();
}

// static
std::string PermissionUmaUtil::GetPromptDispositionString(
    PermissionPromptDisposition ui_disposition) {
  switch (ui_disposition) {
    case PermissionPromptDisposition::ANCHORED_BUBBLE:
      return "AnchoredBubble";
    case PermissionPromptDisposition::CUSTOM_MODAL_DIALOG:
      return "CustomModalDialog";
    case PermissionPromptDisposition::ELEMENT_ANCHORED_BUBBLE:
      return "ElementAnchoredBubble";
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP:
      return "LocationBarLeftChip";
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_CHIP:
      return "LocationBarLeftQuietChip";
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_ABUSIVE_CHIP:
      return "LocationBarLeftQuietAbusiveChip";
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP_AUTO_BUBBLE:
      return "LocationBarLeftChipAutoBubble";
    case PermissionPromptDisposition::LOCATION_BAR_RIGHT_ANIMATED_ICON:
      return "LocationBarRightAnimatedIcon";
    case PermissionPromptDisposition::LOCATION_BAR_RIGHT_STATIC_ICON:
      return "LocationBarRightStaticIcon";
    case PermissionPromptDisposition::MINI_INFOBAR:
      return "MiniInfobar";
    case PermissionPromptDisposition::MESSAGE_UI:
      return "MessageUI";
    case PermissionPromptDisposition::MODAL_DIALOG:
      return "ModalDialog";
    case PermissionPromptDisposition::NONE_VISIBLE:
      return "NoneVisible";
    case PermissionPromptDisposition::NOT_APPLICABLE:
      return "NotApplicable";
    case PermissionPromptDisposition::MAC_OS_PROMPT:
      return "MacOsPrompt";
  }

  NOTREACHED();
  return std::string();
}

// static
std::string PermissionUmaUtil::GetPromptDispositionReasonString(
    PermissionPromptDispositionReason ui_disposition_reason) {
  switch (ui_disposition_reason) {
    case PermissionPromptDispositionReason::DEFAULT_FALLBACK:
      return "DefaultFallback";
    case PermissionPromptDispositionReason::ON_DEVICE_PREDICTION_MODEL:
      return "OnDevicePredictionModel";
    case PermissionPromptDispositionReason::PREDICTION_SERVICE:
      return "PredictionService";
    case PermissionPromptDispositionReason::SAFE_BROWSING_VERDICT:
      return "SafeBrowsingVerdict";
    case PermissionPromptDispositionReason::USER_PREFERENCE_IN_SETTINGS:
      return "UserPreferenceInSettings";
  }

  NOTREACHED();
  return std::string();
}

// static
std::string PermissionUmaUtil::GetRequestTypeString(RequestType request_type) {
  return GetPermissionRequestString(GetUmaValueForRequestType(request_type));
}

// static
bool PermissionUmaUtil::IsPromptDispositionQuiet(
    PermissionPromptDisposition prompt_disposition) {
  switch (prompt_disposition) {
    case PermissionPromptDisposition::LOCATION_BAR_RIGHT_STATIC_ICON:
    case PermissionPromptDisposition::LOCATION_BAR_RIGHT_ANIMATED_ICON:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_CHIP:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_ABUSIVE_CHIP:
    case PermissionPromptDisposition::MINI_INFOBAR:
    case PermissionPromptDisposition::MESSAGE_UI:
    case PermissionPromptDisposition::MAC_OS_PROMPT:
      return true;
    case PermissionPromptDisposition::ANCHORED_BUBBLE:
    case PermissionPromptDisposition::ELEMENT_ANCHORED_BUBBLE:
    case PermissionPromptDisposition::MODAL_DIALOG:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP_AUTO_BUBBLE:
    case PermissionPromptDisposition::NONE_VISIBLE:
    case PermissionPromptDisposition::CUSTOM_MODAL_DIALOG:
    case PermissionPromptDisposition::NOT_APPLICABLE:
      return false;
  }
}

// static
bool PermissionUmaUtil::IsPromptDispositionLoud(
    PermissionPromptDisposition prompt_disposition) {
  switch (prompt_disposition) {
    case PermissionPromptDisposition::ANCHORED_BUBBLE:
    case PermissionPromptDisposition::ELEMENT_ANCHORED_BUBBLE:
    case PermissionPromptDisposition::MODAL_DIALOG:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_CHIP_AUTO_BUBBLE:
      return true;
    case PermissionPromptDisposition::LOCATION_BAR_RIGHT_STATIC_ICON:
    case PermissionPromptDisposition::LOCATION_BAR_RIGHT_ANIMATED_ICON:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_CHIP:
    case PermissionPromptDisposition::LOCATION_BAR_LEFT_QUIET_ABUSIVE_CHIP:
    case PermissionPromptDisposition::MINI_INFOBAR:
    case PermissionPromptDisposition::MESSAGE_UI:
    case PermissionPromptDisposition::NONE_VISIBLE:
    case PermissionPromptDisposition::CUSTOM_MODAL_DIALOG:
    case PermissionPromptDisposition::NOT_APPLICABLE:
    case PermissionPromptDisposition::MAC_OS_PROMPT:
      return false;
  }
}

// static
void PermissionUmaUtil::RecordIgnoreReason(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    PermissionPromptDisposition prompt_disposition,
    PermissionIgnoredReason reason) {
  RequestTypeForUma request_type = RequestTypeForUma::MULTIPLE;
  if (requests.size() == 1) {
    request_type = GetUmaValueForRequestType(requests[0]->request_type());
  }

  std::string histogram_name =
      "Permissions.Prompt." + GetPermissionRequestString(request_type) + "." +
      GetPromptDispositionString(prompt_disposition) + ".IgnoredReason";
  base::UmaHistogramEnumeration(histogram_name, reason,
                                PermissionIgnoredReason::NUM);
}

// static
void PermissionUmaUtil::RecordPermissionsUsageSourceAndPolicyConfiguration(
    ContentSettingsType content_settings_type,
    content::RenderFrameHost* render_frame_host) {
  const bool is_cross_origin_subframe =
      IsCrossOriginSubframe(render_frame_host);
  const auto usage_histogram = base::StrCat(
      {kPermissionsExperimentalUsagePrefix,
       PermissionUtil::GetPermissionString(content_settings_type)});
  base::UmaHistogramBoolean(
      base::StrCat({usage_histogram, ".IsCrossOriginFrame"}),
      is_cross_origin_subframe);
  if (is_cross_origin_subframe) {
    RecordTopLevelPermissionsHeaderPolicy(
        content_settings_type,
        base::StrCat(
            {usage_histogram, ".CrossOriginFrame.TopLevelHeaderPolicy"}),
        render_frame_host);
  }
}

// static
void PermissionUmaUtil::RecordElementAnchoredBubbleDismiss(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    DismissedReason reason) {
  CHECK(!requests.empty());

  RequestTypeForUma type =
      GetUmaValueForRequestType(requests[0]->request_type());
  if (requests.size() > 1) {
    type = RequestTypeForUma::MULTIPLE;
  }

  base::UmaHistogramEnumeration("Permissions.Prompt." +
                                    GetPermissionRequestString(type) +
                                    ".ElementAnchoredBubble.DismissedReason",
                                reason);
}

// static
void PermissionUmaUtil::RecordElementAnchoredBubbleOsScreenAction(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    OsScreen screen,
    OsScreenAction action) {
  CHECK(!requests.empty());

  RequestTypeForUma type =
      GetUmaValueForRequestType(requests[0]->request_type());
  if (requests.size() > 1) {
    type = RequestTypeForUma::MULTIPLE;
  }

  std::string screen_type;
  switch (screen) {
    case OsScreen::OS_PROMPT:
      screen_type = "OS_PROMPT";
      break;
    case OsScreen::OS_SYSTEM_SETTINGS:
      screen_type = "OS_SYSTEM_SETTINGS";
      break;
    default:
      NOTREACHED();
  }

  base::UmaHistogramEnumeration(
      "Permissions.Prompt." + GetPermissionRequestString(type) +
          ".ElementAnchoredBubble" + screen_type + ".OsScreenAction",
      action);
}

void PermissionUmaUtil::RecordElementAnchoredBubbleVariantUMA(
    const std::vector<raw_ptr<PermissionRequest, VectorExperimental>>& requests,
    ElementAnchoredBubbleVariant variant) {
  CHECK(!requests.empty());

  RequestTypeForUma type =
      GetUmaValueForRequestType(requests[0]->request_type());
  if (requests.size() > 1) {
    type = RequestTypeForUma::MULTIPLE;
  }

  base::UmaHistogramEnumeration("Permissions.Prompt." +
                                    GetPermissionRequestString(type) +
                                    ".ElementAnchoredBubble.Variant",
                                variant);
}

// static
void PermissionUmaUtil::RecordCrossOriginFrameActionAndPolicyConfiguration(
    ContentSettingsType content_settings_type,
    PermissionAction action,
    content::RenderFrameHost* render_frame_host) {
  DCHECK(IsCrossOriginSubframe(render_frame_host));

  const auto histogram =
      base::StrCat({kPermissionsActionPrefix,
                    PermissionUtil::GetPermissionString(content_settings_type),
                    ".CrossOriginFrame"});
  base::UmaHistogramEnumeration(histogram, action, PermissionAction::NUM);
  RecordTopLevelPermissionsHeaderPolicy(
      content_settings_type, base::StrCat({histogram, ".TopLevelHeaderPolicy"}),
      render_frame_host);
}

// static
void PermissionUmaUtil::RecordTopLevelPermissionsHeaderPolicyOnNavigation(
    content::RenderFrameHost* render_frame_host) {
  DCHECK(render_frame_host);
  static constexpr ContentSettingsType kContentSettingsTypesForMetrics[] = {
      ContentSettingsType::GEOLOCATION, ContentSettingsType::MEDIASTREAM_CAMERA,
      ContentSettingsType::MEDIASTREAM_MIC};

  for (const auto content_settings_type : kContentSettingsTypesForMetrics) {
    const auto feature =
        PermissionUtil::GetPermissionsPolicyFeature(content_settings_type);
    DCHECK(feature.has_value());
    base::UmaHistogramEnumeration(
        base::StrCat(
            {"Permissions.Experimental.PrimaryMainNavigationFinished.",
             PermissionUtil::GetPermissionString(content_settings_type),
             ".TopLevelHeaderPolicy"}),
        GetTopLevelPermissionHeaderPolicyForUMA(render_frame_host,
                                                feature.value()),
        PermissionHeaderPolicyForUMA::NUM);
  }
}

void PermissionUmaUtil::RecordPermissionRegrantForUnusedSites(
    const GURL& origin,
    ContentSettingsType content_settings_type,
    PermissionSourceUI source_ui,
    content::BrowserContext* browser_context,
    base::Time current_time) {
  auto* hcsm = PermissionsClient::Get()->GetSettingsMap(browser_context);
  std::optional<uint32_t> days_since_revocation =
      GetDaysSinceUnusedSitePermissionRevocation(origin, content_settings_type,
                                                 current_time, hcsm);
  if (!days_since_revocation.has_value()) {
    return;
  }
  std::string source_ui_string;
  // We are only interested in permission updates through the UI that go from
  // Ask to Allow. This can only be done through the permission prompt and the
  // site settings page.
  switch (source_ui) {
    case PermissionSourceUI::PROMPT:
      source_ui_string = "Prompt";
      break;
    case PermissionSourceUI::SITE_SETTINGS:
      source_ui_string = "Settings";
      break;
    default:
      NOTREACHED();
  }
  base::UmaHistogramExactLinear(
      "Settings.SafetyCheck.UnusedSitePermissionsRegrantDays" +
          source_ui_string + "." +
          PermissionUtil::GetPermissionString(content_settings_type),
      days_since_revocation.value(), 31);
  base::UmaHistogramExactLinear(
      "Settings.SafetyCheck.UnusedSitePermissionsRegrantDays" +
          source_ui_string + ".All",
      days_since_revocation.value(), 31);
}

// static
std::optional<uint32_t>
PermissionUmaUtil::GetDaysSinceUnusedSitePermissionRevocation(
    const GURL& origin,
    ContentSettingsType content_settings_type,
    base::Time current_time,
    HostContentSettingsMap* hcsm) {
  content_settings::SettingInfo info;
  base::Value stored_value(hcsm->GetWebsiteSetting(
      origin, origin, ContentSettingsType::REVOKED_UNUSED_SITE_PERMISSIONS,
      &info));
  if (!stored_value.is_dict()) {
    return std::nullopt;
  }
  base::Value::List* permission_type_list =
      stored_value.GetDict().FindList(permissions::kRevokedKey);
  if (!permission_type_list) {
    return std::nullopt;
  }
  base::Time revoked_time =
      info.metadata.expiration() -
      content_settings::features::
          kSafetyCheckUnusedSitePermissionsRevocationCleanUpThreshold.Get();
  uint32_t days_since_revoked = (current_time - revoked_time).InDays();

  for (auto& permission_type : *permission_type_list) {
    auto type_int = permission_type.GetIfInt();
    if (!type_int.has_value()) {
      continue;
    }
    if (content_settings_type ==
        static_cast<ContentSettingsType>(type_int.value())) {
      return days_since_revoked;
    }
  }

  return std::nullopt;
}

}  // namespace permissions
