chromium/chrome/browser/ash/events/event_rewriter_delegate_impl.h

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

#ifndef CHROME_BROWSER_ASH_EVENTS_EVENT_REWRITER_DELEGATE_IMPL_H_
#define CHROME_BROWSER_ASH_EVENTS_EVENT_REWRITER_DELEGATE_IMPL_H_

#include <optional>
#include <utility>

#include "ash/public/cpp/input_device_settings_controller.h"
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "ui/events/ash/event_rewriter_ash.h"
#include "ui/events/ash/mojom/extended_fkeys_modifier.mojom-shared.h"
#include "ui/events/ash/mojom/simulate_right_click_modifier.mojom-shared.h"
#include "ui/events/ash/mojom/six_pack_shortcut_modifier.mojom-shared.h"
#include "ui/wm/public/activation_client.h"

class PrefService;

namespace ash {

class DeprecationNotificationController;
class InputDeviceSettingsNotificationController;

class EventRewriterDelegateImpl : public ui::EventRewriterAsh::Delegate {
 public:
  explicit EventRewriterDelegateImpl(wm::ActivationClient* activation_client);
  EventRewriterDelegateImpl(
      wm::ActivationClient* activation_client,
      std::unique_ptr<DeprecationNotificationController> deprecation_controller,
      std::unique_ptr<InputDeviceSettingsNotificationController>
          input_device_settings_notification_controller,
      InputDeviceSettingsController* input_device_settings_controller);

  EventRewriterDelegateImpl(const EventRewriterDelegateImpl&) = delete;
  EventRewriterDelegateImpl& operator=(const EventRewriterDelegateImpl&) =
      delete;

  ~EventRewriterDelegateImpl() override;

  void set_pref_service_for_testing(PrefService* pref_service) {
    pref_service_for_testing_ = pref_service;
  }

  // ui::EventRewriterAsh::Delegate:
  bool RewriteModifierKeys() override;
  bool RewriteMetaTopRowKeyComboEvents(int device_id) const override;
  std::optional<ui::mojom::ModifierKey> GetKeyboardRemappedModifierValue(
      int device_id,
      ui::mojom::ModifierKey modifier_key,
      const std::string& pref_name) const override;
  bool TopRowKeysAreFunctionKeys(int device_id) const override;
  bool IsExtensionCommandRegistered(ui::KeyboardCode key_code,
                                    int flags) const override;
  bool IsSearchKeyAcceleratorReserved() const override;
  bool NotifyDeprecatedRightClickRewrite() override;
  bool NotifyDeprecatedSixPackKeyRewrite(ui::KeyboardCode key_code) override;
  void SuppressModifierKeyRewrites(bool should_suppress) override;
  void SuppressMetaTopRowKeyComboRewrites(bool should_suppress) override;
  void RecordEventRemappedToRightClick(bool alt_based_right_click) override;
  void RecordSixPackEventRewrite(ui::KeyboardCode key_code,
                                 bool alt_based) override;
  std::optional<ui::mojom::SimulateRightClickModifier>
  GetRemapRightClickModifier(int device_id) override;
  std::optional<ui::mojom::SixPackShortcutModifier>
  GetShortcutModifierForSixPackKey(int device_id,
                                   ui::KeyboardCode key_code) override;
  void NotifyRightClickRewriteBlockedBySetting(
      ui::mojom::SimulateRightClickModifier blocked_modifier,
      ui::mojom::SimulateRightClickModifier active_modifier) override;

  void NotifySixPackRewriteBlockedBySetting(
      ui::KeyboardCode key_code,
      ui::mojom::SixPackShortcutModifier blocked_modifier,
      ui::mojom::SixPackShortcutModifier active_modifier,
      int device_id) override;

  std::optional<ui::mojom::ExtendedFkeysModifier> GetExtendedFkeySetting(
      int device_id,
      ui::KeyboardCode key_code) override;

  // Push a notification when the device has an Fn key and six pack shortcut
  // with search key is pressed.
  void NotifySixPackRewriteBlockedByFnKey(
      ui::KeyboardCode key_code,
      ui::mojom::SixPackShortcutModifier modifier) override;

  // Push a notification when the device has an Fn key and search plus top
  // row key is pressed.
  void NotifyTopRowRewriteBlockedByFnKey() override;

  // Workaround for test behavior injection.
  // Currently, there's no easier way to inject
  // ExtensionCommandsGlobalRegistry's behavior, so difficult to test
  // EventRewriterAsh with changing IsExtensionCommandRegistered's behavior.
  // Introducing a fake class of Delegate implementation can solve the issue,
  // but without further larger refactoring some testing coverage will be lost.
  // This API is for the mitigation for short term.
  // TODO(crbug.com/40265877): Consider clear separation of EventRewriterAsh's
  // test and Delegate's test, then to remove this API.
  void SetExtensionCommandsOverrideForTesting(
      std::optional<base::flat_set<std::pair<ui::KeyboardCode, int>>>
          commands) {
    extension_commands_override_for_testing_ = std::move(commands);
  }

 private:
  PrefService* GetPrefService() const;

  raw_ptr<PrefService> pref_service_for_testing_;

  std::optional<base::flat_set<std::pair<ui::KeyboardCode, int>>>
      extension_commands_override_for_testing_;

  raw_ptr<wm::ActivationClient, DanglingUntriaged> activation_client_;

  // Handles showing notifications when deprecated event rewrites occur.
  std::unique_ptr<DeprecationNotificationController> deprecation_controller_;
  std::unique_ptr<InputDeviceSettingsNotificationController>
      input_device_settings_notification_controller_;

  // Tracks whether modifier rewrites should be suppressed or not.
  bool suppress_modifier_key_rewrites_ = false;

  // Tracks whether meta + top row key rewrites should be suppressed or not.
  bool suppress_meta_top_row_key_rewrites_ = false;

  raw_ptr<InputDeviceSettingsController, DanglingUntriaged>
      input_device_settings_controller_;
};

}  // namespace ash

#endif  // CHROME_BROWSER_ASH_EVENTS_EVENT_REWRITER_DELEGATE_IMPL_H_