render_widget_test.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.
4
5#include "content/public/test/render_widget_test.h"
6
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/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/Source/Platform/chromium/public/WebSize.h"
17#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
18#include "ui/gfx/codec/jpeg_codec.h"
19#include "ui/gfx/size.h"
20#include "ui/surface/transport_dib.h"
21
22namespace content {
23
24const int RenderWidgetTest::kNumBytesPerPixel = 4;
25const int RenderWidgetTest::kLargeWidth = 1024;
26const int RenderWidgetTest::kLargeHeight = 768;
27const int RenderWidgetTest::kSmallWidth = 600;
28const int RenderWidgetTest::kSmallHeight = 450;
29const int RenderWidgetTest::kTextPositionX = 800;
30const int RenderWidgetTest::kTextPositionY = 600;
31const uint32 RenderWidgetTest::kRedARGB = 0xFFFF0000;
32
33RenderWidgetTest::RenderWidgetTest() {}
34
35void RenderWidgetTest::ResizeAndPaint(const gfx::Size& page_size,
36                                      const gfx::Size& desired_size,
37                                      SkBitmap* snapshot) {
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(
42      TransportDIB::Create(
43          page_size.width() * page_size.height() * kNumBytesPerPixel,
44          ++g_sequence_num));
45
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()));
51
52  RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
53  impl->OnPaintAtSize(pixels->handle(), g_sequence_num, page_size,
54                      desired_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, &params);
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);
65
66  SkBitmap tmp_bitmap;
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));
72}
73
74void 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  WebKit::WebSize old_size = view_->GetWebView()->size();
82
83  SkBitmap bitmap;
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));
94
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));
104
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));
113}
114
115bool RenderWidgetTest::ImageContainsColor(const SkBitmap& bitmap,
116                                          uint32 argb_color) {
117  SkAutoLockPixels lock(bitmap);
118  bool ready = bitmap.readyToDraw();
119  EXPECT_TRUE(ready);
120  if (!ready) {
121    return false;
122  }
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)) {
126        return true;
127      }
128    }
129  }
130  return false;
131}
132
133void 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,
140      bitmap.width(),
141      bitmap.height(),
142      static_cast<int>(bitmap.rowBytes()),
143      90 /* quality */,
144      &bitmap_data->data()));
145  ASSERT_LT(0, file_util::WriteFile(
146      file_path,
147      reinterpret_cast<const char*>(bitmap_data->front()),
148      bitmap_data->size()));
149}
150
151}  // namespace content
152