Home | History | Annotate | Download | only in favicon
      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
      3 // found in the LICENSE file.
      4 
      5 #include "base/memory/scoped_ptr.h"
      6 #include "chrome/browser/favicon/favicon_handler.h"
      7 #include "chrome/browser/favicon/favicon_service_factory.h"
      8 #include "chrome/browser/history/history_service_factory.h"
      9 #include "chrome/browser/profiles/profile.h"
     10 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
     11 #include "content/public/browser/favicon_status.h"
     12 #include "content/public/browser/invalidate_type.h"
     13 #include "content/public/browser/navigation_entry.h"
     14 #include "content/public/browser/web_contents.h"
     15 #include "third_party/skia/include/core/SkBitmap.h"
     16 #include "ui/gfx/codec/png_codec.h"
     17 #include "ui/gfx/favicon_size.h"
     18 #include "ui/gfx/image/image.h"
     19 
     20 class TestFaviconHandler;
     21 
     22 using content::FaviconURL;
     23 using content::NavigationEntry;
     24 using content::WebContents;
     25 
     26 namespace {
     27 
     28 // Fill the given bmp with valid png data.
     29 void FillDataToBitmap(int w, int h, SkBitmap* bmp) {
     30   bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
     31   bmp->allocPixels();
     32 
     33   unsigned char* src_data =
     34       reinterpret_cast<unsigned char*>(bmp->getAddr32(0, 0));
     35   for (int i = 0; i < w * h; i++) {
     36     src_data[i * 4 + 0] = static_cast<unsigned char>(i % 255);
     37     src_data[i * 4 + 1] = static_cast<unsigned char>(i % 255);
     38     src_data[i * 4 + 2] = static_cast<unsigned char>(i % 255);
     39     src_data[i * 4 + 3] = static_cast<unsigned char>(i % 255);
     40   }
     41 }
     42 
     43 // Fill the given data buffer with valid png data.
     44 void FillBitmap(int w, int h, std::vector<unsigned char>* output) {
     45   SkBitmap bitmap;
     46   FillDataToBitmap(w, h, &bitmap);
     47   gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, output);
     48 }
     49 
     50 void SetFaviconBitmapResult(
     51     const GURL& icon_url,
     52     chrome::IconType icon_type,
     53     bool expired,
     54     std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) {
     55   scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
     56   FillBitmap(gfx::kFaviconSize, gfx::kFaviconSize, &data->data());
     57   chrome::FaviconBitmapResult bitmap_result;
     58   bitmap_result.expired = expired;
     59   bitmap_result.bitmap_data = data;
     60   // Use a pixel size other than (0,0) as (0,0) has a special meaning.
     61   bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize);
     62   bitmap_result.icon_type = icon_type;
     63   bitmap_result.icon_url = icon_url;
     64 
     65   favicon_bitmap_results->push_back(bitmap_result);
     66 }
     67 
     68 void SetFaviconBitmapResult(
     69     const GURL& icon_url,
     70     std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) {
     71   SetFaviconBitmapResult(icon_url, chrome::FAVICON, false /* expired */,
     72                          favicon_bitmap_results);
     73 }
     74 
     75 // This class is used to save the download request for verifying with test case.
     76 // It also will be used to invoke the onDidDownload callback.
     77 class DownloadHandler {
     78  public:
     79   explicit DownloadHandler(TestFaviconHandler* favicon_helper)
     80       : favicon_helper_(favicon_helper),
     81         failed_(false) {
     82   }
     83 
     84   virtual ~DownloadHandler() {
     85   }
     86 
     87   void Reset() {
     88     download_.reset(NULL);
     89     failed_ = false;
     90   }
     91 
     92   void AddDownload(
     93       int download_id,
     94       const GURL& image_url,
     95       int image_size,
     96       int max_image_size) {
     97     download_.reset(new Download(
     98         download_id, image_url, image_size, max_image_size, false));
     99   }
    100 
    101   void InvokeCallback();
    102 
    103   void set_failed(bool failed) { failed_ = failed; }
    104 
    105   bool HasDownload() const { return download_.get() != NULL; }
    106   const GURL& GetImageUrl() const { return download_->image_url; }
    107   void SetImageSize(int size) { download_->image_size = size; }
    108 
    109  private:
    110   struct Download {
    111     Download(int id, GURL url, int size, int max_size, bool failed)
    112         : download_id(id),
    113           image_url(url),
    114           image_size(size),
    115           max_image_size(max_size) {}
    116     ~Download() {}
    117     int download_id;
    118     GURL image_url;
    119     int image_size;
    120     int max_image_size;
    121   };
    122 
    123   TestFaviconHandler* favicon_helper_;
    124   scoped_ptr<Download> download_;
    125   bool failed_;
    126 
    127   DISALLOW_COPY_AND_ASSIGN(DownloadHandler);
    128 };
    129 
    130 // This class is used to save the history request for verifying with test case.
    131 // It also will be used to simulate the history response.
    132 class HistoryRequestHandler {
    133  public:
    134   HistoryRequestHandler(const GURL& page_url,
    135                         const GURL& icon_url,
    136                         int icon_type,
    137                         const FaviconService::FaviconResultsCallback& callback)
    138       : page_url_(page_url),
    139         icon_url_(icon_url),
    140         icon_type_(icon_type),
    141         callback_(callback) {
    142   }
    143 
    144   HistoryRequestHandler(const GURL& page_url,
    145                         const GURL& icon_url,
    146                         int icon_type,
    147                         const std::vector<unsigned char>& bitmap_data)
    148       : page_url_(page_url),
    149         icon_url_(icon_url),
    150         icon_type_(icon_type),
    151         bitmap_data_(bitmap_data) {
    152   }
    153 
    154   virtual ~HistoryRequestHandler() {}
    155   void InvokeCallback();
    156 
    157   const GURL page_url_;
    158   const GURL icon_url_;
    159   const int icon_type_;
    160   const std::vector<unsigned char> bitmap_data_;
    161   std::vector<chrome::FaviconBitmapResult> history_results_;
    162   FaviconService::FaviconResultsCallback callback_;
    163 
    164  private:
    165   DISALLOW_COPY_AND_ASSIGN(HistoryRequestHandler);
    166 };
    167 
    168 }  // namespace
    169 
    170 
    171 class TestFaviconHandlerDelegate : public FaviconHandlerDelegate {
    172  public:
    173   TestFaviconHandlerDelegate() {
    174   }
    175 
    176   virtual ~TestFaviconHandlerDelegate() {
    177   }
    178 
    179   virtual NavigationEntry* GetActiveEntry() OVERRIDE {
    180     ADD_FAILURE() << "TestFaviconHandlerDelegate::GetActiveEntry() "
    181                   << "should never be called in tests.";
    182     return NULL;
    183   }
    184 
    185   virtual int StartDownload(const GURL& url,
    186                             int max_bitmap_size) OVERRIDE {
    187     ADD_FAILURE() << "TestFaviconHandlerDelegate::StartDownload() "
    188                   << "should never be called in tests.";
    189     return -1;
    190   }
    191 
    192   virtual void NotifyFaviconUpdated(bool icon_url_changed) OVERRIDE {
    193     ADD_FAILURE() << "TestFaviconHandlerDelegate::NotifyFaviconUpdated() "
    194                   << "should never be called in tests.";
    195   }
    196 
    197  private:
    198   DISALLOW_COPY_AND_ASSIGN(TestFaviconHandlerDelegate);
    199 };
    200 
    201 // This class is used to catch the FaviconHandler's download and history
    202 // request, and also provide the methods to access the FaviconHandler
    203 // internals.
    204 class TestFaviconHandler : public FaviconHandler {
    205  public:
    206   TestFaviconHandler(const GURL& page_url,
    207                      Profile* profile,
    208                      FaviconHandlerDelegate* delegate,
    209                      Type type)
    210       : FaviconHandler(profile, delegate, type),
    211         entry_(NavigationEntry::Create()),
    212         download_id_(0),
    213         num_favicon_updates_(0) {
    214     entry_->SetURL(page_url);
    215     download_handler_.reset(new DownloadHandler(this));
    216   }
    217 
    218   virtual ~TestFaviconHandler() {
    219   }
    220 
    221   HistoryRequestHandler* history_handler() {
    222     return history_handler_.get();
    223   }
    224 
    225   // This method will take the ownership of the given handler.
    226   void set_history_handler(HistoryRequestHandler* handler) {
    227     history_handler_.reset(handler);
    228   }
    229 
    230   DownloadHandler* download_handler() {
    231     return download_handler_.get();
    232   }
    233 
    234   size_t num_favicon_update_notifications() const {
    235     return num_favicon_updates_;
    236   }
    237 
    238   void ResetNumFaviconUpdateNotifications() {
    239     num_favicon_updates_ = 0;
    240   }
    241 
    242   // Methods to access favicon internals.
    243   virtual NavigationEntry* GetEntry() OVERRIDE {
    244     return entry_.get();
    245   }
    246 
    247   const std::deque<FaviconURL>& urls() {
    248     return image_urls_;
    249   }
    250 
    251   FaviconURL* current_candidate() {
    252     return FaviconHandler::current_candidate();
    253   }
    254 
    255  protected:
    256   virtual void UpdateFaviconMappingAndFetch(
    257       const GURL& page_url,
    258       const GURL& icon_url,
    259       chrome::IconType icon_type,
    260       const FaviconService::FaviconResultsCallback& callback,
    261       CancelableTaskTracker* tracker) OVERRIDE {
    262     history_handler_.reset(new HistoryRequestHandler(page_url, icon_url,
    263                                                      icon_type, callback));
    264   }
    265 
    266   virtual void GetFavicon(
    267       const GURL& icon_url,
    268       chrome::IconType icon_type,
    269       const FaviconService::FaviconResultsCallback& callback,
    270       CancelableTaskTracker* tracker) OVERRIDE {
    271     history_handler_.reset(new HistoryRequestHandler(GURL(), icon_url,
    272                                                      icon_type, callback));
    273   }
    274 
    275   virtual void GetFaviconForURL(
    276       const GURL& page_url,
    277       int icon_types,
    278       const FaviconService::FaviconResultsCallback& callback,
    279       CancelableTaskTracker* tracker) OVERRIDE {
    280     history_handler_.reset(new HistoryRequestHandler(page_url, GURL(),
    281                                                      icon_types, callback));
    282   }
    283 
    284   virtual int DownloadFavicon(const GURL& image_url,
    285                               int max_bitmap_size) OVERRIDE {
    286     download_id_++;
    287     download_handler_->AddDownload(
    288         download_id_, image_url, 0, max_bitmap_size);
    289     return download_id_;
    290   }
    291 
    292   virtual void SetHistoryFavicons(const GURL& page_url,
    293                                   const GURL& icon_url,
    294                                   chrome::IconType icon_type,
    295                                   const gfx::Image& image) OVERRIDE {
    296     scoped_refptr<base::RefCountedMemory> bytes = image.As1xPNGBytes();
    297     std::vector<unsigned char> bitmap_data(bytes->front(),
    298                                            bytes->front() + bytes->size());
    299     history_handler_.reset(new HistoryRequestHandler(
    300         page_url, icon_url, icon_type, bitmap_data));
    301   }
    302 
    303   virtual FaviconService* GetFaviconService() OVERRIDE {
    304     // Just give none NULL value, so overridden methods can be hit.
    305     return (FaviconService*)(1);
    306   }
    307 
    308   virtual bool ShouldSaveFavicon(const GURL& url) OVERRIDE {
    309     return true;
    310   }
    311 
    312   virtual void NotifyFaviconUpdated(bool icon_url_changed) OVERRIDE {
    313     ++num_favicon_updates_;
    314   }
    315 
    316   GURL page_url_;
    317 
    318  private:
    319   scoped_ptr<NavigationEntry> entry_;
    320 
    321   // The unique id of a download request. It will be returned to a
    322   // FaviconHandler.
    323   int download_id_;
    324 
    325   scoped_ptr<DownloadHandler> download_handler_;
    326   scoped_ptr<HistoryRequestHandler> history_handler_;
    327 
    328   // The number of times that NotifyFaviconUpdated() has been called.
    329   size_t num_favicon_updates_;
    330 
    331   DISALLOW_COPY_AND_ASSIGN(TestFaviconHandler);
    332 };
    333 
    334 namespace {
    335 
    336 void HistoryRequestHandler::InvokeCallback() {
    337   if (!callback_.is_null()) {
    338     callback_.Run(history_results_);
    339   }
    340 }
    341 
    342 void DownloadHandler::InvokeCallback() {
    343   int original_size = (download_->image_size > 0) ?
    344       download_->image_size : gfx::kFaviconSize;
    345   int downloaded_size = original_size;
    346   if (download_->max_image_size != 0 &&
    347       downloaded_size > download_->max_image_size) {
    348     downloaded_size = download_->max_image_size;
    349   }
    350   std::vector<SkBitmap> bitmaps;
    351   std::vector<gfx::Size> original_bitmap_sizes;
    352   if (!failed_) {
    353     SkBitmap bitmap;
    354     FillDataToBitmap(downloaded_size, downloaded_size, &bitmap);
    355     bitmaps.push_back(bitmap);
    356     original_bitmap_sizes.push_back(gfx::Size(original_size, original_size));
    357   }
    358   favicon_helper_->OnDidDownloadFavicon(download_->download_id,
    359                                         download_->image_url,
    360                                         bitmaps,
    361                                         original_bitmap_sizes);
    362 }
    363 
    364 class FaviconHandlerTest : public ChromeRenderViewHostTestHarness {
    365  public:
    366   FaviconHandlerTest() {
    367   }
    368 
    369   virtual ~FaviconHandlerTest() {
    370   }
    371 
    372   // Simulates requesting a favicon for |page_url| given:
    373   // - We have not previously cached anything in history for |page_url| or for
    374   //   any of |candidates|.
    375   // - The page provides favicons at |candidate_icons|.
    376   // - The favicons at |candidate_icons| have edge pixel sizes of
    377   //   |candidate_icon_sizes|.
    378   void DownloadTillDoneIgnoringHistory(
    379       TestFaviconHandler* favicon_handler,
    380       const GURL& page_url,
    381       const std::vector<FaviconURL>& candidate_icons,
    382       const int* candidate_icon_sizes) {
    383     favicon_handler->ResetNumFaviconUpdateNotifications();
    384 
    385     favicon_handler->FetchFavicon(page_url);
    386     favicon_handler->history_handler()->InvokeCallback();
    387 
    388     favicon_handler->OnUpdateFaviconURL(0, candidate_icons);
    389     EXPECT_EQ(candidate_icons.size(), favicon_handler->image_urls().size());
    390 
    391     DownloadHandler* download_handler = favicon_handler->download_handler();
    392     for (size_t i = 0; i < candidate_icons.size(); ++i) {
    393       favicon_handler->history_handler()->history_results_.clear();
    394       favicon_handler->history_handler()->InvokeCallback();
    395       ASSERT_TRUE(download_handler->HasDownload());
    396       EXPECT_EQ(download_handler->GetImageUrl(),
    397                 candidate_icons[i].icon_url);
    398       download_handler->SetImageSize(candidate_icon_sizes[i]);
    399       download_handler->InvokeCallback();
    400 
    401       if (favicon_handler->num_favicon_update_notifications())
    402         return;
    403     }
    404   }
    405 
    406   virtual void SetUp() {
    407     // The score computed by SelectFaviconFrames() is dependent on the supported
    408     // scale factors of the platform. It is used for determining the goodness of
    409     // a downloaded bitmap in FaviconHandler::OnDidDownloadFavicon().
    410     // Force the values of the scale factors so that the tests produce the same
    411     // results on all platforms.
    412     std::vector<ui::ScaleFactor> scale_factors;
    413     scale_factors.push_back(ui::SCALE_FACTOR_100P);
    414     scoped_set_supported_scale_factors_.reset(
    415         new ui::test::ScopedSetSupportedScaleFactors(scale_factors));
    416 
    417     ChromeRenderViewHostTestHarness::SetUp();
    418   }
    419 
    420   virtual void TearDown() OVERRIDE {
    421     Profile* profile = Profile::FromBrowserContext(
    422         web_contents()->GetBrowserContext());
    423     FaviconServiceFactory::GetInstance()->SetTestingFactory(
    424       profile, NULL);
    425     ChromeRenderViewHostTestHarness::TearDown();
    426   }
    427 
    428  private:
    429   typedef scoped_ptr<ui::test::ScopedSetSupportedScaleFactors>
    430       ScopedSetSupportedScaleFactors;
    431   ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_;
    432   DISALLOW_COPY_AND_ASSIGN(FaviconHandlerTest);
    433 };
    434 
    435 TEST_F(FaviconHandlerTest, GetFaviconFromHistory) {
    436   const GURL page_url("http://www.google.com");
    437   const GURL icon_url("http://www.google.com/favicon");
    438 
    439   TestFaviconHandlerDelegate delegate;
    440   Profile* profile = Profile::FromBrowserContext(
    441       web_contents()->GetBrowserContext());
    442   TestFaviconHandler helper(page_url, profile,
    443                             &delegate, FaviconHandler::FAVICON);
    444 
    445   helper.FetchFavicon(page_url);
    446   HistoryRequestHandler* history_handler = helper.history_handler();
    447   // Ensure the data given to history is correct.
    448   ASSERT_TRUE(history_handler);
    449   EXPECT_EQ(page_url, history_handler->page_url_);
    450   EXPECT_EQ(GURL(), history_handler->icon_url_);
    451   EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_);
    452 
    453   SetFaviconBitmapResult(icon_url, &history_handler->history_results_);
    454 
    455   // Send history response.
    456   history_handler->InvokeCallback();
    457   // Verify FaviconHandler status
    458   EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
    459   EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
    460 
    461   // Simulates update favicon url.
    462   std::vector<FaviconURL> urls;
    463   urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON));
    464   helper.OnUpdateFaviconURL(0, urls);
    465 
    466   // Verify FaviconHandler status
    467   EXPECT_EQ(1U, helper.urls().size());
    468   ASSERT_TRUE(helper.current_candidate());
    469   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    470   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    471 
    472   // Favicon shouldn't request to download icon.
    473   EXPECT_FALSE(helper.download_handler()->HasDownload());
    474 }
    475 
    476 TEST_F(FaviconHandlerTest, DownloadFavicon) {
    477   const GURL page_url("http://www.google.com");
    478   const GURL icon_url("http://www.google.com/favicon");
    479 
    480   TestFaviconHandlerDelegate delegate;
    481   Profile* profile = Profile::FromBrowserContext(
    482       web_contents()->GetBrowserContext());
    483   TestFaviconHandler helper(page_url, profile,
    484                             &delegate, FaviconHandler::FAVICON);
    485 
    486   helper.FetchFavicon(page_url);
    487   HistoryRequestHandler* history_handler = helper.history_handler();
    488   // Ensure the data given to history is correct.
    489   ASSERT_TRUE(history_handler);
    490   EXPECT_EQ(page_url, history_handler->page_url_);
    491   EXPECT_EQ(GURL(), history_handler->icon_url_);
    492   EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_);
    493 
    494   // Set icon data expired
    495   SetFaviconBitmapResult(icon_url, chrome::FAVICON, true /* expired */,
    496                          &history_handler->history_results_);
    497   // Send history response.
    498   history_handler->InvokeCallback();
    499   // Verify FaviconHandler status
    500   EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
    501   EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
    502 
    503   // Simulates update favicon url.
    504   std::vector<FaviconURL> urls;
    505   urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON));
    506   helper.OnUpdateFaviconURL(0, urls);
    507 
    508   // Verify FaviconHandler status
    509   EXPECT_EQ(1U, helper.urls().size());
    510   ASSERT_TRUE(helper.current_candidate());
    511   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    512   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    513 
    514   // Favicon should request to download icon now.
    515   DownloadHandler* download_handler = helper.download_handler();
    516   EXPECT_TRUE(helper.download_handler()->HasDownload());
    517 
    518   // Verify the download request.
    519   EXPECT_EQ(icon_url, download_handler->GetImageUrl());
    520 
    521   // Reset the history_handler to verify whether favicon is set.
    522   helper.set_history_handler(NULL);
    523 
    524   // Smulates download done.
    525   download_handler->InvokeCallback();
    526 
    527   // New icon should be saved to history backend and navigation entry.
    528   history_handler = helper.history_handler();
    529   ASSERT_TRUE(history_handler);
    530   EXPECT_EQ(icon_url, history_handler->icon_url_);
    531   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    532   EXPECT_LT(0U, history_handler->bitmap_data_.size());
    533   EXPECT_EQ(page_url, history_handler->page_url_);
    534 
    535   // Verify NavigationEntry.
    536   content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon();
    537   EXPECT_EQ(icon_url, favicon_status.url);
    538   EXPECT_TRUE(favicon_status.valid);
    539   EXPECT_FALSE(favicon_status.image.IsEmpty());
    540   EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width());
    541 }
    542 
    543 TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) {
    544   const GURL page_url("http://www.google.com");
    545   const GURL icon_url("http://www.google.com/favicon");
    546   const GURL new_icon_url("http://www.google.com/new_favicon");
    547 
    548   TestFaviconHandlerDelegate delegate;
    549   Profile* profile = Profile::FromBrowserContext(
    550       web_contents()->GetBrowserContext());
    551   TestFaviconHandler helper(page_url, profile,
    552                             &delegate, FaviconHandler::FAVICON);
    553 
    554   helper.FetchFavicon(page_url);
    555   HistoryRequestHandler* history_handler = helper.history_handler();
    556   // Ensure the data given to history is correct.
    557   ASSERT_TRUE(history_handler);
    558   EXPECT_EQ(page_url, history_handler->page_url_);
    559   EXPECT_EQ(GURL(), history_handler->icon_url_);
    560   EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_);
    561 
    562   // Set valid icon data.
    563   SetFaviconBitmapResult(icon_url, &history_handler->history_results_);
    564 
    565   // Send history response.
    566   history_handler->InvokeCallback();
    567   // Verify FaviconHandler status.
    568   EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
    569   EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
    570 
    571   // Reset the history_handler to verify whether new icon is requested from
    572   // history.
    573   helper.set_history_handler(NULL);
    574 
    575   // Simulates update with the different favicon url.
    576   std::vector<FaviconURL> urls;
    577   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    578   helper.OnUpdateFaviconURL(0, urls);
    579 
    580   // Verify FaviconHandler status.
    581   EXPECT_EQ(1U, helper.urls().size());
    582   ASSERT_TRUE(helper.current_candidate());
    583   ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
    584   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    585 
    586   // Favicon should be requested from history.
    587   history_handler = helper.history_handler();
    588   ASSERT_TRUE(history_handler);
    589   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    590   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    591   EXPECT_EQ(page_url, history_handler->page_url_);
    592 
    593   // Simulate not find icon.
    594   history_handler->history_results_.clear();
    595   history_handler->InvokeCallback();
    596 
    597   // Favicon should request to download icon now.
    598   DownloadHandler* download_handler = helper.download_handler();
    599   EXPECT_TRUE(helper.download_handler()->HasDownload());
    600 
    601   // Verify the download request.
    602   EXPECT_EQ(new_icon_url, download_handler->GetImageUrl());
    603 
    604   // Reset the history_handler to verify whether favicon is set.
    605   helper.set_history_handler(NULL);
    606 
    607   // Smulates download done.
    608   download_handler->InvokeCallback();
    609 
    610   // New icon should be saved to history backend and navigation entry.
    611   history_handler = helper.history_handler();
    612   ASSERT_TRUE(history_handler);
    613   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    614   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    615   EXPECT_LT(0U, history_handler->bitmap_data_.size());
    616   EXPECT_EQ(page_url, history_handler->page_url_);
    617 
    618   // Verify NavigationEntry.
    619   content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon();
    620   EXPECT_EQ(new_icon_url, favicon_status.url);
    621   EXPECT_TRUE(favicon_status.valid);
    622   EXPECT_FALSE(favicon_status.image.IsEmpty());
    623   EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width());
    624 }
    625 
    626 TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) {
    627   const GURL page_url("http://www.google.com");
    628   const GURL icon_url("http://www.google.com/favicon");
    629 
    630   TestFaviconHandlerDelegate delegate;
    631   Profile* profile = Profile::FromBrowserContext(
    632       web_contents()->GetBrowserContext());
    633   TestFaviconHandler helper(page_url, profile,
    634                             &delegate, FaviconHandler::FAVICON);
    635 
    636   helper.FetchFavicon(page_url);
    637   HistoryRequestHandler* history_handler = helper.history_handler();
    638   // Ensure the data given to history is correct.
    639   ASSERT_TRUE(history_handler);
    640   EXPECT_EQ(page_url, history_handler->page_url_);
    641   EXPECT_EQ(GURL(), history_handler->icon_url_);
    642   EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_);
    643 
    644   // Set non empty but invalid data.
    645   chrome::FaviconBitmapResult bitmap_result;
    646   bitmap_result.expired = false;
    647   // Empty bitmap data is invalid.
    648   bitmap_result.bitmap_data = new base::RefCountedBytes();
    649   bitmap_result.pixel_size = gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize);
    650   bitmap_result.icon_type = chrome::FAVICON;
    651   bitmap_result.icon_url = icon_url;
    652   history_handler->history_results_.clear();
    653   history_handler->history_results_.push_back(bitmap_result);
    654 
    655   // Send history response.
    656   history_handler->InvokeCallback();
    657   // The NavigationEntry should not be set yet as the history data is invalid.
    658   EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid);
    659   EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url);
    660 
    661   // Reset the history_handler to verify whether new icon is requested from
    662   // history.
    663   helper.set_history_handler(NULL);
    664 
    665   // Simulates update with matching favicon URL.
    666   std::vector<FaviconURL> urls;
    667   urls.push_back(FaviconURL(icon_url, FaviconURL::FAVICON));
    668   helper.OnUpdateFaviconURL(0, urls);
    669 
    670   // A download for the favicon should be requested, and we should not do
    671   // another history request.
    672   DownloadHandler* download_handler = helper.download_handler();
    673   EXPECT_TRUE(helper.download_handler()->HasDownload());
    674   EXPECT_EQ(NULL, helper.history_handler());
    675 
    676   // Verify the download request.
    677   EXPECT_EQ(icon_url, download_handler->GetImageUrl());
    678 
    679   // Simulates download done.
    680   download_handler->InvokeCallback();
    681 
    682   // New icon should be saved to history backend and navigation entry.
    683   history_handler = helper.history_handler();
    684   ASSERT_TRUE(history_handler);
    685   EXPECT_EQ(icon_url, history_handler->icon_url_);
    686   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    687   EXPECT_LT(0U, history_handler->bitmap_data_.size());
    688   EXPECT_EQ(page_url, history_handler->page_url_);
    689 
    690   // Verify NavigationEntry.
    691   content::FaviconStatus favicon_status = helper.GetEntry()->GetFavicon();
    692   EXPECT_EQ(icon_url, favicon_status.url);
    693   EXPECT_TRUE(favicon_status.valid);
    694   EXPECT_FALSE(favicon_status.image.IsEmpty());
    695   EXPECT_EQ(gfx::kFaviconSize, favicon_status.image.Width());
    696 }
    697 
    698 TEST_F(FaviconHandlerTest, UpdateFavicon) {
    699   const GURL page_url("http://www.google.com");
    700   const GURL icon_url("http://www.google.com/favicon");
    701   const GURL new_icon_url("http://www.google.com/new_favicon");
    702 
    703   TestFaviconHandlerDelegate delegate;
    704   Profile* profile = Profile::FromBrowserContext(
    705       web_contents()->GetBrowserContext());
    706   TestFaviconHandler helper(page_url, profile,
    707                             &delegate, FaviconHandler::FAVICON);
    708 
    709   helper.FetchFavicon(page_url);
    710   HistoryRequestHandler* history_handler = helper.history_handler();
    711   // Ensure the data given to history is correct.
    712   ASSERT_TRUE(history_handler);
    713   EXPECT_EQ(page_url, history_handler->page_url_);
    714   EXPECT_EQ(GURL(), history_handler->icon_url_);
    715   EXPECT_EQ(chrome::FAVICON, history_handler->icon_type_);
    716 
    717   SetFaviconBitmapResult(icon_url, &history_handler->history_results_);
    718 
    719   // Send history response.
    720   history_handler->InvokeCallback();
    721   // Verify FaviconHandler status.
    722   EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
    723   EXPECT_EQ(icon_url, helper.GetEntry()->GetFavicon().url);
    724 
    725   // Reset the history_handler to verify whether new icon is requested from
    726   // history.
    727   helper.set_history_handler(NULL);
    728 
    729   // Simulates update with the different favicon url.
    730   std::vector<FaviconURL> urls;
    731   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    732   helper.OnUpdateFaviconURL(0, urls);
    733 
    734   // Verify FaviconHandler status.
    735   EXPECT_EQ(1U, helper.urls().size());
    736   ASSERT_TRUE(helper.current_candidate());
    737   ASSERT_EQ(new_icon_url, helper.current_candidate()->icon_url);
    738   ASSERT_EQ(FaviconURL::FAVICON, helper.current_candidate()->icon_type);
    739 
    740   // Favicon should be requested from history.
    741   history_handler = helper.history_handler();
    742   ASSERT_TRUE(history_handler);
    743   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    744   EXPECT_EQ(FaviconURL::FAVICON, history_handler->icon_type_);
    745   EXPECT_EQ(page_url, history_handler->page_url_);
    746 
    747   // Simulate find icon.
    748   SetFaviconBitmapResult(new_icon_url, &history_handler->history_results_);
    749   history_handler->InvokeCallback();
    750 
    751   // Shouldn't request download favicon
    752   EXPECT_FALSE(helper.download_handler()->HasDownload());
    753 
    754   // Verify the favicon status.
    755   EXPECT_EQ(new_icon_url, helper.GetEntry()->GetFavicon().url);
    756   EXPECT_TRUE(helper.GetEntry()->GetFavicon().valid);
    757   EXPECT_FALSE(helper.GetEntry()->GetFavicon().image.IsEmpty());
    758 }
    759 
    760 TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) {
    761   const GURL page_url("http://www.google.com");
    762   const GURL icon_url("http://www.google.com/favicon");
    763   const GURL new_icon_url("http://www.google.com/new_favicon");
    764 
    765   TestFaviconHandlerDelegate delegate;
    766   Profile* profile = Profile::FromBrowserContext(
    767       web_contents()->GetBrowserContext());
    768   TestFaviconHandler helper(page_url, profile,
    769                             &delegate, FaviconHandler::TOUCH);
    770 
    771   helper.FetchFavicon(page_url);
    772   HistoryRequestHandler* history_handler = helper.history_handler();
    773   // Ensure the data given to history is correct.
    774   ASSERT_TRUE(history_handler);
    775   EXPECT_EQ(page_url, history_handler->page_url_);
    776   EXPECT_EQ(GURL(), history_handler->icon_url_);
    777   EXPECT_EQ(chrome::TOUCH_PRECOMPOSED_ICON | chrome::TOUCH_ICON,
    778             history_handler->icon_type_);
    779 
    780   // Icon not found.
    781   history_handler->history_results_.clear();
    782   // Send history response.
    783   history_handler->InvokeCallback();
    784   // Verify FaviconHandler status.
    785   EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid);
    786   EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url);
    787 
    788   // Reset the history_handler to verify whether new icon is requested from
    789   // history.
    790   helper.set_history_handler(NULL);
    791 
    792   // Simulates update with the different favicon url.
    793   std::vector<FaviconURL> urls;
    794   urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON));
    795   urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON));
    796   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    797   helper.OnUpdateFaviconURL(0, urls);
    798 
    799   // Verify FaviconHandler status.
    800   EXPECT_EQ(2U, helper.urls().size());
    801   ASSERT_TRUE(helper.current_candidate());
    802   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    803   ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
    804             helper.current_candidate()->icon_type);
    805 
    806   // Favicon should be requested from history.
    807   history_handler = helper.history_handler();
    808   ASSERT_TRUE(history_handler);
    809   EXPECT_EQ(icon_url, history_handler->icon_url_);
    810   EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
    811   EXPECT_EQ(page_url, history_handler->page_url_);
    812 
    813   // Simulate not find icon.
    814   history_handler->history_results_.clear();
    815   history_handler->InvokeCallback();
    816 
    817   // Should request download favicon.
    818   DownloadHandler* download_handler = helper.download_handler();
    819   EXPECT_TRUE(helper.download_handler()->HasDownload());
    820 
    821   // Verify the download request.
    822   EXPECT_EQ(icon_url, download_handler->GetImageUrl());
    823 
    824   // Reset the history_handler to verify whether favicon is request from
    825   // history.
    826   helper.set_history_handler(NULL);
    827   // Smulates download failed.
    828   download_handler->set_failed(true);
    829   download_handler->InvokeCallback();
    830 
    831   // Left 1 url.
    832   EXPECT_EQ(1U, helper.urls().size());
    833   ASSERT_TRUE(helper.current_candidate());
    834   EXPECT_EQ(new_icon_url, helper.current_candidate()->icon_url);
    835   EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
    836 
    837   // Favicon should be requested from history.
    838   history_handler = helper.history_handler();
    839   ASSERT_TRUE(history_handler);
    840   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    841   EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
    842   EXPECT_EQ(page_url, history_handler->page_url_);
    843 
    844   // Reset download handler
    845   download_handler->Reset();
    846 
    847   // Simulates getting a expired icon from history.
    848   SetFaviconBitmapResult(new_icon_url, chrome::TOUCH_ICON,
    849       true /* expired */, &history_handler->history_results_);
    850   history_handler->InvokeCallback();
    851 
    852   // Verify the download request.
    853   EXPECT_TRUE(helper.download_handler()->HasDownload());
    854   EXPECT_EQ(new_icon_url, download_handler->GetImageUrl());
    855 
    856   helper.set_history_handler(NULL);
    857 
    858   // Simulates icon being downloaded.
    859   download_handler->InvokeCallback();
    860 
    861   // New icon should be saved to history backend.
    862   history_handler = helper.history_handler();
    863   ASSERT_TRUE(history_handler);
    864   EXPECT_EQ(new_icon_url, history_handler->icon_url_);
    865   EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
    866   EXPECT_LT(0U, history_handler->bitmap_data_.size());
    867   EXPECT_EQ(page_url, history_handler->page_url_);
    868 }
    869 
    870 TEST_F(FaviconHandlerTest, UpdateDuringDownloading) {
    871   const GURL page_url("http://www.google.com");
    872   const GURL icon_url("http://www.google.com/favicon");
    873   const GURL new_icon_url("http://www.google.com/new_favicon");
    874 
    875   TestFaviconHandlerDelegate delegate;
    876   Profile* profile = Profile::FromBrowserContext(
    877       web_contents()->GetBrowserContext());
    878   TestFaviconHandler helper(page_url, profile,
    879                             &delegate, FaviconHandler::TOUCH);
    880 
    881   helper.FetchFavicon(page_url);
    882   HistoryRequestHandler* history_handler = helper.history_handler();
    883   // Ensure the data given to history is correct.
    884   ASSERT_TRUE(history_handler);
    885   EXPECT_EQ(page_url, history_handler->page_url_);
    886   EXPECT_EQ(GURL(), history_handler->icon_url_);
    887   EXPECT_EQ(chrome::TOUCH_PRECOMPOSED_ICON | chrome::TOUCH_ICON,
    888             history_handler->icon_type_);
    889 
    890   // Icon not found.
    891   history_handler->history_results_.clear();
    892   // Send history response.
    893   history_handler->InvokeCallback();
    894   // Verify FaviconHandler status.
    895   EXPECT_FALSE(helper.GetEntry()->GetFavicon().valid);
    896   EXPECT_EQ(GURL(), helper.GetEntry()->GetFavicon().url);
    897 
    898   // Reset the history_handler to verify whether new icon is requested from
    899   // history.
    900   helper.set_history_handler(NULL);
    901 
    902   // Simulates update with the different favicon url.
    903   std::vector<FaviconURL> urls;
    904   urls.push_back(FaviconURL(icon_url, FaviconURL::TOUCH_PRECOMPOSED_ICON));
    905   urls.push_back(FaviconURL(new_icon_url, FaviconURL::TOUCH_ICON));
    906   urls.push_back(FaviconURL(new_icon_url, FaviconURL::FAVICON));
    907   helper.OnUpdateFaviconURL(0, urls);
    908 
    909   // Verify FaviconHandler status.
    910   EXPECT_EQ(2U, helper.urls().size());
    911   ASSERT_TRUE(helper.current_candidate());
    912   ASSERT_EQ(icon_url, helper.current_candidate()->icon_url);
    913   ASSERT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON,
    914             helper.current_candidate()->icon_type);
    915 
    916   // Favicon should be requested from history.
    917   history_handler = helper.history_handler();
    918   ASSERT_TRUE(history_handler);
    919   EXPECT_EQ(icon_url, history_handler->icon_url_);
    920   EXPECT_EQ(FaviconURL::TOUCH_PRECOMPOSED_ICON, history_handler->icon_type_);
    921   EXPECT_EQ(page_url, history_handler->page_url_);
    922 
    923   // Simulate not find icon.
    924   history_handler->history_results_.clear();
    925   history_handler->InvokeCallback();
    926 
    927   // Should request download favicon.
    928   DownloadHandler* download_handler = helper.download_handler();
    929   EXPECT_TRUE(helper.download_handler()->HasDownload());
    930 
    931   // Verify the download request.
    932   EXPECT_EQ(icon_url, download_handler->GetImageUrl());
    933 
    934   // Reset the history_handler to verify whether favicon is request from
    935   // history.
    936   helper.set_history_handler(NULL);
    937   const GURL latest_icon_url("http://www.google.com/latest_favicon");
    938   std::vector<FaviconURL> latest_urls;
    939   latest_urls.push_back(FaviconURL(latest_icon_url, FaviconURL::TOUCH_ICON));
    940   helper.OnUpdateFaviconURL(0, latest_urls);
    941 
    942   EXPECT_EQ(1U, helper.urls().size());
    943   EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url);
    944   EXPECT_EQ(FaviconURL::TOUCH_ICON, helper.current_candidate()->icon_type);
    945 
    946   // Whether new icon is requested from history
    947   history_handler = helper.history_handler();
    948   ASSERT_TRUE(history_handler);
    949   EXPECT_EQ(latest_icon_url, history_handler->icon_url_);
    950   EXPECT_EQ(FaviconURL::TOUCH_ICON, history_handler->icon_type_);
    951   EXPECT_EQ(page_url, history_handler->page_url_);
    952 
    953   // Reset the history_handler to verify whether favicon is request from
    954   // history.
    955   // Save the callback for late use.
    956   FaviconService::FaviconResultsCallback callback = history_handler->callback_;
    957   helper.set_history_handler(NULL);
    958 
    959   // Simulates download succeed.
    960   download_handler->InvokeCallback();
    961   // The downloaded icon should be thrown away as there is favicon update.
    962   EXPECT_FALSE(helper.history_handler());
    963 
    964   download_handler->Reset();
    965 
    966   // Simulates getting the icon from history.
    967   scoped_ptr<HistoryRequestHandler> handler;
    968   handler.reset(new HistoryRequestHandler(page_url, latest_icon_url,
    969                                           chrome::TOUCH_ICON, callback));
    970   SetFaviconBitmapResult(latest_icon_url, chrome::TOUCH_ICON,
    971       false /* expired */, &handler->history_results_);
    972   handler->InvokeCallback();
    973 
    974   // No download request.
    975   EXPECT_FALSE(download_handler->HasDownload());
    976 }
    977 
    978 #if !defined(OS_ANDROID)
    979 
    980 // Test the favicon which is selected when the web page provides several
    981 // favicons and none of the favicons are cached in history.
    982 // The goal of this test is to be more of an integration test than
    983 // SelectFaviconFramesTest.*.
    984 TEST_F(FaviconHandlerTest, MultipleFavicons) {
    985   const GURL kPageURL("http://www.google.com");
    986   const FaviconURL kSourceIconURLs[] = {
    987     FaviconURL(GURL("http://www.google.com/a"), FaviconURL::FAVICON),
    988     FaviconURL(GURL("http://www.google.com/b"), FaviconURL::FAVICON),
    989     FaviconURL(GURL("http://www.google.com/c"), FaviconURL::FAVICON),
    990     FaviconURL(GURL("http://www.google.com/d"), FaviconURL::FAVICON),
    991     FaviconURL(GURL("http://www.google.com/e"), FaviconURL::FAVICON)
    992   };
    993 
    994   // Set the supported scale factors to 1x and 2x. This affects the behavior of
    995   // SelectFaviconFrames().
    996   std::vector<ui::ScaleFactor> scale_factors;
    997   scale_factors.push_back(ui::SCALE_FACTOR_100P);
    998   scale_factors.push_back(ui::SCALE_FACTOR_200P);
    999   ui::test::ScopedSetSupportedScaleFactors scoped_supported(scale_factors);
   1000 
   1001   Profile* profile = Profile::FromBrowserContext(
   1002       web_contents()->GetBrowserContext());
   1003 
   1004   // 1) Test that if there are several single resolution favicons to choose from
   1005   // that the largest exact match is chosen.
   1006   TestFaviconHandlerDelegate delegate1;
   1007   TestFaviconHandler handler1(kPageURL, profile,
   1008                               &delegate1, FaviconHandler::FAVICON);
   1009   const int kSizes1[] = { 16, 24, 32, 48, 256 };
   1010   std::vector<FaviconURL> urls1(kSourceIconURLs,
   1011                                 kSourceIconURLs + arraysize(kSizes1));
   1012   DownloadTillDoneIgnoringHistory(&handler1, kPageURL, urls1, kSizes1);
   1013 
   1014   content::FaviconStatus favicon_status1(handler1.GetEntry()->GetFavicon());
   1015   EXPECT_EQ(0u, handler1.image_urls().size());
   1016   EXPECT_TRUE(favicon_status1.valid);
   1017   EXPECT_FALSE(favicon_status1.image.IsEmpty());
   1018   EXPECT_EQ(gfx::kFaviconSize, favicon_status1.image.Width());
   1019 
   1020   size_t expected_index = 2u;
   1021   EXPECT_EQ(32, kSizes1[expected_index]);
   1022   EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
   1023             handler1.GetEntry()->GetFavicon().url);
   1024 
   1025   // 2) Test that if there are several single resolution favicons to choose
   1026   // from, the exact match is preferred even if it results in upsampling.
   1027   TestFaviconHandlerDelegate delegate2;
   1028   TestFaviconHandler handler2(kPageURL, profile,
   1029                               &delegate2, FaviconHandler::FAVICON);
   1030   const int kSizes2[] = { 16, 24, 48, 256 };
   1031   std::vector<FaviconURL> urls2(kSourceIconURLs,
   1032                                 kSourceIconURLs + arraysize(kSizes2));
   1033   DownloadTillDoneIgnoringHistory(&handler2, kPageURL, urls2, kSizes2);
   1034   EXPECT_TRUE(handler2.GetEntry()->GetFavicon().valid);
   1035   expected_index = 0u;
   1036   EXPECT_EQ(16, kSizes2[expected_index]);
   1037   EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
   1038             handler2.GetEntry()->GetFavicon().url);
   1039 
   1040   // 3) Test that favicons which need to be upsampled a little or downsampled
   1041   // a little are preferred over huge favicons.
   1042   TestFaviconHandlerDelegate delegate3;
   1043   TestFaviconHandler handler3(kPageURL, profile,
   1044                               &delegate3, FaviconHandler::FAVICON);
   1045   const int kSizes3[] = { 256, 48 };
   1046   std::vector<FaviconURL> urls3(kSourceIconURLs,
   1047                                 kSourceIconURLs + arraysize(kSizes3));
   1048   DownloadTillDoneIgnoringHistory(&handler3, kPageURL, urls3, kSizes3);
   1049   EXPECT_TRUE(handler3.GetEntry()->GetFavicon().valid);
   1050   expected_index = 1u;
   1051   EXPECT_EQ(48, kSizes3[expected_index]);
   1052   EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
   1053             handler3.GetEntry()->GetFavicon().url);
   1054 
   1055   TestFaviconHandlerDelegate delegate4;
   1056   TestFaviconHandler handler4(kPageURL, profile,
   1057                               &delegate4, FaviconHandler::FAVICON);
   1058   const int kSizes4[] = { 17, 256 };
   1059   std::vector<FaviconURL> urls4(kSourceIconURLs,
   1060                                 kSourceIconURLs + arraysize(kSizes4));
   1061   DownloadTillDoneIgnoringHistory(&handler4, kPageURL, urls4, kSizes4);
   1062   EXPECT_TRUE(handler4.GetEntry()->GetFavicon().valid);
   1063   expected_index = 0u;
   1064   EXPECT_EQ(17, kSizes4[expected_index]);
   1065   EXPECT_EQ(kSourceIconURLs[expected_index].icon_url,
   1066             handler4.GetEntry()->GetFavicon().url);
   1067 }
   1068 
   1069 #endif
   1070 
   1071 static BrowserContextKeyedService* BuildFaviconService(
   1072     content::BrowserContext* profile) {
   1073   return new FaviconService(static_cast<Profile*>(profile));
   1074 }
   1075 
   1076 static BrowserContextKeyedService* BuildHistoryService(
   1077     content::BrowserContext* profile) {
   1078   return NULL;
   1079 }
   1080 
   1081 // Test that Favicon is not requested repeatedly during the same session if
   1082 // server returns HTTP 404 status.
   1083 TEST_F(FaviconHandlerTest, UnableToDownloadFavicon) {
   1084   const GURL missing_icon_url("http://www.google.com/favicon.ico");
   1085   const GURL another_icon_url("http://www.youtube.com/favicon.ico");
   1086 
   1087   Profile* profile = Profile::FromBrowserContext(
   1088       web_contents()->GetBrowserContext());
   1089 
   1090   FaviconServiceFactory::GetInstance()->SetTestingFactory(
   1091       profile, BuildFaviconService);
   1092 
   1093   HistoryServiceFactory::GetInstance()->SetTestingFactory(
   1094       profile, BuildHistoryService);
   1095 
   1096   FaviconService* favicon_service = FaviconServiceFactory::GetForProfile(
   1097       profile, Profile::IMPLICIT_ACCESS);
   1098 
   1099   FaviconTabHelper::CreateForWebContents(web_contents());
   1100   FaviconTabHelper* favicon_tab_helper =
   1101       FaviconTabHelper::FromWebContents(web_contents());
   1102 
   1103   std::vector<SkBitmap> empty_icons;
   1104   std::vector<gfx::Size> empty_icon_sizes;
   1105   int download_id = 0;
   1106 
   1107   // Try to download missing icon.
   1108   download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
   1109   EXPECT_NE(0, download_id);
   1110   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
   1111 
   1112   // Report download failure with HTTP 503 status.
   1113   favicon_tab_helper->DidDownloadFavicon(download_id, 503, missing_icon_url,
   1114       empty_icons, empty_icon_sizes);
   1115   // Icon is not marked as UnableToDownload as HTTP status is not 404.
   1116   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
   1117 
   1118   // Try to download again.
   1119   download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
   1120   EXPECT_NE(0, download_id);
   1121   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
   1122 
   1123   // Report download failure with HTTP 404 status.
   1124   favicon_tab_helper->DidDownloadFavicon(download_id, 404, missing_icon_url,
   1125       empty_icons, empty_icon_sizes);
   1126   // Icon is marked as UnableToDownload.
   1127   EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
   1128 
   1129   // Try to download again.
   1130   download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
   1131   // Download is not started and Icon is still marked as UnableToDownload.
   1132   EXPECT_EQ(0, download_id);
   1133   EXPECT_TRUE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
   1134 
   1135   // Try to download another icon.
   1136   download_id = favicon_tab_helper->StartDownload(another_icon_url, 0);
   1137   // Download is started as another icon URL is not same as missing_icon_url.
   1138   EXPECT_NE(0, download_id);
   1139   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url));
   1140 
   1141   // Clear the list of missing icons.
   1142   favicon_service->ClearUnableToDownloadFavicons();
   1143   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
   1144   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(another_icon_url));
   1145 
   1146   // Try to download again.
   1147   download_id = favicon_tab_helper->StartDownload(missing_icon_url, 0);
   1148   EXPECT_NE(0, download_id);
   1149   // Report download success with HTTP 200 status.
   1150   favicon_tab_helper->DidDownloadFavicon(download_id, 200, missing_icon_url,
   1151       empty_icons, empty_icon_sizes);
   1152   // Icon is not marked as UnableToDownload as HTTP status is not 404.
   1153   EXPECT_FALSE(favicon_service->WasUnableToDownloadFavicon(missing_icon_url));
   1154 }
   1155 
   1156 }  // namespace.
   1157