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_
.get());
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 // Flaky on ChromeOS (http://crbug.com/405945).
512 #if defined(OS_WIN) || defined(USE_OZONE) || defined(OS_CHROMEOS)
513 #define MAYBE_OverscrollScreenshot DISABLED_OverscrollScreenshot
515 #define MAYBE_OverscrollScreenshot OverscrollScreenshot
517 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, MAYBE_OverscrollScreenshot
) {
518 // Disable the test for WinXP. See http://crbug/294116.
520 if (base::win::GetVersion() < base::win::VERSION_VISTA
) {
521 LOG(WARNING
) << "Test disabled due to unknown bug on WinXP.";
526 ASSERT_NO_FATAL_FAILURE(
527 StartTestWithPage("files/overscroll_navigation.html"));
528 WebContentsImpl
* web_contents
=
529 static_cast<WebContentsImpl
*>(shell()->web_contents());
530 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
532 set_min_screenshot_interval(0);
534 // Do a few navigations initiated by the page.
535 // Screenshots should never be captured since these are all in-page
537 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
538 EXPECT_EQ(1, GetCurrentIndex());
539 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
540 EXPECT_EQ(2, GetCurrentIndex());
541 screenshot_manager()->WaitUntilScreenshotIsReady();
543 NavigationEntryImpl
* entry
= NavigationEntryImpl::FromNavigationEntry(
544 web_contents
->GetController().GetEntryAtIndex(2));
545 EXPECT_FALSE(entry
->screenshot().get());
547 entry
= NavigationEntryImpl::FromNavigationEntry(
548 web_contents
->GetController().GetEntryAtIndex(1));
549 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
551 entry
= NavigationEntryImpl::FromNavigationEntry(
552 web_contents
->GetController().GetEntryAtIndex(0));
553 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
555 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
556 screenshot_manager()->WaitUntilScreenshotIsReady();
558 entry
= NavigationEntryImpl::FromNavigationEntry(
559 web_contents
->GetController().GetEntryAtIndex(2));
560 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
562 entry
= NavigationEntryImpl::FromNavigationEntry(
563 web_contents
->GetController().GetEntryAtIndex(3));
564 EXPECT_FALSE(entry
->screenshot().get());
566 // Now, swipe right to navigate backwards. This should navigate away from
567 // index 3 to index 2.
568 base::string16 expected_title
= base::ASCIIToUTF16("Title: #2");
569 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
570 aura::Window
* content
= web_contents
->GetContentNativeView();
571 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
572 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
573 generator
.GestureScrollSequence(
574 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
575 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
576 base::TimeDelta::FromMilliseconds(20),
578 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
579 EXPECT_EQ(expected_title
, actual_title
);
580 EXPECT_EQ(2, GetCurrentIndex());
581 screenshot_manager()->WaitUntilScreenshotIsReady();
582 entry
= NavigationEntryImpl::FromNavigationEntry(
583 web_contents
->GetController().GetEntryAtIndex(3));
584 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
587 // Navigate a couple more times.
588 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
589 EXPECT_EQ(3, GetCurrentIndex());
590 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
591 EXPECT_EQ(4, GetCurrentIndex());
592 screenshot_manager()->WaitUntilScreenshotIsReady();
593 entry
= NavigationEntryImpl::FromNavigationEntry(
594 web_contents
->GetController().GetEntryAtIndex(4));
595 EXPECT_FALSE(entry
->screenshot().get());
598 // Navigate back in history.
599 base::string16 expected_title
= base::ASCIIToUTF16("Title: #3");
600 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
601 web_contents
->GetController().GoBack();
602 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
603 EXPECT_EQ(expected_title
, actual_title
);
604 EXPECT_EQ(3, GetCurrentIndex());
605 screenshot_manager()->WaitUntilScreenshotIsReady();
606 entry
= NavigationEntryImpl::FromNavigationEntry(
607 web_contents
->GetController().GetEntryAtIndex(4));
608 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
612 // Crashes under ThreadSanitizer, http://crbug.com/356758.
613 #if defined(THREAD_SANITIZER)
614 #define MAYBE_ScreenshotForSwappedOutRenderViews \
615 DISABLED_ScreenshotForSwappedOutRenderViews
617 #define MAYBE_ScreenshotForSwappedOutRenderViews \
618 ScreenshotForSwappedOutRenderViews
620 // Tests that screenshot is taken correctly when navigation causes a
621 // RenderViewHost to be swapped out.
622 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
623 MAYBE_ScreenshotForSwappedOutRenderViews
) {
624 ASSERT_NO_FATAL_FAILURE(
625 StartTestWithPage("files/overscroll_navigation.html"));
626 // Create a new server with a different site.
627 net::SpawnedTestServer
https_server(
628 net::SpawnedTestServer::TYPE_HTTPS
,
629 net::SpawnedTestServer::kLocalhost
,
630 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
631 ASSERT_TRUE(https_server
.Start());
633 WebContentsImpl
* web_contents
=
634 static_cast<WebContentsImpl
*>(shell()->web_contents());
635 set_min_screenshot_interval(0);
641 { https_server
.GetURL("files/title1.html"),
642 PAGE_TRANSITION_TYPED
| PAGE_TRANSITION_FROM_ADDRESS_BAR
},
643 { test_server()->GetURL("files/title2.html"),
644 PAGE_TRANSITION_AUTO_BOOKMARK
},
645 { https_server
.GetURL("files/title3.html"),
646 PAGE_TRANSITION_TYPED
| PAGE_TRANSITION_FROM_ADDRESS_BAR
},
650 screenshot_manager()->Reset();
651 for (int i
= 0; !navigations
[i
].url
.is_empty(); ++i
) {
652 // Navigate via the user initiating a navigation from the UI.
653 NavigationController::LoadURLParams
params(navigations
[i
].url
);
654 params
.transition_type
= PageTransitionFromInt(navigations
[i
].transition
);
656 RenderViewHost
* old_host
= web_contents
->GetRenderViewHost();
657 web_contents
->GetController().LoadURLWithParams(params
);
658 WaitForLoadStop(web_contents
);
659 screenshot_manager()->WaitUntilScreenshotIsReady();
661 EXPECT_NE(old_host
, web_contents
->GetRenderViewHost())
662 << navigations
[i
].url
.spec();
663 EXPECT_EQ(old_host
, screenshot_manager()->screenshot_taken_for());
665 NavigationEntryImpl
* entry
= NavigationEntryImpl::FromNavigationEntry(
666 web_contents
->GetController().GetEntryAtOffset(-1));
667 EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry
));
669 entry
= NavigationEntryImpl::FromNavigationEntry(
670 web_contents
->GetController().GetLastCommittedEntry());
671 EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry
));
672 EXPECT_FALSE(entry
->screenshot().get());
673 screenshot_manager()->Reset();
676 // Increase the minimum interval between taking screenshots.
677 set_min_screenshot_interval(60000);
679 // Navigate again. This should not take any screenshot because of the
680 // increased screenshot interval.
681 NavigationController::LoadURLParams
params(navigations
[0].url
);
682 params
.transition_type
= PageTransitionFromInt(navigations
[0].transition
);
683 web_contents
->GetController().LoadURLWithParams(params
);
684 WaitForLoadStop(web_contents
);
685 screenshot_manager()->WaitUntilScreenshotIsReady();
687 EXPECT_EQ(NULL
, screenshot_manager()->screenshot_taken_for());
690 // Tests that navigations resulting from reloads, history.replaceState,
691 // and history.pushState do not capture screenshots.
692 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, ReplaceStateReloadPushState
) {
693 ASSERT_NO_FATAL_FAILURE(
694 StartTestWithPage("files/overscroll_navigation.html"));
695 WebContentsImpl
* web_contents
=
696 static_cast<WebContentsImpl
*>(shell()->web_contents());
697 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
699 set_min_screenshot_interval(0);
700 screenshot_manager()->Reset();
701 ExecuteSyncJSFunction(main_frame
, "use_replace_state()");
702 screenshot_manager()->WaitUntilScreenshotIsReady();
703 // history.replaceState shouldn't capture a screenshot
704 EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
705 screenshot_manager()->Reset();
706 web_contents
->GetController().Reload(true);
707 WaitForLoadStop(web_contents
);
708 // reloading the page shouldn't capture a screenshot
709 // TODO (mfomitchev): currently broken. Uncomment when
710 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page
711 // is populated properly when reloading the page.
712 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
713 screenshot_manager()->Reset();
714 ExecuteSyncJSFunction(main_frame
, "use_push_state()");
715 screenshot_manager()->WaitUntilScreenshotIsReady();
716 // pushing a state shouldn't capture a screenshot
717 // TODO (mfomitchev): currently broken. Uncomment when
718 // FrameHostMsg_DidCommitProvisionalLoad_Params.was_within_same_page
719 // is populated properly when pushState is used.
720 //EXPECT_FALSE(screenshot_manager()->screenshot_taken_for());
723 // TODO(sadrul): This test is disabled because it reparents in a way the
724 // FocusController does not support. This code would crash in
725 // a production build. It only passed prior to this revision
726 // because testing used the old FocusManager which did some
727 // different (osbolete) processing. TODO(sadrul) to figure out
728 // how this test should work that mimics production code a bit
730 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
731 DISABLED_ContentWindowReparent
) {
732 ASSERT_NO_FATAL_FAILURE(
733 StartTestWithPage("files/overscroll_navigation.html"));
735 scoped_ptr
<aura::Window
> window(new aura::Window(NULL
));
736 window
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
738 WebContentsImpl
* web_contents
=
739 static_cast<WebContentsImpl
*>(shell()->web_contents());
740 ExecuteSyncJSFunction(web_contents
->GetMainFrame(), "navigate_next()");
741 EXPECT_EQ(1, GetCurrentIndex());
743 aura::Window
* content
= web_contents
->GetContentNativeView();
744 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
745 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
746 generator
.GestureScrollSequence(
747 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
748 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
749 base::TimeDelta::FromMilliseconds(20),
752 window
->AddChild(shell()->web_contents()->GetContentNativeView());
755 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, ContentWindowClose
) {
756 ASSERT_NO_FATAL_FAILURE(
757 StartTestWithPage("files/overscroll_navigation.html"));
759 WebContentsImpl
* web_contents
=
760 static_cast<WebContentsImpl
*>(shell()->web_contents());
761 ExecuteSyncJSFunction(web_contents
->GetMainFrame(), "navigate_next()");
762 EXPECT_EQ(1, GetCurrentIndex());
764 aura::Window
* content
= web_contents
->GetContentNativeView();
765 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
766 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
767 generator
.GestureScrollSequence(
768 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
769 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
770 base::TimeDelta::FromMilliseconds(20),
773 delete web_contents
->GetContentNativeView();
777 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
778 // This appears to be flaky in the same was as the other overscroll
779 // tests. Enabling for non-Windows platforms.
780 // See http://crbug.com/369871.
781 // For linux, see http://crbug.com/381294
782 #define MAYBE_RepeatedQuickOverscrollGestures DISABLED_RepeatedQuickOverscrollGestures
784 #define MAYBE_RepeatedQuickOverscrollGestures RepeatedQuickOverscrollGestures
787 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
788 MAYBE_RepeatedQuickOverscrollGestures
) {
789 ASSERT_NO_FATAL_FAILURE(
790 StartTestWithPage("files/overscroll_navigation.html"));
792 WebContentsImpl
* web_contents
=
793 static_cast<WebContentsImpl
*>(shell()->web_contents());
794 NavigationController
& controller
= web_contents
->GetController();
795 RenderFrameHost
* main_frame
= web_contents
->GetMainFrame();
796 ExecuteSyncJSFunction(main_frame
, "install_touch_handler()");
798 // Navigate twice, then navigate back in history once.
799 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
800 ExecuteSyncJSFunction(main_frame
, "navigate_next()");
801 EXPECT_EQ(2, GetCurrentIndex());
802 EXPECT_TRUE(controller
.CanGoBack());
803 EXPECT_FALSE(controller
.CanGoForward());
805 web_contents
->GetController().GoBack();
806 WaitForLoadStop(web_contents
);
807 EXPECT_EQ(1, GetCurrentIndex());
808 EXPECT_EQ(base::ASCIIToUTF16("Title: #1"), web_contents
->GetTitle());
809 EXPECT_TRUE(controller
.CanGoBack());
810 EXPECT_TRUE(controller
.CanGoForward());
812 aura::Window
* content
= web_contents
->GetContentNativeView();
813 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
814 ui::test::EventGenerator
generator(content
->GetRootWindow(), content
);
816 // Do a swipe left to start a forward navigation. Then quickly do a swipe
818 base::string16 expected_title
= base::ASCIIToUTF16("Title: #2");
819 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
820 NavigationWatcher
nav_watcher(web_contents
);
822 generator
.GestureScrollSequence(
823 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
824 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
825 base::TimeDelta::FromMilliseconds(2000),
827 nav_watcher
.WaitUntilNavigationStarts();
829 generator
.GestureScrollSequence(
830 gfx::Point(bounds
.x() + 2, bounds
.y() + 10),
831 gfx::Point(bounds
.right() - 10, bounds
.y() + 10),
832 base::TimeDelta::FromMilliseconds(2000),
834 base::string16 actual_title
= title_watcher
.WaitAndGetTitle();
835 EXPECT_EQ(expected_title
, actual_title
);
837 EXPECT_EQ(2, GetCurrentIndex());
838 EXPECT_TRUE(controller
.CanGoBack());
839 EXPECT_FALSE(controller
.CanGoForward());
842 // Verify that hiding a parent of the renderer will hide the content too.
843 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, HideContentOnParenHide
) {
844 ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/title1.html"));
845 WebContentsImpl
* web_contents
=
846 static_cast<WebContentsImpl
*>(shell()->web_contents());
847 aura::Window
* content
= web_contents
->GetNativeView()->parent();
848 EXPECT_TRUE(web_contents
->should_normally_be_visible());
850 EXPECT_FALSE(web_contents
->should_normally_be_visible());
852 EXPECT_TRUE(web_contents
->should_normally_be_visible());
855 // Ensure that SnapToPhysicalPixelBoundary() is called on WebContentsView parent
856 // change. This is a regression test for http://crbug.com/388908.
857 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
, WebContentsViewReparent
) {
858 ASSERT_NO_FATAL_FAILURE(
859 StartTestWithPage("files/overscroll_navigation.html"));
861 scoped_ptr
<aura::Window
> window(new aura::Window(NULL
));
862 window
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
864 RenderWidgetHostViewAura
* rwhva
=
865 static_cast<RenderWidgetHostViewAura
*>(
866 shell()->web_contents()->GetRenderWidgetHostView());
867 rwhva
->ResetHasSnappedToBoundary();
868 EXPECT_FALSE(rwhva
->has_snapped_to_boundary());
869 window
->AddChild(shell()->web_contents()->GetNativeView());
870 EXPECT_TRUE(rwhva
->has_snapped_to_boundary());
873 // Flaky on some platforms, likely for the same reason as other flaky overscroll
874 // tests. http://crbug.com/305722
875 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
876 #define MAYBE_OverscrollNavigationTouchThrottling \
877 DISABLED_OverscrollNavigationTouchThrottling
879 #define MAYBE_OverscrollNavigationTouchThrottling \
880 OverscrollNavigationTouchThrottling
883 // Tests that touch moves are not throttled when performing a scroll gesture on
884 // a non-scrollable area, except during gesture-nav.
885 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest
,
886 MAYBE_OverscrollNavigationTouchThrottling
) {
887 ASSERT_NO_FATAL_FAILURE(
888 StartTestWithPage("files/overscroll_navigation.html"));
890 AddInputEventMessageFilter();
892 WebContentsImpl
* web_contents
=
893 static_cast<WebContentsImpl
*>(shell()->web_contents());
894 aura::Window
* content
= web_contents
->GetContentNativeView();
895 gfx::Rect bounds
= content
->GetBoundsInRootWindow();
898 ExecuteSyncJSFunction(web_contents
->GetMainFrame(),
899 "install_touchmove_handler()");
903 for (int navigated
= 0; navigated
<= 1; ++navigated
) {
905 ExecuteSyncJSFunction(web_contents
->GetMainFrame(), "navigate_next()");
906 ExecuteSyncJSFunction(web_contents
->GetMainFrame(),
907 "reset_touchmove_count()");
910 SyntheticWebTouchEvent touch
;
911 touch
.PressPoint(bounds
.x() + 2, bounds
.y() + 10);
912 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch
,
914 filter()->WaitForAck(blink::WebInputEvent::TouchStart
);
917 // Assert on the ack, because we'll end up waiting for acks that will never
918 // come if this is not true.
919 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
, filter()->last_ack_state());
921 // Send first touch move, and then a scroll begin.
922 touch
.MovePoint(0, bounds
.x() + 20 + 1 * dx
, bounds
.y() + 100);
923 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch
,
925 filter()->WaitForAck(blink::WebInputEvent::TouchMove
);
926 ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED
, filter()->last_ack_state());
928 blink::WebGestureEvent scroll_begin
=
929 SyntheticWebGestureEventBuilder::BuildScrollBegin(1, 1);
930 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
931 scroll_begin
, ui::LatencyInfo());
932 // Scroll begin ignores ack disposition, so don't wait for the ack.
935 // First touchmove already sent, start at 2.
936 for (int i
= 2; i
<= 10; ++i
) {
937 // Send a touch move, followed by a scroll update
938 touch
.MovePoint(0, bounds
.x() + 20 + i
* dx
, bounds
.y() + 100);
939 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(
940 touch
, ui::LatencyInfo());
943 blink::WebGestureEvent scroll_update
=
944 SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx
, 5, 0);
946 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
947 scroll_update
, ui::LatencyInfo());
952 touch
.ReleasePoint(0);
953 GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch
,
957 blink::WebGestureEvent scroll_end
;
958 scroll_end
.type
= blink::WebInputEvent::GestureScrollEnd
;
959 GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
960 scroll_end
, ui::LatencyInfo());
964 EXPECT_EQ(10, ExecuteScriptAndExtractInt("touchmoveCount"));
966 EXPECT_GT(10, ExecuteScriptAndExtractInt("touchmoveCount"));
970 } // namespace content