// Copyright 2021 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 "pdf/pdf_view_web_plugin.h"

#include <memory>
#include <string>
#include <utility>

#include "base/strings/string_piece.h"
#include "cc/paint/paint_canvas.h"
#include "cc/test/pixel_comparator.h"
#include "cc/test/pixel_test_utils.h"
#include "pdf/ppapi_migration/bitmap.h"
#include "pdf/test/test_helpers.h"
#include "pdf/test/test_pdfium_engine.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/common/input/web_pointer_properties.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_text_input_type.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_associated_url_loader.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/cursor/cursor.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/latency/latency_info.h"

namespace chrome_pdf {

namespace {

using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::MockFunction;
using ::testing::NiceMock;
using ::testing::Pointwise;
using ::testing::Return;

// `kCanvasSize` needs to be big enough to hold plugin's snapshots during
// testing.
constexpr gfx::Size kCanvasSize(100, 100);

// A common device scale for high DPI displays.
constexpr float kDeviceScale = 2.0f;

// Note: Make sure `kDefaultColor` is different from `kPaintColor` and the
// plugin's background color. This will help identify bitmap changes after
// painting.
constexpr SkColor kDefaultColor = SK_ColorGREEN;

constexpr SkColor kPaintColor = SK_ColorRED;

struct PaintParams {
  // The plugin container's device scale.
  float device_scale;

  // The window area in CSS pixels.
  gfx::Rect window_rect;

  // The target painting area on the canvas in CSS pixels.
  gfx::Rect paint_rect;

  // The expected clipped area to be filled with paint color. The clipped area
  // should be the intersection of `paint_rect` and `window_rect`.
  gfx::Rect expected_clipped_rect;
};

MATCHER(SearchStringResultEq, "") {
  PDFEngine::Client::SearchStringResult l = std::get<0>(arg);
  PDFEngine::Client::SearchStringResult r = std::get<1>(arg);
  return l.start_index == r.start_index && l.length == r.length;
}

MATCHER_P(IsExpectedImeKeyEvent, expected_text, "") {
  if (arg.GetType() != blink::WebInputEvent::Type::kChar)
    return false;

  const auto& event = static_cast<const blink::WebKeyboardEvent&>(arg);
  return event.GetModifiers() == blink::WebInputEvent::kNoModifiers &&
         event.windows_key_code == expected_text[0] &&
         event.native_key_code == expected_text[0] &&
         event.dom_code == static_cast<int>(ui::DomCode::NONE) &&
         event.dom_key == ui::DomKey::NONE && !event.is_system_key &&
         !event.is_browser_shortcut && event.text == expected_text &&
         event.unmodified_text == expected_text;
}

// Generates the expected `SkBitmap` with `paint_color` filled in the expected
// clipped area and `kDefaultColor` as the background color.
SkBitmap GenerateExpectedBitmapForPaint(const gfx::Rect& expected_clipped_rect,
                                        SkColor paint_color) {
  SkBitmap expected_bitmap =
      CreateN32PremulSkBitmap(gfx::SizeToSkISize(kCanvasSize));
  expected_bitmap.eraseColor(kDefaultColor);
  expected_bitmap.erase(paint_color, gfx::RectToSkIRect(expected_clipped_rect));
  return expected_bitmap;
}

blink::WebMouseEvent CreateDefaultMouseDownEvent() {
  blink::WebMouseEvent web_event(
      blink::WebInputEvent::Type::kMouseDown,
      /*position=*/gfx::PointF(),
      /*global_position=*/gfx::PointF(),
      blink::WebPointerProperties::Button::kLeft,
      /*click_count_param=*/1, blink::WebInputEvent::Modifiers::kLeftButtonDown,
      blink::WebInputEvent::GetStaticTimeStampForTests());
  web_event.SetFrameScale(1);
  return web_event;
}

class FakeContainerWrapper : public PdfViewWebPlugin::ContainerWrapper {
 public:
  explicit FakeContainerWrapper(PdfViewWebPlugin* web_plugin)
      : web_plugin_(web_plugin) {
    ON_CALL(*this, UpdateTextInputState)
        .WillByDefault(Invoke(
            this, &FakeContainerWrapper::UpdateTextInputStateFromPlugin));

    UpdateTextInputStateFromPlugin();
  }

