Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Unified Diff: components/favicon/core/favicon_handler_unittest.cc

Issue 2739173002: Always select best favicon bitmap (Closed)
Patch Set: Updated. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/favicon/core/favicon_handler_unittest.cc
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc
index 7514a5e2ecdd7b1cf8d2a1e117afb282d042b684..e478a44524165dc8c787d4e9d4a0ff4edaf0dc60 100644
--- a/components/favicon/core/favicon_handler_unittest.cc
+++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -25,6 +25,7 @@
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
namespace favicon {
namespace {
@@ -33,6 +34,7 @@ using favicon_base::FAVICON;
using favicon_base::FaviconRawBitmapResult;
using favicon_base::TOUCH_ICON;
using favicon_base::TOUCH_PRECOMPOSED_ICON;
+using testing::AllOf;
using testing::AnyNumber;
using testing::Assign;
using testing::AtLeast;
@@ -54,26 +56,42 @@ MATCHER_P2(ImageSizeIs, width, height, "") {
return arg.Size() == gfx::Size(width, height);
}
-// Fill the given bmp with some test data.
-SkBitmap CreateBitmap(int w, int h) {
- SkBitmap bmp;
- bmp.allocN32Pixels(w, h);
+MATCHER_P(HasScaleFactor, scale, "") {
+ return arg.AsImageSkia().HasRepresentation(scale);
+}
- unsigned char* src_data =
- reinterpret_cast<unsigned char*>(bmp.getAddr32(0, 0));
- for (int i = 0; i < w * h; i++) {
- src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255);
- src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255);
- src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255);
- src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255);
+MATCHER_P2(ImageColorForScaleIs, scale, expected_color, "") {
+ gfx::ImageSkia image_skia = arg.AsImageSkia();
+ image_skia.EnsureRepsForSupportedScales();
+ const SkBitmap& bitmap = image_skia.GetRepresentation(scale).sk_bitmap();
+ if (bitmap.empty()) {
+ *result_listener << "expected color but no bitmap data available";
}
- return bmp;
+
+ SkAutoLockPixels lock(bitmap);
+ SkColor actual_color = bitmap.getColor(1, 1);
+ if (actual_color == expected_color) {
+ return true;
+ }
+
+ *result_listener << "expected color "
+ << base::StringPrintf("%08X", expected_color)
+ << " but actual color is "
+ << base::StringPrintf("%08X", actual_color);
+ return false;
}
-// Fill the given data buffer with valid png data.
-void FillBitmap(int w, int h, std::vector<unsigned char>* output) {
- SkBitmap bitmap = CreateBitmap(w, h);
- gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output);
+MATCHER_P(HasIconURL, expected_url, "") {
+ *result_listener << "where icon URL is " << arg.icon_url;
+ return arg.icon_url == GURL(expected_url);
+}
+
+// Fill the given bmp with some test data.
+SkBitmap CreateBitmap(int w, int h, SkColor color) {
+ SkBitmap bmp;
+ bmp.allocN32Pixels(w, h);
+ bmp.eraseColor(color);
+ return bmp;
}
std::vector<gfx::Size> CreateSquareSizes(const IntVector& sizes) {
@@ -84,28 +102,42 @@ std::vector<gfx::Size> CreateSquareSizes(const IntVector& sizes) {
return result;
}
-std::vector<SkBitmap> CreateBitmaps(const std::vector<gfx::Size>& sizes) {
+std::vector<SkBitmap> CreateBitmaps(const std::vector<gfx::Size>& sizes,
+ const std::vector<SkColor>& colors) {
std::vector<SkBitmap> bitmaps;
- for (const gfx::Size& size : sizes) {
- bitmaps.push_back(CreateBitmap(size.width(), size.height()));
+ for (size_t i = 0; i < sizes.size(); ++i) {
+ bitmaps.push_back(CreateBitmap(sizes[i].width(), sizes[i].height(),
+ colors[i]));
}
return bitmaps;
}
-std::vector<FaviconRawBitmapResult> CreateRawBitmapResult(
- const GURL& icon_url,
- favicon_base::IconType icon_type = FAVICON,
- bool expired = false) {
+FaviconRawBitmapResult CreateRawBitmapResult(const GURL& icon_url,
+ favicon_base::IconType icon_type,
+ bool expired,
+ const gfx::Size& size,
+ SkColor color) {
scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
- FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data());
+ SkBitmap bitmap = CreateBitmap(size.width(), size.height(), color);
+ gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data->data());
FaviconRawBitmapResult bitmap_result;
bitmap_result.expired = expired;
bitmap_result.bitmap_data = data;
- // Use a pixel size other than (0,0) as (0,0) has a special meaning.
- bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize);
+ bitmap_result.pixel_size = size;
bitmap_result.icon_type = icon_type;
bitmap_result.icon_url = icon_url;
- return {bitmap_result};
+ return bitmap_result;
+}
+
+std::vector<FaviconRawBitmapResult> CreateRawBitmapResults(
+ const GURL& icon_url,
+ favicon_base::IconType icon_type = FAVICON,
+ bool expired = false) {
+ // Use a pixel size other than (0,0) as (0,0) has a special meaning.
+ return {
+ CreateRawBitmapResult(icon_url, icon_type, expired,
+ gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize),
+ SK_ColorRED)};
}
// Fake that implements the calls to FaviconHalder::Delegate's DownloadImage(),
@@ -141,14 +173,29 @@ class FakeImageDownloader {
AddWithOriginalSizes(icon_url, sizes, sizes);
}
+ void AddWithColors(const GURL& icon_url, const IntVector& sizes,
+ const std::vector<SkColor>& colors) {
+ AddWithColorsAndOriginalSizes(icon_url, sizes, colors, sizes);
+ }
+
void AddWithOriginalSizes(const GURL& icon_url,
const IntVector& sizes,
const IntVector& original_sizes) {
+ std::vector<SkColor> colors;
+ colors.resize(sizes.size(), SK_ColorRED);
+ AddWithColorsAndOriginalSizes(icon_url, sizes, colors, original_sizes);
+ }
+
+ void AddWithColorsAndOriginalSizes(const GURL& icon_url,
+ const IntVector& sizes,
+ const std::vector<SkColor>& colors,
+ const IntVector& original_sizes) {
+ DCHECK_EQ(sizes.size(), colors.size());
DCHECK_EQ(sizes.size(), original_sizes.size());
Response response;
response.http_status_code = 200;
response.original_bitmap_sizes = CreateSquareSizes(original_sizes);
- response.bitmaps = CreateBitmaps(CreateSquareSizes(sizes));
+ response.bitmaps = CreateBitmaps(CreateSquareSizes(sizes), colors);
responses_[icon_url] = response;
}
@@ -250,7 +297,7 @@ class FakeFaviconService {
base::CancelableTaskTracker::TaskId GetFavicon(
const GURL& icon_url,
favicon_base::IconType icon_type,
- int desired_size_in_dip,
+ const std::vector<int>& desired_sizes_in_pixel,
const favicon_base::FaviconResultsCallback& callback,
base::CancelableTaskTracker* tracker) {
return GetFaviconForPageOrIconURL(icon_url, callback, tracker);
@@ -259,7 +306,7 @@ class FakeFaviconService {
base::CancelableTaskTracker::TaskId GetFaviconForPageURL(
const GURL& page_url,
int icon_types,
- int desired_size_in_dip,
+ const std::vector<int>& desired_sizes_in_pixel,
const favicon_base::FaviconResultsCallback& callback,
base::CancelableTaskTracker* tracker) {
return GetFaviconForPageOrIconURL(page_url, callback, tracker);
@@ -269,7 +316,7 @@ class FakeFaviconService {
const GURL& page_url,
const std::vector<GURL>& icon_urls,
int icon_types,
- int desired_size_in_dip,
+ const std::vector<int>& desired_sizes_in_pixel,
const favicon_base::FaviconResultsCallback& callback,
base::CancelableTaskTracker* tracker) {
CHECK_EQ(1U, icon_urls.size()) << "Multi-icon lookup not implemented";
@@ -324,6 +371,7 @@ class FaviconHandlerTest : public testing::Test {
const GURL kIconURL10x10 = GURL("http://www.google.com/favicon10x10");
const GURL kIconURL12x12 = GURL("http://www.google.com/favicon12x12");
const GURL kIconURL16x16 = GURL("http://www.google.com/favicon16x16");
+ const GURL kIconURL32x32 = GURL("http://www.google.com/favicon32x32");
const GURL kIconURL64x64 = GURL("http://www.google.com/favicon64x64");
FaviconHandlerTest() {
@@ -331,6 +379,7 @@ class FaviconHandlerTest : public testing::Test {
delegate_.fake_downloader().Add(kIconURL10x10, IntVector{10});
delegate_.fake_downloader().Add(kIconURL12x12, IntVector{12});
delegate_.fake_downloader().Add(kIconURL16x16, IntVector{16});
+ delegate_.fake_downloader().Add(kIconURL32x32, IntVector{32});
delegate_.fake_downloader().Add(kIconURL64x64, IntVector{64});
// The score computed by SelectFaviconFrames() is dependent on the supported
@@ -389,7 +438,7 @@ TEST_F(FaviconHandlerTest, GetFaviconFromHistory) {
const GURL kIconURL("http://www.google.com/favicon");
favicon_service_.fake()->Store(kPageURL, kIconURL,
- CreateRawBitmapResult(kIconURL));
+ CreateRawBitmapResults(kIconURL));
// Shouldn't request to download icon.
EXPECT_CALL(delegate_, OnFaviconUpdated(
@@ -476,7 +525,7 @@ TEST_F(FaviconHandlerTest, DownloadUnknownFaviconIfCandidatesFaster) {
TEST_F(FaviconHandlerTest, RedownloadExpiredPageUrlFavicon) {
favicon_service_.fake()->Store(
kPageURL, kIconURL16x16,
- CreateRawBitmapResult(kIconURL16x16, FAVICON, /*expired=*/true));
+ CreateRawBitmapResults(kIconURL16x16, FAVICON, /*expired=*/true));
// TODO(crbug.com/700811): It would be nice if we could check whether the two
// OnFaviconUpdated() calls are called with different gfx::Images (as opposed
@@ -525,7 +574,7 @@ TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) {
const GURL kNewIconURL = kIconURL16x16;
favicon_service_.fake()->Store(kPageURL, kOldIconURL,
- CreateRawBitmapResult(kOldIconURL));
+ CreateRawBitmapResults(kOldIconURL));
InSequence seq;
EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kOldIconURL, _, _));
@@ -569,9 +618,9 @@ TEST_F(FaviconHandlerTest, UpdateFavicon) {
const GURL kNewIconURL("http://www.google.com/new_favicon");
favicon_service_.fake()->Store(kPageURL, kIconURL,
- CreateRawBitmapResult(kIconURL));
+ CreateRawBitmapResults(kIconURL));
favicon_service_.fake()->Store(kSomePreviousPageURL, kNewIconURL,
- CreateRawBitmapResult(kNewIconURL));
+ CreateRawBitmapResults(kNewIconURL));
EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
@@ -591,8 +640,8 @@ TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) {
favicon_service_.fake()->Store(
kPageURL, kIconURL64x64,
- CreateRawBitmapResult(kIconURL64x64, TOUCH_ICON,
- /*expired=*/true));
+ CreateRawBitmapResults(kIconURL64x64, TOUCH_ICON,
+ /*expired=*/true));
EXPECT_CALL(delegate_,
OnFaviconUpdated(kPageURL, FaviconDriverObserver::TOUCH_LARGEST,
@@ -824,6 +873,57 @@ TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseMinorUpsamplingOverHugeIcon) {
EXPECT_EQ(17, DownloadTillDoneIgnoringHistory(IntVector{17, 256}));
}
+// Test that the FaviconHandler process finishes when the database provides
+// a favicon with multiple bitmaps.
+TEST_F(FaviconHandlerMultipleFaviconsTest,
+ GetFaviconFromHistoryWithMultipleBitmaps) {
+ const GURL kIconURL32_16("http://www.google.com/a");
+ ui::test::ScopedSetSupportedScaleFactors({ui::SCALE_FACTOR_100P, ui::SCALE_FACTOR_200P});
+
+ favicon_service_.fake()->Store(
+ kPageURL, kIconURL32_16,
+ {CreateRawBitmapResult(kIconURL32_16, FAVICON, /*expired=*/false,
+ gfx::Size(32, 32), SK_ColorGREEN),
+ CreateRawBitmapResult(kIconURL32_16, FAVICON, /*expired=*/false,
+ gfx::Size(16, 16), SK_ColorBLUE)});
+
+ // Set 16x16 bitmap is needed for sync purposes.
+ EXPECT_CALL(delegate_, OnFaviconUpdated(
+ _, _, _, _,
+ AllOf(ImageSizeIs(16, 16),
+ ImageColorForScaleIs(1.0f, SK_ColorBLUE),
+ ImageColorForScaleIs(2.0f, SK_ColorGREEN))));
+
+ RunHandlerWithSimpleFaviconCandidates({kIconURL32_16});
+}
+
+// Test that the FaviconHandler process finishes when:
+// - There is no data in the database for neither the page URL nor the icon URL.
+// - FaviconService::GetFaviconForPageURL() callback returns before
+// FaviconHandler::OnUpdateFaviconURL() is called.
+// AND
+// - The page provides a favicon with multiple bitmaps.
+TEST_F(FaviconHandlerMultipleFaviconsTest,
+ DownloadUnknownFaviconWithMultipleBitmaps) {
+ const GURL kIconURL32_16("http://www.google.com/a");
+
+ delegate_.fake_downloader().AddWithColors(
+ kIconURL32_16, IntVector{32, 16}, {SK_ColorGREEN, SK_ColorBLUE});
+
+ // Set 16x16 bitmap is needed for sync purposes.
+ EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _,
+ AllOf(ImageSizeIs(16, 16),
+ ImageColorForScaleIs(1.0f, SK_ColorBLUE),
+ ImageColorForScaleIs(2.0f, SK_ColorGREEN))));
+ EXPECT_CALL(favicon_service_,
+ SetFavicons(kPageURL, kIconURL32_16, FAVICON,
+ AllOf(ImageSizeIs(16, 16),
+ ImageColorForScaleIs(1.0f, SK_ColorBLUE),
+ ImageColorForScaleIs(2.0f, SK_ColorGREEN))));
+
+ RunHandlerWithSimpleFaviconCandidates({kIconURL32_16});
+}
+
// Test that the best favicon is selected when:
// - The page provides several favicons.
// - Downloading one of the page's icon URLs previously returned a 404.
@@ -878,7 +978,7 @@ TEST_F(FaviconHandlerTest, FaviconInvalidURL) {
EXPECT_THAT(delegate_.downloads(), IsEmpty());
}
-TEST_F(FaviconHandlerTest, TestSortFavicon) {
+TEST_F(FaviconHandlerTest, TestSortFavicon16DIP) {
const std::vector<favicon::FaviconURL> kSourceIconURLs{
FaviconURL(GURL("http://www.google.com/a"), FAVICON,
{gfx::Size(1, 1), gfx::Size(17, 17)}),
@@ -887,37 +987,103 @@ TEST_F(FaviconHandlerTest, TestSortFavicon) {
FaviconURL(GURL("http://www.google.com/c"), FAVICON,
{gfx::Size(16, 16), gfx::Size(14, 14)}),
FaviconURL(GURL("http://www.google.com/d"), FAVICON, kEmptySizes),
- FaviconURL(GURL("http://www.google.com/e"), FAVICON, kEmptySizes)};
+ FaviconURL(GURL("http://www.google.com/e"), FAVICON, kEmptySizes),
+ FaviconURL(GURL("http://www.google.com/f"), FAVICON,
+ {gfx::Size(10, 10), gfx::Size(400, 400)})};
+
+ std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
+ FaviconDriverObserver::NON_TOUCH_16_DIP, kSourceIconURLs);
+
+ EXPECT_THAT(handler->image_urls(),
+ ElementsAre(HasIconURL("http://www.google.com/c"),
+ HasIconURL("http://www.google.com/a"),
+ HasIconURL("http://www.google.com/f"),
+ HasIconURL("http://www.google.com/b"),
+ // The rest of bitmaps come in order, there is no
+ // sizes attribute.
+ HasIconURL("http://www.google.com/d"),
+ HasIconURL("http://www.google.com/e")));
+}
+
+TEST_F(FaviconHandlerTest, TestSortFaviconLargest) {
+ const std::vector<favicon::FaviconURL> kSourceIconURLs{
+ FaviconURL(GURL("http://www.google.com/a"), FAVICON,
+ {gfx::Size(1, 1), gfx::Size(17, 17)}),
+ FaviconURL(GURL("http://www.google.com/b"), FAVICON,
+ {gfx::Size(1024, 1024), gfx::Size(512, 512)}),
+ FaviconURL(GURL("http://www.google.com/c"), FAVICON,
+ {gfx::Size(16, 16), gfx::Size(14, 14)}),
+ FaviconURL(GURL("http://www.google.com/d"), FAVICON, kEmptySizes),
+ FaviconURL(GURL("http://www.google.com/e"), FAVICON, kEmptySizes),
+ FaviconURL(GURL("http://www.google.com/f"), FAVICON,
+ {gfx::Size(10, 10), gfx::Size(400, 400)})};
std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
FaviconDriverObserver::NON_TOUCH_LARGEST, kSourceIconURLs);
- struct ExpectedResult {
- // The favicon's index in kSourceIconURLs.
- size_t favicon_index;
- // Width of largest bitmap.
- int width;
- } results[] = {
- // First is icon2, though its size larger than maximal.
- {1, 1024},
- // Second is icon1
- // The 17x17 is largest.
- {0, 17},
- // Third is icon3 though it has same size as icon1.
- // The 16x16 is largest.
- {2, 16},
- // The rest of bitmaps come in order, there is no sizes attribute.
- {3, -1},
- {4, -1},
- };
- const std::vector<FaviconURL>& icons = handler->image_urls();
- ASSERT_EQ(5u, icons.size());
- for (size_t i = 0; i < icons.size(); ++i) {
- EXPECT_EQ(kSourceIconURLs[results[i].favicon_index].icon_url,
- icons[i].icon_url);
- if (results[i].width != -1)
- EXPECT_EQ(results[i].width, icons[i].icon_sizes[0].width());
- }
+ EXPECT_THAT(handler->image_urls(),
+ ElementsAre(HasIconURL("http://www.google.com/f"),
+ HasIconURL("http://www.google.com/b"),
+ HasIconURL("http://www.google.com/a"),
+ HasIconURL("http://www.google.com/c"),
+ // The rest of bitmaps come in order, there is no
+ // sizes attribute.
+ HasIconURL("http://www.google.com/d"),
+ HasIconURL("http://www.google.com/e")));
+}
+
+TEST_F(FaviconHandlerTest, DownloadNoMoreAfterExactMatch) {
+ RunHandlerWithSimpleFaviconCandidates({kIconURL16x16, kIconURL64x64});
+ EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
+}
+
+TEST_F(FaviconHandlerTest, DownloadExactMatchFirstIfSizesProvided) {
+ RunHandlerWithCandidates(
+ FaviconDriverObserver::NON_TOUCH_16_DIP,
+ {
+ FaviconURL(kIconURL64x64, FAVICON, SizeVector{gfx::Size(64, 64)}),
+ FaviconURL(kIconURL16x16, FAVICON, SizeVector{gfx::Size(16, 16)}),
+ });
+ EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
+}
+
+TEST_F(FaviconHandlerTest, DownloadLargeButNotAboveLimit) {
+ const GURL kIconURL192x192 = GURL("http://www.google.com/favicon192x192");
+ const GURL kIconURL512x512 = GURL("http://www.google.com/favicon512x512");
+
+ delegate_.fake_downloader().Add(kIconURL192x192, IntVector{192});
+ delegate_.fake_downloader().Add(kIconURL512x512, IntVector{512});
+
+ RunHandlerWithCandidates(
+ FaviconDriverObserver::NON_TOUCH_LARGEST,
+ {
+ FaviconURL(kIconURL512x512, FAVICON, SizeVector{gfx::Size(512, 512)}),
+ FaviconURL(kIconURL192x192, FAVICON, SizeVector{gfx::Size(192, 192)}),
+ });
+
+ EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL192x192));
+}
+
+// Test that the high-resolution favicon is selected when:
+// - The page provides several favicons.
+// - The low-resolution one is cached in the Favicons database (e.g. was written
+// via sync).
+// AND
+// - The high-resolution candidate is the best match.
+TEST_F(FaviconHandlerTest, DownloadHighResolutionWhenOnlyLowResolutionCached) {
+ favicon_service_.fake()->Store(kPageURL, kIconURL16x16,
+ CreateRawBitmapResults(kIconURL16x16, FAVICON,
+ /*expired=*/false));
+
+ EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL32x32, _, _));
+
+ RunHandlerWithCandidates(
+ FaviconDriverObserver::NON_TOUCH_LARGEST,
+ {
+ FaviconURL(kIconURL16x16, FAVICON, SizeVector{gfx::Size(16, 16)}),
+ FaviconURL(kIconURL32x32, FAVICON, SizeVector{gfx::Size(32, 32)}),
+ });
+ EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL32x32));
}
TEST_F(FaviconHandlerTest, TestDownloadLargestFavicon) {
@@ -971,7 +1137,11 @@ TEST_F(FaviconHandlerTest, TestSelectLargestFavicon) {
}
TEST_F(FaviconHandlerTest, TestFaviconWasScaledAfterDownload) {
- const int kMaximalSize = FaviconHandler::GetMaximalIconSize(FAVICON);
+#if defined(OS_IOS)
+ const int kMaximalSize = 144;
+#else
+ const int kMaximalSize = 192;
+#endif
const GURL kIconURL1("http://www.google.com/b");
const GURL kIconURL2("http://www.google.com/c");

Powered by Google App Engine
This is Rietveld 408576698