1 // Copyright 2013 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 "chrome/browser/extensions/favicon_downloader.h"
6
7 #include "base/files/scoped_temp_dir.h"
8 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
9 #include "content/public/common/favicon_url.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
12
13 using content::RenderViewHostTester;
14
15 namespace {
16
17 // Creates valid SkBitmaps of the dimensions found in |sizes| and pushes them
18 // into |bitmaps|.
CreateTestBitmaps(const std::vector<gfx::Size> & sizes)19 std::vector<SkBitmap> CreateTestBitmaps(const std::vector<gfx::Size>& sizes) {
20 std::vector<SkBitmap> bitmaps(sizes.size());
21 for (size_t i = 0; i < sizes.size(); ++i) {
22 SkBitmap& bitmap = bitmaps[i];
23 bitmap.allocN32Pixels(sizes[i].width(), sizes[i].height());
24 bitmap.eraseColor(SK_ColorRED);
25 }
26 return bitmaps;
27 }
28
29 class FaviconDownloaderTest : public ChromeRenderViewHostTestHarness {
30 protected:
FaviconDownloaderTest()31 FaviconDownloaderTest() {
32 }
33
~FaviconDownloaderTest()34 virtual ~FaviconDownloaderTest() {
35 }
36
37 private:
38 DISALLOW_COPY_AND_ASSIGN(FaviconDownloaderTest);
39 };
40
41 } // namespace
42
43 class TestFaviconDownloader : public FaviconDownloader {
44 public:
TestFaviconDownloader(content::WebContents * web_contents,std::vector<GURL> extra_favicon_urls)45 TestFaviconDownloader(content::WebContents* web_contents,
46 std::vector<GURL> extra_favicon_urls)
47 : FaviconDownloader(
48 web_contents,
49 extra_favicon_urls,
50 base::Bind(&TestFaviconDownloader::DownloadsComplete,
51 base::Unretained(this))),
52 id_counter_(0) {
53 }
~TestFaviconDownloader()54 virtual ~TestFaviconDownloader() {}
55
DownloadImage(const GURL & url)56 virtual int DownloadImage(const GURL& url) OVERRIDE {
57 return id_counter_++;
58 }
59
GetFaviconURLsFromWebContents()60 virtual std::vector<content::FaviconURL> GetFaviconURLsFromWebContents()
61 OVERRIDE {
62 return initial_favicon_urls_;
63 }
64
pending_requests() const65 size_t pending_requests() const {
66 return in_progress_requests_.size();
67 }
68
DownloadsComplete(bool success,const FaviconDownloader::FaviconMap & map)69 void DownloadsComplete(bool success,
70 const FaviconDownloader::FaviconMap& map) {
71 favicon_map_ = map;
72 }
73
favicon_map() const74 FaviconDownloader::FaviconMap favicon_map() const {
75 return favicon_map_;
76 }
77
CompleteImageDownload(int id,const GURL & image_url,const std::vector<gfx::Size> & original_bitmap_sizes)78 void CompleteImageDownload(
79 int id,
80 const GURL& image_url,
81 const std::vector<gfx::Size>& original_bitmap_sizes) {
82 FaviconDownloader::DidDownloadFavicon(id, 200, image_url,
83 CreateTestBitmaps(original_bitmap_sizes), original_bitmap_sizes);
84 }
85
UpdateFaviconURLs(const std::vector<content::FaviconURL> & candidates)86 void UpdateFaviconURLs(const std::vector<content::FaviconURL>& candidates) {
87 FaviconDownloader::DidUpdateFaviconURL(candidates);
88 }
89
set_initial_favicon_urls(const std::vector<content::FaviconURL> & urls)90 void set_initial_favicon_urls(const std::vector<content::FaviconURL>& urls) {
91 initial_favicon_urls_ = urls;
92 }
93
94 private:
95 std::vector<content::FaviconURL> initial_favicon_urls_;
96 FaviconDownloader::FaviconMap favicon_map_;
97 int id_counter_;
98 DISALLOW_COPY_AND_ASSIGN(TestFaviconDownloader);
99 };
100
TEST_F(FaviconDownloaderTest,SimpleDownload)101 TEST_F(FaviconDownloaderTest, SimpleDownload) {
102 const GURL favicon_url("http://www.google.com/favicon.ico");
103 TestFaviconDownloader downloader(web_contents(), std::vector<GURL>());
104
105 std::vector<content::FaviconURL> favicon_urls;
106 favicon_urls.push_back(content::FaviconURL(
107 favicon_url, content::FaviconURL::FAVICON, std::vector<gfx::Size>()));
108 downloader.set_initial_favicon_urls(favicon_urls);
109 EXPECT_EQ(0u, downloader.pending_requests());
110
111 downloader.Start();
112 EXPECT_EQ(1u, downloader.pending_requests());
113
114 std::vector<gfx::Size> sizes(1, gfx::Size(32, 32));
115 downloader.CompleteImageDownload(0, favicon_urls[0].icon_url, sizes);
116 EXPECT_EQ(0u, downloader.pending_requests());
117
118 EXPECT_EQ(1u, downloader.favicon_map().size());
119 EXPECT_EQ(1u, downloader.favicon_map()[favicon_url].size());
120 }
121
TEST_F(FaviconDownloaderTest,DownloadWithUrlsFromWebContentsNotification)122 TEST_F(FaviconDownloaderTest, DownloadWithUrlsFromWebContentsNotification) {
123 const GURL favicon_url("http://www.google.com/favicon.ico");
124 TestFaviconDownloader downloader(web_contents(), std::vector<GURL>());
125
126 std::vector<content::FaviconURL> favicon_urls;
127 favicon_urls.push_back(content::FaviconURL(
128 favicon_url, content::FaviconURL::FAVICON, std::vector<gfx::Size>()));
129 EXPECT_EQ(0u, downloader.pending_requests());
130
131 // Start downloader before favicon URLs are loaded.
132 downloader.Start();
133 EXPECT_EQ(0u, downloader.pending_requests());
134
135 downloader.UpdateFaviconURLs(favicon_urls);
136 EXPECT_EQ(1u, downloader.pending_requests());
137
138 std::vector<gfx::Size> sizes(1, gfx::Size(32, 32));
139 downloader.CompleteImageDownload(0, favicon_urls[0].icon_url, sizes);
140 EXPECT_EQ(0u, downloader.pending_requests());
141
142 EXPECT_EQ(1u, downloader.favicon_map().size());
143 EXPECT_EQ(1u, downloader.favicon_map()[favicon_url].size());
144 }
145
TEST_F(FaviconDownloaderTest,DownloadMultipleUrls)146 TEST_F(FaviconDownloaderTest, DownloadMultipleUrls) {
147 const GURL empty_favicon("http://www.google.com/empty_favicon.ico");
148 const GURL favicon_url_1("http://www.google.com/favicon.ico");
149 const GURL favicon_url_2("http://www.google.com/favicon2.ico");
150
151 std::vector<GURL> extra_urls;
152 // This should get downloaded.
153 extra_urls.push_back(favicon_url_2);
154 // This is duplicated in the favicon urls and should only be downloaded once.
155 extra_urls.push_back(empty_favicon);
156
157 TestFaviconDownloader downloader(web_contents(), extra_urls);
158 std::vector<content::FaviconURL> favicon_urls;
159 favicon_urls.push_back(content::FaviconURL(
160 favicon_url_1, content::FaviconURL::FAVICON, std::vector<gfx::Size>()));
161 // This is duplicated in the favicon urls and should only be downloaded once.
162 favicon_urls.push_back(content::FaviconURL(
163 empty_favicon, content::FaviconURL::FAVICON, std::vector<gfx::Size>()));
164 // Invalid icons shouldn't get put into the download queue.
165 favicon_urls.push_back(
166 content::FaviconURL(GURL("http://www.google.com/invalid.ico"),
167 content::FaviconURL::INVALID_ICON,
168 std::vector<gfx::Size>()));
169 downloader.set_initial_favicon_urls(favicon_urls);
170 downloader.Start();
171 EXPECT_EQ(3u, downloader.pending_requests());
172
173 std::vector<gfx::Size> sizes_1(1, gfx::Size(16, 16));
174 downloader.CompleteImageDownload(0, favicon_url_1, sizes_1);
175
176 std::vector<gfx::Size> sizes_2;
177 sizes_2.push_back(gfx::Size(32, 32));
178 sizes_2.push_back(gfx::Size(64, 64));
179 downloader.CompleteImageDownload(1, favicon_url_2, sizes_2);
180
181 // Only 1 download should have been initiated for |empty_favicon| even though
182 // the URL was in both the web app info and the favicon urls.
183 downloader.CompleteImageDownload(2, empty_favicon, std::vector<gfx::Size>());
184 EXPECT_EQ(0u, downloader.pending_requests());
185
186 EXPECT_EQ(3u, downloader.favicon_map().size());
187 EXPECT_EQ(0u, downloader.favicon_map()[empty_favicon].size());
188 EXPECT_EQ(1u, downloader.favicon_map()[favicon_url_1].size());
189 EXPECT_EQ(2u, downloader.favicon_map()[favicon_url_2].size());
190 }
191