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

#include "services/ws/injected_event_handler.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "services/ws/public/cpp/host/gpu_interface_provider.h"
#include "services/ws/public/mojom/constants.mojom.h"
#include "services/ws/public/mojom/window_tree.mojom.h"
#include "services/ws/window_service.h"
#include "services/ws/window_service_test_setup.h"
#include "services/ws/window_tree.h"
#include "services/ws/window_tree_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/test/window_event_dispatcher_test_api.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_rewriter.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/platform_window/platform_window_init_properties.h"

namespace ws {

TEST(InjectedEventHandlerTest, SyncDispatch) {
  WindowServiceTestSetup test_setup;

  bool was_callback_run = false;
  InjectedEventHandler injected_event_handler(test_setup.service(),
                                              test_setup.root()->GetHost());

  // Inject the event, the callback should be run immediately as the location is
  // not over a client's window.
  std::unique_ptr<ui::Event> event = std::make_unique<ui::MouseEvent>(
      ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), base::TimeTicks::Now(),
      /* flags */ 0, /*changed_button_flags*/ 0);
  injected_event_handler.Inject(
      std::move(event),
      base::BindOnce([](bool* foo) { *foo = true; }, &was_callback_run));
  EXPECT_TRUE(was_callback_run);
}

TEST(InjectedEventHandlerTest, OverRemoteWindow) {
  WindowServiceTestSetup test_setup;
  aura::Window* top_level =
      test_setup.window_tree_test_helper()->NewTopLevelWindow();
  ASSERT_TRUE(top_level);
  top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
  top_level->Show();

  bool was_callback_run = false;
  InjectedEventHandler injected_event_handler(test_setup.service(),
                                              test_setup.root()->GetHost());

  // Inject the event, the callback should not be run immediately as the
  // location is over a client's window.
  std::unique_ptr<ui::Event> event = std::make_unique<ui::MouseEvent>(
      ui::ET_MOUSE_PRESSED, gfx::Point(10, 10), gfx::Point(10, 10),
      base::TimeTicks::Now(),
      /* flags */ 0, /*changed_button_flags*/ 0);
  injected_event_handler.Inject(
      std::move(event), base::BindOnce([](bool* was_run) { *was_run = true; },
                                       &was_callback_run));
  EXPECT_FALSE(was_callback_run);

  // Ack the event, which should trigger running the callback.
  test_setup.window_tree_client()->AckFirstEvent(test_setup.window_tree(),
                                                 mojom::EventResult::HANDLED);
  EXPECT_TRUE(was_callback_run);
}

TEST(InjectedEventHandlerTest, WindowTreeHostDeletedWhileWaiting) {
  WindowServiceTestSetup test_setup;

  // Create a new WindowTreeHost.
  std::unique_ptr<aura::WindowTreeHost> second_host =
      aura::WindowTreeHost::Create(
          ui::PlatformWindowInitProperties{gfx::Rect(20, 30, 100, 50)});
  second_host->InitHost();
  second_host->window()->Show();

  // Create a top-level in |second_host|.
  test_setup.delegate()->set_top_level_parent(second_host->window());
  aura::Window* top_level =
      test_setup.window_tree_test_helper()->NewTopLevelWindow();
  ASSERT_TRUE(top_level);
  top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
  top_level->Show();

  // Send an event to the top-level.
  bool was_callback_run = false;
  InjectedEventHandler injected_event_handler(test_setup.service(),
                                              second_host.get());

  // Inject the event, the callback should not be run immediately as the
  // location is over a client's window.
  std::unique_ptr<ui::Event> event = std::make_unique<ui::MouseEvent>(
      ui::ET_MOUSE_PRESSED, gfx::Point(10, 10), gfx::Point(10, 10),
      base::TimeTicks::Now(),
      /* flags */ 0, /*changed_button_flags*/ 0);
  injected_event_handler.Inject(
      std::move(event), base::BindOnce([](bool* was_run) { *was_run = true; },
                                       &was_callback_run));
  EXPECT_FALSE(was_callback_run);

  // Deleting the host should trigger notifying running the callback.
  second_host.reset();
  EXPECT_TRUE(was_callback_run);
}

TEST(InjectedEventHandlerTest, HeldEvent) {
  WindowServiceTestSetup test_setup;
  aura::Window* top_level =
      test_setup.window_tree_test_helper()->NewTopLevelWindow();
  ASSERT_TRUE(top_level);
  top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
  top_level->Show();

  bool was_callback_run = false;
  InjectedEventHandler injected_event_handler(test_setup.service(),
                                              test_setup.root()->GetHost());

  test_setup.root()->GetHost()->dispatcher()->HoldPointerMoves();

  // Inject the event, the callback should not be run immediately as moves are
  // being held (ET_MOUSE_DRAGGED triggers the event holding logic in
  // WindowEventDispatcher).
  std::unique_ptr<ui::Event> event = std::make_unique<ui::MouseEvent>(
      ui::ET_MOUSE_DRAGGED, gfx::Point(10, 10), gfx::Point(10, 10),
      base::TimeTicks::Now(),
      /* flags */ 0, /*changed_button_flags*/ 0);
  injected_event_handler.Inject(
      std::move(event), base::BindOnce([](bool* was_run) { *was_run = true; },
                                       &was_callback_run));
  EXPECT_FALSE(was_callback_run);

  // Releasing the move should run the callback.
  test_setup.root()->GetHost()->dispatcher()->ReleasePointerMoves();
  aura::test::WindowEventDispatcherTestApi(
      test_setup.root()->GetHost()->dispatcher())
      .WaitUntilPointerMovesDispatched();
  EXPECT_TRUE(was_callback_run);
}

class DiscardingEventRewriter : public ui::EventRewriter {
 public:
  DiscardingEventRewriter() = default;
  ~DiscardingEventRewriter() override = default;

  bool got_rewrite_event() const { return got_rewrite_event_; }

  // ui::EventRewriter:
  ui::EventDispatchDetails RewriteEvent(
      const ui::Event& event,
      const Continuation continuation) override {
    got_rewrite_event_ = true;
    return DiscardEvent(continuation);
  }

 private:
  bool got_rewrite_event_ = false;

  DISALLOW_COPY_AND_ASSIGN(DiscardingEventRewriter);
};

TEST(InjectedEventHandlerTest, RewriterDiscards) {
  // Create a single window and give it focus.
  DiscardingEventRewriter rewriter;
  WindowServiceTestSetup test_setup;
  test_setup.aura_test_helper()->root_window()->GetHost()->AddEventRewriter(
      &rewriter);
  aura::Window* top_level =
      test_setup.window_tree_test_helper()->NewTopLevelWindow();
  ASSERT_TRUE(top_level);
  top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
  top_level->Show();
  top_level->Focus();
  EXPECT_TRUE(top_level->HasFocus());

  // Dispatch an event. Because the rewriter discards the event, the callback
  // should be run immediately.
  bool was_callback_run = false;
  InjectedEventHandler injected_event_handler(test_setup.service(),
                                              test_setup.root()->GetHost());

  ui::KeyEvent char_event('A', ui::VKEY_A, ui::DomCode::NONE, 0);
  injected_event_handler.Inject(
      ui::Event::Clone(char_event),
      base::BindOnce([](bool* was_run) { *was_run = true; },
                     &was_callback_run));
  EXPECT_TRUE(was_callback_run);
  EXPECT_TRUE(rewriter.got_rewrite_event());
}

}  // namespace ws
