This source file includes following definitions.
- waiting_for_screenshots_
- screenshot_taken_for
- Reset
- SetScreenshotInterval
- WaitUntilScreenshotIsReady
- ScreenshotSetForEntry
- TakeScreenshotImpl
- OnScreenshotSet
- should_quit_loop_
- WaitUntilNavigationStarts
- AboutToNavigateRenderView
- ExecuteSyncJSFunction
- StartTestWithPage
- TestOverscrollNavigation
- GetCurrentIndex
- screenshot_manager
- set_min_screenshot_interval
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
- IN_PROC_BROWSER_TEST_F
#include "content/browser/web_contents/web_contents_view_aura.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_timeouts.h"
#include "base/values.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/event_processor.h"
namespace content {
class ScreenshotTracker : public NavigationEntryScreenshotManager {
public:
explicit ScreenshotTracker(NavigationControllerImpl* controller)
: NavigationEntryScreenshotManager(controller),
screenshot_taken_for_(NULL),
waiting_for_screenshots_(0) {
}
virtual ~ScreenshotTracker() {
}
RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; }
void Reset() {
screenshot_taken_for_ = NULL;
screenshot_set_.clear();
}
void SetScreenshotInterval(int interval_ms) {
SetMinScreenshotIntervalMS(interval_ms);
}
void WaitUntilScreenshotIsReady() {
if (!waiting_for_screenshots_)
return;
message_loop_runner_ = new content::MessageLoopRunner;
message_loop_runner_->Run();
}
bool ScreenshotSetForEntry(NavigationEntryImpl* entry) const {
return screenshot_set_.count(entry) > 0;
}
private:
virtual void TakeScreenshotImpl(RenderViewHost* host,
NavigationEntryImpl* entry) OVERRIDE {
++waiting_for_screenshots_;
screenshot_taken_for_ = host;
NavigationEntryScreenshotManager::TakeScreenshotImpl(host, entry);
}
virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE {
--waiting_for_screenshots_;
screenshot_set_[entry] = true;
NavigationEntryScreenshotManager::OnScreenshotSet(entry);
if (waiting_for_screenshots_ == 0 && message_loop_runner_.get())
message_loop_runner_->Quit();
}
RenderViewHost* screenshot_taken_for_;
scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
int waiting_for_screenshots_;
std::map<NavigationEntryImpl*, bool> screenshot_set_;
DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker);
};
class NavigationWatcher : public WebContentsObserver {
public:
explicit NavigationWatcher(WebContents* contents)
: WebContentsObserver(contents),
navigated_(false),
should_quit_loop_(false) {
}
virtual ~NavigationWatcher() {}
void WaitUntilNavigationStarts() {
if (navigated_)
return;
should_quit_loop_ = true;
base::MessageLoop::current()->Run();
}
private:
virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE {
navigated_ = true;
if (should_quit_loop_)
base::MessageLoop::current()->Quit();
}
bool navigated_;
bool should_quit_loop_;
DISALLOW_COPY_AND_ASSIGN(NavigationWatcher);
};
class WebContentsViewAuraTest : public ContentBrowserTest {
public:
WebContentsViewAuraTest()
: screenshot_manager_(NULL) {
}
void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) {
scoped_ptr<base::Value> value =
content::ExecuteScriptAndGetValue(rfh, jscript);
}
void StartTestWithPage(const std::string& url) {
ASSERT_TRUE(test_server()->Start());
GURL test_url(test_server()->GetURL(url));
NavigateToURL(shell(), test_url);
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
NavigationControllerImpl* controller = &web_contents->GetController();
screenshot_manager_ = new ScreenshotTracker(controller);
controller->SetScreenshotManager(screenshot_manager_);
}
void TestOverscrollNavigation(bool touch_handler) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
NavigationController& controller = web_contents->GetController();
RenderFrameHost* main_frame = web_contents->GetMainFrame();
WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
web_contents->GetView());
view_aura->SetupOverlayWindowForTesting();
EXPECT_FALSE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
int index = -1;
scoped_ptr<base::Value> value =
content::ExecuteScriptAndGetValue(main_frame, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
EXPECT_EQ(0, index);
if (touch_handler)
ExecuteSyncJSFunction(main_frame, "install_touch_handler()");
ExecuteSyncJSFunction(main_frame, "navigate_next()");
ExecuteSyncJSFunction(main_frame, "navigate_next()");
value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
EXPECT_EQ(2, index);
EXPECT_TRUE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
aura::Window* content = web_contents->GetView()->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
aura::test::EventGenerator generator(content->GetRootWindow(), content);
const int kScrollDurationMs = 20;
const int kScrollSteps = 10;
{
base::string16 expected_title = base::ASCIIToUTF16("Title: #1");
content::TitleWatcher title_watcher(web_contents, expected_title);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(kScrollDurationMs),
kScrollSteps);
base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
EXPECT_EQ(1, index);
EXPECT_TRUE(controller.CanGoBack());
EXPECT_TRUE(controller.CanGoForward());
}
{
base::string16 expected_title = base::ASCIIToUTF16("Title:");
content::TitleWatcher title_watcher(web_contents, expected_title);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(kScrollDurationMs),
kScrollSteps);
base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
EXPECT_EQ(0, index);
EXPECT_FALSE(controller.CanGoBack());
EXPECT_TRUE(controller.CanGoForward());
}
{
base::string16 expected_title = base::ASCIIToUTF16("Title: #1");
content::TitleWatcher title_watcher(web_contents, expected_title);
generator.GestureScrollSequence(
gfx::Point(bounds.right() - 10, bounds.y() + 10),
gfx::Point(bounds.x() + 2, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(kScrollDurationMs),
kScrollSteps);
base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
ASSERT_TRUE(value->GetAsInteger(&index));
EXPECT_EQ(1, index);
EXPECT_TRUE(controller.CanGoBack());
EXPECT_TRUE(controller.CanGoForward());
}
}
int GetCurrentIndex() {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
RenderFrameHost* main_frame = web_contents->GetMainFrame();
int index = -1;
scoped_ptr<base::Value> value;
value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
if (!value->GetAsInteger(&index))
index = -1;
return index;
}
protected:
ScreenshotTracker* screenshot_manager() { return screenshot_manager_; }
void set_min_screenshot_interval(int interval_ms) {
screenshot_manager_->SetScreenshotInterval(interval_ms);
}
private:
ScreenshotTracker* screenshot_manager_;
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
};
#if defined(OS_WIN)
#define MAYBE_OverscrollNavigation DISABLED_OverscrollNavigation
#else
#define MAYBE_OverscrollNavigation OverscrollNavigation
#endif
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollNavigation) {
TestOverscrollNavigation(false);
}
#if defined(OS_WIN)
#define MAYBE_OverscrollNavigationWithTouchHandler \
DISABLED_OverscrollNavigationWithTouchHandler
#else
#define MAYBE_OverscrollNavigationWithTouchHandler \
OverscrollNavigationWithTouchHandler
#endif
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
MAYBE_OverscrollNavigationWithTouchHandler) {
TestOverscrollNavigation(true);
}
#if defined(OS_WIN)
#define MAYBE_QuickOverscrollDirectionChange \
DISABLED_QuickOverscrollDirectionChange
#else
#define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange
#endif
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
MAYBE_QuickOverscrollDirectionChange) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
RenderFrameHost* main_frame = web_contents->GetMainFrame();
ui::ScopedAnimationDurationScaleMode fast_duration_mode(
ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(1, GetCurrentIndex());
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(2, GetCurrentIndex());
web_contents->GetController().GoBack();
EXPECT_EQ(1, GetCurrentIndex());
aura::Window* content = web_contents->GetView()->GetContentNativeView();
ui::EventProcessor* dispatcher = content->GetHost()->event_processor();
gfx::Rect bounds = content->GetBoundsInRootWindow();
base::TimeDelta timestamp;
ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
0, timestamp);
ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(1, GetCurrentIndex());
timestamp += base::TimeDelta::FromMilliseconds(10);
ui::TouchEvent move1(ui::ET_TOUCH_MOVED,
gfx::Point(bounds.right() - 10, bounds.y() + 5),
0, timestamp);
details = dispatcher->OnEventFromSource(&move1);
ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(1, GetCurrentIndex());
for (int x = bounds.right() - 10; x >= bounds.x() + 10; x-= 10) {
timestamp += base::TimeDelta::FromMilliseconds(10);
ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
gfx::Point(x, bounds.y() + 5),
0, timestamp);
details = dispatcher->OnEventFromSource(&inc);
ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(1, GetCurrentIndex());
}
for (int x = bounds.x() + 10; x <= bounds.width() - 10; x+= 10) {
timestamp += base::TimeDelta::FromMilliseconds(10);
ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
gfx::Point(x, bounds.y() + 5),
0, timestamp);
details = dispatcher->OnEventFromSource(&inc);
ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(1, GetCurrentIndex());
}
for (int x = bounds.width() - 10; x >= bounds.x() + 10; x-= 10) {
timestamp += base::TimeDelta::FromMilliseconds(10);
ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
gfx::Point(x, bounds.y() + 5),
0, timestamp);
details = dispatcher->OnEventFromSource(&inc);
ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(1, GetCurrentIndex());
}
}
#if defined(OS_WIN)
#define MAYBE_OverscrollScreenshot DISABLED_OverscrollScreenshot
#else
#define MAYBE_OverscrollScreenshot OverscrollScreenshot
#endif
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) {
#if defined(OS_WIN)
if (base::win::GetVersion() < base::win::VERSION_VISTA) {
LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
return;
}
#endif
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
RenderFrameHost* main_frame = web_contents->GetMainFrame();
set_min_screenshot_interval(0);
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(1, GetCurrentIndex());
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(2, GetCurrentIndex());
screenshot_manager()->WaitUntilScreenshotIsReady();
NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(2));
EXPECT_FALSE(entry->screenshot().get());
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(1));
EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(0));
EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(3, GetCurrentIndex());
screenshot_manager()->WaitUntilScreenshotIsReady();
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(2));
EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(3));
EXPECT_FALSE(entry->screenshot().get());
{
base::string16 expected_title = base::ASCIIToUTF16("Title: #2");
content::TitleWatcher title_watcher(web_contents, expected_title);
aura::Window* content = web_contents->GetView()->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
aura::test::EventGenerator generator(content->GetRootWindow(), content);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(20),
1);
base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
EXPECT_EQ(2, GetCurrentIndex());
screenshot_manager()->WaitUntilScreenshotIsReady();
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(3));
EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
}
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(3, GetCurrentIndex());
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(4, GetCurrentIndex());
screenshot_manager()->WaitUntilScreenshotIsReady();
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(4));
EXPECT_FALSE(entry->screenshot().get());
{
base::string16 expected_title = base::ASCIIToUTF16("Title: #3");
content::TitleWatcher title_watcher(web_contents, expected_title);
web_contents->GetController().GoBack();
base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
EXPECT_EQ(3, GetCurrentIndex());
screenshot_manager()->WaitUntilScreenshotIsReady();
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtIndex(4));
EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
}
}
#if defined(THREAD_SANITIZER)
#define MAYBE_ScreenshotForSwappedOutRenderViews \
DISABLED_ScreenshotForSwappedOutRenderViews
#else
#define MAYBE_ScreenshotForSwappedOutRenderViews \
ScreenshotForSwappedOutRenderViews
#endif
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
MAYBE_ScreenshotForSwappedOutRenderViews) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
net::SpawnedTestServer https_server(
net::SpawnedTestServer::TYPE_HTTPS,
net::SpawnedTestServer::kLocalhost,
base::FilePath(FILE_PATH_LITERAL("content/test/data")));
ASSERT_TRUE(https_server.Start());
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
set_min_screenshot_interval(0);
struct {
GURL url;
int transition;
} navigations[] = {
{ https_server.GetURL("files/title1.html"),
PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
{ test_server()->GetURL("files/title2.html"),
PAGE_TRANSITION_AUTO_BOOKMARK },
{ https_server.GetURL("files/title3.html"),
PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
{ GURL(), 0 }
};
screenshot_manager()->Reset();
for (int i = 0; !navigations[i].url.is_empty(); ++i) {
NavigationController::LoadURLParams params(navigations[i].url);
params.transition_type = PageTransitionFromInt(navigations[i].transition);
RenderViewHost* old_host = web_contents->GetRenderViewHost();
web_contents->GetController().LoadURLWithParams(params);
WaitForLoadStop(web_contents);
screenshot_manager()->WaitUntilScreenshotIsReady();
EXPECT_NE(old_host, web_contents->GetRenderViewHost())
<< navigations[i].url.spec();
EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for());
NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetEntryAtOffset(-1));
EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
entry = NavigationEntryImpl::FromNavigationEntry(
web_contents->GetController().GetLastCommittedEntry());
EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
EXPECT_FALSE(entry->screenshot().get());
screenshot_manager()->Reset();
}
set_min_screenshot_interval(60000);
NavigationController::LoadURLParams params(navigations[0].url);
params.transition_type = PageTransitionFromInt(navigations[0].transition);
web_contents->GetController().LoadURLWithParams(params);
WaitForLoadStop(web_contents);
screenshot_manager()->WaitUntilScreenshotIsReady();
EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for());
}
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
DISABLED_ContentWindowReparent) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
scoped_ptr<aura::Window> window(new aura::Window(NULL));
window->Init(aura::WINDOW_LAYER_NOT_DRAWN);
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
EXPECT_EQ(1, GetCurrentIndex());
aura::Window* content = web_contents->GetView()->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
aura::test::EventGenerator generator(content->GetRootWindow(), content);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(20),
1);
window->AddChild(shell()->web_contents()->GetView()->GetContentNativeView());
}
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
ContentWindowClose) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
EXPECT_EQ(1, GetCurrentIndex());
aura::Window* content = web_contents->GetView()->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
aura::test::EventGenerator generator(content->GetRootWindow(), content);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(20),
1);
delete web_contents->GetView()->GetContentNativeView();
}
IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
RepeatedQuickOverscrollGestures) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
NavigationController& controller = web_contents->GetController();
RenderFrameHost* main_frame = web_contents->GetMainFrame();
WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
web_contents->GetView());
view_aura->SetupOverlayWindowForTesting();
ExecuteSyncJSFunction(main_frame, "install_touch_handler()");
ExecuteSyncJSFunction(main_frame, "navigate_next()");
ExecuteSyncJSFunction(main_frame, "navigate_next()");
EXPECT_EQ(2, GetCurrentIndex());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
web_contents->GetController().GoBack();
WaitForLoadStop(web_contents);
EXPECT_EQ(1, GetCurrentIndex());
EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents->GetTitle());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_TRUE(controller.CanGoForward());
aura::Window* content = web_contents->GetView()->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
aura::test::EventGenerator generator(content->GetRootWindow(), content);
base::string16 expected_title = base::ASCIIToUTF16("Title: #2");
content::TitleWatcher title_watcher(web_contents, expected_title);
NavigationWatcher nav_watcher(web_contents);
generator.GestureScrollSequence(
gfx::Point(bounds.right() - 10, bounds.y() + 10),
gfx::Point(bounds.x() + 2, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(2000),
10);
nav_watcher.WaitUntilNavigationStarts();
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
base::TimeDelta::FromMilliseconds(2000),
10);
base::string16 actual_title = title_watcher.WaitAndGetTitle();
EXPECT_EQ(expected_title, actual_title);
EXPECT_EQ(2, GetCurrentIndex());
EXPECT_TRUE(controller.CanGoBack());
EXPECT_FALSE(controller.CanGoForward());
}
}