1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/files/file_path.h"
6 #include "base/functional/callback_helpers.h"
7 #include "base/run_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "build/build_config.h"
10 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
11 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/interactive_test_utils.h"
17 #include "chrome/test/base/ui_test_utils.h"
18 #include "components/javascript_dialogs/tab_modal_dialog_manager.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/test/browser_test.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "ui/base/test/ui_controls.h"
27 // Integration test of browser event forwarding and web content event handling.
28 class MouseEventsTest : public InProcessBrowserTest {
30 MouseEventsTest() = default;
32 MouseEventsTest(const MouseEventsTest&) = delete;
33 MouseEventsTest& operator=(const MouseEventsTest&) = delete;
35 // InProcessBrowserTest:
36 void SetUpOnMainThread() override {
37 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
40 content::WebContents* GetActiveWebContents() {
41 return browser()->tab_strip_model()->GetActiveWebContents();
44 // Wait for the active web contents title to match |title|.
45 void WaitForTitle(const std::string& title) {
46 // Logging added temporarily to track down flakiness cited below.
47 LOG(INFO) << "Waiting for title: " << title;
48 const std::u16string expected_title(base::ASCIIToUTF16(title));
49 content::TitleWatcher title_watcher(GetActiveWebContents(), expected_title);
50 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
53 // Load the test page and wait for onmouseover to be called.
54 void NavigateAndWaitForMouseOver() {
55 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
57 // Move the mouse 2px above the web contents; allows onmouseover after load.
58 const gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
59 ui_controls::SendMouseMove(bounds.CenterPoint().x(), bounds.y() - 2);
61 // Navigate to the test page and wait for onload to be called.
62 const GURL url = ui_test_utils::GetTestUrl(
64 base::FilePath(FILE_PATH_LITERAL("mouse_events_test.html")));
65 ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
66 WaitForTitle("onload");
68 // Move the mouse over the div and wait for onmouseover to be called.
69 ui_controls::SendMouseMove(bounds.CenterPoint().x(), bounds.y() + 10);
70 WaitForTitle("onmouseover");
73 // Load the test page and wait for onmouseover then onmouseout to be called.
74 void NavigateAndWaitForMouseOverThenMouseOut() {
75 EXPECT_NO_FATAL_FAILURE(NavigateAndWaitForMouseOver());
77 // Moving the mouse outside the div should trigger onmouseout.
78 const gfx::Rect bounds = GetActiveWebContents()->GetContainerBounds();
79 ui_controls::SendMouseMove(bounds.CenterPoint().x(), bounds.y() - 10);
80 WaitForTitle("onmouseout");
85 // Flaky; http://crbug.com/133361.
86 #define MAYBE_MouseOver DISABLED_MouseOver
88 #define MAYBE_MouseOver MouseOver
91 IN_PROC_BROWSER_TEST_F(MouseEventsTest, MAYBE_MouseOver) {
92 NavigateAndWaitForMouseOver();
96 // Flaky; http://crbug.com/133361.
97 #define MAYBE_ClickAndDoubleClick DISABLED_ClickAndDoubleClick
99 #define MAYBE_ClickAndDoubleClick ClickAndDoubleClick
102 IN_PROC_BROWSER_TEST_F(MouseEventsTest, MAYBE_ClickAndDoubleClick) {
103 NavigateAndWaitForMouseOver();
105 ui_controls::SendMouseClick(ui_controls::LEFT);
106 WaitForTitle("onclick");
108 ui_controls::SendMouseClick(ui_controls::LEFT);
109 WaitForTitle("ondblclick");
112 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
114 // Flaky; http://crbug.com/133361.
115 #define MAYBE_TestOnMouseOut DISABLED_TestOnMouseOut
117 #define MAYBE_TestOnMouseOut TestOnMouseOut
120 IN_PROC_BROWSER_TEST_F(MouseEventsTest, MAYBE_TestOnMouseOut) {
121 NavigateAndWaitForMouseOverThenMouseOut();
124 #if BUILDFLAG(IS_WIN)
125 // Mac/Linux are flaky; http://crbug.com/133361.
126 IN_PROC_BROWSER_TEST_F(MouseEventsTest, MouseDownOnBrowserCaption) {
127 gfx::Rect browser_bounds = browser()->window()->GetBounds();
128 ui_controls::SendMouseMove(browser_bounds.x() + 200, browser_bounds.y() + 10);
129 ui_controls::SendMouseClick(ui_controls::LEFT);
131 NavigateAndWaitForMouseOverThenMouseOut();
135 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_OZONE)
136 // Test that a mouseleave is not triggered when showing the context menu.
137 // If the test is failed, it means that Blink gets the mouseleave event
138 // when showing the context menu and it could make the unexpecting
139 // content behavior such as clearing the hover status.
140 // Please refer to the below issue for understanding what happens .
141 // Flaky; See http://crbug.com/656101.
142 #define MAYBE_ContextMenu DISABLED_ContextMenu
144 #define MAYBE_ContextMenu ContextMenu
147 IN_PROC_BROWSER_TEST_F(MouseEventsTest, MAYBE_ContextMenu) {
148 EXPECT_NO_FATAL_FAILURE(NavigateAndWaitForMouseOver());
150 ContextMenuWaiter menu_observer;
151 ui_controls::SendMouseClick(ui_controls::RIGHT);
152 // Wait until the context menu is opened and closed.
153 menu_observer.WaitForMenuOpenAndClose();
155 content::WebContents* tab = GetActiveWebContents();
156 tab->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(u"done()",
157 base::NullCallback());
158 const std::u16string success_title = u"without mouseleave";
159 const std::u16string failure_title = u"with mouseleave";
160 content::TitleWatcher done_title_watcher(tab, success_title);
161 done_title_watcher.AlsoWaitForTitle(failure_title);
162 EXPECT_EQ(success_title, done_title_watcher.WaitAndGetTitle());
165 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
166 BUILDFLAG(IS_CHROMEOS)
167 // Test that a mouseleave is not triggered when showing a modal dialog.
168 // Sample regression: crbug.com/394672
169 // Flaky; http://crbug.com/838120
170 #define MAYBE_ModalDialog DISABLED_ModalDialog
172 #define MAYBE_ModalDialog ModalDialog
175 IN_PROC_BROWSER_TEST_F(MouseEventsTest, MAYBE_ModalDialog) {
176 EXPECT_NO_FATAL_FAILURE(NavigateAndWaitForMouseOver());
178 content::WebContents* tab = GetActiveWebContents();
179 auto* js_dialog_manager =
180 javascript_dialogs::TabModalDialogManager::FromWebContents(tab);
181 base::RunLoop dialog_wait;
182 js_dialog_manager->SetDialogShownCallbackForTesting(
183 dialog_wait.QuitClosure());
184 tab->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(u"alert()",
185 base::NullCallback());
188 // Cancel the dialog.
189 js_dialog_manager->HandleJavaScriptDialog(tab, false, nullptr);
191 tab->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(u"done()",
192 base::NullCallback());
193 const std::u16string success_title = u"without mouseleave";
194 const std::u16string failure_title = u"with mouseleave";
195 content::TitleWatcher done_title_watcher(tab, success_title);
196 done_title_watcher.AlsoWaitForTitle(failure_title);
197 EXPECT_EQ(success_title, done_title_watcher.WaitAndGetTitle());