  FakeContainerWrapper(const FakeContainerWrapper&) = delete;
  FakeContainerWrapper& operator=(const FakeContainerWrapper&) = delete;
  ~FakeContainerWrapper() override = default;

  // PdfViewWebPlugin::ContainerWrapper:
  void Invalidate() override {}

  MOCK_METHOD(void,
              RequestTouchEventType,
              (blink::WebPluginContainer::TouchEventRequestType),
              (override));

  MOCK_METHOD(void, ReportFindInPageMatchCount, (int, int, bool), (override));

  MOCK_METHOD(void, ReportFindInPageSelection, (int, int), (override));

  float DeviceScaleFactor() override { return device_scale_; }

  MOCK_METHOD(void,
              SetReferrerForRequest,
              (blink::WebURLRequest&, const blink::WebURL&),
              (override));

  MOCK_METHOD(void, Alert, (const blink::WebString&), (override));

  MOCK_METHOD(bool, Confirm, (const blink::WebString&), (override));

  MOCK_METHOD(blink::WebString,
              Prompt,
              (const blink::WebString&, const blink::WebString&),
              (override));

  MOCK_METHOD(void,
              TextSelectionChanged,
              (const blink::WebString&, uint32_t, const gfx::Range&),
              (override));

  MOCK_METHOD(std::unique_ptr<blink::WebAssociatedURLLoader>,
              CreateAssociatedURLLoader,
              (const blink::WebAssociatedURLLoaderOptions&),
              (override));

  MOCK_METHOD(void, UpdateTextInputState, (), (override));

  MOCK_METHOD(void, UpdateSelectionBounds, (), (override));

  std::string GetEmbedderOriginString() override {
    return "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/";
  }

  blink::WebLocalFrame* GetFrame() override { return nullptr; }

  blink::WebLocalFrameClient* GetWebLocalFrameClient() override {
    return nullptr;
  }

  // TODO(https://crbug.com/1207575): Container() should not be used for testing
  // since it doesn't have a valid blink::WebPluginContainer. Make this method
  // fail once ContainerWrapper instead of blink::WebPluginContainer is used for
  // initializing `PostMessageSender`.
  blink::WebPluginContainer* Container() override { return nullptr; }

  blink::WebTextInputType widget_text_input_type() const {
    return widget_text_input_type_;
  }

  void set_device_scale(float device_scale) { device_scale_ = device_scale; }

 private:
  void UpdateTextInputStateFromPlugin() {
    widget_text_input_type_ = web_plugin_->GetPluginTextInputType();
  }

  float device_scale_ = 1.0f;

  // Represents the frame widget's text input type.
  blink::WebTextInputType widget_text_input_type_;

  PdfViewWebPlugin* web_plugin_;
};

class FakePdfViewWebPluginClient : public PdfViewWebPlugin::Client {
 public:
  FakePdfViewWebPluginClient() = default;
  FakePdfViewWebPluginClient(const FakePdfViewWebPluginClient&) = delete;
  FakePdfViewWebPluginClient& operator=(const FakePdfViewWebPluginClient&) =
      delete;
  ~FakePdfViewWebPluginClient() override = default;

  // PdfViewWebPlugin::Client:
  MOCK_METHOD(bool, IsUseZoomForDSFEnabled, (), (const, override));
};

}  // namespace

class PdfViewWebPluginWithoutInitializeTest : public testing::Test {
 public:
  PdfViewWebPluginWithoutInitializeTest(
      const PdfViewWebPluginWithoutInitializeTest&) = delete;
  PdfViewWebPluginWithoutInitializeTest& operator=(
      const PdfViewWebPluginWithoutInitializeTest&) = delete;

