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