|  | // Copyright 2019 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 "base/command_line.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/run_loop.h" | 
|  | #include "base/test/scoped_feature_list.h" | 
|  | #include "base/threading/thread_task_runner_handle.h" | 
|  | #include "build/chromeos_buildflags.h" | 
|  | #include "cc/base/switches.h" | 
|  | #include "chrome/browser/ui/browser.h" | 
|  | #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
|  | #include "chrome/test/base/in_process_browser_test.h" | 
|  | #include "chrome/test/base/ui_test_utils.h" | 
|  | #include "content/public/browser/render_widget_host.h" | 
|  | #include "content/public/browser/render_widget_host_view.h" | 
|  | #include "content/public/browser/web_contents.h" | 
|  | #include "content/public/common/content_features.h" | 
|  | #include "content/public/common/content_switches.h" | 
|  | #include "content/public/test/browser_test.h" | 
|  | #include "content/public/test/browser_test_utils.h" | 
|  | #include "net/dns/mock_host_resolver.h" | 
|  | #include "third_party/blink/public/common/input/web_input_event.h" | 
|  | #include "third_party/blink/public/common/input/web_touch_event.h" | 
|  | #include "ui/display/display_switches.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // This test verifies renderer event injection works. That is, it verifies | 
|  | // a renderer can inject events and that they're received by content. It's in | 
|  | // the Chrome side (not content) so that it can verify events work correctly | 
|  | // when all of Chrome is brought up. This is especially important for ChromeOS, | 
|  | // as content tests do not bring up the ChromeOS window-manager (ash). | 
|  | // | 
|  | // The parameter is how the display is configured, and is only applicable to | 
|  | // ChromeOS. | 
|  | class RendererEventInjectionTest | 
|  | : public InProcessBrowserTest, | 
|  | public ::testing::WithParamInterface<const char*> { | 
|  | public: | 
|  | RendererEventInjectionTest() {} | 
|  | ~RendererEventInjectionTest() override {} | 
|  |  | 
|  | // InProcessBrowserTest: | 
|  | void SetUp() override { | 
|  | scoped_feature_list_.InitAndEnableFeature( | 
|  | features::kSyntheticPointerActions); | 
|  | InProcessBrowserTest::SetUp(); | 
|  | } | 
|  |  | 
|  | void SetUpCommandLine(base::CommandLine* command_line) override { | 
|  | command_line->AppendSwitch(switches::kDisableRendererBackgrounding); | 
|  | command_line->AppendSwitch(cc::switches::kEnableGpuBenchmarking); | 
|  | // kHostWindowBounds is unique to ChromeOS. | 
|  | #if BUILDFLAG(IS_CHROMEOS_ASH) | 
|  | command_line->AppendSwitchASCII(switches::kHostWindowBounds, GetParam()); | 
|  | #endif | 
|  | embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data"); | 
|  | ASSERT_TRUE(embedded_test_server()->Start()); | 
|  | } | 
|  |  | 
|  | void SetUpOnMainThread() override { | 
|  | host_resolver()->AddRule("*", "127.0.0.1"); | 
|  | } | 
|  |  | 
|  | private: | 
|  | base::test::ScopedFeatureList scoped_feature_list_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(RendererEventInjectionTest); | 
|  | }; | 
|  |  | 
|  | // Detects when a touch press is received. | 
|  | class TouchEventObserver | 
|  | : public content::RenderWidgetHost::InputEventObserver { | 
|  | public: | 
|  | TouchEventObserver(const gfx::Point& location, | 
|  | base::RepeatingClosure quit_closure) | 
|  | : expected_location_(location), quit_closure_(std::move(quit_closure)) {} | 
|  | ~TouchEventObserver() override = default; | 
|  |  | 
|  | private: | 
|  | // content::RenderWidgetHost::InputEventObserver: | 
|  | void OnInputEvent(const blink::WebInputEvent& event) override { | 
|  | if (blink::WebInputEvent::IsTouchEventType(event.GetType())) { | 
|  | const blink::WebTouchEvent& web_touch = | 
|  | static_cast<const blink::WebTouchEvent&>(event); | 
|  | if (event.GetType() == blink::WebInputEvent::Type::kTouchStart) { | 
|  | for (unsigned i = 0; i < web_touch.touches_length; i++) { | 
|  | const blink::WebTouchPoint& touch_point = web_touch.touches[i]; | 
|  | const gfx::Point location( | 
|  | static_cast<int>(touch_point.PositionInWidget().x()), | 
|  | static_cast<int>(touch_point.PositionInWidget().y())); | 
|  | if (touch_point.state == blink::WebTouchPoint::State::kStatePressed && | 
|  | location == expected_location_) { | 
|  | quit_closure_.Run(); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | const gfx::Point expected_location_; | 
|  | base::RepeatingClosure quit_closure_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(TouchEventObserver); | 
|  | }; | 
|  |  | 
|  | IN_PROC_BROWSER_TEST_P(RendererEventInjectionTest, TestRootTransform) { | 
|  | content::WebContents* main_contents = | 
|  | browser()->tab_strip_model()->GetActiveWebContents(); | 
|  | GURL url = embedded_test_server()->GetURL("/title1.html"); | 
|  | ui_test_utils::NavigateToURL(browser(), url); | 
|  | base::RunLoop run_loop; | 
|  | content::RenderWidgetHost* rwh = | 
|  | main_contents->GetRenderWidgetHostView()->GetRenderWidgetHost(); | 
|  | TouchEventObserver touch_observer(gfx::Point(100, 150), | 
|  | run_loop.QuitClosure()); | 
|  | rwh->AddInputEventObserver(&touch_observer); | 
|  | EXPECT_TRUE(ExecJs(main_contents, | 
|  | "chrome.gpuBenchmarking.tap(100, 150, ()=>{}, " | 
|  | "50, chrome.gpuBenchmarking.TOUCH_INPUT);")); | 
|  | run_loop.Run(); | 
|  | rwh->RemoveInputEventObserver(&touch_observer); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(IS_CHROMEOS_ASH) | 
|  | // This configures the display in various interesting ways for ChromeOS. In | 
|  | // particular, it tests rotation "/r" and a scale factor of 2 "*2". | 
|  | INSTANTIATE_TEST_SUITE_P( | 
|  | All, | 
|  | RendererEventInjectionTest, | 
|  | ::testing::Values("1200x800", "1200x800/r", "1200x800*2", "1200x800*2/r")); | 
|  | #else | 
|  | INSTANTIATE_TEST_SUITE_P(All, | 
|  | RendererEventInjectionTest, | 
|  | ::testing::Values("")); | 
|  | #endif | 
|  |  | 
|  | }  // namespace |