web_contents_view_aura_browsertest.cc revision c2db58bd994c04d98e4ee2cd7565b71548655fe3
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#include "content/browser/renderer_host/render_view_host_impl.h" 13#include "content/browser/web_contents/navigation_controller_impl.h" 14#include "content/browser/web_contents/navigation_entry_impl.h" 15#include "content/browser/web_contents/web_contents_impl.h" 16#include "content/browser/web_contents/web_contents_screenshot_manager.h" 17#include "content/public/browser/web_contents_view.h" 18#include "content/public/common/content_switches.h" 19#include "content/public/test/browser_test_utils.h" 20#include "content/public/test/test_utils.h" 21#include "content/shell/shell.h" 22#include "content/test/content_browser_test.h" 23#include "content/test/content_browser_test_utils.h" 24#include "ui/aura/root_window.h" 25#include "ui/aura/test/event_generator.h" 26#include "ui/aura/window.h" 27#include "ui/compositor/scoped_animation_duration_scale_mode.h" 28 29namespace content { 30 31// This class keeps track of the RenderViewHost whose screenshot was captured. 32class ScreenshotTracker : public WebContentsScreenshotManager { 33 public: 34 explicit ScreenshotTracker(NavigationControllerImpl* controller) 35 : WebContentsScreenshotManager(controller), 36 screenshot_taken_for_(NULL), 37 waiting_for_screenshots_(0) { 38 } 39 40 virtual ~ScreenshotTracker() { 41 } 42 43 RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; } 44 45 void Reset() { 46 screenshot_taken_for_ = NULL; 47 } 48 49 void SetScreenshotInterval(int interval_ms) { 50 SetMinScreenshotIntervalMS(interval_ms); 51 } 52 53 void WaitUntilScreenshotIsReady() { 54 if (!waiting_for_screenshots_) 55 return; 56 message_loop_runner_ = new content::MessageLoopRunner; 57 message_loop_runner_->Run(); 58 } 59 60 private: 61 // Overridden from WebContentsScreenshotManager: 62 virtual void TakeScreenshotImpl(RenderViewHost* host, 63 NavigationEntryImpl* entry) OVERRIDE { 64 ++waiting_for_screenshots_; 65 screenshot_taken_for_ = host; 66 WebContentsScreenshotManager::TakeScreenshotImpl(host, entry); 67 } 68 69 virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE { 70 --waiting_for_screenshots_; 71 WebContentsScreenshotManager::OnScreenshotSet(entry); 72 if (waiting_for_screenshots_ == 0 && message_loop_runner_.get()) 73 message_loop_runner_->Quit(); 74 } 75 76 RenderViewHost* screenshot_taken_for_; 77 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 78 int waiting_for_screenshots_; 79 80 DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker); 81}; 82 83class WebContentsViewAuraTest : public ContentBrowserTest { 84 public: 85 WebContentsViewAuraTest() 86 : screenshot_manager_(NULL) { 87 } 88 89 virtual void SetUp() OVERRIDE { 90 // TODO(jbauman): Remove this. http://crbug.com/268644 91 UseRealGLContexts(); 92 } 93 94 // Executes the javascript synchronously and makes sure the returned value is 95 // freed properly. 96 void ExecuteSyncJSFunction(RenderViewHost* rvh, const std::string& jscript) { 97 scoped_ptr<base::Value> value = 98 content::ExecuteScriptAndGetValue(rvh, jscript); 99 } 100 101 // Starts the test server and navigates to the given url. Sets a large enough 102 // size to the root window. Returns after the navigation to the url is 103 // complete. 104 void StartTestWithPage(const std::string& url) { 105 ASSERT_TRUE(test_server()->Start()); 106 GURL test_url(test_server()->GetURL(url)); 107 NavigateToURL(shell(), test_url); 108 aura::Window* content = 109 shell()->web_contents()->GetView()->GetContentNativeView(); 110 content->GetRootWindow()->SetHostSize(gfx::Size(800, 600)); 111 112 WebContentsImpl* web_contents = 113 static_cast<WebContentsImpl*>(shell()->web_contents()); 114 NavigationControllerImpl* controller = &web_contents->GetController(); 115 116 screenshot_manager_ = new ScreenshotTracker(controller); 117 controller->SetScreenshotManager(screenshot_manager_); 118 } 119 120 void TestOverscrollNavigation(bool touch_handler) { 121 ASSERT_NO_FATAL_FAILURE( 122 StartTestWithPage("files/overscroll_navigation.html")); 123 WebContentsImpl* web_contents = 124 static_cast<WebContentsImpl*>(shell()->web_contents()); 125 NavigationController& controller = web_contents->GetController(); 126 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 127 web_contents->GetRenderViewHost()); 128 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>( 129 web_contents->GetView()); 130 view_aura->SetupOverlayWindowForTesting(); 131 132 EXPECT_FALSE(controller.CanGoBack()); 133 EXPECT_FALSE(controller.CanGoForward()); 134 int index = -1; 135 scoped_ptr<base::Value> value = 136 content::ExecuteScriptAndGetValue(view_host, "get_current()"); 137 ASSERT_TRUE(value->GetAsInteger(&index)); 138 EXPECT_EQ(0, index); 139 140 if (touch_handler) 141 ExecuteSyncJSFunction(view_host, "install_touch_handler()"); 142 143 ExecuteSyncJSFunction(view_host, "navigate_next()"); 144 ExecuteSyncJSFunction(view_host, "navigate_next()"); 145 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 146 ASSERT_TRUE(value->GetAsInteger(&index)); 147 EXPECT_EQ(2, index); 148 EXPECT_TRUE(controller.CanGoBack()); 149 EXPECT_FALSE(controller.CanGoForward()); 150 151 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 152 gfx::Rect bounds = content->GetBoundsInRootWindow(); 153 aura::test::EventGenerator generator(content->GetRootWindow(), content); 154 155 { 156 // Do a swipe-right now. That should navigate backwards. 157 string16 expected_title = ASCIIToUTF16("Title: #1"); 158 content::TitleWatcher title_watcher(web_contents, expected_title); 159 generator.GestureScrollSequence( 160 gfx::Point(bounds.x() + 2, bounds.y() + 10), 161 gfx::Point(bounds.right() - 10, bounds.y() + 10), 162 base::TimeDelta::FromMilliseconds(20), 163 1); 164 string16 actual_title = title_watcher.WaitAndGetTitle(); 165 EXPECT_EQ(expected_title, actual_title); 166 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 167 ASSERT_TRUE(value->GetAsInteger(&index)); 168 EXPECT_EQ(1, index); 169 EXPECT_TRUE(controller.CanGoBack()); 170 EXPECT_TRUE(controller.CanGoForward()); 171 } 172 173 { 174 // Do a fling-right now. That should navigate backwards. 175 string16 expected_title = ASCIIToUTF16("Title:"); 176 content::TitleWatcher title_watcher(web_contents, expected_title); 177 generator.GestureScrollSequence( 178 gfx::Point(bounds.x() + 2, bounds.y() + 10), 179 gfx::Point(bounds.right() - 10, bounds.y() + 10), 180 base::TimeDelta::FromMilliseconds(20), 181 10); 182 string16 actual_title = title_watcher.WaitAndGetTitle(); 183 EXPECT_EQ(expected_title, actual_title); 184 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 185 ASSERT_TRUE(value->GetAsInteger(&index)); 186 EXPECT_EQ(0, index); 187 EXPECT_FALSE(controller.CanGoBack()); 188 EXPECT_TRUE(controller.CanGoForward()); 189 } 190 191 { 192 // Do a swipe-left now. That should navigate forward. 193 string16 expected_title = ASCIIToUTF16("Title: #1"); 194 content::TitleWatcher title_watcher(web_contents, expected_title); 195 generator.GestureScrollSequence( 196 gfx::Point(bounds.right() - 10, bounds.y() + 10), 197 gfx::Point(bounds.x() + 2, bounds.y() + 10), 198 base::TimeDelta::FromMilliseconds(20), 199 10); 200 string16 actual_title = title_watcher.WaitAndGetTitle(); 201 EXPECT_EQ(expected_title, actual_title); 202 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 203 ASSERT_TRUE(value->GetAsInteger(&index)); 204 EXPECT_EQ(1, index); 205 EXPECT_TRUE(controller.CanGoBack()); 206 EXPECT_TRUE(controller.CanGoForward()); 207 } 208 } 209 210 int GetCurrentIndex() { 211 WebContentsImpl* web_contents = 212 static_cast<WebContentsImpl*>(shell()->web_contents()); 213 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 214 web_contents->GetRenderViewHost()); 215 int index = -1; 216 scoped_ptr<base::Value> value; 217 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 218 if (!value->GetAsInteger(&index)) 219 index = -1; 220 return index; 221 } 222 223 protected: 224 ScreenshotTracker* screenshot_manager() { return screenshot_manager_; } 225 void set_min_screenshot_interval(int interval_ms) { 226 screenshot_manager_->SetScreenshotInterval(interval_ms); 227 } 228 229 private: 230 ScreenshotTracker* screenshot_manager_; 231 232 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest); 233}; 234 235IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 236 OverscrollNavigation) { 237 TestOverscrollNavigation(false); 238} 239 240IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 241 OverscrollNavigationWithTouchHandler) { 242 TestOverscrollNavigation(true); 243} 244 245// Disabled because the test always fails the first time it runs on the Win Aura 246// bots, and usually but not always passes second-try (See crbug.com/179532). 247#if defined(OS_WIN) 248#define MAYBE_QuickOverscrollDirectionChange \ 249 DISABLED_QuickOverscrollDirectionChange 250#else 251#define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange 252#endif 253IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 254 MAYBE_QuickOverscrollDirectionChange) { 255 ASSERT_NO_FATAL_FAILURE( 256 StartTestWithPage("files/overscroll_navigation.html")); 257 WebContentsImpl* web_contents = 258 static_cast<WebContentsImpl*>(shell()->web_contents()); 259 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 260 web_contents->GetRenderViewHost()); 261 262 // This test triggers a large number of animations. Speed them up to ensure 263 // the test completes within its time limit. 264 ui::ScopedAnimationDurationScaleMode fast_duration_mode( 265 ui::ScopedAnimationDurationScaleMode::FAST_DURATION); 266 267 // Make sure the page has both back/forward history. 268 ExecuteSyncJSFunction(view_host, "navigate_next()"); 269 EXPECT_EQ(1, GetCurrentIndex()); 270 ExecuteSyncJSFunction(view_host, "navigate_next()"); 271 EXPECT_EQ(2, GetCurrentIndex()); 272 web_contents->GetController().GoBack(); 273 EXPECT_EQ(1, GetCurrentIndex()); 274 275 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 276 aura::RootWindow* root_window = content->GetRootWindow(); 277 gfx::Rect bounds = content->GetBoundsInRootWindow(); 278 279 base::TimeDelta timestamp; 280 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, 281 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), 282 0, timestamp); 283 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&press); 284 EXPECT_EQ(1, GetCurrentIndex()); 285 286 timestamp += base::TimeDelta::FromMilliseconds(10); 287 ui::TouchEvent move1(ui::ET_TOUCH_MOVED, 288 gfx::Point(bounds.right() - 10, bounds.y() + 5), 289 0, timestamp); 290 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1); 291 EXPECT_EQ(1, GetCurrentIndex()); 292 293 // Swipe back from the right edge, back to the left edge, back to the right 294 // edge. 295 296 for (int x = bounds.right() - 10; x >= bounds.x() + 10; x-= 10) { 297 timestamp += base::TimeDelta::FromMilliseconds(10); 298 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 299 gfx::Point(x, bounds.y() + 5), 300 0, timestamp); 301 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc); 302 EXPECT_EQ(1, GetCurrentIndex()); 303 } 304 305 for (int x = bounds.x() + 10; x <= bounds.width() - 10; x+= 10) { 306 timestamp += base::TimeDelta::FromMilliseconds(10); 307 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 308 gfx::Point(x, bounds.y() + 5), 309 0, timestamp); 310 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc); 311 EXPECT_EQ(1, GetCurrentIndex()); 312 } 313 314 for (int x = bounds.width() - 10; x >= bounds.x() + 10; x-= 10) { 315 timestamp += base::TimeDelta::FromMilliseconds(10); 316 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 317 gfx::Point(x, bounds.y() + 5), 318 0, timestamp); 319 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc); 320 EXPECT_EQ(1, GetCurrentIndex()); 321 } 322 323 // Do not end the overscroll sequence. 324} 325 326// Tests that the page has has a screenshot when navigation happens: 327// - from within the page (from a JS function) 328// - interactively, when user does an overscroll gesture 329// - interactively, when user navigates in history without the overscroll 330// gesture. 331IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 332 OverscrollScreenshot) { 333 ASSERT_NO_FATAL_FAILURE( 334 StartTestWithPage("files/overscroll_navigation.html")); 335 WebContentsImpl* web_contents = 336 static_cast<WebContentsImpl*>(shell()->web_contents()); 337 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 338 web_contents->GetRenderViewHost()); 339 340 set_min_screenshot_interval(0); 341 342 // Do a few navigations initiated by the page. 343 ExecuteSyncJSFunction(view_host, "navigate_next()"); 344 EXPECT_EQ(1, GetCurrentIndex()); 345 ExecuteSyncJSFunction(view_host, "navigate_next()"); 346 EXPECT_EQ(2, GetCurrentIndex()); 347 screenshot_manager()->WaitUntilScreenshotIsReady(); 348 349 // The current entry won't have any screenshots. But the entries in the 350 // history should now have screenshots. 351 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 352 web_contents->GetController().GetEntryAtIndex(2)); 353 EXPECT_FALSE(entry->screenshot().get()); 354 355 entry = NavigationEntryImpl::FromNavigationEntry( 356 web_contents->GetController().GetEntryAtIndex(1)); 357 EXPECT_TRUE(entry->screenshot().get()); 358 359 entry = NavigationEntryImpl::FromNavigationEntry( 360 web_contents->GetController().GetEntryAtIndex(0)); 361 EXPECT_TRUE(entry->screenshot().get()); 362 363 // Navigate again. Index 2 should now have a screenshot. 364 ExecuteSyncJSFunction(view_host, "navigate_next()"); 365 EXPECT_EQ(3, GetCurrentIndex()); 366 screenshot_manager()->WaitUntilScreenshotIsReady(); 367 368 entry = NavigationEntryImpl::FromNavigationEntry( 369 web_contents->GetController().GetEntryAtIndex(2)); 370 EXPECT_TRUE(entry->screenshot().get()); 371 372 entry = NavigationEntryImpl::FromNavigationEntry( 373 web_contents->GetController().GetEntryAtIndex(3)); 374 EXPECT_FALSE(entry->screenshot().get()); 375 376 { 377 // Now, swipe right to navigate backwards. This should navigate away from 378 // index 3 to index 2, and index 3 should have a screenshot. 379 string16 expected_title = ASCIIToUTF16("Title: #2"); 380 content::TitleWatcher title_watcher(web_contents, expected_title); 381 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 382 gfx::Rect bounds = content->GetBoundsInRootWindow(); 383 aura::test::EventGenerator generator(content->GetRootWindow(), content); 384 generator.GestureScrollSequence( 385 gfx::Point(bounds.x() + 2, bounds.y() + 10), 386 gfx::Point(bounds.right() - 10, bounds.y() + 10), 387 base::TimeDelta::FromMilliseconds(20), 388 1); 389 string16 actual_title = title_watcher.WaitAndGetTitle(); 390 EXPECT_EQ(expected_title, actual_title); 391 EXPECT_EQ(2, GetCurrentIndex()); 392 screenshot_manager()->WaitUntilScreenshotIsReady(); 393 entry = NavigationEntryImpl::FromNavigationEntry( 394 web_contents->GetController().GetEntryAtIndex(3)); 395 EXPECT_TRUE(entry->screenshot().get()); 396 } 397 398 // Navigate a couple more times. 399 ExecuteSyncJSFunction(view_host, "navigate_next()"); 400 EXPECT_EQ(3, GetCurrentIndex()); 401 ExecuteSyncJSFunction(view_host, "navigate_next()"); 402 EXPECT_EQ(4, GetCurrentIndex()); 403 screenshot_manager()->WaitUntilScreenshotIsReady(); 404 entry = NavigationEntryImpl::FromNavigationEntry( 405 web_contents->GetController().GetEntryAtIndex(4)); 406 EXPECT_FALSE(entry->screenshot().get()); 407 408 { 409 // Navigate back in history. 410 string16 expected_title = ASCIIToUTF16("Title: #3"); 411 content::TitleWatcher title_watcher(web_contents, expected_title); 412 web_contents->GetController().GoBack(); 413 string16 actual_title = title_watcher.WaitAndGetTitle(); 414 EXPECT_EQ(expected_title, actual_title); 415 EXPECT_EQ(3, GetCurrentIndex()); 416 screenshot_manager()->WaitUntilScreenshotIsReady(); 417 entry = NavigationEntryImpl::FromNavigationEntry( 418 web_contents->GetController().GetEntryAtIndex(4)); 419 EXPECT_TRUE(entry->screenshot().get()); 420 } 421} 422 423// Tests that screenshot is taken correctly when navigation causes a 424// RenderViewHost to be swapped out. 425IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 426 ScreenshotForSwappedOutRenderViews) { 427 ASSERT_NO_FATAL_FAILURE( 428 StartTestWithPage("files/overscroll_navigation.html")); 429 // Create a new server with a different site. 430 net::SpawnedTestServer https_server( 431 net::SpawnedTestServer::TYPE_HTTPS, 432 net::SpawnedTestServer::kLocalhost, 433 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); 434 ASSERT_TRUE(https_server.Start()); 435 436 WebContentsImpl* web_contents = 437 static_cast<WebContentsImpl*>(shell()->web_contents()); 438 set_min_screenshot_interval(0); 439 440 struct { 441 GURL url; 442 int transition; 443 } navigations[] = { 444 { https_server.GetURL("files/title1.html"), 445 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR }, 446 { test_server()->GetURL("files/title2.html"), 447 PAGE_TRANSITION_AUTO_BOOKMARK }, 448 { https_server.GetURL("files/title3.html"), 449 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR }, 450 { GURL(), 0 } 451 }; 452 453 screenshot_manager()->Reset(); 454 for (int i = 0; !navigations[i].url.is_empty(); ++i) { 455 // Navigate via the user initiating a navigation from the UI. 456 NavigationController::LoadURLParams params(navigations[i].url); 457 params.transition_type = PageTransitionFromInt(navigations[i].transition); 458 459 RenderViewHost* old_host = web_contents->GetRenderViewHost(); 460 web_contents->GetController().LoadURLWithParams(params); 461 WaitForLoadStop(web_contents); 462 screenshot_manager()->WaitUntilScreenshotIsReady(); 463 464 EXPECT_NE(old_host, web_contents->GetRenderViewHost()) 465 << navigations[i].url.spec(); 466 EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for()); 467 screenshot_manager()->Reset(); 468 469 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 470 web_contents->GetController().GetEntryAtOffset(-1)); 471 EXPECT_TRUE(entry->screenshot().get()); 472 473 entry = NavigationEntryImpl::FromNavigationEntry( 474 web_contents->GetController().GetActiveEntry()); 475 EXPECT_FALSE(entry->screenshot().get()); 476 } 477 478 // Increase the minimum interval between taking screenshots. 479 set_min_screenshot_interval(60000); 480 481 // Navigate again. This should not take any screenshot because of the 482 // increased screenshot interval. 483 NavigationController::LoadURLParams params(navigations[0].url); 484 params.transition_type = PageTransitionFromInt(navigations[0].transition); 485 web_contents->GetController().LoadURLWithParams(params); 486 WaitForLoadStop(web_contents); 487 screenshot_manager()->WaitUntilScreenshotIsReady(); 488 489 EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for()); 490} 491 492// Failing on win7_aura trybot (see crbug.com/260983). 493#if defined(OS_WIN) 494#define MAYBE_ContentWindowReparent \ 495 DISABLED_ContentWindowReparent 496#else 497#define MAYBE_ContentWindowReparent ContentWindowReparent 498#endif 499IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 500 MAYBE_ContentWindowReparent) { 501 ASSERT_NO_FATAL_FAILURE( 502 StartTestWithPage("files/overscroll_navigation.html")); 503 504 scoped_ptr<aura::Window> window(new aura::Window(NULL)); 505 window->Init(ui::LAYER_NOT_DRAWN); 506 507 WebContentsImpl* web_contents = 508 static_cast<WebContentsImpl*>(shell()->web_contents()); 509 ExecuteSyncJSFunction(web_contents->GetRenderViewHost(), "navigate_next()"); 510 EXPECT_EQ(1, GetCurrentIndex()); 511 512 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 513 gfx::Rect bounds = content->GetBoundsInRootWindow(); 514 aura::test::EventGenerator generator(content->GetRootWindow(), content); 515 generator.GestureScrollSequence( 516 gfx::Point(bounds.x() + 2, bounds.y() + 10), 517 gfx::Point(bounds.right() - 10, bounds.y() + 10), 518 base::TimeDelta::FromMilliseconds(20), 519 1); 520 521 window->AddChild(shell()->web_contents()->GetView()->GetContentNativeView()); 522} 523 524IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 525 ContentWindowClose) { 526 ASSERT_NO_FATAL_FAILURE( 527 StartTestWithPage("files/overscroll_navigation.html")); 528 529 WebContentsImpl* web_contents = 530 static_cast<WebContentsImpl*>(shell()->web_contents()); 531 ExecuteSyncJSFunction(web_contents->GetRenderViewHost(), "navigate_next()"); 532 EXPECT_EQ(1, GetCurrentIndex()); 533 534 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 535 gfx::Rect bounds = content->GetBoundsInRootWindow(); 536 aura::test::EventGenerator generator(content->GetRootWindow(), content); 537 generator.GestureScrollSequence( 538 gfx::Point(bounds.x() + 2, bounds.y() + 10), 539 gfx::Point(bounds.right() - 10, bounds.y() + 10), 540 base::TimeDelta::FromMilliseconds(20), 541 1); 542 543 delete web_contents->GetView()->GetContentNativeView(); 544} 545 546IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 547 RepeatedQuickOverscrollGestures) { 548 ASSERT_NO_FATAL_FAILURE( 549 StartTestWithPage("files/overscroll_navigation.html")); 550 551 WebContentsImpl* web_contents = 552 static_cast<WebContentsImpl*>(shell()->web_contents()); 553 NavigationController& controller = web_contents->GetController(); 554 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 555 web_contents->GetRenderViewHost()); 556 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>( 557 web_contents->GetView()); 558 view_aura->SetupOverlayWindowForTesting(); 559 ExecuteSyncJSFunction(view_host, "install_touch_handler()"); 560 561 // Navigate twice, then navigate back in history once. 562 ExecuteSyncJSFunction(view_host, "navigate_next()"); 563 ExecuteSyncJSFunction(view_host, "navigate_next()"); 564 EXPECT_EQ(2, GetCurrentIndex()); 565 EXPECT_TRUE(controller.CanGoBack()); 566 EXPECT_FALSE(controller.CanGoForward()); 567 568 web_contents->GetController().GoBack(); 569 WaitForLoadStop(web_contents); 570 EXPECT_EQ(1, GetCurrentIndex()); 571 EXPECT_TRUE(controller.CanGoBack()); 572 EXPECT_TRUE(controller.CanGoForward()); 573 574 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 575 gfx::Rect bounds = content->GetBoundsInRootWindow(); 576 aura::test::EventGenerator generator(content->GetRootWindow(), content); 577 578 // Do a swipe left to start a forward navigation. Then quickly do a swipe 579 // right. 580 string16 expected_title = ASCIIToUTF16("Title: #2"); 581 content::TitleWatcher title_watcher(web_contents, expected_title); 582 583 generator.GestureScrollSequence( 584 gfx::Point(bounds.right() - 10, bounds.y() + 10), 585 gfx::Point(bounds.x() + 2, bounds.y() + 10), 586 base::TimeDelta::FromMilliseconds(2000), 587 10); 588 // Make sure the GestureEventFilter's debouncing doesn't interfere. 589 base::MessageLoop::current()->PostDelayedTask( 590 FROM_HERE, 591 base::MessageLoop::QuitClosure(), 592 base::TimeDelta::FromMilliseconds(100)); 593 base::MessageLoop::current()->Run(); 594 generator.GestureScrollSequence( 595 gfx::Point(bounds.x() + 2, bounds.y() + 10), 596 gfx::Point(bounds.right() - 10, bounds.y() + 10), 597 base::TimeDelta::FromMilliseconds(2000), 598 10); 599 string16 actual_title = title_watcher.WaitAndGetTitle(); 600 EXPECT_EQ(expected_title, actual_title); 601 602 EXPECT_EQ(2, GetCurrentIndex()); 603 EXPECT_TRUE(controller.CanGoBack()); 604 EXPECT_FALSE(controller.CanGoForward()); 605} 606 607} // namespace content 608