Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / favicon / core / large_icon_service_unittest.cc
blobbe6905251a0e13a4fe2adb95524b08f77f106b4f
1 // Copyright 2015 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 "components/favicon/core/large_icon_service.h"
7 #include <deque>
9 #include "base/bind.h"
10 #include "base/memory/ref_counted_memory.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/task/cancelable_task_tracker.h"
14 #include "components/favicon/core/favicon_client.h"
15 #include "components/favicon/core/favicon_service.h"
16 #include "components/favicon_base/fallback_icon_style.h"
17 #include "components/favicon_base/favicon_types.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "third_party/skia/include/core/SkColor.h"
21 #include "ui/gfx/codec/png_codec.h"
22 #include "ui/gfx/geometry/size.h"
23 #include "ui/gfx/image/image.h"
24 #include "url/gurl.h"
26 namespace favicon {
27 namespace {
29 const char kDummyUrl[] = "http://www.example.com";
30 const char kDummyIconUrl[] = "http://www.example.com/touch_icon.png";
32 const SkColor kTestColor = SK_ColorRED;
34 favicon_base::FaviconRawBitmapResult CreateTestBitmap(
35 int w, int h, SkColor color) {
36 favicon_base::FaviconRawBitmapResult result;
37 result.expired = false;
39 // Create bitmap and fill with |color|.
40 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
41 SkBitmap bitmap;
42 bitmap.allocN32Pixels(w, h);
43 bitmap.eraseColor(color);
44 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data->data());
45 result.bitmap_data = data;
47 result.pixel_size = gfx::Size(w, h);
48 result.icon_url = GURL(kDummyIconUrl);
49 result.icon_type = favicon_base::TOUCH_ICON;
50 CHECK(result.is_valid());
51 return result;
54 // A mock FaviconService that emits pre-programmed response.
55 class MockFaviconService : public FaviconService {
56 public:
57 MockFaviconService() : FaviconService(nullptr, nullptr) {
60 ~MockFaviconService() override {
63 base::CancelableTaskTracker::TaskId GetLargestRawFaviconForPageURL(
64 const GURL& page_url,
65 const std::vector<int>& icon_types,
66 int minimum_size_in_pixels,
67 const favicon_base::FaviconRawBitmapCallback& callback,
68 base::CancelableTaskTracker* tracker) override {
69 favicon_base::FaviconRawBitmapResult mock_result =
70 mock_result_queue_.front();
71 mock_result_queue_.pop_front();
72 return tracker->PostTask(
73 base::MessageLoop::current()->task_runner().get(), FROM_HERE,
74 base::Bind(callback, mock_result));
77 void InjectResult(const favicon_base::FaviconRawBitmapResult& mock_result) {
78 mock_result_queue_.push_back(mock_result);
81 bool HasUnusedResults() {
82 return !mock_result_queue_.empty();
85 private:
86 std::deque<favicon_base::FaviconRawBitmapResult> mock_result_queue_;
88 DISALLOW_COPY_AND_ASSIGN(MockFaviconService);
91 // This class provides access to LargeIconService internals, using the current
92 // thread's task runner for testing.
93 class TestLargeIconService : public LargeIconService {
94 public:
95 explicit TestLargeIconService(MockFaviconService* mock_favicon_service)
96 : LargeIconService(mock_favicon_service,
97 base::MessageLoop::current()->task_runner()) {}
98 ~TestLargeIconService() override {
101 private:
102 DISALLOW_COPY_AND_ASSIGN(TestLargeIconService);
105 class LargeIconServiceTest : public testing::Test {
106 public:
107 LargeIconServiceTest() : is_callback_invoked_(false) {
110 ~LargeIconServiceTest() override {
113 void SetUp() override {
114 testing::Test::SetUp();
115 mock_favicon_service_.reset(new MockFaviconService());
116 large_icon_service_.reset(
117 new TestLargeIconService(mock_favicon_service_.get()));
120 void ResultCallback(const favicon_base::LargeIconResult& result) {
121 is_callback_invoked_ = true;
123 // Checking presence and absence of results.
124 EXPECT_EQ(expected_bitmap_.is_valid(), result.bitmap.is_valid());
125 EXPECT_EQ(expected_fallback_icon_style_ != nullptr,
126 result.fallback_icon_style != nullptr);
128 if (expected_bitmap_.is_valid()) {
129 EXPECT_EQ(expected_bitmap_.pixel_size, result.bitmap.pixel_size);
130 // Not actually checking bitmap content.
132 if (expected_fallback_icon_style_.get()) {
133 EXPECT_EQ(*expected_fallback_icon_style_,
134 *result.fallback_icon_style);
136 // Ensure all mock results have been consumed.
137 EXPECT_FALSE(mock_favicon_service_->HasUnusedResults());
140 protected:
141 base::MessageLoopForIO loop_;
143 scoped_ptr<MockFaviconService> mock_favicon_service_;
144 scoped_ptr<TestLargeIconService> large_icon_service_;
145 base::CancelableTaskTracker cancelable_task_tracker_;
147 favicon_base::FaviconRawBitmapResult expected_bitmap_;
148 scoped_ptr<favicon_base::FallbackIconStyle> expected_fallback_icon_style_;
150 bool is_callback_invoked_;
152 private:
153 DISALLOW_COPY_AND_ASSIGN(LargeIconServiceTest);
156 TEST_F(LargeIconServiceTest, SameSize) {
157 mock_favicon_service_->InjectResult(CreateTestBitmap(24, 24, kTestColor));
158 expected_bitmap_ = CreateTestBitmap(24, 24, kTestColor);
159 large_icon_service_->GetLargeIconOrFallbackStyle(
160 GURL(kDummyUrl),
161 24, // |min_source_size_in_pixel|
162 24, // |desired_size_in_pixel|
163 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
164 &cancelable_task_tracker_);
165 base::MessageLoop::current()->RunUntilIdle();
166 EXPECT_TRUE(is_callback_invoked_);
169 TEST_F(LargeIconServiceTest, ScaleDown) {
170 mock_favicon_service_->InjectResult(CreateTestBitmap(32, 32, kTestColor));
171 expected_bitmap_ = CreateTestBitmap(24, 24, kTestColor);
172 large_icon_service_->GetLargeIconOrFallbackStyle(
173 GURL(kDummyUrl),
176 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
177 &cancelable_task_tracker_);
178 base::MessageLoop::current()->RunUntilIdle();
179 EXPECT_TRUE(is_callback_invoked_);
182 TEST_F(LargeIconServiceTest, ScaleUp) {
183 mock_favicon_service_->InjectResult(CreateTestBitmap(16, 16, kTestColor));
184 expected_bitmap_ = CreateTestBitmap(24, 24, kTestColor);
185 large_icon_service_->GetLargeIconOrFallbackStyle(
186 GURL(kDummyUrl),
187 14, // Lowered requirement so stored bitmap is admitted.
189 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
190 &cancelable_task_tracker_);
191 base::MessageLoop::current()->RunUntilIdle();
192 EXPECT_TRUE(is_callback_invoked_);
195 // |desired_size_in_pixel| == 0 means retrieve original image without scaling.
196 TEST_F(LargeIconServiceTest, NoScale) {
197 mock_favicon_service_->InjectResult(CreateTestBitmap(24, 24, kTestColor));
198 expected_bitmap_ = CreateTestBitmap(24, 24, kTestColor);
199 large_icon_service_->GetLargeIconOrFallbackStyle(
200 GURL(kDummyUrl),
203 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
204 &cancelable_task_tracker_);
205 base::MessageLoop::current()->RunUntilIdle();
206 EXPECT_TRUE(is_callback_invoked_);
209 TEST_F(LargeIconServiceTest, FallbackSinceIconTooSmall) {
210 mock_favicon_service_->InjectResult(CreateTestBitmap(16, 16, kTestColor));
211 expected_fallback_icon_style_.reset(new favicon_base::FallbackIconStyle);
212 expected_fallback_icon_style_->background_color = kTestColor;
213 large_icon_service_->GetLargeIconOrFallbackStyle(
214 GURL(kDummyUrl),
217 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
218 &cancelable_task_tracker_);
219 base::MessageLoop::current()->RunUntilIdle();
220 EXPECT_TRUE(is_callback_invoked_);
223 TEST_F(LargeIconServiceTest, FallbackSinceIconNotSquare) {
224 mock_favicon_service_->InjectResult(CreateTestBitmap(24, 32, kTestColor));
225 expected_fallback_icon_style_.reset(new favicon_base::FallbackIconStyle);
226 expected_fallback_icon_style_->background_color = kTestColor;
227 large_icon_service_->GetLargeIconOrFallbackStyle(
228 GURL(kDummyUrl),
231 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
232 &cancelable_task_tracker_);
233 base::MessageLoop::current()->RunUntilIdle();
234 EXPECT_TRUE(is_callback_invoked_);
237 TEST_F(LargeIconServiceTest, FallbackSinceIconMissing) {
238 mock_favicon_service_->InjectResult(favicon_base::FaviconRawBitmapResult());
239 // Expect default fallback style, including background.
240 expected_fallback_icon_style_.reset(new favicon_base::FallbackIconStyle);
241 large_icon_service_->GetLargeIconOrFallbackStyle(
242 GURL(kDummyUrl),
245 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
246 &cancelable_task_tracker_);
247 base::MessageLoop::current()->RunUntilIdle();
248 EXPECT_TRUE(is_callback_invoked_);
251 TEST_F(LargeIconServiceTest, FallbackSinceIconMissingNoScale) {
252 mock_favicon_service_->InjectResult(favicon_base::FaviconRawBitmapResult());
253 // Expect default fallback style, including background.
254 expected_fallback_icon_style_.reset(new favicon_base::FallbackIconStyle);
255 large_icon_service_->GetLargeIconOrFallbackStyle(
256 GURL(kDummyUrl),
259 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
260 &cancelable_task_tracker_);
261 base::MessageLoop::current()->RunUntilIdle();
262 EXPECT_TRUE(is_callback_invoked_);
265 // Oddball case where we demand a high resolution icon to scale down. Generates
266 // fallback even though an icon with the final size is available.
267 TEST_F(LargeIconServiceTest, FallbackSinceTooPicky) {
268 mock_favicon_service_->InjectResult(CreateTestBitmap(24, 24, kTestColor));
269 expected_fallback_icon_style_.reset(new favicon_base::FallbackIconStyle);
270 expected_fallback_icon_style_->background_color = kTestColor;
271 large_icon_service_->GetLargeIconOrFallbackStyle(
272 GURL(kDummyUrl),
275 base::Bind(&LargeIconServiceTest::ResultCallback, base::Unretained(this)),
276 &cancelable_task_tracker_);
277 base::MessageLoop::current()->RunUntilIdle();
278 EXPECT_TRUE(is_callback_invoked_);
281 } // namespace
282 } // namespace favicon