chromium/ui/events/ash/keyboard_device_id_event_rewriter_unittest.cc

// 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.

#include "ui/events/ash/keyboard_device_id_event_rewriter.h"

#include <memory>
#include <utility>
#include <vector>

#include "base/memory/weak_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/ash/event_property.h"
#include "ui/events/ash/keyboard_capability.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/device_data_manager_test_api.h"
#include "ui/events/devices/input_device.h"
#include "ui/events/event.h"
#include "ui/events/event_dispatcher.h"
#include "ui/events/event_rewriter_continuation.h"
#include "ui/gfx/geometry/point_f.h"

namespace ui {

namespace {

// Captures SendEvent calls.
class TestContinuation : public EventRewriterContinuation {
 public:
  TestContinuation() = default;
  TestContinuation(const TestContinuation&) = delete;
  TestContinuation& operator=(const TestContinuation&) = delete;
  ~TestContinuation() override = default;

  const std::vector<std::unique_ptr<Event>>& send_event_events() const {
    return send_event_events_;
  }

  base::WeakPtr<EventRewriterContinuation> GetWeakPtr() {
    return weak_ptr_factory_.GetWeakPtr();
  }

  // EventRewriterContinuation:
  ui::EventDispatchDetails SendEvent(const ui::Event* event) override {
    send_event_events_.push_back(event->Clone());
    return ui::EventDispatchDetails();
  }

  ui::EventDispatchDetails SendEventFinally(const ui::Event* event) override {
    ADD_FAILURE();
    return ui::EventDispatchDetails();
  }

  ui::EventDispatchDetails DiscardEvent() override {
    ADD_FAILURE();
    return ui::EventDispatchDetails();
  }

 private:
  std::vector<std::unique_ptr<Event>> send_event_events_;
  base::WeakPtrFactory<TestContinuation> weak_ptr_factory_{this};
};

}  // namespace

class KeyboardDeviceIdEventRewriterTest : public testing::Test {
 public:
  KeyboardDeviceIdEventRewriterTest() = default;
  ~KeyboardDeviceIdEventRewriterTest() override = default;

  KeyboardDeviceIdEventRewriter& rewriter() { return *rewriter_; }
  KeyboardCapability& capability() { return *capability_; }

  void SetUp() override {
    DeviceDataManager::CreateInstance();
    capability_ = std::make_unique<KeyboardCapability>();
    rewriter_ =
        std::make_unique<KeyboardDeviceIdEventRewriter>(capability_.get());
  }

  void TearDown() override {
    rewriter_.reset();
    capability_.reset();
    DeviceDataManager::DeleteInstance();
  }

 private:
  std::unique_ptr<KeyboardCapability> capability_;
  std::unique_ptr<KeyboardDeviceIdEventRewriter> rewriter_;
};

TEST_F(KeyboardDeviceIdEventRewriterTest, KeyEventRewriting) {
  constexpr int kKeyboardDeviceId = 10;
  constexpr int kVirtualCoreKeyboardDeviceId = 20;

  KeyboardDevice device(kVirtualCoreKeyboardDeviceId,
                        /*type=*/InputDeviceType::INPUT_DEVICE_INTERNAL,
                        /*name=*/"virtual core keyboard");
  DeviceDataManagerTestApi().SetKeyboardDevices({device});
  KeyboardCapability::KeyboardInfo keyboard_info;
  keyboard_info.device_type =
      KeyboardCapability::DeviceType::kDeviceVirtualCoreKeyboard;
  capability().SetKeyboardInfoForTesting(device, std::move(keyboard_info));

  // Rewriting for non-virtual-core-keyboard has no effect.
  {
    auto key_event = std::make_unique<KeyEvent>(EventType::kKeyPressed, VKEY_A,
                                                /*flags=*/0);
    key_event->set_source_device_id(kKeyboardDeviceId);

    TestContinuation continuation;
    rewriter().RewriteEvent(*key_event, continuation.GetWeakPtr());
    ASSERT_EQ(1u, continuation.send_event_events().size());
    const Event& rewritten_event = *continuation.send_event_events()[0];
    EXPECT_EQ(kKeyboardDeviceId, GetKeyboardDeviceIdProperty(rewritten_event));
  }

  // Rewriting for virtual-core-keyboard annotates the device id
  // of the previous event.
  {
    auto key_event = std::make_unique<KeyEvent>(EventType::kKeyPressed, VKEY_A,
                                                /*flags=*/0);
    key_event->set_source_device_id(kVirtualCoreKeyboardDeviceId);

    TestContinuation continuation;
    rewriter().RewriteEvent(*key_event, continuation.GetWeakPtr());
    ASSERT_EQ(1u, continuation.send_event_events().size());
    const Event& rewritten_event = *continuation.send_event_events()[0];
    EXPECT_EQ(kKeyboardDeviceId, GetKeyboardDeviceIdProperty(rewritten_event));
  }
}

TEST_F(KeyboardDeviceIdEventRewriterTest, MotionEventRewriting) {
  constexpr int kKeyDeviceId = 10;
  constexpr int kMotionDeviceId = 20;

  // Rewriting for non-virtual-core-keyboard has no effect, but remembers it.
  {
    auto key_event = std::make_unique<KeyEvent>(EventType::kKeyPressed, VKEY_A,
                                                /*flags=*/0);
    key_event->set_source_device_id(kKeyDeviceId);

    TestContinuation continuation;
    rewriter().RewriteEvent(*key_event, continuation.GetWeakPtr());
    ASSERT_EQ(1u, continuation.send_event_events().size());
    const Event& rewritten_event = *continuation.send_event_events()[0];
    EXPECT_EQ(kKeyDeviceId, GetKeyboardDeviceIdProperty(rewritten_event));
  }

  // motion event is rewritten.
  {
    auto touch_event = std::make_unique<TouchEvent>(
        EventType::kTouchPressed, gfx::PointF(0.f, 0.f), gfx::PointF(0.f, 0.f),
        base::TimeTicks(), PointerDetails());
    touch_event->set_source_device_id(kMotionDeviceId);

    TestContinuation continuation;
    rewriter().RewriteEvent(*touch_event, continuation.GetWeakPtr());
    ASSERT_EQ(1u, continuation.send_event_events().size());
    const Event& rewritten_event = *continuation.send_event_events()[0];
    EXPECT_EQ(kKeyDeviceId, GetKeyboardDeviceIdProperty(rewritten_event));
  }
}

}  // namespace ui