// 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 "content/browser/renderer_host/direct_manipulation_helper_win.h"

#include <windows.h>

#include "base/macros.h"
#include "base/test/scoped_feature_list.h"
#include "base/win/windows_version.h"
#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/win/window_event_target.h"
#include "ui/events/event_rewriter.h"
#include "ui/events/event_source.h"
#include "url/gurl.h"

namespace content {

class DirectManipulationBrowserTest : public ContentBrowserTest,
                                      public testing::WithParamInterface<bool> {
 public:
  DirectManipulationBrowserTest() {
    if (GetParam()) {
      scoped_feature_list_.InitWithFeatures(
          {features::kPrecisionTouchpad,
           features::kPrecisionTouchpadScrollPhase},
          {});
    } else {
      scoped_feature_list_.InitWithFeatures(
          {features::kPrecisionTouchpad},
          {features::kPrecisionTouchpadScrollPhase});
    }
  }

  ~DirectManipulationBrowserTest() override {}

  LegacyRenderWidgetHostHWND* GetLegacyRenderWidgetHostHWND() {
    RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
        shell()->web_contents()->GetRenderWidgetHostView());
    return rwhva->legacy_render_widget_host_HWND_;
  }

  HWND GetSubWindowHWND() {
    LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();

    return lrwhh->hwnd();
  }

  ui::WindowEventTarget* GetWindowEventTarget() {
    LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();

    return lrwhh->GetWindowEventTarget(lrwhh->GetParent());
  }

  void SimulatePointerHitTest() {
    LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();

    lrwhh->direct_manipulation_helper_->need_poll_events_ = true;
    lrwhh->CreateAnimationObserver();
  }

  void UpdateParent(HWND hwnd) {
    LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();

    lrwhh->UpdateParent(hwnd);
  }

  bool HasCompositorAnimationObserver(LegacyRenderWidgetHostHWND* lrwhh) {
    return lrwhh->compositor_animation_observer_ != nullptr;
  }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;

  DISALLOW_COPY_AND_ASSIGN(DirectManipulationBrowserTest);
};

INSTANTIATE_TEST_SUITE_P(WithScrollEventPhase,
                         DirectManipulationBrowserTest,
                         testing::Bool());

// Ensure the AnimationObserver destroy when hwnd reparent to other hwnd.
IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, HWNDReparent) {
  if (base::win::GetVersion() < base::win::Version::WIN10)
    return;

  NavigateToURL(shell(), GURL(url::kAboutBlankURL));

  LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();
  ASSERT_TRUE(lrwhh);

  // The observer should not create before it needed.
  ASSERT_TRUE(!HasCompositorAnimationObserver(lrwhh));

  // Add AnimationObserver to tab to simulate direct manipulation start.
  SimulatePointerHitTest();
  ASSERT_TRUE(HasCompositorAnimationObserver(lrwhh));

  // Create another browser.
  Shell* shell2 = CreateBrowser();
  NavigateToURL(shell2, GURL(url::kAboutBlankURL));

  // Move to the tab to browser2.
  UpdateParent(
      shell2->window()->GetRootWindow()->GetHost()->GetAcceleratedWidget());

  // The animation observer should be removed.
  EXPECT_FALSE(HasCompositorAnimationObserver(lrwhh));

  shell2->Close();
}

// EventLogger is to observe the events sent from WindowEventTarget (the root
// window).
class EventLogger : public ui::EventRewriter {
 public:
  EventLogger() {}
  ~EventLogger() override {}

  std::unique_ptr<ui::Event> ReleaseLastEvent() {
    return std::move(last_event_);
  }

 private:
  // ui::EventRewriter
  ui::EventDispatchDetails RewriteEvent(
      const ui::Event& event,
      const Continuation continuation) override {
    DCHECK(!last_event_);
    last_event_ = ui::Event::Clone(event);
    return SendEvent(continuation, &event);
  }

  std::unique_ptr<ui::Event> last_event_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(EventLogger);
};

