chromium/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc

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

#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h"

#include <memory>

#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
#include "extensions/browser/api_unittest.h"

namespace extensions {

namespace {

class MockVirtualKeyboardDelegate : public VirtualKeyboardDelegate {
 public:
  MockVirtualKeyboardDelegate() = default;

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

  ~MockVirtualKeyboardDelegate() override = default;

  // VirtualKeyboardDelegate impl:
  void GetKeyboardConfig(
      OnKeyboardSettingsCallback on_settings_callback) override {}
  void OnKeyboardConfigChanged() override {}
  bool HideKeyboard() override { return false; }
  bool InsertText(const std::u16string& text) override { return false; }
  bool OnKeyboardLoaded() override { return false; }
  void SetHotrodKeyboard(bool enable) override {}
  bool LockKeyboard(bool state) override { return false; }
  bool SendKeyEvent(const std::string& type,
                    int char_value,
                    int key_code,
                    const std::string& key_name,
                    int modifiers) override {
    return false;
  }
  bool ShowLanguageSettings() override { return false; }
  bool ShowSuggestionSettings() override { return false; }
  bool IsSettingsEnabled() override { return false; }
  bool SetVirtualKeyboardMode(api::virtual_keyboard_private::KeyboardMode mode,
                              gfx::Rect target_bounds,
                              OnSetModeCallback on_set_mode_callback) override {
    return false;
  }
  bool SetDraggableArea(
      const api::virtual_keyboard_private::Bounds& rect) override {
    return false;
  }
  bool SetRequestedKeyboardState(
      api::virtual_keyboard_private::KeyboardState state) override {
    return false;
  }

  bool SetOccludedBounds(const std::vector<gfx::Rect>& bounds) override {
    occluded_bounds_ = bounds;
    return true;
  }
  const std::vector<gfx::Rect>& GetOccludedBounds() { return occluded_bounds_; }

  bool SetHitTestBounds(const std::vector<gfx::Rect>& bounds) override {
    hit_test_bounds_ = bounds;
    return true;
  }
  const std::vector<gfx::Rect>& GetHitTestBounds() { return hit_test_bounds_; }

  bool SetAreaToRemainOnScreen(const gfx::Rect& bounds) override {
    area_to_remain_on_screen_ = bounds;
    return true;
  }
  const gfx::Rect& GetAreaToRemainOnScreen() {
    return area_to_remain_on_screen_;
  }

  bool SetWindowBoundsInScreen(const gfx::Rect& bounds_in_screen) override {
    window_bounds_ = bounds_in_screen;
    return true;
  }
  const gfx::Rect& GetWindowBounds() { return window_bounds_; }

  void GetClipboardHistory(
      OnGetClipboardHistoryCallback get_history_callback) override {}
  bool PasteClipboardItem(const std::string& clipboard_item_id) override {
    return false;
  }
  bool DeleteClipboardItem(const std::string& clipboard_item_id) override {
    return false;
  }

  void RestrictFeatures(
      const api::virtual_keyboard::RestrictFeatures::Params& params,
      OnRestrictFeaturesCallback callback) override {
    std::move(callback).Run(api::virtual_keyboard::FeatureRestrictions());
  }

 private:
  std::vector<gfx::Rect> occluded_bounds_;
  std::vector<gfx::Rect> hit_test_bounds_;
  gfx::Rect area_to_remain_on_screen_;
  gfx::Rect window_bounds_;
};

class TestVirtualKeyboardExtensionsAPIClient : public ExtensionsAPIClient {
 public:
  TestVirtualKeyboardExtensionsAPIClient() = default;

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

  ~TestVirtualKeyboardExtensionsAPIClient() override = default;

  // ExtensionsAPIClient implementation.
  std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate(
      content::BrowserContext* browser_context) const override {
    auto delegate = std::make_unique<MockVirtualKeyboardDelegate>();
    delegates_[browser_context] = delegate.get();
    return std::move(delegate);
  }

  MockVirtualKeyboardDelegate* GetDelegateForBrowserContext(
      content::BrowserContext* browser_context) const {
    return delegates_[browser_context];
  }

 private:
  // Points to the last mock delegate created for each browser context. Does not
  // own the delegates.
  mutable std::map<content::BrowserContext*, MockVirtualKeyboardDelegate*>
      delegates_;
};

}  // namespace

class VirtualKeyboardPrivateApiUnittest : public ApiUnitTest {
 public:
  VirtualKeyboardPrivateApiUnittest() = default;
  ~VirtualKeyboardPrivateApiUnittest() override = default;