 protected:
  // Custom deleter for `plugin_`. PdfViewWebPlugin must be destroyed by
  // PdfViewWebPlugin::Destroy() instead of its destructor.
  struct PluginDeleter {
    void operator()(PdfViewWebPlugin* ptr) { ptr->Destroy(); }
  };

  PdfViewWebPluginWithoutInitializeTest() = default;
  ~PdfViewWebPluginWithoutInitializeTest() override = default;

  void SetUp() override {
    // Set a dummy URL for initializing the plugin.
    blink::WebPluginParams params;
    params.attribute_names.push_back(blink::WebString("src"));
    params.attribute_values.push_back(blink::WebString("dummy.pdf"));

    auto client = std::make_unique<NiceMock<FakePdfViewWebPluginClient>>();
    client_ptr_ = client.get();

    mojo::AssociatedRemote<pdf::mojom::PdfService> unbound_remote;
    plugin_ =
        std::unique_ptr<PdfViewWebPlugin, PluginDeleter>(new PdfViewWebPlugin(
            std::move(client), std::move(unbound_remote), params));
  }

  void TearDown() override { plugin_.reset(); }

  FakePdfViewWebPluginClient* client_ptr_;
  std::unique_ptr<PdfViewWebPlugin, PluginDeleter> plugin_;
};

class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
 protected:
  void SetUp() override {
    PdfViewWebPluginWithoutInitializeTest::SetUp();

    auto wrapper =
        std::make_unique<NiceMock<FakeContainerWrapper>>(plugin_.get());
    wrapper_ptr_ = wrapper.get();
    auto engine = CreateEngine();
    engine_ptr_ = engine.get();
    EXPECT_TRUE(
        plugin_->InitializeForTesting(std::move(wrapper), std::move(engine)));
  }

  void TearDown() override {
    wrapper_ptr_ = nullptr;

    PdfViewWebPluginWithoutInitializeTest::TearDown();
  }

  // Allow derived test classes to create their own custom TestPDFiumEngine.
  virtual std::unique_ptr<TestPDFiumEngine> CreateEngine() {
    return std::make_unique<TestPDFiumEngine>(plugin_.get());
  }

  void UpdatePluginGeometry(float device_scale, const gfx::Rect& window_rect) {
    // The plugin container's device scale must be set before calling
    // UpdateGeometry().
    ASSERT_TRUE(wrapper_ptr_);
    wrapper_ptr_->set_device_scale(device_scale);
    plugin_->UpdateGeometry(window_rect, window_rect, window_rect,
                            /*is_visible=*/true);
  }

  void TestUpdateGeometrySetsPluginRect(float device_scale,
                                        const gfx::Rect& window_rect,
                                        float expected_device_scale,
                                        const gfx::Rect& expected_plugin_rect) {
    UpdatePluginGeometry(device_scale, window_rect);
    EXPECT_EQ(expected_device_scale, plugin_->GetDeviceScaleForTesting())
        << "Device scale comparison failure at device scale of "
        << device_scale;
    EXPECT_EQ(expected_plugin_rect, plugin_->GetPluginRectForTesting())
        << "Plugin rect comparison failure at device scale of " << device_scale
        << ", window rect of " << window_rect.ToString();
  }

  void TestPaintEmptySnapshots(float device_scale,
                               const gfx::Rect& window_rect,
                               const gfx::Rect& paint_rect,
                               const gfx::Rect& expected_clipped_rect) {
    UpdatePluginGeometry(device_scale, window_rect);
    canvas_.DrawColor(kDefaultColor);

    plugin_->Paint(canvas_.sk_canvas(), paint_rect);

    // Expect the clipped area on canvas to be filled with plugin's background
    // color.
    SkBitmap expected_bitmap = GenerateExpectedBitmapForPaint(
        expected_clipped_rect, plugin_->GetBackgroundColor());
    EXPECT_TRUE(
        cc::MatchesBitmap(canvas_.GetBitmap(), expected_bitmap,
                          cc::ExactPixelComparator(/*discard_alpha=*/false)))
        << "Failure at device scale of " << device_scale << ", window rect of "
        << window_rect.ToString();
  }

