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

#include "content/browser/accessibility/browser_accessibility_state_impl.h"

#include <stddef.h>

#include <algorithm>
#include <utility>

#include "base/check.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/browser/accessibility/render_accessibility_host.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/scoped_accessibility_mode.h"
#include "content/public/browser/web_contents_user_data.h"
#include "content/public/common/content_switches.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/accessibility/accessibility_switches.h"
#include "ui/accessibility/ax_mode_histogram_logger.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/color_utils.h"

namespace content {

namespace {

BrowserAccessibilityStateImpl* g_instance = nullptr;

// Auto-disable accessibility if this many seconds elapse with user input
// events but no accessibility API usage.
constexpr int kAutoDisableAccessibilityTimeSecs = 30;

// Minimum number of user input events with no accessibility API usage
// before auto-disabling accessibility.
constexpr int kAutoDisableAccessibilityEventCount = 3;

// Updating Active/Inactive time on every accessibility api calls would not be
// good for perf. Instead, delay the update task.
constexpr int kOnAccessibilityUsageUpdateDelaySecs = 5;

// Parameter values for --force-renderer-accessibility=[bundle-name].
const char kAXModeBundleBasic[] = "basic";
const char kAXModeBundleFormControls[] = "form-controls";
const char kAXModeBundleComplete[] = "complete";
const char kAXModeBundleOnScreen[] = "on-screen";

// A data holder attached to a WebContents while it is hidden and has
// accessibility enabled. Used only when the disable_on_hide feature of
// ProgressiveAccessibility is enabled and an active screen reader has not been
// detected.
//
// An instance of this class is attached to a WebContents when it is hidden
// (thereby recording the TimeTicks at which the hide event took place). Its
// `Schedule()` method can later be called to schedule disablement of
// accessibility after the WebContents has been hidden for at least five
// minutes (+/- a randomizer of up to twenty seconds).
//
// The instance is removed from the WebContents and destroyed on the first of:
// *  the WebContents is destroyed (by virtue of being a WebContentsUserData),
// *  the WebContents is revealed (see
//    `BrowserAccessibilityStateImpl::OnWebContentsRevealed()`),
// *  an active screen reader is detected (see
//    `BrowserAccessibilityStateImpl::OnAssistiveTechFound()`), or
// *  the task to disable accessibility runs.
class AccessibilityDisabler
    : public WebContentsUserData<AccessibilityDisabler> {
 public:
  WEB_CONTENTS_USER_DATA_KEY_DECL();

  // Constructs an instance for `web_contents`; see comment above for
  // details. `callback` will be run if this instance is destroyed (either
  // because `web_contents` is destroyed or because `Remove()` is called) before
  // `Schedule()` is called.
  using OnDestroyedBeforeScheduleCallback =
      base::OnceCallback<void(WebContentsImpl* web_contents)>;
  AccessibilityDisabler(WebContents* web_contents,
                        OnDestroyedBeforeScheduleCallback callback)
      : WebContentsUserData(*web_contents),
        on_destroyed_before_schedule_(std::move(callback)) {}

  // This destructor is run either when the WebContents to which this instance
  // is attached is destroyed or when `Remove()` is called.
  ~AccessibilityDisabler() override {
    // If the the instance still has the on_destroyed_before_schedule_ callback,
    // then `Schedule()` has not yet been called. Run the callback now so that
    // the BrowserAccessibilityStateImpl can remove the WebContents from its
    // last_hidden_ collection.
    if (on_destroyed_before_schedule_) {
      std::move(on_destroyed_before_schedule_)
          .Run(&static_cast<WebContentsImpl&>(GetWebContents()));
    }
  }

  // Removes (and destroys) an instance attached to `web_contents`.
  static void Remove(WebContentsImpl* web_contents) {
    web_contents->RemoveUserData(UserDataKey());
  }

  // Schedules a task that will disable accessibility for `web_contents` once
  // it has been hidden for at least five minutes +/- twenty seconds.
  static void Schedule(WebContentsImpl* web_contents) {
    auto* disabler = FromWebContents(web_contents);
    CHECK(disabler);
    // Elapsed ticks since the WebContents was hidden.
    const base::TimeDelta since_hidden =
        base::TimeTicks::Now() - disabler->hide_instant_;
    // Ticks until accessibility should be disabled.
    const base::TimeDelta disable_in =
        BrowserAccessibilityStateImpl::GetRandomizedDisableDelay() -
        since_hidden;

    disabler->disable_ax_timer_.Start(
        FROM_HERE, std::max(disable_in, base::TimeDelta()), disabler,
        &AccessibilityDisabler::DisableAccessibility);

    // Now that this WebContents has been scheduled for disablement, it is no
    // longer in the BrowserAccessibilityStateImpl's last_hidden_ collection,
    // therefore it is no longer necessary to notify it upon destruction.
    disabler->on_destroyed_before_schedule_.Reset();
  }

 private:
  void DisableAccessibility() {
    base::UmaHistogramBoolean("Accessibility.DisabledAfterHide", true);
    auto& web_contents = static_cast<WebContentsImpl&>(GetWebContents());
    web_contents.SetAccessibilityMode({});
    web_contents.RemoveUserData(UserDataKey());  // deletes `this`.
  }

  // A callback to be run if the WebContents is destroyed before `Schedule()` is
  // called.
  OnDestroyedBeforeScheduleCallback on_destroyed_before_schedule_;

  // The time the WebContents was hidden.
  base::TimeTicks hide_instant_{base::TimeTicks::Now()};

  // A timer to disable accessibility after a delay.
  base::OneShotTimer disable_ax_timer_;
};

WEB_CONTENTS_USER_DATA_KEY_IMPL(AccessibilityDisabler);

// A holder of a ScopedModeCollection targeting a specific BrowserContext or
// WebContents. The collection is bound to the lifetime of the target.
class ModeCollectionForTarget : public base::SupportsUserData::Data,
                                public ScopedModeCollection::Delegate {
 public:
  using OnModeChangedCallback =
      base::RepeatingCallback<void(ui::AXMode old_mode, ui::AXMode new_mode)>;
  ModeCollectionForTarget(base::SupportsUserData* target,
                          OnModeChangedCallback on_mode_changed)
      : target_(target), on_mode_changed_(std::move(on_mode_changed)) {}
  ModeCollectionForTarget(const ModeCollectionForTarget&) = delete;
  ModeCollectionForTarget& operator=(const ModeCollectionForTarget&) = delete;

  static ui::AXMode GetAccessibilityMode(base::SupportsUserData* target) {
    auto* instance = FromTarget(target);
    return instance ? instance->scoped_mode_collection_.accessibility_mode()
                    : ui::AXMode();
  }

  // Adds a new scoper targeting `target` (a BrowserContext or a WebContents)
  // that applies the accessibility mode flags in `mode`. `on_changed_function`
  // is a pointer to a member function of `BrowserAccessibilityStateImpl` that
  // is called when the effective mode for `target` changes; see
  // `ScopedModeCollection::OnModeChangedCallback`. It is bound into a callback
  // (along with `impl`) when this is the first addition for `target`;
  // otherwise, it (and `impl`) are ignored.
  template <class Target>
  static std::unique_ptr<ScopedAccessibilityMode> Add(
      Target* target,
      void (BrowserAccessibilityStateImpl::*on_changed_function)(Target*,
                                                                 ui::AXMode,
                                                                 ui::AXMode),
      BrowserAccessibilityStateImpl* impl,
      ui::AXMode mode) {
    auto* instance = FromTarget(target);
    if (!instance) {
      auto holder = std::make_unique<ModeCollectionForTarget>(
          target,
          base::BindRepeating(on_changed_function, base::Unretained(impl),
                              base::Unretained(target)));
      instance = holder.get();
      target->SetUserData(&kUserDataKey, std::move(holder));
    }
    return instance->scoped_mode_collection_.Add(mode);
  }

 private:
  static ModeCollectionForTarget* FromTarget(base::SupportsUserData* target) {
    return static_cast<ModeCollectionForTarget*>(
        target->GetUserData(&ModeCollectionForTarget::kUserDataKey));
  }

  void OnModeChanged(ui::AXMode old_mode, ui::AXMode new_mode) override {
    // If the collection is no longer bound to the target, the target is in the
    // process of being destroyed. Ignore changes when this is the case.
    if (auto* const collection = FromTarget(target_); collection) {
      on_mode_changed_.Run(old_mode, new_mode);
    }
  }

  ui::AXMode FilterModeFlags(ui::AXMode mode) override { return mode; }

  static const int kUserDataKey = 0;

  raw_ptr<base::SupportsUserData> target_;
  OnModeChangedCallback on_mode_changed_;
  ScopedModeCollection scoped_mode_collection_{*this};
};

// static
const int ModeCollectionForTarget::kUserDataKey;

// Returns a subset of `mode` for delivery to a WebContents.
ui::AXMode FilterAccessibilityModeInvariants(ui::AXMode mode) {
  // kFromPlatform is never sent to WebContents.
  CHECK(!mode.has_mode(ui::AXMode::kFromPlatform));

  // Strip kLabelImages if kExtendedProperties is absent.
  // TODO(grt): kLabelImages is a feature of //chrome. Find a way to
  // achieve this filtering without teaching //content about it. Perhaps via
  // the delegate interface to be added in support of https://crbug.com/1470199.
  if (ui::AXMode(mode.flags() ^ ui::AXMode::kExtendedProperties)
          .has_mode(ui::AXMode::kLabelImages |
                    ui::AXMode::kExtendedProperties)) {
    mode.set_mode(ui::AXMode::kLabelImages, false);
  }

  // Modes above kNativeAPIs and kWebContents require kWebContents. Some
  // components may enable higher bits, but those should only be given to a
  // WebContents if that WebContents also has the kWebContents mode enabled;
  // see `content::RenderFrameHostImpl::UpdateAccessibilityMode()` and
  // `content::RenderAccessibilityManager::SetMode()`.
  if (!mode.has_mode(ui::AXMode::kWebContents)) {
    return mode & ui::AXMode::kNativeAPIs;
  }

  // Form controls mode is restrictive. There are other modes that should not be
  // used in combination with it. This could occur if something that needs
  // screen reader mode is turned on after forms control mode. In that case,
  // forms mode must be removed.
  if (mode.has_mode(ui::AXMode::kInlineTextBoxes) ||
      mode.has_mode(ui::AXMode::kExtendedProperties)) {
    return ui::AXMode(mode.flags(),
                      mode.filter_flags() & ~ui::AXMode::kFormsAndLabelsOnly);
  }

  return mode;
}

// Determines if the given `mode` contains flags that conflict
// with the performance experiment. Certain AXMode flags are allowed because
// they are either extra annotations or not relevant to web content (the
// primary focus of the performance measurement).
bool IsAXModeConflictingWithExperiment(ui::AXMode mode) {
  // Remove the allowed flags from the 'mode'.
  // If any flags remain after this operation, they are considered conflicting.
  mode &=
      ~ui::AXMode(ui::AXMode::kAnnotateMainNode | ui::AXMode::kFromPlatform |
                  ui::AXMode::kLabelImages | ui::AXMode::kNativeAPIs);

  // If 'mode' is not entirely cleared after removing allowed flags, then
  // conflicting flags were present.
  return !mode.is_mode_off();
}

}  // namespace

// static
BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() {
  return BrowserAccessibilityStateImpl::GetInstance();
}

// static
BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() {
  CHECK(g_instance);
  return g_instance;
}

// On Android, Mac, Windows and Linux there are platform-specific subclasses.
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC) && \
    !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
