1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130

ash / system / input_device_settings / input_device_notifier.h [blame]

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

#ifndef ASH_SYSTEM_INPUT_DEVICE_SETTINGS_INPUT_DEVICE_NOTIFIER_H_
#define ASH_SYSTEM_INPUT_DEVICE_SETTINGS_INPUT_DEVICE_NOTIFIER_H_

#include <vector>

#include "ash/ash_export.h"
#include "ash/bluetooth_devices_observer.h"
#include "ash/public/cpp/input_device_settings_controller.h"
#include "ash/public/cpp/session/session_controller.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/public/mojom/input_device_settings.mojom-forward.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/export_template.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "ui/events/devices/input_device.h"
#include "ui/events/devices/input_device_event_observer.h"
#include "ui/events/devices/keyboard_device.h"
#include "ui/events/devices/touchpad_device.h"

namespace ash {

class BluetoothDevicesObserver;

// Calls the given callback every time a device is connected or removed with
// lists of which were added or removed.
template <typename MojomDevicePtr, typename InputDeviceType>
class ASH_EXPORT InputDeviceNotifier : public ui::InputDeviceEventObserver,
                                       public SessionObserver {
 public:
  using DeviceId = InputDeviceSettingsController::DeviceId;
  using InputDeviceListsUpdatedCallback =
      base::RepeatingCallback<void(std::vector<InputDeviceType>,
                                   std::vector<DeviceId>)>;

  // Passed in `connected_devices` must outlive constructed
  // `InputDeviceNotifier`.
  InputDeviceNotifier(
      base::flat_map<DeviceId, MojomDevicePtr>* connected_devices,
      InputDeviceListsUpdatedCallback callback);
  InputDeviceNotifier(const InputDeviceNotifier&) = delete;
  InputDeviceNotifier& operator=(const InputDeviceNotifier&) = delete;
  ~InputDeviceNotifier() override;

  // ui::InputDeviceEventObserver
  void OnInputDeviceConfigurationChanged(uint8_t input_device_type) override;
  void OnDeviceListsComplete() override;

  // SessionObserver
  void OnLoginStatusChanged(LoginStatus login_status) override;

  // Used as callback for `bluetooth_devices_observer_` whenever a bluetooth
  // device state changes.
  void OnBluetoothAdapterOrDeviceChanged(device::BluetoothDevice* device);

 private:
  void RefreshDevices();

  std::vector<InputDeviceType> GetUpdatedDeviceList();
  void HandleImposterPref(
      const std::vector<InputDeviceType>& updated_device_list);

  // `connected_devices_` is owned by `InputDeviceSettingsControllerImpl` which
  // instantiates the `InputDeviceNotifier` as a member. `connected_devices_`
  // will always outlive `InputDeviceNotifier`.
  raw_ptr<base::flat_map<DeviceId, MojomDevicePtr>> connected_devices_;
  InputDeviceListsUpdatedCallback device_lists_updated_callback_;

  std::unique_ptr<BluetoothDevicesObserver> bluetooth_devices_observer_;

  // The set of devices that were keyboard imposters last time devices were
  // refreshed.
  base::flat_set<DeviceId> keyboard_imposter_devices_;
  // The set of devices that were mouse imposters last time devices were
  // refreshed.
  base::flat_set<DeviceId> mouse_imposter_devices_;
  // The set of device keys to add to the prefs.
  base::flat_set<std::string> keyboard_imposter_false_positives_to_add_;
  base::flat_set<std::string> mouse_imposter_false_positives_to_add_;
};

// Below explicit template instantiations needed for all supported types.
template <>
ASH_EXPORT void
InputDeviceNotifier<mojom::KeyboardPtr, ui::KeyboardDevice>::HandleImposterPref(
    const std::vector<ui::KeyboardDevice>& updated_device_list);
template <>
ASH_EXPORT void
InputDeviceNotifier<mojom::MousePtr, ui::InputDevice>::HandleImposterPref(
    const std::vector<ui::InputDevice>& updated_device_list);

template <>
ASH_EXPORT std::vector<ui::KeyboardDevice>
InputDeviceNotifier<mojom::KeyboardPtr,
                    ui::KeyboardDevice>::GetUpdatedDeviceList();
template <>
ASH_EXPORT std::vector<ui::TouchpadDevice>
InputDeviceNotifier<mojom::TouchpadPtr,
                    ui::TouchpadDevice>::GetUpdatedDeviceList();
template <>
ASH_EXPORT std::vector<ui::InputDevice>
InputDeviceNotifier<mojom::MousePtr, ui::InputDevice>::GetUpdatedDeviceList();
template <>
ASH_EXPORT std::vector<ui::InputDevice>
InputDeviceNotifier<mojom::PointingStickPtr,
                    ui::InputDevice>::GetUpdatedDeviceList();
template <>
ASH_EXPORT std::vector<ui::InputDevice>
InputDeviceNotifier<mojom::GraphicsTabletPtr,
                    ui::InputDevice>::GetUpdatedDeviceList();

extern template class EXPORT_TEMPLATE_DECLARE(ASH_EXPORT)
    InputDeviceNotifier<mojom::KeyboardPtr, ui::KeyboardDevice>;
extern template class EXPORT_TEMPLATE_DECLARE(ASH_EXPORT)
    InputDeviceNotifier<mojom::TouchpadPtr, ui::TouchpadDevice>;
extern template class EXPORT_TEMPLATE_DECLARE(ASH_EXPORT)
    InputDeviceNotifier<mojom::MousePtr, ui::InputDevice>;
extern template class EXPORT_TEMPLATE_DECLARE(ASH_EXPORT)
    InputDeviceNotifier<mojom::PointingStickPtr, ui::InputDevice>;
extern template class EXPORT_TEMPLATE_DECLARE(ASH_EXPORT)
    InputDeviceNotifier<mojom::GraphicsTabletPtr, ui::InputDevice>;

}  // namespace ash

#endif  // ASH_SYSTEM_INPUT_DEVICE_SETTINGS_INPUT_DEVICE_NOTIFIER_H_