  void TestPaintSnapshots(float device_scale,
                          const gfx::Rect& window_rect,
                          const gfx::Rect& paint_rect,
                          const gfx::Rect& expected_clipped_rect) {
    UpdatePluginGeometry(device_scale, window_rect);
    canvas_.DrawColor(kDefaultColor);

    // Fill the graphics device with `kPaintColor` and update the plugin's
    // snapshot.
    const gfx::Rect& plugin_rect = plugin_->GetPluginRectForTesting();
    std::unique_ptr<Graphics> graphics =
        plugin_->CreatePaintGraphics(plugin_rect.size());
    graphics->PaintImage(
        CreateSkiaImageForTesting(plugin_rect.size(), kPaintColor),
        gfx::Rect(plugin_rect.width(), plugin_rect.height()));
    graphics->Flush(base::DoNothing());

    plugin_->Paint(canvas_.sk_canvas(), paint_rect);

    // Expect the clipped area on canvas to be filled with `kPaintColor`.
    SkBitmap expected_bitmap =
        GenerateExpectedBitmapForPaint(expected_clipped_rect, kPaintColor);
    EXPECT_TRUE(
        cc::MatchesBitmap(canvas_.GetBitmap(), expected_bitmap,
                          cc::ExactPixelComparator(/*discard_alpha=*/false)))
        << "Failure at device scale of " << device_scale << ", window rect of "
        << window_rect.ToString();
  }

  TestPDFiumEngine* engine_ptr_;
  FakeContainerWrapper* wrapper_ptr_;

  // Provides the cc::PaintCanvas for painting.
  gfx::Canvas canvas_{kCanvasSize, /*image_scale=*/1.0f, /*is_opaque=*/true};
};

TEST_F(PdfViewWebPluginWithoutInitializeTest, Initialize) {
  auto wrapper =
      std::make_unique<NiceMock<FakeContainerWrapper>>(plugin_.get());
  auto engine = std::make_unique<TestPDFiumEngine>(plugin_.get());
  EXPECT_CALL(*wrapper,
              RequestTouchEventType(
                  blink::WebPluginContainer::kTouchEventRequestTypeRaw));

  EXPECT_TRUE(
      plugin_->InitializeForTesting(std::move(wrapper), std::move(engine)));
}

TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRectUseZoomForDSFEnabled) {
  EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
      .WillRepeatedly(Return(true));
  EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
  TestUpdateGeometrySetsPluginRect(
      /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(4, 4, 12, 12),
      /*expected_device_scale=*/2.0f,
      /*expected_plugin_rect=*/gfx::Rect(4, 4, 12, 12));
}

TEST_F(PdfViewWebPluginTest,
       UpdateGeometrySetsPluginRectUseZoomForDSFDisabled) {
  EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
      .WillRepeatedly(Return(false));
  EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
  TestUpdateGeometrySetsPluginRect(
      /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(4, 4, 12, 12),
      /*expected_device_scale=*/2.0f,
      /*expected_plugin_rect=*/gfx::Rect(8, 8, 24, 24));
}

TEST_F(PdfViewWebPluginTest,
       UpdateGeometrySetsPluginRectOnVariousDeviceScales) {
  struct UpdateGeometryParams {
    // The plugin container's device scale.
    float device_scale;

    //  The window rect in CSS pixels.
    gfx::Rect window_rect;

    // The expected plugin device scale.
    float expected_device_scale;

    // The expected plugin rect in device pixels.
    gfx::Rect expected_plugin_rect;
  };

  // Keep the using zoom for DSF setting consistent within the test.
  EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
      .WillRepeatedly(Return(true));

  static constexpr UpdateGeometryParams kUpdateGeometryParams[] = {
      {1.0f, gfx::Rect(3, 4, 5, 6), 1.0f, gfx::Rect(3, 4, 5, 6)},
      {2.0f, gfx::Rect(3, 4, 5, 6), 2.0f, gfx::Rect(3, 4, 5, 6)},
  };

  for (const auto& params : kUpdateGeometryParams) {
    TestUpdateGeometrySetsPluginRect(params.device_scale, params.window_rect,
                                     params.expected_device_scale,
                                     params.expected_plugin_rect);
  }
}