// Check DirectManipulation events convert to ui::event correctly.
IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, EventConvert) {
  if (base::win::GetVersion() < base::win::Version::WIN10)
    return;

  NavigateToURL(shell(), GURL(url::kAboutBlankURL));

  LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();
  ASSERT_TRUE(lrwhh);

  HWND hwnd =
      shell()->window()->GetRootWindow()->GetHost()->GetAcceleratedWidget();

  ui::EventSource* dwthw = static_cast<ui::EventSource*>(
      aura::WindowTreeHost::GetForAcceleratedWidget(hwnd));
  EventLogger event_logger;
  dwthw->AddEventRewriter(&event_logger);

  ui::WindowEventTarget* target = GetWindowEventTarget();

  {
    target->ApplyPanGestureScroll(1, 2);
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();
    ASSERT_TRUE(event);

    if (GetParam()) {
      EXPECT_EQ(ui::ET_SCROLL, event->type());
      ui::ScrollEvent* scroll_event = event->AsScrollEvent();
      EXPECT_EQ(1, scroll_event->x_offset());
      EXPECT_EQ(2, scroll_event->y_offset());
      EXPECT_EQ(ui::EventMomentumPhase::NONE, scroll_event->momentum_phase());
      EXPECT_EQ(ui::ScrollEventPhase::kUpdate,
                scroll_event->scroll_event_phase());
    } else {
      EXPECT_EQ(ui::ET_MOUSEWHEEL, event->type());
      ui::MouseWheelEvent* wheel_event = event->AsMouseWheelEvent();
      EXPECT_EQ(1, wheel_event->x_offset());
      EXPECT_EQ(2, wheel_event->y_offset());
      EXPECT_TRUE(wheel_event->flags() & ui::EF_PRECISION_SCROLLING_DELTA);
    }
  }

  {
    target->ApplyPanGestureFling(1, 2);
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();
    ASSERT_TRUE(event);

    if (GetParam()) {
      EXPECT_EQ(ui::ET_SCROLL, event->type());
      ui::ScrollEvent* scroll_event = event->AsScrollEvent();
      EXPECT_EQ(1, scroll_event->x_offset());
      EXPECT_EQ(2, scroll_event->y_offset());
      EXPECT_EQ(ui::EventMomentumPhase::INERTIAL_UPDATE,
                scroll_event->momentum_phase());
      EXPECT_EQ(ui::ScrollEventPhase::kNone,
                scroll_event->scroll_event_phase());
    } else {
      EXPECT_EQ(ui::ET_MOUSEWHEEL, event->type());
      ui::MouseWheelEvent* wheel_event = event->AsMouseWheelEvent();
      EXPECT_EQ(1, wheel_event->x_offset());
      EXPECT_EQ(2, wheel_event->y_offset());
      EXPECT_TRUE(wheel_event->flags() & ui::EF_PRECISION_SCROLLING_DELTA);
    }
  }

  {
    target->ApplyPanGestureScrollBegin(1, 2);
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();

    if (GetParam()) {
      ASSERT_TRUE(event);
      EXPECT_EQ(ui::ET_SCROLL, event->type());
      ui::ScrollEvent* scroll_event = event->AsScrollEvent();
      EXPECT_EQ(1, scroll_event->x_offset());
      EXPECT_EQ(2, scroll_event->y_offset());
      EXPECT_EQ(ui::EventMomentumPhase::NONE, scroll_event->momentum_phase());
      EXPECT_EQ(ui::ScrollEventPhase::kBegan,
                scroll_event->scroll_event_phase());
    } else {
      EXPECT_EQ(ui::ET_MOUSEWHEEL, event->type());
      ui::MouseWheelEvent* wheel_event = event->AsMouseWheelEvent();
      EXPECT_EQ(1, wheel_event->x_offset());
      EXPECT_EQ(2, wheel_event->y_offset());
      EXPECT_TRUE(wheel_event->flags() & ui::EF_PRECISION_SCROLLING_DELTA);
    }
  }

  {
    target->ApplyPanGestureScrollEnd();
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();

    if (GetParam()) {
      ASSERT_TRUE(event);
      EXPECT_EQ(ui::ET_SCROLL, event->type());
      ui::ScrollEvent* scroll_event = event->AsScrollEvent();
      EXPECT_EQ(0, scroll_event->x_offset());
      EXPECT_EQ(0, scroll_event->y_offset());
      EXPECT_EQ(ui::EventMomentumPhase::NONE, scroll_event->momentum_phase());
      EXPECT_EQ(ui::ScrollEventPhase::kEnd, scroll_event->scroll_event_phase());
    } else {
      ASSERT_FALSE(event);
    }
  }

  {
    target->ApplyPanGestureFlingBegin();
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();

    if (GetParam()) {
      ASSERT_TRUE(event);
      EXPECT_EQ(ui::ET_SCROLL, event->type());
      ui::ScrollEvent* scroll_event = event->AsScrollEvent();
      EXPECT_EQ(0, scroll_event->x_offset());
      EXPECT_EQ(0, scroll_event->y_offset());
      EXPECT_EQ(ui::EventMomentumPhase::BEGAN, scroll_event->momentum_phase());
      EXPECT_EQ(ui::ScrollEventPhase::kNone,
                scroll_event->scroll_event_phase());
    } else {
      ASSERT_FALSE(event);
    }
  }

  {
    target->ApplyPanGestureFlingEnd();
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();

    if (GetParam()) {
      ASSERT_TRUE(event);
      EXPECT_EQ(ui::ET_SCROLL, event->type());
      ui::ScrollEvent* scroll_event = event->AsScrollEvent();
      EXPECT_EQ(0, scroll_event->x_offset());
      EXPECT_EQ(0, scroll_event->y_offset());
      EXPECT_EQ(ui::EventMomentumPhase::END, scroll_event->momentum_phase());
      EXPECT_EQ(ui::ScrollEventPhase::kNone,
                scroll_event->scroll_event_phase());
    } else {
      ASSERT_FALSE(event);
    }
  }

  {
    target->ApplyPinchZoomBegin();
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();
    ASSERT_TRUE(event);
    EXPECT_EQ(ui::ET_GESTURE_PINCH_BEGIN, event->type());
    ui::GestureEvent* gesture_event = event->AsGestureEvent();
    EXPECT_EQ(ui::GestureDeviceType::DEVICE_TOUCHPAD,
              gesture_event->details().device_type());
  }

  {
    target->ApplyPinchZoomScale(1.1f);
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();
    ASSERT_TRUE(event);
    EXPECT_EQ(ui::ET_GESTURE_PINCH_UPDATE, event->type());
    ui::GestureEvent* gesture_event = event->AsGestureEvent();
    EXPECT_EQ(ui::GestureDeviceType::DEVICE_TOUCHPAD,
              gesture_event->details().device_type());
    EXPECT_EQ(1.1f, gesture_event->details().scale());
  }

  {
    target->ApplyPinchZoomEnd();
    std::unique_ptr<ui::Event> event = event_logger.ReleaseLastEvent();
    ASSERT_TRUE(event);
    EXPECT_EQ(ui::ET_GESTURE_PINCH_END, event->type());
    ui::GestureEvent* gesture_event = event->AsGestureEvent();
    EXPECT_EQ(ui::GestureDeviceType::DEVICE_TOUCHPAD,
              gesture_event->details().device_type());
  }

  dwthw->RemoveEventRewriter(&event_logger);
}

}  // namespace content