  const TestVirtualKeyboardExtensionsAPIClient& client() const {
    return extensions_api_client_;
  }

 protected:
  TestVirtualKeyboardExtensionsAPIClient extensions_api_client_;
};

TEST_F(VirtualKeyboardPrivateApiUnittest, SetOccludedBoundsWithNoBounds) {
  RunFunction(new VirtualKeyboardPrivateSetOccludedBoundsFunction(), "[[]]");

  const auto bounds = client()
                          .GetDelegateForBrowserContext(browser_context())
                          ->GetOccludedBounds();
  EXPECT_EQ(0U, bounds.size());
}

TEST_F(VirtualKeyboardPrivateApiUnittest, SetOccludedBoundsWithOneBound) {
  RunFunction(new VirtualKeyboardPrivateSetOccludedBoundsFunction(),
              R"([[{ "left": 0, "top": 10, "width": 20, "height": 30 }]])");

  const auto bounds = client()
                          .GetDelegateForBrowserContext(browser_context())
                          ->GetOccludedBounds();
  ASSERT_EQ(1U, bounds.size());
  EXPECT_EQ(gfx::Rect(0, 10, 20, 30), bounds[0]);
}

TEST_F(VirtualKeyboardPrivateApiUnittest, SetOccludedBoundsWithTwoBounds) {
  RunFunction(new VirtualKeyboardPrivateSetOccludedBoundsFunction(),
              R"([[{ "left": 0, "top": 10, "width": 20, "height": 30 },
      { "left": 10, "top": 20, "width": 30, "height": 40 }]])");

  const auto bounds = client()
                          .GetDelegateForBrowserContext(browser_context())
                          ->GetOccludedBounds();
  ASSERT_EQ(2U, bounds.size());
  EXPECT_EQ(gfx::Rect(0, 10, 20, 30), bounds[0]);
  EXPECT_EQ(gfx::Rect(10, 20, 30, 40), bounds[1]);
}

TEST_F(VirtualKeyboardPrivateApiUnittest, SetHitTestBoundsWithNoBounds) {
  RunFunction(new VirtualKeyboardPrivateSetHitTestBoundsFunction(), "[[]]");

  const auto bounds = client()
                          .GetDelegateForBrowserContext(browser_context())
                          ->GetHitTestBounds();
  EXPECT_EQ(0U, bounds.size());
}

TEST_F(VirtualKeyboardPrivateApiUnittest, SetHitTestBoundsWithMultipleBounds) {
  RunFunction(new VirtualKeyboardPrivateSetHitTestBoundsFunction(),
              R"([[{ "left": 0, "top": 10, "width": 20, "height": 30 },
      { "left": 10, "top": 20, "width": 30, "height": 40 }]])");

  const auto bounds = client()
                          .GetDelegateForBrowserContext(browser_context())
                          ->GetHitTestBounds();
  ASSERT_EQ(2U, bounds.size());
  EXPECT_EQ(gfx::Rect(0, 10, 20, 30), bounds[0]);
  EXPECT_EQ(gfx::Rect(10, 20, 30, 40), bounds[1]);
}

TEST_F(VirtualKeyboardPrivateApiUnittest, SetAreaToRemainOnScreenWithBounds) {
  RunFunction(new VirtualKeyboardPrivateSetAreaToRemainOnScreenFunction(),
              R"([{ "left": 0, "top": 0, "width": 10, "height": 20 }])");

  const gfx::Rect bounds = client()
                               .GetDelegateForBrowserContext(browser_context())
                               ->GetAreaToRemainOnScreen();
  EXPECT_EQ(gfx::Rect(0, 0, 10, 20), bounds);
}

TEST_F(VirtualKeyboardPrivateApiUnittest, SetWindowBoundsInScreenWithBounds) {
  RunFunction(new VirtualKeyboardPrivateSetWindowBoundsInScreenFunction(),
              R"([{ "left": 120, "top": 300, "width": 400, "height": 250 }])");

  const gfx::Rect bounds = client()
                               .GetDelegateForBrowserContext(browser_context())
                               ->GetWindowBounds();
  EXPECT_EQ(gfx::Rect(120, 300, 400, 250), bounds);
}

}  // namespace extensions