910e62b5创建于 1月15日历史提交
// Copyright 2015 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/scoped_target_handler.h"

#include <memory>
#include <utility>

#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event_handler.h"
#include "ui/events/event_target.h"
#include "ui/events/event_target_iterator.h"
#include "ui/events/event_utils.h"

namespace ui {

namespace {

class TestEventTargetIterator : public EventTargetIterator {
 public:
  TestEventTargetIterator() {}

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

  // EventTargetIterator:
  EventTarget* GetNextTarget() override { return nullptr; }
};

// An EventTarget that holds ownership of its target and delegate EventHandlers.
class TestEventTarget : public EventTarget {
 public:
  TestEventTarget() {}

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

  ~TestEventTarget() override {}

  void SetHandler(std::unique_ptr<EventHandler> target_handler,
                  std::unique_ptr<EventHandler> delegate) {
    target_handler_ = std::move(target_handler);
    delegate_ = std::move(delegate);
  }

  // EventTarget:
  void DispatchEvent(Event* event) { target_handler()->OnEvent(event); }
  bool CanAcceptEvent(const Event& event) override { return true; }
  EventTarget* GetParentTarget() override { return nullptr; }
  std::unique_ptr<EventTargetIterator> GetChildIterator() const override {
    return base::WrapUnique(new TestEventTargetIterator);
  }
  EventTargeter* GetEventTargeter() override { return nullptr; }

 private:
  std::unique_ptr<EventHandler> target_handler_;
  std::unique_ptr<EventHandler> delegate_;
};

// An EventHandler that sets itself as a target handler for an EventTarget and
// can recursively dispatch an Event.
class NestedEventHandler : public EventHandler {
 public:
  NestedEventHandler(TestEventTarget* target, int nesting)
      : target_(target), nesting_(nesting) {
    original_handler_ = target_->SetTargetHandler(this);
  }

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

  ~NestedEventHandler() override {
    EventHandler* handler = target_->SetTargetHandler(original_handler_);
    DCHECK_EQ(this, handler);
  }

 protected:
  void OnEvent(Event* event) override {
    if (--nesting_ == 0)
      return;
    target_->DispatchEvent(event);
  }

 private:
  raw_ptr<TestEventTarget> target_;
  int nesting_;
  raw_ptr<EventHandler> original_handler_;
};

// An EventHandler that sets itself as a target handler for an EventTarget and
// destroys that EventTarget when handling an Event, possibly after recursively
// handling the Event.
class TargetDestroyingEventHandler : public EventHandler {
 public:
  TargetDestroyingEventHandler(TestEventTarget* target, int nesting)
      : target_(target), nesting_(nesting) {
    original_handler_ = target_->SetTargetHandler(this);
  }

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

  ~TargetDestroyingEventHandler() override {
    EventHandler* handler = target_->SetTargetHandler(original_handler_);
    DCHECK_EQ(this, handler);
  }

 protected:
  void OnEvent(Event* event) override {
    if (--nesting_ == 0) {
      delete target_;
      return;
    }
    target_->DispatchEvent(event);
  }

 private:
  raw_ptr<TestEventTarget> target_;
  int nesting_;
  raw_ptr<EventHandler> original_handler_;
};

// An EventHandler that can be set to receive events in addition to the target
// handler and counts the Events that it receives.
class EventCountingEventHandler : public EventHandler {
 public:
  EventCountingEventHandler(EventTarget* target, int* count)
      : scoped_target_handler_(new ScopedTargetHandler(target, this)),
        count_(count) {}

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

  ~EventCountingEventHandler() override {}

 protected:
  void OnEvent(Event* event) override { (*count_)++; }

 private:
  std::unique_ptr<ScopedTargetHandler> scoped_target_handler_;
  raw_ptr<int> count_;
};

// An EventCountingEventHandler that will also mark the event to stop further
// propataion.
class EventStopPropagationHandler : public EventCountingEventHandler {
 public:
  EventStopPropagationHandler(EventTarget* target, int* count)
      : EventCountingEventHandler(target, count) {}

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

  ~EventStopPropagationHandler() override {}

