cc: Make picture pile base thread safe.
[chromium-blink-merge.git] / content / browser / web_contents / touch_editable_impl_aura_browsertest.cc
bloba35f28165b3f3bb03f23e7cafbb5cdab9012117b
1 // Copyright (c) 2012 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.
5 #include "content/browser/web_contents/touch_editable_impl_aura.h"
7 #include "base/command_line.h"
8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/test_timeouts.h"
11 #include "base/values.h"
12 #include "content/browser/web_contents/web_contents_impl.h"
13 #include "content/browser/web_contents/web_contents_view_aura.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/common/content_switches.h"
16 #include "content/public/test/browser_test_utils.h"
17 #include "content/public/test/content_browser_test.h"
18 #include "content/public/test/content_browser_test_utils.h"
19 #include "content/public/test/test_utils.h"
20 #include "content/shell/browser/shell.h"
21 #include "third_party/WebKit/public/web/WebInputEvent.h"
22 #include "ui/aura/window.h"
23 #include "ui/aura/window_tree_host.h"
24 #include "ui/base/ui_base_switches.h"
25 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
26 #include "ui/events/event_utils.h"
27 #include "ui/events/test/event_generator.h"
29 using blink::WebInputEvent;
31 namespace content {
33 class TestTouchEditableImplAura : public TouchEditableImplAura {
34 public:
35 TestTouchEditableImplAura()
36 : selection_changed_callback_arrived_(false),
37 waiting_for_selection_changed_callback_(false),
38 waiting_for_gesture_ack_type_(WebInputEvent::Undefined),
39 last_gesture_ack_type_(WebInputEvent::Undefined),
40 fling_stop_callback_arrived_(false),
41 waiting_for_fling_stop_callback_(false) {}
43 virtual void Reset() {
44 selection_changed_callback_arrived_ = false;
45 waiting_for_selection_changed_callback_ = false;
46 waiting_for_gesture_ack_type_ = WebInputEvent::Undefined;
47 last_gesture_ack_type_ = WebInputEvent::Undefined;
48 fling_stop_callback_arrived_ = false;
49 waiting_for_fling_stop_callback_ = false;
52 virtual void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
53 const gfx::Rect& focus) override {
54 selection_changed_callback_arrived_ = true;
55 TouchEditableImplAura::OnSelectionOrCursorChanged(anchor, focus);
56 if (waiting_for_selection_changed_callback_)
57 selection_changed_wait_run_loop_->Quit();
60 virtual void GestureEventAck(int gesture_event_type) override {
61 last_gesture_ack_type_ =
62 static_cast<WebInputEvent::Type>(gesture_event_type);
63 TouchEditableImplAura::GestureEventAck(gesture_event_type);
64 if (waiting_for_gesture_ack_type_ == gesture_event_type)
65 gesture_ack_wait_run_loop_->Quit();
68 virtual void DidStopFlinging() override {
69 fling_stop_callback_arrived_ = true;
70 TouchEditableImplAura::DidStopFlinging();
71 if (waiting_for_fling_stop_callback_)
72 fling_stop_wait_run_loop_->Quit();
75 virtual void WaitForSelectionChangeCallback() {
76 if (selection_changed_callback_arrived_)
77 return;
78 waiting_for_selection_changed_callback_ = true;
79 selection_changed_wait_run_loop_.reset(new base::RunLoop());
80 selection_changed_wait_run_loop_->Run();
83 virtual void WaitForGestureAck(WebInputEvent::Type gesture_event_type) {
84 if (last_gesture_ack_type_ == gesture_event_type)
85 return;
86 waiting_for_gesture_ack_type_ = gesture_event_type;
87 gesture_ack_wait_run_loop_.reset(new base::RunLoop());
88 gesture_ack_wait_run_loop_->Run();
91 virtual void WaitForFlingStopCallback() {
92 if (fling_stop_callback_arrived_)
93 return;
94 waiting_for_fling_stop_callback_ = true;
95 fling_stop_wait_run_loop_.reset(new base::RunLoop());
96 fling_stop_wait_run_loop_->Run();
99 protected:
100 virtual ~TestTouchEditableImplAura() {}
102 private:
103 bool selection_changed_callback_arrived_;
104 bool waiting_for_selection_changed_callback_;
105 WebInputEvent::Type waiting_for_gesture_ack_type_;
106 WebInputEvent::Type last_gesture_ack_type_;
107 bool fling_stop_callback_arrived_;
108 bool waiting_for_fling_stop_callback_;
109 scoped_ptr<base::RunLoop> selection_changed_wait_run_loop_;
110 scoped_ptr<base::RunLoop> gesture_ack_wait_run_loop_;
111 scoped_ptr<base::RunLoop> fling_stop_wait_run_loop_;
113 DISALLOW_COPY_AND_ASSIGN(TestTouchEditableImplAura);
116 class TouchEditableImplAuraTest : public ContentBrowserTest {
117 public:
118 TouchEditableImplAuraTest() {}
120 protected:
121 virtual void SetUpCommandLine(CommandLine* command_line) override {
122 command_line->AppendSwitch(switches::kEnableTouchEditing);
125 // Executes the javascript synchronously and makes sure the returned value is
126 // freed properly.
127 void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) {
128 scoped_ptr<base::Value> value =
129 content::ExecuteScriptAndGetValue(rfh, jscript);
132 // Starts the test server and navigates to the given url. Sets a large enough
133 // size to the root window. Returns after the navigation to the url is
134 // complete.
135 void StartTestWithPage(const std::string& url) {
136 ASSERT_TRUE(test_server()->Start());
137 GURL test_url(test_server()->GetURL(url));
138 NavigateToURL(shell(), test_url);
139 aura::Window* content = shell()->web_contents()->GetContentNativeView();
140 content->GetHost()->SetBounds(gfx::Rect(800, 600));
143 RenderWidgetHostViewAura* GetRenderWidgetHostViewAura(
144 TouchEditableImplAura* touch_editable) {
145 return touch_editable->rwhva_;
148 ui::TouchSelectionController* GetTouchSelectionController(
149 TouchEditableImplAura* touch_editable) {
150 return touch_editable->touch_selection_controller_.get();
153 ui::TextInputType GetTextInputType(TouchEditableImplAura* touch_editable) {
154 return touch_editable->text_input_type_;
157 private:
158 DISALLOW_COPY_AND_ASSIGN(TouchEditableImplAuraTest);
161 IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
162 TouchSelectionOriginatingFromWebpageTest) {
163 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
164 WebContentsImpl* web_contents =
165 static_cast<WebContentsImpl*>(shell()->web_contents());
166 RenderFrameHost* main_frame = web_contents->GetMainFrame();
167 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
168 web_contents->GetView());
169 TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
170 view_aura->SetTouchEditableForTest(touch_editable);
171 RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
172 web_contents->GetRenderWidgetHostView());
173 aura::Window* content = web_contents->GetContentNativeView();
174 ui::test::EventGenerator generator(content->GetRootWindow(), content);
175 gfx::Rect bounds = content->GetBoundsInRootWindow();
177 touch_editable->Reset();
178 ExecuteSyncJSFunction(main_frame, "select_all_text()");
179 touch_editable->WaitForSelectionChangeCallback();
181 // Tap inside selection to bring up selection handles.
182 generator.GestureTapAt(gfx::Point(bounds.x() + 10, bounds.y() + 10));
183 EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
185 scoped_ptr<base::Value> value =
186 content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
187 std::string selection;
188 value->GetAsString(&selection);
190 // Check if selection handles are showing.
191 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
192 EXPECT_STREQ("Some text we can select", selection.c_str());
194 // Lets move the handles a bit to modify the selection
195 touch_editable->Reset();
196 generator.GestureScrollSequence(
197 gfx::Point(10, 47),
198 gfx::Point(30, 47),
199 base::TimeDelta::FromMilliseconds(20),
201 touch_editable->WaitForSelectionChangeCallback();
203 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
204 value = content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
205 value->GetAsString(&selection);
207 // It is hard to tell what exactly the selection would be now. But it would
208 // definitely be less than whatever was selected before.
209 EXPECT_GT(std::strlen("Some text we can select"), selection.size());
212 IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
213 TestTouchSelectionHiddenWhenScrolling) {
214 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
215 WebContentsImpl* web_contents =
216 static_cast<WebContentsImpl*>(shell()->web_contents());
217 RenderFrameHost* main_frame = web_contents->GetMainFrame();
218 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
219 web_contents->GetView());
220 TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
221 view_aura->SetTouchEditableForTest(touch_editable);
222 RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
223 web_contents->GetRenderWidgetHostView());
224 EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
226 // Long press to select word.
227 ui::GestureEvent long_press(
231 ui::EventTimeForNow(),
232 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
233 touch_editable->Reset();
234 rwhva->OnGestureEvent(&long_press);
235 touch_editable->WaitForSelectionChangeCallback();
237 // Check if selection handles are showing.
238 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
240 scoped_ptr<base::Value> value =
241 content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
242 std::string selection;
243 value->GetAsString(&selection);
244 EXPECT_STREQ("Some", selection.c_str());
246 // Start scrolling. Handles should get hidden.
247 ui::GestureEvent scroll_begin(
251 ui::EventTimeForNow(),
252 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
253 rwhva->OnGestureEvent(&scroll_begin);
254 EXPECT_FALSE(GetTouchSelectionController(touch_editable));
256 // Handles should come back after scroll ends.
257 ui::GestureEvent scroll_end(
261 ui::EventTimeForNow(),
262 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
263 rwhva->OnGestureEvent(&scroll_end);
264 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
267 IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
268 TestTouchSelectionReshownAfterFling) {
269 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
270 WebContentsImpl* web_contents =
271 static_cast<WebContentsImpl*>(shell()->web_contents());
272 RenderFrameHost* main_frame = web_contents->GetMainFrame();
273 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
274 web_contents->GetView());
275 TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
276 view_aura->SetTouchEditableForTest(touch_editable);
277 RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
278 web_contents->GetRenderWidgetHostView());
279 EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
281 // Long press to select word.
282 ui::GestureEvent long_press(
286 ui::EventTimeForNow(),
287 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
288 touch_editable->Reset();
289 rwhva->OnGestureEvent(&long_press);
290 touch_editable->WaitForSelectionChangeCallback();
292 // Check if selection handles are showing.
293 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
295 scoped_ptr<base::Value> value =
296 content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
297 std::string selection;
298 value->GetAsString(&selection);
299 EXPECT_STREQ("Some", selection.c_str());
301 // Start scrolling. Handles should get hidden.
302 ui::GestureEvent scroll_begin(
306 ui::EventTimeForNow(),
307 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0));
308 rwhva->OnGestureEvent(&scroll_begin);
309 EXPECT_FALSE(GetTouchSelectionController(touch_editable));
311 // Start a fling. Handles should come back after fling stops.
312 ui::GestureEvent fling_start(
316 ui::EventTimeForNow(),
317 ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 1, 0));
318 rwhva->OnGestureEvent(&fling_start);
319 touch_editable->WaitForFlingStopCallback();
320 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
323 IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
324 TouchSelectionOnLongPressTest) {
325 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
326 WebContentsImpl* web_contents =
327 static_cast<WebContentsImpl*>(shell()->web_contents());
328 RenderFrameHost* main_frame = web_contents->GetMainFrame();
329 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
330 web_contents->GetView());
331 TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
332 view_aura->SetTouchEditableForTest(touch_editable);
333 RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
334 web_contents->GetRenderWidgetHostView());
335 EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
337 // Long press to select word.
338 ui::GestureEvent long_press(
342 ui::EventTimeForNow(),
343 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
344 touch_editable->Reset();
345 rwhva->OnGestureEvent(&long_press);
346 touch_editable->WaitForSelectionChangeCallback();
348 // Check if selection handles are showing.
349 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
351 scoped_ptr<base::Value> value =
352 content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
353 std::string selection;
354 value->GetAsString(&selection);
355 EXPECT_STREQ("Some", selection.c_str());
358 IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
359 NoTouchSelectionOnDoubleTapTest) {
360 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
361 WebContentsImpl* web_contents =
362 static_cast<WebContentsImpl*>(shell()->web_contents());
363 RenderFrameHost* main_frame = web_contents->GetMainFrame();
364 WebContentsViewAura* view_aura =
365 static_cast<WebContentsViewAura*>(web_contents->GetView());
366 TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
367 view_aura->SetTouchEditableForTest(touch_editable);
368 RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
369 web_contents->GetRenderWidgetHostView());
370 EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
372 // Double-tap to select word.
373 ui::GestureEventDetails details(ui::ET_GESTURE_TAP);
374 details.set_tap_count(2);
375 ui::GestureEvent double_tap(10, 10, 0, ui::EventTimeForNow(), details);
376 touch_editable->Reset();
377 rwhva->OnGestureEvent(&double_tap);
378 touch_editable->WaitForSelectionChangeCallback();
380 // Make sure touch selection handles are not showing.
381 EXPECT_FALSE(GetTouchSelectionController(touch_editable));
383 scoped_ptr<base::Value> value =
384 content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
385 std::string selection;
386 value->GetAsString(&selection);
387 EXPECT_STREQ("Some", selection.c_str());
390 #if defined(OS_CHROMEOS)
391 // http://crbug.com/396509
392 #define MAYBE_TouchCursorInTextfieldTest DISABLED_TouchCursorInTextfieldTest
393 #else
394 #define MAYBE_TouchCursorInTextfieldTest TouchCursorInTextfieldTest
395 #endif
396 IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
397 MAYBE_TouchCursorInTextfieldTest) {
398 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
399 WebContentsImpl* web_contents =
400 static_cast<WebContentsImpl*>(shell()->web_contents());
401 RenderFrameHost* main_frame = web_contents->GetMainFrame();
402 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
403 web_contents->GetView());
404 TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
405 view_aura->SetTouchEditableForTest(touch_editable);
406 RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
407 web_contents->GetRenderWidgetHostView());
408 aura::Window* content = web_contents->GetContentNativeView();
409 ui::test::EventGenerator generator(content->GetRootWindow(), content);
410 gfx::Rect bounds = content->GetBoundsInRootWindow();
411 EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
413 ExecuteSyncJSFunction(main_frame, "focus_textfield()");
414 touch_editable->WaitForSelectionChangeCallback();
416 // Tap textfield
417 touch_editable->Reset();
418 generator.GestureTapAt(gfx::Point(bounds.x() + 50, bounds.y() + 40));
419 // Tap Down acks are sent synchronously, while Tap acks are asynchronous.
420 touch_editable->WaitForGestureAck(WebInputEvent::GestureTap);
421 touch_editable->WaitForSelectionChangeCallback();
422 touch_editable->Reset();
424 // Check if cursor handle is showing.
425 EXPECT_NE(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType(touch_editable));
426 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
428 scoped_ptr<base::Value> value =
429 content::ExecuteScriptAndGetValue(main_frame, "get_cursor_position()");
430 int cursor_pos = -1;
431 value->GetAsInteger(&cursor_pos);
432 EXPECT_NE(-1, cursor_pos);
434 // Move the cursor handle.
435 generator.GestureScrollSequence(
436 gfx::Point(50, 59),
437 gfx::Point(10, 59),
438 base::TimeDelta::FromMilliseconds(20),
440 touch_editable->WaitForSelectionChangeCallback();
441 EXPECT_TRUE(GetTouchSelectionController(touch_editable));
442 value = content::ExecuteScriptAndGetValue(main_frame,
443 "get_cursor_position()");
444 int new_cursor_pos = -1;
445 value->GetAsInteger(&new_cursor_pos);
446 EXPECT_NE(-1, new_cursor_pos);
447 // Cursor should have moved.
448 EXPECT_NE(new_cursor_pos, cursor_pos);
451 } // namespace content