// static
std::unique_ptr<BrowserAccessibilityStateImpl>
BrowserAccessibilityStateImpl::Create() {
  return base::WrapUnique(new BrowserAccessibilityStateImpl());
}
#endif

namespace {

constexpr base::TimeDelta kDisableDelay = base::Minutes(5);
constexpr int kDisableDelayVarianceSeconds = 20;

}  // namespace

// static
base::TimeDelta BrowserAccessibilityStateImpl::GetRandomizedDisableDelay() {
  const base::TimeDelta variance = base::Seconds(base::RandInt(
      -kDisableDelayVarianceSeconds, kDisableDelayVarianceSeconds));
  return kDisableDelay + variance;
}

// static
base::TimeDelta BrowserAccessibilityStateImpl::GetMaxDisableDelay() {
  return kDisableDelay + base::Seconds(kDisableDelayVarianceSeconds);
}

BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
    : platform_ax_mode_(CreateScopedModeForProcess(ui::AXMode())) {
  DCHECK_EQ(g_instance, nullptr);
  g_instance = this;

  bool disallow_changes = false;
  ui::AXMode initial_mode;
  auto& command_line = *base::CommandLine::ForCurrentProcess();

  if (command_line.HasSwitch(
          switches::kDisablePlatformAccessibilityIntegration)) {
    SetActivationFromPlatformEnabled(/*enabled=*/false);
  }

  if (command_line.HasSwitch(switches::kDisableRendererAccessibility)) {
    disallow_changes = true;
  } else if (command_line.HasSwitch(switches::kForceRendererAccessibility)) {
#if BUILDFLAG(IS_WIN)
    std::string ax_mode_bundle =
        base::WideToUTF8(command_line.GetSwitchValueNative(
            switches::kForceRendererAccessibility));
#else
    std::string ax_mode_bundle = command_line.GetSwitchValueNative(
        switches::kForceRendererAccessibility);
#endif

    if (ax_mode_bundle.empty()) {
      // For backwards compatibility, when --force-renderer-accessibility has no
      // parameter, use the screen reader bundle but allow changes.
      // This is the best general choice in development and testing scenarios.
      initial_mode = ui::kAXModeComplete | ui::AXMode::kScreenReader;
    } else {
      // Support
      // --force-renderer-accessibility=[basic|form-controls|complete|
      //                                 screen-reader|on-screen]
      if (ax_mode_bundle.compare(kAXModeBundleBasic) == 0) {
        initial_mode = ui::kAXModeBasic;
      } else if (ax_mode_bundle.compare(kAXModeBundleFormControls) == 0) {
        initial_mode = ui::kAXModeFormControls;
      } else if (ax_mode_bundle.compare(kAXModeBundleComplete) == 0) {
        initial_mode = ui::kAXModeComplete;
      } else if (ax_mode_bundle.compare(kAXModeBundleOnScreen) == 0) {
        initial_mode = ui::kAXModeOnScreen;
      } else {
        // If 'screen-reader', or invalid, default to screen reader bundle,
        // which is the most useful in development and testing scenarios.
        initial_mode = ui::kAXModeComplete | ui::AXMode::kScreenReader;
      }
      disallow_changes = true;
    }
  }

  if (::features::IsAccessibilityOnScreenAXModeEnabled()) {
    initial_mode |= ui::kAXModeOnScreen;
  }

  // Create an initial process-wide ScopedAccessibilityMode whether any flags
  // are enabled or not. Always creating a ScopedAccessibilityMode
  // (even if it holds a mode with all flags off) allows us to avoid null
  // checks elsewhere, thereby simplifying other logic.
  forced_accessibility_mode_ = CreateScopedModeForProcess(initial_mode);

  // Configure the performance experiment if no command-line switches were used.
  if (!disallow_changes && initial_mode.is_mode_off()) {
    experiment_accessibility_mode_ =
        ConfigureAccessibilityPerformanceExperiment();
  }

  UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled",
                        !initial_mode.is_mode_off());

  SetAXModeChangeAllowed(!disallow_changes);
}

BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
  DCHECK_EQ(g_instance, this);
  g_instance = nullptr;

  CHECK(last_hidden_.empty());
}

void BrowserAccessibilityStateImpl::OnAssistiveTechFound(
    ui::AssistiveTech assistive_tech) {
  const bool was_screenreader_active = ax_platform_.IsScreenReaderActive();
  ax_platform_.NotifyAssistiveTechChanged(assistive_tech);

  // Terminate disable_on_hide if a screen reader has just become active. Do
  // this without first checking the feature to avoid activating the field trial
  // when it's not already active. Performing this removal when the feature is
  // off is harmless.
  if (!was_screenreader_active && ax_platform_.IsScreenReaderActive()) {
    // Cancel all disablers. There is one for each WebContents in `last_hidden_`
    // and one for each that has had `AccessibilityDisabler::Schedule()` called.
    // Since these are not specifically tracked, remove a potential disabler
    // from every WebContents. OnDisablerDestroyedForWebContents will be called
    // to remove a WebContents from `last_hidden_` if its disabler has not yet
    // been scheduled.
    std::ranges::for_each(WebContentsImpl::GetAllWebContents(),
                          [](WebContentsImpl* web_contents) {
                            if (!web_contents->IsBeingDestroyed() &&
                                !web_contents->IsNeverComposited()) {
                              AccessibilityDisabler::Remove(web_contents);
                            }
                          });
  }
}

void BrowserAccessibilityStateImpl::RefreshAssistiveTech() {
  bool sr_active = GetAccessibilityMode().has_mode(ui::AXMode::kScreenReader);
  OnAssistiveTechFound(sr_active ? ui::AssistiveTech::kGenericScreenReader
                                 : ui::AssistiveTech::kNone);
}

