Home | History | Annotate | Download | only in extensions
      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|.
     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:
     31   FaviconDownloaderTest() {
     32   }
     33 
     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:
     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   }
     54   virtual ~TestFaviconDownloader() {}
     55 
     56   virtual int DownloadImage(const GURL& url) OVERRIDE {
     57     return id_counter_++;
     58   }
     59 
     60   virtual std::vector<content::FaviconURL> GetFaviconURLsFromWebContents()
     61       OVERRIDE {
     62     return initial_favicon_urls_;
     63   }
     64 
     65   size_t pending_requests() const {
     66     return in_progress_requests_.size();
     67   }
     68 
     69   void DownloadsComplete(bool success,
     70                          const FaviconDownloader::FaviconMap& map) {
     71     favicon_map_ = map;
     72   }
     73 
     74   FaviconDownloader::FaviconMap favicon_map() const {
     75     return favicon_map_;
     76   }
     77 
     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 
     86   void UpdateFaviconURLs(const std::vector<content::FaviconURL>& candidates) {
     87     FaviconDownloader::DidUpdateFaviconURL(candidates);
     88   }
     89 
     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 
    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 
    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 
    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