class PdfViewWebPluginTestUseZoomForDSF
    : public PdfViewWebPluginTest,
      public testing::WithParamInterface<bool> {
 public:
  void SetUp() override {
    PdfViewWebPluginTest::SetUp();
    ON_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
        .WillByDefault(Return(GetParam()));
  }
};

TEST_P(PdfViewWebPluginTestUseZoomForDSF,
       UpdateGeometrySetsPluginRectWithEmptyWindow) {
  EXPECT_CALL(*engine_ptr_, ZoomUpdated).Times(0);
  TestUpdateGeometrySetsPluginRect(
      /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(2, 2, 0, 0),
      /*expected_device_scale=*/1.0f, /*expected_plugin_rect=*/gfx::Rect());
}

TEST_P(PdfViewWebPluginTestUseZoomForDSF, PaintEmptySnapshots) {
  TestPaintEmptySnapshots(/*device_scale=*/4.0f,
                          /*window_rect=*/gfx::Rect(10, 10, 20, 20),
                          /*paint_rect=*/gfx::Rect(5, 5, 15, 15),
                          /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
}

TEST_P(PdfViewWebPluginTestUseZoomForDSF, PaintSnapshots) {
  TestPaintSnapshots(/*device_scale=*/4.0f,
                     /*window_rect=*/gfx::Rect(10, 10, 20, 20),
                     /*paint_rect=*/gfx::Rect(5, 5, 15, 15),
                     /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
}

TEST_P(PdfViewWebPluginTestUseZoomForDSF,
       PaintSnapshotsWithVariousDeviceScales) {
  static constexpr PaintParams kPaintWithVariousScalesParams[] = {
      {0.4f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
       gfx::Rect(10, 10, 28, 28)},
      {1.0f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
       gfx::Rect(10, 10, 28, 28)},
      {4.0f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
       gfx::Rect(10, 10, 28, 28)},
  };

  for (const auto& params : kPaintWithVariousScalesParams) {
    TestPaintSnapshots(params.device_scale, params.window_rect,
                       params.paint_rect, params.expected_clipped_rect);
  }
}

TEST_P(PdfViewWebPluginTestUseZoomForDSF,
       PaintSnapshotsWithVariousRectPositions) {
  static constexpr PaintParams kPaintWithVariousPositionsParams[] = {
      // The window origin falls outside the `paint_rect` area.
      {4.0f, gfx::Rect(10, 10, 20, 20), gfx::Rect(5, 5, 15, 15),
       gfx::Rect(10, 10, 10, 10)},
      // The window origin falls within the `paint_rect` area.
      {4.0f, gfx::Rect(4, 4, 20, 20), gfx::Rect(8, 8, 15, 15),
       gfx::Rect(8, 8, 15, 15)},
  };

  for (const auto& params : kPaintWithVariousPositionsParams) {
    TestPaintSnapshots(params.device_scale, params.window_rect,
                       params.paint_rect, params.expected_clipped_rect);
  }
}

INSTANTIATE_TEST_SUITE_P(All,
                         PdfViewWebPluginTestUseZoomForDSF,
                         testing::Bool());

class PdfViewWebPluginMouseEventsTest : public PdfViewWebPluginTest {
 public:
  class TestPDFiumEngineForMouseEvents : public TestPDFiumEngine {
   public:
    explicit TestPDFiumEngineForMouseEvents(PDFEngine::Client* client)
        : TestPDFiumEngine(client) {}

    // TestPDFiumEngine:
    bool HandleInputEvent(const blink::WebInputEvent& event) override {
      // Since blink::WebInputEvent is an abstract class, we cannot use equal
      // matcher to verify its value. Here we test with blink::WebMouseEvent
      // specifically.
      if (!blink::WebInputEvent::IsMouseEventType(event.GetType()))
        return false;

      scaled_mouse_event_ = std::make_unique<blink::WebMouseEvent>();
      *scaled_mouse_event_ = static_cast<const blink::WebMouseEvent&>(event);
      return true;
    }

    const blink::WebMouseEvent* GetScaledMouseEvent() const {
      return scaled_mouse_event_.get();
    }

   private:
    std::unique_ptr<blink::WebMouseEvent> scaled_mouse_event_;
  };

  std::unique_ptr<TestPDFiumEngine> CreateEngine() override {
    return std::make_unique<TestPDFiumEngineForMouseEvents>(plugin_.get());
  }

  TestPDFiumEngineForMouseEvents* engine() {
    return static_cast<TestPDFiumEngineForMouseEvents*>(engine_ptr_);
  }
};

TEST_F(PdfViewWebPluginMouseEventsTest,
       HandleInputEventWithUseZoomForDSFEnabled) {
  // Test when using zoom for DSF is enabled.
  EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
      .WillRepeatedly(Return(true));
  wrapper_ptr_->set_device_scale(kDeviceScale);
  UpdatePluginGeometry(kDeviceScale, gfx::Rect(20, 20));

  ui::Cursor dummy_cursor;
  plugin_->HandleInputEvent(
      blink::WebCoalescedInputEvent(CreateDefaultMouseDownEvent(),
                                    ui::LatencyInfo()),
      &dummy_cursor);

  const blink::WebMouseEvent* event = engine()->GetScaledMouseEvent();
  ASSERT_TRUE(event);
  EXPECT_EQ(gfx::PointF(-10.0f, 0.0f), event->PositionInWidget());
}

TEST_F(PdfViewWebPluginMouseEventsTest,
       HandleInputEventWithUseZoomForDSFDisabled) {
  // Test when using zoom for DSF is disabled.
  EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
      .WillRepeatedly(Return(false));
  wrapper_ptr_->set_device_scale(kDeviceScale);
  UpdatePluginGeometry(kDeviceScale, gfx::Rect(20, 20));

  ui::Cursor dummy_cursor;
  plugin_->HandleInputEvent(
      blink::WebCoalescedInputEvent(CreateDefaultMouseDownEvent(),
                                    ui::LatencyInfo()),
      &dummy_cursor);

  const blink::WebMouseEvent* event = engine()->GetScaledMouseEvent();
  ASSERT_TRUE(event);
  EXPECT_EQ(gfx::PointF(-20.0f, 0.0f), event->PositionInWidget());
}

class PdfViewWebPluginImeTest : public PdfViewWebPluginTest {
 public:
  class TestPDFiumEngineForIme : public TestPDFiumEngine {
   public:
    explicit TestPDFiumEngineForIme(PDFEngine::Client* client)
        : TestPDFiumEngine(client) {}

    // TestPDFiumEngine:
    MOCK_METHOD(bool,
                HandleInputEvent,
                (const blink::WebInputEvent&),
                (override));
  };

  std::unique_ptr<TestPDFiumEngine> CreateEngine() override {
    return std::make_unique<TestPDFiumEngineForIme>(plugin_.get());
  }

  TestPDFiumEngineForIme* engine() {
    return static_cast<TestPDFiumEngineForIme*>(engine_ptr_);
  }

  void TestImeSetCompositionForPlugin(const blink::WebString& text) {
    EXPECT_CALL(*engine(), HandleInputEvent).Times(0);
    plugin_->ImeSetCompositionForPlugin(text, std::vector<ui::ImeTextSpan>(),
                                        gfx::Range(),
                                        /*selection_start=*/0,
                                        /*selection_end=*/0);
  }

  void TestImeFinishComposingTextForPlugin(
      const blink::WebString& expected_text) {
    InSequence sequence;
    std::u16string expected_text16 = expected_text.Utf16();
    if (expected_text16.size()) {
      for (const auto& c : expected_text16) {
        base::StringPiece16 expected_key(&c, 1);
        EXPECT_CALL(*engine(),
                    HandleInputEvent(IsExpectedImeKeyEvent(expected_key)))
            .WillOnce(Return(true));
      }
    } else {
      EXPECT_CALL(*engine(), HandleInputEvent).Times(0);
    }
    plugin_->ImeFinishComposingTextForPlugin(false);
  }

  void TestImeCommitTextForPlugin(const blink::WebString& text) {
    InSequence sequence;
    std::u16string expected_text16 = text.Utf16();
    if (expected_text16.size()) {
      for (const auto& c : expected_text16) {
        base::StringPiece16 event(&c, 1);
        EXPECT_CALL(*engine(), HandleInputEvent(IsExpectedImeKeyEvent(event)))
            .WillOnce(Return(true));
      }
    } else {
      EXPECT_CALL(*engine(), HandleInputEvent).Times(0);
    }
    plugin_->ImeCommitTextForPlugin(text, std::vector<ui::ImeTextSpan>(),
                                    gfx::Range(),
                                    /*relative_cursor_pos=*/0);
  }
};

TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishAscii) {
  const blink::WebString text = blink::WebString::FromASCII("input");
  TestImeSetCompositionForPlugin(text);
  TestImeFinishComposingTextForPlugin(text);
}

TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishUnicode) {
  const blink::WebString text = blink::WebString::FromUTF16(u"你好");
  TestImeSetCompositionForPlugin(text);
  TestImeFinishComposingTextForPlugin(text);
  // Calling ImeFinishComposingTextForPlugin() again is a no-op.
  TestImeFinishComposingTextForPlugin("");
}

TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishEmpty) {
  const blink::WebString text;
  TestImeSetCompositionForPlugin(text);
  TestImeFinishComposingTextForPlugin(text);
}

TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginAscii) {
  const blink::WebString text = blink::WebString::FromASCII("a b");
  TestImeCommitTextForPlugin(text);
}

TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginUnicode) {
  const blink::WebString text = blink::WebString::FromUTF16(u"さようなら");
  TestImeCommitTextForPlugin(text);
}

TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginEmpty) {
  const blink::WebString text;
  TestImeCommitTextForPlugin(text);
}

TEST_F(PdfViewWebPluginTest, ChangeTextSelection) {
  ASSERT_FALSE(plugin_->HasSelection());
  ASSERT_TRUE(plugin_->SelectionAsText().IsEmpty());
  ASSERT_TRUE(plugin_->SelectionAsMarkup().IsEmpty());

  static constexpr char kSelectedText[] = "1234";
  EXPECT_CALL(*wrapper_ptr_,
              TextSelectionChanged(blink::WebString::FromUTF8(kSelectedText), 0,
                                   gfx::Range(0, 4)));

  plugin_->SetSelectedText(kSelectedText);
  EXPECT_TRUE(plugin_->HasSelection());
  EXPECT_EQ(kSelectedText, plugin_->SelectionAsText().Utf8());
  EXPECT_EQ(kSelectedText, plugin_->SelectionAsMarkup().Utf8());

  static constexpr char kEmptyText[] = "";
  EXPECT_CALL(*wrapper_ptr_,
              TextSelectionChanged(blink::WebString::FromUTF8(kEmptyText), 0,
                                   gfx::Range(0, 0)));
  plugin_->SetSelectedText(kEmptyText);
  EXPECT_FALSE(plugin_->HasSelection());
  EXPECT_TRUE(plugin_->SelectionAsText().IsEmpty());
  EXPECT_TRUE(plugin_->SelectionAsMarkup().IsEmpty());
}

