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.
5 #include "content/browser/web_contents/web_contents_view_aura.h"
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"
13 #include "base/win/windows_version.h"
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"
39 // This class keeps track of the RenderViewHost whose screenshot was captured.
40 class ScreenshotTracker : public NavigationEntryScreenshotManager {
42 explicit ScreenshotTracker(NavigationControllerImpl* controller)
43 : NavigationEntryScreenshotManager(controller),
44 screenshot_taken_for_(NULL),
45 waiting_for_screenshots_(0) {
48 virtual ~ScreenshotTracker() {
51 RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; }
54 screenshot_taken_for_ = NULL;
55 screenshot_set_.clear();
58 void SetScreenshotInterval(int interval_ms) {
59 SetMinScreenshotIntervalMS(interval_ms);
62 void WaitUntilScreenshotIsReady() {
63 if (!waiting_for_screenshots_)
65 message_loop_runner_ = new content::MessageLoopRunner;
66 message_loop_runner_->Run();
69 bool ScreenshotSetForEntry(NavigationEntryImpl* entry) const {
70 return screenshot_set_.count(entry) > 0;
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);
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();
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_;
95 DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker);
98 class NavigationWatcher : public WebContentsObserver {
100 explicit NavigationWatcher(WebContents* contents)
101 : WebContentsObserver(contents),
103 should_quit_loop_(false) {
106 virtual ~NavigationWatcher() {}
108 void WaitUntilNavigationStarts() {
111 should_quit_loop_ = true;
112 base::MessageLoop::current()->Run();
116 // Overridden from WebContentsObserver:
117 virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE {
119 if (should_quit_loop_)
120 base::MessageLoop::current()->Quit();
124 bool should_quit_loop_;
126 DISALLOW_COPY_AND_ASSIGN(NavigationWatcher);
129 class WebContentsViewAuraTest : public ContentBrowserTest {
131 WebContentsViewAuraTest()
132 : screenshot_manager_(NULL) {
135 // Executes the javascript synchronously and makes sure the returned value is
137 void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) {
138 scoped_ptr<base::Value> value =
139 content::ExecuteScriptAndGetValue(rfh, jscript);
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
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);
150 WebContentsImpl* web_contents =
151 static_cast<WebContentsImpl*>(shell()->web_contents());
152 NavigationControllerImpl* controller = &web_contents->GetController();
154 screenshot_manager_ = new ScreenshotTracker(controller);
155 controller->SetScreenshotManager(screenshot_manager_);
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();
166 EXPECT_FALSE(controller.CanGoBack());
167 EXPECT_FALSE(controller.CanGoForward());
169 scoped_ptr<base::Value> value =
170 content::ExecuteScriptAndGetValue(main_frame, "get_current()");
171 ASSERT_TRUE(value->GetAsInteger(&index));
175 ExecuteSyncJSFunction(main_frame, "install_touch_handler()");
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));
182 EXPECT_TRUE(controller.CanGoBack());
183 EXPECT_FALSE(controller.CanGoForward());
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;
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),
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));
205 EXPECT_TRUE(controller.CanGoBack());
206 EXPECT_TRUE(controller.CanGoForward());
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),
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));
223 EXPECT_FALSE(controller.CanGoBack());
224 EXPECT_TRUE(controller.CanGoForward());
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),
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));
241 EXPECT_TRUE(controller.CanGoBack());
242 EXPECT_TRUE(controller.CanGoForward());
246 int GetCurrentIndex() {
247 WebContentsImpl* web_contents =
248 static_cast<WebContentsImpl*>(shell()->web_contents());
249 RenderFrameHost* main_frame = web_contents->GetMainFrame();
251 scoped_ptr<base::Value> value;
252 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
253 if (!value->GetAsInteger(&index))
259 ScreenshotTracker* screenshot_manager() { return screenshot_manager_; }
260 void set_min_screenshot_interval(int interval_ms) {
261 screenshot_manager_->SetScreenshotInterval(interval_ms);
265 ScreenshotTracker* screenshot_manager_;
267 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
270 // Flaky on Windows and ChromeOS: http://crbug.com/305722
271 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
272 DISABLED_OverscrollNavigation) {
273 TestOverscrollNavigation(false);
276 // Flaky on Windows (might be related to the above test):
277 // http://crbug.com/305722
279 #define MAYBE_OverscrollNavigationWithTouchHandler \
280 DISABLED_OverscrollNavigationWithTouchHandler
282 #define MAYBE_OverscrollNavigationWithTouchHandler \
283 OverscrollNavigationWithTouchHandler
285 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
286 MAYBE_OverscrollNavigationWithTouchHandler) {
287 TestOverscrollNavigation(true);
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).
293 #define MAYBE_QuickOverscrollDirectionChange \
294 DISABLED_QuickOverscrollDirectionChange
296 #define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange
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();
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);
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());
319 aura::Window* content = web_contents->GetContentNativeView();
320 ui::EventProcessor* dispatcher = content->GetHost()->event_processor();
321 gfx::Rect bounds = content->GetBoundsInRootWindow();
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),
327 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
328 ASSERT_FALSE(details.dispatcher_destroyed);
329 EXPECT_EQ(1, GetCurrentIndex());
331 timestamp += base::TimeDelta::FromMilliseconds(10);
332 ui::TouchEvent move1(ui::ET_TOUCH_MOVED,
333 gfx::Point(bounds.right() - 10, bounds.y() + 5),
335 details = dispatcher->OnEventFromSource(&move1);
336 ASSERT_FALSE(details.dispatcher_destroyed);
337 EXPECT_EQ(1, GetCurrentIndex());
339 // Swipe back from the right edge, back to the left edge, back to the right
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),
347 details = dispatcher->OnEventFromSource(&inc);
348 ASSERT_FALSE(details.dispatcher_destroyed);
349 EXPECT_EQ(1, GetCurrentIndex());
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),
357 details = dispatcher->OnEventFromSource(&inc);
358 ASSERT_FALSE(details.dispatcher_destroyed);
359 EXPECT_EQ(1, GetCurrentIndex());
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),
367 details = dispatcher->OnEventFromSource(&inc);
368 ASSERT_FALSE(details.dispatcher_destroyed);
369 EXPECT_EQ(1, GetCurrentIndex());
372 // Do not end the overscroll sequence.
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
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.
385 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
386 LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
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();
397 set_min_screenshot_interval(0);
399 // Do a few navigations initiated by the page.
400 ExecuteSyncJSFunction(main_frame, "navigate_next()");
401 EXPECT_EQ(1, GetCurrentIndex());
402 ExecuteSyncJSFunction(main_frame, "navigate_next()");
403 EXPECT_EQ(2, GetCurrentIndex());
404 screenshot_manager()->WaitUntilScreenshotIsReady();
406 // The current entry won't have any screenshots. But the entries in the
407 // history should now have screenshots.
408 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
409 web_contents->GetController().GetEntryAtIndex(2));
410 EXPECT_FALSE(entry->screenshot().get());
412 entry = NavigationEntryImpl::FromNavigationEntry(
413 web_contents->GetController().GetEntryAtIndex(1));
414 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
416 entry = NavigationEntryImpl::FromNavigationEntry(
417 web_contents->GetController().GetEntryAtIndex(0));
418 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
420 // Navigate again. Index 2 should now have a screenshot.
421 ExecuteSyncJSFunction(main_frame, "navigate_next()");
422 EXPECT_EQ(3, GetCurrentIndex());
423 screenshot_manager()->WaitUntilScreenshotIsReady();
425 entry = NavigationEntryImpl::FromNavigationEntry(
426 web_contents->GetController().GetEntryAtIndex(2));
427 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
429 entry = NavigationEntryImpl::FromNavigationEntry(
430 web_contents->GetController().GetEntryAtIndex(3));
431 EXPECT_FALSE(entry->screenshot().get());
434 // Now, swipe right to navigate backwards. This should navigate away from
435 // index 3 to index 2, and index 3 should have a screenshot.
436 base::string16 expected_title = base::ASCIIToUTF16("Title: #2");
437 content::TitleWatcher title_watcher(web_contents, expected_title);
438 aura::Window* content = web_contents->GetContentNativeView();
439 gfx::Rect bounds = content->GetBoundsInRootWindow();
440 aura::test::EventGenerator generator(content->GetRootWindow(), content);
441 generator.GestureScrollSequence(
442 gfx::Point(bounds.x() + 2, bounds.y() + 10),
443 gfx::Point(bounds.right() - 10, bounds.y() + 10),
444 base::TimeDelta::FromMilliseconds(20),
446 base::string16 actual_title = title_watcher.WaitAndGetTitle();
447 EXPECT_EQ(expected_title, actual_title);
448 EXPECT_EQ(2, GetCurrentIndex());
449 screenshot_manager()->WaitUntilScreenshotIsReady();
450 entry = NavigationEntryImpl::FromNavigationEntry(
451 web_contents->GetController().GetEntryAtIndex(3));
452 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
455 // Navigate a couple more times.
456 ExecuteSyncJSFunction(main_frame, "navigate_next()");
457 EXPECT_EQ(3, GetCurrentIndex());
458 ExecuteSyncJSFunction(main_frame, "navigate_next()");
459 EXPECT_EQ(4, GetCurrentIndex());
460 screenshot_manager()->WaitUntilScreenshotIsReady();
461 entry = NavigationEntryImpl::FromNavigationEntry(
462 web_contents->GetController().GetEntryAtIndex(4));
463 EXPECT_FALSE(entry->screenshot().get());
466 // Navigate back in history.
467 base::string16 expected_title = base::ASCIIToUTF16("Title: #3");
468 content::TitleWatcher title_watcher(web_contents, expected_title);
469 web_contents->GetController().GoBack();
470 base::string16 actual_title = title_watcher.WaitAndGetTitle();
471 EXPECT_EQ(expected_title, actual_title);
472 EXPECT_EQ(3, GetCurrentIndex());
473 screenshot_manager()->WaitUntilScreenshotIsReady();
474 entry = NavigationEntryImpl::FromNavigationEntry(
475 web_contents->GetController().GetEntryAtIndex(4));
476 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
480 // Crashes under ThreadSanitizer, http://crbug.com/356758.
481 #if defined(THREAD_SANITIZER)
482 #define MAYBE_ScreenshotForSwappedOutRenderViews \
483 DISABLED_ScreenshotForSwappedOutRenderViews
485 #define MAYBE_ScreenshotForSwappedOutRenderViews \
486 ScreenshotForSwappedOutRenderViews
488 // Tests that screenshot is taken correctly when navigation causes a
489 // RenderViewHost to be swapped out.
490 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
491 MAYBE_ScreenshotForSwappedOutRenderViews) {
492 ASSERT_NO_FATAL_FAILURE(
493 StartTestWithPage("files/overscroll_navigation.html"));
494 // Create a new server with a different site.
495 net::SpawnedTestServer https_server(
496 net::SpawnedTestServer::TYPE_HTTPS,
497 net::SpawnedTestServer::kLocalhost,
498 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
499 ASSERT_TRUE(https_server.Start());
501 WebContentsImpl* web_contents =
502 static_cast<WebContentsImpl*>(shell()->web_contents());
503 set_min_screenshot_interval(0);
509 { https_server.GetURL("files/title1.html"),
510 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
511 { test_server()->GetURL("files/title2.html"),
512 PAGE_TRANSITION_AUTO_BOOKMARK },
513 { https_server.GetURL("files/title3.html"),
514 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
518 screenshot_manager()->Reset();
519 for (int i = 0; !navigations[i].url.is_empty(); ++i) {
520 // Navigate via the user initiating a navigation from the UI.
521 NavigationController::LoadURLParams params(navigations[i].url);
522 params.transition_type = PageTransitionFromInt(navigations[i].transition);
524 RenderViewHost* old_host = web_contents->GetRenderViewHost();
525 web_contents->GetController().LoadURLWithParams(params);
526 WaitForLoadStop(web_contents);
527 screenshot_manager()->WaitUntilScreenshotIsReady();
529 EXPECT_NE(old_host, web_contents->GetRenderViewHost())
530 << navigations[i].url.spec();
531 EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for());
533 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
534 web_contents->GetController().GetEntryAtOffset(-1));
535 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
537 entry = NavigationEntryImpl::FromNavigationEntry(
538 web_contents->GetController().GetLastCommittedEntry());
539 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
540 EXPECT_FALSE(entry->screenshot().get());
541 screenshot_manager()->Reset();
544 // Increase the minimum interval between taking screenshots.
545 set_min_screenshot_interval(60000);
547 // Navigate again. This should not take any screenshot because of the
548 // increased screenshot interval.
549 NavigationController::LoadURLParams params(navigations[0].url);
550 params.transition_type = PageTransitionFromInt(navigations[0].transition);
551 web_contents->GetController().LoadURLWithParams(params);
552 WaitForLoadStop(web_contents);
553 screenshot_manager()->WaitUntilScreenshotIsReady();
555 EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for());
558 // Tests that navigations resulting from reloads and history.replaceState
559 // do not capture screenshots while navigations resulting from
560 // histrory.pushState do.
561 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ReplaceStateReloadPushState) {
562 ASSERT_NO_FATAL_FAILURE(
563 StartTestWithPage("files/overscroll_navigation.html"));
564 WebContentsImpl* web_contents =
565 static_cast<WebContentsImpl*>(shell()->web_contents());
566 RenderFrameHost* main_frame = web_contents->GetMainFrame();
568 set_min_screenshot_interval(0);
569 screenshot_manager()->Reset();
570 ExecuteSyncJSFunction(main_frame, "use_replace_state()");
571 screenshot_manager()->WaitUntilScreenshotIsReady();
572 // history.replaceState shouldn't capture a screenshot
573 EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
574 screenshot_manager()->Reset();
575 web_contents->GetController().Reload(true);
576 WaitForLoadStop(web_contents);
577 // reloading the page shouldn't capture a screenshot
578 EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
579 screenshot_manager()->Reset();
580 ExecuteSyncJSFunction(main_frame, "use_push_state()");
581 screenshot_manager()->WaitUntilScreenshotIsReady();
582 // pushing a state should capture a screenshot
583 EXPECT_TRUE(screenshot_manager()->screenshot_taken_for());
586 // TODO(sadrul): This test is disabled because it reparents in a way the
587 // FocusController does not support. This code would crash in
588 // a production build. It only passed prior to this revision
589 // because testing used the old FocusManager which did some
590 // different (osbolete) processing. TODO(sadrul) to figure out
591 // how this test should work that mimics production code a bit
593 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
594 DISABLED_ContentWindowReparent) {
595 ASSERT_NO_FATAL_FAILURE(
596 StartTestWithPage("files/overscroll_navigation.html"));
598 scoped_ptr<aura::Window> window(new aura::Window(NULL));
599 window->Init(aura::WINDOW_LAYER_NOT_DRAWN);
601 WebContentsImpl* web_contents =
602 static_cast<WebContentsImpl*>(shell()->web_contents());
603 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
604 EXPECT_EQ(1, GetCurrentIndex());
606 aura::Window* content = web_contents->GetContentNativeView();
607 gfx::Rect bounds = content->GetBoundsInRootWindow();
608 aura::test::EventGenerator generator(content->GetRootWindow(), content);
609 generator.GestureScrollSequence(
610 gfx::Point(bounds.x() + 2, bounds.y() + 10),
611 gfx::Point(bounds.right() - 10, bounds.y() + 10),
612 base::TimeDelta::FromMilliseconds(20),
615 window->AddChild(shell()->web_contents()->GetContentNativeView());
618 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) {
619 ASSERT_NO_FATAL_FAILURE(
620 StartTestWithPage("files/overscroll_navigation.html"));
622 WebContentsImpl* web_contents =
623 static_cast<WebContentsImpl*>(shell()->web_contents());
624 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
625 EXPECT_EQ(1, GetCurrentIndex());
627 aura::Window* content = web_contents->GetContentNativeView();
628 gfx::Rect bounds = content->GetBoundsInRootWindow();
629 aura::test::EventGenerator generator(content->GetRootWindow(), content);
630 generator.GestureScrollSequence(
631 gfx::Point(bounds.x() + 2, bounds.y() + 10),
632 gfx::Point(bounds.right() - 10, bounds.y() + 10),
633 base::TimeDelta::FromMilliseconds(20),
636 delete web_contents->GetContentNativeView();
640 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
641 // This appears to be flaky in the same was as the other overscroll
642 // tests. Enabling for non-Windows platforms.
643 // See http://crbug.com/369871.
644 // For linux, see http://crbug.com/381294
645 #define MAYBE_RepeatedQuickOverscrollGestures DISABLED_RepeatedQuickOverscrollGestures
647 #define MAYBE_RepeatedQuickOverscrollGestures RepeatedQuickOverscrollGestures
650 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
651 MAYBE_RepeatedQuickOverscrollGestures) {
652 ASSERT_NO_FATAL_FAILURE(
653 StartTestWithPage("files/overscroll_navigation.html"));
655 WebContentsImpl* web_contents =
656 static_cast<WebContentsImpl*>(shell()->web_contents());
657 NavigationController& controller = web_contents->GetController();
658 RenderFrameHost* main_frame = web_contents->GetMainFrame();
659 ExecuteSyncJSFunction(main_frame, "install_touch_handler()");
661 // Navigate twice, then navigate back in history once.
662 ExecuteSyncJSFunction(main_frame, "navigate_next()");
663 ExecuteSyncJSFunction(main_frame, "navigate_next()");
664 EXPECT_EQ(2, GetCurrentIndex());
665 EXPECT_TRUE(controller.CanGoBack());
666 EXPECT_FALSE(controller.CanGoForward());
668 web_contents->GetController().GoBack();
669 WaitForLoadStop(web_contents);
670 EXPECT_EQ(1, GetCurrentIndex());
671 EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents->GetTitle());
672 EXPECT_TRUE(controller.CanGoBack());
673 EXPECT_TRUE(controller.CanGoForward());
675 aura::Window* content = web_contents->GetContentNativeView();
676 gfx::Rect bounds = content->GetBoundsInRootWindow();
677 aura::test::EventGenerator generator(content->GetRootWindow(), content);
679 // Do a swipe left to start a forward navigation. Then quickly do a swipe
681 base::string16 expected_title = base::ASCIIToUTF16("Title: #2");
682 content::TitleWatcher title_watcher(web_contents, expected_title);
683 NavigationWatcher nav_watcher(web_contents);
685 generator.GestureScrollSequence(
686 gfx::Point(bounds.right() - 10, bounds.y() + 10),
687 gfx::Point(bounds.x() + 2, bounds.y() + 10),
688 base::TimeDelta::FromMilliseconds(2000),
690 nav_watcher.WaitUntilNavigationStarts();
692 generator.GestureScrollSequence(
693 gfx::Point(bounds.x() + 2, bounds.y() + 10),
694 gfx::Point(bounds.right() - 10, bounds.y() + 10),
695 base::TimeDelta::FromMilliseconds(2000),
697 base::string16 actual_title = title_watcher.WaitAndGetTitle();
698 EXPECT_EQ(expected_title, actual_title);
700 EXPECT_EQ(2, GetCurrentIndex());
701 EXPECT_TRUE(controller.CanGoBack());
702 EXPECT_FALSE(controller.CanGoForward());
705 // Verify that hiding a parent of the renderer will hide the content too.
706 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, HideContentOnParenHide) {
707 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/title1.html"));
708 WebContentsImpl* web_contents =
709 static_cast<WebContentsImpl*>(shell()->web_contents());
710 aura::Window* content = web_contents->GetNativeView()->parent();
711 EXPECT_TRUE(web_contents->should_normally_be_visible());
713 EXPECT_FALSE(web_contents->should_normally_be_visible());
715 EXPECT_TRUE(web_contents->should_normally_be_visible());
718 } // namespace content