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. 4 5 #include "content/browser/web_contents/aura/overscroll_navigation_overlay.h" 6 7 #include "content/browser/frame_host/navigation_entry_impl.h" 8 #include "content/browser/web_contents/aura/image_window_delegate.h" 9 #include "content/browser/web_contents/web_contents_view.h" 10 #include "content/common/view_messages.h" 11 #include "content/public/test/mock_render_process_host.h" 12 #include "content/test/test_render_view_host.h" 13 #include "content/test/test_web_contents.h" 14 #include "ui/aura/test/test_windows.h" 15 #include "ui/aura/window.h" 16 #include "ui/gfx/codec/png_codec.h" 17 18 namespace content { 19 20 class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness { 21 public: 22 OverscrollNavigationOverlayTest() {} 23 virtual ~OverscrollNavigationOverlayTest() {} 24 25 gfx::Image CreateDummyScreenshot() { 26 SkBitmap bitmap; 27 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); 28 bitmap.allocPixels(); 29 bitmap.eraseColor(SK_ColorWHITE); 30 return gfx::Image::CreateFrom1xBitmap(bitmap); 31 } 32 33 void SetDummyScreenshotOnNavEntry(NavigationEntry* entry) { 34 SkBitmap bitmap; 35 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); 36 bitmap.allocPixels(); 37 bitmap.eraseColor(SK_ColorWHITE); 38 std::vector<unsigned char> png_data; 39 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &png_data); 40 scoped_refptr<base::RefCountedBytes> png_bytes = 41 base::RefCountedBytes::TakeVector(&png_data); 42 NavigationEntryImpl* entry_impl = 43 NavigationEntryImpl::FromNavigationEntry(entry); 44 entry_impl->SetScreenshotPNGData(png_bytes); 45 } 46 47 void ReceivePaintUpdate() { 48 ViewHostMsg_DidFirstVisuallyNonEmptyPaint msg(test_rvh()->GetRoutingID()); 49 RenderViewHostTester::TestOnMessageReceived(test_rvh(), msg); 50 } 51 52 void PerformBackNavigationViaSliderCallbacks() { 53 // Sets slide direction to SLIDE_BACK, sets screenshot from NavEntry at 54 // offset -1 on layer_delegate_. 55 delete GetOverlay()->CreateBackLayer(); 56 // Performs BACK navigation, sets image from layer_delegate_ on 57 // image_delegate_. 58 GetOverlay()->OnWindowSlideCompleting(); 59 GetOverlay()->OnWindowSlideCompleted(scoped_ptr<ui::Layer>()); 60 } 61 62 protected: 63 // RenderViewHostImplTestHarness: 64 virtual void SetUp() OVERRIDE { 65 RenderViewHostImplTestHarness::SetUp(); 66 67 const GURL first("https://www.google.com"); 68 contents()->NavigateAndCommit(first); 69 EXPECT_TRUE(controller().GetVisibleEntry()); 70 EXPECT_FALSE(controller().CanGoBack()); 71 72 const GURL second("http://www.chromium.org"); 73 contents()->NavigateAndCommit(second); 74 EXPECT_TRUE(controller().CanGoBack()); 75 76 // Receive a paint update. This is necessary to make sure the size is set 77 // correctly in RenderWidgetHostImpl. 78 ViewHostMsg_UpdateRect_Params params; 79 memset(¶ms, 0, sizeof(params)); 80 params.view_size = gfx::Size(10, 10); 81 ViewHostMsg_UpdateRect rect(test_rvh()->GetRoutingID(), params); 82 RenderViewHostTester::TestOnMessageReceived(test_rvh(), rect); 83 84 // Reset pending flags for size/paint. 85 test_rvh()->ResetSizeAndRepaintPendingFlags(); 86 87 // Create the overlay, and set the contents of the overlay window. 88 overlay_.reset(new OverscrollNavigationOverlay(contents())); 89 ImageWindowDelegate* image_delegate = new ImageWindowDelegate(); 90 scoped_ptr<aura::Window> overlay_window( 91 aura::test::CreateTestWindowWithDelegate( 92 image_delegate, 93 0, 94 gfx::Rect(root_window()->bounds().size()), 95 root_window())); 96 97 overlay_->SetOverlayWindow(overlay_window.Pass(), image_delegate); 98 overlay_->StartObserving(); 99 100 EXPECT_TRUE(overlay_->web_contents()); 101 EXPECT_FALSE(overlay_->loading_complete_); 102 EXPECT_FALSE(overlay_->received_paint_update_); 103 } 104 105 virtual void TearDown() OVERRIDE { 106 overlay_.reset(); 107 RenderViewHostImplTestHarness::TearDown(); 108 } 109 110 OverscrollNavigationOverlay* GetOverlay() { 111 return overlay_.get(); 112 } 113 114 private: 115 scoped_ptr<OverscrollNavigationOverlay> overlay_; 116 117 DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlayTest); 118 }; 119 120 TEST_F(OverscrollNavigationOverlayTest, FirstVisuallyNonEmptyPaint_NoImage) { 121 ReceivePaintUpdate(); 122 EXPECT_TRUE(GetOverlay()->received_paint_update_); 123 EXPECT_FALSE(GetOverlay()->loading_complete_); 124 // The paint update will hide the overlay. 125 EXPECT_FALSE(GetOverlay()->web_contents()); 126 } 127 128 TEST_F(OverscrollNavigationOverlayTest, FirstVisuallyNonEmptyPaint_WithImage) { 129 GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot()); 130 131 ReceivePaintUpdate(); 132 EXPECT_TRUE(GetOverlay()->received_paint_update_); 133 EXPECT_FALSE(GetOverlay()->loading_complete_); 134 // The paint update will hide the overlay. 135 EXPECT_FALSE(GetOverlay()->web_contents()); 136 } 137 138 TEST_F(OverscrollNavigationOverlayTest, LoadUpdateWithoutNonEmptyPaint) { 139 GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot()); 140 process()->sink().ClearMessages(); 141 142 contents()->TestSetIsLoading(false); 143 EXPECT_TRUE(GetOverlay()->loading_complete_); 144 EXPECT_FALSE(GetOverlay()->received_paint_update_); 145 // The page load should hide the overlay. 146 EXPECT_FALSE(GetOverlay()->web_contents()); 147 } 148 149 TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_PaintUpdate) { 150 GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot()); 151 SetDummyScreenshotOnNavEntry(controller().GetEntryAtOffset(-1)); 152 153 PerformBackNavigationViaSliderCallbacks(); 154 // Screenshot was set on NavEntry at offset -1. 155 EXPECT_TRUE(GetOverlay()->image_delegate_->has_image()); 156 EXPECT_FALSE(GetOverlay()->received_paint_update_); 157 158 ReceivePaintUpdate(); 159 // Paint updates until the navigation is committed represent updates 160 // for the previous page, so they shouldn't affect the flag. 161 EXPECT_FALSE(GetOverlay()->received_paint_update_); 162 163 contents()->CommitPendingNavigation(); 164 ReceivePaintUpdate(); 165 // Navigation was committed and the paint update was received - the flag 166 // should now be updated. 167 EXPECT_TRUE(GetOverlay()->received_paint_update_); 168 169 EXPECT_FALSE(GetOverlay()->web_contents()); 170 } 171 172 TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_LoadingUpdate) { 173 GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot()); 174 175 PerformBackNavigationViaSliderCallbacks(); 176 // No screenshot was set on NavEntry at offset -1. 177 EXPECT_FALSE(GetOverlay()->image_delegate_->has_image()); 178 // Navigation was started, so the loading status flag should be reset. 179 EXPECT_FALSE(GetOverlay()->loading_complete_); 180 181 // Load updates until the navigation is committed represent updates for the 182 // previous page, so they shouldn't affect the flag. 183 contents()->TestSetIsLoading(true); 184 contents()->TestSetIsLoading(false); 185 EXPECT_FALSE(GetOverlay()->loading_complete_); 186 187 contents()->CommitPendingNavigation(); 188 contents()->TestSetIsLoading(true); 189 contents()->TestSetIsLoading(false); 190 // Navigation was committed and the load update was received - the flag 191 // should now be updated. 192 EXPECT_TRUE(GetOverlay()->loading_complete_); 193 194 EXPECT_FALSE(GetOverlay()->web_contents()); 195 } 196 197 } // namespace content 198