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. 4 5#include "content/browser/web_contents/web_contents_view_aura.h" 6 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#if defined(OS_WIN) 13#include "base/win/windows_version.h" 14#endif 15#include "content/browser/frame_host/navigation_controller_impl.h" 16#include "content/browser/frame_host/navigation_entry_impl.h" 17#include "content/browser/frame_host/navigation_entry_screenshot_manager.h" 18#include "content/browser/renderer_host/render_widget_host_view_aura.h" 19#include "content/browser/web_contents/web_contents_impl.h" 20#include "content/browser/web_contents/web_contents_view.h" 21#include "content/common/input/synthetic_web_input_event_builders.h" 22#include "content/common/input_messages.h" 23#include "content/common/view_messages.h" 24#include "content/public/browser/browser_message_filter.h" 25#include "content/public/browser/render_frame_host.h" 26#include "content/public/browser/web_contents_delegate.h" 27#include "content/public/browser/web_contents_observer.h" 28#include "content/public/common/content_switches.h" 29#include "content/public/test/browser_test_utils.h" 30#include "content/public/test/content_browser_test.h" 31#include "content/public/test/content_browser_test_utils.h" 32#include "content/public/test/test_renderer_host.h" 33#include "content/public/test/test_utils.h" 34#include "content/shell/browser/shell.h" 35#include "ui/aura/window.h" 36#include "ui/aura/window_tree_host.h" 37#include "ui/compositor/scoped_animation_duration_scale_mode.h" 38#include "ui/events/event_processor.h" 39#include "ui/events/event_switches.h" 40#include "ui/events/event_utils.h" 41#include "ui/events/test/event_generator.h" 42 43namespace { 44 45// TODO(tdresser): Find a way to avoid sleeping like this. See crbug.com/405282 46// for details. 47void GiveItSomeTime() { 48 base::RunLoop run_loop; 49 base::MessageLoop::current()->PostDelayedTask( 50 FROM_HERE, 51 run_loop.QuitClosure(), 52 base::TimeDelta::FromMillisecondsD(10)); 53 run_loop.Run(); 54} 55 56// WebContentsDelegate which tracks vertical overscroll updates. 57class VerticalOverscrollTracker : public content::WebContentsDelegate { 58 public: 59 VerticalOverscrollTracker() : count_(0), completed_(false) {} 60 virtual ~VerticalOverscrollTracker() {} 61 62 int num_overscroll_updates() const { 63 return count_; 64 } 65 66 bool overscroll_completed() const { 67 return completed_; 68 } 69 70 void Reset() { 71 count_ = 0; 72 completed_ = false; 73 } 74 75 private: 76 virtual bool CanOverscrollContent() const OVERRIDE { 77 return true; 78 } 79 80 virtual void OverscrollUpdate(int delta_y) OVERRIDE { 81 ++count_; 82 } 83 84 virtual void OverscrollComplete() OVERRIDE { 85 completed_ = true; 86 } 87 88 int count_; 89 bool completed_; 90 91 DISALLOW_COPY_AND_ASSIGN(VerticalOverscrollTracker); 92}; 93 94} //namespace 95 96 97namespace content { 98 99// This class keeps track of the RenderViewHost whose screenshot was captured. 100class ScreenshotTracker : public NavigationEntryScreenshotManager { 101 public: 102 explicit ScreenshotTracker(NavigationControllerImpl* controller) 103 : NavigationEntryScreenshotManager(controller), 104 screenshot_taken_for_(NULL), 105 waiting_for_screenshots_(0) { 106 } 107 108 virtual ~ScreenshotTracker() { 109 } 110 111 RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; } 112 113 void Reset() { 114 screenshot_taken_for_ = NULL; 115 screenshot_set_.clear(); 116 } 117 118 void SetScreenshotInterval(int interval_ms) { 119 SetMinScreenshotIntervalMS(interval_ms); 120 } 121 122 void WaitUntilScreenshotIsReady() { 123 if (!waiting_for_screenshots_) 124 return; 125 message_loop_runner_ = new content::MessageLoopRunner; 126 message_loop_runner_->Run(); 127 } 128 129 bool ScreenshotSetForEntry(NavigationEntryImpl* entry) const { 130 return screenshot_set_.count(entry) > 0; 131 } 132 133 private: 134 // Overridden from NavigationEntryScreenshotManager: 135 virtual void TakeScreenshotImpl(RenderViewHost* host, 136 NavigationEntryImpl* entry) OVERRIDE { 137 ++waiting_for_screenshots_; 138 screenshot_taken_for_ = host; 139 NavigationEntryScreenshotManager::TakeScreenshotImpl(host, entry); 140 } 141 142 virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE { 143 --waiting_for_screenshots_; 144 screenshot_set_[entry] = true; 145 NavigationEntryScreenshotManager::OnScreenshotSet(entry); 146 if (waiting_for_screenshots_ == 0 && message_loop_runner_.get()) 147 message_loop_runner_->Quit(); 148 } 149 150 RenderViewHost* screenshot_taken_for_; 151 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 152 int waiting_for_screenshots_; 153 std::map<NavigationEntryImpl*, bool> screenshot_set_; 154 155 DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker); 156}; 157 158class NavigationWatcher : public WebContentsObserver { 159 public: 160 explicit NavigationWatcher(WebContents* contents) 161 : WebContentsObserver(contents), 162 navigated_(false), 163 should_quit_loop_(false) { 164 } 165 166 virtual ~NavigationWatcher() {} 167 168 void WaitUntilNavigationStarts() { 169 if (navigated_) 170 return; 171 should_quit_loop_ = true; 172 base::MessageLoop::current()->Run(); 173 } 174 175 private: 176 // Overridden from WebContentsObserver: 177 virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE { 178 navigated_ = true; 179 if (should_quit_loop_) 180 base::MessageLoop::current()->Quit(); 181 } 182 183 bool navigated_; 184 bool should_quit_loop_; 185 186 DISALLOW_COPY_AND_ASSIGN(NavigationWatcher); 187}; 188 189class InputEventMessageFilterWaitsForAcks : public BrowserMessageFilter { 190 public: 191 InputEventMessageFilterWaitsForAcks() 192 : BrowserMessageFilter(InputMsgStart), 193 type_(blink::WebInputEvent::Undefined), 194 state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} 195 196 void WaitForAck(blink::WebInputEvent::Type type) { 197 base::RunLoop run_loop; 198 base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure()); 199 base::AutoReset<blink::WebInputEvent::Type> reset_type(&type_, type); 200 run_loop.Run(); 201 } 202 203 InputEventAckState last_ack_state() const { return state_; } 204 205 protected: 206 virtual ~InputEventMessageFilterWaitsForAcks() {} 207 208 private: 209 void ReceivedEventAck(blink::WebInputEvent::Type type, 210 InputEventAckState state) { 211 if (type_ == type) { 212 state_ = state; 213 quit_.Run(); 214 } 215 } 216 217 // BrowserMessageFilter: 218 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 219 if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) { 220 InputHostMsg_HandleInputEvent_ACK::Param params; 221 InputHostMsg_HandleInputEvent_ACK::Read(&message, ¶ms); 222 blink::WebInputEvent::Type type = params.a.type; 223 InputEventAckState ack = params.a.state; 224 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 225 base::Bind(&InputEventMessageFilterWaitsForAcks::ReceivedEventAck, 226 this, type, ack)); 227 } 228 return false; 229 } 230 231 base::Closure quit_; 232 blink::WebInputEvent::Type type_; 233 InputEventAckState state_; 234 235 DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilterWaitsForAcks); 236}; 237 238class WebContentsViewAuraTest : public ContentBrowserTest { 239 public: 240 WebContentsViewAuraTest() 241 : screenshot_manager_(NULL) { 242 } 243 244 // Executes the javascript synchronously and makes sure the returned value is 245 // freed properly. 246 void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) { 247 scoped_ptr<base::Value> value = 248 content::ExecuteScriptAndGetValue(rfh, jscript); 249 } 250 251 // Starts the test server and navigates to the given url. Sets a large enough 252 // size to the root window. Returns after the navigation to the url is 253 // complete. 254 void StartTestWithPage(const std::string& url) { 255 ASSERT_TRUE(test_server()->Start()); 256 GURL test_url(test_server()->GetURL(url)); 257 NavigateToURL(shell(), test_url); 258 259 WebContentsImpl* web_contents = 260 static_cast<WebContentsImpl*>(shell()->web_contents()); 261 NavigationControllerImpl* controller = &web_contents->GetController(); 262 263 screenshot_manager_ = new ScreenshotTracker(controller); 264 controller->SetScreenshotManager(screenshot_manager_); 265 } 266 267 virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE { 268 cmd->AppendSwitchASCII(switches::kTouchEvents, 269 switches::kTouchEventsEnabled); 270 } 271 272 void TestOverscrollNavigation(bool touch_handler) { 273 ASSERT_NO_FATAL_FAILURE( 274 StartTestWithPage("files/overscroll_navigation.html")); 275 WebContentsImpl* web_contents = 276 static_cast<WebContentsImpl*>(shell()->web_contents()); 277 NavigationController& controller = web_contents->GetController(); 278 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 279 280 EXPECT_FALSE(controller.CanGoBack()); 281 EXPECT_FALSE(controller.CanGoForward()); 282 int index = -1; 283 scoped_ptr<base::Value> value = 284 content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 285 ASSERT_TRUE(value->GetAsInteger(&index)); 286 EXPECT_EQ(0, index); 287 288 if (touch_handler) 289 ExecuteSyncJSFunction(main_frame, "install_touch_handler()"); 290 291 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 292 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 293 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 294 ASSERT_TRUE(value->GetAsInteger(&index)); 295 EXPECT_EQ(2, index); 296 EXPECT_TRUE(controller.CanGoBack()); 297 EXPECT_FALSE(controller.CanGoForward()); 298 299 aura::Window* content = web_contents->GetContentNativeView(); 300 gfx::Rect bounds = content->GetBoundsInRootWindow(); 301 ui::test::EventGenerator generator(content->GetRootWindow(), content); 302 const int kScrollDurationMs = 20; 303 const int kScrollSteps = 10; 304 305 { 306 // Do a swipe-right now. That should navigate backwards. 307 base::string16 expected_title = base::ASCIIToUTF16("Title: #1"); 308 content::TitleWatcher title_watcher(web_contents, expected_title); 309 generator.GestureScrollSequence( 310 gfx::Point(bounds.x() + 2, bounds.y() + 10), 311 gfx::Point(bounds.right() - 10, bounds.y() + 10), 312 base::TimeDelta::FromMilliseconds(kScrollDurationMs), 313 kScrollSteps); 314 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 315 EXPECT_EQ(expected_title, actual_title); 316 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 317 ASSERT_TRUE(value->GetAsInteger(&index)); 318 EXPECT_EQ(1, index); 319 EXPECT_TRUE(controller.CanGoBack()); 320 EXPECT_TRUE(controller.CanGoForward()); 321 } 322 323 { 324 // Do a fling-right now. That should navigate backwards. 325 base::string16 expected_title = base::ASCIIToUTF16("Title:"); 326 content::TitleWatcher title_watcher(web_contents, expected_title); 327 generator.GestureScrollSequence( 328 gfx::Point(bounds.x() + 2, bounds.y() + 10), 329 gfx::Point(bounds.right() - 10, bounds.y() + 10), 330 base::TimeDelta::FromMilliseconds(kScrollDurationMs), 331 kScrollSteps); 332 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 333 EXPECT_EQ(expected_title, actual_title); 334 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 335 ASSERT_TRUE(value->GetAsInteger(&index)); 336 EXPECT_EQ(0, index); 337 EXPECT_FALSE(controller.CanGoBack()); 338 EXPECT_TRUE(controller.CanGoForward()); 339 } 340 341 { 342 // Do a swipe-left now. That should navigate forward. 343 base::string16 expected_title = base::ASCIIToUTF16("Title: #1"); 344 content::TitleWatcher title_watcher(web_contents, expected_title); 345 generator.GestureScrollSequence( 346 gfx::Point(bounds.right() - 10, bounds.y() + 10), 347 gfx::Point(bounds.x() + 2, bounds.y() + 10), 348 base::TimeDelta::FromMilliseconds(kScrollDurationMs), 349 kScrollSteps); 350 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 351 EXPECT_EQ(expected_title, actual_title); 352 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 353 ASSERT_TRUE(value->GetAsInteger(&index)); 354 EXPECT_EQ(1, index); 355 EXPECT_TRUE(controller.CanGoBack()); 356 EXPECT_TRUE(controller.CanGoForward()); 357 } 358 } 359 360 int GetCurrentIndex() { 361 WebContentsImpl* web_contents = 362 static_cast<WebContentsImpl*>(shell()->web_contents()); 363 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 364 int index = -1; 365 scoped_ptr<base::Value> value; 366 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 367 if (!value->GetAsInteger(&index)) 368 index = -1; 369 return index; 370 } 371 372 int ExecuteScriptAndExtractInt(const std::string& script) { 373 int value = 0; 374 EXPECT_TRUE(content::ExecuteScriptAndExtractInt( 375 shell()->web_contents(), 376 "domAutomationController.send(" + script + ")", 377 &value)); 378 return value; 379 } 380 381 RenderViewHost* GetRenderViewHost() const { 382 RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost(); 383 CHECK(rvh); 384 return rvh; 385 } 386 387 RenderWidgetHostImpl* GetRenderWidgetHost() const { 388 RenderWidgetHostImpl* const rwh = 389 RenderWidgetHostImpl::From(shell() 390 ->web_contents() 391 ->GetRenderWidgetHostView() 392 ->GetRenderWidgetHost()); 393 CHECK(rwh); 394 return rwh; 395 } 396 397 RenderWidgetHostViewBase* GetRenderWidgetHostView() const { 398 return static_cast<RenderWidgetHostViewBase*>( 399 GetRenderViewHost()->GetView()); 400 } 401 402 InputEventMessageFilterWaitsForAcks* filter() { 403 return filter_.get(); 404 } 405 406 void WaitAFrame() { 407 uint32 frame = GetRenderWidgetHostView()->RendererFrameNumber(); 408 while (!GetRenderWidgetHost()->ScheduleComposite()) 409 GiveItSomeTime(); 410 while (GetRenderWidgetHostView()->RendererFrameNumber() == frame) 411 GiveItSomeTime(); 412 } 413 414 protected: 415 ScreenshotTracker* screenshot_manager() { return screenshot_manager_; } 416 void set_min_screenshot_interval(int interval_ms) { 417 screenshot_manager_->SetScreenshotInterval(interval_ms); 418 } 419 420 void AddInputEventMessageFilter() { 421 filter_ = new InputEventMessageFilterWaitsForAcks(); 422 GetRenderWidgetHost()->GetProcess()->AddFilter(filter_.get()); 423 } 424 425 private: 426 ScreenshotTracker* screenshot_manager_; 427 scoped_refptr<InputEventMessageFilterWaitsForAcks> filter_; 428 429 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest); 430}; 431 432// Flaky on Windows: http://crbug.com/305722 433#if defined(OS_WIN) 434#define MAYBE_OverscrollNavigation DISABLED_OverscrollNavigation 435#else 436#define MAYBE_OverscrollNavigation OverscrollNavigation 437#endif 438 439IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollNavigation) { 440 TestOverscrollNavigation(false); 441} 442 443// Flaky on Windows (might be related to the above test): 444// http://crbug.com/305722 445#if defined(OS_WIN) 446#define MAYBE_OverscrollNavigationWithTouchHandler \ 447 DISABLED_OverscrollNavigationWithTouchHandler 448#else 449#define MAYBE_OverscrollNavigationWithTouchHandler \ 450 OverscrollNavigationWithTouchHandler 451#endif 452IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 453 MAYBE_OverscrollNavigationWithTouchHandler) { 454 TestOverscrollNavigation(true); 455} 456 457// Disabled because the test always fails the first time it runs on the Win Aura 458// bots, and usually but not always passes second-try (See crbug.com/179532). 459#if defined(OS_WIN) 460#define MAYBE_QuickOverscrollDirectionChange \ 461 DISABLED_QuickOverscrollDirectionChange 462#else 463#define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange 464#endif 465IN_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(); 472 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); 477 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()); 485 486 aura::Window* content = web_contents->GetContentNativeView(); 487 ui::EventProcessor* dispatcher = content->GetHost()->event_processor(); 488 gfx::Rect bounds = content->GetBoundsInRootWindow(); 489 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), 493 0, timestamp); 494 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); 495 ASSERT_FALSE(details.dispatcher_destroyed); 496 EXPECT_EQ(1, GetCurrentIndex()); 497 498 timestamp += base::TimeDelta::FromMilliseconds(10); 499 ui::TouchEvent move1(ui::ET_TOUCH_MOVED, 500 gfx::Point(bounds.right() - 10, bounds.y() + 5), 501 0, timestamp); 502 details = dispatcher->OnEventFromSource(&move1); 503 ASSERT_FALSE(details.dispatcher_destroyed); 504 EXPECT_EQ(1, GetCurrentIndex()); 505 506 // Swipe back from the right edge, back to the left edge, back to the right 507 // edge. 508 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), 513 0, timestamp); 514 details = dispatcher->OnEventFromSource(&inc); 515 ASSERT_FALSE(details.dispatcher_destroyed); 516 EXPECT_EQ(1, GetCurrentIndex()); 517 } 518 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), 523 0, timestamp); 524 details = dispatcher->OnEventFromSource(&inc); 525 ASSERT_FALSE(details.dispatcher_destroyed); 526 EXPECT_EQ(1, GetCurrentIndex()); 527 } 528 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), 533 0, timestamp); 534 details = dispatcher->OnEventFromSource(&inc); 535 ASSERT_FALSE(details.dispatcher_destroyed); 536 EXPECT_EQ(1, GetCurrentIndex()); 537 } 538 539 // Do not end the overscroll sequence. 540} 541 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 546// gesture. 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 553#else 554#define MAYBE_OverscrollScreenshot OverscrollScreenshot 555#endif 556IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) { 557 // Disable the test for WinXP. See http://crbug/294116. 558#if defined(OS_WIN) 559 if (base::win::GetVersion() < base::win::VERSION_VISTA) { 560 LOG(WARNING) << "Test disabled due to unknown bug on WinXP."; 561 return; 562 } 563#endif 564 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(); 570 571 set_min_screenshot_interval(0); 572 573 // Do a few navigations initiated by the page. 574 // Screenshots should never be captured since these are all in-page 575 // navigations. 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(); 581 582 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 583 web_contents->GetController().GetEntryAtIndex(2)); 584 EXPECT_FALSE(entry->screenshot().get()); 585 586 entry = NavigationEntryImpl::FromNavigationEntry( 587 web_contents->GetController().GetEntryAtIndex(1)); 588 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 589 590 entry = NavigationEntryImpl::FromNavigationEntry( 591 web_contents->GetController().GetEntryAtIndex(0)); 592 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 593 594 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 595 screenshot_manager()->WaitUntilScreenshotIsReady(); 596 597 entry = NavigationEntryImpl::FromNavigationEntry( 598 web_contents->GetController().GetEntryAtIndex(2)); 599 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 600 601 entry = NavigationEntryImpl::FromNavigationEntry( 602 web_contents->GetController().GetEntryAtIndex(3)); 603 EXPECT_FALSE(entry->screenshot().get()); 604 { 605 // Now, swipe right to navigate backwards. This should navigate away from 606 // index 3 to index 2. 607 base::string16 expected_title = base::ASCIIToUTF16("Title: #2"); 608 content::TitleWatcher title_watcher(web_contents, expected_title); 609 aura::Window* content = web_contents->GetContentNativeView(); 610 gfx::Rect bounds = content->GetBoundsInRootWindow(); 611 ui::test::EventGenerator generator(content->GetRootWindow(), content); 612 generator.GestureScrollSequence( 613 gfx::Point(bounds.x() + 2, bounds.y() + 10), 614 gfx::Point(bounds.right() - 10, bounds.y() + 10), 615 base::TimeDelta::FromMilliseconds(20), 616 1); 617 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 618 EXPECT_EQ(expected_title, actual_title); 619 EXPECT_EQ(2, GetCurrentIndex()); 620 screenshot_manager()->WaitUntilScreenshotIsReady(); 621 entry = NavigationEntryImpl::FromNavigationEntry( 622 web_contents->GetController().GetEntryAtIndex(3)); 623 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 624 } 625 626 // Navigate a couple more times. 627 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 628 EXPECT_EQ(3, GetCurrentIndex()); 629 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 630 EXPECT_EQ(4, GetCurrentIndex()); 631 screenshot_manager()->WaitUntilScreenshotIsReady(); 632 entry = NavigationEntryImpl::FromNavigationEntry( 633 web_contents->GetController().GetEntryAtIndex(4)); 634 EXPECT_FALSE(entry->screenshot().get()); 635 636 { 637 // Navigate back in history. 638 base::string16 expected_title = base::ASCIIToUTF16("Title: #3"); 639 content::TitleWatcher title_watcher(web_contents, expected_title); 640 web_contents->GetController().GoBack(); 641 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 642 EXPECT_EQ(expected_title, actual_title); 643 EXPECT_EQ(3, GetCurrentIndex()); 644 screenshot_manager()->WaitUntilScreenshotIsReady(); 645 entry = NavigationEntryImpl::FromNavigationEntry( 646 web_contents->GetController().GetEntryAtIndex(4)); 647 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 648 } 649} 650 651// Crashes under ThreadSanitizer, http://crbug.com/356758. 652#if defined(THREAD_SANITIZER) 653#define MAYBE_ScreenshotForSwappedOutRenderViews \ 654 DISABLED_ScreenshotForSwappedOutRenderViews 655#else 656#define MAYBE_ScreenshotForSwappedOutRenderViews \ 657 ScreenshotForSwappedOutRenderViews 658#endif 659// Tests that screenshot is taken correctly when navigation causes a 660// RenderViewHost to be swapped out. 661IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 662 MAYBE_ScreenshotForSwappedOutRenderViews) { 663 ASSERT_NO_FATAL_FAILURE( 664 StartTestWithPage("files/overscroll_navigation.html")); 665 // Create a new server with a different site. 666 net::SpawnedTestServer https_server( 667 net::SpawnedTestServer::TYPE_HTTPS, 668 net::SpawnedTestServer::kLocalhost, 669 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); 670 ASSERT_TRUE(https_server.Start()); 671 672 WebContentsImpl* web_contents = 673 static_cast<WebContentsImpl*>(shell()->web_contents()); 674 set_min_screenshot_interval(0); 675 676 struct { 677 GURL url; 678 int transition; 679 } navigations[] = { 680 { https_server.GetURL("files/title1.html"), 681 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR }, 682 { test_server()->GetURL("files/title2.html"), 683 ui::PAGE_TRANSITION_AUTO_BOOKMARK }, 684 { https_server.GetURL("files/title3.html"), 685 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR }, 686 { GURL(), 0 } 687 }; 688 689 screenshot_manager()->Reset(); 690 for (int i = 0; !navigations[i].url.is_empty(); ++i) { 691 // Navigate via the user initiating a navigation from the UI. 692 NavigationController::LoadURLParams params(navigations[i].url); 693 params.transition_type = 694 ui::PageTransitionFromInt(navigations[i].transition); 695 696 RenderViewHost* old_host = web_contents->GetRenderViewHost(); 697 web_contents->GetController().LoadURLWithParams(params); 698 WaitForLoadStop(web_contents); 699 screenshot_manager()->WaitUntilScreenshotIsReady(); 700 701 EXPECT_NE(old_host, web_contents->GetRenderViewHost()) 702 << navigations[i].url.spec(); 703 EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for()); 704 705 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 706 web_contents->GetController().GetEntryAtOffset(-1)); 707 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry)); 708 709 entry = NavigationEntryImpl::FromNavigationEntry( 710 web_contents->GetController().GetLastCommittedEntry()); 711 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 712 EXPECT_FALSE(entry->screenshot().get()); 713 screenshot_manager()->Reset(); 714 } 715 716 // Increase the minimum interval between taking screenshots. 717 set_min_screenshot_interval(60000); 718 719 // Navigate again. This should not take any screenshot because of the 720 // increased screenshot interval. 721 NavigationController::LoadURLParams params(navigations[0].url); 722 params.transition_type = ui::PageTransitionFromInt(navigations[0].transition); 723 web_contents->GetController().LoadURLWithParams(params); 724 WaitForLoadStop(web_contents); 725 screenshot_manager()->WaitUntilScreenshotIsReady(); 726 727 EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for()); 728} 729 730// Tests that navigations resulting from reloads, history.replaceState, 731// and history.pushState do not capture screenshots. 732IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ReplaceStateReloadPushState) { 733 ASSERT_NO_FATAL_FAILURE( 734 StartTestWithPage("files/overscroll_navigation.html")); 735 WebContentsImpl* web_contents = 736 static_cast<WebContentsImpl*>(shell()->web_contents()); 737 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 738 739 set_min_screenshot_interval(0); 740 screenshot_manager()->Reset(); 741 ExecuteSyncJSFunction(main_frame, "use_replace_state()"); 742 screenshot_manager()->WaitUntilScreenshotIsReady(); 743 // history.replaceState shouldn't capture a screenshot 744 EXPECT_FALSE(screenshot_manager()->screenshot_taken_for()); 745 screenshot_manager()->Reset(); 746 web_contents->GetController().Reload(true); 747 WaitForLoadStop(web_contents); 748 // reloading the page shouldn't capture a screenshot 749 // TODO (mfomitchev): currently broken. Uncomment when 750 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page 751 // is populated properly when reloading the page. 752 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for()); 753 screenshot_manager()->Reset(); 754 ExecuteSyncJSFunction(main_frame, "use_push_state()"); 755 screenshot_manager()->WaitUntilScreenshotIsReady(); 756 // pushing a state shouldn't capture a screenshot 757 // TODO (mfomitchev): currently broken. Uncomment when 758 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page 759 // is populated properly when pushState is used. 760 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for()); 761} 762 763// TODO(sadrul): This test is disabled because it reparents in a way the 764// FocusController does not support. This code would crash in 765// a production build. It only passed prior to this revision 766// because testing used the old FocusManager which did some 767// different (osbolete) processing. TODO(sadrul) to figure out 768// how this test should work that mimics production code a bit 769// better. 770IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 771 DISABLED_ContentWindowReparent) { 772 ASSERT_NO_FATAL_FAILURE( 773 StartTestWithPage("files/overscroll_navigation.html")); 774 775 scoped_ptr<aura::Window> window(new aura::Window(NULL)); 776 window->Init(aura::WINDOW_LAYER_NOT_DRAWN); 777 778 WebContentsImpl* web_contents = 779 static_cast<WebContentsImpl*>(shell()->web_contents()); 780 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); 781 EXPECT_EQ(1, GetCurrentIndex()); 782 783 aura::Window* content = web_contents->GetContentNativeView(); 784 gfx::Rect bounds = content->GetBoundsInRootWindow(); 785 ui::test::EventGenerator generator(content->GetRootWindow(), content); 786 generator.GestureScrollSequence( 787 gfx::Point(bounds.x() + 2, bounds.y() + 10), 788 gfx::Point(bounds.right() - 10, bounds.y() + 10), 789 base::TimeDelta::FromMilliseconds(20), 790 1); 791 792 window->AddChild(shell()->web_contents()->GetContentNativeView()); 793} 794 795IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) { 796 ASSERT_NO_FATAL_FAILURE( 797 StartTestWithPage("files/overscroll_navigation.html")); 798 799 WebContentsImpl* web_contents = 800 static_cast<WebContentsImpl*>(shell()->web_contents()); 801 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); 802 EXPECT_EQ(1, GetCurrentIndex()); 803 804 aura::Window* content = web_contents->GetContentNativeView(); 805 gfx::Rect bounds = content->GetBoundsInRootWindow(); 806 ui::test::EventGenerator generator(content->GetRootWindow(), content); 807 generator.GestureScrollSequence( 808 gfx::Point(bounds.x() + 2, bounds.y() + 10), 809 gfx::Point(bounds.right() - 10, bounds.y() + 10), 810 base::TimeDelta::FromMilliseconds(20), 811 1); 812 813 delete web_contents->GetContentNativeView(); 814} 815 816 817#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) 818// This appears to be flaky in the same was as the other overscroll 819// tests. Enabling for non-Windows platforms. 820// See http://crbug.com/369871. 821// For linux, see http://crbug.com/381294 822#define MAYBE_RepeatedQuickOverscrollGestures DISABLED_RepeatedQuickOverscrollGestures 823#else 824#define MAYBE_RepeatedQuickOverscrollGestures RepeatedQuickOverscrollGestures 825#endif 826 827IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 828 MAYBE_RepeatedQuickOverscrollGestures) { 829 ASSERT_NO_FATAL_FAILURE( 830 StartTestWithPage("files/overscroll_navigation.html")); 831 832 WebContentsImpl* web_contents = 833 static_cast<WebContentsImpl*>(shell()->web_contents()); 834 NavigationController& controller = web_contents->GetController(); 835 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 836 ExecuteSyncJSFunction(main_frame, "install_touch_handler()"); 837 838 // Navigate twice, then navigate back in history once. 839 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 840 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 841 EXPECT_EQ(2, GetCurrentIndex()); 842 EXPECT_TRUE(controller.CanGoBack()); 843 EXPECT_FALSE(controller.CanGoForward()); 844 845 web_contents->GetController().GoBack(); 846 WaitForLoadStop(web_contents); 847 EXPECT_EQ(1, GetCurrentIndex()); 848 EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents->GetTitle()); 849 EXPECT_TRUE(controller.CanGoBack()); 850 EXPECT_TRUE(controller.CanGoForward()); 851 852 aura::Window* content = web_contents->GetContentNativeView(); 853 gfx::Rect bounds = content->GetBoundsInRootWindow(); 854 ui::test::EventGenerator generator(content->GetRootWindow(), content); 855 856 // Do a swipe left to start a forward navigation. Then quickly do a swipe 857 // right. 858 base::string16 expected_title = base::ASCIIToUTF16("Title: #2"); 859 content::TitleWatcher title_watcher(web_contents, expected_title); 860 NavigationWatcher nav_watcher(web_contents); 861 862 generator.GestureScrollSequence( 863 gfx::Point(bounds.right() - 10, bounds.y() + 10), 864 gfx::Point(bounds.x() + 2, bounds.y() + 10), 865 base::TimeDelta::FromMilliseconds(2000), 866 10); 867 nav_watcher.WaitUntilNavigationStarts(); 868 869 generator.GestureScrollSequence( 870 gfx::Point(bounds.x() + 2, bounds.y() + 10), 871 gfx::Point(bounds.right() - 10, bounds.y() + 10), 872 base::TimeDelta::FromMilliseconds(2000), 873 10); 874 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 875 EXPECT_EQ(expected_title, actual_title); 876 877 EXPECT_EQ(2, GetCurrentIndex()); 878 EXPECT_TRUE(controller.CanGoBack()); 879 EXPECT_FALSE(controller.CanGoForward()); 880} 881 882// Verify that hiding a parent of the renderer will hide the content too. 883IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, HideContentOnParenHide) { 884 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/title1.html")); 885 WebContentsImpl* web_contents = 886 static_cast<WebContentsImpl*>(shell()->web_contents()); 887 aura::Window* content = web_contents->GetNativeView()->parent(); 888 EXPECT_TRUE(web_contents->should_normally_be_visible()); 889 content->Hide(); 890 EXPECT_FALSE(web_contents->should_normally_be_visible()); 891 content->Show(); 892 EXPECT_TRUE(web_contents->should_normally_be_visible()); 893} 894 895// Ensure that SnapToPhysicalPixelBoundary() is called on WebContentsView parent 896// change. This is a regression test for http://crbug.com/388908. 897IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, WebContentsViewReparent) { 898 ASSERT_NO_FATAL_FAILURE( 899 StartTestWithPage("files/overscroll_navigation.html")); 900 901 scoped_ptr<aura::Window> window(new aura::Window(NULL)); 902 window->Init(aura::WINDOW_LAYER_NOT_DRAWN); 903 904 RenderWidgetHostViewAura* rwhva = 905 static_cast<RenderWidgetHostViewAura*>( 906 shell()->web_contents()->GetRenderWidgetHostView()); 907 rwhva->ResetHasSnappedToBoundary(); 908 EXPECT_FALSE(rwhva->has_snapped_to_boundary()); 909 window->AddChild(shell()->web_contents()->GetNativeView()); 910 EXPECT_TRUE(rwhva->has_snapped_to_boundary()); 911} 912 913// Flaky on some platforms, likely for the same reason as other flaky overscroll 914// tests. http://crbug.com/305722 915// TODO(tdresser): Re-enable this once eager GR is back on. See 916// crbug.com/410280. 917#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) 918#define MAYBE_OverscrollNavigationTouchThrottling \ 919 DISABLED_OverscrollNavigationTouchThrottling 920#else 921#define MAYBE_OverscrollNavigationTouchThrottling \ 922 DISABLED_OverscrollNavigationTouchThrottling 923#endif 924 925// Tests that touch moves are not throttled when performing a scroll gesture on 926// a non-scrollable area, except during gesture-nav. 927IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 928 MAYBE_OverscrollNavigationTouchThrottling) { 929 ASSERT_NO_FATAL_FAILURE( 930 StartTestWithPage("files/overscroll_navigation.html")); 931 932 AddInputEventMessageFilter(); 933 934 WebContentsImpl* web_contents = 935 static_cast<WebContentsImpl*>(shell()->web_contents()); 936 aura::Window* content = web_contents->GetContentNativeView(); 937 gfx::Rect bounds = content->GetBoundsInRootWindow(); 938 const int dx = 20; 939 940 ExecuteSyncJSFunction(web_contents->GetMainFrame(), 941 "install_touchmove_handler()"); 942 943 WaitAFrame(); 944 945 for (int navigated = 0; navigated <= 1; ++navigated) { 946 if (navigated) { 947 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); 948 ExecuteSyncJSFunction(web_contents->GetMainFrame(), 949 "reset_touchmove_count()"); 950 } 951 // Send touch press. 952 SyntheticWebTouchEvent touch; 953 touch.PressPoint(bounds.x() + 2, bounds.y() + 10); 954 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, 955 ui::LatencyInfo()); 956 filter()->WaitForAck(blink::WebInputEvent::TouchStart); 957 WaitAFrame(); 958 959 // Assert on the ack, because we'll end up waiting for acks that will never 960 // come if this is not true. 961 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); 962 963 // Send first touch move, and then a scroll begin. 964 touch.MovePoint(0, bounds.x() + 20 + 1 * dx, bounds.y() + 100); 965 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, 966 ui::LatencyInfo()); 967 filter()->WaitForAck(blink::WebInputEvent::TouchMove); 968 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); 969 970 blink::WebGestureEvent scroll_begin = 971 SyntheticWebGestureEventBuilder::BuildScrollBegin(1, 1); 972 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo( 973 scroll_begin, ui::LatencyInfo()); 974 // Scroll begin ignores ack disposition, so don't wait for the ack. 975 WaitAFrame(); 976 977 // First touchmove already sent, start at 2. 978 for (int i = 2; i <= 10; ++i) { 979 // Send a touch move, followed by a scroll update 980 touch.MovePoint(0, bounds.x() + 20 + i * dx, bounds.y() + 100); 981 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo( 982 touch, ui::LatencyInfo()); 983 WaitAFrame(); 984 985 blink::WebGestureEvent scroll_update = 986 SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, 5, 0); 987 988 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo( 989 scroll_update, ui::LatencyInfo()); 990 991 WaitAFrame(); 992 } 993 994 touch.ReleasePoint(0); 995 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, 996 ui::LatencyInfo()); 997 WaitAFrame(); 998 999 blink::WebGestureEvent scroll_end; 1000 scroll_end.type = blink::WebInputEvent::GestureScrollEnd; 1001 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo( 1002 scroll_end, ui::LatencyInfo()); 1003 WaitAFrame(); 1004 1005 if (!navigated) 1006 EXPECT_EQ(10, ExecuteScriptAndExtractInt("touchmoveCount")); 1007 else 1008 EXPECT_GT(10, ExecuteScriptAndExtractInt("touchmoveCount")); 1009 } 1010} 1011 1012// Test that vertical overscroll updates are sent only when a user overscrolls 1013// vertically. 1014#if defined(OS_WIN) 1015#define MAYBE_VerticalOverscroll DISABLED_VerticalOverscroll 1016#else 1017#define MAYBE_VerticalOverscroll VerticalOverscroll 1018#endif 1019 1020IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_VerticalOverscroll) { 1021 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( 1022 switches::kScrollEndEffect, "1"); 1023 1024 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("about:blank")); 1025 WebContentsImpl* web_contents = 1026 static_cast<WebContentsImpl*>(shell()->web_contents()); 1027 VerticalOverscrollTracker tracker; 1028 web_contents->SetDelegate(&tracker); 1029 1030 // This test triggers a large number of animations. Speed them up to ensure 1031 // the test completes within its time limit. 1032 ui::ScopedAnimationDurationScaleMode fast_duration_mode( 1033 ui::ScopedAnimationDurationScaleMode::FAST_DURATION); 1034 1035 aura::Window* content = web_contents->GetContentNativeView(); 1036 ui::EventProcessor* dispatcher = content->GetHost()->event_processor(); 1037 gfx::Rect bounds = content->GetBoundsInRootWindow(); 1038 1039 // Overscroll horizontally. 1040 { 1041 int kXStep = bounds.width() / 10; 1042 gfx::Point location(bounds.right() - kXStep, bounds.y() + 5); 1043 base::TimeDelta timestamp = ui::EventTimeForNow(); 1044 ui::TouchEvent press( 1045 ui::ET_TOUCH_PRESSED, 1046 location, 1047 0, 1048 timestamp); 1049 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); 1050 ASSERT_FALSE(details.dispatcher_destroyed); 1051 WaitAFrame(); 1052 location -= gfx::Vector2d(kXStep, 0); 1053 timestamp += base::TimeDelta::FromMilliseconds(10); 1054 1055 while (location.x() > bounds.x() + kXStep) { 1056 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp); 1057 details = dispatcher->OnEventFromSource(&inc); 1058 ASSERT_FALSE(details.dispatcher_destroyed); 1059 WaitAFrame(); 1060 location -= gfx::Vector2d(10, 0); 1061 timestamp += base::TimeDelta::FromMilliseconds(10); 1062 } 1063 1064 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, location, 0, timestamp); 1065 details = dispatcher->OnEventFromSource(&press); 1066 ASSERT_FALSE(details.dispatcher_destroyed); 1067 WaitAFrame(); 1068 1069 EXPECT_EQ(0, tracker.num_overscroll_updates()); 1070 EXPECT_FALSE(tracker.overscroll_completed()); 1071 } 1072 1073 // Overscroll vertically. 1074 { 1075 tracker.Reset(); 1076 1077 int kYStep = bounds.height() / 10; 1078 gfx::Point location(bounds.x() + 10, bounds.y() + kYStep); 1079 base::TimeDelta timestamp = ui::EventTimeForNow(); 1080 ui::TouchEvent press( 1081 ui::ET_TOUCH_PRESSED, 1082 location, 1083 0, 1084 timestamp); 1085 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); 1086 ASSERT_FALSE(details.dispatcher_destroyed); 1087 WaitAFrame(); 1088 location += gfx::Vector2d(0, kYStep); 1089 timestamp += base::TimeDelta::FromMilliseconds(10); 1090 1091 while (location.y() < bounds.bottom() - kYStep) { 1092 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp); 1093 details = dispatcher->OnEventFromSource(&inc); 1094 ASSERT_FALSE(details.dispatcher_destroyed); 1095 WaitAFrame(); 1096 location += gfx::Vector2d(0, kYStep); 1097 timestamp += base::TimeDelta::FromMilliseconds(10); 1098 } 1099 1100 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, location, 0, timestamp); 1101 details = dispatcher->OnEventFromSource(&release); 1102 ASSERT_FALSE(details.dispatcher_destroyed); 1103 WaitAFrame(); 1104 1105 EXPECT_LT(0, tracker.num_overscroll_updates()); 1106 EXPECT_TRUE(tracker.overscroll_completed()); 1107 } 1108 1109 // Start out overscrolling vertically, then switch directions and finish 1110 // overscrolling horizontally. 1111 { 1112 tracker.Reset(); 1113 1114 int kXStep = bounds.width() / 10; 1115 int kYStep = bounds.height() / 10; 1116 gfx::Point location = bounds.origin() + gfx::Vector2d(0, kYStep); 1117 base::TimeDelta timestamp = ui::EventTimeForNow(); 1118 ui::TouchEvent press( 1119 ui::ET_TOUCH_PRESSED, 1120 location, 1121 0, 1122 timestamp); 1123 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); 1124 ASSERT_FALSE(details.dispatcher_destroyed); 1125 WaitAFrame(); 1126 location += gfx::Vector2d(0, kYStep); 1127 timestamp += base::TimeDelta::FromMilliseconds(10); 1128 1129 for (size_t i = 0; i < 3; ++i) { 1130 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp); 1131 details = dispatcher->OnEventFromSource(&inc); 1132 ASSERT_FALSE(details.dispatcher_destroyed); 1133 WaitAFrame(); 1134 location += gfx::Vector2d(0, kYStep); 1135 timestamp += base::TimeDelta::FromMilliseconds(10); 1136 } 1137 1138 while (location.x() < bounds.right() - kXStep) { 1139 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp); 1140 details = dispatcher->OnEventFromSource(&inc); 1141 ASSERT_FALSE(details.dispatcher_destroyed); 1142 WaitAFrame(); 1143 location += gfx::Vector2d(kXStep, 0); 1144 timestamp += base::TimeDelta::FromMilliseconds(10); 1145 } 1146 1147 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, location, 0, timestamp); 1148 details = dispatcher->OnEventFromSource(&release); 1149 ASSERT_FALSE(details.dispatcher_destroyed); 1150 WaitAFrame(); 1151 1152 EXPECT_LT(0, tracker.num_overscroll_updates()); 1153 EXPECT_FALSE(tracker.overscroll_completed()); 1154 } 1155} 1156 1157} // namespace content 1158