std::unique_ptr<ScopedAccessibilityMode>
BrowserAccessibilityStateImpl::ConfigureAccessibilityPerformanceExperiment() {
  if (!features::IsAccessibilityPerformanceMeasurementExperimentEnabled()) {
    // This is the control group.
    return nullptr;
  }

  // Checking the flag is what causes the study to be active, so we need to
  // configure the AXModes based on which experiment arm we are in.

  switch (features::GetAccessibilityPerformanceMeasurementExperimentGroup()) {
    case features::AccessibilityPerformanceMeasurementExperimentGroup::
        kAXModeComplete:
      return CreateScopedModeForProcess(ui::kAXModeComplete);
    case features::AccessibilityPerformanceMeasurementExperimentGroup::
        kWebContentsOnly:
      // TODO(accessibility): there seems to be a strange naming here.
      // kWebContentsOnly helper function in ax_mode.h defines almost a
      // kAXModeComplete. However, in experiment setup discussions, we wanted
      // more likely kAXModeBasic, where only the real, AXMode, kWebContents
      // is set. Which one is it?
      return CreateScopedModeForProcess(ui::kAXModeBasic);
    case features::AccessibilityPerformanceMeasurementExperimentGroup::
        kAXModeCompleteNoInlineTextBoxes:
      return CreateScopedModeForProcess(ui::kAXModeComplete &
                                        ~ui::AXMode::kInlineTextBoxes);
    case features::AccessibilityPerformanceMeasurementExperimentGroup::
        kRendererSerializationOnly:
      RenderAccessibilityHost::SetRendererSerializationExperimentEnabled(true);
      return CreateScopedModeForProcess(ui::kAXModeComplete);
  }

  NOTREACHED();
}

void BrowserAccessibilityStateImpl::RefreshAssistiveTechIfNecessary(
    ui::AXMode new_mode) {
  // Platforms that use this default implementation have a perfect signal
  // for screen reader launches. These platforms use AXMode::kScreenReader to
  // actively indicate that a screen reader is active.
  // Other platforms don't have this perfect signal and compute this off-thread,
  // adding/removing AXMode::kScreenReader after detection is complete.
  bool was_screen_reader_active = ax_platform_.IsScreenReaderActive();
  bool has_screen_reader_mode = new_mode.has_mode(ui::AXMode::kScreenReader);
  if (was_screen_reader_active != has_screen_reader_mode) {
    RefreshAssistiveTech();
  }
}

ui::AssistiveTech BrowserAccessibilityStateImpl::ActiveAssistiveTech() const {
  return ax_platform_.active_assistive_tech();
}

void BrowserAccessibilityStateImpl::SetPerformanceFilteringAllowed(
    bool allowed) {
  performance_filtering_allowed_ = allowed;
}

bool BrowserAccessibilityStateImpl::IsPerformanceFilteringAllowed() {
  return performance_filtering_allowed_;
}

void BrowserAccessibilityStateImpl::UpdateAccessibilityActivityTask() {
  if (!g_instance) {
    // There can be a race on shutdown since this is posted as a delayed task.
    return;
  }
  base::TimeTicks now = ui::EventTimeForNow();
  accessibility_last_usage_time_ = now;
  if (accessibility_active_start_time_.is_null()) {
    accessibility_active_start_time_ = now;
  }
  // If accessibility was enabled but inactive until now, log the amount
  // of time between now and the last API usage.
  if (!accessibility_inactive_start_time_.is_null()) {
    base::UmaHistogramLongTimes("Accessibility.InactiveTime",
                                now - accessibility_inactive_start_time_);
    accessibility_inactive_start_time_ = base::TimeTicks();
  }
  accessibility_update_task_pending_ = false;
}

ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() {
  return scoped_modes_for_process_.accessibility_mode();
}

ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityModeForBrowserContext(
    BrowserContext* browser_context) {
  return FilterAccessibilityModeInvariants(
      GetAccessibilityMode() |
      ModeCollectionForTarget::GetAccessibilityMode(browser_context));
}

bool BrowserAccessibilityStateImpl::ShouldBlockAutoDisable() {
  // This condition should only occur if a known assistive tech is active.
  // * If the assistive tech is actually still active, it indicates an error
  // with the heuristic, and we should notify a histogram so that we can
  // gather data and improve the heuristic's logic, as well as block the auto
  // disable from occurring.
  // * If the assistive tech is no longer active, then it has been unloaded
  // and it is fine to auto-disable.
  // Reaching here should be a rare case, and therefore we call the 'slow'
  // code (uses system calls on Windows/Linux) to update the running active
  // assistive tech state, before we make a determination.
  return ActiveAssistiveTech() != ui::AssistiveTech::kNone;
}

