Home | History | Annotate | Download | only in web_contents
      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