overscroll_navigation_overlay_unittest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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()->OnWindowSlideCompleting();
57    GetOverlay()->OnWindowSlideCompleted();
58  }
59
60 protected:
61  // RenderViewHostImplTestHarness:
62  virtual void SetUp() OVERRIDE {
63    RenderViewHostImplTestHarness::SetUp();
64
65    const GURL first("https://www.google.com");
66    contents()->NavigateAndCommit(first);
67    EXPECT_TRUE(controller().GetVisibleEntry());
68    EXPECT_FALSE(controller().CanGoBack());
69
70    const GURL second("http://www.chromium.org");
71    contents()->NavigateAndCommit(second);
72    EXPECT_TRUE(controller().CanGoBack());
73
74    // Turn on compositing.
75    ViewHostMsg_DidActivateAcceleratedCompositing msg(
76        test_rvh()->GetRoutingID(), true);
77    RenderViewHostTester::TestOnMessageReceived(test_rvh(), msg);
78
79    // Receive a paint update. This is necessary to make sure the size is set
80    // correctly in RenderWidgetHostImpl.
81    ViewHostMsg_UpdateRect_Params params;
82    memset(&params, 0, sizeof(params));
83    params.view_size = gfx::Size(10, 10);
84    params.bitmap_rect = gfx::Rect(params.view_size);
85    params.scroll_rect = gfx::Rect();
86    params.needs_ack = false;
87    ViewHostMsg_UpdateRect rect(test_rvh()->GetRoutingID(), params);
88    RenderViewHostTester::TestOnMessageReceived(test_rvh(), rect);
89
90    // Reset pending flags for size/paint.
91    test_rvh()->ResetSizeAndRepaintPendingFlags();
92
93    // Create the overlay, and set the contents of the overlay window.
94    overlay_.reset(new OverscrollNavigationOverlay(contents()));
95    ImageWindowDelegate* image_delegate = new ImageWindowDelegate();
96    scoped_ptr<aura::Window> overlay_window(
97      aura::test::CreateTestWindowWithDelegate(
98          image_delegate,
99          0,
100          gfx::Rect(root_window()->bounds().size()),
101          root_window()));
102
103    overlay_->SetOverlayWindow(overlay_window.Pass(), image_delegate);
104    overlay_->StartObserving();
105
106    EXPECT_TRUE(overlay_->web_contents());
107    EXPECT_FALSE(overlay_->loading_complete_);
108    EXPECT_FALSE(overlay_->received_paint_update_);
109  }
110
111  virtual void TearDown() OVERRIDE {
112    overlay_.reset();
113    RenderViewHostImplTestHarness::TearDown();
114  }
115
116  OverscrollNavigationOverlay* GetOverlay() {
117    return overlay_.get();
118  }
119
120 private:
121  scoped_ptr<OverscrollNavigationOverlay> overlay_;
122
123  DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlayTest);
124};
125
126TEST_F(OverscrollNavigationOverlayTest, FirstVisuallyNonEmptyPaint_NoImage) {
127  ReceivePaintUpdate();
128  EXPECT_TRUE(GetOverlay()->received_paint_update_);
129  EXPECT_FALSE(GetOverlay()->loading_complete_);
130
131  // The paint update will hide the overlay, although the page hasn't completely
132  // loaded yet. This is because the image-delegate doesn't have an image set.
133  EXPECT_FALSE(GetOverlay()->web_contents());
134}
135
136TEST_F(OverscrollNavigationOverlayTest, FirstVisuallyNonEmptyPaint_WithImage) {
137  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
138
139  ReceivePaintUpdate();
140  EXPECT_TRUE(GetOverlay()->received_paint_update_);
141  EXPECT_FALSE(GetOverlay()->loading_complete_);
142  EXPECT_TRUE(GetOverlay()->web_contents());
143
144  contents()->TestSetIsLoading(false);
145  EXPECT_TRUE(GetOverlay()->loading_complete_);
146  EXPECT_FALSE(GetOverlay()->web_contents());
147}
148
149TEST_F(OverscrollNavigationOverlayTest, PaintUpdateWithoutNonEmptyPaint) {
150  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
151  process()->sink().ClearMessages();
152
153  // The page load is complete, but the overlay should still be visible, because
154  // there hasn't been any paint update.
155  // This should also send a repaint request to the renderer, so that the
156  // renderer repaints the contents.
157  contents()->TestSetIsLoading(false);
158  EXPECT_FALSE(GetOverlay()->received_paint_update_);
159  EXPECT_TRUE(GetOverlay()->loading_complete_);
160  EXPECT_TRUE(GetOverlay()->web_contents());
161  EXPECT_TRUE(process()->sink().GetFirstMessageMatching(ViewMsg_Repaint::ID));
162
163  // Receive a repaint ack update. This should hide the overlay.
164  ViewHostMsg_UpdateRect_Params params;
165  memset(&params, 0, sizeof(params));
166  params.view_size = gfx::Size(10, 10);
167  params.bitmap_rect = gfx::Rect(params.view_size);
168  params.scroll_rect = gfx::Rect();
169  params.needs_ack = false;
170  params.flags = ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK;
171  ViewHostMsg_UpdateRect rect(test_rvh()->GetRoutingID(), params);
172  RenderViewHostTester::TestOnMessageReceived(test_rvh(), rect);
173  EXPECT_TRUE(GetOverlay()->received_paint_update_);
174  EXPECT_FALSE(GetOverlay()->web_contents());
175}
176
177TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_PaintUpdate) {
178  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
179  SetDummyScreenshotOnNavEntry(controller().GetEntryAtOffset(-1));
180
181  ReceivePaintUpdate();
182  EXPECT_TRUE(GetOverlay()->received_paint_update_);
183
184  PerformBackNavigationViaSliderCallbacks();
185  // Screenshot was set on NavEntry at offset -1.
186  EXPECT_TRUE(GetOverlay()->image_delegate_->has_image());
187  // Navigation was started, so the paint update flag should be reset.
188  EXPECT_FALSE(GetOverlay()->received_paint_update_);
189
190  ReceivePaintUpdate();
191  // Paint updates until the navigation is committed represent updates
192  // for the previous page, so they shouldn't affect the flag.
193  EXPECT_FALSE(GetOverlay()->received_paint_update_);
194
195  contents()->CommitPendingNavigation();
196  ReceivePaintUpdate();
197  // Navigation was committed and the paint update was received - the flag
198  // should now be updated.
199  EXPECT_TRUE(GetOverlay()->received_paint_update_);
200
201  EXPECT_TRUE(GetOverlay()->web_contents());
202  contents()->TestSetIsLoading(true);
203  contents()->TestSetIsLoading(false);
204  EXPECT_FALSE(GetOverlay()->web_contents());
205}
206
207TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_LoadingUpdate) {
208  GetOverlay()->image_delegate_->SetImage(CreateDummyScreenshot());
209
210  contents()->TestSetIsLoading(false);
211  EXPECT_TRUE(GetOverlay()->loading_complete_);
212
213  PerformBackNavigationViaSliderCallbacks();
214  // No screenshot was set on NavEntry at offset -1.
215  EXPECT_FALSE(GetOverlay()->image_delegate_->has_image());
216  // Navigation was started, so the loading status flag should be reset.
217  EXPECT_FALSE(GetOverlay()->loading_complete_);
218
219  // Load updates until the navigation is committed represent updates for the
220  //  previous page, so they shouldn't affect the flag.
221  contents()->TestSetIsLoading(true);
222  contents()->TestSetIsLoading(false);
223  EXPECT_FALSE(GetOverlay()->loading_complete_);
224
225  contents()->CommitPendingNavigation();
226  contents()->TestSetIsLoading(true);
227  contents()->TestSetIsLoading(false);
228  // Navigation was committed and the load update was received - the flag
229  // should now be updated.
230  EXPECT_TRUE(GetOverlay()->loading_complete_);
231
232  EXPECT_TRUE(GetOverlay()->web_contents());
233  ReceivePaintUpdate();
234  EXPECT_FALSE(GetOverlay()->web_contents());
235}
236
237}  // namespace content
238