void BrowserAccessibilityStateImpl::OnUserInputEvent() {
  // No need to do anything if accessibility is off, or if it was forced on.
  if (GetAccessibilityMode().is_mode_off() || !allow_ax_mode_changes_) {
    return;
  }

  // If we get at least kAutoDisableAccessibilityEventCount user input
  // events, more than kAutoDisableAccessibilityTimeSecs apart, with
  // no accessibility API usage in-between disable accessibility.
  // (See also OnAccessibilityApiUsage()).
  // TODO(accessibility) This heuristic will possibly be removed because it's
  // easy for user input events to occur without causing any changes to the
  // a11y tree, or firing any events that an assistive tech would process.
  // However, we should also consider whether to use this heuristic in addition
  // to the focus/load complete one. Some categories of AT don't listen to focus
  // or load complete either e.g. Select to Speak. It may not be necessary for
  // Select-To-Speak to block auto disable if the disabling is lazy, e.g. on
  // next page load and just for this WebContents.
  base::TimeTicks now = ui::EventTimeForNow();
  user_input_event_count_++;
  if (user_input_event_count_ == 1) {
    first_user_input_event_time_ = now;
    return;
  }

  if (user_input_event_count_ < kAutoDisableAccessibilityEventCount) {
    return;
  }

  if (ShouldBlockAutoDisable()) {
    base::UmaHistogramEnumeration(
        "Accessibility.AutoDisabled.BlockedAfter.UserInput",
        ActiveAssistiveTech());
    return;
  }

  if (now - first_user_input_event_time_ >
      base::Seconds(kAutoDisableAccessibilityTimeSecs)) {
    if (!accessibility_active_start_time_.is_null()) {
      base::UmaHistogramLongTimes(
          "Accessibility.ActiveTime",
          accessibility_last_usage_time_ - accessibility_active_start_time_);

      // This will help track the time accessibility spends enabled, but
      // inactive.
      if (!features::IsAutoDisableAccessibilityEnabled()) {
        accessibility_inactive_start_time_ = accessibility_last_usage_time_;
      }

      accessibility_active_start_time_ = base::TimeTicks();
    }

    // Check if the feature to auto-disable accessibility is even enabled.
    if (features::IsAutoDisableAccessibilityEnabled()) {
      base::UmaHistogramCounts1000("Accessibility.AutoDisabled.EventCount",
                                   user_input_event_count_);
      DCHECK(!accessibility_enabled_time_.is_null());
      base::UmaHistogramLongTimes("Accessibility.AutoDisabled.EnabledTime",
                                  now - accessibility_enabled_time_);

      accessibility_disabled_time_ = now;

      // TODO(accessibility) Reimplement by making a11y dormant as opposed to
      // turning off flags, which leads to thrashing.
    }
  }
}

void BrowserAccessibilityStateImpl::SetAXModeChangeAllowed(bool allowed) {
  allow_ax_mode_changes_ = allowed;
  ui::AXPlatformNode::SetAXModeChangeAllowed(allowed);
}

bool BrowserAccessibilityStateImpl::IsAXModeChangeAllowed() const {
  return allow_ax_mode_changes_;
}

void BrowserAccessibilityStateImpl::SetActivationFromPlatformEnabled(
    bool enabled) {
  if (activation_from_platform_enabled_ == enabled) {
    return;
  }
  activation_from_platform_enabled_ = enabled;
  scoped_modes_for_process_.Recompute(MakePassKey());
}

bool BrowserAccessibilityStateImpl::IsActivationFromPlatformEnabled() {
  return activation_from_platform_enabled_;
}

bool BrowserAccessibilityStateImpl::
    IsAccessibilityPerformanceMeasurementExperimentActive() const {
  return experiment_accessibility_mode_.get();
}

void BrowserAccessibilityStateImpl::NotifyWebContentsPreferencesChanged()
    const {
  for (WebContentsImpl* wc : WebContentsImpl::GetAllWebContents()) {
    wc->OnWebPreferencesChanged();
  }
}

base::CallbackListSubscription
BrowserAccessibilityStateImpl::RegisterFocusChangedCallback(
    FocusChangedCallback callback) {
  return focus_changed_callbacks_.Add(std::move(callback));
}

void BrowserAccessibilityStateImpl::EnableAXModeFromPlatform(
    ui::AXMode modes_to_add) {
  ui::AXMode old_mode = platform_ax_mode_->mode();
  ui::AXMode new_mode = old_mode | modes_to_add;
  if (old_mode != new_mode) {
    platform_ax_mode_ =
        CreateScopedModeForProcess(new_mode | ui::AXMode::kFromPlatform);
  }

  // If AXMode::kWebContent is being requested, turn off auto-disable.
  // TODO(accessibility) Re-work the auto-disable feature.
  // Platform accessibility API usage affects auto-disable.
  // See OnUserInputEvent for how this is used to disable accessibility.
  user_input_event_count_ = 0;

  // See comment above kOnAccessibilityUsageUpdateDelaySecs for why we post a
  // delayed task.
  if (!accessibility_update_task_pending_) {
    accessibility_update_task_pending_ = true;
    GetUIThreadTaskRunner({})->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(
            &BrowserAccessibilityStateImpl::UpdateAccessibilityActivityTask,
            base::Unretained(this)),
        base::Seconds(kOnAccessibilityUsageUpdateDelaySecs));
  }
}

void BrowserAccessibilityStateImpl::OnMinimalPropertiesUsed() {
  // When only basic minimal functionality is used, just enable kNativeAPIs.
  // Enabling kNativeAPIs gives little perf impact, but allows these APIs to
  // interact with the BrowserAccessibilityManager allowing ATs to be able at
  // least find the document without using any advanced APIs.
  EnableAXModeFromPlatform(ui::AXMode::kNativeAPIs);
}

void BrowserAccessibilityStateImpl::OnPropertiesUsedInBrowserUI() {
  EnableAXModeFromPlatform(ui::AXMode::kNativeAPIs);
}

void BrowserAccessibilityStateImpl::OnPropertiesUsedInWebContent() {
  // When accessibility APIs have been used in content, enable basic web
  // accessibility support. Full screen reader support is detected later when
  // specific more advanced APIs are accessed.
  EnableAXModeFromPlatform(ui::kAXModeBasic);
}

void BrowserAccessibilityStateImpl::OnInlineTextBoxesUsedInWebContent() {
  EnableAXModeFromPlatform(ui::kAXModeBasic | ui::AXMode::kInlineTextBoxes);
}

void BrowserAccessibilityStateImpl::OnExtendedPropertiesUsedInWebContent() {
  EnableAXModeFromPlatform(ui::kAXModeBasic | ui::AXMode::kExtendedProperties);
}

void BrowserAccessibilityStateImpl::OnHTMLAttributesUsed() {
  EnableAXModeFromPlatform(ui::kAXModeBasic | ui::AXMode::kHTML);
}

