web_contents_view_aura_browsertest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/test/test_timeouts.h" 10#include "base/utf_string_conversions.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_) 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 // Executes the javascript synchronously and makes sure the returned value is 90 // freed properly. 91 void ExecuteSyncJSFunction(RenderViewHost* rvh, const std::string& jscript) { 92 scoped_ptr<base::Value> value = 93 content::ExecuteScriptAndGetValue(rvh, jscript); 94 } 95 96 // Starts the test server and navigates to the given url. Sets a large enough 97 // size to the root window. Returns after the navigation to the url is 98 // complete. 99 void StartTestWithPage(const std::string& url) { 100 ASSERT_TRUE(test_server()->Start()); 101 GURL test_url(test_server()->GetURL(url)); 102 NavigateToURL(shell(), test_url); 103 aura::Window* content = 104 shell()->web_contents()->GetView()->GetContentNativeView(); 105 content->GetRootWindow()->SetHostSize(gfx::Size(800, 600)); 106 107 WebContentsImpl* web_contents = 108 static_cast<WebContentsImpl*>(shell()->web_contents()); 109 NavigationControllerImpl* controller = &web_contents->GetController(); 110 111 screenshot_manager_ = new ScreenshotTracker(controller); 112 controller->SetScreenshotManager(screenshot_manager_); 113 } 114 115 void TestOverscrollNavigation(bool touch_handler) { 116 ASSERT_NO_FATAL_FAILURE( 117 StartTestWithPage("files/overscroll_navigation.html")); 118 WebContentsImpl* web_contents = 119 static_cast<WebContentsImpl*>(shell()->web_contents()); 120 NavigationController& controller = web_contents->GetController(); 121 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 122 web_contents->GetRenderViewHost()); 123 WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>( 124 web_contents->GetView()); 125 view_aura->SetupOverlayWindowForTesting(); 126 127 EXPECT_FALSE(controller.CanGoBack()); 128 EXPECT_FALSE(controller.CanGoForward()); 129 int index = -1; 130 scoped_ptr<base::Value> value = 131 content::ExecuteScriptAndGetValue(view_host, "get_current()"); 132 ASSERT_TRUE(value->GetAsInteger(&index)); 133 EXPECT_EQ(0, index); 134 135 if (touch_handler) 136 ExecuteSyncJSFunction(view_host, "install_touch_handler()"); 137 138 ExecuteSyncJSFunction(view_host, "navigate_next()"); 139 ExecuteSyncJSFunction(view_host, "navigate_next()"); 140 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 141 ASSERT_TRUE(value->GetAsInteger(&index)); 142 EXPECT_EQ(2, index); 143 EXPECT_TRUE(controller.CanGoBack()); 144 EXPECT_FALSE(controller.CanGoForward()); 145 146 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 147 gfx::Rect bounds = content->GetBoundsInRootWindow(); 148 aura::test::EventGenerator generator(content->GetRootWindow(), content); 149 150 { 151 // Do a swipe-right now. That should navigate backwards. 152 string16 expected_title = ASCIIToUTF16("Title: #1"); 153 content::TitleWatcher title_watcher(web_contents, expected_title); 154 generator.GestureScrollSequence( 155 gfx::Point(bounds.x() + 2, bounds.y() + 10), 156 gfx::Point(bounds.right() - 10, bounds.y() + 10), 157 base::TimeDelta::FromMilliseconds(20), 158 1); 159 string16 actual_title = title_watcher.WaitAndGetTitle(); 160 EXPECT_EQ(expected_title, actual_title); 161 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 162 ASSERT_TRUE(value->GetAsInteger(&index)); 163 EXPECT_EQ(1, index); 164 EXPECT_TRUE(controller.CanGoBack()); 165 EXPECT_TRUE(controller.CanGoForward()); 166 } 167 168 { 169 // Do a fling-right now. That should navigate backwards. 170 string16 expected_title = ASCIIToUTF16("Title:"); 171 content::TitleWatcher title_watcher(web_contents, expected_title); 172 generator.GestureScrollSequence( 173 gfx::Point(bounds.x() + 2, bounds.y() + 10), 174 gfx::Point(bounds.right() - 10, bounds.y() + 10), 175 base::TimeDelta::FromMilliseconds(20), 176 10); 177 string16 actual_title = title_watcher.WaitAndGetTitle(); 178 EXPECT_EQ(expected_title, actual_title); 179 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 180 ASSERT_TRUE(value->GetAsInteger(&index)); 181 EXPECT_EQ(0, index); 182 EXPECT_FALSE(controller.CanGoBack()); 183 EXPECT_TRUE(controller.CanGoForward()); 184 } 185 186 { 187 // Do a swipe-left now. That should navigate forward. 188 string16 expected_title = ASCIIToUTF16("Title: #1"); 189 content::TitleWatcher title_watcher(web_contents, expected_title); 190 generator.GestureScrollSequence( 191 gfx::Point(bounds.right() - 10, bounds.y() + 10), 192 gfx::Point(bounds.x() + 2, bounds.y() + 10), 193 base::TimeDelta::FromMilliseconds(20), 194 10); 195 string16 actual_title = title_watcher.WaitAndGetTitle(); 196 EXPECT_EQ(expected_title, actual_title); 197 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 198 ASSERT_TRUE(value->GetAsInteger(&index)); 199 EXPECT_EQ(1, index); 200 EXPECT_TRUE(controller.CanGoBack()); 201 EXPECT_TRUE(controller.CanGoForward()); 202 } 203 } 204 205 int GetCurrentIndex() { 206 WebContentsImpl* web_contents = 207 static_cast<WebContentsImpl*>(shell()->web_contents()); 208 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 209 web_contents->GetRenderViewHost()); 210 int index = -1; 211 scoped_ptr<base::Value> value; 212 value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); 213 if (!value->GetAsInteger(&index)) 214 index = -1; 215 return index; 216 } 217 218 protected: 219 ScreenshotTracker* screenshot_manager() { return screenshot_manager_; } 220 void set_min_screenshot_interval(int interval_ms) { 221 screenshot_manager_->SetScreenshotInterval(interval_ms); 222 } 223 224 private: 225 ScreenshotTracker* screenshot_manager_; 226 227 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest); 228}; 229 230IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 231 OverscrollNavigation) { 232 TestOverscrollNavigation(false); 233} 234 235IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 236 OverscrollNavigationWithTouchHandler) { 237 TestOverscrollNavigation(true); 238} 239 240// Disabled because the test always fails the first time it runs on the Win Aura 241// bots, and usually but not always passes second-try (See crbug.com/179532). 242#if defined(OS_WIN) 243#define MAYBE_QuickOverscrollDirectionChange \ 244 DISABLED_QuickOverscrollDirectionChange 245#else 246#define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange 247#endif 248IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 249 MAYBE_QuickOverscrollDirectionChange) { 250 ASSERT_NO_FATAL_FAILURE( 251 StartTestWithPage("files/overscroll_navigation.html")); 252 WebContentsImpl* web_contents = 253 static_cast<WebContentsImpl*>(shell()->web_contents()); 254 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 255 web_contents->GetRenderViewHost()); 256 257 // This test triggers a large number of animations. Speed them up to ensure 258 // the test completes within its time limit. 259 ui::ScopedAnimationDurationScaleMode fast_duration_mode( 260 ui::ScopedAnimationDurationScaleMode::FAST_DURATION); 261 262 // Make sure the page has both back/forward history. 263 ExecuteSyncJSFunction(view_host, "navigate_next()"); 264 EXPECT_EQ(1, GetCurrentIndex()); 265 ExecuteSyncJSFunction(view_host, "navigate_next()"); 266 EXPECT_EQ(2, GetCurrentIndex()); 267 web_contents->GetController().GoBack(); 268 EXPECT_EQ(1, GetCurrentIndex()); 269 270 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 271 aura::RootWindow* root_window = content->GetRootWindow(); 272 gfx::Rect bounds = content->GetBoundsInRootWindow(); 273 274 base::TimeDelta timestamp; 275 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, 276 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5), 277 0, timestamp); 278 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&press); 279 EXPECT_EQ(1, GetCurrentIndex()); 280 281 timestamp += base::TimeDelta::FromMilliseconds(10); 282 ui::TouchEvent move1(ui::ET_TOUCH_MOVED, 283 gfx::Point(bounds.right() - 10, bounds.y() + 5), 284 0, timestamp); 285 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&move1); 286 EXPECT_EQ(1, GetCurrentIndex()); 287 288 // Swipe back from the right edge, back to the left edge, back to the right 289 // edge. 290 291 for (int x = bounds.right() - 10; x >= bounds.x() + 10; x-= 10) { 292 timestamp += base::TimeDelta::FromMilliseconds(10); 293 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 294 gfx::Point(x, bounds.y() + 5), 295 0, timestamp); 296 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc); 297 EXPECT_EQ(1, GetCurrentIndex()); 298 } 299 300 for (int x = bounds.x() + 10; x <= bounds.width() - 10; x+= 10) { 301 timestamp += base::TimeDelta::FromMilliseconds(10); 302 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 303 gfx::Point(x, bounds.y() + 5), 304 0, timestamp); 305 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc); 306 EXPECT_EQ(1, GetCurrentIndex()); 307 } 308 309 for (int x = bounds.width() - 10; x >= bounds.x() + 10; x-= 10) { 310 timestamp += base::TimeDelta::FromMilliseconds(10); 311 ui::TouchEvent inc(ui::ET_TOUCH_MOVED, 312 gfx::Point(x, bounds.y() + 5), 313 0, timestamp); 314 root_window->AsRootWindowHostDelegate()->OnHostTouchEvent(&inc); 315 EXPECT_EQ(1, GetCurrentIndex()); 316 } 317 318 // Do not end the overscroll sequence. 319} 320 321// Tests that the page has has a screenshot when navigation happens: 322// - from within the page (from a JS function) 323// - interactively, when user does an overscroll gesture 324// - interactively, when user navigates in history without the overscroll 325// gesture. 326IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 327 OverscrollScreenshot) { 328 ASSERT_NO_FATAL_FAILURE( 329 StartTestWithPage("files/overscroll_navigation.html")); 330 WebContentsImpl* web_contents = 331 static_cast<WebContentsImpl*>(shell()->web_contents()); 332 RenderViewHostImpl* view_host = static_cast<RenderViewHostImpl*>( 333 web_contents->GetRenderViewHost()); 334 335 set_min_screenshot_interval(0); 336 337 // Do a few navigations initiated by the page. 338 ExecuteSyncJSFunction(view_host, "navigate_next()"); 339 EXPECT_EQ(1, GetCurrentIndex()); 340 ExecuteSyncJSFunction(view_host, "navigate_next()"); 341 EXPECT_EQ(2, GetCurrentIndex()); 342 screenshot_manager()->WaitUntilScreenshotIsReady(); 343 344 // The current entry won't have any screenshots. But the entries in the 345 // history should now have screenshots. 346 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 347 web_contents->GetController().GetEntryAtIndex(2)); 348 EXPECT_FALSE(entry->screenshot().get()); 349 350 entry = NavigationEntryImpl::FromNavigationEntry( 351 web_contents->GetController().GetEntryAtIndex(1)); 352 EXPECT_TRUE(entry->screenshot().get()); 353 354 entry = NavigationEntryImpl::FromNavigationEntry( 355 web_contents->GetController().GetEntryAtIndex(0)); 356 EXPECT_TRUE(entry->screenshot().get()); 357 358 // Navigate again. Index 2 should now have a screenshot. 359 ExecuteSyncJSFunction(view_host, "navigate_next()"); 360 EXPECT_EQ(3, GetCurrentIndex()); 361 screenshot_manager()->WaitUntilScreenshotIsReady(); 362 363 entry = NavigationEntryImpl::FromNavigationEntry( 364 web_contents->GetController().GetEntryAtIndex(2)); 365 EXPECT_TRUE(entry->screenshot().get()); 366 367 entry = NavigationEntryImpl::FromNavigationEntry( 368 web_contents->GetController().GetEntryAtIndex(3)); 369 EXPECT_FALSE(entry->screenshot().get()); 370 371 { 372 // Now, swipe right to navigate backwards. This should navigate away from 373 // index 3 to index 2, and index 3 should have a screenshot. 374 string16 expected_title = ASCIIToUTF16("Title: #2"); 375 content::TitleWatcher title_watcher(web_contents, expected_title); 376 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 377 gfx::Rect bounds = content->GetBoundsInRootWindow(); 378 aura::test::EventGenerator generator(content->GetRootWindow(), content); 379 generator.GestureScrollSequence( 380 gfx::Point(bounds.x() + 2, bounds.y() + 10), 381 gfx::Point(bounds.right() - 10, bounds.y() + 10), 382 base::TimeDelta::FromMilliseconds(20), 383 1); 384 string16 actual_title = title_watcher.WaitAndGetTitle(); 385 EXPECT_EQ(expected_title, actual_title); 386 EXPECT_EQ(2, GetCurrentIndex()); 387 screenshot_manager()->WaitUntilScreenshotIsReady(); 388 entry = NavigationEntryImpl::FromNavigationEntry( 389 web_contents->GetController().GetEntryAtIndex(3)); 390 EXPECT_TRUE(entry->screenshot().get()); 391 } 392 393 // Navigate a couple more times. 394 ExecuteSyncJSFunction(view_host, "navigate_next()"); 395 EXPECT_EQ(3, GetCurrentIndex()); 396 ExecuteSyncJSFunction(view_host, "navigate_next()"); 397 EXPECT_EQ(4, GetCurrentIndex()); 398 screenshot_manager()->WaitUntilScreenshotIsReady(); 399 entry = NavigationEntryImpl::FromNavigationEntry( 400 web_contents->GetController().GetEntryAtIndex(4)); 401 EXPECT_FALSE(entry->screenshot().get()); 402 403 { 404 // Navigate back in history. 405 string16 expected_title = ASCIIToUTF16("Title: #3"); 406 content::TitleWatcher title_watcher(web_contents, expected_title); 407 web_contents->GetController().GoBack(); 408 string16 actual_title = title_watcher.WaitAndGetTitle(); 409 EXPECT_EQ(expected_title, actual_title); 410 EXPECT_EQ(3, GetCurrentIndex()); 411 screenshot_manager()->WaitUntilScreenshotIsReady(); 412 entry = NavigationEntryImpl::FromNavigationEntry( 413 web_contents->GetController().GetEntryAtIndex(4)); 414 EXPECT_TRUE(entry->screenshot().get()); 415 } 416} 417 418// Tests that screenshot is taken correctly when navigation causes a 419// RenderViewHost to be swapped out. 420IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 421 ScreenshotForSwappedOutRenderViews) { 422 ASSERT_NO_FATAL_FAILURE( 423 StartTestWithPage("files/overscroll_navigation.html")); 424 // Create a new server with a different site. 425 net::SpawnedTestServer https_server( 426 net::SpawnedTestServer::TYPE_HTTPS, 427 net::SpawnedTestServer::kLocalhost, 428 base::FilePath(FILE_PATH_LITERAL("content/test/data"))); 429 ASSERT_TRUE(https_server.Start()); 430 431 WebContentsImpl* web_contents = 432 static_cast<WebContentsImpl*>(shell()->web_contents()); 433 set_min_screenshot_interval(0); 434 435 struct { 436 GURL url; 437 int transition; 438 } navigations[] = { 439 { https_server.GetURL("files/title1.html"), 440 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR }, 441 { test_server()->GetURL("files/title2.html"), 442 PAGE_TRANSITION_AUTO_BOOKMARK }, 443 { https_server.GetURL("files/title3.html"), 444 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR }, 445 { GURL(), 0 } 446 }; 447 448 screenshot_manager()->Reset(); 449 for (int i = 0; !navigations[i].url.is_empty(); ++i) { 450 // Navigate via the user initiating a navigation from the UI. 451 NavigationController::LoadURLParams params(navigations[i].url); 452 params.transition_type = PageTransitionFromInt(navigations[i].transition); 453 454 RenderViewHost* old_host = web_contents->GetRenderViewHost(); 455 web_contents->GetController().LoadURLWithParams(params); 456 WaitForLoadStop(web_contents); 457 screenshot_manager()->WaitUntilScreenshotIsReady(); 458 459 EXPECT_NE(old_host, web_contents->GetRenderViewHost()) 460 << navigations[i].url.spec(); 461 EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for()); 462 screenshot_manager()->Reset(); 463 464 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 465 web_contents->GetController().GetEntryAtOffset(-1)); 466 EXPECT_TRUE(entry->screenshot().get()); 467 468 entry = NavigationEntryImpl::FromNavigationEntry( 469 web_contents->GetController().GetActiveEntry()); 470 EXPECT_FALSE(entry->screenshot().get()); 471 } 472 473 // Increase the minimum interval between taking screenshots. 474 set_min_screenshot_interval(60000); 475 476 // Navigate again. This should not take any screenshot because of the 477 // increased screenshot interval. 478 NavigationController::LoadURLParams params(navigations[0].url); 479 params.transition_type = PageTransitionFromInt(navigations[0].transition); 480 web_contents->GetController().LoadURLWithParams(params); 481 WaitForLoadStop(web_contents); 482 screenshot_manager()->WaitUntilScreenshotIsReady(); 483 484 EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for()); 485} 486 487IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 488 ContentWindowReparent) { 489 ASSERT_NO_FATAL_FAILURE( 490 StartTestWithPage("files/overscroll_navigation.html")); 491 492 scoped_ptr<aura::Window> window(new aura::Window(NULL)); 493 window->Init(ui::LAYER_NOT_DRAWN); 494 495 WebContentsImpl* web_contents = 496 static_cast<WebContentsImpl*>(shell()->web_contents()); 497 ExecuteSyncJSFunction(web_contents->GetRenderViewHost(), "navigate_next()"); 498 EXPECT_EQ(1, GetCurrentIndex()); 499 500 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 501 gfx::Rect bounds = content->GetBoundsInRootWindow(); 502 aura::test::EventGenerator generator(content->GetRootWindow(), content); 503 generator.GestureScrollSequence( 504 gfx::Point(bounds.x() + 2, bounds.y() + 10), 505 gfx::Point(bounds.right() - 10, bounds.y() + 10), 506 base::TimeDelta::FromMilliseconds(20), 507 1); 508 509 window->AddChild(shell()->web_contents()->GetView()->GetContentNativeView()); 510} 511 512IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, 513 ContentWindowClose) { 514 ASSERT_NO_FATAL_FAILURE( 515 StartTestWithPage("files/overscroll_navigation.html")); 516 517 WebContentsImpl* web_contents = 518 static_cast<WebContentsImpl*>(shell()->web_contents()); 519 ExecuteSyncJSFunction(web_contents->GetRenderViewHost(), "navigate_next()"); 520 EXPECT_EQ(1, GetCurrentIndex()); 521 522 aura::Window* content = web_contents->GetView()->GetContentNativeView(); 523 gfx::Rect bounds = content->GetBoundsInRootWindow(); 524 aura::test::EventGenerator generator(content->GetRootWindow(), content); 525 generator.GestureScrollSequence( 526 gfx::Point(bounds.x() + 2, bounds.y() + 10), 527 gfx::Point(bounds.right() - 10, bounds.y() + 10), 528 base::TimeDelta::FromMilliseconds(20), 529 1); 530 531 delete web_contents->GetView()->GetContentNativeView(); 532} 533 534} // namespace content 535