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/renderer_host/render_widget_host_view_aura.h"
19 #include "content/browser/web_contents/web_contents_impl.h"
20 #include "content/browser/web_contents/web_contents_view.h"
21 #include "content/common/input/synthetic_web_input_event_builders.h"
22 #include "content/common/input_messages.h"
23 #include "content/common/view_messages.h"
24 #include "content/public/browser/browser_message_filter.h"
25 #include "content/public/browser/render_frame_host.h"
26 #include "content/public/browser/web_contents_observer.h"
27 #include "content/public/common/content_switches.h"
28 #include "content/public/test/browser_test_utils.h"
29 #include "content/public/test/content_browser_test.h"
30 #include "content/public/test/content_browser_test_utils.h"
31 #include "content/public/test/test_renderer_host.h"
32 #include "content/public/test/test_utils.h"
33 #include "content/shell/browser/shell.h"
34 #include "ui/aura/window.h"
35 #include "ui/aura/window_tree_host.h"
36 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
37 #include "ui/events/event_processor.h"
38 #include "ui/events/event_switches.h"
39 #include "ui/events/event_utils.h"
40 #include "ui/events/test/event_generator.h"
44 // TODO(tdresser): Find a way to avoid sleeping like this. See crbug.com/405282
46 void GiveItSomeTime() {
47 base::RunLoop run_loop;
48 base::MessageLoop::current()->PostDelayedTask(
50 run_loop.QuitClosure(),
51 base::TimeDelta::FromMillisecondsD(10));
60 // This class keeps track of the RenderViewHost whose screenshot was captured.
61 class ScreenshotTracker : public NavigationEntryScreenshotManager {
63 explicit ScreenshotTracker(NavigationControllerImpl* controller)
64 : NavigationEntryScreenshotManager(controller),
65 screenshot_taken_for_(NULL),
66 waiting_for_screenshots_(0) {
69 virtual ~ScreenshotTracker() {
72 RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; }
75 screenshot_taken_for_ = NULL;
76 screenshot_set_.clear();
79 void SetScreenshotInterval(int interval_ms) {
80 SetMinScreenshotIntervalMS(interval_ms);
83 void WaitUntilScreenshotIsReady() {
84 if (!waiting_for_screenshots_)
86 message_loop_runner_ = new content::MessageLoopRunner;
87 message_loop_runner_->Run();
90 bool ScreenshotSetForEntry(NavigationEntryImpl* entry) const {
91 return screenshot_set_.count(entry) > 0;
95 // Overridden from NavigationEntryScreenshotManager:
96 virtual void TakeScreenshotImpl(RenderViewHost* host,
97 NavigationEntryImpl* entry) OVERRIDE {
98 ++waiting_for_screenshots_;
99 screenshot_taken_for_ = host;
100 NavigationEntryScreenshotManager::TakeScreenshotImpl(host, entry);
103 virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE {
104 --waiting_for_screenshots_;
105 screenshot_set_[entry] = true;
106 NavigationEntryScreenshotManager::OnScreenshotSet(entry);
107 if (waiting_for_screenshots_ == 0 && message_loop_runner_.get())
108 message_loop_runner_->Quit();
111 RenderViewHost* screenshot_taken_for_;
112 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
113 int waiting_for_screenshots_;
114 std::map<NavigationEntryImpl*, bool> screenshot_set_;
116 DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker);
119 class NavigationWatcher : public WebContentsObserver {
121 explicit NavigationWatcher(WebContents* contents)
122 : WebContentsObserver(contents),
124 should_quit_loop_(false) {
127 virtual ~NavigationWatcher() {}
129 void WaitUntilNavigationStarts() {
132 should_quit_loop_ = true;
133 base::MessageLoop::current()->Run();
137 // Overridden from WebContentsObserver:
138 virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE {
140 if (should_quit_loop_)
141 base::MessageLoop::current()->Quit();
145 bool should_quit_loop_;
147 DISALLOW_COPY_AND_ASSIGN(NavigationWatcher);
150 class InputEventMessageFilterWaitsForAcks : public BrowserMessageFilter {
152 InputEventMessageFilterWaitsForAcks()
153 : BrowserMessageFilter(InputMsgStart),
154 type_(blink::WebInputEvent::Undefined),
155 state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
157 void WaitForAck(blink::WebInputEvent::Type type) {
158 base::RunLoop run_loop;
159 base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
160 base::AutoReset<blink::WebInputEvent::Type> reset_type(&type_, type);
164 InputEventAckState last_ack_state() const { return state_; }
167 virtual ~InputEventMessageFilterWaitsForAcks() {}
170 void ReceivedEventAck(blink::WebInputEvent::Type type,
171 InputEventAckState state) {
178 // BrowserMessageFilter:
179 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
180 if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
181 InputHostMsg_HandleInputEvent_ACK::Param params;
182 InputHostMsg_HandleInputEvent_ACK::Read(&message, ¶ms);
183 blink::WebInputEvent::Type type = params.a.type;
184 InputEventAckState ack = params.a.state;
185 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
186 base::Bind(&InputEventMessageFilterWaitsForAcks::ReceivedEventAck,
193 blink::WebInputEvent::Type type_;
194 InputEventAckState state_;
196 DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilterWaitsForAcks);
199 class WebContentsViewAuraTest : public ContentBrowserTest {
201 WebContentsViewAuraTest()
202 : screenshot_manager_(NULL) {
205 // Executes the javascript synchronously and makes sure the returned value is
207 void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) {
208 scoped_ptr<base::Value> value =
209 content::ExecuteScriptAndGetValue(rfh, jscript);
212 // Starts the test server and navigates to the given url. Sets a large enough
213 // size to the root window. Returns after the navigation to the url is
215 void StartTestWithPage(const std::string& url) {
216 ASSERT_TRUE(test_server()->Start());
217 GURL test_url(test_server()->GetURL(url));
218 NavigateToURL(shell(), test_url);
220 WebContentsImpl* web_contents =
221 static_cast<WebContentsImpl*>(shell()->web_contents());
222 NavigationControllerImpl* controller = &web_contents->GetController();
224 screenshot_manager_ = new ScreenshotTracker(controller);
225 controller->SetScreenshotManager(screenshot_manager_);
228 virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
229 cmd->AppendSwitchASCII(switches::kTouchEvents,
230 switches::kTouchEventsEnabled);
233 void TestOverscrollNavigation(bool touch_handler) {
234 ASSERT_NO_FATAL_FAILURE(
235 StartTestWithPage("files/overscroll_navigation.html"));
236 WebContentsImpl* web_contents =
237 static_cast<WebContentsImpl*>(shell()->web_contents());
238 NavigationController& controller = web_contents->GetController();
239 RenderFrameHost* main_frame = web_contents->GetMainFrame();
241 EXPECT_FALSE(controller.CanGoBack());
242 EXPECT_FALSE(controller.CanGoForward());
244 scoped_ptr<base::Value> value =
245 content::ExecuteScriptAndGetValue(main_frame, "get_current()");
246 ASSERT_TRUE(value->GetAsInteger(&index));
250 ExecuteSyncJSFunction(main_frame, "install_touch_handler()");
252 ExecuteSyncJSFunction(main_frame, "navigate_next()");
253 ExecuteSyncJSFunction(main_frame, "navigate_next()");
254 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
255 ASSERT_TRUE(value->GetAsInteger(&index));
257 EXPECT_TRUE(controller.CanGoBack());
258 EXPECT_FALSE(controller.CanGoForward());
260 aura::Window* content = web_contents->GetContentNativeView();
261 gfx::Rect bounds = content->GetBoundsInRootWindow();
262 ui::test::EventGenerator generator(content->GetRootWindow(), content);
263 const int kScrollDurationMs = 20;
264 const int kScrollSteps = 10;
267 // Do a swipe-right now. That should navigate backwards.
268 base::string16 expected_title = base::ASCIIToUTF16("Title: #1");
269 content::TitleWatcher title_watcher(web_contents, expected_title);
270 generator.GestureScrollSequence(
271 gfx::Point(bounds.x() + 2, bounds.y() + 10),
272 gfx::Point(bounds.right() - 10, bounds.y() + 10),
273 base::TimeDelta::FromMilliseconds(kScrollDurationMs),
275 base::string16 actual_title = title_watcher.WaitAndGetTitle();
276 EXPECT_EQ(expected_title, actual_title);
277 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
278 ASSERT_TRUE(value->GetAsInteger(&index));
280 EXPECT_TRUE(controller.CanGoBack());
281 EXPECT_TRUE(controller.CanGoForward());
285 // Do a fling-right now. That should navigate backwards.
286 base::string16 expected_title = base::ASCIIToUTF16("Title:");
287 content::TitleWatcher title_watcher(web_contents, expected_title);
288 generator.GestureScrollSequence(
289 gfx::Point(bounds.x() + 2, bounds.y() + 10),
290 gfx::Point(bounds.right() - 10, bounds.y() + 10),
291 base::TimeDelta::FromMilliseconds(kScrollDurationMs),
293 base::string16 actual_title = title_watcher.WaitAndGetTitle();
294 EXPECT_EQ(expected_title, actual_title);
295 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
296 ASSERT_TRUE(value->GetAsInteger(&index));
298 EXPECT_FALSE(controller.CanGoBack());
299 EXPECT_TRUE(controller.CanGoForward());
303 // Do a swipe-left now. That should navigate forward.
304 base::string16 expected_title = base::ASCIIToUTF16("Title: #1");
305 content::TitleWatcher title_watcher(web_contents, expected_title);
306 generator.GestureScrollSequence(
307 gfx::Point(bounds.right() - 10, bounds.y() + 10),
308 gfx::Point(bounds.x() + 2, bounds.y() + 10),
309 base::TimeDelta::FromMilliseconds(kScrollDurationMs),
311 base::string16 actual_title = title_watcher.WaitAndGetTitle();
312 EXPECT_EQ(expected_title, actual_title);
313 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
314 ASSERT_TRUE(value->GetAsInteger(&index));
316 EXPECT_TRUE(controller.CanGoBack());
317 EXPECT_TRUE(controller.CanGoForward());
321 int GetCurrentIndex() {
322 WebContentsImpl* web_contents =
323 static_cast<WebContentsImpl*>(shell()->web_contents());
324 RenderFrameHost* main_frame = web_contents->GetMainFrame();
326 scoped_ptr<base::Value> value;
327 value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
328 if (!value->GetAsInteger(&index))
333 int ExecuteScriptAndExtractInt(const std::string& script) {
335 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
336 shell()->web_contents(),
337 "domAutomationController.send(" + script + ")",
342 RenderViewHost* GetRenderViewHost() const {
343 RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
348 RenderWidgetHostImpl* GetRenderWidgetHost() const {
349 RenderWidgetHostImpl* const rwh =
350 RenderWidgetHostImpl::From(shell()
352 ->GetRenderWidgetHostView()
353 ->GetRenderWidgetHost());
358 RenderWidgetHostViewBase* GetRenderWidgetHostView() const {
359 return static_cast<RenderWidgetHostViewBase*>(
360 GetRenderViewHost()->GetView());
363 InputEventMessageFilterWaitsForAcks* filter() {
364 return filter_.get();
368 uint32 frame = GetRenderWidgetHostView()->RendererFrameNumber();
369 while (!GetRenderWidgetHost()->ScheduleComposite())
371 while (GetRenderWidgetHostView()->RendererFrameNumber() == frame)
376 ScreenshotTracker* screenshot_manager() { return screenshot_manager_; }
377 void set_min_screenshot_interval(int interval_ms) {
378 screenshot_manager_->SetScreenshotInterval(interval_ms);
381 void AddInputEventMessageFilter() {
382 filter_ = new InputEventMessageFilterWaitsForAcks();
383 GetRenderWidgetHost()->GetProcess()->AddFilter(filter_);
387 ScreenshotTracker* screenshot_manager_;
388 scoped_refptr<InputEventMessageFilterWaitsForAcks> filter_;
390 DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
393 // Flaky on Windows: http://crbug.com/305722
395 #define MAYBE_OverscrollNavigation DISABLED_OverscrollNavigation
397 #define MAYBE_OverscrollNavigation OverscrollNavigation
400 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollNavigation) {
401 TestOverscrollNavigation(false);
404 // Flaky on Windows (might be related to the above test):
405 // http://crbug.com/305722
407 #define MAYBE_OverscrollNavigationWithTouchHandler \
408 DISABLED_OverscrollNavigationWithTouchHandler
410 #define MAYBE_OverscrollNavigationWithTouchHandler \
411 OverscrollNavigationWithTouchHandler
413 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
414 MAYBE_OverscrollNavigationWithTouchHandler) {
415 TestOverscrollNavigation(true);
418 // Disabled because the test always fails the first time it runs on the Win Aura
419 // bots, and usually but not always passes second-try (See crbug.com/179532).
421 #define MAYBE_QuickOverscrollDirectionChange \
422 DISABLED_QuickOverscrollDirectionChange
424 #define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange
426 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
427 MAYBE_QuickOverscrollDirectionChange) {
428 ASSERT_NO_FATAL_FAILURE(
429 StartTestWithPage("files/overscroll_navigation.html"));
430 WebContentsImpl* web_contents =
431 static_cast<WebContentsImpl*>(shell()->web_contents());
432 RenderFrameHost* main_frame = web_contents->GetMainFrame();
434 // This test triggers a large number of animations. Speed them up to ensure
435 // the test completes within its time limit.
436 ui::ScopedAnimationDurationScaleMode fast_duration_mode(
437 ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
439 // Make sure the page has both back/forward history.
440 ExecuteSyncJSFunction(main_frame, "navigate_next()");
441 EXPECT_EQ(1, GetCurrentIndex());
442 ExecuteSyncJSFunction(main_frame, "navigate_next()");
443 EXPECT_EQ(2, GetCurrentIndex());
444 web_contents->GetController().GoBack();
445 EXPECT_EQ(1, GetCurrentIndex());
447 aura::Window* content = web_contents->GetContentNativeView();
448 ui::EventProcessor* dispatcher = content->GetHost()->event_processor();
449 gfx::Rect bounds = content->GetBoundsInRootWindow();
451 base::TimeDelta timestamp = ui::EventTimeForNow();
452 ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
453 gfx::Point(bounds.x() + bounds.width() / 2, bounds.y() + 5),
455 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
456 ASSERT_FALSE(details.dispatcher_destroyed);
457 EXPECT_EQ(1, GetCurrentIndex());
459 timestamp += base::TimeDelta::FromMilliseconds(10);
460 ui::TouchEvent move1(ui::ET_TOUCH_MOVED,
461 gfx::Point(bounds.right() - 10, bounds.y() + 5),
463 details = dispatcher->OnEventFromSource(&move1);
464 ASSERT_FALSE(details.dispatcher_destroyed);
465 EXPECT_EQ(1, GetCurrentIndex());
467 // Swipe back from the right edge, back to the left edge, back to the right
470 for (int x = bounds.right() - 10; x >= bounds.x() + 10; x-= 10) {
471 timestamp += base::TimeDelta::FromMilliseconds(10);
472 ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
473 gfx::Point(x, bounds.y() + 5),
475 details = dispatcher->OnEventFromSource(&inc);
476 ASSERT_FALSE(details.dispatcher_destroyed);
477 EXPECT_EQ(1, GetCurrentIndex());
480 for (int x = bounds.x() + 10; x <= bounds.width() - 10; x+= 10) {
481 timestamp += base::TimeDelta::FromMilliseconds(10);
482 ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
483 gfx::Point(x, bounds.y() + 5),
485 details = dispatcher->OnEventFromSource(&inc);
486 ASSERT_FALSE(details.dispatcher_destroyed);
487 EXPECT_EQ(1, GetCurrentIndex());
490 for (int x = bounds.width() - 10; x >= bounds.x() + 10; x-= 10) {
491 timestamp += base::TimeDelta::FromMilliseconds(10);
492 ui::TouchEvent inc(ui::ET_TOUCH_MOVED,
493 gfx::Point(x, bounds.y() + 5),
495 details = dispatcher->OnEventFromSource(&inc);
496 ASSERT_FALSE(details.dispatcher_destroyed);
497 EXPECT_EQ(1, GetCurrentIndex());
500 // Do not end the overscroll sequence.
503 // Tests that the page has has a screenshot when navigation happens:
504 // - from within the page (from a JS function)
505 // - interactively, when user does an overscroll gesture
506 // - interactively, when user navigates in history without the overscroll
508 // Flaky on Windows (http://crbug.com/357311). Might be related to
509 // OverscrollNavigation test.
510 // Flaky on Ozone (http://crbug.com/399676).
511 #if defined(OS_WIN) || defined(USE_OZONE)
512 #define MAYBE_OverscrollScreenshot DISABLED_OverscrollScreenshot
514 #define MAYBE_OverscrollScreenshot OverscrollScreenshot
516 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) {
517 // Disable the test for WinXP. See http://crbug/294116.
519 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
520 LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
525 ASSERT_NO_FATAL_FAILURE(
526 StartTestWithPage("files/overscroll_navigation.html"));
527 WebContentsImpl* web_contents =
528 static_cast<WebContentsImpl*>(shell()->web_contents());
529 RenderFrameHost* main_frame = web_contents->GetMainFrame();
531 set_min_screenshot_interval(0);
533 // Do a few navigations initiated by the page.
534 // Screenshots should never be captured since these are all in-page
536 ExecuteSyncJSFunction(main_frame, "navigate_next()");
537 EXPECT_EQ(1, GetCurrentIndex());
538 ExecuteSyncJSFunction(main_frame, "navigate_next()");
539 EXPECT_EQ(2, GetCurrentIndex());
540 screenshot_manager()->WaitUntilScreenshotIsReady();
542 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
543 web_contents->GetController().GetEntryAtIndex(2));
544 EXPECT_FALSE(entry->screenshot().get());
546 entry = NavigationEntryImpl::FromNavigationEntry(
547 web_contents->GetController().GetEntryAtIndex(1));
548 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
550 entry = NavigationEntryImpl::FromNavigationEntry(
551 web_contents->GetController().GetEntryAtIndex(0));
552 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
554 ExecuteSyncJSFunction(main_frame, "navigate_next()");
555 screenshot_manager()->WaitUntilScreenshotIsReady();
557 entry = NavigationEntryImpl::FromNavigationEntry(
558 web_contents->GetController().GetEntryAtIndex(2));
559 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
561 entry = NavigationEntryImpl::FromNavigationEntry(
562 web_contents->GetController().GetEntryAtIndex(3));
563 EXPECT_FALSE(entry->screenshot().get());
565 // Now, swipe right to navigate backwards. This should navigate away from
566 // index 3 to index 2.
567 base::string16 expected_title = base::ASCIIToUTF16("Title: #2");
568 content::TitleWatcher title_watcher(web_contents, expected_title);
569 aura::Window* content = web_contents->GetContentNativeView();
570 gfx::Rect bounds = content->GetBoundsInRootWindow();
571 ui::test::EventGenerator generator(content->GetRootWindow(), content);
572 generator.GestureScrollSequence(
573 gfx::Point(bounds.x() + 2, bounds.y() + 10),
574 gfx::Point(bounds.right() - 10, bounds.y() + 10),
575 base::TimeDelta::FromMilliseconds(20),
577 base::string16 actual_title = title_watcher.WaitAndGetTitle();
578 EXPECT_EQ(expected_title, actual_title);
579 EXPECT_EQ(2, GetCurrentIndex());
580 screenshot_manager()->WaitUntilScreenshotIsReady();
581 entry = NavigationEntryImpl::FromNavigationEntry(
582 web_contents->GetController().GetEntryAtIndex(3));
583 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
586 // Navigate a couple more times.
587 ExecuteSyncJSFunction(main_frame, "navigate_next()");
588 EXPECT_EQ(3, GetCurrentIndex());
589 ExecuteSyncJSFunction(main_frame, "navigate_next()");
590 EXPECT_EQ(4, GetCurrentIndex());
591 screenshot_manager()->WaitUntilScreenshotIsReady();
592 entry = NavigationEntryImpl::FromNavigationEntry(
593 web_contents->GetController().GetEntryAtIndex(4));
594 EXPECT_FALSE(entry->screenshot().get());
597 // Navigate back in history.
598 base::string16 expected_title = base::ASCIIToUTF16("Title: #3");
599 content::TitleWatcher title_watcher(web_contents, expected_title);
600 web_contents->GetController().GoBack();
601 base::string16 actual_title = title_watcher.WaitAndGetTitle();
602 EXPECT_EQ(expected_title, actual_title);
603 EXPECT_EQ(3, GetCurrentIndex());
604 screenshot_manager()->WaitUntilScreenshotIsReady();
605 entry = NavigationEntryImpl::FromNavigationEntry(
606 web_contents->GetController().GetEntryAtIndex(4));
607 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
611 // Crashes under ThreadSanitizer, http://crbug.com/356758.
612 #if defined(THREAD_SANITIZER)
613 #define MAYBE_ScreenshotForSwappedOutRenderViews \
614 DISABLED_ScreenshotForSwappedOutRenderViews
616 #define MAYBE_ScreenshotForSwappedOutRenderViews \
617 ScreenshotForSwappedOutRenderViews
619 // Tests that screenshot is taken correctly when navigation causes a
620 // RenderViewHost to be swapped out.
621 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
622 MAYBE_ScreenshotForSwappedOutRenderViews) {
623 ASSERT_NO_FATAL_FAILURE(
624 StartTestWithPage("files/overscroll_navigation.html"));
625 // Create a new server with a different site.
626 net::SpawnedTestServer https_server(
627 net::SpawnedTestServer::TYPE_HTTPS,
628 net::SpawnedTestServer::kLocalhost,
629 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
630 ASSERT_TRUE(https_server.Start());
632 WebContentsImpl* web_contents =
633 static_cast<WebContentsImpl*>(shell()->web_contents());
634 set_min_screenshot_interval(0);
640 { https_server.GetURL("files/title1.html"),
641 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
642 { test_server()->GetURL("files/title2.html"),
643 PAGE_TRANSITION_AUTO_BOOKMARK },
644 { https_server.GetURL("files/title3.html"),
645 PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
649 screenshot_manager()->Reset();
650 for (int i = 0; !navigations[i].url.is_empty(); ++i) {
651 // Navigate via the user initiating a navigation from the UI.
652 NavigationController::LoadURLParams params(navigations[i].url);
653 params.transition_type = PageTransitionFromInt(navigations[i].transition);
655 RenderViewHost* old_host = web_contents->GetRenderViewHost();
656 web_contents->GetController().LoadURLWithParams(params);
657 WaitForLoadStop(web_contents);
658 screenshot_manager()->WaitUntilScreenshotIsReady();
660 EXPECT_NE(old_host, web_contents->GetRenderViewHost())
661 << navigations[i].url.spec();
662 EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for());
664 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
665 web_contents->GetController().GetEntryAtOffset(-1));
666 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
668 entry = NavigationEntryImpl::FromNavigationEntry(
669 web_contents->GetController().GetLastCommittedEntry());
670 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
671 EXPECT_FALSE(entry->screenshot().get());
672 screenshot_manager()->Reset();
675 // Increase the minimum interval between taking screenshots.
676 set_min_screenshot_interval(60000);
678 // Navigate again. This should not take any screenshot because of the
679 // increased screenshot interval.
680 NavigationController::LoadURLParams params(navigations[0].url);
681 params.transition_type = PageTransitionFromInt(navigations[0].transition);
682 web_contents->GetController().LoadURLWithParams(params);
683 WaitForLoadStop(web_contents);
684 screenshot_manager()->WaitUntilScreenshotIsReady();
686 EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for());
689 // Tests that navigations resulting from reloads, history.replaceState,
690 // and history.pushState do not capture screenshots.
691 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ReplaceStateReloadPushState) {
692 ASSERT_NO_FATAL_FAILURE(
693 StartTestWithPage("files/overscroll_navigation.html"));
694 WebContentsImpl* web_contents =
695 static_cast<WebContentsImpl*>(shell()->web_contents());
696 RenderFrameHost* main_frame = web_contents->GetMainFrame();
698 set_min_screenshot_interval(0);
699 screenshot_manager()->Reset();
700 ExecuteSyncJSFunction(main_frame, "use_replace_state()");
701 screenshot_manager()->WaitUntilScreenshotIsReady();
702 // history.replaceState shouldn't capture a screenshot
703 EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
704 screenshot_manager()->Reset();
705 web_contents->GetController().Reload(true);
706 WaitForLoadStop(web_contents);
707 // reloading the page shouldn't capture a screenshot
708 // TODO (mfomitchev): currently broken. Uncomment when
709 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page
710 // is populated properly when reloading the page.
711 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
712 screenshot_manager()->Reset();
713 ExecuteSyncJSFunction(main_frame, "use_push_state()");
714 screenshot_manager()->WaitUntilScreenshotIsReady();
715 // pushing a state shouldn't capture a screenshot
716 // TODO (mfomitchev): currently broken. Uncomment when
717 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page
718 // is populated properly when pushState is used.
719 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
722 // TODO(sadrul): This test is disabled because it reparents in a way the
723 // FocusController does not support. This code would crash in
724 // a production build. It only passed prior to this revision
725 // because testing used the old FocusManager which did some
726 // different (osbolete) processing. TODO(sadrul) to figure out
727 // how this test should work that mimics production code a bit
729 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
730 DISABLED_ContentWindowReparent) {
731 ASSERT_NO_FATAL_FAILURE(
732 StartTestWithPage("files/overscroll_navigation.html"));
734 scoped_ptr<aura::Window> window(new aura::Window(NULL));
735 window->Init(aura::WINDOW_LAYER_NOT_DRAWN);
737 WebContentsImpl* web_contents =
738 static_cast<WebContentsImpl*>(shell()->web_contents());
739 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
740 EXPECT_EQ(1, GetCurrentIndex());
742 aura::Window* content = web_contents->GetContentNativeView();
743 gfx::Rect bounds = content->GetBoundsInRootWindow();
744 ui::test::EventGenerator generator(content->GetRootWindow(), content);
745 generator.GestureScrollSequence(
746 gfx::Point(bounds.x() + 2, bounds.y() + 10),
747 gfx::Point(bounds.right() - 10, bounds.y() + 10),
748 base::TimeDelta::FromMilliseconds(20),
751 window->AddChild(shell()->web_contents()->GetContentNativeView());
754 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) {
755 ASSERT_NO_FATAL_FAILURE(
756 StartTestWithPage("files/overscroll_navigation.html"));
758 WebContentsImpl* web_contents =
759 static_cast<WebContentsImpl*>(shell()->web_contents());
760 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
761 EXPECT_EQ(1, GetCurrentIndex());
763 aura::Window* content = web_contents->GetContentNativeView();
764 gfx::Rect bounds = content->GetBoundsInRootWindow();
765 ui::test::EventGenerator generator(content->GetRootWindow(), content);
766 generator.GestureScrollSequence(
767 gfx::Point(bounds.x() + 2, bounds.y() + 10),
768 gfx::Point(bounds.right() - 10, bounds.y() + 10),
769 base::TimeDelta::FromMilliseconds(20),
772 delete web_contents->GetContentNativeView();
776 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
777 // This appears to be flaky in the same was as the other overscroll
778 // tests. Enabling for non-Windows platforms.
779 // See http://crbug.com/369871.
780 // For linux, see http://crbug.com/381294
781 #define MAYBE_RepeatedQuickOverscrollGestures DISABLED_RepeatedQuickOverscrollGestures
783 #define MAYBE_RepeatedQuickOverscrollGestures RepeatedQuickOverscrollGestures
786 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
787 MAYBE_RepeatedQuickOverscrollGestures) {
788 ASSERT_NO_FATAL_FAILURE(
789 StartTestWithPage("files/overscroll_navigation.html"));
791 WebContentsImpl* web_contents =
792 static_cast<WebContentsImpl*>(shell()->web_contents());
793 NavigationController& controller = web_contents->GetController();
794 RenderFrameHost* main_frame = web_contents->GetMainFrame();
795 ExecuteSyncJSFunction(main_frame, "install_touch_handler()");
797 // Navigate twice, then navigate back in history once.
798 ExecuteSyncJSFunction(main_frame, "navigate_next()");
799 ExecuteSyncJSFunction(main_frame, "navigate_next()");
800 EXPECT_EQ(2, GetCurrentIndex());
801 EXPECT_TRUE(controller.CanGoBack());
802 EXPECT_FALSE(controller.CanGoForward());
804 web_contents->GetController().GoBack();
805 WaitForLoadStop(web_contents);
806 EXPECT_EQ(1, GetCurrentIndex());
807 EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents->GetTitle());
808 EXPECT_TRUE(controller.CanGoBack());
809 EXPECT_TRUE(controller.CanGoForward());
811 aura::Window* content = web_contents->GetContentNativeView();
812 gfx::Rect bounds = content->GetBoundsInRootWindow();
813 ui::test::EventGenerator generator(content->GetRootWindow(), content);
815 // Do a swipe left to start a forward navigation. Then quickly do a swipe
817 base::string16 expected_title = base::ASCIIToUTF16("Title: #2");
818 content::TitleWatcher title_watcher(web_contents, expected_title);
819 NavigationWatcher nav_watcher(web_contents);
821 generator.GestureScrollSequence(
822 gfx::Point(bounds.right() - 10, bounds.y() + 10),
823 gfx::Point(bounds.x() + 2, bounds.y() + 10),
824 base::TimeDelta::FromMilliseconds(2000),
826 nav_watcher.WaitUntilNavigationStarts();
828 generator.GestureScrollSequence(
829 gfx::Point(bounds.x() + 2, bounds.y() + 10),
830 gfx::Point(bounds.right() - 10, bounds.y() + 10),
831 base::TimeDelta::FromMilliseconds(2000),
833 base::string16 actual_title = title_watcher.WaitAndGetTitle();
834 EXPECT_EQ(expected_title, actual_title);
836 EXPECT_EQ(2, GetCurrentIndex());
837 EXPECT_TRUE(controller.CanGoBack());
838 EXPECT_FALSE(controller.CanGoForward());
841 // Verify that hiding a parent of the renderer will hide the content too.
842 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, HideContentOnParenHide) {
843 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/title1.html"));
844 WebContentsImpl* web_contents =
845 static_cast<WebContentsImpl*>(shell()->web_contents());
846 aura::Window* content = web_contents->GetNativeView()->parent();
847 EXPECT_TRUE(web_contents->should_normally_be_visible());
849 EXPECT_FALSE(web_contents->should_normally_be_visible());
851 EXPECT_TRUE(web_contents->should_normally_be_visible());
854 // Ensure that SnapToPhysicalPixelBoundary() is called on WebContentsView parent
855 // change. This is a regression test for http://crbug.com/388908.
856 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, WebContentsViewReparent) {
857 ASSERT_NO_FATAL_FAILURE(
858 StartTestWithPage("files/overscroll_navigation.html"));
860 scoped_ptr<aura::Window> window(new aura::Window(NULL));
861 window->Init(aura::WINDOW_LAYER_NOT_DRAWN);
863 RenderWidgetHostViewAura* rwhva =
864 static_cast<RenderWidgetHostViewAura*>(
865 shell()->web_contents()->GetRenderWidgetHostView());
866 rwhva->ResetHasSnappedToBoundary();
867 EXPECT_FALSE(rwhva->has_snapped_to_boundary());
868 window->AddChild(shell()->web_contents()->GetNativeView());
869 EXPECT_TRUE(rwhva->has_snapped_to_boundary());
872 // Flaky on Windows, likely for the same reason as other flaky overscroll tests.
873 // http://crbug.com/305722
875 #define MAYBE_OverscrollNavigationTouchThrottling \
876 DISABLED_OverscrollNavigationTouchThrottling
878 #define MAYBE_OverscrollNavigationTouchThrottling \
879 OverscrollNavigationTouchThrottling
882 // Tests that touch moves are not throttled when performing a scroll gesture on
883 // a non-scrollable area, except during gesture-nav.
884 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
885 MAYBE_OverscrollNavigationTouchThrottling) {
886 ASSERT_NO_FATAL_FAILURE(
887 StartTestWithPage("files/overscroll_navigation.html"));
889 AddInputEventMessageFilter();
891 WebContentsImpl* web_contents =
892 static_cast<WebContentsImpl*>(shell()->web_contents());
893 aura::Window* content = web_contents->GetContentNativeView();
894 gfx::Rect bounds = content->GetBoundsInRootWindow();
897 ExecuteSyncJSFunction(web_contents->GetMainFrame(),
898 "install_touchmove_handler()");
902 for (int navigated = 0; navigated <= 1; ++navigated) {
904 ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
905 ExecuteSyncJSFunction(web_contents->GetMainFrame(),
906 "reset_touchmove_count()");
909 SyntheticWebTouchEvent touch;
910 touch.PressPoint(bounds.x() + 2, bounds.y() + 10);
911 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
913 filter()->WaitForAck(blink::WebInputEvent::TouchStart);
914 // Assert on the ack, because we'll end up waiting for acks that will never
915 // come if this is not true.
916 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
918 // Send first touch move, and then a scroll begin.
919 touch.MovePoint(0, bounds.x() + 20 + 1 * dx, bounds.y() + 100);
920 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
922 filter()->WaitForAck(blink::WebInputEvent::TouchMove);
923 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
925 blink::WebGestureEvent scroll_begin =
926 SyntheticWebGestureEventBuilder::BuildScrollBegin(1, 1);
927 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
928 scroll_begin, ui::LatencyInfo());
929 // Scroll begin ignores ack disposition, so don't wait for the ack.
933 // First touchmove already sent, start at 2.
934 for (int i = 2; i <= 10; ++i) {
935 // Send a touch move, followed by a scroll update
936 touch.MovePoint(0, bounds.x() + 20 + i * dx, bounds.y() + 100);
937 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(
938 touch, ui::LatencyInfo());
941 blink::WebGestureEvent scroll_update =
942 SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, 5, 0);
944 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
945 scroll_update, ui::LatencyInfo());
950 touch.ReleasePoint(0);
951 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
955 blink::WebGestureEvent scroll_end;
956 scroll_end.type = blink::WebInputEvent::GestureScrollEnd;
957 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
958 scroll_end, ui::LatencyInfo());
962 EXPECT_EQ(10, ExecuteScriptAndExtractInt("touchmoveCount"));
964 EXPECT_GT(10, ExecuteScriptAndExtractInt("touchmoveCount"));
968 } // namespace content