OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/input/EventHandler.h" | 5 #include "core/input/EventHandler.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include "core/dom/ClientRect.h" | |
9 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
10 #include "core/dom/Range.h" | 9 #include "core/dom/Range.h" |
11 #include "core/editing/Editor.h" | 10 #include "core/editing/Editor.h" |
12 #include "core/editing/FrameSelection.h" | 11 #include "core/editing/FrameSelection.h" |
13 #include "core/frame/FrameView.h" | 12 #include "core/frame/FrameView.h" |
14 #include "core/frame/LocalFrame.h" | 13 #include "core/frame/LocalFrame.h" |
15 #include "core/frame/Settings.h" | 14 #include "core/frame/Settings.h" |
16 #include "core/layout/LayoutBox.h" | |
17 #include "core/loader/EmptyClients.h" | 15 #include "core/loader/EmptyClients.h" |
18 #include "core/page/AutoscrollController.h" | 16 #include "core/page/AutoscrollController.h" |
19 #include "core/page/Page.h" | 17 #include "core/page/Page.h" |
20 #include "core/paint/PaintLayerScrollableArea.h" | |
21 #include "core/testing/DummyPageHolder.h" | 18 #include "core/testing/DummyPageHolder.h" |
22 #include "platform/scroll/MainThreadScrollingReason.h" | |
23 #include "platform/testing/HistogramTester.h" | |
24 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
25 | 20 |
26 #define EXPECT_WHEEL_BUCKET(reason, count) \ | |
27 histogram_tester.ExpectBucketCount( \ | |
28 "Renderer4.MainThreadWheelScrollReason", \ | |
29 GetBucketIndex(MainThreadScrollingReason::reason), count); | |
30 | |
31 #define EXPECT_TOUCH_BUCKET(reason, count) \ | |
32 histogram_tester.ExpectBucketCount( \ | |
33 "Renderer4.MainThreadGestureScrollReason", \ | |
34 GetBucketIndex(MainThreadScrollingReason::reason), count); | |
35 | |
36 #define EXPECT_WHEEL_TOTAL(count) \ | |
37 histogram_tester.ExpectTotalCount("Renderer4.MainThreadWheelScrollReason", \ | |
38 count); | |
39 | |
40 #define EXPECT_TOUCH_TOTAL(count) \ | |
41 histogram_tester.ExpectTotalCount("Renderer4.MainThreadGestureScrollReason", \ | |
42 count); | |
43 | |
44 namespace blink { | 21 namespace blink { |
45 | 22 |
46 class EventHandlerTest : public ::testing::Test { | 23 class EventHandlerTest : public ::testing::Test { |
47 protected: | 24 protected: |
48 void SetUp() override; | 25 void SetUp() override; |
49 | 26 |
50 Page& GetPage() const { return dummy_page_holder_->GetPage(); } | 27 Page& GetPage() const { return dummy_page_holder_->GetPage(); } |
51 Document& GetDocument() const { return dummy_page_holder_->GetDocument(); } | 28 Document& GetDocument() const { return dummy_page_holder_->GetDocument(); } |
52 FrameSelection& Selection() const { | 29 FrameSelection& Selection() const { |
53 return GetDocument().GetFrame()->Selection(); | 30 return GetDocument().GetFrame()->Selection(); |
54 } | 31 } |
55 | 32 |
56 void SetHtmlInnerHTML(const char* html_content); | 33 void SetHtmlInnerHTML(const char* html_content); |
57 | 34 |
58 protected: | 35 protected: |
59 std::unique_ptr<DummyPageHolder> dummy_page_holder_; | 36 std::unique_ptr<DummyPageHolder> dummy_page_holder_; |
60 }; | 37 }; |
61 | 38 |
62 class NonCompositedMainThreadScrollingReasonRecordTest | |
63 : public EventHandlerTest { | |
64 protected: | |
65 class ScrollBeginEventBuilder : public WebGestureEvent { | |
66 public: | |
67 ScrollBeginEventBuilder(IntPoint position, | |
68 FloatPoint delta, | |
69 WebGestureDevice device) | |
70 : WebGestureEvent() { | |
71 type_ = WebInputEvent::kGestureScrollBegin; | |
72 x = global_x = position.X(); | |
73 y = global_y = position.Y(); | |
74 data.scroll_begin.delta_y_hint = delta.Y(); | |
75 source_device = device; | |
76 frame_scale_ = 1; | |
77 } | |
78 }; | |
79 | |
80 class ScrollUpdateEventBuilder : public WebGestureEvent { | |
81 public: | |
82 ScrollUpdateEventBuilder() : WebGestureEvent() { | |
83 type_ = WebInputEvent::kGestureScrollUpdate; | |
84 data.scroll_update.delta_x = 0.0f; | |
85 data.scroll_update.delta_y = 1.0f; | |
86 data.scroll_update.velocity_x = 0; | |
87 data.scroll_update.velocity_y = 1; | |
88 frame_scale_ = 1; | |
89 } | |
90 }; | |
91 | |
92 class ScrollEndEventBuilder : public WebGestureEvent { | |
93 public: | |
94 ScrollEndEventBuilder() : WebGestureEvent() { | |
95 type_ = WebInputEvent::kGestureScrollEnd; | |
96 frame_scale_ = 1; | |
97 } | |
98 }; | |
99 | |
100 int GetBucketIndex(uint32_t reason); | |
101 void Scroll(Element*, const WebGestureDevice); | |
102 }; | |
103 | |
104 class TapEventBuilder : public WebGestureEvent { | 39 class TapEventBuilder : public WebGestureEvent { |
105 public: | 40 public: |
106 TapEventBuilder(IntPoint position, int tap_count) | 41 TapEventBuilder(IntPoint position, int tap_count) |
107 : WebGestureEvent(WebInputEvent::kGestureTap, | 42 : WebGestureEvent(WebInputEvent::kGestureTap, |
108 WebInputEvent::kNoModifiers, | 43 WebInputEvent::kNoModifiers, |
109 TimeTicks::Now().InSeconds()) { | 44 TimeTicks::Now().InSeconds()) { |
110 x = global_x = position.X(); | 45 x = global_x = position.X(); |
111 y = global_y = position.Y(); | 46 y = global_y = position.Y(); |
112 source_device = kWebGestureDeviceTouchscreen; | 47 source_device = kWebGestureDeviceTouchscreen; |
113 data.tap.tap_count = tap_count; | 48 data.tap.tap_count = tap_count; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 | 83 |
149 void EventHandlerTest::SetUp() { | 84 void EventHandlerTest::SetUp() { |
150 dummy_page_holder_ = DummyPageHolder::Create(IntSize(300, 400)); | 85 dummy_page_holder_ = DummyPageHolder::Create(IntSize(300, 400)); |
151 } | 86 } |
152 | 87 |
153 void EventHandlerTest::SetHtmlInnerHTML(const char* html_content) { | 88 void EventHandlerTest::SetHtmlInnerHTML(const char* html_content) { |
154 GetDocument().documentElement()->setInnerHTML(String::FromUTF8(html_content)); | 89 GetDocument().documentElement()->setInnerHTML(String::FromUTF8(html_content)); |
155 GetDocument().View()->UpdateAllLifecyclePhases(); | 90 GetDocument().View()->UpdateAllLifecyclePhases(); |
156 } | 91 } |
157 | 92 |
158 int NonCompositedMainThreadScrollingReasonRecordTest::GetBucketIndex( | |
159 uint32_t reason) { | |
160 int index = 1; | |
161 while (!(reason & 1)) { | |
162 reason >>= 1; | |
163 ++index; | |
164 } | |
165 DCHECK_EQ(reason, 1u); | |
166 return index; | |
167 } | |
168 | |
169 void NonCompositedMainThreadScrollingReasonRecordTest::Scroll( | |
170 Element* element, | |
171 const WebGestureDevice device) { | |
172 DCHECK(element); | |
173 DCHECK(element->getBoundingClientRect()); | |
174 ClientRect* rect = element->getBoundingClientRect(); | |
175 ScrollBeginEventBuilder scroll_begin( | |
176 IntPoint(rect->left() + rect->width() / 2, | |
177 rect->top() + rect->height() / 2), | |
178 FloatPoint(0.f, 1.f), device); | |
179 ScrollUpdateEventBuilder scroll_update; | |
180 ScrollEndEventBuilder scroll_end; | |
181 GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(scroll_begin); | |
182 GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(scroll_update); | |
183 GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(scroll_end); | |
184 } | |
185 | |
186 TEST_F(EventHandlerTest, dragSelectionAfterScroll) { | 93 TEST_F(EventHandlerTest, dragSelectionAfterScroll) { |
187 SetHtmlInnerHTML( | 94 SetHtmlInnerHTML( |
188 "<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }" | 95 "<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }" |
189 ".lower { margin: 0px; width: 300px; height: 400px; } .line { display: " | 96 ".lower { margin: 0px; width: 300px; height: 400px; } .line { display: " |
190 "block; width: 300px; height: 30px; } </style>" | 97 "block; width: 300px; height: 30px; } </style>" |
191 "<div class='upper'></div>" | 98 "<div class='upper'></div>" |
192 "<div class='lower'>" | 99 "<div class='lower'>" |
193 "<span class='line'>Line 1</span><span class='line'>Line 2</span><span " | 100 "<span class='line'>Line 1</span><span class='line'>Line 2</span><span " |
194 "class='line'>Line 3</span><span class='line'>Line 4</span><span " | 101 "class='line'>Line 3</span><span class='line'>Line 4</span><span " |
195 "class='line'>Line 5</span>" | 102 "class='line'>Line 5</span>" |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 WebInputEvent::kMouseLeave, WebFloatPoint(0, 0), WebFloatPoint(0, 0), | 541 WebInputEvent::kMouseLeave, WebFloatPoint(0, 0), WebFloatPoint(0, 0), |
635 WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers, | 542 WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers, |
636 TimeTicks::Now().InSeconds()); | 543 TimeTicks::Now().InSeconds()); |
637 mouse_leave_event.SetFrameScale(1); | 544 mouse_leave_event.SetFrameScale(1); |
638 GetDocument().GetFrame()->GetEventHandler().HandleMouseLeaveEvent( | 545 GetDocument().GetFrame()->GetEventHandler().HandleMouseLeaveEvent( |
639 mouse_leave_event); | 546 mouse_leave_event); |
640 | 547 |
641 EXPECT_EQ(WTF::String(), LastToolTip()); | 548 EXPECT_EQ(WTF::String(), LastToolTip()); |
642 } | 549 } |
643 | 550 |
644 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, | |
645 TouchAndWheelGeneralTest) { | |
646 SetHtmlInnerHTML( | |
647 "<style>" | |
648 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
649 " .translucent { opacity: 0.5; }" | |
650 " .spacer { height: 1000px; }" | |
651 "</style>" | |
652 "<div id='box' class='translucent box'>" | |
653 " <div class='spacer'></div>" | |
654 "</div>"); | |
655 | |
656 GetDocument().View()->UpdateAllLifecyclePhases(); | |
657 | |
658 Element* box = GetDocument().getElementById("box"); | |
659 HistogramTester histogram_tester; | |
660 | |
661 // Test touch scroll. | |
662 Scroll(box, kWebGestureDeviceTouchscreen); | |
663 EXPECT_TOUCH_BUCKET(kHasOpacityAndLCDText, 1); | |
664 EXPECT_TOUCH_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
665 | |
666 Scroll(box, kWebGestureDeviceTouchscreen); | |
667 EXPECT_TOUCH_BUCKET(kHasOpacityAndLCDText, 2); | |
668 EXPECT_TOUCH_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 2); | |
669 EXPECT_TOUCH_TOTAL(4); | |
670 | |
671 // Test wheel scroll. | |
672 Scroll(box, kWebGestureDeviceTouchpad); | |
673 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
674 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
675 EXPECT_WHEEL_TOTAL(2); | |
676 } | |
677 | |
678 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, | |
679 CompositedScrollableAreaTest) { | |
680 SetHtmlInnerHTML( | |
681 "<style>" | |
682 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
683 " .translucent { opacity: 0.5; }" | |
684 " .composited { will-change: transform; }" | |
685 " .spacer { height: 1000px; }" | |
686 "</style>" | |
687 "<div id='box' class='translucent box'>" | |
688 " <div class='spacer'></div>" | |
689 "</div>"); | |
690 | |
691 GetPage().GetSettings().SetAcceleratedCompositingEnabled(true); | |
692 GetDocument().View()->SetParentVisible(true); | |
693 GetDocument().View()->SetSelfVisible(true); | |
694 GetDocument().View()->UpdateAllLifecyclePhases(); | |
695 | |
696 Element* box = GetDocument().getElementById("box"); | |
697 HistogramTester histogram_tester; | |
698 | |
699 Scroll(box, kWebGestureDeviceTouchpad); | |
700 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
701 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
702 EXPECT_WHEEL_TOTAL(2); | |
703 | |
704 box->setAttribute("class", "composited translucent box"); | |
705 GetDocument().View()->UpdateAllLifecyclePhases(); | |
706 Scroll(box, kWebGestureDeviceTouchpad); | |
707 EXPECT_FALSE(ToLayoutBox(box->GetLayoutObject()) | |
708 ->GetScrollableArea() | |
709 ->GetNonCompositedMainThreadScrollingReasons()); | |
710 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
711 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
712 EXPECT_WHEEL_TOTAL(2); | |
713 } | |
714 | |
715 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, | |
716 NotScrollableAreaTest) { | |
717 SetHtmlInnerHTML( | |
718 "<style>.box { overflow:scroll; width: 100px; height: 100px; }" | |
719 " .translucent { opacity: 0.5; }" | |
720 " .hidden { overflow: hidden; }" | |
721 " .spacer { height: 1000px; }" | |
722 "</style>" | |
723 "<div id='box' class='translucent box'>" | |
724 " <div class='spacer'></div>" | |
725 "</div>"); | |
726 | |
727 GetDocument().View()->UpdateAllLifecyclePhases(); | |
728 | |
729 Element* box = GetDocument().getElementById("box"); | |
730 HistogramTester histogram_tester; | |
731 | |
732 Scroll(box, kWebGestureDeviceTouchpad); | |
733 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
734 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
735 EXPECT_WHEEL_TOTAL(2); | |
736 | |
737 box->setAttribute("class", "hidden translucent box"); | |
738 GetDocument().View()->UpdateAllLifecyclePhases(); | |
739 Scroll(box, kWebGestureDeviceTouchpad); | |
740 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
741 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
742 EXPECT_WHEEL_TOTAL(2); | |
743 } | |
744 | |
745 TEST_F(NonCompositedMainThreadScrollingReasonRecordTest, NestedScrollersTest) { | |
746 SetHtmlInnerHTML( | |
747 "<style>" | |
748 " .container { overflow:scroll; width: 200px; height: 200px; }" | |
749 " .box { overflow:scroll; width: 100px; height: 100px; }" | |
750 " .translucent { opacity: 0.5; }" | |
751 " .transform { transform: scale(0.8); }" | |
752 " .with-border-radius { border: 5px solid; border-radius: 5px; }" | |
753 " .spacer { height: 1000px; }" | |
754 " .composited { will-change: transform; }" | |
755 "</style>" | |
756 "<div id='container' class='container with-border-radius'>" | |
757 " <div class='translucent box'>" | |
758 " <div id='inner' class='composited transform box'>" | |
759 " <div class='spacer'></div>" | |
760 " </div>" | |
761 " </div>" | |
762 " <div class='spacer'></div>" | |
763 "</div>"); | |
764 | |
765 GetPage().GetSettings().SetAcceleratedCompositingEnabled(true); | |
766 GetDocument().View()->SetParentVisible(true); | |
767 GetDocument().View()->SetSelfVisible(true); | |
768 GetDocument().View()->UpdateAllLifecyclePhases(); | |
769 | |
770 Element* box = GetDocument().getElementById("inner"); | |
771 HistogramTester histogram_tester; | |
772 | |
773 Scroll(box, kWebGestureDeviceTouchpad); | |
774 // Scrolling the inner box will gather reasons from the scrolling chain. The | |
775 // inner box itself has no reason because it's composited. Other scrollable | |
776 // areas from the chain have corresponding reasons. | |
777 EXPECT_WHEEL_BUCKET(kHasOpacityAndLCDText, 1); | |
778 EXPECT_WHEEL_BUCKET(kBackgroundNotOpaqueInRectAndLCDText, 1); | |
779 EXPECT_WHEEL_BUCKET(kHasBorderRadius, 1); | |
780 EXPECT_WHEEL_BUCKET(kHasTransformAndLCDText, 0); | |
781 EXPECT_WHEEL_TOTAL(3); | |
782 } | |
783 | |
784 } // namespace blink | 551 } // namespace blink |
OLD | NEW |