void BrowserAccessibilityStateImpl::OnActionFromAssistiveTech() {
  // See OnUserInputEvent for how this is used to disable accessibility.
  user_input_event_count_ = 0;
  if (has_recently_checked_for_screen_reader_) {
    return;
  }
  has_recently_checked_for_screen_reader_ = true;

  // Some platforms might not perfectly signal when an assistive technology (AT)
  // is active, and may re-check for ATs after the AXMode
  // changes. If the AXMode is already configured with `kAXModeComplete`
  // (meaning all accessibility features are enabled), a new AT trying to access
  // APIs won't cause a mode change because those flags are already present.
  // This check allows for an AT to be detected and computed when a page loads
  // and the AT requests an action, specifically in the rare scenario where the
  // current mode is `ui::kAXModeComplete` but no AT has been identified yet.
  // This ensures the algorithm is complete.
  const bool has_ax_mode_complete =
      (GetAccessibilityMode() & ui::kAXModeComplete) == ui::kAXModeComplete;
  if (has_ax_mode_complete && !ax_platform_.IsScreenReaderActive()) {
    if (discover_at_callback_for_testing_) {
      discover_at_callback_for_testing_.Run();
      return;
    }
    RefreshAssistiveTechIfNecessary(GetAccessibilityMode());
  }
}

void BrowserAccessibilityStateImpl::OnPageNavigationComplete() {
  ++num_page_navs_before_first_use_;
  has_recently_checked_for_screen_reader_ = false;
}

void BrowserAccessibilityStateImpl::OnWebContentsInitialized(
    WebContentsImpl* web_contents) {
  const ui::AXMode effective_mode = FilterAccessibilityModeInvariants(
      GetAccessibilityMode() |
      ModeCollectionForTarget::GetAccessibilityMode(
          web_contents->GetBrowserContext()) |
      ui::AXMode());

  // Return early to avoid activating the field trial when accessibility is not
  // enabled.
  if (effective_mode.is_mode_off()) {
    return;
  }

  // Do not set any initial accessibility mode if ProgressiveAccessibility is
  // enabled and the WebContents is initially hidden. This behavior is the same
  // for both the only_enable and disable_on_hide variants of the feature.
  if (web_contents->GetVisibility() == Visibility::HIDDEN &&
      base::FeatureList::IsEnabled(features::kProgressiveAccessibility)) {
    return;
  }

  web_contents->SetAccessibilityMode(effective_mode);
}

void BrowserAccessibilityStateImpl::OnWebContentsRevealed(
    WebContentsImpl* web_contents) {
  // Unconditionally cancel the disabler; even if the "disable_on_hide" mode is
  // not selected. Do this without first checking the feature to avoid
  // activating the field trial when it's not already active. Performing this
  // removal when the feature is off is harmless. When the feature is active,
  // this removal will call OnDisablerDestroyedForWebContents to remove
  // `web_contents` from `last_hidden_` if the disabler has not yet been
  // scheduled.
  AccessibilityDisabler::Remove(web_contents);

  const ui::AXMode effective_mode = FilterAccessibilityModeInvariants(
      GetAccessibilityMode() |
      ModeCollectionForTarget::GetAccessibilityMode(
          web_contents->GetBrowserContext()) |
      ModeCollectionForTarget::GetAccessibilityMode(web_contents));

  // Return early to avoid activating the field trial when accessibility is not
  // enabled.
  if (effective_mode == web_contents->GetAccessibilityMode()) {
    return;
  }

  // No special behavior when ProgressiveAccessibility is not enabled.
  if (!base::FeatureList::IsEnabled(features::kProgressiveAccessibility)) {
    return;
  }

  // Send the current mode flags to the WebContents and its renderers.
  web_contents->SetAccessibilityMode(effective_mode);
}

void BrowserAccessibilityStateImpl::OnWebContentsHidden(
    WebContentsImpl* web_contents) {
  // Return early to avoid activating the field trial when accessibility is not
  // enabled.
  if (web_contents->GetAccessibilityMode().is_mode_off()) {
    return;
  }

  // No special behavior if ProgressiveAccessibility is not enabled, the
  // "disable_on_hide" mode is not selected, or if a screen reader has been
  // detected. This final limitation in in place because screen readers may lose
  // their "point of regard" if the accessibility tree is destroyed and rebuilt;
  // and because functional and fast accessibility is required to serve users of
  // screen readers.
  if (!base::FeatureList::IsEnabled(features::kProgressiveAccessibility) ||
      features::kProgressiveAccessibilityModeParam.Get() !=
          features::ProgressiveAccessibilityMode::kDisableOnHide ||
      ax_platform_.IsScreenReaderActive()) {
    return;
  }

  // Add `web_contents` to the list of the last five hidden WCs.
  CHECK(!base::Contains(last_hidden_, web_contents));
  last_hidden_.push_back(web_contents);

  // Create the disabler for this WebContents. The provided callback will be run
  // if `web_contents` is destroyed before the disabler's `Schedule()` method is
  // called. This is the period in which the WebContents is in this instance's
  // `last_hidden_` collection. `Unretained` is safe here because this instance
  // outlives all WebContents.
  AccessibilityDisabler::CreateForWebContents(
      web_contents,
      base::BindOnce(
          &BrowserAccessibilityStateImpl::OnDisablerDestroyedForWebContents,
          base::Unretained(this)));

  // If there was a sixth, schedule it for dropping 5m after it was hidden.
  if (last_hidden_.size() > kMaxPreservedWebContents) {
    AccessibilityDisabler::Schedule(last_hidden_.front().get());
    last_hidden_.pop_front();
  }
}

void BrowserAccessibilityStateImpl::OnDisablerDestroyedForWebContents(
    WebContentsImpl* web_contents) {
  // Remove `web_contents` from the list of last five hidden WCs.
  CHECK(std::erase(last_hidden_, web_contents));
}