TEST_F(PdfViewWebPluginTest, FormTextFieldFocusChangeUpdatesTextInputType) {
  ASSERT_EQ(blink::WebTextInputType::kWebTextInputTypeNone,
            wrapper_ptr_->widget_text_input_type());

  MockFunction<void()> checkpoint;
  {
    InSequence sequence;
    EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
    EXPECT_CALL(checkpoint, Call);
    EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
  }

  plugin_->FormTextFieldFocusChange(true);
  EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeText,
            wrapper_ptr_->widget_text_input_type());

  checkpoint.Call();

  plugin_->FormTextFieldFocusChange(false);
  EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeNone,
            wrapper_ptr_->widget_text_input_type());
}

TEST_F(PdfViewWebPluginTest, SearchString) {
  static constexpr char16_t kPattern[] = u"fox";
  static constexpr char16_t kTarget[] =
      u"The quick brown fox jumped over the lazy Fox";

  {
    static constexpr PDFEngine::Client::SearchStringResult kExpectation[] = {
        {16, 3}};
    EXPECT_THAT(
        plugin_->SearchString(kTarget, kPattern, /*case_sensitive=*/true),
        Pointwise(SearchStringResultEq(), kExpectation));
  }
  {
    static constexpr PDFEngine::Client::SearchStringResult kExpectation[] = {
        {16, 3}, {41, 3}};
    EXPECT_THAT(
        plugin_->SearchString(kTarget, kPattern, /*case_sensitive=*/false),
        Pointwise(SearchStringResultEq(), kExpectation));
  }
}

