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/web_contents/web_contents_impl.h" 19 #include "content/browser/web_contents/web_contents_view.h" 20 #include "content/common/view_messages.h" 21 #include "content/public/browser/render_frame_host.h" 22 #include "content/public/browser/web_contents_observer.h" 23 #include "content/public/common/content_switches.h" 24 #include "content/public/test/browser_test_utils.h" 25 #include "content/public/test/content_browser_test.h" 26 #include "content/public/test/content_browser_test_utils.h" 27 #include "content/public/test/test_renderer_host.h" 28 #include "content/public/test/test_utils.h" 29 #include "content/shell/browser/shell.h" 30 #include "ui/aura/test/event_generator.h" 31 #include "ui/aura/window.h" 32 #include "ui/aura/window_tree_host.h" 33 #include "ui/compositor/scoped_animation_duration_scale_mode.h" 34 #include "ui/events/event_processor.h" 35 #include "ui/events/event_utils.h" 36 37 namespace content { 38 39 // This class keeps track of the RenderViewHost whose screenshot was captured. 40 class ScreenshotTracker : public NavigationEntryScreenshotManager { 41 public: 42 explicit ScreenshotTracker(NavigationControllerImpl* controller) 43 : NavigationEntryScreenshotManager(controller), 44 screenshot_taken_for_(NULL), 45 waiting_for_screenshots_(0) { 46 } 47 48 virtual ~ScreenshotTracker() { 49 } 50 51 RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; } 52 53 void Reset() { 54 screenshot_taken_for_ = NULL; 55 screenshot_set_.clear(); 56 } 57 58 void SetScreenshotInterval(int interval_ms) { 59 SetMinScreenshotIntervalMS(interval_ms); 60 } 61 62 void WaitUntilScreenshotIsReady() { 63 if (!waiting_for_screenshots_) 64 return; 65 message_loop_runner_ = new content::MessageLoopRunner; 66 message_loop_runner_->Run(); 67 } 68 69 bool ScreenshotSetForEntry(NavigationEntryImpl* entry) const { 70 return screenshot_set_.count(entry) > 0; 71 } 72 73 private: 74 // Overridden from NavigationEntryScreenshotManager: 75 virtual void TakeScreenshotImpl(RenderViewHost* host, 76 NavigationEntryImpl* entry) OVERRIDE { 77 ++waiting_for_screenshots_; 78 screenshot_taken_for_ = host; 79 NavigationEntryScreenshotManager::TakeScreenshotImpl(host, entry); 80 } 81 82 virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE { 83 --waiting_for_screenshots_; 84 screenshot_set_[entry] = true; 85 NavigationEntryScreenshotManager::OnScreenshotSet(entry); 86 if (waiting_for_screenshots_ == 0 && message_loop_runner_.get()) 87 message_loop_runner_->Quit(); 88 } 89 90 RenderViewHost* screenshot_taken_for_; 91 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 92 int waiting_for_screenshots_; 93 std::map<NavigationEntryImpl*, bool> screenshot_set_; 94 95 DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker); 96 }; 97 98 class NavigationWatcher : public WebContentsObserver { 99 public: 100 explicit NavigationWatcher(WebContents* contents) 101 : WebContentsObserver(contents), 102 navigated_(false), 103 should_quit_loop_(false) { 104 } 105 106 virtual ~NavigationWatcher() {} 107 108 void WaitUntilNavigationStarts() { 109 if (navigated_) 110 return; 111 should_quit_loop_ = true; 112 base::MessageLoop::current()->Run(); 113 } 114 115 private: 116 // Overridden from WebContentsObserver: 117 virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE { 118 navigated_ = true; 119 if (should_quit_loop_) 120 base::MessageLoop::current()->Quit(); 121 } 122 123 bool navigated_; 124 bool should_quit_loop_; 125 126 DISALLOW_COPY_AND_ASSIGN(NavigationWatcher); 127 }; 128 129 class WebContentsViewAuraTest : public ContentBrowserTest { 130 public: 131 WebContentsViewAuraTest() 132 : screenshot_manager_(NULL) { 133 } 134 135 // Executes the javascript synchronously and makes sure the returned value is 136 // freed properly. 137 void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) { 138 scoped_ptr<base::Value> value = 139 content::ExecuteScriptAndGetValue(rfh, jscript); 140 } 141 142 // Starts the test server and navigates to the given url. Sets a large enough 143 // size to the root window. Returns after the navigation to the url is 144 // complete. 145 void StartTestWithPage(const std::string& url) { 146 ASSERT_TRUE(test_server()->Start()); 147 GURL test_url(test_server()->GetURL(url)); 148 NavigateToURL(shell(), test_url); 149 150 WebContentsImpl* web_contents = 151 static_cast<WebContentsImpl*>(shell()->web_contents()); 152 NavigationControllerImpl* controller = &web_contents->GetController(); 153 154 screenshot_manager_ = new ScreenshotTracker(controller); 155 controller->SetScreenshotManager(screenshot_manager_); 156 } 157 158 void TestOverscrollNavigation(bool touch_handler) { 159 ASSERT_NO_FATAL_FAILURE( 160 StartTestWithPage("files/overscroll_navigation.html")); 161 WebContentsImpl* web_contents = 162 static_cast<WebContentsImpl*>(shell()->web_contents()); 163 NavigationController& controller = web_contents->GetController(); 164 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 165 166 EXPECT_FALSE(controller.CanGoBack()); 167 EXPECT_FALSE(controller.CanGoForward()); 168 int index = -1; 169 scoped_ptr<base::Value> value = 170 content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 171 ASSERT_TRUE(value->GetAsInteger(&index)); 172 EXPECT_EQ(0, index); 173 174 if (touch_handler) 175 ExecuteSyncJSFunction(main_frame, "install_touch_handler()"); 176 177 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 178 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 179 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 180 ASSERT_TRUE(value->GetAsInteger(&index)); 181 EXPECT_EQ(2, index); 182 EXPECT_TRUE(controller.CanGoBack()); 183 EXPECT_FALSE(controller.CanGoForward()); 184 185 aura::Window* content = web_contents->GetContentNativeView(); 186 gfx::Rect bounds = content->GetBoundsInRootWindow(); 187 aura::test::EventGenerator generator(content->GetRootWindow(), content); 188 const int kScrollDurationMs = 20; 189 const int kScrollSteps = 10; 190 191 { 192 // Do a swipe-right now. That should navigate backwards. 193 base::string16 expected_title = base::ASCIIToUTF16("Title: #1"); 194 content::TitleWatcher title_watcher(web_contents, expected_title); 195 generator.GestureScrollSequence( 196 gfx::Point(bounds.x() + 2, bounds.y() + 10), 197 gfx::Point(bounds.right() - 10, bounds.y() + 10), 198 base::TimeDelta::FromMilliseconds(kScrollDurationMs), 199 kScrollSteps); 200 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 201 EXPECT_EQ(expected_title, actual_title); 202 value = content::ExecuteScriptAndGetValue(main_frame, "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 // Do a fling-right now. That should navigate backwards. 211 base::string16 expected_title = base::ASCIIToUTF16("Title:"); 212 content::TitleWatcher title_watcher(web_contents, expected_title); 213 generator.GestureScrollSequence( 214 gfx::Point(bounds.x() + 2, bounds.y() + 10), 215 gfx::Point(bounds.right() - 10, bounds.y() + 10), 216 base::TimeDelta::FromMilliseconds(kScrollDurationMs), 217 kScrollSteps); 218 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 219 EXPECT_EQ(expected_title, actual_title); 220 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 221 ASSERT_TRUE(value->GetAsInteger(&index)); 222 EXPECT_EQ(0, index); 223 EXPECT_FALSE(controller.CanGoBack()); 224 EXPECT_TRUE(controller.CanGoForward()); 225 } 226 227 { 228 // Do a swipe-left now. That should navigate forward. 229 base::string16 expected_title = base::ASCIIToUTF16("Title: #1"); 230 content::TitleWatcher title_watcher(web_contents, expected_title); 231 generator.GestureScrollSequence( 232 gfx::Point(bounds.right() - 10, bounds.y() + 10), 233 gfx::Point(bounds.x() + 2, bounds.y() + 10), 234 base::TimeDelta::FromMilliseconds(kScrollDurationMs), 235 kScrollSteps); 236 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 237 EXPECT_EQ(expected_title, actual_title); 238 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 239 ASSERT_TRUE(value->GetAsInteger(&index)); 240 EXPECT_EQ(1, index); 241 EXPECT_TRUE(controller.CanGoBack()); 242 EXPECT_TRUE(controller.CanGoForward()); 243 } 244 } 245 246 int GetCurrentIndex() { 247 WebContentsImpl* web_contents = 248 static_cast<WebContentsImpl*>(shell()->web_contents()); 249 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 250 int index = -1; 251 scoped_ptr<base::Value> value; 252 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()"); 253 if (!value->GetAsInteger(&index)) 254 index = -1; 255 return index; 256 } 257 258 protected: 259 ScreenshotTracker* screenshot_manager() { return screenshot_manager_; } 260 void set_min_screenshot_interval(int interval_ms) { 261 screenshot_manager_->SetScreenshotInterval(interval_ms); 262 } 263 264 private: 265 ScreenshotTracker* screenshot_manager_; 266 267 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest); 268 }; 269 270 // Flaky on Windows and ChromeOS: http://crbug.com/305722 271 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 272 DISABLED_OverscrollNavigation) { 273 TestOverscrollNavigation(false); 274 } 275 276 // Flaky on Windows (might be related to the above test): 277 // http://crbug.com/305722 278 #if defined(OS_WIN) 279 #define MAYBE_OverscrollNavigationWithTouchHandler \ 280 DISABLED_OverscrollNavigationWithTouchHandler 281 #else 282 #define MAYBE_OverscrollNavigationWithTouchHandler \ 283 OverscrollNavigationWithTouchHandler 284 #endif 285 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 286 MAYBE_OverscrollNavigationWithTouchHandler) { 287 TestOverscrollNavigation(true); 288 } 289 290 // Disabled because the test always fails the first time it runs on the Win Aura 291 // bots, and usually but not always passes second-try (See crbug.com/179532). 292 #if defined(OS_WIN) 293 #define MAYBE_QuickOverscrollDirectionChange \ 294 DISABLED_QuickOverscrollDirectionChange 295 #else 296 #define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange 297 #endif 298 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 299 MAYBE_QuickOverscrollDirectionChange) { 300 ASSERT_NO_FATAL_FAILURE( 301 StartTestWithPage("files/overscroll_navigation.html")); 302 WebContentsImpl* web_contents = 303 static_cast<WebContentsImpl*>(shell()->web_contents()); 304 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 305 306 // This test triggers a large number of animations. Speed them up to ensure 307 // the test completes within its time limit. 308 ui::ScopedAnimationDurationScaleMode fast_duration_mode( 309 ui::ScopedAnimationDurationScaleMode::FAST_DURATION); 310 311 // Make sure the page has both back/forward history. 312 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 313 EXPECT_EQ(1, GetCurrentIndex()); 314 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 315 EXPECT_EQ(2, GetCurrentIndex()); 316 web_contents->GetController().GoBack(); 317 EXPECT_EQ(1, GetCurrentIndex()); 318 319 aura::Window* content = web_contents->GetContentNativeView(); 320 ui::EventProcessor* dispatcher = content->GetHost()->event_processor(); 321 gfx::Rect bounds = content->GetBoundsInRootWindow(); 322 323 base::TimeDelta timestamp = ui::EventTimeForNow(); 324 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, 325 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), 326 0, timestamp); 327 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); 328 ASSERT_FALSE(details.dispatcher_destroyed); 329 EXPECT_EQ(1, GetCurrentIndex()); 330 331 timestamp += base::TimeDelta::FromMilliseconds(10); 332 ui::TouchEvent move1(ui::ET_TOUCH_MOVED, 333 gfx::Point(bounds.right() - 10, bounds.y() + 5), 334 0, timestamp); 335 details = dispatcher->OnEventFromSource(&move1); 336 ASSERT_FALSE(details.dispatcher_destroyed); 337 EXPECT_EQ(1, GetCurrentIndex()); 338 339 // Swipe back from the right edge, back to the left edge, back to the right 340 // edge. 341 342 for (int x = bounds.right() - 10; x >= bounds.x() + 10; x-= 10) { 343 timestamp += base::TimeDelta::FromMilliseconds(10); 344 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 345 gfx::Point(x, bounds.y() + 5), 346 0, timestamp); 347 details = dispatcher->OnEventFromSource(&inc); 348 ASSERT_FALSE(details.dispatcher_destroyed); 349 EXPECT_EQ(1, GetCurrentIndex()); 350 } 351 352 for (int x = bounds.x() + 10; x <= bounds.width() - 10; x+= 10) { 353 timestamp += base::TimeDelta::FromMilliseconds(10); 354 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 355 gfx::Point(x, bounds.y() + 5), 356 0, timestamp); 357 details = dispatcher->OnEventFromSource(&inc); 358 ASSERT_FALSE(details.dispatcher_destroyed); 359 EXPECT_EQ(1, GetCurrentIndex()); 360 } 361 362 for (int x = bounds.width() - 10; x >= bounds.x() + 10; x-= 10) { 363 timestamp += base::TimeDelta::FromMilliseconds(10); 364 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 365 gfx::Point(x, bounds.y() + 5), 366 0, timestamp); 367 details = dispatcher->OnEventFromSource(&inc); 368 ASSERT_FALSE(details.dispatcher_destroyed); 369 EXPECT_EQ(1, GetCurrentIndex()); 370 } 371 372 // Do not end the overscroll sequence. 373 } 374 375 // Tests that the page has has a screenshot when navigation happens: 376 // - from within the page (from a JS function) 377 // - interactively, when user does an overscroll gesture 378 // - interactively, when user navigates in history without the overscroll 379 // gesture. 380 // Flaky on Windows and ChromeOS (http://crbug.com/357311). Might be related to 381 // OverscrollNavigation test. 382 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, DISABLED_OverscrollScreenshot) { 383 // Disable the test for WinXP. See http://crbug/294116. 384 #if defined(OS_WIN) 385 if (base::win::GetVersion() < base::win::VERSION_VISTA) { 386 LOG(WARNING) << "Test disabled due to unknown bug on WinXP."; 387 return; 388 } 389 #endif 390 391 ASSERT_NO_FATAL_FAILURE( 392 StartTestWithPage("files/overscroll_navigation.html")); 393 WebContentsImpl* web_contents = 394 static_cast<WebContentsImpl*>(shell()->web_contents()); 395 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 396 397 set_min_screenshot_interval(0); 398 399 // Do a few navigations initiated by the page. 400 // Screenshots should never be captured since these are all in-page 401 // navigations. 402 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 403 EXPECT_EQ(1, GetCurrentIndex()); 404 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 405 EXPECT_EQ(2, GetCurrentIndex()); 406 screenshot_manager()->WaitUntilScreenshotIsReady(); 407 408 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 409 web_contents->GetController().GetEntryAtIndex(2)); 410 EXPECT_FALSE(entry->screenshot().get()); 411 412 entry = NavigationEntryImpl::FromNavigationEntry( 413 web_contents->GetController().GetEntryAtIndex(1)); 414 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 415 416 entry = NavigationEntryImpl::FromNavigationEntry( 417 web_contents->GetController().GetEntryAtIndex(0)); 418 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 419 420 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 421 screenshot_manager()->WaitUntilScreenshotIsReady(); 422 423 entry = NavigationEntryImpl::FromNavigationEntry( 424 web_contents->GetController().GetEntryAtIndex(2)); 425 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 426 427 entry = NavigationEntryImpl::FromNavigationEntry( 428 web_contents->GetController().GetEntryAtIndex(3)); 429 EXPECT_FALSE(entry->screenshot().get()); 430 { 431 // Now, swipe right to navigate backwards. This should navigate away from 432 // index 3 to index 2. 433 base::string16 expected_title = base::ASCIIToUTF16("Title: #2"); 434 content::TitleWatcher title_watcher(web_contents, expected_title); 435 aura::Window* content = web_contents->GetContentNativeView(); 436 gfx::Rect bounds = content->GetBoundsInRootWindow(); 437 aura::test::EventGenerator generator(content->GetRootWindow(), content); 438 generator.GestureScrollSequence( 439 gfx::Point(bounds.x() + 2, bounds.y() + 10), 440 gfx::Point(bounds.right() - 10, bounds.y() + 10), 441 base::TimeDelta::FromMilliseconds(20), 442 1); 443 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 444 EXPECT_EQ(expected_title, actual_title); 445 EXPECT_EQ(2, GetCurrentIndex()); 446 screenshot_manager()->WaitUntilScreenshotIsReady(); 447 entry = NavigationEntryImpl::FromNavigationEntry( 448 web_contents->GetController().GetEntryAtIndex(3)); 449 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 450 } 451 452 // Navigate a couple more times. 453 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 454 EXPECT_EQ(3, GetCurrentIndex()); 455 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 456 EXPECT_EQ(4, GetCurrentIndex()); 457 screenshot_manager()->WaitUntilScreenshotIsReady(); 458 entry = NavigationEntryImpl::FromNavigationEntry( 459 web_contents->GetController().GetEntryAtIndex(4)); 460 EXPECT_FALSE(entry->screenshot().get()); 461 462 { 463 // Navigate back in history. 464 base::string16 expected_title = base::ASCIIToUTF16("Title: #3"); 465 content::TitleWatcher title_watcher(web_contents, expected_title); 466 web_contents->GetController().GoBack(); 467 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 468 EXPECT_EQ(expected_title, actual_title); 469 EXPECT_EQ(3, GetCurrentIndex()); 470 screenshot_manager()->WaitUntilScreenshotIsReady(); 471 entry = NavigationEntryImpl::FromNavigationEntry( 472 web_contents->GetController().GetEntryAtIndex(4)); 473 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 474 } 475 } 476 477 // Crashes under ThreadSanitizer, http://crbug.com/356758. 478 #if defined(THREAD_SANITIZER) 479 #define MAYBE_ScreenshotForSwappedOutRenderViews \ 480 DISABLED_ScreenshotForSwappedOutRenderViews 481 #else 482 #define MAYBE_ScreenshotForSwappedOutRenderViews \ 483 ScreenshotForSwappedOutRenderViews 484 #endif 485 // Tests that screenshot is taken correctly when navigation causes a 486 // RenderViewHost to be swapped out. 487 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 488 MAYBE_ScreenshotForSwappedOutRenderViews) { 489 ASSERT_NO_FATAL_FAILURE( 490 StartTestWithPage("files/overscroll_navigation.html")); 491 // Create a new server with a different site. 492 net::SpawnedTestServer https_server( 493 net::SpawnedTestServer::TYPE_HTTPS, 494 net::SpawnedTestServer::kLocalhost, 495 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); 496 ASSERT_TRUE(https_server.Start()); 497 498 WebContentsImpl* web_contents = 499 static_cast<WebContentsImpl*>(shell()->web_contents()); 500 set_min_screenshot_interval(0); 501 502 struct { 503 GURL url; 504 int transition; 505 } navigations[] = { 506 { https_server.GetURL("files/title1.html"), 507 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR }, 508 { test_server()->GetURL("files/title2.html"), 509 PAGE_TRANSITION_AUTO_BOOKMARK }, 510 { https_server.GetURL("files/title3.html"), 511 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR }, 512 { GURL(), 0 } 513 }; 514 515 screenshot_manager()->Reset(); 516 for (int i = 0; !navigations[i].url.is_empty(); ++i) { 517 // Navigate via the user initiating a navigation from the UI. 518 NavigationController::LoadURLParams params(navigations[i].url); 519 params.transition_type = PageTransitionFromInt(navigations[i].transition); 520 521 RenderViewHost* old_host = web_contents->GetRenderViewHost(); 522 web_contents->GetController().LoadURLWithParams(params); 523 WaitForLoadStop(web_contents); 524 screenshot_manager()->WaitUntilScreenshotIsReady(); 525 526 EXPECT_NE(old_host, web_contents->GetRenderViewHost()) 527 << navigations[i].url.spec(); 528 EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for()); 529 530 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 531 web_contents->GetController().GetEntryAtOffset(-1)); 532 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry)); 533 534 entry = NavigationEntryImpl::FromNavigationEntry( 535 web_contents->GetController().GetLastCommittedEntry()); 536 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry)); 537 EXPECT_FALSE(entry->screenshot().get()); 538 screenshot_manager()->Reset(); 539 } 540 541 // Increase the minimum interval between taking screenshots. 542 set_min_screenshot_interval(60000); 543 544 // Navigate again. This should not take any screenshot because of the 545 // increased screenshot interval. 546 NavigationController::LoadURLParams params(navigations[0].url); 547 params.transition_type = PageTransitionFromInt(navigations[0].transition); 548 web_contents->GetController().LoadURLWithParams(params); 549 WaitForLoadStop(web_contents); 550 screenshot_manager()->WaitUntilScreenshotIsReady(); 551 552 EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for()); 553 } 554 555 // Tests that navigations resulting from reloads, history.replaceState, 556 // and history.pushState do not capture screenshots. 557 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ReplaceStateReloadPushState) { 558 ASSERT_NO_FATAL_FAILURE( 559 StartTestWithPage("files/overscroll_navigation.html")); 560 WebContentsImpl* web_contents = 561 static_cast<WebContentsImpl*>(shell()->web_contents()); 562 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 563 564 set_min_screenshot_interval(0); 565 screenshot_manager()->Reset(); 566 ExecuteSyncJSFunction(main_frame, "use_replace_state()"); 567 screenshot_manager()->WaitUntilScreenshotIsReady(); 568 // history.replaceState shouldn't capture a screenshot 569 EXPECT_FALSE(screenshot_manager()->screenshot_taken_for()); 570 screenshot_manager()->Reset(); 571 web_contents->GetController().Reload(true); 572 WaitForLoadStop(web_contents); 573 // reloading the page shouldn't capture a screenshot 574 // TODO (mfomitchev): currently broken. Uncomment when 575 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page 576 // is populated properly when reloading the page. 577 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for()); 578 screenshot_manager()->Reset(); 579 ExecuteSyncJSFunction(main_frame, "use_push_state()"); 580 screenshot_manager()->WaitUntilScreenshotIsReady(); 581 // pushing a state shouldn't capture a screenshot 582 // TODO (mfomitchev): currently broken. Uncomment when 583 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page 584 // is populated properly when pushState is used. 585 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for()); 586 } 587 588 // TODO(sadrul): This test is disabled because it reparents in a way the 589 // FocusController does not support. This code would crash in 590 // a production build. It only passed prior to this revision 591 // because testing used the old FocusManager which did some 592 // different (osbolete) processing. TODO(sadrul) to figure out 593 // how this test should work that mimics production code a bit 594 // better. 595 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 596 DISABLED_ContentWindowReparent) { 597 ASSERT_NO_FATAL_FAILURE( 598 StartTestWithPage("files/overscroll_navigation.html")); 599 600 scoped_ptr<aura::Window> window(new aura::Window(NULL)); 601 window->Init(aura::WINDOW_LAYER_NOT_DRAWN); 602 603 WebContentsImpl* web_contents = 604 static_cast<WebContentsImpl*>(shell()->web_contents()); 605 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); 606 EXPECT_EQ(1, GetCurrentIndex()); 607 608 aura::Window* content = web_contents->GetContentNativeView(); 609 gfx::Rect bounds = content->GetBoundsInRootWindow(); 610 aura::test::EventGenerator generator(content->GetRootWindow(), content); 611 generator.GestureScrollSequence( 612 gfx::Point(bounds.x() + 2, bounds.y() + 10), 613 gfx::Point(bounds.right() - 10, bounds.y() + 10), 614 base::TimeDelta::FromMilliseconds(20), 615 1); 616 617 window->AddChild(shell()->web_contents()->GetContentNativeView()); 618 } 619 620 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) { 621 ASSERT_NO_FATAL_FAILURE( 622 StartTestWithPage("files/overscroll_navigation.html")); 623 624 WebContentsImpl* web_contents = 625 static_cast<WebContentsImpl*>(shell()->web_contents()); 626 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()"); 627 EXPECT_EQ(1, GetCurrentIndex()); 628 629 aura::Window* content = web_contents->GetContentNativeView(); 630 gfx::Rect bounds = content->GetBoundsInRootWindow(); 631 aura::test::EventGenerator generator(content->GetRootWindow(), content); 632 generator.GestureScrollSequence( 633 gfx::Point(bounds.x() + 2, bounds.y() + 10), 634 gfx::Point(bounds.right() - 10, bounds.y() + 10), 635 base::TimeDelta::FromMilliseconds(20), 636 1); 637 638 delete web_contents->GetContentNativeView(); 639 } 640 641 642 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) 643 // This appears to be flaky in the same was as the other overscroll 644 // tests. Enabling for non-Windows platforms. 645 // See http://crbug.com/369871. 646 // For linux, see http://crbug.com/381294 647 #define MAYBE_RepeatedQuickOverscrollGestures DISABLED_RepeatedQuickOverscrollGestures 648 #else 649 #define MAYBE_RepeatedQuickOverscrollGestures RepeatedQuickOverscrollGestures 650 #endif 651 652 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 653 MAYBE_RepeatedQuickOverscrollGestures) { 654 ASSERT_NO_FATAL_FAILURE( 655 StartTestWithPage("files/overscroll_navigation.html")); 656 657 WebContentsImpl* web_contents = 658 static_cast<WebContentsImpl*>(shell()->web_contents()); 659 NavigationController& controller = web_contents->GetController(); 660 RenderFrameHost* main_frame = web_contents->GetMainFrame(); 661 ExecuteSyncJSFunction(main_frame, "install_touch_handler()"); 662 663 // Navigate twice, then navigate back in history once. 664 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 665 ExecuteSyncJSFunction(main_frame, "navigate_next()"); 666 EXPECT_EQ(2, GetCurrentIndex()); 667 EXPECT_TRUE(controller.CanGoBack()); 668 EXPECT_FALSE(controller.CanGoForward()); 669 670 web_contents->GetController().GoBack(); 671 WaitForLoadStop(web_contents); 672 EXPECT_EQ(1, GetCurrentIndex()); 673 EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents->GetTitle()); 674 EXPECT_TRUE(controller.CanGoBack()); 675 EXPECT_TRUE(controller.CanGoForward()); 676 677 aura::Window* content = web_contents->GetContentNativeView(); 678 gfx::Rect bounds = content->GetBoundsInRootWindow(); 679 aura::test::EventGenerator generator(content->GetRootWindow(), content); 680 681 // Do a swipe left to start a forward navigation. Then quickly do a swipe 682 // right. 683 base::string16 expected_title = base::ASCIIToUTF16("Title: #2"); 684 content::TitleWatcher title_watcher(web_contents, expected_title); 685 NavigationWatcher nav_watcher(web_contents); 686 687 generator.GestureScrollSequence( 688 gfx::Point(bounds.right() - 10, bounds.y() + 10), 689 gfx::Point(bounds.x() + 2, bounds.y() + 10), 690 base::TimeDelta::FromMilliseconds(2000), 691 10); 692 nav_watcher.WaitUntilNavigationStarts(); 693 694 generator.GestureScrollSequence( 695 gfx::Point(bounds.x() + 2, bounds.y() + 10), 696 gfx::Point(bounds.right() - 10, bounds.y() + 10), 697 base::TimeDelta::FromMilliseconds(2000), 698 10); 699 base::string16 actual_title = title_watcher.WaitAndGetTitle(); 700 EXPECT_EQ(expected_title, actual_title); 701 702 EXPECT_EQ(2, GetCurrentIndex()); 703 EXPECT_TRUE(controller.CanGoBack()); 704 EXPECT_FALSE(controller.CanGoForward()); 705 } 706 707 // Verify that hiding a parent of the renderer will hide the content too. 708 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, HideContentOnParenHide) { 709 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/title1.html")); 710 WebContentsImpl* web_contents = 711 static_cast<WebContentsImpl*>(shell()->web_contents()); 712 aura::Window* content = web_contents->GetNativeView()->parent(); 713 EXPECT_TRUE(web_contents->should_normally_be_visible()); 714 content->Hide(); 715 EXPECT_FALSE(web_contents->should_normally_be_visible()); 716 content->Show(); 717 EXPECT_TRUE(web_contents->should_normally_be_visible()); 718 } 719 720 } // namespace content 721