void BrowserAccessibilityStateImpl::OnInputEvent(
    const RenderWidgetHost& widget,
    const blink::WebInputEvent& event) {
  // |this| observer cares about user input events (specifically keyboard,
  // mouse & touch events) to decide if the accessibility APIs can be disabled.
  if (event.GetType() == blink::WebInputEvent::Type::kMouseDown ||
      event.GetType() == blink::WebInputEvent::Type::kGestureTapDown ||
      event.GetType() == blink::WebInputEvent::Type::kTouchStart ||
      event.GetType() == blink::WebInputEvent::Type::kRawKeyDown ||
      event.GetType() == blink::WebInputEvent::Type::kKeyDown) {
    OnUserInputEvent();
  }
}

std::unique_ptr<ScopedAccessibilityMode>
BrowserAccessibilityStateImpl::CreateScopedModeForProcess(ui::AXMode mode) {
  auto scoped_mode_for_process = scoped_modes_for_process_.Add(mode);
  if (IsAccessibilityPerformanceMeasurementExperimentActive() &&
      IsAXModeConflictingWithExperiment(mode)) {
    // A new mode is being added while the performance experiment is
    // running, which indicates that user is turning on accessibility features.
    // The experiment is stopped by posting a task to avoid
    // synchronous destruction, which could be problematic if an accessibility
    // service is currently in a callstack that's using the accessibility tree
    // that this class might modify or destroy during cleanup.
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE,
        base::BindOnce(
            &BrowserAccessibilityStateImpl::ExitPerformanceExperiment,
            base::Unretained(this)));
  }
  return scoped_mode_for_process;
}

void BrowserAccessibilityStateImpl::ApplyAccessibilityModeToWebContents(
    WebContentsImpl* web_contents,
    ui::AXMode process_mode,
    ui::AXMode browser_context_mode,
    ui::AXMode web_contents_mode) {
  const ui::AXMode effective_mode = FilterAccessibilityModeInvariants(
      process_mode | browser_context_mode | web_contents_mode);

  // Nothing to do if no change in the WebContents's accessibility mode.
  if (effective_mode == web_contents->GetAccessibilityMode()) {
    return;
  }

  // Unconditionally update the WebContents when turning accessibility off.
  // TODO(accessibility): If there is evidence of jank induced by accessibility
  // being turned off for all WebContentses at once (e.g., if VoiceOver is
  // turned off), consider putting WCs in a queue (maybe only hidden ones) and
  // sending the empty effective mode one at a time with some delay between
  // each.
  if (effective_mode.is_mode_off()) {
    web_contents->SetAccessibilityMode(effective_mode);
    return;
  }

  // Unconditionally update the WebContents if ProgressiveAccessibility is not
  // enabled.
  if (!base::FeatureList::IsEnabled(features::kProgressiveAccessibility)) {
    web_contents->SetAccessibilityMode(effective_mode);
    return;
  }

  // Only update the WebContents if it is not hidden.
  if (web_contents->GetVisibility() != Visibility::HIDDEN) {
    web_contents->SetAccessibilityMode(effective_mode);
  }  // else the WebContents will be updated when it is revealed.
}

// This ScopedModeCollection::Delegate override is called by
// scoped_modes_for_process_ when the effective mode for the collection of
// scopers targeting the process changes.
void BrowserAccessibilityStateImpl::OnModeChanged(ui::AXMode old_mode,
                                                  ui::AXMode new_mode) {
  ui::RecordAccessibilityModeHistograms(ui::AXHistogramPrefix::kNone, new_mode,
                                        old_mode);

  // Track the time since start-up before the kWebContents mode was enabled,
  // ensuring we record this value only one time.
  if (!has_enabled_accessibility_in_session_ &&
      new_mode.has_mode(ui::AXMode::kWebContents)) {
    has_enabled_accessibility_in_session_ = true;
    UMA_HISTOGRAM_LONG_TIMES_100("Accessibility.EngineUse.TimeUntilStart",
                                 first_use_timer_.Elapsed());
    UMA_HISTOGRAM_COUNTS_10000("Accessibility.EngineUse.PageNavsUntilStart",
                               num_page_navs_before_first_use_);
  }

  RefreshAssistiveTechIfNecessary(new_mode);

  // Add a crash key with the ax_mode, to enable searching for top crashes that
  // occur when accessibility is turned on. This adds it for the browser
  // process, and elsewhere the same key is added to renderer processes.
  static auto* const ax_mode_crash_key = base::debug::AllocateCrashKeyString(
      "ax_mode", base::debug::CrashKeySize::Size64);
  if (ax_mode_crash_key) {
    base::debug::SetCrashKeyString(ax_mode_crash_key, new_mode.ToString());
  }

  // Combine the new mode for the process with the effective mode for each
  // WebContents and its associated BrowserContext.
  std::ranges::for_each(
      WebContentsImpl::GetAllWebContents(),
      [this, new_mode](WebContentsImpl* web_contents) {
        if (!web_contents->IsBeingDestroyed() &&
            !web_contents->IsNeverComposited()) {
          ApplyAccessibilityModeToWebContents(
              web_contents, new_mode,
              ModeCollectionForTarget::GetAccessibilityMode(
                  web_contents->GetBrowserContext()),
              ModeCollectionForTarget::GetAccessibilityMode(web_contents));
        }
      });

  // Handle additions to the process's mode flags.
  if (const auto additions = new_mode & ~old_mode; !additions.is_mode_off()) {
    // Keep track of the total time accessibility is enabled, and the time
    // it was previously disabled.
    if (old_mode.is_mode_off()) {
      base::TimeTicks now = ui::EventTimeForNow();
      accessibility_enabled_time_ = now;
      if (!accessibility_disabled_time_.is_null()) {
        base::UmaHistogramLongTimes("Accessibility.AutoDisabled.DisabledTime",
                                    now - accessibility_disabled_time_);
      }
    }

    // Broadcast the new mode flags, if any, to the AXModeObservers.
    ax_platform_.NotifyModeAdded(additions);
  }
}

