1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/test/metrics/histogram_tester.h"
6 #include "content/browser/renderer_host/render_widget_host_impl.h"
7 #include "content/public/browser/render_view_host.h"
8 #include "content/public/test/content_browser_test.h"
9 #include "content/public/test/content_browser_test_utils.h"
10 #include "content/public/test/hit_test_region_observer.h"
11 #include "content/shell/browser/shell.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/aura/window.h"
15 #include "ui/aura/window_tree_host.h"
16 #include "ui/events/test/event_generator.h"
17 
18 namespace content {
19 
20 class EventLatencyBrowserTest : public ContentBrowserTest {
21  public:
22   EventLatencyBrowserTest() = default;
23   ~EventLatencyBrowserTest() override = default;
24 
25   EventLatencyBrowserTest(const EventLatencyBrowserTest&) = delete;
26   EventLatencyBrowserTest& operator=(const EventLatencyBrowserTest&) = delete;
27 
28  protected:
GetWidgetHost()29   RenderWidgetHostImpl* GetWidgetHost() {
30     return RenderWidgetHostImpl::From(
31         shell()->web_contents()->GetRenderViewHost()->GetWidget());
32   }
33 
34   // Starts the test server and navigates to the test page. Returns after the
35   // navigation is complete.
LoadTestPage()36   void LoadTestPage() {
37     ASSERT_TRUE(embedded_test_server()->Start());
38 
39     // Navigate to the test page which has a rAF animation and a main thread
40     // animation running.
41     GURL test_url =
42         embedded_test_server()->GetURL("/event-latency-animation.html");
43     EXPECT_TRUE(NavigateToURL(shell(), test_url));
44 
45     aura::Window* content = shell()->web_contents()->GetContentNativeView();
46     content->GetHost()->SetBoundsInPixels(gfx::Rect(800, 600));
47 
48     RenderWidgetHostImpl* host = GetWidgetHost();
49     HitTestRegionObserver observer(host->GetFrameSinkId());
50 
51     // Wait for the hit test data to be ready.
52     observer.WaitForHitTestData();
53   }
54 
FocusButton() const55   void FocusButton() const { ASSERT_TRUE(ExecJs(shell(), "focusButton()")); }
56 
StartAnimations() const57   void StartAnimations() const {
58     ASSERT_TRUE(ExecJs(shell(), "startAnimations()"));
59   }
60 };
61 
62 // Tests that if a key-press on a page causes a visual update, appropriate event
63 // latency metrics are reported.
IN_PROC_BROWSER_TEST_F(EventLatencyBrowserTest,KeyPressOnButton)64 IN_PROC_BROWSER_TEST_F(EventLatencyBrowserTest, KeyPressOnButton) {
65   base::HistogramTester histogram_tester;
66 
67   ASSERT_NO_FATAL_FAILURE(LoadTestPage());
68   FocusButton();
69 
70   ui::test::EventGenerator generator(shell()
71                                          ->web_contents()
72                                          ->GetRenderWidgetHostView()
73                                          ->GetNativeView()
74                                          ->GetRootWindow());
75 
76   // Press and release the space key. Since the button on the test page is
77   // focused, this should change the visuals of the button and generate a
78   // compositor frame with appropriate event latency metrics.
79   generator.PressKey(ui::VKEY_SPACE, 0);
80   generator.ReleaseKey(ui::VKEY_SPACE, 0);
81   RunUntilInputProcessed(GetWidgetHost());
82 
83   FetchHistogramsFromChildProcesses();
84 
85   base::HistogramTester::CountsMap expected_counts = {
86       {"EventLatency.KeyReleased.TotalLatency", 1},
87   };
88   EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("EventLatency."),
89               testing::ContainerEq(expected_counts));
90 }
91 
92 // Tests that if a key-press on a page with an animation causes a visual update,
93 // appropriate event latency metrics are reported.
IN_PROC_BROWSER_TEST_F(EventLatencyBrowserTest,KeyPressOnButtonWithAnimation)94 IN_PROC_BROWSER_TEST_F(EventLatencyBrowserTest, KeyPressOnButtonWithAnimation) {
95   base::HistogramTester histogram_tester;
96 
97   ASSERT_NO_FATAL_FAILURE(LoadTestPage());
98   StartAnimations();
99   FocusButton();
100 
101   ui::test::EventGenerator generator(shell()
102                                          ->web_contents()
103                                          ->GetRenderWidgetHostView()
104                                          ->GetNativeView()
105                                          ->GetRootWindow());
106 
107   // Press and release the space key. Since the button on the test page is
108   // focused, this should change the visuals of the button and generate a
109   // compositor frame with appropriate event latency metrics.
110   generator.PressKey(ui::VKEY_SPACE, 0);
111   generator.ReleaseKey(ui::VKEY_SPACE, 0);
112   RunUntilInputProcessed(GetWidgetHost());
113 
114   FetchHistogramsFromChildProcesses();
115 
116   base::HistogramTester::CountsMap expected_counts = {
117       {"EventLatency.KeyReleased.TotalLatency", 1},
118   };
119   EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("EventLatency."),
120               testing::ContainerEq(expected_counts));
121 }
122 
123 }  // namespace content
124