TEST_F(PdfViewWebPluginTest, UpdateFocus) {
  MockFunction<void(int checkpoint_num)> checkpoint;

  {
    InSequence sequence;

    // Focus false -> true: Triggers updates.
    EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
    EXPECT_CALL(*wrapper_ptr_, UpdateSelectionBounds);
    EXPECT_CALL(checkpoint, Call(1));

    // Focus true -> true: No updates.
    EXPECT_CALL(checkpoint, Call(2));

    // Focus true -> false: Triggers updates. `UpdateTextInputState` is called
    // twice because it also gets called due to
    // `PDFiumEngine::UpdateFocus(false)`.
    EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState).Times(2);
    EXPECT_CALL(*wrapper_ptr_, UpdateSelectionBounds);
    EXPECT_CALL(checkpoint, Call(3));

    // Focus false -> false: No updates.
    EXPECT_CALL(checkpoint, Call(4));

    // Focus false -> true: Triggers updates.
    EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
    EXPECT_CALL(*wrapper_ptr_, UpdateSelectionBounds);
  }

  // The focus type does not matter in this test.
  plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
  checkpoint.Call(1);
  plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
  checkpoint.Call(2);
  plugin_->UpdateFocus(/*focused=*/false, blink::mojom::FocusType::kNone);
  checkpoint.Call(3);
  plugin_->UpdateFocus(/*focused=*/false, blink::mojom::FocusType::kNone);
  checkpoint.Call(4);
  plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
}

TEST_F(PdfViewWebPluginTest, ShouldDispatchImeEventsToPlugin) {
  ASSERT_TRUE(plugin_->ShouldDispatchImeEventsToPlugin());
}

TEST_F(PdfViewWebPluginTest, CaretChangeUseZoomForDSFEnabled) {
  EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
      .WillRepeatedly(Return(true));
  EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
  UpdatePluginGeometry(
      /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(12, 24, 36, 48));
  plugin_->CaretChanged(gfx::Rect(10, 20, 30, 40));
  EXPECT_EQ(gfx::Rect(28, 20, 30, 40), plugin_->GetPluginCaretBounds());
}

TEST_F(PdfViewWebPluginTest, CaretChangeUseZoomForDSFDisabled) {
  EXPECT_CALL(*client_ptr_, IsUseZoomForDSFEnabled)
      .WillRepeatedly(Return(false));
  EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
  UpdatePluginGeometry(
      /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(12, 24, 36, 48));
  plugin_->CaretChanged(gfx::Rect(10, 20, 30, 40));
  EXPECT_EQ(gfx::Rect(23, 10, 15, 20), plugin_->GetPluginCaretBounds());
}

}  // namespace chrome_pdf