// This ScopedModeCollection::Delegate override is called by
// scoped_modes_for_process_ when recomputing the effective mode for the
// collection of scopers targeting the process.
ui::AXMode BrowserAccessibilityStateImpl::FilterModeFlags(ui::AXMode mode) {
  if (activation_from_platform_enabled_) {
    // Allow mode changes with `kFromPlatform`, but filter out that one bit.
    // It need not be sent to renderers.
    return mode & ~ui::AXMode(ui::AXMode::kFromPlatform);
  }
  // Otherwise, ignore any mode change with `kFromPlatform`.
  return mode.has_mode(ui::AXMode::kFromPlatform) ? ui::AXMode() : mode;
}

std::unique_ptr<ScopedAccessibilityMode>
BrowserAccessibilityStateImpl::CreateScopedModeForBrowserContext(
    BrowserContext* browser_context,
    ui::AXMode mode) {
  // kFromPlatform is only permissible for process-wide scopers.
  CHECK(!mode.has_mode(ui::AXMode::kFromPlatform));
  auto scoped_mode = ModeCollectionForTarget::Add(
      browser_context,
      &BrowserAccessibilityStateImpl::OnModeChangedForBrowserContext, this,
      mode);
  if (IsAccessibilityPerformanceMeasurementExperimentActive() &&
      IsAXModeConflictingWithExperiment(mode)) {
    // A new mode is being added while the performance experiment is
    // running, which indicates that user is turning on accessibility features.
    // The experiment is stopped by posting a task to avoid
    // synchronous destruction, which could be problematic if an accessibility
    // service is currently in a callstack that's using the accessibility tree
    // that this class might modify or destroy during cleanup.
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE,
        base::BindOnce(
            &BrowserAccessibilityStateImpl::ExitPerformanceExperiment,
            base::Unretained(this)));
  }
  return scoped_mode;
}

void BrowserAccessibilityStateImpl::OnModeChangedForBrowserContext(
    BrowserContext* browser_context,
    ui::AXMode old_mode,
    ui::AXMode new_mode) {
  // Combine this with the effective mode for each WebContents associated with
  // `browser_context`.
  std::ranges::for_each(
      WebContentsImpl::GetAllWebContents(),
      [this, browser_context, process_mode = GetAccessibilityMode(),
       new_mode](WebContentsImpl* web_contents) {
        if (!web_contents->IsBeingDestroyed() &&
            !web_contents->IsNeverComposited() &&
            web_contents->GetBrowserContext() == browser_context) {
          ApplyAccessibilityModeToWebContents(
              web_contents, process_mode, new_mode,
              ModeCollectionForTarget::GetAccessibilityMode(web_contents));
        }
      });
}

std::unique_ptr<ScopedAccessibilityMode>
BrowserAccessibilityStateImpl::CreateScopedModeForWebContents(
    WebContents* web_contents,
    ui::AXMode mode) {
  // WebContents that are never shown must never have accessibility enabled.
  CHECK(!web_contents->IsNeverComposited());
  // kFromPlatform is only permissible for process-wide scopers.
  CHECK(!mode.has_mode(ui::AXMode::kFromPlatform));
  auto scoped_mode = ModeCollectionForTarget::Add(
      web_contents, &BrowserAccessibilityStateImpl::OnModeChangedForWebContents,
      this, mode);
  if (IsAccessibilityPerformanceMeasurementExperimentActive() &&
      IsAXModeConflictingWithExperiment(mode)) {
    // A new mode is being added while the performance experiment is
    // running, which indicates that user is turning on accessibility features.
    // The experiment is stopped by posting a task to avoid
    // synchronous destruction, which could be problematic if an accessibility
    // service is currently in a callstack that's using the accessibility tree
    // that this class might modify or destroy during cleanup.
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE,
        base::BindOnce(
            &BrowserAccessibilityStateImpl::ExitPerformanceExperiment,
            base::Unretained(this)));
  }
  return scoped_mode;
}

void BrowserAccessibilityStateImpl::OnModeChangedForWebContents(
    WebContents* web_contents,
    ui::AXMode old_mode,
    ui::AXMode new_mode) {
  if (web_contents->IsBeingDestroyed()) {
    return;
  }

  // Combine the effective modes for the process, `web_contents`'s
  // BrowserContext, and for `web_contents.
  ApplyAccessibilityModeToWebContents(
      static_cast<WebContentsImpl*>(web_contents), GetAccessibilityMode(),
      ModeCollectionForTarget::GetAccessibilityMode(
          web_contents->GetBrowserContext()),
      new_mode);
}

void BrowserAccessibilityStateImpl::OnFocusChangedInPage(
    const FocusedNodeDetails& details) {
  focus_changed_callbacks_.Notify(details);
}

void BrowserAccessibilityStateImpl::ExitPerformanceExperiment() {
  experiment_accessibility_mode_.reset();
  if (features::GetAccessibilityPerformanceMeasurementExperimentGroup() !=
      features::AccessibilityPerformanceMeasurementExperimentGroup::
          kRendererSerializationOnly) {
    return;
  }
  RenderAccessibilityHost::SetRendererSerializationExperimentEnabled(false);
  if (BrowserAccessibilityState::GetInstance()->GetAccessibilityMode().has_mode(
          ui::AXMode::kWebContents)) {
    // If this experiment variant was discarding incoming accessibility
    // events,
    // and the accessibility mode still includes `ui::AXMode::kWebContents`
    // after the experiment shutdown, force a reset on all WebContents.
    // This ensures they rebuild the full accessibility tree.
    std::ranges::for_each(WebContentsImpl::GetAllWebContents(),
                          [](WebContentsImpl* web_contents) {
                            if (!web_contents->IsBeingDestroyed() &&
                                !web_contents->IsNeverComposited()) {
                              web_contents->ResetAccessibility();
                            }
                          });
  }
}

}  // namespace content