 protected:
  void OnEvent(Event* event) override {
    EventCountingEventHandler::OnEvent(event);
    event->StopPropagation();
  }
};

}  // namespace

// Tests that a ScopedTargetHandler invokes both the target and a delegate.
TEST(ScopedTargetHandlerTest, HandlerInvoked) {
  int count = 0;
  std::unique_ptr<TestEventTarget> target = std::make_unique<TestEventTarget>();
  std::unique_ptr<NestedEventHandler> target_handler(
      new NestedEventHandler(target.get(), 1));
  std::unique_ptr<EventCountingEventHandler> delegate(
      new EventCountingEventHandler(target.get(), &count));
  target->SetHandler(std::move(target_handler), std::move(delegate));
  MouseEvent event(EventType::kMousePressed, gfx::Point(), gfx::Point(),
                   EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
                   EF_LEFT_MOUSE_BUTTON);
  target->DispatchEvent(&event);
  EXPECT_EQ(1, count);
}

// Tests that a ScopedTargetHandler invokes both the target and a delegate but
// does not further propagate the event after a handler stops event propagation.
TEST(ScopedTargetHandlerTest, HandlerInvokedOnceThenEventStopsPropagating) {
  int count = 0;
  std::unique_ptr<TestEventTarget> target = std::make_unique<TestEventTarget>();
  std::unique_ptr<NestedEventHandler> target_handler(
      new NestedEventHandler(target.get(), 3));
  std::unique_ptr<EventStopPropagationHandler> delegate(
      new EventStopPropagationHandler(target.get(), &count));
  target->SetHandler(std::move(target_handler), std::move(delegate));
  MouseEvent event(EventType::kMousePressed, gfx::Point(), gfx::Point(),
                   EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
                   EF_LEFT_MOUSE_BUTTON);
  target->DispatchEvent(&event);
  EXPECT_EQ(1, count);
}

// Tests that a ScopedTargetHandler invokes both the target and a delegate when
// an Event is dispatched recursively such as with synthetic events.
TEST(ScopedTargetHandlerTest, HandlerInvokedNested) {
  int count = 0;
  std::unique_ptr<TestEventTarget> target = std::make_unique<TestEventTarget>();
  std::unique_ptr<NestedEventHandler> target_handler(
      new NestedEventHandler(target.get(), 2));
  std::unique_ptr<EventCountingEventHandler> delegate(
      new EventCountingEventHandler(target.get(), &count));
  target->SetHandler(std::move(target_handler), std::move(delegate));
  MouseEvent event(EventType::kMousePressed, gfx::Point(), gfx::Point(),
                   EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
                   EF_LEFT_MOUSE_BUTTON);
  target->DispatchEvent(&event);
  EXPECT_EQ(2, count);
}

// Tests that a it is safe to delete a ScopedTargetHandler while handling an
// event.
TEST(ScopedTargetHandlerTest, SafeToDestroy) {
  int count = 0;
  TestEventTarget* target = new TestEventTarget;
  std::unique_ptr<TargetDestroyingEventHandler> target_handler(
      new TargetDestroyingEventHandler(target, 1));
  std::unique_ptr<EventCountingEventHandler> delegate(
      new EventCountingEventHandler(target, &count));
  target->SetHandler(std::move(target_handler), std::move(delegate));
  MouseEvent event(EventType::kMousePressed, gfx::Point(), gfx::Point(),
                   EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
                   EF_LEFT_MOUSE_BUTTON);
  target->DispatchEvent(&event);
  EXPECT_EQ(0, count);
}

// Tests that a it is safe to delete a ScopedTargetHandler while handling an
// event recursively.
TEST(ScopedTargetHandlerTest, SafeToDestroyNested) {
  int count = 0;
  TestEventTarget* target = new TestEventTarget;
  std::unique_ptr<TargetDestroyingEventHandler> target_handler(
      new TargetDestroyingEventHandler(target, 2));
  std::unique_ptr<EventCountingEventHandler> delegate(
      new EventCountingEventHandler(target, &count));
  target->SetHandler(std::move(target_handler), std::move(delegate));
  MouseEvent event(EventType::kMousePressed, gfx::Point(), gfx::Point(),
                   EventTimeForNow(), EF_LEFT_MOUSE_BUTTON,
                   EF_LEFT_MOUSE_BUTTON);
  target->DispatchEvent(&event);
  EXPECT_EQ(0, count);
}

}  // namespace ui