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/web_contents_view_aura.h"
7 #include "base/command_line.h"
8 #include "base/location.h"
9 #include "base/run_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/values.h"
16 #include "base/win/windows_version.h"
18 #include "content/browser/frame_host/navigation_controller_impl.h"
19 #include "content/browser/frame_host/navigation_entry_impl.h"
20 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
21 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
22 #include "content/browser/web_contents/web_contents_impl.h"
23 #include "content/browser/web_contents/web_contents_view.h"
24 #include "content/common/input/synthetic_web_input_event_builders.h"
25 #include "content/common/input_messages.h"
26 #include "content/common/view_messages.h"
27 #include "content/public/browser/browser_message_filter.h"
28 #include "content/public/browser/render_frame_host.h"
29 #include "content/public/browser/web_contents_delegate.h"
30 #include "content/public/browser/web_contents_observer.h"
31 #include "content/public/common/content_switches.h"
32 #include "content/public/test/browser_test_utils.h"
33 #include "content/public/test/content_browser_test.h"
34 #include "content/public/test/content_browser_test_utils.h"
35 #include "content/public/test/test_renderer_host.h"
36 #include "content/public/test/test_utils.h"
37 #include "content/shell/browser/shell.h"
38 #include "ui/aura/window.h"
39 #include "ui/aura/window_tree_host.h"
40 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
41 #include "ui/events/event_processor.h"
42 #include "ui/events/event_switches.h"
43 #include "ui/events/event_utils.h"
44 #include "ui/events/test/event_generator.h"
48 // TODO(tdresser): Find a way to avoid sleeping like this. See crbug.com/405282
50 void GiveItSomeTime() {
51 base::RunLoop run_loop
;
52 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
53 FROM_HERE
, run_loop
.QuitClosure(),
54 base::TimeDelta::FromMillisecondsD(10));
58 // WebContentsDelegate which tracks vertical overscroll updates.
59 class VerticalOverscrollTracker
: public content::WebContentsDelegate
{
61 VerticalOverscrollTracker() : count_(0), completed_(false) {}
62 ~VerticalOverscrollTracker() override
{}
64 int num_overscroll_updates() const {
68 bool overscroll_completed() const {
78 bool CanOverscrollContent() const override
{ return true; }
80 void OverscrollUpdate(float delta_y
) override
{ ++count_
; }
82 void OverscrollComplete() override
{ completed_
= true; }
87 DISALLOW_COPY_AND_ASSIGN(VerticalOverscrollTracker
);
95 // This class keeps track of the RenderViewHost whose screenshot was captured.
96 class ScreenshotTracker
: public NavigationEntryScreenshotManager
{
98 explicit ScreenshotTracker(NavigationControllerImpl
* controller
)
99 : NavigationEntryScreenshotManager(controller
),
100 screenshot_taken_for_(NULL
),
101 waiting_for_screenshots_(0) {
104 ~ScreenshotTracker() override
{}
106 RenderViewHost
* screenshot_taken_for() { return screenshot_taken_for_
; }
109 screenshot_taken_for_
= NULL
;
110 screenshot_set_
.clear();
113 void SetScreenshotInterval(int interval_ms
) {
114 SetMinScreenshotIntervalMS(interval_ms
);
117 void WaitUntilScreenshotIsReady() {
118 if (!waiting_for_screenshots_
)
120 message_loop_runner_
= new content::MessageLoopRunner
;
121 message_loop_runner_
->Run();
124 bool ScreenshotSetForEntry(NavigationEntryImpl
* entry
) const {
125 return screenshot_set_
.count(entry
) > 0;
129 // Overridden from NavigationEntryScreenshotManager:
130 void TakeScreenshotImpl(RenderViewHost
* host
,
131 NavigationEntryImpl
* entry
) override
{
132 ++waiting_for_screenshots_
;
133 screenshot_taken_for_
= host
;
134 NavigationEntryScreenshotManager::TakeScreenshotImpl(host
, entry
);
137 void OnScreenshotSet(NavigationEntryImpl
* entry
) override
{
138 --waiting_for_screenshots_
;
139 screenshot_set_
[entry
] = true;
140 NavigationEntryScreenshotManager::OnScreenshotSet(entry
);
141 if (waiting_for_screenshots_
== 0 && message_loop_runner_
.get())
142 message_loop_runner_
->Quit();
145 RenderViewHost
* screenshot_taken_for_
;
146 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
147 int waiting_for_screenshots_
;
148 std::map
<NavigationEntryImpl
*, bool> screenshot_set_
;
150 DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker
);
153 class NavigationWatcher
: public WebContentsObserver
{
155 explicit NavigationWatcher(WebContents
* contents
)
156 : WebContentsObserver(contents
),
158 should_quit_loop_(false) {
161 ~NavigationWatcher() override
{}
163 void WaitUntilNavigationStarts() {
166 should_quit_loop_
= true;
167 base::MessageLoop::current()->Run();
171 // Overridden from WebContentsObserver:
172 void DidStartNavigationToPendingEntry(
173 const GURL
& validated_url
,
174 NavigationController::ReloadType reload_type
) override
{
176 if (should_quit_loop_
)
177 base::MessageLoop::current()->Quit();
181 bool should_quit_loop_
;
183 DISALLOW_COPY_AND_ASSIGN(NavigationWatcher
);
186 class InputEventMessageFilterWaitsForAcks
: public BrowserMessageFilter
{
188 InputEventMessageFilterWaitsForAcks()
189 : BrowserMessageFilter(InputMsgStart
),
190 type_(blink::WebInputEvent::Undefined
),
191 state_(INPUT_EVENT_ACK_STATE_UNKNOWN
) {}
193 void WaitForAck(blink::WebInputEvent::Type type
) {
194 base::RunLoop run_loop
;
195 base::AutoReset
<base::Closure
> reset_quit(&quit_
, run_loop
.QuitClosure());
196 base::AutoReset
<blink::WebInputEvent::Type
> reset_type(&type_
, type
);
200 InputEventAckState
last_ack_state() const { return state_
; }
203 ~InputEventMessageFilterWaitsForAcks() override
{}
206 void ReceivedEventAck(blink::WebInputEvent::Type type
,
207 InputEventAckState state
) {
214 // BrowserMessageFilter:
215 bool OnMessageReceived(const IPC::Message
& message
) override
{
216 if (message
.type() == InputHostMsg_HandleInputEvent_ACK::ID
) {
217 InputHostMsg_HandleInputEvent_ACK::Param params
;
218 InputHostMsg_HandleInputEvent_ACK::Read(&message
, ¶ms
);
219 blink::WebInputEvent::Type type
= base::get
<0>(params
).type
;
220 InputEventAckState ack
= base::get
<0>(params
).state
;
221 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
222 base::Bind(&InputEventMessageFilterWaitsForAcks::ReceivedEventAck
,
229 blink::WebInputEvent::Type type_
;
230 InputEventAckState state_
;
232 DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilterWaitsForAcks
);
235 class WebContentsViewAuraTest
: public ContentBrowserTest
{
237 WebContentsViewAuraTest()
238 : screenshot_manager_(NULL
) {
241 // Executes the javascript synchronously and makes sure the returned value is
243 void ExecuteSyncJSFunction(RenderFrameHost
* rfh
, const std::string
& jscript
) {
244 scoped_ptr
<base::Value
> value
=
245 content::ExecuteScriptAndGetValue(rfh
, jscript
);
248 // Starts the test server and navigates to the given url. Sets a large enough
249 // size to the root window. Returns after the navigation to the url is
251 void StartTestWithPage(const std::string
& url
) {
252 ASSERT_TRUE(test_server()->Start());
253 GURL
test_url(test_server()->GetURL(url
));
254 NavigateToURL(shell(), test_url
);
256 WebContentsImpl
* web_contents
=
257 static_cast<WebContentsImpl
*>(shell()->web_contents());
258 NavigationControllerImpl
* controller
= &web_contents
->GetController();
260 screenshot_manager_
= new ScreenshotTracker(controller
);
261 controller
->SetScreenshotManager(screenshot_manager_
);
264 void SetUpCommandLine(base::CommandLine
* cmd
) override
{
265 cmd
->AppendSwitchASCII(switches::kTouchEvents
,
266 switches::kTouchEventsEnabled
);
269 void TestOverscrollNavigation(bool touch_handler
) {
270 ASSERT_NO_FATAL_FAILURE(
271 StartTestWithPage("files/overscroll_navigation.html"));
272 WebContentsImpl
* web_contents
=
273 static_cast<WebContentsImpl
*>(shell()->web_contents());
274 NavigationController
& controller
= web_contents
->GetController();
275 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
277 EXPECT_FALSE(controller
.CanGoBack());
278 EXPECT_FALSE(controller
.CanGoForward());
280 scoped_ptr
<base::Value
> value
=
281 content::ExecuteScriptAndGetValue(main_frame
, "get_current()");
282 ASSERT_TRUE(value
->GetAsInteger(&index
));
286 ExecuteSyncJSFunction(main_frame
, "install_touch_handler()");
288 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
289 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
290 value
= content::ExecuteScriptAndGetValue(main_frame
, "get_current()");
291 ASSERT_TRUE(value
->GetAsInteger(&index
));
293 EXPECT_TRUE(controller
.CanGoBack());
294 EXPECT_FALSE(controller
.CanGoForward());
296 aura::Window
* content
= web_contents
->GetContentNativeView();
297 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
298 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
299 const int kScrollDurationMs
= 20;
300 const int kScrollSteps
= 10;
303 // Do a swipe-right now. That should navigate backwards.
304 base::string16 expected_title
= base::ASCIIToUTF16("Title: #1");
305 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
306 generator
.GestureScrollSequence(
307 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
308 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
309 base::TimeDelta::FromMilliseconds(kScrollDurationMs
),
311 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
312 EXPECT_EQ(expected_title
, actual_title
);
313 value
= content::ExecuteScriptAndGetValue(main_frame
, "get_current()");
314 ASSERT_TRUE(value
->GetAsInteger(&index
));
316 EXPECT_TRUE(controller
.CanGoBack());
317 EXPECT_TRUE(controller
.CanGoForward());
321 // Do a fling-right now. That should navigate backwards.
322 base::string16 expected_title
= base::ASCIIToUTF16("Title:");
323 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
324 generator
.GestureScrollSequence(
325 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
326 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
327 base::TimeDelta::FromMilliseconds(kScrollDurationMs
),
329 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
330 EXPECT_EQ(expected_title
, actual_title
);
331 value
= content::ExecuteScriptAndGetValue(main_frame
, "get_current()");
332 ASSERT_TRUE(value
->GetAsInteger(&index
));
334 EXPECT_FALSE(controller
.CanGoBack());
335 EXPECT_TRUE(controller
.CanGoForward());
339 // Do a swipe-left now. That should navigate forward.
340 base::string16 expected_title
= base::ASCIIToUTF16("Title: #1");
341 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
342 generator
.GestureScrollSequence(
343 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
344 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
345 base::TimeDelta::FromMilliseconds(kScrollDurationMs
),
347 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
348 EXPECT_EQ(expected_title
, actual_title
);
349 value
= content::ExecuteScriptAndGetValue(main_frame
, "get_current()");
350 ASSERT_TRUE(value
->GetAsInteger(&index
));
352 EXPECT_TRUE(controller
.CanGoBack());
353 EXPECT_TRUE(controller
.CanGoForward());
357 int GetCurrentIndex() {
358 WebContentsImpl
* web_contents
=
359 static_cast<WebContentsImpl
*>(shell()->web_contents());
360 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
362 scoped_ptr
<base::Value
> value
;
363 value
= content::ExecuteScriptAndGetValue(main_frame
, "get_current()");
364 if (!value
->GetAsInteger(&index
))
369 int ExecuteScriptAndExtractInt(const std::string
& script
) {
371 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
372 shell()->web_contents(),
373 "domAutomationController.send(" + script
+ ")",
378 RenderViewHost
* GetRenderViewHost() const {
379 RenderViewHost
* const rvh
= shell()->web_contents()->GetRenderViewHost();
384 RenderWidgetHostImpl
* GetRenderWidgetHost() const {
385 RenderWidgetHostImpl
* const rwh
=
386 RenderWidgetHostImpl::From(shell()
388 ->GetRenderWidgetHostView()
389 ->GetRenderWidgetHost());
394 RenderWidgetHostViewBase
* GetRenderWidgetHostView() const {
395 return static_cast<RenderWidgetHostViewBase
*>(
396 GetRenderViewHost()->GetView());
399 InputEventMessageFilterWaitsForAcks
* filter() {
400 return filter_
.get();
404 uint32 frame
= GetRenderWidgetHostView()->RendererFrameNumber();
405 while (!GetRenderWidgetHost()->ScheduleComposite())
407 while (GetRenderWidgetHostView()->RendererFrameNumber() == frame
)
412 ScreenshotTracker
* screenshot_manager() { return screenshot_manager_
; }
413 void set_min_screenshot_interval(int interval_ms
) {
414 screenshot_manager_
->SetScreenshotInterval(interval_ms
);
417 void AddInputEventMessageFilter() {
418 filter_
= new InputEventMessageFilterWaitsForAcks();
419 GetRenderWidgetHost()->GetProcess()->AddFilter(filter_
.get());
423 ScreenshotTracker
* screenshot_manager_
;
424 scoped_refptr
<InputEventMessageFilterWaitsForAcks
> filter_
;
426 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest
);
429 // Flaky on Windows: http://crbug.com/305722
430 // The test frequently times out on Linux, too. See crbug.com/440043.
431 #if defined(OS_WIN) || defined(OS_LINUX)
432 #define MAYBE_OverscrollNavigation DISABLED_OverscrollNavigation
434 #define MAYBE_OverscrollNavigation OverscrollNavigation
437 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, MAYBE_OverscrollNavigation
) {
438 TestOverscrollNavigation(false);
441 // Flaky on Windows (might be related to the above test):
442 // http://crbug.com/305722
443 // On Linux, the test frequently times out. (See crbug.com/440043).
444 #if defined(OS_WIN) || defined(OS_LINUX)
445 #define MAYBE_OverscrollNavigationWithTouchHandler \
446 DISABLED_OverscrollNavigationWithTouchHandler
448 #define MAYBE_OverscrollNavigationWithTouchHandler \
449 OverscrollNavigationWithTouchHandler
451 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
452 MAYBE_OverscrollNavigationWithTouchHandler
) {
453 TestOverscrollNavigation(true);
456 // Disabled because the test always fails the first time it runs on the Win Aura
457 // bots, and usually but not always passes second-try (See crbug.com/179532).
458 // On Linux, the test frequently times out. (See crbug.com/440043).
459 #if defined(OS_WIN) || defined(OS_LINUX)
460 #define MAYBE_QuickOverscrollDirectionChange \
461 DISABLED_QuickOverscrollDirectionChange
463 #define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange
465 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
466 MAYBE_QuickOverscrollDirectionChange
) {
467 ASSERT_NO_FATAL_FAILURE(
468 StartTestWithPage("files/overscroll_navigation.html"));
469 WebContentsImpl
* web_contents
=
470 static_cast<WebContentsImpl
*>(shell()->web_contents());
471 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
473 // This test triggers a large number of animations. Speed them up to ensure
474 // the test completes within its time limit.
475 ui::ScopedAnimationDurationScaleMode
fast_duration_mode(
476 ui::ScopedAnimationDurationScaleMode::FAST_DURATION
);
478 // Make sure the page has both back/forward history.
479 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
480 EXPECT_EQ(1, GetCurrentIndex());
481 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
482 EXPECT_EQ(2, GetCurrentIndex());
483 web_contents
->GetController().GoBack();
484 EXPECT_EQ(1, GetCurrentIndex());
486 aura::Window
* content
= web_contents
->GetContentNativeView();
487 ui::EventProcessor
* dispatcher
= content
->GetHost()->event_processor();
488 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
490 base::TimeDelta timestamp
= ui::EventTimeForNow();
491 ui::TouchEvent
press(ui::ET_TOUCH_PRESSED
,
492 gfx::Point(bounds
.x() + bounds
.width() / 2, bounds
.y() + 5),
494 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&press
);
495 ASSERT_FALSE(details
.dispatcher_destroyed
);
496 EXPECT_EQ(1, GetCurrentIndex());
498 timestamp
+= base::TimeDelta::FromMilliseconds(10);
499 ui::TouchEvent
move1(ui::ET_TOUCH_MOVED
,
500 gfx::Point(bounds
.right() - 10, bounds
.y() + 5),
502 details
= dispatcher
->OnEventFromSource(&move1
);
503 ASSERT_FALSE(details
.dispatcher_destroyed
);
504 EXPECT_EQ(1, GetCurrentIndex());
506 // Swipe back from the right edge, back to the left edge, back to the right
509 for (int x
= bounds
.right() - 10; x
>= bounds
.x() + 10; x
-= 10) {
510 timestamp
+= base::TimeDelta::FromMilliseconds(10);
511 ui::TouchEvent
inc(ui::ET_TOUCH_MOVED
,
512 gfx::Point(x
, bounds
.y() + 5),
514 details
= dispatcher
->OnEventFromSource(&inc
);
515 ASSERT_FALSE(details
.dispatcher_destroyed
);
516 EXPECT_EQ(1, GetCurrentIndex());
519 for (int x
= bounds
.x() + 10; x
<= bounds
.width() - 10; x
+= 10) {
520 timestamp
+= base::TimeDelta::FromMilliseconds(10);
521 ui::TouchEvent
inc(ui::ET_TOUCH_MOVED
,
522 gfx::Point(x
, bounds
.y() + 5),
524 details
= dispatcher
->OnEventFromSource(&inc
);
525 ASSERT_FALSE(details
.dispatcher_destroyed
);
526 EXPECT_EQ(1, GetCurrentIndex());
529 for (int x
= bounds
.width() - 10; x
>= bounds
.x() + 10; x
-= 10) {
530 timestamp
+= base::TimeDelta::FromMilliseconds(10);
531 ui::TouchEvent
inc(ui::ET_TOUCH_MOVED
,
532 gfx::Point(x
, bounds
.y() + 5),
534 details
= dispatcher
->OnEventFromSource(&inc
);
535 ASSERT_FALSE(details
.dispatcher_destroyed
);
536 EXPECT_EQ(1, GetCurrentIndex());
539 // Do not end the overscroll sequence.
542 // Tests that the page has has a screenshot when navigation happens:
543 // - from within the page (from a JS function)
544 // - interactively, when user does an overscroll gesture
545 // - interactively, when user navigates in history without the overscroll
547 // Flaky on Windows (http://crbug.com/357311). Might be related to
548 // OverscrollNavigation test.
549 // Flaky on Ozone (http://crbug.com/399676).
550 // Flaky on ChromeOS (http://crbug.com/405945).
551 #if defined(OS_WIN) || defined(USE_OZONE) || defined(OS_CHROMEOS)
552 #define MAYBE_OverscrollScreenshot DISABLED_OverscrollScreenshot
554 #define MAYBE_OverscrollScreenshot OverscrollScreenshot
556 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, MAYBE_OverscrollScreenshot
) {
557 // Disable the test for WinXP. See http://crbug/294116.
559 if (base::win::GetVersion() < base::win::VERSION_VISTA
) {
560 LOG(WARNING
) << "Test disabled due to unknown bug on WinXP.";
565 ASSERT_NO_FATAL_FAILURE(
566 StartTestWithPage("files/overscroll_navigation.html"));
567 WebContentsImpl
* web_contents
=
568 static_cast<WebContentsImpl
*>(shell()->web_contents());
569 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
571 set_min_screenshot_interval(0);
573 // Do a few navigations initiated by the page.
574 // Screenshots should never be captured since these are all in-page
576 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
577 EXPECT_EQ(1, GetCurrentIndex());
578 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
579 EXPECT_EQ(2, GetCurrentIndex());
580 screenshot_manager()->WaitUntilScreenshotIsReady();
582 NavigationEntryImpl
* entry
= web_contents
->GetController().GetEntryAtIndex(2);
583 EXPECT_FALSE(entry
->screenshot().get());
585 entry
= web_contents
->GetController().GetEntryAtIndex(1);
586 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
588 entry
= web_contents
->GetController().GetEntryAtIndex(0);
589 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
591 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
592 screenshot_manager()->WaitUntilScreenshotIsReady();
594 entry
= web_contents
->GetController().GetEntryAtIndex(2);
595 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
597 entry
= web_contents
->GetController().GetEntryAtIndex(3);
598 EXPECT_FALSE(entry
->screenshot().get());
600 // Now, swipe right to navigate backwards. This should navigate away from
601 // index 3 to index 2.
602 base::string16 expected_title
= base::ASCIIToUTF16("Title: #2");
603 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
604 aura::Window
* content
= web_contents
->GetContentNativeView();
605 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
606 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
607 generator
.GestureScrollSequence(
608 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
609 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
610 base::TimeDelta::FromMilliseconds(20),
612 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
613 EXPECT_EQ(expected_title
, actual_title
);
614 EXPECT_EQ(2, GetCurrentIndex());
615 screenshot_manager()->WaitUntilScreenshotIsReady();
616 entry
= web_contents
->GetController().GetEntryAtIndex(3);
617 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
620 // Navigate a couple more times.
621 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
622 EXPECT_EQ(3, GetCurrentIndex());
623 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
624 EXPECT_EQ(4, GetCurrentIndex());
625 screenshot_manager()->WaitUntilScreenshotIsReady();
626 entry
= web_contents
->GetController().GetEntryAtIndex(4);
627 EXPECT_FALSE(entry
->screenshot().get());
630 // Navigate back in history.
631 base::string16 expected_title
= base::ASCIIToUTF16("Title: #3");
632 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
633 web_contents
->GetController().GoBack();
634 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
635 EXPECT_EQ(expected_title
, actual_title
);
636 EXPECT_EQ(3, GetCurrentIndex());
637 screenshot_manager()->WaitUntilScreenshotIsReady();
638 entry
= web_contents
->GetController().GetEntryAtIndex(4);
639 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
643 // Crashes under ThreadSanitizer, http://crbug.com/356758.
644 #if defined(THREAD_SANITIZER)
645 #define MAYBE_ScreenshotForSwappedOutRenderViews \
646 DISABLED_ScreenshotForSwappedOutRenderViews
648 #define MAYBE_ScreenshotForSwappedOutRenderViews \
649 ScreenshotForSwappedOutRenderViews
651 // Tests that screenshot is taken correctly when navigation causes a
652 // RenderViewHost to be swapped out.
653 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
654 MAYBE_ScreenshotForSwappedOutRenderViews
) {
655 ASSERT_NO_FATAL_FAILURE(
656 StartTestWithPage("files/overscroll_navigation.html"));
657 // Create a new server with a different site.
658 net::SpawnedTestServer
https_server(
659 net::SpawnedTestServer::TYPE_HTTPS
,
660 net::SpawnedTestServer::kLocalhost
,
661 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
662 ASSERT_TRUE(https_server
.Start());
664 WebContentsImpl
* web_contents
=
665 static_cast<WebContentsImpl
*>(shell()->web_contents());
666 set_min_screenshot_interval(0);
672 { https_server
.GetURL("files/title1.html"),
673 ui::PAGE_TRANSITION_TYPED
| ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
},
674 { test_server()->GetURL("files/title2.html"),
675 ui::PAGE_TRANSITION_AUTO_BOOKMARK
},
676 { https_server
.GetURL("files/title3.html"),
677 ui::PAGE_TRANSITION_TYPED
| ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
},
681 screenshot_manager()->Reset();
682 for (int i
= 0; !navigations
[i
].url
.is_empty(); ++i
) {
683 // Navigate via the user initiating a navigation from the UI.
684 NavigationController::LoadURLParams
params(navigations
[i
].url
);
685 params
.transition_type
=
686 ui::PageTransitionFromInt(navigations
[i
].transition
);
688 RenderViewHost
* old_host
= web_contents
->GetRenderViewHost();
689 web_contents
->GetController().LoadURLWithParams(params
);
690 WaitForLoadStop(web_contents
);
691 screenshot_manager()->WaitUntilScreenshotIsReady();
693 EXPECT_NE(old_host
, web_contents
->GetRenderViewHost())
694 << navigations
[i
].url
.spec();
695 EXPECT_EQ(old_host
, screenshot_manager()->screenshot_taken_for());
697 NavigationEntryImpl
* entry
=
698 web_contents
->GetController().GetEntryAtOffset(-1);
699 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry
));
701 entry
= web_contents
->GetController().GetLastCommittedEntry();
702 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
703 EXPECT_FALSE(entry
->screenshot().get());
704 screenshot_manager()->Reset();
707 // Increase the minimum interval between taking screenshots.
708 set_min_screenshot_interval(60000);
710 // Navigate again. This should not take any screenshot because of the
711 // increased screenshot interval.
712 NavigationController::LoadURLParams
params(navigations
[0].url
);
713 params
.transition_type
= ui::PageTransitionFromInt(navigations
[0].transition
);
714 web_contents
->GetController().LoadURLWithParams(params
);
715 WaitForLoadStop(web_contents
);
716 screenshot_manager()->WaitUntilScreenshotIsReady();
718 EXPECT_EQ(NULL
, screenshot_manager()->screenshot_taken_for());
721 // Tests that navigations resulting from reloads, history.replaceState,
722 // and history.pushState do not capture screenshots.
723 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, ReplaceStateReloadPushState
) {
724 ASSERT_NO_FATAL_FAILURE(
725 StartTestWithPage("files/overscroll_navigation.html"));
726 WebContentsImpl
* web_contents
=
727 static_cast<WebContentsImpl
*>(shell()->web_contents());
728 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
730 set_min_screenshot_interval(0);
731 screenshot_manager()->Reset();
732 ExecuteSyncJSFunction(main_frame
, "use_replace_state()");
733 screenshot_manager()->WaitUntilScreenshotIsReady();
734 // history.replaceState shouldn't capture a screenshot
735 EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
736 screenshot_manager()->Reset();
737 web_contents
->GetController().Reload(true);
738 WaitForLoadStop(web_contents
);
739 // reloading the page shouldn't capture a screenshot
740 // TODO (mfomitchev): currently broken. Uncomment when
741 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page
742 // is populated properly when reloading the page.
743 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
744 screenshot_manager()->Reset();
745 ExecuteSyncJSFunction(main_frame
, "use_push_state()");
746 screenshot_manager()->WaitUntilScreenshotIsReady();
747 // pushing a state shouldn't capture a screenshot
748 // TODO (mfomitchev): currently broken. Uncomment when
749 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page
750 // is populated properly when pushState is used.
751 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
754 // TODO(sadrul): This test is disabled because it reparents in a way the
755 // FocusController does not support. This code would crash in
756 // a production build. It only passed prior to this revision
757 // because testing used the old FocusManager which did some
758 // different (osbolete) processing. TODO(sadrul) to figure out
759 // how this test should work that mimics production code a bit
761 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
762 DISABLED_ContentWindowReparent
) {
763 ASSERT_NO_FATAL_FAILURE(
764 StartTestWithPage("files/overscroll_navigation.html"));
766 scoped_ptr
<aura::Window
> window(new aura::Window(NULL
));
767 window
->Init(ui::LAYER_NOT_DRAWN
);
769 WebContentsImpl
* web_contents
=
770 static_cast<WebContentsImpl
*>(shell()->web_contents());
771 ExecuteSyncJSFunction(web_contents
->GetMainFrame(), "navigate_next()");
772 EXPECT_EQ(1, GetCurrentIndex());
774 aura::Window
* content
= web_contents
->GetContentNativeView();
775 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
776 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
777 generator
.GestureScrollSequence(
778 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
779 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
780 base::TimeDelta::FromMilliseconds(20),
783 window
->AddChild(shell()->web_contents()->GetContentNativeView());
786 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, ContentWindowClose
) {
787 ASSERT_NO_FATAL_FAILURE(
788 StartTestWithPage("files/overscroll_navigation.html"));
790 WebContentsImpl
* web_contents
=
791 static_cast<WebContentsImpl
*>(shell()->web_contents());
792 ExecuteSyncJSFunction(web_contents
->GetMainFrame(), "navigate_next()");
793 EXPECT_EQ(1, GetCurrentIndex());
795 aura::Window
* content
= web_contents
->GetContentNativeView();
796 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
797 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
798 generator
.GestureScrollSequence(
799 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
800 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
801 base::TimeDelta::FromMilliseconds(20),
804 delete web_contents
->GetContentNativeView();
808 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
809 // This appears to be flaky in the same was as the other overscroll
810 // tests. Enabling for non-Windows platforms.
811 // See http://crbug.com/369871.
812 // For linux, see http://crbug.com/381294
813 #define MAYBE_RepeatedQuickOverscrollGestures DISABLED_RepeatedQuickOverscrollGestures
815 #define MAYBE_RepeatedQuickOverscrollGestures RepeatedQuickOverscrollGestures
818 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
819 MAYBE_RepeatedQuickOverscrollGestures
) {
820 ASSERT_NO_FATAL_FAILURE(
821 StartTestWithPage("files/overscroll_navigation.html"));
823 WebContentsImpl
* web_contents
=
824 static_cast<WebContentsImpl
*>(shell()->web_contents());
825 NavigationController
& controller
= web_contents
->GetController();
826 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
827 ExecuteSyncJSFunction(main_frame
, "install_touch_handler()");
829 // Navigate twice, then navigate back in history once.
830 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
831 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
832 EXPECT_EQ(2, GetCurrentIndex());
833 EXPECT_TRUE(controller
.CanGoBack());
834 EXPECT_FALSE(controller
.CanGoForward());
836 web_contents
->GetController().GoBack();
837 WaitForLoadStop(web_contents
);
838 EXPECT_EQ(1, GetCurrentIndex());
839 EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents
->GetTitle());
840 EXPECT_TRUE(controller
.CanGoBack());
841 EXPECT_TRUE(controller
.CanGoForward());
843 aura::Window
* content
= web_contents
->GetContentNativeView();
844 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
845 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
847 // Do a swipe left to start a forward navigation. Then quickly do a swipe
849 base::string16 expected_title
= base::ASCIIToUTF16("Title: #2");
850 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
851 NavigationWatcher
nav_watcher(web_contents
);
853 generator
.GestureScrollSequence(
854 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
855 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
856 base::TimeDelta::FromMilliseconds(2000),
858 nav_watcher
.WaitUntilNavigationStarts();
860 generator
.GestureScrollSequence(
861 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
862 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
863 base::TimeDelta::FromMilliseconds(2000),
865 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
866 EXPECT_EQ(expected_title
, actual_title
);
868 EXPECT_EQ(2, GetCurrentIndex());
869 EXPECT_TRUE(controller
.CanGoBack());
870 EXPECT_FALSE(controller
.CanGoForward());
873 // Verify that hiding a parent of the renderer will hide the content too.
874 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, HideContentOnParenHide
) {
875 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/title1.html"));
876 WebContentsImpl
* web_contents
=
877 static_cast<WebContentsImpl
*>(shell()->web_contents());
878 aura::Window
* content
= web_contents
->GetNativeView()->parent();
879 EXPECT_TRUE(web_contents
->should_normally_be_visible());
881 EXPECT_FALSE(web_contents
->should_normally_be_visible());
883 EXPECT_TRUE(web_contents
->should_normally_be_visible());
886 // Ensure that SnapToPhysicalPixelBoundary() is called on WebContentsView parent
887 // change. This is a regression test for http://crbug.com/388908.
888 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, WebContentsViewReparent
) {
889 ASSERT_NO_FATAL_FAILURE(
890 StartTestWithPage("files/overscroll_navigation.html"));
892 scoped_ptr
<aura::Window
> window(new aura::Window(NULL
));
893 window
->Init(ui::LAYER_NOT_DRAWN
);
895 RenderWidgetHostViewAura
* rwhva
=
896 static_cast<RenderWidgetHostViewAura
*>(
897 shell()->web_contents()->GetRenderWidgetHostView());
898 rwhva
->ResetHasSnappedToBoundary();
899 EXPECT_FALSE(rwhva
->has_snapped_to_boundary());
900 window
->AddChild(shell()->web_contents()->GetNativeView());
901 EXPECT_TRUE(rwhva
->has_snapped_to_boundary());
904 // Flaky on some platforms, likely for the same reason as other flaky overscroll
905 // tests. http://crbug.com/305722
906 // TODO(tdresser): Re-enable this once eager GR is back on. See
908 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
909 #define MAYBE_OverscrollNavigationTouchThrottling \
910 DISABLED_OverscrollNavigationTouchThrottling
912 #define MAYBE_OverscrollNavigationTouchThrottling \
913 DISABLED_OverscrollNavigationTouchThrottling
916 // Tests that touch moves are not throttled when performing a scroll gesture on
917 // a non-scrollable area, except during gesture-nav.
918 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
919 MAYBE_OverscrollNavigationTouchThrottling
) {
920 ASSERT_NO_FATAL_FAILURE(
921 StartTestWithPage("files/overscroll_navigation.html"));
923 AddInputEventMessageFilter();
925 WebContentsImpl
* web_contents
=
926 static_cast<WebContentsImpl
*>(shell()->web_contents());
927 aura::Window
* content
= web_contents
->GetContentNativeView();
928 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
931 ExecuteSyncJSFunction(web_contents
->GetMainFrame(),
932 "install_touchmove_handler()");
936 for (int navigated
= 0; navigated
<= 1; ++navigated
) {
938 ExecuteSyncJSFunction(web_contents
->GetMainFrame(), "navigate_next()");
939 ExecuteSyncJSFunction(web_contents
->GetMainFrame(),
940 "reset_touchmove_count()");
943 SyntheticWebTouchEvent touch
;
944 touch
.PressPoint(bounds
.x() + 2, bounds
.y() + 10);
945 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch
,
947 filter()->WaitForAck(blink::WebInputEvent::TouchStart
);
950 // Assert on the ack, because we'll end up waiting for acks that will never
951 // come if this is not true.
952 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
, filter()->last_ack_state());
954 // Send first touch move, and then a scroll begin.
955 touch
.MovePoint(0, bounds
.x() + 20 + 1 * dx
, bounds
.y() + 100);
956 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch
,
958 filter()->WaitForAck(blink::WebInputEvent::TouchMove
);
959 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
, filter()->last_ack_state());
961 blink::WebGestureEvent scroll_begin
=
962 SyntheticWebGestureEventBuilder::BuildScrollBegin(1, 1);
963 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
964 scroll_begin
, ui::LatencyInfo());
965 // Scroll begin ignores ack disposition, so don't wait for the ack.
968 // First touchmove already sent, start at 2.
969 for (int i
= 2; i
<= 10; ++i
) {
970 // Send a touch move, followed by a scroll update
971 touch
.MovePoint(0, bounds
.x() + 20 + i
* dx
, bounds
.y() + 100);
972 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(
973 touch
, ui::LatencyInfo());
976 blink::WebGestureEvent scroll_update
=
977 SyntheticWebGestureEventBuilder::BuildScrollUpdate(
978 dx
, 5, 0, blink::WebGestureDeviceTouchscreen
);
980 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
981 scroll_update
, ui::LatencyInfo());
986 touch
.ReleasePoint(0);
987 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch
,
991 blink::WebGestureEvent scroll_end
;
992 scroll_end
.type
= blink::WebInputEvent::GestureScrollEnd
;
993 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
994 scroll_end
, ui::LatencyInfo());
998 EXPECT_EQ(10, ExecuteScriptAndExtractInt("touchmoveCount"));
1000 EXPECT_GT(10, ExecuteScriptAndExtractInt("touchmoveCount"));
1004 // Test that vertical overscroll updates are sent only when a user overscrolls
1007 #define MAYBE_VerticalOverscroll DISABLED_VerticalOverscroll
1009 #define MAYBE_VerticalOverscroll VerticalOverscroll
1012 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, MAYBE_VerticalOverscroll
) {
1013 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1014 switches::kScrollEndEffect
, "1");
1016 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("about:blank"));
1017 WebContentsImpl
* web_contents
=
1018 static_cast<WebContentsImpl
*>(shell()->web_contents());
1019 VerticalOverscrollTracker tracker
;
1020 web_contents
->SetDelegate(&tracker
);
1022 // This test triggers a large number of animations. Speed them up to ensure
1023 // the test completes within its time limit.
1024 ui::ScopedAnimationDurationScaleMode
fast_duration_mode(
1025 ui::ScopedAnimationDurationScaleMode::FAST_DURATION
);
1027 aura::Window
* content
= web_contents
->GetContentNativeView();
1028 ui::EventProcessor
* dispatcher
= content
->GetHost()->event_processor();
1029 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
1031 // Overscroll horizontally.
1033 int kXStep
= bounds
.width() / 10;
1034 gfx::Point
location(bounds
.right() - kXStep
, bounds
.y() + 5);
1035 base::TimeDelta timestamp
= ui::EventTimeForNow();
1036 ui::TouchEvent
press(
1037 ui::ET_TOUCH_PRESSED
,
1041 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&press
);
1042 ASSERT_FALSE(details
.dispatcher_destroyed
);
1044 location
-= gfx::Vector2d(kXStep
, 0);
1045 timestamp
+= base::TimeDelta::FromMilliseconds(10);
1047 while (location
.x() > bounds
.x() + kXStep
) {
1048 ui::TouchEvent
inc(ui::ET_TOUCH_MOVED
, location
, 0, timestamp
);
1049 details
= dispatcher
->OnEventFromSource(&inc
);
1050 ASSERT_FALSE(details
.dispatcher_destroyed
);
1052 location
-= gfx::Vector2d(10, 0);
1053 timestamp
+= base::TimeDelta::FromMilliseconds(10);
1056 ui::TouchEvent
release(ui::ET_TOUCH_RELEASED
, location
, 0, timestamp
);
1057 details
= dispatcher
->OnEventFromSource(&release
);
1058 ASSERT_FALSE(details
.dispatcher_destroyed
);
1061 EXPECT_EQ(0, tracker
.num_overscroll_updates());
1062 EXPECT_FALSE(tracker
.overscroll_completed());
1065 // Overscroll vertically.
1069 int kYStep
= bounds
.height() / 10;
1070 gfx::Point
location(bounds
.x() + 10, bounds
.y() + kYStep
);
1071 base::TimeDelta timestamp
= ui::EventTimeForNow();
1072 ui::TouchEvent
press(
1073 ui::ET_TOUCH_PRESSED
,
1077 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&press
);
1078 ASSERT_FALSE(details
.dispatcher_destroyed
);
1080 location
+= gfx::Vector2d(0, kYStep
);
1081 timestamp
+= base::TimeDelta::FromMilliseconds(10);
1083 while (location
.y() < bounds
.bottom() - kYStep
) {
1084 ui::TouchEvent
inc(ui::ET_TOUCH_MOVED
, location
, 0, timestamp
);
1085 details
= dispatcher
->OnEventFromSource(&inc
);
1086 ASSERT_FALSE(details
.dispatcher_destroyed
);
1088 location
+= gfx::Vector2d(0, kYStep
);
1089 timestamp
+= base::TimeDelta::FromMilliseconds(10);
1092 ui::TouchEvent
release(ui::ET_TOUCH_RELEASED
, location
, 0, timestamp
);
1093 details
= dispatcher
->OnEventFromSource(&release
);
1094 ASSERT_FALSE(details
.dispatcher_destroyed
);
1097 EXPECT_LT(0, tracker
.num_overscroll_updates());
1098 EXPECT_TRUE(tracker
.overscroll_completed());
1101 // Start out overscrolling vertically, then switch directions and finish
1102 // overscrolling horizontally.
1106 int kXStep
= bounds
.width() / 10;
1107 int kYStep
= bounds
.height() / 10;
1108 gfx::Point location
= bounds
.origin() + gfx::Vector2d(0, kYStep
);
1109 base::TimeDelta timestamp
= ui::EventTimeForNow();
1110 ui::TouchEvent
press(
1111 ui::ET_TOUCH_PRESSED
,
1115 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&press
);
1116 ASSERT_FALSE(details
.dispatcher_destroyed
);
1118 location
+= gfx::Vector2d(0, kYStep
);
1119 timestamp
+= base::TimeDelta::FromMilliseconds(10);
1121 for (size_t i
= 0; i
< 3; ++i
) {
1122 ui::TouchEvent
inc(ui::ET_TOUCH_MOVED
, location
, 0, timestamp
);
1123 details
= dispatcher
->OnEventFromSource(&inc
);
1124 ASSERT_FALSE(details
.dispatcher_destroyed
);
1126 location
+= gfx::Vector2d(0, kYStep
);
1127 timestamp
+= base::TimeDelta::FromMilliseconds(10);
1130 while (location
.x() < bounds
.right() - kXStep
) {
1131 ui::TouchEvent
inc(ui::ET_TOUCH_MOVED
, location
, 0, timestamp
);
1132 details
= dispatcher
->OnEventFromSource(&inc
);
1133 ASSERT_FALSE(details
.dispatcher_destroyed
);
1135 location
+= gfx::Vector2d(kXStep
, 0);
1136 timestamp
+= base::TimeDelta::FromMilliseconds(10);
1139 ui::TouchEvent
release(ui::ET_TOUCH_RELEASED
, location
, 0, timestamp
);
1140 details
= dispatcher
->OnEventFromSource(&release
);
1141 ASSERT_FALSE(details
.dispatcher_destroyed
);
1144 EXPECT_LT(0, tracker
.num_overscroll_updates());
1145 EXPECT_FALSE(tracker
.overscroll_completed());
1149 } // namespace content