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.
5 #include "content/public/test/render_widget_test.h"
7 #include "base/basictypes.h"
8 #include "base/file_util.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/ref_counted_memory.h"
11 #include "base/strings/stringprintf.h"
12 #include "content/common/view_messages.h"
13 #include "content/renderer/render_view_impl.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
16 #include "third_party/WebKit/public/platform/WebSize.h"
17 #include "third_party/WebKit/public/web/WebView.h"
18 #include "ui/gfx/codec/jpeg_codec.h"
19 #include "ui/gfx/size.h"
20 #include "ui/surface/transport_dib.h"
24 const int RenderWidgetTest::kNumBytesPerPixel
= 4;
25 const int RenderWidgetTest::kLargeWidth
= 1024;
26 const int RenderWidgetTest::kLargeHeight
= 768;
27 const int RenderWidgetTest::kSmallWidth
= 600;
28 const int RenderWidgetTest::kSmallHeight
= 450;
29 const int RenderWidgetTest::kTextPositionX
= 800;
30 const int RenderWidgetTest::kTextPositionY
= 600;
31 const uint32
RenderWidgetTest::kRedARGB
= 0xFFFF0000;
33 RenderWidgetTest::RenderWidgetTest() {}
35 void RenderWidgetTest::ResizeAndPaint(const gfx::Size
& page_size
,
36 const gfx::Size
& desired_size
,
38 ASSERT_TRUE(snapshot
);
39 static int g_sequence_num
= 0;
40 // Use a new sequence number for each DIB.
41 scoped_ptr
<TransportDIB
> pixels(
43 page_size
.width() * page_size
.height() * kNumBytesPerPixel
,
46 // Go ahead and map the DIB into memory, so that we can use it below to fill
47 // tmp_bitmap. Note that we need to do this before calling OnPaintAtSize, or
48 // the last reference to the shared memory will be closed and the handle will
49 // no longer be valid.
50 scoped_ptr
<TransportDIB
> mapped_pixels(TransportDIB::Map(pixels
->handle()));
52 RenderViewImpl
* impl
= static_cast<RenderViewImpl
*>(view_
);
53 impl
->OnPaintAtSize(pixels
->handle(), g_sequence_num
, page_size
,
55 ProcessPendingMessages();
56 const IPC::Message
* msg
= render_thread_
->sink().GetUniqueMessageMatching(
57 ViewHostMsg_PaintAtSize_ACK::ID
);
58 ASSERT_NE(static_cast<IPC::Message
*>(NULL
), msg
);
59 ViewHostMsg_PaintAtSize_ACK::Param params
;
60 ViewHostMsg_PaintAtSize_ACK::Read(msg
, ¶ms
);
61 render_thread_
->sink().ClearMessages();
62 EXPECT_EQ(g_sequence_num
, params
.a
);
63 gfx::Size size
= params
.b
;
64 EXPECT_EQ(desired_size
, size
);
67 tmp_bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
68 size
.width(), size
.height());
69 tmp_bitmap
.setPixels(mapped_pixels
->memory());
70 // Copy the pixels from the TransportDIB object to the given snapshot.
71 ASSERT_TRUE(tmp_bitmap
.copyTo(snapshot
, SkBitmap::kARGB_8888_Config
));
74 void RenderWidgetTest::TestResizeAndPaint() {
75 // Hello World message is only visible if the view size is at least
76 // kTextPositionX x kTextPositionY
77 LoadHTML(base::StringPrintf(
78 "<html><body><div style='position: absolute; top: %d; left: "
79 "%d; background-color: red;'>Hello World</div></body></html>",
80 kTextPositionY
, kTextPositionX
).c_str());
81 blink::WebSize old_size
= view_
->GetWebView()->size();
84 // If we re-size the view to something smaller than where the 'Hello World'
85 // text is displayed we won't see any text in the snapshot. Hence,
86 // the snapshot should not contain any red.
87 gfx::Size
size(kSmallWidth
, kSmallHeight
);
88 ResizeAndPaint(size
, size
, &bitmap
);
89 // Make sure that the view has been re-sized to its old size.
90 EXPECT_TRUE(old_size
== view_
->GetWebView()->size());
91 EXPECT_EQ(kSmallWidth
, bitmap
.width());
92 EXPECT_EQ(kSmallHeight
, bitmap
.height());
93 EXPECT_FALSE(ImageContainsColor(bitmap
, kRedARGB
));
95 // Since we ask for the view to be re-sized to something larger than where the
96 // 'Hello World' text is written the text should be visible in the snapshot.
97 // Hence, the snapshot should contain some red.
98 size
.SetSize(kLargeWidth
, kLargeHeight
);
99 ResizeAndPaint(size
, size
, &bitmap
);
100 EXPECT_TRUE(old_size
== view_
->GetWebView()->size());
101 EXPECT_EQ(kLargeWidth
, bitmap
.width());
102 EXPECT_EQ(kLargeHeight
, bitmap
.height());
103 EXPECT_TRUE(ImageContainsColor(bitmap
, kRedARGB
));
105 // Even if the desired size is smaller than where the text is located we
106 // should still see the 'Hello World' message since the view size is
107 // still large enough.
108 ResizeAndPaint(size
, gfx::Size(kSmallWidth
, kSmallHeight
), &bitmap
);
109 EXPECT_TRUE(old_size
== view_
->GetWebView()->size());
110 EXPECT_EQ(kSmallWidth
, bitmap
.width());
111 EXPECT_EQ(kSmallHeight
, bitmap
.height());
112 EXPECT_TRUE(ImageContainsColor(bitmap
, kRedARGB
));
115 bool RenderWidgetTest::ImageContainsColor(const SkBitmap
& bitmap
,
117 SkAutoLockPixels
lock(bitmap
);
118 bool ready
= bitmap
.readyToDraw();
123 for (int x
= 0; x
< bitmap
.width(); ++x
) {
124 for (int y
= 0; y
< bitmap
.height(); ++y
) {
125 if (argb_color
== *bitmap
.getAddr32(x
, y
)) {
133 void RenderWidgetTest::OutputBitmapToFile(const SkBitmap
& bitmap
,
134 const base::FilePath
& file_path
) {
135 scoped_refptr
<base::RefCountedBytes
> bitmap_data(new base::RefCountedBytes());
136 SkAutoLockPixels
lock(bitmap
);
137 ASSERT_TRUE(gfx::JPEGCodec::Encode(
138 reinterpret_cast<unsigned char*>(bitmap
.getAddr32(0, 0)),
139 gfx::JPEGCodec::FORMAT_BGRA
,
142 static_cast<int>(bitmap
.rowBytes()),
144 &bitmap_data
->data()));
145 ASSERT_LT(0, file_util::WriteFile(
147 reinterpret_cast<const char*>(bitmap_data
->front()),
148 bitmap_data
->size()));
151 void RenderWidgetTest::TestOnResize() {
152 RenderWidget
* widget
= static_cast<RenderViewImpl
*>(view_
);
154 // The initial bounds is empty, so setting it to the same thing should do
156 ViewMsg_Resize_Params resize_params
;
157 resize_params
.screen_info
= blink::WebScreenInfo();
158 resize_params
.new_size
= gfx::Size();
159 resize_params
.physical_backing_size
= gfx::Size();
160 resize_params
.overdraw_bottom_height
= 0.f
;
161 resize_params
.resizer_rect
= gfx::Rect();
162 resize_params
.is_fullscreen
= false;
163 widget
->OnResize(resize_params
);
164 EXPECT_FALSE(widget
->next_paint_is_resize_ack());
166 // Setting empty physical backing size should not send the ack.
167 resize_params
.new_size
= gfx::Size(10, 10);
168 widget
->OnResize(resize_params
);
169 EXPECT_FALSE(widget
->next_paint_is_resize_ack());
171 // Setting the bounds to a "real" rect should send the ack.
172 render_thread_
->sink().ClearMessages();
173 gfx::Size
size(100, 100);
174 resize_params
.new_size
= size
;
175 resize_params
.physical_backing_size
= size
;
176 widget
->OnResize(resize_params
);
177 EXPECT_TRUE(widget
->next_paint_is_resize_ack());
178 widget
->DoDeferredUpdate();
179 ProcessPendingMessages();
181 const ViewHostMsg_UpdateRect
* msg
=
182 static_cast<const ViewHostMsg_UpdateRect
*>(
183 render_thread_
->sink().GetUniqueMessageMatching(
184 ViewHostMsg_UpdateRect::ID
));
186 ViewHostMsg_UpdateRect::Schema::Param update_rect_params
;
187 EXPECT_TRUE(ViewHostMsg_UpdateRect::Read(msg
, &update_rect_params
));
188 EXPECT_TRUE(ViewHostMsg_UpdateRect_Flags::is_resize_ack(
189 update_rect_params
.a
.flags
));
191 update_rect_params
.a
.view_size
);
192 render_thread_
->sink().ClearMessages();
194 // Setting the same size again should not send the ack.
195 widget
->OnResize(resize_params
);
196 EXPECT_FALSE(widget
->next_paint_is_resize_ack());
198 // Resetting the rect to empty should not send the ack.
199 resize_params
.new_size
= gfx::Size();
200 resize_params
.physical_backing_size
= gfx::Size();
201 widget
->OnResize(resize_params
);
202 EXPECT_FALSE(widget
->next_paint_is_resize_ack());
205 } // namespace content