[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / web_contents / aura / overscroll_navigation_overlay_unittest.cc
blob841332a6ce44b0b79d8e5e899303ac030d6596ad
1 // Copyright 2014 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/aura/overscroll_navigation_overlay.h"
7 #include <vector>
8 #include "base/command_line.h"
9 #include "content/browser/frame_host/navigation_entry_impl.h"
10 #include "content/browser/web_contents/web_contents_view.h"
11 #include "content/common/frame_messages.h"
12 #include "content/common/view_messages.h"
13 #include "content/public/browser/overscroll_configuration.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/test/mock_render_process_host.h"
16 #include "content/test/test_render_frame_host.h"
17 #include "content/test/test_render_view_host.h"
18 #include "content/test/test_web_contents.h"
19 #include "ui/aura/test/test_windows.h"
20 #include "ui/aura/window.h"
21 #include "ui/aura_extra/image_window_delegate.h"
22 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
23 #include "ui/compositor/scoped_layer_animation_settings.h"
24 #include "ui/compositor/test/layer_animator_test_controller.h"
25 #include "ui/events/gesture_detection/gesture_configuration.h"
26 #include "ui/events/test/event_generator.h"
27 #include "ui/gfx/codec/png_codec.h"
29 namespace content {
31 // A subclass of TestWebContents that offers a fake content window.
32 class OverscrollTestWebContents : public TestWebContents {
33 public:
34 ~OverscrollTestWebContents() override {}
36 static OverscrollTestWebContents* Create(
37 BrowserContext* browser_context,
38 SiteInstance* instance,
39 scoped_ptr<aura::Window> fake_native_view,
40 scoped_ptr<aura::Window> fake_contents_window) {
41 OverscrollTestWebContents* web_contents = new OverscrollTestWebContents(
42 browser_context, fake_native_view.Pass(), fake_contents_window.Pass());
43 web_contents->Init(WebContents::CreateParams(browser_context, instance));
44 return web_contents;
47 void ResetNativeView() { fake_native_view_.reset(); }
49 void ResetContentNativeView() { fake_contents_window_.reset(); }
51 void set_is_being_destroyed(bool val) { is_being_destroyed_ = val; }
53 gfx::NativeView GetNativeView() override { return fake_native_view_.get(); }
55 gfx::NativeView GetContentNativeView() override {
56 return fake_contents_window_.get();
59 bool IsBeingDestroyed() const override { return is_being_destroyed_; }
61 protected:
62 explicit OverscrollTestWebContents(
63 BrowserContext* browser_context,
64 scoped_ptr<aura::Window> fake_native_view,
65 scoped_ptr<aura::Window> fake_contents_window)
66 : TestWebContents(browser_context),
67 fake_native_view_(fake_native_view.Pass()),
68 fake_contents_window_(fake_contents_window.Pass()),
69 is_being_destroyed_(false) {}
71 private:
72 scoped_ptr<aura::Window> fake_native_view_;
73 scoped_ptr<aura::Window> fake_contents_window_;
74 bool is_being_destroyed_;
77 class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
78 public:
79 OverscrollNavigationOverlayTest()
80 : first_("https://www.google.com"),
81 second_("http://www.chromium.org"),
82 third_("https://www.kernel.org/"),
83 fourth_("https://github.com/") {}
85 ~OverscrollNavigationOverlayTest() override {}
87 void SetDummyScreenshotOnNavEntry(NavigationEntry* entry) {
88 SkBitmap bitmap;
89 bitmap.allocN32Pixels(1, 1);
90 bitmap.eraseColor(SK_ColorWHITE);
91 std::vector<unsigned char> png_data;
92 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &png_data);
93 scoped_refptr<base::RefCountedBytes> png_bytes =
94 base::RefCountedBytes::TakeVector(&png_data);
95 NavigationEntryImpl* entry_impl =
96 NavigationEntryImpl::FromNavigationEntry(entry);
97 entry_impl->SetScreenshotPNGData(png_bytes);
100 void ReceivePaintUpdate() {
101 ViewHostMsg_DidFirstVisuallyNonEmptyPaint msg(
102 main_test_rfh()->GetRoutingID());
103 RenderViewHostTester::TestOnMessageReceived(test_rvh(), msg);
106 void PerformBackNavigationViaSliderCallbacks() {
107 // Sets slide direction to BACK, sets screenshot from NavEntry at
108 // offset -1 on layer_delegate_.
109 scoped_ptr<aura::Window> window(
110 GetOverlay()->CreateBackWindow(GetBackSlideWindowBounds()));
111 bool window_created = window;
112 // Performs BACK navigation, sets image from layer_delegate_ on
113 // image_delegate_.
114 GetOverlay()->OnOverscrollCompleting();
115 if (window_created)
116 EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
117 else
118 EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE);
119 window->SetBounds(gfx::Rect(root_window()->bounds().size()));
120 GetOverlay()->OnOverscrollCompleted(window.Pass());
121 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
122 switches::kEnableBrowserSideNavigation)) {
123 main_test_rfh()->PrepareForCommit();
124 } else {
125 contents()->GetPendingMainFrame()->PrepareForCommit();
127 if (window_created)
128 EXPECT_TRUE(contents()->CrossProcessNavigationPending());
129 else
130 EXPECT_FALSE(contents()->CrossProcessNavigationPending());
133 gfx::Rect GetFrontSlideWindowBounds() {
134 gfx::Rect bounds = gfx::Rect(root_window()->bounds().size());
135 bounds.Offset(root_window()->bounds().size().width(), 0);
136 return bounds;
139 gfx::Rect GetBackSlideWindowBounds() {
140 return gfx::Rect(root_window()->bounds().size());
143 // Const accessors.
144 const GURL first() { return first_; }
145 const GURL second() { return second_; }
146 const GURL third() { return third_; }
147 const GURL fourth() { return fourth_; }
149 protected:
150 // RenderViewHostImplTestHarness:
151 void SetUp() override {
152 RenderViewHostImplTestHarness::SetUp();
154 // Set up the fake web contents native view.
155 scoped_ptr<aura::Window> fake_native_view(new aura::Window(nullptr));
156 fake_native_view->Init(ui::LAYER_SOLID_COLOR);
157 root_window()->AddChild(fake_native_view.get());
158 fake_native_view->SetBounds(gfx::Rect(root_window()->bounds().size()));
160 // Set up the fake contents window.
161 scoped_ptr<aura::Window> fake_contents_window(new aura::Window(nullptr));
162 fake_contents_window->Init(ui::LAYER_SOLID_COLOR);
163 root_window()->AddChild(fake_contents_window.get());
164 fake_contents_window->SetBounds(gfx::Rect(root_window()->bounds().size()));
166 // Replace the default test web contents with our custom class.
167 SetContents(OverscrollTestWebContents::Create(
168 browser_context(),
169 SiteInstance::Create(browser_context()),
170 fake_native_view.Pass(),
171 fake_contents_window.Pass()));
173 contents()->NavigateAndCommit(first());
174 EXPECT_TRUE(controller().GetVisibleEntry());
175 EXPECT_FALSE(controller().CanGoBack());
177 contents()->NavigateAndCommit(second());
178 EXPECT_TRUE(controller().CanGoBack());
180 contents()->NavigateAndCommit(third());
181 EXPECT_TRUE(controller().CanGoBack());
183 contents()->NavigateAndCommit(fourth_);
184 EXPECT_TRUE(controller().CanGoBack());
185 EXPECT_FALSE(controller().CanGoForward());
187 // Receive a paint update. This is necessary to make sure the size is set
188 // correctly in RenderWidgetHostImpl.
189 ViewHostMsg_UpdateRect_Params params;
190 memset(&params, 0, sizeof(params));
191 params.view_size = gfx::Size(10, 10);
192 ViewHostMsg_UpdateRect rect(test_rvh()->GetRoutingID(), params);
193 RenderViewHostTester::TestOnMessageReceived(test_rvh(), rect);
195 // Reset pending flags for size/paint.
196 test_rvh()->ResetSizeAndRepaintPendingFlags();
198 // Create the overlay, and set the contents of the overlay window.
199 overlay_.reset(new OverscrollNavigationOverlay(contents(), root_window()));
202 void TearDown() override {
203 overlay_.reset();
204 RenderViewHostImplTestHarness::TearDown();
207 OverscrollNavigationOverlay* GetOverlay() {
208 return overlay_.get();
211 private:
212 // Tests URLs.
213 const GURL first_;
214 const GURL second_;
215 const GURL third_;
216 const GURL fourth_;
218 scoped_ptr<OverscrollNavigationOverlay> overlay_;
220 DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlayTest);
223 // Tests that if a screenshot is available, it is set in the overlay window
224 // delegate.
225 TEST_F(OverscrollNavigationOverlayTest, WithScreenshot) {
226 SetDummyScreenshotOnNavEntry(controller().GetEntryAtOffset(-1));
227 PerformBackNavigationViaSliderCallbacks();
228 // Screenshot was set on NavEntry at offset -1.
229 EXPECT_TRUE(static_cast<aura_extra::ImageWindowDelegate*>(
230 GetOverlay()->window_->delegate())->has_image());
233 // Tests that if a screenshot is not available, no image is set in the overlay
234 // window delegate.
235 TEST_F(OverscrollNavigationOverlayTest, WithoutScreenshot) {
236 PerformBackNavigationViaSliderCallbacks();
237 // No screenshot was set on NavEntry at offset -1.
238 EXPECT_FALSE(static_cast<aura_extra::ImageWindowDelegate*>(
239 GetOverlay()->window_->delegate())->has_image());
242 // Tests that if a navigation is attempted but there is nothing to navigate to,
243 // we return a null window.
244 TEST_F(OverscrollNavigationOverlayTest, CannotNavigate) {
245 EXPECT_EQ(GetOverlay()->CreateFrontWindow(GetFrontSlideWindowBounds()),
246 nullptr);
249 // Tests that if a navigation is cancelled, no navigation is performed and the
250 // state is restored.
251 TEST_F(OverscrollNavigationOverlayTest, CancelNavigation) {
252 scoped_ptr<aura::Window> window =
253 GetOverlay()->CreateBackWindow(GetBackSlideWindowBounds());
254 EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
256 GetOverlay()->OnOverscrollCancelled();
257 EXPECT_FALSE(contents()->CrossProcessNavigationPending());
258 EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE);
261 // Performs two navigations. The second navigation is cancelled, tests that the
262 // first one worked correctly.
263 TEST_F(OverscrollNavigationOverlayTest, CancelAfterSuccessfulNavigation) {
264 PerformBackNavigationViaSliderCallbacks();
265 scoped_ptr<aura::Window> wrapper =
266 GetOverlay()->CreateBackWindow(GetBackSlideWindowBounds());
267 EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
269 GetOverlay()->OnOverscrollCancelled();
270 EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE);
272 EXPECT_TRUE(contents()->CrossProcessNavigationPending());
273 NavigationEntry* pending = contents()->GetController().GetPendingEntry();
274 contents()->GetPendingMainFrame()->SendNavigate(
275 pending->GetPageID(), pending->GetUniqueID(), false, pending->GetURL());
276 EXPECT_EQ(contents()->GetURL(), third());
279 // Tests that an overscroll navigation that receives a paint update actually
280 // stops observing.
281 TEST_F(OverscrollNavigationOverlayTest, Navigation_PaintUpdate) {
282 PerformBackNavigationViaSliderCallbacks();
283 ReceivePaintUpdate();
285 // Paint updates until the navigation is committed typically represent updates
286 // for the previous page, so we should still be observing.
287 EXPECT_TRUE(GetOverlay()->web_contents());
289 NavigationEntry* pending = contents()->GetController().GetPendingEntry();
290 contents()->GetPendingMainFrame()->SendNavigate(
291 pending->GetPageID(), pending->GetUniqueID(), false, pending->GetURL());
292 ReceivePaintUpdate();
294 // Navigation was committed and the paint update was received - we should no
295 // longer be observing.
296 EXPECT_FALSE(GetOverlay()->web_contents());
297 EXPECT_EQ(contents()->GetURL(), third());
300 // Tests that an overscroll navigation that receives a loading update actually
301 // stops observing.
302 TEST_F(OverscrollNavigationOverlayTest, Navigation_LoadingUpdate) {
303 PerformBackNavigationViaSliderCallbacks();
304 EXPECT_TRUE(GetOverlay()->web_contents());
305 // DidStopLoading for any navigation should always reset the load flag and
306 // dismiss the overlay even if the pending navigation wasn't committed -
307 // this is a "safety net" in case we mis-identify the destination webpage
308 // (which can happen if a new navigation is performed while while a GestureNav
309 // navigation is in progress).
310 contents()->TestSetIsLoading(true);
311 contents()->TestSetIsLoading(false);
312 EXPECT_FALSE(GetOverlay()->web_contents());
313 NavigationEntry* pending = contents()->GetController().GetPendingEntry();
314 contents()->GetPendingMainFrame()->SendNavigate(
315 pending->GetPageID(), pending->GetUniqueID(), false, pending->GetURL());
316 EXPECT_EQ(contents()->GetURL(), third());
319 TEST_F(OverscrollNavigationOverlayTest, CloseDuringAnimation) {
320 ui::ScopedAnimationDurationScaleMode normal_duration_(
321 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
322 GetOverlay()->owa_->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST);
323 GetOverlay()->owa_->OnOverscrollComplete(OVERSCROLL_EAST);
324 EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::BACK);
325 OverscrollTestWebContents* test_web_contents =
326 static_cast<OverscrollTestWebContents*>(web_contents());
327 test_web_contents->set_is_being_destroyed(true);
328 test_web_contents->ResetContentNativeView();
329 test_web_contents->ResetNativeView();
330 // Ensure a clean close.
334 // Tests that swapping the overlay window at the end of a gesture caused by the
335 // start of a new overscroll does not crash and the events still reach the new
336 // overlay window.
337 TEST_F(OverscrollNavigationOverlayTest, OverlayWindowSwap) {
338 PerformBackNavigationViaSliderCallbacks();
339 aura::Window* first_overlay_window = GetOverlay()->window_.get();
340 EXPECT_TRUE(GetOverlay()->web_contents());
341 EXPECT_TRUE(first_overlay_window);
343 // At this stage, the overlay window is covering the web contents. Configure
344 // the animator of the overlay window for the test.
345 ui::ScopedAnimationDurationScaleMode normal_duration(
346 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
347 ui::LayerAnimator* animator = GetOverlay()->window_->layer()->GetAnimator();
348 animator->set_disable_timer_for_test(true);
349 ui::LayerAnimatorTestController test_controller(animator);
351 int overscroll_complete_distance =
352 root_window()->bounds().size().width() *
353 content::GetOverscrollConfig(
354 content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE) +
355 ui::GestureConfiguration::GetInstance()
356 ->max_touch_move_in_pixels_for_click() + 1;
358 // Start and complete a back navigation via a gesture.
359 ui::test::EventGenerator generator(root_window());
360 generator.GestureScrollSequence(gfx::Point(0, 0),
361 gfx::Point(overscroll_complete_distance, 0),
362 base::TimeDelta::FromMilliseconds(10),
363 10);
365 ui::ScopedLayerAnimationSettings settings(animator);
366 test_controller.StartThreadedAnimationsIfNeeded();
368 // The overlay window should now be being animated to the edge of the screen.
369 // |first()overlay_window| is the back window.
370 // This is what the screen should look like. The X indicates where the next
371 // gesture starts for the test.
372 // +---------root_window--------+
373 // |+-back window--+--front window--+
374 // || | | |
375 // || 1 |X 2 | |
376 // || | | |
377 // |+--------------+------------|---+
378 // +----------------------------+
379 // | overscroll ||
380 // | complete ||
381 // | distance ||
382 // |<------------->||
383 // | second |
384 // | overscroll |
385 // | start distance |
386 // |<-------------->|
387 EXPECT_EQ(GetOverlay()->window_.get(), first_overlay_window);
389 // The overlay window is halfway through, start another animation that will
390 // cancel the first one. The event that cancels the animation will go to
391 // the slide window, which will be used as the overlay window when the new
392 // overscroll starts.
393 int second_overscroll_start_distance = overscroll_complete_distance + 1;
394 generator.GestureScrollSequence(
395 gfx::Point(second_overscroll_start_distance, 0),
396 gfx::Point(
397 second_overscroll_start_distance + overscroll_complete_distance, 0),
398 base::TimeDelta::FromMilliseconds(10), 10);
399 EXPECT_TRUE(GetOverlay()->window_.get());
400 // The overlay window should be a new window.
401 EXPECT_NE(GetOverlay()->window_.get(), first_overlay_window);
403 // Complete the animation.
404 GetOverlay()->window_->layer()->GetAnimator()->StopAnimating();
405 EXPECT_TRUE(GetOverlay()->window_.get());
407 // Load the page.
408 contents()->CommitPendingNavigation();
409 ReceivePaintUpdate();
410 EXPECT_FALSE(GetOverlay()->window_.get());
411 EXPECT_EQ(contents()->GetURL(), first());
414 } // namespace content