overscroll_navigation_overlay_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/common/view_messages.h"
10#include "content/public/browser/web_contents_view.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
17namespace content {
18
19class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
20 public:
21  OverscrollNavigationOverlayTest() {}
22  virtual ~OverscrollNavigationOverlayTest() {}
23
24  gfx::Image CreateDummyScreenshot() {
25    SkBitmap bitmap;
26    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
27    bitmap.allocPixels();
28    bitmap.eraseColor(SK_ColorWHITE);
29    return gfx::Image::CreateFrom1xBitmap(bitmap);
30  }
31
32  void SetDummyScreenshotOnNavEntry(NavigationEntry* entry) {
33    const unsigned char* raw_data =
34        reinterpret_cast<const unsigned char*>("garbage");
35    const int length = 5;
36    std::vector<unsigned char> data_vector(raw_data, raw_data+length);
37    scoped_refptr<base::RefCountedBytes> png_bytes =
38        base::RefCountedBytes::TakeVector(&data_vector);
39    NavigationEntryImpl* entry_impl =
40        NavigationEntryImpl::FromNavigationEntry(entry);
41    entry_impl->SetScreenshotPNGData(png_bytes);
42  }
43
44  void ReceivePaintUpdate() {
45    ViewHostMsg_DidFirstVisuallyNonEmptyPaint msg(
46        test_rvh()->GetRoutingID(), 0);
47    RenderViewHostTester::TestOnMessageReceived(test_rvh(), msg);
48  }
49
50  void PerformBackNavigationViaSliderCallbacks() {
51    // Sets slide direction to SLIDE_BACK, sets screenshot from NavEntry at
52    // offset -1  on layer_delegate_.
53    delete GetOverlay()->CreateBackLayer();
54    // Performs BACK navigation, sets image from layer_delegate_ on
55    // image_delegate_.
56    GetOverlay()->OnWindowSlideComplete();
57  }
58
59 protected:
60  // RenderViewHostImplTestHarness:
61  virtual void SetUp() OVERRIDE {
62    RenderViewHostImplTestHarness::SetUp();
63
64    const GURL first("https://www.google.com");
65    contents()->NavigateAndCommit(first);
66    EXPECT_TRUE(controller().GetVisibleEntry());
67    EXPECT_FALSE(controller().CanGoBack());
68
69    const GURL second("http://www.chromium.org");
70    contents()->NavigateAndCommit(second);
71    EXPECT_TRUE(controller().CanGoBack());
72
73    // Turn on compositing.
74    ViewHostMsg_DidActivateAcceleratedCompositing msg(
75        test_rvh()->GetRoutingID(), true);
76    RenderViewHostTester::TestOnMessageReceived(test_rvh(), msg);
77
78    // Receive a paint update. This is necessary to make sure the size is set
79    // correctly in RenderWidgetHostImpl.
80    ViewHostMsg_UpdateRect_Params params;
81    memset(&params, 0, sizeof(params));
82    params.view_size = gfx::Size(10, 10);
83    params.bitmap_rect = gfx::Rect(params.view_size);
84    params.scroll_rect = gfx::Rect();
85    params.needs_ack = false;
86    ViewHostMsg_UpdateRect rect(test_rvh()->GetRoutingID(), params);
87    RenderViewHostTester::TestOnMessageReceived(test_rvh(), rect);
88
89    // Reset pending flags for size/paint.
90    test_rvh()->ResetSizeAndRepaintPendingFlags();
91
92    // Create the overlay, and set the contents of the overlay window.
93    overlay_.reset(new OverscrollNavigationOverlay(contents()));
94    ImageWindowDelegate* image_delegate = new ImageWindowDelegate();
95    scoped_ptr<aura::Window> overlay_window(
96      aura::test::CreateTestWindowWithDelegate(
97          image_delegate,
98          0,
99          gfx::Rect(root_window()->bounds().size()),
100          root_window()));
101
102    overlay_->SetOverlayWindow(overlay_window.Pass(), image_delegate);
103    overlay_->StartObserving();
104
105    EXPECT_TRUE(overlay_->web_contents());
106    EXPECT_FALSE(overlay_->loading_complete_);
107    EXPECT_FALSE(overlay_->received_paint_update_);
108  }
109
110  virtual void TearDown() OVERRIDE {
111    overlay_.reset();
112    RenderViewHostImplTestHarness::TearDown();
113  }
114
115  OverscrollNavigationOverlay* GetOverlay() {
116    return overlay_.get();
117  }
118
119 private:
120  scoped_ptr<OverscrollNavigationOverlay> overlay_;
121
122  DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlayTest);
123};
124
125TEST_F(OverscrollNavigationOverlayTest, FirstVisuallyNonEmptyPaint_NoImage) {
126  ReceivePaintUpdate();
127  EXPECT_TRUE(GetOverlay()->received_paint_update_);
128  EXPECT_FALSE(GetOverlay()->loading_complete_);
129
130  // The paint update will hide the overlay, although the page hasn't completely
131  // loaded yet. This is because the image-delegate doesn't have an image set.
132  EXPECT_FALSE(GetOverlay()->web_contents());
133}
134
135TEST_F(OverscrollNavigationOverlayTest, FirstVisuallyNonEmptyPaint_WithImage) {
136  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
137
138  ReceivePaintUpdate();
139  EXPECT_TRUE(GetOverlay()->received_paint_update_);
140  EXPECT_FALSE(GetOverlay()->loading_complete_);
141  EXPECT_TRUE(GetOverlay()->web_contents());
142
143  contents()->TestSetIsLoading(false);
144  EXPECT_TRUE(GetOverlay()->loading_complete_);
145  EXPECT_FALSE(GetOverlay()->web_contents());
146}
147
148TEST_F(OverscrollNavigationOverlayTest, PaintUpdateWithoutNonEmptyPaint) {
149  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
150  process()->sink().ClearMessages();
151
152  // The page load is complete, but the overlay should still be visible, because
153  // there hasn't been any paint update.
154  // This should also send a repaint request to the renderer, so that the
155  // renderer repaints the contents.
156  contents()->TestSetIsLoading(false);
157  EXPECT_FALSE(GetOverlay()->received_paint_update_);
158  EXPECT_TRUE(GetOverlay()->loading_complete_);
159  EXPECT_TRUE(GetOverlay()->web_contents());
160  EXPECT_TRUE(process()->sink().GetFirstMessageMatching(ViewMsg_Repaint::ID));
161
162  // Receive a repaint ack update. This should hide the overlay.
163  ViewHostMsg_UpdateRect_Params params;
164  memset(&params, 0, sizeof(params));
165  params.view_size = gfx::Size(10, 10);
166  params.bitmap_rect = gfx::Rect(params.view_size);
167  params.scroll_rect = gfx::Rect();
168  params.needs_ack = false;
169  params.flags = ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK;
170  ViewHostMsg_UpdateRect rect(test_rvh()->GetRoutingID(), params);
171  RenderViewHostTester::TestOnMessageReceived(test_rvh(), rect);
172  EXPECT_TRUE(GetOverlay()->received_paint_update_);
173  EXPECT_FALSE(GetOverlay()->web_contents());
174}
175
176TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_PaintUpdate) {
177  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
178  SetDummyScreenshotOnNavEntry(controller().GetEntryAtOffset(-1));
179
180  ReceivePaintUpdate();
181  EXPECT_TRUE(GetOverlay()->received_paint_update_);
182
183  PerformBackNavigationViaSliderCallbacks();
184  // Screenshot was set on NavEntry at offset -1.
185  EXPECT_TRUE(GetOverlay()->image_delegate_->has_image());
186  // Navigation was started, so the paint update flag should be reset.
187  EXPECT_FALSE(GetOverlay()->received_paint_update_);
188
189  ReceivePaintUpdate();
190  // Paint updates until the navigation is committed represent updates
191  // for the previous page, so they shouldn't affect the flag.
192  EXPECT_FALSE(GetOverlay()->received_paint_update_);
193
194  contents()->CommitPendingNavigation();
195  ReceivePaintUpdate();
196  // Navigation was committed and the paint update was received - the flag
197  // should now be updated.
198  EXPECT_TRUE(GetOverlay()->received_paint_update_);
199
200  EXPECT_TRUE(GetOverlay()->web_contents());
201  contents()->TestSetIsLoading(true);
202  contents()->TestSetIsLoading(false);
203  EXPECT_FALSE(GetOverlay()->web_contents());
204}
205
206TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_LoadingUpdate) {
207  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
208
209  contents()->TestSetIsLoading(false);
210  EXPECT_TRUE(GetOverlay()->loading_complete_);
211
212  PerformBackNavigationViaSliderCallbacks();
213  // No screenshot was set on NavEntry at offset -1.
214  EXPECT_FALSE(GetOverlay()->image_delegate_->has_image());
215  // Navigation was started, so the loading status flag should be reset.
216  EXPECT_FALSE(GetOverlay()->loading_complete_);
217
218  // Load updates until the navigation is committed represent updates for the
219  //  previous page, so they shouldn't affect the flag.
220  contents()->TestSetIsLoading(true);
221  contents()->TestSetIsLoading(false);
222  EXPECT_FALSE(GetOverlay()->loading_complete_);
223
224  contents()->CommitPendingNavigation();
225  contents()->TestSetIsLoading(true);
226  contents()->TestSetIsLoading(false);
227  // Navigation was committed and the load update was received - the flag
228  // should now be updated.
229  EXPECT_TRUE(GetOverlay()->loading_complete_);
230
231  EXPECT_TRUE(GetOverlay()->web_contents());
232  ReceivePaintUpdate();
233  EXPECT_FALSE(GetOverlay()->web_contents());
234}
235
236}  // namespace content
237