Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / web_contents / web_contents_view_aura_browsertest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/web_contents/web_contents_view_aura.h"
6
7 #include "base/command_line.h"
8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/test_timeouts.h"
11 #include "base/values.h"
12 #if defined(OS_WIN)
13 #include "base/win/windows_version.h"
14 #endif
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"
41
42 namespace {
43
44 // TODO(tdresser): Find a way to avoid sleeping like this. See crbug.com/405282
45 // for details.
46 void GiveItSomeTime() {
47   base::RunLoop run_loop;
48   base::MessageLoop::current()->PostDelayedTask(
49       FROM_HERE,
50       run_loop.QuitClosure(),
51       base::TimeDelta::FromMillisecondsD(10));
52   run_loop.Run();
53 }
54
55 }  //namespace
56
57
58 namespace content {
59
60 // This class keeps track of the RenderViewHost whose screenshot was captured.
61 class ScreenshotTracker : public NavigationEntryScreenshotManager {
62  public:
63   explicit ScreenshotTracker(NavigationControllerImpl* controller)
64       : NavigationEntryScreenshotManager(controller),
65         screenshot_taken_for_(NULL),
66         waiting_for_screenshots_(0) {
67   }
68
69   virtual ~ScreenshotTracker() {
70   }
71
72   RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; }
73
74   void Reset() {
75     screenshot_taken_for_ = NULL;
76     screenshot_set_.clear();
77   }
78
79   void SetScreenshotInterval(int interval_ms) {
80     SetMinScreenshotIntervalMS(interval_ms);
81   }
82
83   void WaitUntilScreenshotIsReady() {
84     if (!waiting_for_screenshots_)
85       return;
86     message_loop_runner_ = new content::MessageLoopRunner;
87     message_loop_runner_->Run();
88   }
89
90   bool ScreenshotSetForEntry(NavigationEntryImpl* entry) const {
91     return screenshot_set_.count(entry) > 0;
92   }
93
94  private:
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);
101   }
102
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();
109   }
110
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_;
115
116   DISALLOW_COPY_AND_ASSIGN(ScreenshotTracker);
117 };
118
119 class NavigationWatcher : public WebContentsObserver {
120  public:
121   explicit NavigationWatcher(WebContents* contents)
122       : WebContentsObserver(contents),
123         navigated_(false),
124         should_quit_loop_(false) {
125   }
126
127   virtual ~NavigationWatcher() {}
128
129   void WaitUntilNavigationStarts() {
130     if (navigated_)
131       return;
132     should_quit_loop_ = true;
133     base::MessageLoop::current()->Run();
134   }
135
136  private:
137   // Overridden from WebContentsObserver:
138   virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE {
139     navigated_ = true;
140     if (should_quit_loop_)
141       base::MessageLoop::current()->Quit();
142   }
143
144   bool navigated_;
145   bool should_quit_loop_;
146
147   DISALLOW_COPY_AND_ASSIGN(NavigationWatcher);
148 };
149
150 class InputEventMessageFilterWaitsForAcks : public BrowserMessageFilter {
151  public:
152   InputEventMessageFilterWaitsForAcks()
153       : BrowserMessageFilter(InputMsgStart),
154         type_(blink::WebInputEvent::Undefined),
155         state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
156
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);
161     run_loop.Run();
162   }
163
164   InputEventAckState last_ack_state() const { return state_; }
165
166  protected:
167   virtual ~InputEventMessageFilterWaitsForAcks() {}
168
169  private:
170   void ReceivedEventAck(blink::WebInputEvent::Type type,
171                         InputEventAckState state) {
172     if (type_ == type) {
173       state_ = state;
174       quit_.Run();
175     }
176   }
177
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, &params);
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,
187                      this, type, ack));
188     }
189     return false;
190   }
191
192   base::Closure quit_;
193   blink::WebInputEvent::Type type_;
194   InputEventAckState state_;
195
196   DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilterWaitsForAcks);
197 };
198
199 class WebContentsViewAuraTest : public ContentBrowserTest {
200  public:
201   WebContentsViewAuraTest()
202       : screenshot_manager_(NULL) {
203   }
204
205   // Executes the javascript synchronously and makes sure the returned value is
206   // freed properly.
207   void ExecuteSyncJSFunction(RenderFrameHost* rfh, const std::string& jscript) {
208     scoped_ptr<base::Value> value =
209         content::ExecuteScriptAndGetValue(rfh, jscript);
210   }
211
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
214   // complete.
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);
219
220     WebContentsImpl* web_contents =
221         static_cast<WebContentsImpl*>(shell()->web_contents());
222     NavigationControllerImpl* controller = &web_contents->GetController();
223
224     screenshot_manager_ = new ScreenshotTracker(controller);
225     controller->SetScreenshotManager(screenshot_manager_);
226   }
227
228   virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
229     cmd->AppendSwitchASCII(switches::kTouchEvents,
230                            switches::kTouchEventsEnabled);
231   }
232
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();
240
241     EXPECT_FALSE(controller.CanGoBack());
242     EXPECT_FALSE(controller.CanGoForward());
243     int index = -1;
244     scoped_ptr<base::Value> value =
245         content::ExecuteScriptAndGetValue(main_frame, "get_current()");
246     ASSERT_TRUE(value->GetAsInteger(&index));
247     EXPECT_EQ(0, index);
248
249     if (touch_handler)
250       ExecuteSyncJSFunction(main_frame, "install_touch_handler()");
251
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));
256     EXPECT_EQ(2, index);
257     EXPECT_TRUE(controller.CanGoBack());
258     EXPECT_FALSE(controller.CanGoForward());
259
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;
265
266     {
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),
274           kScrollSteps);
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));
279       EXPECT_EQ(1, index);
280       EXPECT_TRUE(controller.CanGoBack());
281       EXPECT_TRUE(controller.CanGoForward());
282     }
283
284     {
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),
292           kScrollSteps);
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));
297       EXPECT_EQ(0, index);
298       EXPECT_FALSE(controller.CanGoBack());
299       EXPECT_TRUE(controller.CanGoForward());
300     }
301
302     {
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),
310           kScrollSteps);
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));
315       EXPECT_EQ(1, index);
316       EXPECT_TRUE(controller.CanGoBack());
317       EXPECT_TRUE(controller.CanGoForward());
318     }
319   }
320
321   int GetCurrentIndex() {
322     WebContentsImpl* web_contents =
323         static_cast<WebContentsImpl*>(shell()->web_contents());
324     RenderFrameHost* main_frame = web_contents->GetMainFrame();
325     int index = -1;
326     scoped_ptr<base::Value> value;
327     value = content::ExecuteScriptAndGetValue(main_frame, "get_current()");
328     if (!value->GetAsInteger(&index))
329       index = -1;
330     return index;
331   }
332
333   int ExecuteScriptAndExtractInt(const std::string& script) {
334     int value = 0;
335     EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
336         shell()->web_contents(),
337         "domAutomationController.send(" + script + ")",
338         &value));
339     return value;
340   }
341
342   RenderViewHost* GetRenderViewHost() const {
343     RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
344     CHECK(rvh);
345     return rvh;
346   }
347
348   RenderWidgetHostImpl* GetRenderWidgetHost() const {
349     RenderWidgetHostImpl* const rwh =
350         RenderWidgetHostImpl::From(shell()
351                                        ->web_contents()
352                                        ->GetRenderWidgetHostView()
353                                        ->GetRenderWidgetHost());
354     CHECK(rwh);
355     return rwh;
356   }
357
358   RenderWidgetHostViewBase* GetRenderWidgetHostView() const {
359     return static_cast<RenderWidgetHostViewBase*>(
360         GetRenderViewHost()->GetView());
361   }
362
363   InputEventMessageFilterWaitsForAcks* filter() {
364     return filter_.get();
365   }
366
367   void WaitAFrame() {
368     uint32 frame = GetRenderWidgetHostView()->RendererFrameNumber();
369     while (!GetRenderWidgetHost()->ScheduleComposite())
370       GiveItSomeTime();
371     while (GetRenderWidgetHostView()->RendererFrameNumber() == frame)
372       GiveItSomeTime();
373   }
374
375  protected:
376   ScreenshotTracker* screenshot_manager() { return screenshot_manager_; }
377   void set_min_screenshot_interval(int interval_ms) {
378     screenshot_manager_->SetScreenshotInterval(interval_ms);
379   }
380
381   void AddInputEventMessageFilter() {
382     filter_ = new InputEventMessageFilterWaitsForAcks();
383     GetRenderWidgetHost()->GetProcess()->AddFilter(filter_);
384   }
385
386  private:
387   ScreenshotTracker* screenshot_manager_;
388   scoped_refptr<InputEventMessageFilterWaitsForAcks> filter_;
389
390   DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
391 };
392
393 // Flaky on Windows: http://crbug.com/305722
394 #if defined(OS_WIN)
395 #define MAYBE_OverscrollNavigation DISABLED_OverscrollNavigation
396 #else
397 #define MAYBE_OverscrollNavigation OverscrollNavigation
398 #endif
399
400 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollNavigation) {
401   TestOverscrollNavigation(false);
402 }
403
404 // Flaky on Windows (might be related to the above test):
405 // http://crbug.com/305722
406 #if defined(OS_WIN)
407 #define MAYBE_OverscrollNavigationWithTouchHandler \
408         DISABLED_OverscrollNavigationWithTouchHandler
409 #else
410 #define MAYBE_OverscrollNavigationWithTouchHandler \
411         OverscrollNavigationWithTouchHandler
412 #endif
413 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
414                        MAYBE_OverscrollNavigationWithTouchHandler) {
415   TestOverscrollNavigation(true);
416 }
417
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).
420 #if defined(OS_WIN)
421 #define MAYBE_QuickOverscrollDirectionChange \
422         DISABLED_QuickOverscrollDirectionChange
423 #else
424 #define MAYBE_QuickOverscrollDirectionChange QuickOverscrollDirectionChange
425 #endif
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();
433
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);
438
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());
446
447   aura::Window* content = web_contents->GetContentNativeView();
448   ui::EventProcessor* dispatcher = content->GetHost()->event_processor();
449   gfx::Rect bounds = content->GetBoundsInRootWindow();
450
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),
454       0, timestamp);
455   ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
456   ASSERT_FALSE(details.dispatcher_destroyed);
457   EXPECT_EQ(1, GetCurrentIndex());
458
459   timestamp += base::TimeDelta::FromMilliseconds(10);
460   ui::TouchEvent move1(ui::ET_TOUCH_MOVED,
461       gfx::Point(bounds.right() - 10, bounds.y() + 5),
462       0, timestamp);
463   details = dispatcher->OnEventFromSource(&move1);
464   ASSERT_FALSE(details.dispatcher_destroyed);
465   EXPECT_EQ(1, GetCurrentIndex());
466
467   // Swipe back from the right edge, back to the left edge, back to the right
468   // edge.
469
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),
474         0, timestamp);
475     details = dispatcher->OnEventFromSource(&inc);
476     ASSERT_FALSE(details.dispatcher_destroyed);
477     EXPECT_EQ(1, GetCurrentIndex());
478   }
479
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),
484         0, timestamp);
485     details = dispatcher->OnEventFromSource(&inc);
486     ASSERT_FALSE(details.dispatcher_destroyed);
487     EXPECT_EQ(1, GetCurrentIndex());
488   }
489
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),
494         0, timestamp);
495     details = dispatcher->OnEventFromSource(&inc);
496     ASSERT_FALSE(details.dispatcher_destroyed);
497     EXPECT_EQ(1, GetCurrentIndex());
498   }
499
500   // Do not end the overscroll sequence.
501 }
502
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
507 //    gesture.
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
513 #else
514 #define MAYBE_OverscrollScreenshot OverscrollScreenshot
515 #endif
516 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) {
517   // Disable the test for WinXP.  See http://crbug/294116.
518 #if defined(OS_WIN)
519   if (base::win::GetVersion() < base::win::VERSION_VISTA) {
520     LOG(WARNING) << "Test disabled due to unknown bug on WinXP.";
521     return;
522   }
523 #endif
524
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();
530
531   set_min_screenshot_interval(0);
532
533   // Do a few navigations initiated by the page.
534   // Screenshots should never be captured since these are all in-page
535   // navigations.
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();
541
542   NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
543       web_contents->GetController().GetEntryAtIndex(2));
544   EXPECT_FALSE(entry->screenshot().get());
545
546   entry = NavigationEntryImpl::FromNavigationEntry(
547       web_contents->GetController().GetEntryAtIndex(1));
548   EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
549
550   entry = NavigationEntryImpl::FromNavigationEntry(
551       web_contents->GetController().GetEntryAtIndex(0));
552   EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
553
554   ExecuteSyncJSFunction(main_frame, "navigate_next()");
555   screenshot_manager()->WaitUntilScreenshotIsReady();
556
557   entry = NavigationEntryImpl::FromNavigationEntry(
558       web_contents->GetController().GetEntryAtIndex(2));
559   EXPECT_FALSE(screenshot_manager()->ScreenshotSetForEntry(entry));
560
561   entry = NavigationEntryImpl::FromNavigationEntry(
562       web_contents->GetController().GetEntryAtIndex(3));
563   EXPECT_FALSE(entry->screenshot().get());
564   {
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),
576         1);
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));
584   }
585
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());
595
596   {
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));
608   }
609 }
610
611 // Crashes under ThreadSanitizer, http://crbug.com/356758.
612 #if defined(THREAD_SANITIZER)
613 #define MAYBE_ScreenshotForSwappedOutRenderViews \
614     DISABLED_ScreenshotForSwappedOutRenderViews
615 #else
616 #define MAYBE_ScreenshotForSwappedOutRenderViews \
617     ScreenshotForSwappedOutRenderViews
618 #endif
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());
631
632   WebContentsImpl* web_contents =
633       static_cast<WebContentsImpl*>(shell()->web_contents());
634   set_min_screenshot_interval(0);
635
636   struct {
637     GURL url;
638     int transition;
639   } navigations[] = {
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 },
646     { GURL(), 0 }
647   };
648
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);
654
655     RenderViewHost* old_host = web_contents->GetRenderViewHost();
656     web_contents->GetController().LoadURLWithParams(params);
657     WaitForLoadStop(web_contents);
658     screenshot_manager()->WaitUntilScreenshotIsReady();
659
660     EXPECT_NE(old_host, web_contents->GetRenderViewHost())
661         << navigations[i].url.spec();
662     EXPECT_EQ(old_host, screenshot_manager()->screenshot_taken_for());
663
664     NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
665         web_contents->GetController().GetEntryAtOffset(-1));
666     EXPECT_TRUE(screenshot_manager()->ScreenshotSetForEntry(entry));
667
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();
673   }
674
675   // Increase the minimum interval between taking screenshots.
676   set_min_screenshot_interval(60000);
677
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();
685
686   EXPECT_EQ(NULL, screenshot_manager()->screenshot_taken_for());
687 }
688
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();
697
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());
720 }
721
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
728 //               better.
729 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
730                        DISABLED_ContentWindowReparent) {
731   ASSERT_NO_FATAL_FAILURE(
732       StartTestWithPage("files/overscroll_navigation.html"));
733
734   scoped_ptr<aura::Window> window(new aura::Window(NULL));
735   window->Init(aura::WINDOW_LAYER_NOT_DRAWN);
736
737   WebContentsImpl* web_contents =
738       static_cast<WebContentsImpl*>(shell()->web_contents());
739   ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
740   EXPECT_EQ(1, GetCurrentIndex());
741
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),
749       1);
750
751   window->AddChild(shell()->web_contents()->GetContentNativeView());
752 }
753
754 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) {
755   ASSERT_NO_FATAL_FAILURE(
756       StartTestWithPage("files/overscroll_navigation.html"));
757
758   WebContentsImpl* web_contents =
759       static_cast<WebContentsImpl*>(shell()->web_contents());
760   ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
761   EXPECT_EQ(1, GetCurrentIndex());
762
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),
770       1);
771
772   delete web_contents->GetContentNativeView();
773 }
774
775
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
782 #else
783 #define MAYBE_RepeatedQuickOverscrollGestures RepeatedQuickOverscrollGestures
784 #endif
785
786 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
787                        MAYBE_RepeatedQuickOverscrollGestures) {
788   ASSERT_NO_FATAL_FAILURE(
789       StartTestWithPage("files/overscroll_navigation.html"));
790
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()");
796
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());
803
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());
810
811   aura::Window* content = web_contents->GetContentNativeView();
812   gfx::Rect bounds = content->GetBoundsInRootWindow();
813   ui::test::EventGenerator generator(content->GetRootWindow(), content);
814
815   // Do a swipe left to start a forward navigation. Then quickly do a swipe
816   // right.
817   base::string16 expected_title = base::ASCIIToUTF16("Title: #2");
818   content::TitleWatcher title_watcher(web_contents, expected_title);
819   NavigationWatcher nav_watcher(web_contents);
820
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),
825       10);
826   nav_watcher.WaitUntilNavigationStarts();
827
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),
832       10);
833   base::string16 actual_title = title_watcher.WaitAndGetTitle();
834   EXPECT_EQ(expected_title, actual_title);
835
836   EXPECT_EQ(2, GetCurrentIndex());
837   EXPECT_TRUE(controller.CanGoBack());
838   EXPECT_FALSE(controller.CanGoForward());
839 }
840
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());
848   content->Hide();
849   EXPECT_FALSE(web_contents->should_normally_be_visible());
850   content->Show();
851   EXPECT_TRUE(web_contents->should_normally_be_visible());
852 }
853
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"));
859
860   scoped_ptr<aura::Window> window(new aura::Window(NULL));
861   window->Init(aura::WINDOW_LAYER_NOT_DRAWN);
862
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());
870 }
871
872 // Flaky on Windows, likely for the same reason as other flaky overscroll tests.
873 // http://crbug.com/305722
874 #if defined(OS_WIN)
875 #define MAYBE_OverscrollNavigationTouchThrottling \
876         DISABLED_OverscrollNavigationTouchThrottling
877 #else
878 #define MAYBE_OverscrollNavigationTouchThrottling \
879         OverscrollNavigationTouchThrottling
880 #endif
881
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"));
888
889   AddInputEventMessageFilter();
890
891   WebContentsImpl* web_contents =
892       static_cast<WebContentsImpl*>(shell()->web_contents());
893   aura::Window* content = web_contents->GetContentNativeView();
894   gfx::Rect bounds = content->GetBoundsInRootWindow();
895   const int dx = 20;
896
897   ExecuteSyncJSFunction(web_contents->GetMainFrame(),
898                         "install_touchmove_handler()");
899
900   WaitAFrame();
901
902   for (int navigated = 0; navigated <= 1; ++navigated) {
903     if (navigated) {
904       ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
905       ExecuteSyncJSFunction(web_contents->GetMainFrame(),
906                             "reset_touchmove_count()");
907     }
908     // Send touch press.
909     SyntheticWebTouchEvent touch;
910     touch.PressPoint(bounds.x() + 2, bounds.y() + 10);
911     GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
912                                                             ui::LatencyInfo());
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());
917
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,
921                                                             ui::LatencyInfo());
922     filter()->WaitForAck(blink::WebInputEvent::TouchMove);
923     ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
924
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.
930     //    GiveItSomeTime();
931     WaitAFrame();
932
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());
939       WaitAFrame();
940
941       blink::WebGestureEvent scroll_update =
942           SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, 5, 0);
943
944       GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
945           scroll_update, ui::LatencyInfo());
946
947       WaitAFrame();
948     }
949
950     touch.ReleasePoint(0);
951     GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
952                                                             ui::LatencyInfo());
953     WaitAFrame();
954
955     blink::WebGestureEvent scroll_end;
956     scroll_end.type = blink::WebInputEvent::GestureScrollEnd;
957     GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
958         scroll_end, ui::LatencyInfo());
959     WaitAFrame();
960
961     if (!navigated)
962       EXPECT_EQ(10, ExecuteScriptAndExtractInt("touchmoveCount"));
963     else
964       EXPECT_GT(10, ExecuteScriptAndExtractInt("touchmoveCount"));
965   }
966 }
967
968 }  // namespace content