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

Side by Side Diff: components/favicon/core/favicon_handler_unittest.cc

Issue 2872643002: Verify favicon bitmap content in FaviconHandler tests (Closed)
Patch Set: Forgotten upload addressing comments. Created 3 years, 7 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/favicon/core/favicon_handler.h" 5 #include "components/favicon/core/favicon_handler.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <map> 9 #include <map>
10 #include <memory> 10 #include <memory>
11 #include <set> 11 #include <set>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/run_loop.h" 16 #include "base/run_loop.h"
17 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
18 #include "base/test/histogram_tester.h" 18 #include "base/test/histogram_tester.h"
19 #include "base/test/scoped_task_environment.h" 19 #include "base/test/scoped_task_environment.h"
20 #include "base/test/test_simple_task_runner.h" 20 #include "base/test/test_simple_task_runner.h"
21 #include "components/favicon/core/favicon_driver.h" 21 #include "components/favicon/core/favicon_driver.h"
22 #include "components/favicon/core/test/mock_favicon_service.h" 22 #include "components/favicon/core/test/mock_favicon_service.h"
23 #include "testing/gmock/include/gmock/gmock.h" 23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h" 24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/skia/include/core/SkBitmap.h" 25 #include "third_party/skia/include/core/SkBitmap.h"
26 #include "third_party/skia/include/core/SkColor.h"
26 #include "ui/base/layout.h" 27 #include "ui/base/layout.h"
27 #include "ui/gfx/codec/png_codec.h" 28 #include "ui/gfx/codec/png_codec.h"
28 #include "ui/gfx/favicon_size.h" 29 #include "ui/gfx/favicon_size.h"
29 #include "ui/gfx/image/image.h" 30 #include "ui/gfx/image/image.h"
30 31
31 namespace favicon { 32 namespace favicon {
32 namespace { 33 namespace {
33 34
34 using favicon_base::FAVICON; 35 using favicon_base::FAVICON;
35 using favicon_base::FaviconRawBitmapResult; 36 using favicon_base::FaviconRawBitmapResult;
(...skipping 11 matching lines...) Expand all
47 using IntVector = std::vector<int>; 48 using IntVector = std::vector<int>;
48 using URLVector = std::vector<GURL>; 49 using URLVector = std::vector<GURL>;
49 using BitmapVector = std::vector<SkBitmap>; 50 using BitmapVector = std::vector<SkBitmap>;
50 using SizeVector = std::vector<gfx::Size>; 51 using SizeVector = std::vector<gfx::Size>;
51 52
52 MATCHER_P2(ImageSizeIs, width, height, "") { 53 MATCHER_P2(ImageSizeIs, width, height, "") {
53 *result_listener << "where size is " << arg.Width() << "x" << arg.Height(); 54 *result_listener << "where size is " << arg.Width() << "x" << arg.Height();
54 return arg.Size() == gfx::Size(width, height); 55 return arg.Size() == gfx::Size(width, height);
55 } 56 }
56 57
57 // Fill the given bmp with some test data. 58 // |arg| is a gfx::Image.
58 SkBitmap CreateBitmapWithEdgeSize(int size) { 59 MATCHER_P(ImageColorIs, expected_color, "") {
60 SkBitmap bitmap = arg.AsBitmap();
61 if (bitmap.empty()) {
62 *result_listener << "expected color but no bitmap data available";
63 return false;
64 }
65
66 SkColor actual_color = bitmap.getColor(1, 1);
67 if (actual_color != expected_color) {
68 *result_listener << "expected color "
69 << base::StringPrintf("%08X", expected_color)
70 << " but actual color is "
71 << base::StringPrintf("%08X", actual_color);
72 return false;
73 }
74 return true;
75 }
76
77 SkBitmap CreateBitmapWithEdgeSize(int size, SkColor color) {
59 SkBitmap bmp; 78 SkBitmap bmp;
60 bmp.allocN32Pixels(size, size); 79 bmp.allocN32Pixels(size, size);
61 80 bmp.eraseColor(color);
62 unsigned char* src_data =
63 reinterpret_cast<unsigned char*>(bmp.getAddr32(0, 0));
64 for (int i = 0; i < size * size; i++) {
65 src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255);
66 src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255);
67 src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255);
68 src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255);
69 }
70 return bmp; 81 return bmp;
71 } 82 }
72 83
73 // Fill the given data buffer with valid png data. 84 // Fill the given data buffer with valid png data.
74 std::vector<unsigned char> FillBitmapWithEdgeSize(int size) { 85 std::vector<unsigned char> FillBitmapWithEdgeSize(int size, SkColor color) {
75 SkBitmap bitmap = CreateBitmapWithEdgeSize(size); 86 SkBitmap bitmap = CreateBitmapWithEdgeSize(size, color);
76 std::vector<unsigned char> output; 87 std::vector<unsigned char> output;
77 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output); 88 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output);
78 return output; 89 return output;
79 } 90 }
80 91
81 std::vector<FaviconRawBitmapResult> CreateRawBitmapResult( 92 std::vector<FaviconRawBitmapResult> CreateRawBitmapResult(
82 const GURL& icon_url, 93 const GURL& icon_url,
83 favicon_base::IconType icon_type = FAVICON, 94 favicon_base::IconType icon_type = FAVICON,
84 bool expired = false, 95 bool expired = false,
85 int edge_size = gfx::kFaviconSize) { 96 int edge_size = gfx::kFaviconSize,
97 SkColor color = SK_ColorRED) {
86 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); 98 scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
87 data->data() = FillBitmapWithEdgeSize(edge_size); 99 data->data() = FillBitmapWithEdgeSize(edge_size, color);
88 FaviconRawBitmapResult bitmap_result; 100 FaviconRawBitmapResult bitmap_result;
89 bitmap_result.expired = expired; 101 bitmap_result.expired = expired;
90 bitmap_result.bitmap_data = data; 102 bitmap_result.bitmap_data = data;
91 // Use a pixel size other than (0,0) as (0,0) has a special meaning. 103 // Use a pixel size other than (0,0) as (0,0) has a special meaning.
92 bitmap_result.pixel_size = gfx::Size(edge_size, edge_size); 104 bitmap_result.pixel_size = gfx::Size(edge_size, edge_size);
93 bitmap_result.icon_type = icon_type; 105 bitmap_result.icon_type = icon_type;
94 bitmap_result.icon_url = icon_url; 106 bitmap_result.icon_url = icon_url;
95 return {bitmap_result}; 107 return {bitmap_result};
96 } 108 }
97 109
(...skipping 21 matching lines...) Expand all
119 base::Closure bound_callback = 131 base::Closure bound_callback =
120 base::Bind(callback, download_id, response.http_status_code, url, 132 base::Bind(callback, download_id, response.http_status_code, url,
121 response.bitmaps, response.original_bitmap_sizes); 133 response.bitmaps, response.original_bitmap_sizes);
122 if (url == manual_callback_url_) 134 if (url == manual_callback_url_)
123 manual_callback_ = bound_callback; 135 manual_callback_ = bound_callback;
124 else 136 else
125 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, bound_callback); 137 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, bound_callback);
126 return download_id; 138 return download_id;
127 } 139 }
128 140
129 void Add(const GURL& icon_url, const IntVector& sizes) { 141 void Add(const GURL& icon_url,
130 AddWithOriginalSizes(icon_url, sizes, sizes); 142 const IntVector& sizes,
131 } 143 const IntVector& original_sizes,
132 144 SkColor color) {
133 void AddWithOriginalSizes(const GURL& icon_url,
134 const IntVector& sizes,
135 const IntVector& original_sizes) {
136 DCHECK_EQ(sizes.size(), original_sizes.size()); 145 DCHECK_EQ(sizes.size(), original_sizes.size());
137 Response response; 146 Response response;
138 response.http_status_code = 200; 147 response.http_status_code = 200;
139 for (int size : sizes) { 148 for (int size : sizes) {
140 response.original_bitmap_sizes.push_back(gfx::Size(size, size)); 149 response.original_bitmap_sizes.push_back(gfx::Size(size, size));
141 response.bitmaps.push_back(CreateBitmapWithEdgeSize(size)); 150 response.bitmaps.push_back(CreateBitmapWithEdgeSize(size, color));
142 } 151 }
143 responses_[icon_url] = response; 152 responses_[icon_url] = response;
144 } 153 }
145 154
155 // Simpler overload of the function above.
156 void Add(const GURL& icon_url, const IntVector& sizes) {
157 Add(icon_url, sizes, sizes, SK_ColorRED);
158 }
159
146 void AddError(const GURL& icon_url, int http_status_code) { 160 void AddError(const GURL& icon_url, int http_status_code) {
147 Response response; 161 Response response;
148 response.http_status_code = http_status_code; 162 response.http_status_code = http_status_code;
149 responses_[icon_url] = response; 163 responses_[icon_url] = response;
150 } 164 }
151 165
152 // Disables automatic callback for |url|. This is useful for emulating a 166 // Disables automatic callback for |url|. This is useful for emulating a
153 // download taking a long time. The callback for DownloadImage() will be 167 // download taking a long time. The callback for DownloadImage() will be
154 // stored in |manual_callback_|. 168 // stored in |manual_callback_|.
155 void SetRunCallbackManuallyForUrl(const GURL& url) { 169 void SetRunCallbackManuallyForUrl(const GURL& url) {
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 574
561 EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL16x16, _, _)); 575 EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL16x16, _, _));
562 576
563 RunHandlerWithSimpleFaviconCandidates({kIconURL16x16}); 577 RunHandlerWithSimpleFaviconCandidates({kIconURL16x16});
564 EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16)); 578 EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
565 } 579 }
566 580
567 // Test that the icon is redownloaded if the icon cached for the page URL 581 // Test that the icon is redownloaded if the icon cached for the page URL
568 // expired. 582 // expired.
569 TEST_F(FaviconHandlerTest, RedownloadExpiredPageUrlFavicon) { 583 TEST_F(FaviconHandlerTest, RedownloadExpiredPageUrlFavicon) {
584 const GURL kIconURL("http://www.google.com/favicon");
585 const SkColor kOldColor = SK_ColorBLUE;
586 const SkColor kNewColor = SK_ColorGREEN;
587
570 favicon_service_.fake()->Store( 588 favicon_service_.fake()->Store(
571 kPageURL, kIconURL16x16, 589 kPageURL, kIconURL,
572 CreateRawBitmapResult(kIconURL16x16, FAVICON, /*expired=*/true)); 590 CreateRawBitmapResult(kIconURL, FAVICON, /*expired=*/true,
591 gfx::kFaviconSize, kOldColor));
573 592
574 // TODO(crbug.com/700811): It would be nice if we could check whether the two 593 delegate_.fake_downloader().Add(kIconURL, IntVector{gfx::kFaviconSize},
575 // OnFaviconUpdated() calls are called with different gfx::Images (as opposed 594 IntVector{gfx::kFaviconSize}, kNewColor);
576 // to calling OnFaviconUpdated() with the expired gfx::Image both times).
577 EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _)).Times(2);
578 EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL16x16, _, _));
579 595
580 RunHandlerWithSimpleFaviconCandidates({kIconURL16x16}); 596 EXPECT_CALL(favicon_service_,
581 // We know from the |kPageUrl| database request that |kIconURL16x16| has 597 SetFavicons(_, kIconURL, _, ImageColorIs(kNewColor)));
582 // expired. A second request for |kIconURL16x16| should not have been made 598
583 // because it is redundant. 599 InSequence seq;
600 EXPECT_CALL(delegate_,
601 OnFaviconUpdated(_, _, kIconURL, _, ImageColorIs(kOldColor)));
602 EXPECT_CALL(delegate_,
603 OnFaviconUpdated(_, _, kIconURL, _, ImageColorIs(kNewColor)));
604
605 RunHandlerWithSimpleFaviconCandidates({kIconURL});
606 // We know from the |kPageUrl| database request that |kIconURL| has expired. A
607 // second request for |kIconURL| should not have been made because it is
608 // redundant.
584 EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL)); 609 EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL));
585 EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16)); 610 EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL));
586 } 611 }
587 612
588 // Test that FaviconHandler requests the new data when: 613 // Test that FaviconHandler requests the new data when:
589 // - There is valid data in the database for the page URL. 614 // - There is valid data in the database for the page URL.
590 // AND 615 // AND
591 // - The icon URL used by the page has changed. 616 // - The icon URL used by the page has changed.
592 // AND 617 // AND
593 // - There is no data in database for the new icon URL. 618 // - There is no data in database for the new icon URL.
594 TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) { 619 TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) {
595 const GURL kOldIconURL("http://www.google.com/old_favicon"); 620 const GURL kOldIconURL("http://www.google.com/old_favicon");
596 const GURL kNewIconURL = kIconURL16x16; 621 const GURL kNewIconURL = kIconURL16x16;
597 622
598 favicon_service_.fake()->Store(kPageURL, kOldIconURL, 623 favicon_service_.fake()->Store(kPageURL, kOldIconURL,
599 CreateRawBitmapResult(kOldIconURL)); 624 CreateRawBitmapResult(kOldIconURL));
600 625
601 InSequence seq; 626 InSequence seq;
602 EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kOldIconURL, _, _)); 627 EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kOldIconURL, _, _));
603 EXPECT_CALL(favicon_service_, SetFavicons(_, kNewIconURL, _, _)); 628 EXPECT_CALL(favicon_service_, SetFavicons(_, kNewIconURL, _, _));
604 EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kNewIconURL, _, _)); 629 EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kNewIconURL, _, _));
605 630
606 RunHandlerWithSimpleFaviconCandidates({kNewIconURL}); 631 RunHandlerWithSimpleFaviconCandidates({kNewIconURL});
607 EXPECT_THAT(delegate_.downloads(), ElementsAre(kNewIconURL)); 632 EXPECT_THAT(delegate_.downloads(), ElementsAre(kNewIconURL));
608 } 633 }
609 634
610 // If there is data for the page URL in history which is invalid, test that: 635 // If there is data for the page URL in history which is invalid, test that:
611 // - The invalid data is not sent to the UI. 636 // - The invalid data is not sent to the UI.
612 // - The icon is redownloaded. 637 // - The icon is redownloaded.
613 TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) { 638 TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) {
639 const GURL kIconURL("http://www.google.com/favicon");
640
641 delegate_.fake_downloader().Add(kIconURL, IntVector{gfx::kFaviconSize},
642 IntVector{gfx::kFaviconSize}, SK_ColorBLUE);
643
614 // Set non empty but invalid data. 644 // Set non empty but invalid data.
615 std::vector<FaviconRawBitmapResult> bitmap_result = 645 std::vector<FaviconRawBitmapResult> bitmap_result =
616 CreateRawBitmapResult(kIconURL16x16); 646 CreateRawBitmapResult(kIconURL);
617 // Empty bitmap data is invalid. 647 // Empty bitmap data is invalid.
618 bitmap_result[0].bitmap_data = new base::RefCountedBytes(); 648 bitmap_result[0].bitmap_data = new base::RefCountedBytes();
619 649
620 favicon_service_.fake()->Store(kPageURL, kIconURL16x16, bitmap_result); 650 favicon_service_.fake()->Store(kPageURL, kIconURL, bitmap_result);
621 651
622 // TODO(crbug.com/700811): It would be nice if we could check the image 652 EXPECT_CALL(delegate_,
623 // being published to rule out invalid data. 653 OnFaviconUpdated(_, _, kIconURL, _, ImageColorIs(SK_ColorBLUE)));
624 EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _));
625 654
626 RunHandlerWithSimpleFaviconCandidates({kIconURL16x16}); 655 RunHandlerWithSimpleFaviconCandidates({kIconURL});
627 656
628 EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL)); 657 EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL));
629 EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16)); 658 EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL));
630 } 659 }
631 660
632 // Test that no downloads are done if a user visits a page which changed its 661 // Test that no downloads are done if a user visits a page which changed its
633 // favicon URL to a favicon URL which is already cached in the database. 662 // favicon URL to a favicon URL which is already cached in the database.
634 TEST_F(FaviconHandlerTest, UpdateFavicon) { 663 TEST_F(FaviconHandlerTest, UpdateFavicon) {
635 const GURL kSomePreviousPageURL("https://www.google.com/previous"); 664 const GURL kSomePreviousPageURL("https://www.google.com/previous");
636 const GURL kIconURL("http://www.google.com/favicon"); 665 const GURL kIconURL("http://www.google.com/favicon");
637 const GURL kNewIconURL("http://www.google.com/new_favicon"); 666 const GURL kNewIconURL("http://www.google.com/new_favicon");
638 667
639 favicon_service_.fake()->Store(kPageURL, kIconURL, 668 favicon_service_.fake()->Store(kPageURL, kIconURL,
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 TEST_F(FaviconHandlerTest, TestFaviconWasScaledAfterDownload) { 1128 TEST_F(FaviconHandlerTest, TestFaviconWasScaledAfterDownload) {
1100 const int kMaximalSize = FaviconHandler::GetMaximalIconSize( 1129 const int kMaximalSize = FaviconHandler::GetMaximalIconSize(
1101 FaviconDriverObserver::NON_TOUCH_LARGEST); 1130 FaviconDriverObserver::NON_TOUCH_LARGEST);
1102 1131
1103 const GURL kIconURL1("http://www.google.com/b"); 1132 const GURL kIconURL1("http://www.google.com/b");
1104 const GURL kIconURL2("http://www.google.com/c"); 1133 const GURL kIconURL2("http://www.google.com/c");
1105 1134
1106 const int kOriginalSize1 = kMaximalSize + 1; 1135 const int kOriginalSize1 = kMaximalSize + 1;
1107 const int kOriginalSize2 = kMaximalSize + 2; 1136 const int kOriginalSize2 = kMaximalSize + 2;
1108 1137
1109 delegate_.fake_downloader().AddWithOriginalSizes( 1138 delegate_.fake_downloader().Add(kIconURL1, IntVector{kMaximalSize},
1110 kIconURL1, IntVector{kMaximalSize}, IntVector{kOriginalSize1}); 1139 IntVector{kOriginalSize1}, SK_ColorBLUE);
1111 delegate_.fake_downloader().AddWithOriginalSizes( 1140 delegate_.fake_downloader().Add(kIconURL2, IntVector{kMaximalSize},
1112 kIconURL2, IntVector{kMaximalSize}, IntVector{kOriginalSize2}); 1141 IntVector{kOriginalSize2}, SK_ColorBLUE);
1113 1142
1114 // Verify the best bitmap was selected (although smaller than |kIconURL2|) 1143 // Verify the best bitmap was selected (although smaller than |kIconURL2|)
1115 // and that it was scaled down to |kMaximalSize|. 1144 // and that it was scaled down to |kMaximalSize|.
1116 EXPECT_CALL(delegate_, 1145 EXPECT_CALL(delegate_,
1117 OnFaviconUpdated(_, _, kIconURL1, _, 1146 OnFaviconUpdated(_, _, kIconURL1, _,
1118 ImageSizeIs(kMaximalSize, kMaximalSize))); 1147 ImageSizeIs(kMaximalSize, kMaximalSize)));
1119 1148
1120 RunHandlerWithCandidates( 1149 RunHandlerWithCandidates(
1121 FaviconDriverObserver::NON_TOUCH_LARGEST, 1150 FaviconDriverObserver::NON_TOUCH_LARGEST,
1122 {FaviconURL(kIconURL1, FAVICON, 1151 {FaviconURL(kIconURL1, FAVICON,
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 RunHandlerWithSimpleFaviconCandidates({k404IconURL}); 1319 RunHandlerWithSimpleFaviconCandidates({k404IconURL});
1291 1320
1292 EXPECT_THAT( 1321 EXPECT_THAT(
1293 histogram_tester.GetAllSamples("Favicons.DownloadOutcome"), 1322 histogram_tester.GetAllSamples("Favicons.DownloadOutcome"),
1294 ElementsAre(base::Bucket(static_cast<int>(DownloadOutcome::SKIPPED), 1323 ElementsAre(base::Bucket(static_cast<int>(DownloadOutcome::SKIPPED),
1295 /*expected_count=*/1))); 1324 /*expected_count=*/1)));
1296 } 1325 }
1297 1326
1298 } // namespace 1327 } // namespace
1299 } // namespace favicon 1328 } // namespace favicon
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698