| // Copyright 2020 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 "third_party/blink/renderer/core/editing/substring_util.h" |
| |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/web/web_script_source.h" |
| #include "third_party/blink/public/web/web_view.h" |
| #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" |
| #include "third_party/blink/renderer/core/frame/frame_test_helpers.h" |
| #include "third_party/blink/renderer/core/frame/local_frame.h" |
| #include "third_party/blink/renderer/core/frame/web_frame_widget_base.h" |
| #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" |
| #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" |
| #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" |
| |
| namespace blink { |
| |
| class SubStringUtilTest : public testing::Test { |
| public: |
| SubStringUtilTest() : base_url_("http://www.test.com/") {} |
| |
| void TearDown() override { |
| url_test_helpers::UnregisterAllURLsAndClearMemoryCache(); |
| } |
| |
| protected: |
| std::string RegisterMockedHttpURLLoad(const std::string& file_name) { |
| // TODO(crbug.com/751425): We should use the mock functionality |
| // via |web_view_helper_|. |
| return url_test_helpers::RegisterMockedURLLoadFromBase( |
| WebString::FromUTF8(base_url_), test::CoreTestDataPath(), |
| WebString::FromUTF8(file_name)) |
| .GetString() |
| .Utf8(); |
| } |
| |
| std::string base_url_; |
| frame_test_helpers::WebViewHelper web_view_helper_; |
| }; |
| |
| TEST_F(SubStringUtilTest, SubstringUtil) { |
| RegisterMockedHttpURLLoad("content_editable_populated.html"); |
| WebView* web_view = static_cast<WebView*>(web_view_helper_.InitializeAndLoad( |
| base_url_ + "content_editable_populated.html")); |
| |
| web_view->GetSettings()->SetDefaultFontSize(12); |
| web_view->Resize(WebSize(400, 400)); |
| WebLocalFrameImpl* frame = |
| static_cast<WebLocalFrameImpl*>(web_view->MainFrame()); |
| |
| gfx::Point baseline_point; |
| NSAttributedString* result = SubstringUtil::AttributedSubstringInRange( |
| frame->GetFrame(), 10, 3, &baseline_point); |
| ASSERT_TRUE(!!result); |
| |
| gfx::Point point(baseline_point); |
| result = SubstringUtil::AttributedWordAtPoint(frame->FrameWidgetImpl(), point, |
| baseline_point); |
| ASSERT_TRUE(!!result); |
| |
| web_view->SetZoomLevel(3); |
| |
| result = SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 5, 5, |
| &baseline_point); |
| ASSERT_TRUE(!!result); |
| |
| point = baseline_point; |
| result = SubstringUtil::AttributedWordAtPoint(frame->FrameWidgetImpl(), point, |
| baseline_point); |
| ASSERT_TRUE(!!result); |
| } |
| |
| TEST_F(SubStringUtilTest, SubstringUtilBaselinePoint) { |
| RegisterMockedHttpURLLoad("content_editable_multiline.html"); |
| WebView* web_view = static_cast<WebView*>(web_view_helper_.InitializeAndLoad( |
| base_url_ + "content_editable_multiline.html")); |
| web_view->GetSettings()->SetDefaultFontSize(12); |
| web_view->Resize(WebSize(400, 400)); |
| WebLocalFrameImpl* frame = |
| static_cast<WebLocalFrameImpl*>(web_view->MainFrame()); |
| |
| gfx::Point old_point; |
| SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 3, 1, |
| &old_point); |
| |
| gfx::Point new_point; |
| SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 3, 20, |
| &new_point); |
| |
| EXPECT_EQ(old_point.x(), new_point.x()); |
| EXPECT_EQ(old_point.y(), new_point.y()); |
| } |
| |
| TEST_F(SubStringUtilTest, SubstringUtilPinchZoom) { |
| RegisterMockedHttpURLLoad("content_editable_populated.html"); |
| WebView* web_view = static_cast<WebView*>(web_view_helper_.InitializeAndLoad( |
| base_url_ + "content_editable_populated.html")); |
| web_view->GetSettings()->SetDefaultFontSize(12); |
| web_view->Resize(WebSize(400, 400)); |
| WebLocalFrameImpl* frame = |
| static_cast<WebLocalFrameImpl*>(web_view->MainFrame()); |
| NSAttributedString* result = nil; |
| |
| gfx::Point baseline_point; |
| result = SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 10, 3, |
| &baseline_point); |
| ASSERT_TRUE(!!result); |
| |
| web_view->SetPageScaleFactor(3); |
| |
| gfx::Point point_after_zoom; |
| result = SubstringUtil::AttributedSubstringInRange(frame->GetFrame(), 10, 3, |
| &point_after_zoom); |
| ASSERT_TRUE(!!result); |
| |
| // We won't have moved by a full factor of 3 because of the translations, but |
| // we should move by a factor of >2. |
| EXPECT_LT(2 * baseline_point.x(), point_after_zoom.x()); |
| EXPECT_LT(2 * baseline_point.y(), point_after_zoom.y()); |
| } |
| |
| TEST_F(SubStringUtilTest, SubstringUtilIframe) { |
| RegisterMockedHttpURLLoad("single_iframe.html"); |
| RegisterMockedHttpURLLoad("visible_iframe.html"); |
| WebView* web_view = static_cast<WebView*>( |
| web_view_helper_.InitializeAndLoad(base_url_ + "single_iframe.html")); |
| web_view->GetSettings()->SetDefaultFontSize(12); |
| web_view->GetSettings()->SetJavaScriptEnabled(true); |
| web_view->Resize(WebSize(400, 400)); |
| WebLocalFrameImpl* main_frame = |
| static_cast<WebLocalFrameImpl*>(web_view->MainFrame()); |
| WebLocalFrameImpl* child_frame = WebLocalFrameImpl::FromFrame( |
| To<LocalFrame>(main_frame->GetFrame()->Tree().FirstChild())); |
| |
| gfx::Point baseline_point; |
| NSAttributedString* result = SubstringUtil::AttributedSubstringInRange( |
| child_frame->GetFrame(), 11, 7, &baseline_point); |
| ASSERT_NE(result, nullptr); |
| |
| gfx::Point point(baseline_point); |
| result = SubstringUtil::AttributedWordAtPoint(main_frame->FrameWidgetImpl(), |
| point, baseline_point); |
| ASSERT_NE(result, nullptr); |
| |
| int y_before_change = baseline_point.y(); |
| |
| // Now move the <iframe> down by 100px. |
| main_frame->ExecuteScript(WebScriptSource( |
| "document.querySelector('iframe').style.marginTop = '100px';")); |
| |
| point = gfx::Point(point.x(), point.y() + 100); |
| result = SubstringUtil::AttributedWordAtPoint(main_frame->FrameWidgetImpl(), |
| point, baseline_point); |
| ASSERT_NE(result, nullptr); |
| |
| EXPECT_EQ(y_before_change, baseline_point.y() - 100); |
| } |
| |
| } // namespace blink |